如何使用AUGraph来实现这样的链接

时间:2019-04-17 03:49:29

标签: ios audiounit augraph

我想实现这样的链接 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

现在它们不能正常工作,我该如何实现我想要的处理方式?

0 个答案:

没有答案