通话过程中拔下耳机时 AVAudioEngine 崩溃

Posted

技术标签:

【中文标题】通话过程中拔下耳机时 AVAudioEngine 崩溃【英文标题】:AVAudioEngine crashes when I unplug headphones during a call 【发布时间】:2015-07-19 13:53:44 【问题描述】:

这是我在日志中看到的:

16:33:20.236: Call is Dialing
16:33:21.088: AVAudiosessionInterruptionNotification
16:33:21.450: AVAudioSessionRouteChangeNotification
16:33:21.450: ....change reason CategoryChange
16:33:21.539: AVAudioEngineConfigurationChangeNotification
16:33:21.542: Starting Audio Engine
16:33:23.863: AVAudioSessionRouteChangeNotification
16:33:23.863: ....change reason OldDeviceUnavailable
16:33:23.860 ERROR:     [0x100a70000] AVAudioIONodeImpl.mm:317: ___ZN13AVAudioIOUnit11GetHWFormatEjPj_block_invoke: required condition is false: hwFormat
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: hwFormat'

我已经订阅了AVAudioEngineConfigurationChangeNotificationAVAudioSessionInterruptionNotification

@objc private func handleAudioEngineConfigurationChangeNotification(notification: NSNotification) 
    println2(notification.name)
    makeEngineConnections()
    startEngine()


@objc private func handleAudioSessionInterruptionNotification(notification: NSNotification) 
    println2(notification.name)
    if let interruptionType = AVAudioSessionInterruptionType(rawValue: notification.userInfo?[AVAudioSessionInterruptionTypeKey] as! UInt) 
        switch interruptionType 
        case .Began:
            audioPlayerNode.stop()
        case .Ended:
            if let interruptionOptionValue = notification.userInfo?[AVAudioSessionInterruptionOptionKey] as? UInt 
                let interruptionOption = AVAudioSessionInterruptionOptions(interruptionOptionValue)
                if interruptionOption == AVAudioSessionInterruptionOptions.OptionShouldResume 
                    AVAudioSession.sharedInstance().setActive(true, error: nil)
                    startEngine()
                
            
        
    


func startEngine() 
    println2("Starting Audio Engine")
    var error: NSError?

    if !audioEngine.running 
        audioEngine.startAndReturnError(&error)
        if let error = error 
            println2("Error initializing Audio Engine: " + error.localizedDescription)
        
    


private func makeEngineConnections() 
    let mainMixer = audioEngine.mainMixerNode
    audioEngine.connect(audioPlayerNode, to: audioEqNode, format: mainMixer.outputFormatForBus(0))
    audioEngine.connect(audioEqNode, to: audioTimePitch, format: mainMixer.outputFormatForBus(0))
    audioEngine.connect(audioTimePitch, to: mainMixer, format: mainMixer.outputFormatForBus(0))

但它似乎不起作用。

如何避免这种崩溃?

【问题讨论】:

转到***.com/questions/26728250/… 谢谢,但这无济于事。可以看到,应用订阅了AVAudioEngineConfigurationChangeNotification 您收到通知了吗?音频是否成功停止?还是在收到通知之前就崩溃了。 从日志中可以看到,应用在第二次收到AVAudioSessionRouteChangeNotification后就崩溃了。 【参考方案1】:

我怀疑问题出在这里:audioEngine.connect(audioTimePitch, to: mainMixer, format: mainMixer.outputFormatForBus(0))

documentation 说:

此方法调用 connect:to:fromBus:toBus:format: 使用总线 0 作为源音频节点,使用总线 0 作为目标音频节点,除非目标是混音器,在这种情况下destination 是混音器的 nextAvailableInputBus。

【讨论】:

以上是关于通话过程中拔下耳机时 AVAudioEngine 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

MPMoviePlayerController - 插入耳机时自动恢复

AVAudioEngine 离线渲染:仅在连接耳机时静音输出

拔下耳机时是不是有事件?

拔下耳机时 MPMoviePlayerViewController 停止播放

拔下耳机时暂停ExoPlayer

用于拔下耳机的广播接收器