音频输出单元的输入回调中允许哪些操作

Posted

技术标签:

【中文标题】音频输出单元的输入回调中允许哪些操作【英文标题】:What actions are permitted in an Audio Output Unit's input callback 【发布时间】:2015-04-20 22:27:23 【问题描述】:

我正在使用音频输出单元来捕获麦克风数据。我收到通知,通过我使用 kAudioOutputUnit_SetInputCallback 属性设置的回调读取数据,并在回调中通过调用 AudioUnitRender() 读取数据。

最终,我将根据通过分析这些数据提取的一些信息来更新我的应用程序的用户界面。因此,我需要在某个阶段对主队列执行 dispatch_async。分析相当耗时,并且是分块完成的,而不是我从 AudioUnitRender() 获得的那些,因此负载是突发性的。

我的问题是:在输入回调本身的实现中,哪些操作被认为是可以接受的?我发现很多资料表明对 render 回调有严格限制(没有内存分配、没有 i/o、没有与其他线程同步等),但根本没有关于 input 回调。

如果我遵循与渲染回调相同的规则,我会遇到一些挑战。 dispatch_async() 本身是不可取的,因为它会分配内存,而且负载无论如何都是突发的(在某些回合中很容易超过一个渲染周期,而在其他回合中几乎为零)。因此,似乎有必要将我的数据发送到工作线程进行处理并进行 dispatch_async() 调用。但是,我仍然需要管理将数据传递到此工作线程。最简单的方法(在 C++ 中)是使用循环缓冲区,加上互斥体和条件变量,以在数据可用时发出信号。但是,这将需要输入回调来锁定互斥锁,而渲染回调指南明确不鼓励这样做。

避免这种互斥锁将带我使用无锁循环缓冲区、信号量(POSIX 或 GCD)、自旋锁等,我想知道这对于简单地听麦克风是否有点过头了。这些东西缺乏令人震惊的文档,我不知道幕后到底发生了什么。我真的需要担心在我的输入回调实现中等待互斥锁(仅短暂且很少被另一个线程锁定)吗?

【问题讨论】:

【参考方案1】:

我使用来自:https://github.com/michaeltyson/TPCircularBuffer的循环缓冲区

描述说明:

只要您将多线程访问限制为仅一个生产者和一个消费者,此实用程序就应该是线程安全的。

因此,您可以安全地从循环缓冲区渲染(生产)和处理(消费),而不必担心锁。

更新

我真的需要担心在我的输入回调实现中等待互斥锁(只是短暂且很少被另一个线程锁定)吗?

对此我说是的。 “很少锁定”是输入回调失败所需的全部内容。而“简要”已经太长了。我有输入回调失败只是因为 NSLogging 的东西。

【讨论】:

是的,正如我在最后提到的,为了避免互斥锁,看起来我需要一个无锁循环缓冲区和 std::condition_variable 以外的其他东西来获取工人当有数据时线程唤醒(GCD 信号量看起来最有希望)。这种循环缓冲区实现很有帮助,而且它实际上具有 documented 线程保证,这与 CARingBuffer 不同,所以非常感谢。然而,问题仍然是在输入回调中是否真的需要避免互斥锁。

以上是关于音频输出单元的输入回调中允许哪些操作的主要内容,如果未能解决你的问题,请参考以下文章

直接调用音频单元而不是回调 iOS

输入标签内的 HTML 名称属性中允许使用哪些字符?

如何使用音频单元 osx 从设备音频输入中获取音频

覆盖接近传感器时,音频单元增加渲染回调 inNumberFrames

使用 AUHAL 音频单元将字节写入音频文件

什么会影响音频单元渲染回调周期(周期)?