匹配 AVAudioEngine 的输入和输出硬件设置

Posted

技术标签:

【中文标题】匹配 AVAudioEngine 的输入和输出硬件设置【英文标题】:Matching Input & Output Hardware Settings for AVAudioEngine 【发布时间】:2016-05-02 21:21:28 【问题描述】:

我正在尝试使用 Core Audio for ios 构建一个非常简单的音频效果链。到目前为止,我已经实现了一个 EQ - Compression - Limiter 链,它在模拟器中运行良好。但是在设备上,由于输入和输出硬件格式明显不匹配,应用程序在将节点连接到 AVAudioEngine 时会崩溃。

'com.apple.coreaudio.avfaudio', reason: 'required condition is false:
 IsFormatSampleRateAndChannelCountValid(outputHWFormat)'

举个基本的例子,我的Audio Graph如下。

Mic -> Limiter -> Main Mixer (and Output)

图表使用

填充
engine.connect(engine.inputNode!, to: limiter, format: engine.inputNode!.outputFormatForBus(0))
engine.connect(limiter, to: engine.mainMixerNode, format: engine.inputNode!.outputFormatForBus(0))

由于上述异常而崩溃。如果我在连接到混音器时改用限制器的格式

engine.connect(engine.inputNode!, to: limiter, format: engine.inputNode!.outputFormatForBus(0))
engine.connect(limiter, to: engine.mainMixerNode, format: limiter.outputFormatForBus(0))

应用程序因 kAudioUnitErr_FormatNotSupported 错误而崩溃

'com.apple.coreaudio.avfaudio', reason: 'error -10868'

在引擎中连接音频节点之前,inputNode有1个通道,采样率为44.100Hz,而outputNode有0个通道,采样率为0Hz(使用outputFormatForBus(0)推导财产)。但这可能是因为还没有节点连接到输出混音器?在 AVAudioSession 上设置首选采样率没有任何区别。

这里有什么我遗漏的吗?我有麦克风访问权限(使用 AVAudioSession.sharedInstance().recordPermission() 验证),并且我已将 AVAudioSession 模式设置为录制 (AVAudioSession.sharedInstance() .setCategory(AVAudioSessionCategoryRecord))。

限制器是一个 AVAudioUnitEffect,初始化如下:

let limiter = AVAudioUnitEffect( audioComponentDescription:
                AudioComponentDescription(
                    componentType: kAudioUnitType_Effect,
                    componentSubType: kAudioUnitSubType_PeakLimiter,
                    componentManufacturer: kAudioUnitManufacturer_Apple,
                    componentFlags: 0,
                    componentFlagsMask: 0) )
engine.attachNode(limiter)

并且引擎是一个全局的类变量

var engine = AVAudioEngine()

正如我所说,使用模拟器(和 Mac 的默认硬件)可以正常工作,但在 iOS8 和 iOS9 上的各种 iPad 上不断崩溃。我有一个超级基本的例子,它只是将麦克风输入提供给播放器到输出混音器

do 
     file = try AVAudioFile(forWriting: NSURL.URLToDocumentsFolderForName(name: "test", WithType type: "caf")!, settings: engine.inputNode!.outputFormatForBus(0).settings)
 catch 
engine.connect(player, to: engine.mainMixerNode, format: file.processingFormat)

这里 inputNode 有 1 个通道和 44.100Hz 的采样率,而 outputNode 有 2 个通道和 44.100Hz 的采样率,但似乎没有出现不匹配的情况。因此问题一定是 AVAudioUnitEffect 连接到输出混音器的方式。

任何帮助将不胜感激。

【问题讨论】:

你有想过这个吗? AVAUdio 的背后是一个可怕的痛苦,文档写得不好,引擎按照非常模糊的规则工作,以及无用的错误代码。这很糟糕,但我们必须向前耕耘。如果我解决它,我会发布答案。 你有复制这个的项目吗? 【参考方案1】:

这取决于您共享的代码之外的一些因素,但您可能使用了错误的 AVAudioSession 类别。

在一些略有不同的情况下,我遇到了同样的问题。当我使用 AVAudioSessionCategoryRecord 作为 AVAudioSession 类别时,我在尝试连接音频分接头时遇到了同样的问题。我不仅收到了这个错误,而且我的 AVAudioEngine inputNode 显示了一个采样率为 0.0 的 outputFormat。

将其更改为 AVAudioSessionCategoryPlayAndRecord 我收到了预期的 44.100Hz 采样率,问题已解决。

【讨论】:

以上是关于匹配 AVAudioEngine 的输入和输出硬件设置的主要内容,如果未能解决你的问题,请参考以下文章

iOS8 AVAudioEngine 如何将麦克风输入路由到(底部)扬声器输出?

使用 AVAudioEngine 进行电平测量

如何将 AVAudioEngine 连接到 Lightning Port 音频输入?

swift AVAudioEngine 和 AVAudioSinkNode sampleRate 转换

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

Swift AVAudioEngine:更改MacOS的音频输入设备