AudioUnit 实现录音和播放
AudioUnit是iOS底层音频框架,相比于AudioQueue和AVAudioRecorder,能够对音频数据进行更多的控制,可以用来进行混音、均衡、格式转换、实时IO录制、回放、离线渲染等音频处理。
先看下苹果官方的原理图(此处以I/O单元为例):
image.png
谈一下我用AudioUnit 录音播放时遇到的问题
1、刚开始看不懂IO流和StreamFormat 的具体设置,经过仔细阅读明白并记录下来其中1代表Input,0代表Output ,其实也挺神似的.
这个是录音的输入部分即 麦克风--->element1
AudioUnitSetProperty(_recordAudioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
INPUT_BUS,
&flag,
sizeof(flag));
这个是播放的 输出部分 即element0---->扬声器
AudioUnitSetProperty(_recordAudioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
OUTPUT_BUS,
&flag,
sizeof(flag));
这个是录音的输出部分即 element1---> APP
AudioUnitSetProperty(_recordAudioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
OUTPUT_BUS,
&audioFormat,
sizeof(audioFormat));
这个是播放的输入部分即 APP---> element0
AudioUnitSetProperty(_recordAudioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
INPUT_BUS,
&audioFormat,
sizeof(audioFormat));
总结一下上面的代码 其实很简单
1)一个AudioUnit包含2个element即element0和element1
2)每个element包含输入和输出部分即(Input scope 和 Output scope)。
3)硬件到element的部分我们无法介入,我们能控的就element与我们APP关联的部分即 element1---> APP和APP---> element0。
4)实现录音就是主要关注element1到APP的过程,播放则是关注APP到element0的过程。
2、录音播放部分的回调
static OSStatus RecordCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
inRefCon:上下文对象 ,inTimeStamp:调用回调的时间,inBusNumber:调用回调的音频单元总数,
inNumberFrames:回调在当前调用时要求提供的音频样本帧的数量,ioData:存放音频数据缓冲区的指针
ioActionFlags:当没有音频数据处理时,该参数允许向音频单元提供提示(具体没有用过)
AudioUnitRender() 把数据渲染到指定的bufferlist 中
播放中的 ioData: 是要把数据填充到ioData中,用来播放
3、播放音频的时候明明是女声播放出来变成男声,后来改变了采样率就正常了
后续我会贴上我用audioUnit 写的录音和播放的demo地址