iOS提供了音频处理插件,支持混合、均衡、格式转换和实时输入/输出用于录制、播放、离线渲染和实时对话如VoIP(互联网协议语音)。你可以从iOS应用动态加载和使用它,这些强大和灵活的插件叫做Audio Unit。
Audio units通常工作在一个封闭对象的上下文中,该对象为audio processing graph,如下图。在此例中,你的app通过一个或多个callback functions发送audio到第一个audio unit,并对每个audio unit单独控制。I/O输出unit,直接连接输出硬件。
audio_unit.png
Audio units提供非常有用的个性化功能,如立体声像,混音,音量控制,音频电平测量。
1、低延迟的同时音频I/O(输入和输出),例如VoIP应用
2、响应回放合成声音,例如用于音乐游戏或或合成乐器
3、使用特定的音频单元功能,例如回声消除,混音,或者音调均衡
4、一种处理链架构,让你灵活的将音频处理模块组装起来,这是iOS中唯一提供此功能的音频API
iOS根据功能提供了七种audio unit,分为四类,如下图:
category.png
3.1 Effect Unit
iOS4提供了一个effect unit,即iPod Equalizer,与内置iPod应用程序使用的均衡器相同。要查看该audio unit的iPod应用程序用户界面,请转至Setting> iPod> EQ。 使用此audio unit时,您必须提供自己的UI。 该audio unit提供一组预设均衡曲线,如低音增强器,流行音乐和口语
3.2 Mixer Units
iOS提供两个mixer units。3D Mixer unit是OpenAL构建的基础。在大多数情况下,如果需要3D Mixer unit的功能,最佳选择是使用OpenAL,它提供更适合游戏应用的更高级API。
Multichannel Mixer unit可以为任意数量的单声道或立体声流提供混音,并带有立体声输出。你可以打开或关闭每个输入,设置其输入增益,并设置其立体声平移位置。
3.3 I/O Units
iOS提供三个I/O unit。Remote I/O是最常用的。它连接输入和输出音频硬件,并为你提供对各个传入和传出音频样品值的低延迟访问。它提供硬件音频格式和应用程序音频格式之间的格式转换,通过Format Converter unit进行格式转换。
Voice-Processing I/O unit通过添加声学回声消除来扩展远程I/O单元,以用于VoIP或语音聊天应用程序。它还提供自动增益校正,语音处理质量和静音。
Generic Output unit不连接到音频硬件,而是提供将处理链的输出发送到应用程序。通常使用Generic Output unit 进行离线音频处理
3.4 Format Converter Unit
iOS4提供,通常通过I/O单元间接使用
要在运行时查找audio unit,需要为AudioComponentDescription数据结构指定type,subtype,manufacturer。无论是audio unit还是audio process graph API。
AudioComponentDescription audioDesc = {0};
audioDesc.componentType = kAudioUnitType_Output;
audioDesc.componentSubType = kAudioUnitSubType_RemoteIO;
audioDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
不同的audio unit的AudioComponentDescription设置如下图表:
component_description_setting.png
5.1 使用AudioComponentDescription初始化Audio Unit:
// find component
AudioComponent compoent = AudioComponentFindNext(NULL, &audioDesc);
// create new instance
AudioComponentInstanceNew(compoent, &audioUnit);
5.2 使用AUGraph来初始化audio unit:
// Declare and instantiate an audio processing graph
AUGraph processingGraph;
NewAUGraph (&processingGraph);
// Add an audio unit node to the graph, then instantiate the audio unit
AUNode ioNode;
AUGraphAddNode (processingGraph, &audioDesc, &ioNode);
AUGraphOpen (processingGraph); // indirectly performs audio unit instantiation
// Obtain a reference to the newly-instantiated I/O unit
AudioUnit ioUnit;
AUGraphNodeInfo (processingGraph, ioNode, NULL, &ioUnit);
Audio unit的各个部分组织成scopes and element,如下图所示。当调用函数去配置和控制audio unit时,你可以指定scope和element以标识函数的特点目标。
scope_elements.png
scope是audio unit内的编程上下文。虽然global scope可能暗示,但这些上下文从不嵌套。一般是使用一个常量值来自AudioUnitScope枚举。
element是嵌套在audio unit scope中的编程上下文。当element是输入或输出scope的一部分时,它类似于物理音频设备中的信号总线,因此有时成为总线。
global scope适用于整个audio unit,不与任何特定音频流相关联。它只有一个元素,即0。某些属性,如每个切片最大帧数(kAudioUnitProperty_MaximumFramesPerSlice),仅适用于global scope
输入和输出scopes直接参与通过audio unit移动一个或多个音频流。正如你所期待的那样,音频输入scope进入从输出scope离开。属性或参数可以作为整体应用于输入scope或输出scope,某些属性只能应用于scope特定的element
AudioUnitProperty是一个键值对。以下是audio unit开发中常用的一些属性:kAudioOutputUnitProperty_EnableIO
:用于在I/O unit上启用和禁用input or output。默认情况输出已启用,输入已禁用kAudioUnitProperty_ElementCount
:用于配置mixer unit上输入elements的数量kAudioUnitProperty_MaximumFramesPerSlice
:用于指定audio unit应准备响应于渲染调用而产生的音频数据最大帧数。不需要为I/O unit设置该值,因为它们已预先配置为处理系统请求的任何切片大小。对于其它audio unit,你必须将此属性设置为4096以处理屏幕睡眠,除非设备上正在运行音频输入。当音频输入运行时,系统保持切片大小为1024kAudioUnitProperty_StreamFormat
:用于指定特定音频单元输出或输出总线的音频流数据格式
发现属性的可用性,访问其值以及监听其值的更改使用以下函数
audio unit parameter是用户可调节的设置,可在audio unit产生音频时改变。实际上,大多数parameters是在audio unit正在执行处理时,实时调整的。它也是键值对的形式。每个parameter的值是32位浮点类型。使用以下函数来设置或获取parameter的值:
I/O_unit.png
上图I/O Unit有两个element,但它们是独立的,例如,你可以根据应用程序的需要使用enable I/O属性(kAudioOutputUnitProperty_EnableIO)来独立启用或禁用某个element。每个element都有Input scope和Output scope。
I/O Unit的element 1
连接音频的输入硬件,在上图中由麦克风表示。开发者只能访问控制Output scope
I/O Unit的element 0
连接音频的输出硬件,在上图中由扬声器表示。开发者只能访问控制Input scope
input element is element 1(单词Input的字母“I”,类似1)
output element is element 0 (单词Output的字母“O”,类型0)
使用数据类型AUGraph,用于构建和管理audio unit处理链。它可以利用多个音频单元和多个渲染回调函数的功能,允许你创建几乎任何你能想象的音频处理解决方案。
AUGraph是线程安全的,它能够动态地重新配置处理链。例如,你可以安全的插入均衡器,甚至可以在播放时交换混音器输入的不同渲染回调函数。事实上AUGraph是iOS唯一提供的API,用于在音频应用中执行此类动态重新配置。
AUNode来表示graph上下文中的单个audio unit。当使用graph是,你通常与node交互,而不是直接与audio unit交互
当你将graph放在一起时,你必须配置每个audio unit。为此你必须通过audio unit API直接与audio unit进行交互。audio unit node本身是不可配置的
你还可以将AUNode实例作为复杂graph中的元素,通过定义node来表示完整audio processing subgraph。在这种情况下,subgraph末尾必须是Generic Output unit(一种不连接到硬件设备的I/O unit)
总而言之,构建audio processing graph需要三个任务:
1、添加node到graph
2、直接配置nodes表示的audio units
3、互连nodes
AUGraph提供了以下函数来重新配置:
AUGraphAddNode,AUGraphRemoveNode:添加或移除audio unit node
AUGraphConnectNodeInput,AUGraphDisconnectNodeInput:添加或移除nodes之间的connections
AUGraphSetNodeInputCallback:connecting一个渲染回调给audio unit的input bus
I/O Pass Through
I/O pass-through模式将传入的音频直接发送到硬件输出,中间没有处理音频数据。
I/O.png
I/O Without a Render Callback Function
在Remote I/O unit的elements之间添加一个或多个其它audio unit,可以构建出更有用的应用,因为没有回调函数,则无法直接操作音频,限制了实用性。
I/O_No_Callback.png
I/O with a Render Callback Function
在Remote I/O unit之间添加一个回调函数,可以在传入音频到达输出硬件之前对其进行操作。比如使用渲染回调函数调整输出音量,添加颤音,铃声调制,回声或其他效果。通过使用Accelerate框架中提供的傅立叶和卷积函数,你的可能性是无穷尽的
render_callback.png
Output-Only with a Render Callback Function
适用于游戏和音乐合成app,将渲染回调函数直接连接到Remote I/O的Output element的input scope
only_output.png
complex pattern
complex.png
参考文章:
Audio Unit Hosting Guide for iOS
4人点赞
作者:流星泪x
链接:https://www.jianshu.com/p/8ce865c9bbac
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。