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

时间:2011-11-24 16:18:46

标签: ios core-audio

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

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

即使我有PCM数据的缓冲区,我也无法让应用程序实际播放声音。在搜索iOS文档后,我开始实现AudioUnit。这个AudioUnit的问题是使用渲染回调(据我所知,输出声音的唯一方法)。来自Apple's developer documentation

  

...渲染回调具有严格的性能要求,您必须这样做   坚持。渲染回调存在于实时优先级线程上   后续的渲染调用是异步到达的。你做的工作   在渲染回调的主体中,在这个时间受限的情况下发生   环境。如果您的回调仍在生成示例帧   在下一次渲染调用时响应上一次渲染调用   到了,你的声音就会出现差距。因此你不能服用   锁定,分配内存,访问文件系统或网络   连接,或以其他方式执行耗时的任务   渲染回调函数

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

唯一的例子I found实际上在render方法中生成了PCM数据,这是我无法做到的。

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

是否可以从内存中播放PCM数据?

1 个答案:

答案 0 :(得分:4)

使用RemoteIO音频单元可能需要在音频单元回调之外设置单独的数据队列(fifo或循环缓冲区),这可以预先缓冲来自文件读取的足够音频数据,在音频单元渲染回调之前,到遇到更糟糕的案例延迟。然后,渲染回调只需要快速复制音频数据,然后更新一个只写标志,指示音频数据被消耗。

iOS内置的替代方案是使用Audio Queue API,它为您进行预缓冲。它允许您的应用提前在主运行循环中填充许多较大的音频缓冲区。您仍然需要预先缓冲足够的数据以允许最大的文件,网络,锁定或其他延迟。

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