如何正确使用iOS AudioUnit渲染回调

rah*_*ark 5 core-audio ios

我正在编写一个 iOS 应用程序,它将播放音频指令作为其功能之一。

\n\n

每次应用程序想要播放音频时,它都会从非标准文件中读取并将该音频的结果 PCM 数据放入内存的缓冲区中。

\n\n

尽管我有 PCM 数据的缓冲区,但我在让应用程序实际播放声音时遇到了困难。在搜索了 iOS 文档之后,我开始实现一个 AudioUnit。这个 AudioUnit 的问题是使用渲染回调(据我所知,这是输出声音的唯一方法)。来自苹果的开发者文档

\n\n
\n

\xe2\x80\xa6 渲染回调有严格的性能要求,您必须\n 遵守。渲染回调存在于实时优先级线程上,后续渲染调用异步到达。您在渲染回调主体中所做的工作发生在这个时间受限的环境中。如果当下一个渲染调用到达时,您的回调仍在响应上一个渲染调用而生成示例帧,您会在声音中出现间隙。因此,您不得在渲染回调函数体内获取锁、分配内存、访问文件系统或网络连接或以其他方式执行耗时的任务

\n
\n\n

如果我不能在渲染回调方法中使用锁,我就无法在写入缓冲区时读取缓冲区。没有机会读取文件并写入缓冲区,因为渲染回调将不断访问它。

\n\n

我发现的唯一示例实际上在渲染方法中生成了 PCM 数据,但我做不到。

\n\n

这是使用 AudioUnits(带有异步渲染回调)的唯一方法吗?

\n\n

是否有其他方法可以从内存中播放 PCM 数据?

\n

hot*_*aw2 4

使用 RemoteIO 音频单元可能需要在音频单元回调之外有一个单独的数据队列(fifo 或循环缓冲区),它可以在音频单元渲染回调之前从文件读取中预先缓冲足够的音频数据,以满足最坏的情况延迟。然后渲染回调只需要快速复制音频数据,然后更新指示音频数据已被消耗的只写标志。

iOS 中内置的另一种方法是使用音频队列 API,它可以为您进行预缓冲。它允许您的应用程序提前在主运行循环中填充多个较大的音频缓冲区。您仍然必须预先缓冲足够的数据,以允许最大的文件、网络、锁定或其他延迟。

另一种策略是,如果文件或网络读取没有跟上,则使用替代音频数据来提供实时渲染回调,例如快速创建一个逐渐减小到静音的音频缓冲区(然后在实际数据开始到达时取消逐渐减小)再次)。