我想实现这样的链接 MicInput-(单声道)-> MixerNode-(立体声)->输出 其中,MixerNode的CallBack会说出单声道音频以缓冲立体声音频,并处理音频数据,例如添加“延迟”,“增益”,“声像调整”。
//
// AudioEngine.m
// mooer
//
// Created by 柳泽 on 2019/4/17.
// Copyright © 2019 柳泽. All rights reserved.
//
#import "AudioEngine.h"
@implementation AudioEngine
- (instancetype)init
{
self = [super init];
if (self) {
[self initAudioSession];
[self initAudioGraph];
[self initBuffList];
[self initAudioFormat];
[self initIoNode];
[self initMixerNode];
[self initAudioUnit];
}
return self;
}
//开启引擎
- (void)startEngine
{
AUGraphInitialize(_AudioEngine);
AUGraphStart(_AudioEngine);
}
//结束引擎
- (void)stopEngine
{
AUGraphStop(_AudioEngine);
}
//初始化音频管理
- (void)initAudioSession
{
_AudioSession = [AVAudioSession sharedInstance];
[_AudioSession setPreferredSampleRate:G_SampleRate error:nil];
[_AudioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[_AudioSession setPreferredIOBufferDuration:0.002 error:nil];
[_AudioSession setActive:YES error:nil];
}
//初始化缓冲区
- (void)initBuffList
{
}
//初始化输入和输出音频流格式
- (void)initAudioFormat
{
_AudioFormat.mSampleRate = G_SampleRate;//采样率
_AudioFormat.mFormatID = kAudioFormatLinearPCM;//PCM采样
_AudioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
_AudioFormat.mFramesPerPacket = 1;//每个数据包多少帧
_AudioFormat.mChannelsPerFrame = 2;//1单声道,2立体声
_AudioFormat.mBitsPerChannel = 16;//语音每采样点占用位数
_AudioFormat.mBytesPerFrame = _AudioFormat.mBitsPerChannel*_AudioFormat.mChannelsPerFrame/8;//每帧的bytes数
_AudioFormat.mBytesPerPacket = _AudioFormat.mBytesPerFrame*_AudioFormat.mFramesPerPacket;//每个数据包的bytes总数,每帧的bytes数*每个数据包的帧数
_AudioFormat.mReserved = 0;
}
//初始化AUGraph
- (void)initAudioGraph
{
NewAUGraph(&_AudioEngine);
}
//初始化IONode
- (void)initIoNode
{
//io节点描述
AudioComponentDescription ioACD;
ioACD.componentType = kAudioUnitType_Output;
ioACD.componentSubType = kAudioUnitSubType_RemoteIO;
ioACD.componentManufacturer = kAudioUnitManufacturer_Apple;
ioACD.componentFlags = 0;
ioACD.componentFlagsMask = 0;
//添加到AudioEngine
AUGraphAddNode(_AudioEngine, &ioACD, &_IoNode);
}
//初始化MixerNode
- (void)initMixerNode
{
//mixer节点描述
AudioComponentDescription mixerACD;
mixerACD.componentType = kAudioUnitType_Mixer;
mixerACD.componentSubType = kAudioUnitSubType_MultiChannelMixer;
mixerACD.componentManufacturer = kAudioUnitManufacturer_Apple;
mixerACD.componentFlags = 0;
mixerACD.componentFlagsMask = 0;
//添加到节点
AUGraphAddNode(_AudioEngine, &mixerACD, &_MixerNode);
}
//初始化音频单元
- (void)initAudioUnit
{
//链接mixer节点的输出到io节点的输出的输入
AUGraphConnectNodeInput(_AudioEngine,_MixerNode, G_MIXER_OUTPUT_BUS, _IoNode, G_IO_INPUT_BUS);
//开启引擎
AUGraphOpen(_AudioEngine);
//获取io节点的音频单元
AUGraphNodeInfo(_AudioEngine, _IoNode, NULL, &_IoUint);
//获取mixer节点的音频单元
AUGraphNodeInfo(_AudioEngine, _MixerNode, NULL, &_MixerUint);
//开启IO单元的MIC输入
UInt32 flag = 1;
AudioUnitSetProperty(_IoUint,kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Input,G_IO_OUTPUT_BUS,&flag,sizeof(flag));
//设置mic输入的音频流格式
AudioUnitSetProperty(_IoUint,kAudioUnitProperty_StreamFormat,kAudioUnitScope_Output, G_IO_OUTPUT_BUS,&_AudioFormat, sizeof(AudioStreamBasicDescription));
//设置mixer单元的输出格式
AudioUnitSetProperty(_MixerUint,kAudioUnitProperty_StreamFormat,kAudioUnitScope_Output, G_MIXER_OUTPUT_BUS,&_AudioFormat, sizeof(AudioStreamBasicDescription));
//配置mixer单元的输入数量
UInt32 numberOfMixBus = 1;
AudioUnitSetProperty(_MixerUint, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, G_MIXER_OUTPUT_BUS,&numberOfMixBus, sizeof(numberOfMixBus));
//配置mixer渲染回调
AURenderCallbackStruct rcbs;
rcbs.inputProc = &renderInput;
rcbs.inputProcRefCon = (__bridge void *)(self);
AUGraphSetNodeInputCallback(_AudioEngine, _MixerNode, 1, &rcbs);
//配置mixe bus输入格式
AudioUnitSetProperty(_MixerUint, kAudioUnitProperty_StreamFormat,kAudioUnitScope_Input, 1,&_AudioFormat, sizeof(AudioStreamBasicDescription));
//配置mixer的采样率
double sampleRate = 44100.00;
AudioUnitSetProperty(_MixerUint, kAudioUnitProperty_SampleRate,kAudioUnitScope_Output, 0,&sampleRate , sizeof(sampleRate));
}
static OSStatus renderInput(void *inRefCon,AudioUnitRenderActionFlags *ioActionFlags,const AudioTimeStamp *inTimeStamp,UInt32 inBusNumber, UInt32 inNumberFrames,AudioBufferList *ioData)
{
AudioEngine *THIS=(__bridge AudioEngine*)inRefCon;
AudioUnitRender(THIS->_IoUint,ioActionFlags,inTimeStamp,1,inNumberFrames,ioData);
return noErr;
}
@end
现在它们不能正常工作,我该如何实现我想要的处理方式?