iOS基于Audio Unit的实时音频录制流程
前言
本文在基于开发项目中的一个语音模块功能所作出的对Audio Unit的使用的简要总结。 在iOS中有很多方法可以进行音视频采集。如 AVCaptureDevice, AudioQueue以及Audio Unit。其中 Audio Unit是最底层的接口,其优点在于功能强大,延迟低; 但弊端在于学习成本高,难度大。
对于iOS的Audio Unit一共三种设置:
1.一个IO Unit(其中remote io unit是iPhone 的三个IO Unit中的一个)的element 1(bus 1)直接与设备上的输入硬件(麦克风)相连;
2.一个IO Unit的element 0(也叫bus 0)直接与设备上的输出硬件(比如扬声器)相连;
3.Remote IO Unit启用了输出而禁止了输入。
对于其设计模式可分为两种:1.录音设计:设置remote io unit的渲染回调,从输入硬件获得采样传入到回调函数进行渲染,从而获得录音数据;2.放音设计:设置remote io unit的输入回调.向回调函数填数据,从而向输出硬件提供数据进行放音。
本文主要是针对iOS接入硬件设备麦克风的音频录制过程进行一个简单的使用流程介绍。
使用流程概要
1.初始化Audio Unit
1).设置上下文描述信息,指定一个特定的音频单元
此代码段仅指定一个音频单元 - Remote I/O unit,所有iOS音频设备都使用componentManufacturer字段的kAudioUnitManufacturer_Apple密钥。其中componentType和componentSubType的值是根据不同的音频单元来设置:具体可参考Identifier Keys for Audio Units
对于其他设备的描述信息可参照此图进行设置2).使用音频单元API获取一个音频单元实例
AudioComponentFindNext函数的结果是对定义音频单元的动态链接库的引用,将引用传递给AudioComponentInstanceNew函数以实例化音频单元。
3).创建录制buffer,设置AudioBuffer的基础信息,分配缓冲区
此实例设置的是单声道,若需要设置立体声,将上述Channels设置为2即可。同时为buffer段分配1024byte的缓冲区。
4).设置音频流格式信息
mSampleRate为采样率:即每秒钟采样的次数
帧frame:每一次采样的数据对应一帧
声道数mChannelsPerFrame:人的两个耳朵对统一音源的感受不同带来距离定位,多声道也是为了立体感,每个声道有单独的采样数据,所以多一个声道就多一批的数据。
每一次采样单个声道的数据格式:由mFormatFlags和mBitsPerChannel确定。mBitsPerChannel:数据大小,即采样位深,越大取值范围就更大,不容易数据溢出。mFormatFlags里包含是否有符号、整数或浮点数、大端或是小端等。有符号数就有正负之分,声音也是波,振动有正负之分。这里采用s16格式,即有符号的16比特整数格式。
从层级关系来分析:每秒有SampleRate次采样,每次采样一个frame,每个frame有mChannelsPerFrame个样本,每个样本有mBitsPerChannel这么多数据。
5).设置输入的回调函数
属性kAudioOutputUnitProperty_SetInputCallback指定输入的回调,kInputBus为1,表示element1。
其中输入的回调函数recordingCallbackStruct定义如下:
使用回调函数的目的在于:构建AudioBufferList,使用AudioUnitRender实时获取录制的音频数据。AudioBufferList的内存数据需要我们自己分配,因此需要计算buffer的大小,根据传入的样本数和声道数来计算。
2.开始录制
3.停止录制
其中代码段中利用socket向服务器发送数据的相关信息在此将不再赘述。
以上描述仅用于iOS开发过程中基于Audio Unit音频录制的一个简要的使用流程,同理对于音频播放的使用流程类似。