如何在AVAudioEngine图中配置AUMatrixMixer?

时间:2018-01-02 10:36:19

标签: ios audio

我完全坚持这一点,并希望得到任何帮助......

我在AVAudioEngine图表中实现了AUMatrixMixer,但我无法获得任何声音。如果我将AUMatrixMixer替换为AUMultiChannelMixer,我可以获得声音。 我已经在直接上游节点(AUHighPassFilter)上安装了一个水龙头,我可以看到AUMatrixMixer正在拉动音频。如果我将水龙头移动到AUMatrixMixer的输出端,我可以看到从下一个下游节点 - AVAudioEngine主混音器节点拉出的数据 - 但它都是静音......

关于AUMatrixMixers的评论并不多,所以它可能是一些我不知道的神奇背景。作为参考资料,我收到了来自Apple技术支持的电子邮件,其中包含以下重要观察结果:

" ...要在AVAudioEngine设置中使用Matrix-Mixer,您需要使用+ instantiateWithComponentDescription创建一个AVAudioUnit:options:completionHandler:AVAudioUnit上的API:

由于AVAudioUnit是AVAudioNode的子类,因此您可以使用AVAudioUnit在AVAudioEngine设置中利用Matrix-Mixer。您将能够进行类似于以下的设置:

AVAudioPlayerNode - > AVAudioUnit(配置为分割频道的Matrix混音器音频单元) - >主混音器(您将为多路径频道映射配置) - >输出..."

所以它应该有效。我还分析了Apple提供的示例代码:

(MatrixMixerTest https://developer.apple.com/library/mac/samplecode/MatrixMixerTest/Introduction/Intro.html) - 这不是我想做的事情,但我在API的使用方面看不出任何不同。

创建AUMatrixMixer的代码(一个输入总线,两个输出总线):

private func setupMatrixMixer() {
    AVAudioUnit.instantiate(with: matrixMixerDescr, options: [.loadOutOfProcess], completionHandler: {(audioUnit, auError) in
        if let au = audioUnit {
            self.matrixMixer = au
            var error:OSStatus = noErr
            var numInputBuses:UInt32 = 1
            var numOutputBuses:UInt32 = 2
            // Input bus config
            error = AudioUnitSetProperty(self.matrixMixer.audioUnit,
                                    AudioUnitPropertyID(kAudioUnitProperty_ElementCount),
                                    AudioUnitScope(kAudioUnitScope_Input),
                                    0,
                                    &numInputBuses,
                                    UInt32(MemoryLayout<UInt32>.size))
            if error != noErr {
                assert(true, "ERROR: Setting matrix mixer number of input buses")
                return
            }
            // Output bus config
            error = AudioUnitSetProperty(self.matrixMixer.audioUnit,
                                         AudioUnitPropertyID(kAudioUnitProperty_ElementCount),
                                         AudioUnitScope(kAudioUnitScope_Output),
                                         0,
                                         &numOutputBuses,
                                         UInt32(MemoryLayout<UInt32>.size))
            if error != noErr {
                assert(true, "ERROR: Setting matrix mixer number of output buses")
                return
            }
        }
        else { trace(level: .skim, items: "ERROR: failed to create matrix mixer. Error code: \(String(describing: auError))")}
    } )
}

图表创建:

private func makeEngineConnections() {
    // Get the engine's optional singleton main mixer node
    let output = engine.mainMixerNode
    // Connect nodes
    engine.connect(player, to: timePitch, fromBus: 0, toBus: 0, format: audioFormat)
    engine.connect(timePitch, to: lowPassFilter, fromBus: 0, toBus: 0, format: audioFormat)
    engine.connect(lowPassFilter, to: highPassFilter, fromBus: 0, toBus: 0, format: audioFormat)
    engine.connect(highPassFilter, to: matrixMixer, fromBus: 0, toBus: 0, format: audioFormat)
    engine.connect(matrixMixer, to: output, fromBus: 0, toBus: 0, format: audioFormat)
    engine.connect(matrixMixer, to: output, fromBus: 1, toBus: 1, format: audioFormat)
}

设置后转储引擎图:

________ GraphDescription ________ AVAudioEngineGraph 0x1701c6450:initialized = 1,running = 1,节点数= 8

 ******** output chain ********

 node 0x1700a9960 {'auou' 'rioc' 'appl'}, 'I'
     inputs = 1
         (bus0) <- (bus0) 0x1740ee180, {'aumx' 'mcmx' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]

 node 0x1740ee180 {'aumx' 'mcmx' 'appl'}, 'I'
     inputs = 2
         (bus0) <- (bus0) 0x1700f0200, {'aumx' 'mxmx' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
         (bus1) <- (bus1) 0x1700f0200, {'aumx' 'mxmx' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
     outputs = 1
         (bus0) -> (bus0) 0x1700a9960, {'auou' 'rioc' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]

 node 0x1700f0200 {'aumx' 'mxmx' 'appl'}, 'I'
     inputs = 1
         (bus0) <- (bus0) 0x1740ee100, {'aufx' 'hpas' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
     outputs = 2
         (bus0) -> (bus0) 0x1740ee180, {'aumx' 'mcmx' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
         (bus1) -> (bus1) 0x1740ee180, {'aumx' 'mcmx' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]

 node 0x1740ee100 {'aufx' 'hpas' 'appl'}, 'I'
     inputs = 1
         (bus0) <- (bus0) 0x1740ee700, {'aufx' 'lpas' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
     outputs = 1
         (bus0) -> (bus0) 0x1700f0200, {'aumx' 'mxmx' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]

 node 0x1740ee700 {'aufx' 'lpas' 'appl'}, 'I'
     inputs = 1
         (bus0) <- (bus0) 0x1740ee480, {'aufc' 'nutp' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
     outputs = 1
         (bus0) -> (bus0) 0x1740ee100, {'aufx' 'hpas' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]

 node 0x1740ee480 {'aufc' 'nutp' 'appl'}, 'I'
     inputs = 1
         (bus0) <- (bus0) 0x174198fc0, {'augn' 'sspl' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
     outputs = 1
         (bus0) -> (bus0) 0x1740ee700, {'aufx' 'lpas' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]

 node 0x174198fc0 {'augn' 'sspl' 'appl'}, 'I'
     outputs = 1
         (bus0) -> (bus0) 0x1740ee480, {'aufc' 'nutp' 'appl'}, [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]

 ******** other nodes ********

 node 0x1700ef000 {'aumx' 'mcmx' 'appl'}, 'U'

AUMatrixMixer内部设置有点乏味。总结:

  • 启用输入总线
  • 在每个输入通道上设置音量(其中2个)
  • 启用输出总线(实际上,这是冗余的,因为它们都是永久启用的)
  • 在每个输出通道上设置音量(其中4个)
  • 在每个交叉点上设置卷(我现在将所有内容设置为1(最大卷)) - 其中8个
  • 设置调音台的全局音量(1设置)

执行上述操作后,这是内部状态的转储:

Matrix dimensions: [2, 4]
Input element count: 1
Input channel 0 volume: 1.0
Input channel 1 volume: 1.0
Output element count: 2
Output channel 0 volume: 1.0
Output channel 1 volume: 1.0
Output channel 2 volume: 1.0
Output channel 3 volume: 1.0
Crosspoint volumes: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
Input 0 enabled parameter: 1.0
Output 0 enabled parameter: 1.0
Output 1 enabled parameter: 1.0

如您所见,一切都已启用,所有音量设置为最大但没有输出声音......

如上所述,通过在各个节点的输出上使用敲击,我已经验证了良好的数据正在从高通滤波器移动到矩阵混频器,但它是在矩阵混频器和主混频器之间移动的静音混合节点。

有没有人知道我需要做的其他任何事情才能从中获得声音?

此致 AC

1 个答案:

答案 0 :(得分:1)

我几周来一直面临同样的情况。刚才,我正在撰写一段示例代码,询问Apple Code-Level支持。我正在测试它,就像我要发送一样,假设它不会照常工作,但令人惊讶的是它确实有效!我认为,像AUGraph一样,必须有一些特定的顺序来设置流格式,连接节点等,以使其正常工作。 (而且,和AUGraph一样,文档并没有准确地解释这个命令是什么。)所以我不确定这次我做了什么不同,但至少它现在适用于我。

所以这是一个成功使用AVAudioEngine矩阵混音器的准系统示例:

in