1

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

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

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

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

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

4

1 回答 1

2

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

描述指出:

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

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

更新

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

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

于 2015-04-20T23:07:11.723 回答