1、阅读前提:
-
Audio Session基础(Audio Session)
-
Core Audio基本数据结构(Core Audio)
-
音视频基础知识
-
C/C++ 简单数据结构,函数使用
以下概念是文中常用的词语,因为其含义一般直接用英文表达, 一般不需中文翻译,可将其理解为固定名词词组.
-
audio unit: 主要介绍的技术名称
-
audio processing graph: 另一种处理audio unit的技术
-
node: 承载audio unit的容器
-
input scope /output scope : 可理解为音频流动的位置(比如从input scope流向output scope)
-
input element : 连接输入端硬件(如麦克风)的一个组件.
-
output element : 连接输出端硬件(如扬声器)的一个组件.
-
bus: 与element概念相同,在文中强调信号流时使用“bus”,在强调音频单元的特定功能方面时使用“element”,\
-
I/O Units: 输入输出常用的audio unit类型,其中包括Remote I/O unit, Voice-Processing I/O, Generic Output unit三种类型.
注意每个element还可能具有input scope与output scope.
1.1 Overview
Audio Unit : iOS提供音频处理插件,支持混合,均衡,格式转换和实时输入/输出,用于录制,播放,离线渲染和实时对话,例如VoIP(互联网协议语音).可以从iOS应用程序动态加载和使用它.
Audio Unit通常在称为audio processing graph的封闭对象的上下文中工作,如图所示。在此示例中,您的应用程序通过一个或多个回调函数将音频发送到graph中的第一个audio unit,并对每个audio unit进行单独控制。最终生成的I / O unit直接输出给连接的硬件.
audio unit是iOS音频层面中最底层的编码层,如果要充分利用它需要对audio unit有更深入的了解.除非你需要实时播放同步的声音,低延迟的输入输出或是一些音频优化的其他特性,否则请使用Media Player, AV Foundation, OpenAL, or Audio Toolbox等上层框架.
1.2 优点
Audio Unit提供了更快,模块化的音频处理,同时提供了强大的个性化功能,如立体声声像,混音,音量控制和音频电平测量。如果想充分使用它的功能,必须深入了解包括音频数据流格式,回调函数和音频单元架构等基础知识。
-
出色的响应能力: 可以通过回调函数访问实时的音频数据.可以直接使用audio unit合成乐器音,实时同步语音.
-
动态的重新配置: 围绕AUGraph opaque类型构建的 audio processing graph API允许以线程安全的方式动态组装,重新配置和重新排列复杂的音频处理链,同时处理音频。这是iOS中唯一提供此功能的音频API。
1.3 生命周期
-
运行时,获取对动态可链接库的引用,该库定义您要使用的audio unit
-
新建一个audio unit实例
-
根据需求配置audio unit
-
初始化audio unit以准备处理音频
-
开启audio unit
-
控制audio unit
-
用完后释放audio unit
1.4 选择设计模式
-
配置audio session负责app与硬件间的交互,配置I/O unit: I/O units有两个独立元素(elements)组成,一个从输入端硬件接收音频数据,一个将音频数据送给输出端硬件.可以根据需求选择我们要开启的元素.
-
构造audio processing graph: 在audio processing graph中,必须指定音频数据流格式.
-
控制audio units的生命周期:建立audio unit的连接并注册回调函数.
2、工作原理
如图所示,audio unit是iOS中音频最底层的API,audio unit仅在高性能,专业处理声音的需求下使用才有意义.
2.1 audio unit提供了快速的,模块化的音频处理**
使用场景
-
以最低延迟的方式同步音频的输入输出,如VoIP.
-
手动同步音视频,如游戏,直播类软件
-
使用特定的audio unit:如回声消除,混音,音调均衡
-
一种处理链架构:将音频处理模块组装成灵活的网络。这是iOS中唯一提供此功能的音频API。
2.1.1 iOS中的audio unit
功能 | Audio units |
---|---|
Effect | iPod Equalizer |
Mixing | 3D Mixer,Multichannel Mixer |
I/O | Remote I/O, Voice-Processing I/O, Generic Output |
Format conversion | Format Converter |
-
Effect Unit
-
-
提供一组预设均衡曲线,如重低音,流行音等等。
-
-
Mixer Units
-
-
3D Mixer unit: OpenAL构建的基础,如果需要3D Mixer unit特性,建议直接使用OpenAL,因为它提供了很多封装好的功能强大的API.
-
Multichannel Mixer unit: 为一个或多个声道的声音提供混音功能,以立体声输出.你可以单独打开或关闭其中一个声道的声音,调节音量,快进快退等.
-
-
I/O Units
-
-
Remote I/O unit: 直接连接输入,输出的音频硬件,以低延迟的方式访问单个接收或发出的音频采样点.提供了格式转换功能,
-
Voice-Processing I/O: 通过声学的回声消除拓展了Remote I/O unit,常用于VoIP或语音通信的应用.它还提供了自动增益校正,语音处理质量调整和静音等功能.
-
Generic Output unit: 不连接音频硬件而是提供了一种机制:将处理链的输出传递给应用程序.通常用来做离线音频处理.
-
-
Format Converter Unit
通常通过I/O unit间接使用.
2.1.2 同时使用两个Audio Unit APIs
iOS有一个用于直接处理audio units的API,另一个用于处理audio processing graphs,可以同时使用这两种API. 然而这两种API中有一部分功能是相同的,如下:
-
获取audio units的动态可链接库的引用
-
实例化audio units
-
连接audio units并注册回调函数
-
启动和停止音频流
2.1.3 指定Audio Unit属性以获取其引用对象
AudioComponentDescription ioUnitDescription;
ioUnitDescription.componentType = kAudioUnitType_Output;
ioUnitDescription.componentSubType = kAudioUnitSubType_RemoteIO;
ioUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
ioUnitDescription.componentFlags = 0;
ioUnitDescription.componentFlagsMask = 0;
AudioComponent foundIoUnitReference = AudioComponentFindNext (
NULL,
&ioUnitDescription
);
AudioUnit ioUnitInstance;
AudioComponentInstanceNew (
foundIoUnitReference,
&ioUnitInstance
);
AudioComponentFindNext
:第一个参数设置为NULL表示使用系统定义的顺序查找第一个匹配的audio unit.如果你将上一个使用的audio unit引用传给该参数,则该函数将继续寻找下一个与之描述匹配的audio unit.
还可以使用audio processing graph API初始化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,
&ioUnitDescription,
&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
);
2.1.4 Audio Units的Scopes,Elements.
如下图,Audio Units由Scopes,Elements组成.
-
scope: audio unit内部的编程上下文,scope概念有一点抽象,可以这样理解,比如input scope表示里面所有的element都需要一个输入。output scope 表示里面所有的element都会输出到某个地方。至于global scope应该是用来配置一些和输入输出概念无关的属性。
-
element: 当element是input/output scope的一部分时,它类似于物理音频设备中的信号总线.因此这两个术语"element, bus"在audio unit中是一个含义.本文档在强调信号流时使用“bus”,在强调音频单元的特定功能方面时使用“element”,例如I / O unit的输入和输出element.
上图展示了audio unit的一种常见架构,其中输入和输出上的element数量相同。然而,不同的audio unit使用不同架构。例如,mixer unit可能具有多个输入element但是具有单个输出element。
-
global scope:作为整体应用于audio unit并且不与任何特定音频流相关联.它只有一个element。该范围仅适用于个别属性,比如每个片的最大帧数(kAudioUnitProperty_MaximumFramesPerSlice)
input , output scopes直接参与通过audio unit移动一个或多个音频流.audio进入input scope并从output scope离开 。属性或参数可以作为整体应用于input或output scope,例如kAudioUnitProperty_ElementCount.其他属性和参数(如enable I / O属性(kAudioOutputUnitProperty_EnableIO)或volume参数&#