AVAEInternal / coreaudio.avfaudio 在 AVAudioEngine 上初始化 AVAudioSequencer 时出错

AVAEInternal / coreaudio.avfaudio Error When Initializing AVAudioSequencer on AVAudioEngine

我正在尝试使用 AVAudioEngineAVAudioUnitSamplerAVAudioSequencer 创建和测试基本音频设置;然而,即使是这个最基本的代码版本也会抛出以下错误,导致应用程序完全崩溃。

谁能告诉我为什么会这样?原因特别是初始化音序器的行(如果注释掉,错误就会停止),但我不确定为什么。这与步骤顺序有关,还是我在这里遗漏了什么?

它说了一些关于检索 outputNode 的事情,但我认为 AVAudioEngine 有一个默认初始化的节点。

谢谢。

class TestAudioClass {

    private var audioEngine: AVAudioEngine
    private var sampler: AVAudioUnitSampler
    private var sequencer: AVAudioSequencer

    init() {
        self.audioEngine = AVAudioEngine()
        self.sampler = AVAudioUnitSampler()
        self.sequencer = AVAudioSequencer(audioEngine: audioEngine)
    }
}

Thread 1: signal SIGABRT

[avae] AVAEInternal.h:70:_AVAE_Check: required condition is false: [AVAudioEngineGraph.mm:4474:GetDefaultMusicDevice: (outputNode)]

[avae] AVAEInternal.h:103:_AVAE_CheckNoErr: [AVAudioEngineGraph.mm:4309:SetSequence: (err = MusicSequenceSetAudioGraph(inSequence, _seqGraphImpl)): error -1

*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'error -1'

所以,经过一番挖掘,我找到了解决方案:虽然 AVAudioEngine 确实带有开箱即用的 outputNode,但 Apple 还不够清楚的是该输出节点在初始化后不立即存在。

在上面的代码中,sequencer 在创建时尝试访问引擎的输出节点,但发现那里什么也没有,从而引发了崩溃。

在创建音序器之前,您必须以某种方式访问​​引擎的 outputNode(直接访问,或通过 mainMixerNode 间接访问)。这可能只是通过调用 属性,但一个好的方法是将任何相关节点连接到它,例如 AVAudioUnitSampler.

修改后的代码如下:

class TestAudioClass {

    private var audioEngine: AVAudioEngine
    private var sampler: AVAudioUnitSampler
    private var sequencer: AVAudioSequencer

    init() {
        self.audioEngine = AVAudioEngine()
        self.sampler = AVAudioUnitSampler()
        audioEngine.attach(sampler)
        audioEngine.connect(sampler, to: audioEngine.mainMixerNode, format: nil)
        self.sequencer = AVAudioSequencer(audioEngine: audioEngine)
    }
}

还值得注意的是,如果您首先直接访问 outputNode,则不会导致连接混音器。根据 Apple 工作人员的说法 here

"...the default output is created for you automatically either with a mixer attached (access mainMixerNode first) or just by itself (access outputNode first)."

注意:在取消初始化此对象期间(例如对另一个 ViewController 执行展开转场时),您可能仍会遇到类似的崩溃。有关如何解决此问题的详细信息,请参见 .