【问题标题】:setting AVAudioFormat to connect function has crash将 AVAudioFormat 设置为连接功能已崩溃
【发布时间】:2017-01-07 18:51:26
【问题描述】:

我一直在尝试使用 AVAudioEngine 播放 16 位流数据。

但是传递给 AVAudioFormat 连接函数总是会崩溃。

如下代码:

let AUDIO_OUTPUT_SAMPLE_RATE    = 44100
let AUDIO_OUTPUT_CHANNELS       = 2
let AUDIO_OUTPUT_BITS           = 16
var audioEngine: AVAudioEngine?
var audioPlayer: AVAudioPlayerNode?

...

    audioEngine = AVAudioEngine()
    audioPlayer = AVAudioPlayerNode()

    audioEngine?.attach(audioPlayer!)

    let mixer = audioEngine?.mainMixerNode
    mixer!.outputVolume = 1.0
    let stereoFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: Double(AUDIO_OUTPUT_SAMPLE_RATE), channels: 2, interleaved: false)
    audioEngine!.connect(audioPlayer!, to: mixer!, format: stereoFormat)

...

audioEngine!.connect(...) 正在崩溃

我正在使用 Xcode 8 beta 6、OS X El Capitan,而且,这种情况来自模拟器和设备。

这是崩溃消息的一部分:

ERROR:    >avae> AVAudioNode.mm:751: AUSetFormat: error -10868
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'error -10868'

...
3   AVFAudio  0x000000011e0a5630 _Z19AVAE_RaiseExceptionP8NSStringz + 176
4   AVFAudio  0x000000011e0f270d _ZN19AVAudioNodeImplBase11AUSetFormatEP28OpaqueAudioComponentInstancejjP13AVAudioFormat + 213
5   AVFAudio  0x000000011e0f2630 _ZN19AVAudioNodeImplBase15SetOutputFormatEmP13AVAudioFormat + 46
6   AVFAudio  0x000000011e0f9663 _ZN21AVAudioPlayerNodeImpl15SetOutputFormatEmP13AVAudioFormat + 25
7   AVFAudio  0x000000011e099cfd _ZN18AVAudioEngineGraph8_ConnectEP19AVAudioNodeImplBaseS1_jjP13AVAudioFormat + 2377
8   AVFAudio  0x000000011e09d15f _ZN18AVAudioEngineGraph7ConnectEP11AVAudioNodeS1_mmP13AVAudioFormat + 355
9   AVFAudio  0x000000011e0fc80e _ZN17AVAudioEngineImpl7ConnectEP11AVAudioNodeS1_mmP13AVAudioFormat + 348

从音频文件中播放缓冲区和格式没有问题。

我犯了什么错误?

谢谢。

【问题讨论】:

    标签: crash avfoundation swift3 avaudioengine


    【解决方案1】:

    -10868,又名kAudioUnitErr_FormatNotSupported,因此您的PCMFormatInt16 似乎不受欢迎。将其更改为 .PCMFormatFloat32 确实有效。

    【讨论】:

    • 我遇到了同样的情况,用Float32修复了。我注意到 outputNode 中的默认 AudioFormat 在 3 个不同的 iOD 设备上也是 Float32。这是否意味着 iOS 设备仅支持 Float32 播放?
    【解决方案2】:

    来自 Apple,AVAudioPlayerNode

    在播放缓冲区时,有一个隐含的假设,即缓冲区与节点的输出格式具有相同的采样率。

    然后打印AVAudioPlayerNode的输出格式,即engine.mainMixerNode.inputFormat

        open func connectNodes() {
            print(engine.mainMixerNode.inputFormat(forBus: 0))
            engine.connect(playerNode, to: engine.mainMixerNode, format: readFormat)
        }
    

    结果是

    所以选择.pcmFormatFloat32,而不是.pcmFormatInt16


    OSStatus master website

    【讨论】:

      【解决方案3】:

      您不需要自己创建音频格式,

      从实际音频数据(pcm缓冲区或音频文件)中获取音频格式

      来自 WWDC 2016 的音频格式,提供卓越的音频体验


      来自 WWDC 2015 的实际音频格式理论,Core Audio 的新功能

      • 输出的实际音频格式

      • 输入的实际音频格式

      • 做音频通道映射,音频位深保持不变

      【讨论】:

        【解决方案4】:

        你可以使用singed 16位音频格式,但你应该先转换它。

        // Setup your own format
        let inputFormat = AVAudioFormat(
            commonFormat: .pcmFormatInt16,
            sampleRate: 44100,
            channels: AVAudioChannelCount(2),
            interleaved: true
        )!
        
        let engine = AVAudioEngine()
        // Use system format as output format
        let outputFormat = engine.mainMixerNode.outputFormat(forBus: 0)
        self.converter = AVAudioConverter(from: inputFormat, to: outputFormat)!
        
        self.playerNode = AVAudioPlayerNode()
        engine.attach(playerNode)
        engine.connect(playerNode, to: engine.mainMixerNode, format: nil)
        
        ...
        
        // Prepare input and output buffer
        let inputBuffer = AVAudioPCMBuffer(pcmFormat: inputFormat, frameCapacity: maxSamplesPerBuffer)!
        let outputBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: maxSamplesPerBuffer)!
        
        // When you fill your Int16 buffer with data, send it to converter
        self.converter.convert(to: outputBuffer, error: nil) { inNumPackets, outStatus in
            outStatus.pointee = .haveData
            return inputBuffer
        }
        
        // Now in outputBuffer sound in system format and we can play it
        self.playerNode.scheduleBuffer(outputBuffer)
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多