Audio Processing Graphs 管理 Audio Units

Audio Processing Graphs 管理 Audio Units

audio processing graph(AUGraph)是一种基于 Core Foundation 风格的数据结构,常用来管理 audio unit 处理链。audio processing graph 可以利用多个 audio unit 与回调函数,以用来解决任意音频处理方法。

AUGraph 类型保证了音频单元的线程安全性,它使得程序员能够实时重新配置处理链。例如,在音频播放时,可以安全地插入均衡器,甚至为混音器输入交换不同的渲染回调函数。事实上,AUGraph 类型提供了 iOS 中唯一用于在音频应用程序中执行此类动态重新配置的 API。

audio processing graph API 使用另一种不透明类型 AUNode 来表示图形上下文中的单个 Audio Unit。使用 audio processing graph 时,通常与 AUNode 交互,作为其包含音频单元的代理,而不是直接与Audio Unit 交互。

然而,当我们将 graph 放在一起时,必须使用 audio unit 的 API 配置每个 audio unit,而 nodes 则不能直接配置audio unit。因此,使用 graph 必须同时使用这两套 API。

还可以通过定义 AUNode 来表示一个完整的 audio processing subgraph(音频处理子图),将 AUNode 实例用作复杂 graph 中的 element。在这种情况下,子图末尾的 I/O 单元必须是 Generic Output unit(一种不连接到设备硬件的 I/O 单元)。

宽泛地说,构建 Audio Processing Graph 需要三步:

  1. 向 graph 中添加 nodes。
  2. 通过 nodes 直接配置 audio units。
  3. 互相连接 nodes。

Audio Processing Graph 拥有精确的 I/O Unit

无论正在录制、播放或是同步,每个 audio processing graph 都有一个 I/O unit。

通过 AUGraphStartAUGraphStop 可以开启或停止音频流。通过 AudioOutputUnitStartAudioOutputUnitStop 可以开启或停止 I/O unit。通过这种方式,graph 的 I/O 单元负责 graph 中的音频流。

Audio Processing Graph 提供线程安全

audio processing graph API 采用“待办事项列表”比喻来提供线程安全。此 API 中的某些功能将工作单元添加到稍后执行的更改列表中。指定完整的更改集后,要求 graph 去实现它们。

以下是 audio processing graph API 支持的一些常见重新配置及其相关功能:

  • 添加、移除 audio unit nodes(AUGraphAddNode, AUGraphRemoveNode)
  • 添加、移除 nodes 间的连接(AUGraphConnectNodeInput, AUGraphDisconnectNodeInput)
  • 连接 audio unit input bus 的回调函数(AUGraphSetNodeInputCallback)

下图描绘了一种架构:构建了一个包含多通道混音器单元和远程 I/O 单元的 graph,用于混合播放两个合成的声音。在输入端,把声音反馈给混音器的两个输入总线。混音器输出进入 I/O 单元的输出元素,然后进入输出音频硬件。

在这里插入图片描述

现在,假设用户想将均衡器插入两个音频流之一。要做到这一点,就在其中一个声音和它的混音器输入之间添加一个 iPod EQ 单元,如下图所示。

在这里插入图片描述

完成此实时重新配置的步骤如下:

  1. 通过调用 AUGraphDisconnectNodeInput 断开 mixer unit input 1 的 “beats sound” 回调。

  2. 将包含 iPod EQ 单元的音频单元节点添加到 graph 中。通过指定具有 AudioComponentDescription 结构的 iPod EQ 单元,然后调用 AUGraphAddNode 来做到这一点。此时,iPod EQ 单元已实例化,但未初始化。它由 graph 拥有,但尚未参与音频流。

  3. 配置和初始化 iPod EQ 单元。在这个例子中,这需要一些步骤:

    • 调用 AudioUnitGetProperty 从 mixer 的输入端检索 kAudioUnitProperty_StreamFormat 流格式。
    • 调用两次 AudioUnitSetProperty,一次设置 iPod EQ 单元的输入流格式,一次设置输出流格式。
    • 调用 AudioUnitInitialize 以分配内存准备使用。这个函数是线程不安全的,但是,当 iPod EQ 单元尚未主动参与 audio processing graph 时,必须在序列时执行它,因为此时没有调用AUGraphUpdate 函数。
  4. 通过调用 AUGraphSetNodeInputCallback,将 “beats sound” 回调函数添加到 iPod EQ 的输入端。

在前面的步骤中,步骤1、2 和 4 都是 AUGraph* 函数调用,它们都被添加到 graph 的“待办事项”列表中。调用 AUGraphUpdate 执行这些待处理的任务。AUGraphUpdate 功能成功返回后,graph 已被动态重新配置,iPod EQ 已到位并处理音频。

通过 graph “pull” 音频流

在 audio processing graph 中可以使用类似生产者消费者模式,消费者在需要更多音频数据时通知生产者。请求音频数据流的方向与音频流提供的方向正好相反,如下图所示:

在这里插入图片描述

对一组数据的每个请求都被称为渲染调用(render call),或者非正式地称为 pull。该图将渲染调用表示为灰色的“控制流”箭头。渲染调用请求的数据更恰当地称为一组音频样本帧(audio sample frames)。反过来,响应拉流而提供的一组音频样本帧被称为 slice。提供 slice 的代码称为渲染回调函数(render callback function)。

图 1-6 的 pull 实现步骤:

  1. 调用 AUGraphStart 函数后,虚拟输出设备会调用远程 I/O 单元输出元素的渲染回调。此调用要求一片已处理的音频数据帧。
  2. 远程 I/O 单元的渲染回调功能在其输入缓冲区中查找要处理的音频数据,以满足渲染调用。如果有等待处理的数据,远程I/O单元会使用它。否则,如图所示,它会调用应用程序连接到其输入的任何内容的渲染回调。在本例中,远程 I/O 单元的输入连接到效果单元的输出。因此,I/O 单元 pull 效果单元,要求提供一段音频帧。
  3. 效果单元的行为与远程 I/O 单元一样。当它需要音频数据时,它会从输入连接中获取。在本例中,效果单元拉动应用程序的渲染回调函数。
  4. 应用程序的渲染回调函数是 pull 的最终接收者。它向效果单元提供所需的帧。
  5. 效果单元处理应用程序渲染回调提供的 slice。然后,效果单元将之前请求的处理数据(在步骤 2 中)提供给远程 I/O 单元。
  6. 远程 I/O 单元处理效果单元提供的切片。然后,远程 I/O 单元将最初请求的已处理切片(在步骤 1 中)提供给虚拟输出设备。这完成了一个 pull 周期。
  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值