如何获取音频块以在核心音频或 AVFoundation 中进行分析
Posted
技术标签:
【中文标题】如何获取音频块以在核心音频或 AVFoundation 中进行分析【英文标题】:How to obtain audio chunks for analysis in core audio or AVFoundation 【发布时间】:2016-01-15 15:00:51 【问题描述】:我需要以 8kHz 的采样率分析(大约)1 秒的音频数据块。虽然音频将被实时记录,但它仅用于检测特定事件。因此,没有严格的延迟要求。在这种情况下使用的最佳框架是什么?
我已经开始学习 Core Audio,并且通过了《Learning Core Audio》一书进行了学习。借助互联网上最少量的 Swift 文档,我能够为 ios 设置一个 AUGraph,以使用远程 I/O 音频单元录制音频,并通过输出渲染回调访问原始样本。不幸的是,我被困在创建 1 秒的音频样本块来执行音频分析。可以为此使用自定义 AudioBufferList 吗?或者是否可以在远程 I/O 音频单元上实现大型环形缓冲区(就像在 HAL 音频单元的情况下需要它一样)?
我还尝试采用带有 AVAssetReader 的 AVFoundation 来获取音频块。虽然我能够获得录制的音频信号的样本,但我没有成功创建 1 秒的缓冲区(我什至不知道是否可以实时做到这一点)。无论如何,在这种情况下,AVFoundation 会是一个不错的选择吗?
如果您对此提出任何建议,我将不胜感激。
我的一个主要问题是我尝试使用 Swift 但没有太多示例代码可用,而且文档更少。我觉得最好切换到 Objective-C 进行音频编程,并停止尝试在 Swift 中获取所有内容。我很好奇这是否是更好的时间投资?
【问题讨论】:
【参考方案1】:要分析 1 秒窗口的音频样本,最简单的解决方案是使用带有无锁环形缓冲区(例如大约 2 秒长)的音频队列 API 来记录样本。您可以使用重复的 nstimer 任务来轮询缓冲区的满载情况,并在它们可用时将 1 秒的块发送到处理任务。
Core Audio 和 RemoteIO 音频单元适用于您需要更短的数据窗口,延迟要求大约为几毫秒。
【讨论】:
这很清楚。因为我将来可能想做实时音频处理,所以我认为 Audio Units 最适合我。尽管您的答案很有用,但由于示例代码,我接受了另一个答案(不幸的是,我不能同时接受)。【参考方案2】:Core Audio 是一个 C API。 Objective-C 是 C 的扩展。我发现 Objective-C 在处理核心音频方面比 swift 更好。
我创建了一个跨平台的 c 无锁环形缓冲区。有示例代码演示了设置环、设置麦克风、播放音频以及从环中读取和写入。
环记录您指定的持续 N 秒数。旧数据被新数据覆盖。因此,您指定要记录最近的 3 秒。我展示的示例在通过麦克风录制时播放正弦波。每 7 秒,它会抓取最后 2 秒的录制音频。
Here is the complete sample code on github.
【讨论】:
这很有帮助!非常感谢。根据您的评论和我在 Swift 中使用 Core Audio 的经验,我决定改用 Objective-C。虽然我完成了“Learning Core Audio”,但我可能需要更多地提高我的 Objective-C 技能,但我一定会尝试更详细地理解你的代码。现在我想知道您实现的环形缓冲区与 Apple 的 CARingBuffer 和 Michael Tyson 的 TPCircularBuffer 之间是否存在重大差异? 好久没看TP了。但总的来说,M. Tyson 写的任何东西都是好的。我没有看过 CA,但我确信它是可靠的。大多数环形缓冲区允许您“使用”并删除缓冲区中最早的数据(FIFO)。所以从环中读取得到最旧的数据。我的工作是最新的数据。它在 2 秒前和现在之间获取数据。假设您有 6 秒的缓冲区。我的读取得到 4 到 6 秒,而其他环形缓冲区实现得到 0 到 2 秒。所以我的就像一个 LIFO。如果您没有任何实时限制,TP 或 CA 可能工作正常。 我终于完成了你的代码,我理解得很好。但是,在运行代码时,播放不起作用(只是正弦波)。我观察到渲染回调(outRenderProc)中没有AudioUnitRender可以从系统输入(只是正弦波发生器)中绘制。但是当我添加 AudioUnitRender 时,什么都没有改变。可能是interruptListener配置不正确?我试图修改它,但无法让它工作。我希望你能对此发表评论。 您是否要从麦克风获取音频?如果不是,您的音频来源在哪里,扬声器是否在播放任何内容? 我发现问题似乎与 i/o AU 的输入范围上的立体声流格式有关。当我在渲染回调中设置 AudioUnitRender 而不是正弦波时,不会播放音频(尽管它适用于单流格式)。我的问题是将输入样本复制到输出通道,以便可以立体声播放。我放置了一个新的question。也许,你也可以在这里帮助我,但是你的代码对我理解材料很有帮助!以上是关于如何获取音频块以在核心音频或 AVFoundation 中进行分析的主要内容,如果未能解决你的问题,请参考以下文章