|
|
|
@ -55,6 +55,7 @@ public class SimpleAudioReceiver: NSObject { |
|
|
|
//public var onAudioData: ((Data) -> Void)? |
|
|
|
public var recordfile: RecordFile? |
|
|
|
public var isHeadphones = true |
|
|
|
public var isReceiverHFP = false // 是否是接收HFP音频 |
|
|
|
|
|
|
|
/** |
|
|
|
* 初始化 |
|
|
|
@ -119,6 +120,7 @@ public class SimpleAudioReceiver: NSObject { |
|
|
|
|
|
|
|
print("AudioStream音频配置设置完成") |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 开始音频输入 |
|
|
|
*/ |
|
|
|
@ -129,9 +131,11 @@ public class SimpleAudioReceiver: NSObject { |
|
|
|
print("startAudioRecord=audioSourceType\(audioSourceType)") |
|
|
|
switch audioSourceType { |
|
|
|
case .microphone: |
|
|
|
runMicrophoneCapture() |
|
|
|
isReceiverHFP = true |
|
|
|
runMicrophoneCapture() |
|
|
|
case .external: |
|
|
|
runExternalCapture() |
|
|
|
isReceiverHFP = false |
|
|
|
runExternalCapture() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -225,20 +229,14 @@ public class SimpleAudioReceiver: NSObject { |
|
|
|
*/ |
|
|
|
private func runExternalCapture() { |
|
|
|
if audioSourceType == .external { |
|
|
|
// do { |
|
|
|
// try audioSession.setCategory(.playback, |
|
|
|
// mode: .videoChat, |
|
|
|
// options: [ .mixWithOthers,.allowBluetoothA2DP // 允许蓝牙耳机,不占用hfp链路 |
|
|
|
// ]) // 添加音频优先级控制 |
|
|
|
// try audioSession.overrideOutputAudioPort(.none) |
|
|
|
// try audioSession.setActive(true) |
|
|
|
// } catch { |
|
|
|
// print("设置音频会话失败: \(error.localizedDescription)") |
|
|
|
// } |
|
|
|
|
|
|
|
do { |
|
|
|
// 根据通话状态进行安全的音频会话配置 |
|
|
|
try safeConfigureAudioSessionForMic() |
|
|
|
} catch { |
|
|
|
print("设置音频会话失败: \(error.localizedDescription)") |
|
|
|
} |
|
|
|
//pushAudioData(data: Data()) |
|
|
|
micCapture.stopCapture() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
/** |
|
|
|
@ -254,26 +252,47 @@ public class SimpleAudioReceiver: NSObject { |
|
|
|
let desiredCategory: AVAudioSession.Category |
|
|
|
let desiredMode: AVAudioSession.Mode |
|
|
|
let desiredOptions: AVAudioSession.CategoryOptions |
|
|
|
|
|
|
|
if isTelephonyActive() { |
|
|
|
// 通话中:录音优先,避免 A2DP(仅播放),改用 HFP(.allowBluetooth) |
|
|
|
desiredCategory = .record |
|
|
|
desiredMode = .voiceChat |
|
|
|
desiredOptions = [.allowBluetooth] |
|
|
|
} else { |
|
|
|
if(isHeadphones){ |
|
|
|
// 非通话:保持原有逻辑,但使用 .allowBluetooth 以支持录音(而不是 A2DP) |
|
|
|
desiredCategory = .playAndRecord |
|
|
|
desiredMode = .videoChat |
|
|
|
desiredOptions = [.allowBluetooth, .mixWithOthers, .defaultToSpeaker] |
|
|
|
//desiredOptions = [.mixWithOthers, .defaultToSpeaker] |
|
|
|
}else{ |
|
|
|
desiredCategory = .playAndRecord |
|
|
|
desiredMode = .videoChat |
|
|
|
desiredOptions = [.mixWithOthers, .defaultToSpeaker] |
|
|
|
if isReceiverHFP { |
|
|
|
if isTelephonyActive() { |
|
|
|
// 通话中:录音优先,避免 A2DP(仅播放),改用 HFP(.allowBluetooth) |
|
|
|
desiredCategory = .record |
|
|
|
desiredMode = .voiceChat |
|
|
|
desiredOptions = [.allowBluetooth] |
|
|
|
} else { |
|
|
|
if(isHeadphones){ |
|
|
|
// 非通话:保持原有逻辑,但使用 .allowBluetooth 以支持录音(而不是 A2DP) |
|
|
|
desiredCategory = .playAndRecord |
|
|
|
desiredMode = .videoChat |
|
|
|
desiredOptions = [.allowBluetooth, .mixWithOthers, .defaultToSpeaker] |
|
|
|
//desiredOptions = [.mixWithOthers, .defaultToSpeaker] |
|
|
|
}else{ |
|
|
|
desiredCategory = .playAndRecord |
|
|
|
desiredMode = .videoChat |
|
|
|
desiredOptions = [.mixWithOthers, .defaultToSpeaker] |
|
|
|
} |
|
|
|
} |
|
|
|
}else{ |
|
|
|
if isTelephonyActive() { |
|
|
|
// 通话中:录音优先,避免 A2DP(仅播放),改用 HFP(.allowBluetooth) |
|
|
|
desiredCategory = .record |
|
|
|
desiredMode = .voiceChat |
|
|
|
desiredOptions = [.allowBluetoothA2DP] |
|
|
|
} else { |
|
|
|
if(isHeadphones){ |
|
|
|
// 非通话:保持原有逻辑,但使用 .allowBluetooth 以支持录音(而不是 A2DP) |
|
|
|
desiredCategory = .playAndRecord |
|
|
|
desiredMode = .videoChat |
|
|
|
desiredOptions = [.allowBluetoothA2DP, .mixWithOthers, .defaultToSpeaker] |
|
|
|
//desiredOptions = [.mixWithOthers, .defaultToSpeaker] |
|
|
|
}else{ |
|
|
|
desiredCategory = .playAndRecord |
|
|
|
desiredMode = .videoChat |
|
|
|
desiredOptions = [.mixWithOthers, .defaultToSpeaker] |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 仅在类别或模式变化时才调用 setCategory,避免触发不必要的 categoryChange |
|
|
|
let needsSetCategory = (audioSession.category != desiredCategory) || (audioSession.mode != desiredMode) |
|
|
|
if needsSetCategory { |
|
|
|
|