我正在使用AVFoundation / AudioKit来录制iPhone / iPad的内部麦克风。在BluetoothA2DP和内置扬声器之间切换输出后,应该可以继续使用该应用程序。麦克风应继续从设备的内部麦克风获取输入。确实如此。一切正常,但是直到我要更改输出设备为止。
func basicAudioSetup(){
// microphone
self.microphone = AKMicrophone()
// select input of device
if let input = AudioKit.inputDevice {
try! self.microphone?.setDevice(input)
}
AKSettings.sampleRate = 44100
AKSettings.channelCount = 2
AKSettings.playbackWhileMuted = true
AKSettings.enableRouteChangeHandling = false
AKSettings.useBluetooth = true
AKSettings.allowAirPlay = true
AKSettings.defaultToSpeaker = true
AKSettings.audioInputEnabled = true
// init DSP
self.dsp = AKClock(amountSamples: Int32(self.amountSamples), amountGroups: Int32(self.amountGroups), bpm: self.bpm, iPad:self.iPad)
self.masterbusTracker = AKAmplitudeTracker(self.dsp)
self.mixer.connect(input: self.masterbusTracker)
self.player = AKPlayer()
self.mixer.connect(input: self.player)
self.microphone?.stop()
self.microphoneTracker = AKAmplitudeTracker(self.microphone)
self.microphoneTracker?.stop()
self.microphoneRecorder = try! AKNodeRecorder(node: self.microphone)
self.microphoneMonitoring = AKBooster(self.microphoneTracker)
self.microphoneMonitoring?.gain = 0
self.mixer.connect(input: self.microphoneMonitoring)
AudioKit.output = self.mixer
// the following line is actually happening inside a customized AudioKit.start() function to make sure that only BluetoothA2DP is used for better sound quality:
try AKSettings.setSession(category: .playAndRecord, with: [.defaultToSpeaker, .allowBluetoothA2DP, .allowAirPlay, .mixWithOthers])
do {
try AudioKit.start()
}catch{
print("AudioKit did not start")
}
// adding Notifications to manually restart the engine.
NotificationCenter.default.addObserver(self, selector: #selector(self.audioRouteChangeListener(notification:)), name: NSNotification.Name.AVAudioSessionRouteChange, object: nil)
}
@objc func audioRouteChangeListener(notification:NSNotification) {
let audioRouteChangeReason = notification.userInfo![AVAudioSessionRouteChangeReasonKey] as! UInt
let checkRestart = {
print("ROUTE CHANGE")
do{
try AudioKit.engine.start()
}catch{
print("error rebooting engine")
}
}
if audioRouteChangeReason == AVAudioSessionRouteChangeReason.newDeviceAvailable.rawValue ||
audioRouteChangeReason == AVAudioSessionRouteChangeReason.oldDeviceUnavailable.rawValue{
if Thread.isMainThread {
checkRestart()
} else {
DispatchQueue.main.async(execute: checkRestart)
}
}
}
我注意到,当连接麦克风时,从内部扬声器切换到蓝牙时,AVAudioSessionRouteChange不会被调用。从蓝牙启动并从内置扬声器切换到内置扬声器时,我确实收到消息:
[[AVAudioEngineGraph.mm:1481:Start:(err = PerformCommand(* ioNode,kAUStartIO,NULL,0))
此消息的确切含义是什么?我尝试了一切,从手动断开引擎的所有输入/取消激活并重新激活会话到重建整个链。无效。
理论上,输入源没有改变,因为它停留在电话的输入上。任何帮助,高度赞赏。
FYI:我正在使用AudioKit库的自定义版本,在其中删除了AVAudioSessionRouteChange的内部通知,以避免不必要的Doppelgaenger。出于相同的原因,此定制的库还在内部设置了会话类别和选项,并确保仅使用BluetoothA2DP。