1. 音频基础
1.1 语音产生的过程
声音是一种波,其振动频率在 20Hz ~ 20kHz 之间,语音是有一定语法和意义的声音,其振动频率最高可达 1.5kHz.
语音由肺和气管提供能源,生成气流;喉是声音的生成机构,气流冲击喉部的声带,形成周期性的开启和闭合,产生振动,发出声音;最后通过声道时,声道不同的形状将声音调制成语音。
声带的周期性开启和闭合称为基音周期,其倒数为基音频率,简称基频。频率快则声调高,频率慢则音调低。
声道是分布参数系统,为谐振腔,有多个谐振频率,声道外形变化产生不同谐振频率。
这些谐振频率称为共振峰频率,简称共振峰。语音频率特性主要由共振峰决定,它决定了所发出声音的频谱特性即音色。
共振峰可由语音的频谱特性观察到,语音可以用多个共振峰准确描述。声学语音学中考虑前两个共振峰,语音识别至少考虑三个共振峰,语音合成则需要五个共振峰。
1.2 语音的基本特性
物理特性:
- 音质:是一种声音区别于其它声音的基本特征
- 音调:是声音的高低,取决于声波的频率;频率开则音调高,频率慢则音调低
- 音强:声音的强弱,即音量,又称响度,由声波振动的幅度决定
- 音长:声音的长短,取决于发音持续时间的长短
语音信号:
- 时间波形
- 频谱特性
- 统计特性
1.3 语音的感知
- 音色:也称音质
- 音调:也称音高,是人耳对声音频率高低的感受
- 响度:是人耳对声音强弱程度的主观反应,取决于声音的幅度
- 听觉掩蔽效应:是指在强信号附近的弱信号听不到,即被掩蔽掉
2. AudioUnit
AudioUnit 是 iOS 中所有音频处理 api 的基础,Media Player, AV Foundation, OpenAL, and Audio Toolbox 都是对 AudioUnit 进行封装。只有在需要高性能,高扩展性,以及使用 AEC 等特性时,建议直接使用 AudioUnit 。
2.1 Create AudioUnit
iOS 提供了直接使用 AudioUnit 和 Audio process graphs 两套 API:
- 指定 type, subtype, and manufacturer keys
AudioComponentDescription ioUnitDescription;
ioUnitDescription.componentType = kAudioUnitType_Output;
ioUnitDescription.componentSubType = kAudioUnitSubType_RemoteIO;
ioUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
ioUnitDescription.componentFlags = 0;
ioUnitDescription.componentFlagsMask = 0;
- 使用 AudioUnit API 创建 AudioUnit
AudioComponent foundIoUnitReference = AudioComponentFindNext (
NULL,
&ioUnitDescription
);
AudioUnit ioUnitInstance;
AudioComponentInstanceNew (
foundIoUnitReference,
&ioUnitInstance
);
- 使用 Audio process graphs 创建 AudioUnit
// 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.2 scope&element
AudioUnit 分成 scope 和 element 两个部分。
- scope 是 AudioUnit 中的可编程上下文,分为 input, output, global 三类。
- element 又称作 bus,是嵌入到 scope 中的可编程上下文。 input/output scope 代表了 audio stream 的流动方向,audio stream 从 input 进入,从 output 离开。通常的 AudioUnit 只有一个 input/output,但如果是混音的 AudioUnit 则会存在多个 input 和一个 output。
global 则是对应 AudioUnit 整体,不关联特定的 audio stream ,且只有一个 element 0。
2.3 AudioUnit property¶meters
AudioUnit 的 property 格式为 key-value , key 为整数。设置 property 的函数为AudioUnitSetProperty
UInt32 busCount = 2;
OSStatus result = AudioUnitSetProperty (
mixerUnit,
kAudioUnitProperty_ElementCount, // the property key
kAudioUnitScope_Input, // the scope to set the property on
0, // the element to set the property on
&busCount, // the property value
sizeof (busCount)
);
AudioUnit 的使用中有几个常用的 property:
kAudioOutputUnitProperty_EnableIO, for enabling or disabling input or output on an I/O unit. By default, output is enabled but input is disabled.kAudioUnitProperty_ElementCount, for configuring the number of input elements on a mixer unit, for example.kAudioUnitProperty_MaximumFramesPerSlice, for specifying the maximum number of frames of audio data an audio unit should be prepared to produce in response to a render call. For most audio units, in most scenarios, you must set this property as described in the reference documentation. If you don’t, your audio will stop when the screen locks.kAudioUnitProperty_StreamFormat, for specifying the audio stream data format for a particular audio unit input or output bus.
AudioUnit 的 parameters 与 property 一样是 key-value 格式,设置一些用户可调的参数,例如音量和立体声等。不同的是 value 的类型都是 32 位浮点数,取值范围和单位由具体参数决定。
2.4 I/O Unit
I/O Unit 是 AudioUnit 中最常用的一类。Element0 和 Element1 属于同一个 I/O Unit ,但是需要分别独立配置。Element1 的 input scope 连接到输入设备,例如麦克风。Element0 的 output scope 连接到输出设备,例如扬声器。
在一个输入输出同时激活的 APP 中,将从 Element1 的 output scope 接受到 audio stream , 再将 audio stream 发送到 Element0 的 input scope 。
Working with audio units, you’ll often hear the two elements of an I/O unit described not by their numbers but by name:
- The input element is element 1 (mnemonic device: the letter “I” of the word “Input” has an appearance similar to the number 1)
- The output element is element 0 (mnemonic device: the letter “O” of the word “Output” has an appearance similar to the number 0)
2.5 AUGraph
AUGraph 是一个 Core Foundation 风格的类型,用来创建和管理 AudioUnit process chain ,支持串联多个不通能力的 AudioUnit 和 多个 render callback 函数。相关 API 是线程安全,且可以在音频播放过程中进行调整。通过 to-do list 方式,在调用一系列 API ,创建一个完整的修改集合后,再调用 AUGraphUpdate 统一执行修改。