Audio Unit是iOS音视频最底层的接口
支持混合、均衡、格式转换和实时输入/输出用于录制、播放、离线渲染和实时对话如VoIP(互联网协议语音)等,
它的优点是功能强大,延迟低; 而缺点是学习成本高,难度大。今天重点介绍一下Audio Unit的基本用法。
1、设置AVAudioSession
NSError *error = nil;
AVAudioSession* session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:&error];
[session setActive:YES error:nil];
2、创建描述音频单元
AudioComponentDescription desc;
desc.componentType =kAudioUnitType_Output;
desc.componentSubType =kAudioUnitSubType_VoiceProcessingIO;
//kAudioUnitSubType_RemoteIO不带回音消除功能,,kAudioUnitSubType_VoiceProcessingIO带回音消除功能
desc.componentFlags =0;
desc.componentFlagsMask =0;
desc.componentManufacturer =kAudioUnitManufacturer_Apple;
3、关联查找音频单元
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
4、获取音频单元实例
status = AudioComponentInstanceNew(inputComponent, &audioUnit);
5、启用录制功能
UInt32 flag = 1; //falg为1表示开启录制功能,为0则不开启
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
kInputBus,
&flag,
sizeof(flag));
6、启用播放功能
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
kOutputBus,
&flag,
sizeof(flag));
7、创建音频流描述
AudioStreamBasicDescription audioFormat; //声音是44100.00采样率,16bit,单声道,pcm的
audioFormat.mSampleRate = 44100.00;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 1;
audioFormat.mBitsPerChannel = 16;
audioFormat.mBytesPerPacket = 2;
audioFormat.mBytesPerFrame = 2;
8、设置录制和播放的音频流描述
8.1、设置录制的音频流描述
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
kInputBus,
&audioFormat,
sizeof(audioFormat));
8.2 、设置 播放的音频流描述
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
kOutputBus,
&audioFormat,
sizeof(audioFormat));
9、设置回调
9.1 设置录制的回调
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = recordingCallback;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
kInputBus,
&callbackStruct,
sizeof(callbackStruct));
9.2、设置播放的回调
callbackStruct.inputProc = playbackCallback;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
kOutputBus,
&callbackStruct,
sizeof(callbackStruct));
10、回调方法
10.1 录制的回调方法
` static OSStatus recordingCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
AudioBufferList *bufferList;
OSStatus status = AudioUnitRender([(shockmanViewController *)inRefCon audioUnit],
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
bufferList);
return noErr;
}`
10.2 、播放的回调方法
`static OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
return noErr;
}`
11、初始化AudioUnit
status = AudioUnitInitialize(_audioUnit);
12、开启 AudioUnit
OSStatus status = AudioOutputUnitStart(audioUnit);
13、关闭Audio unit
OSStatus status = AudioOutputUnitStop(audioUnit);
14、销毁Audio unit
AudioComponentInstanceDispose(audioUnit);
15、设置回声消除
///0 开启,1 关闭
`-(void)openOrCloseEchoCancellation:(UInt32)newEchoCancellationStatus
{
UInt32 echoCancellation;
UInt32 size = sizeof(echoCancellation);
AudioUnitGetProperty(_audioUnit,
kAUVoiceIOProperty_BypassVoiceProcessing,
kAudioUnitScope_Global,
0,
&echoCancellation,
&size);
if (newEchoCancellationStatus == echoCancellation)
{
return;
}
AudioUnitSetProperty(_audioUnit,
kAUVoiceIOProperty_BypassVoiceProcessing,
kAudioUnitScope_Global,
0,
&newEchoCancellationStatus,
sizeof(newEchoCancellationStatus));
}
`