我可以发送使用 AVAudioSinkNode 接收到的声音缓冲区以使用 AVAudioSourceNode 进行实时渲染吗?

问题描述 投票:0回答:2

我正在尝试新的 AVAudioSinkNodeAVAudioSourceNode 节点,与 AVAudioEngine 一起使用。

在设置方面,与另一篇post中描述的测试类似,我的接收器节点连接到输入节点(例如麦克风),我的源节点连接到输出节点(例如扬声器)。接收器回调按预期工作。另外,在源节点一侧,我生成了一个正弦波信号——源节点似乎也正常工作。

问题

出于测试目的,我想将在接收器节点捕获的(浮动)缓冲区发送到源节点,最好是实时发送并且不保存到文件。这应该具有将麦克风输入重放到扬声器输出的效果。有没有(简单?)方法可以做到这一点?

本质上,我正在寻找一种将接收器节点连接到源节点的方法,即使这些节点可能不应该以这种方式使用,因为接收器节点没有输出总线并且源节点没有输入总线 (来源).

我假设我可以将输入节点连接到连接到输出节点的混音器,以便将麦克风输入传输到扬声器,但出于我的目的,我想在配置中使用新的接收器和源节点,如上所述。

我在想我需要以某种方式对接收节点捕获的缓冲区进行排队,直到源节点可以读取它们以填充自己的缓冲区。我研究了音频队列服务,但它似乎不合适。

swift avfoundation core-audio avaudioengine
2个回答
1
投票

实时执行此操作的方法是使用音频单元回调(其缓冲区可以小至几毫秒)。它们几乎总是具有相同的大小(除了设备电源状态发生变化时),因此只需保存每个,根据需要对其进行处理,并为几毫秒后的下一个输出做好准备。或者使用圆形/环形 fifo/缓冲区。 iOS 中的 RemoteIO 音频单元已同步 I/O。


0
投票

接受的答案是正确的。我面临的挑战是找到一个完整、简单、有效的 AUAudioUnit 实现示例。

为了直接回答原来的问题,您可以通过 AVAudioSinkNode 接收帧,以某种方式处理它们,并将结果帧传递给 AVAudioSourceNode。我已经编写了一个应用程序来完成这个任务。

通过接收器节点接收到的帧被处理并放入我编写的 CircularAudioFrameQueue 中。它基本上是一个带有头索引和尾索引的 UInt32 数组。由于接收器节点和源节点闭包是在同一音频线程上调用的,因此不需要同步(事实上,这不利于这些节点的实时要求)。

源节点只是从该队列中提取帧并将它们复制到提供给源节点闭包的缓冲区中。

从我所看到的来看,它非常可靠,并且它的优点是让我获得非常小的缓冲持续时间,甚至小于 10 毫秒。

我知道这个问题有点过时,但我在搜索信息和示例时偶然发现了它。所以我认为有必要做出简短的回应。

© www.soinside.com 2019 - 2024. All rights reserved.