iOS是否在渲染回调处理之前添加音频效果?

iOS是否在渲染回调处理之前添加音频效果?,ios,audio,callback,core-audio,audiounit,Ios,Audio,Callback,Core Audio,Audiounit,在我的应用程序中,我在渲染回调中进行音频处理(仅输入,无输出)。 以下是我初始化音频的方式: -(void) initAudio { OSStatus status; NewAUGraph(&graph); AudioComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_Remote

在我的应用程序中,我在渲染回调中进行音频处理(仅输入,无输出)。 以下是我初始化音频的方式:

-(void) initAudio {

OSStatus status;

NewAUGraph(&graph);

AudioComponentDescription desc;
desc.componentType          = kAudioUnitType_Output;
desc.componentSubType       = kAudioUnitSubType_RemoteIO;
desc.componentFlags         = 0;
desc.componentFlagsMask     = 0;
desc.componentManufacturer  = kAudioUnitManufacturer_Apple;

AUNode ioNode;

status = AUGraphAddNode(graph, &desc, &ioNode);
checkStatus(status, "At adding node");

AUGraphOpen(graph);

AUGraphNodeInfo(graph, ioNode, NULL, &audioUnit);

//Enable IO for recording
UInt32 enableInput = 1;
status = AudioUnitSetProperty(audioUnit,
                              kAudioOutputUnitProperty_EnableIO,
                              kAudioUnitScope_Input,
                              kInputBus,
                              &enableInput,
                              sizeof(enableInput));
checkStatus(status, "At setting property for input");

//Disable playback
UInt32 enableOutput = 0;
status = AudioUnitSetProperty(audioUnit,
                              kAudioOutputUnitProperty_EnableIO,
                              kAudioUnitScope_Output,
                              kOutputBus,
                              &enableOutput,
                              sizeof(enableOutput));
checkStatus(status, "At setting property for input");

// ASBD
AudioStreamBasicDescription audioFormatIn;
audioFormatIn.mSampleRate         = SampleRate;
audioFormatIn.mFormatID           = kAudioFormatLinearPCM;
audioFormatIn.mFormatFlags        = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormatIn.mFramesPerPacket    = 1;
audioFormatIn.mChannelsPerFrame   = 1;
audioFormatIn.mBitsPerChannel     = 16;//sizeof(AudioSampleType) * 8;
audioFormatIn.mBytesPerPacket     = 2 * audioFormatIn.mChannelsPerFrame;
audioFormatIn.mBytesPerFrame      = 2 * audioFormatIn.mChannelsPerFrame;

//Apply format
status = AudioUnitSetProperty(audioUnit,
                              kAudioUnitProperty_StreamFormat,
                              kAudioUnitScope_Output,
                              kInputBus,
                              &audioFormatIn,
                              sizeof(audioFormatIn));
checkStatus(status,"At setting property for AudioStreamBasicDescription for input");


//Set up input callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = recordingCallback;
callbackStruct.inputProcRefCon = (__bridge void *)self;

status = AudioUnitSetProperty(audioUnit,
                              kAudioOutputUnitProperty_SetInputCallback,
                              kAudioUnitScope_Global,
                              kInputBus,
                              &callbackStruct,
                              sizeof(callbackStruct));
checkStatus(status,"At setting property for recording callback");

// Disable buffer allocation for the recorder
UInt32  flag = 0;
status = AudioUnitSetProperty(audioUnit,
                              kAudioUnitProperty_ShouldAllocateBuffer,
                              kAudioUnitScope_Output,
                              kInputBus,
                              &flag,
                              sizeof(flag));
checkStatus(status, "At set property should allocate buffer");

// Allocate own buffers
tempBuffer.mNumberChannels  = 1;
tempBuffer.mDataByteSize    = 1024 * 2;
tempBuffer.mData            = malloc( 1024 * 2 );

status = AUGraphInitialize(graph);
checkStatus(status,"At AUGraph Initalize");
}
现在,我想在渲染回调中处理输入音频之前,向其添加高通滤波器或带通滤波器。因此,我想我应该添加如下内容:

desc.componentType          = kAudioUnitType_Effect;
desc.componentSubType       = kAudioUnitSubType_BandPassFilter;
desc.componentFlags         = 0;
desc.componentFlagsMask     = 0;
desc.componentManufacturer  = kAudioUnitManufacturer_Apple;
但是我没有正确创建/连接节点以使其正常工作。。。
谢谢你的帮助

当我想做一件类似的事情时,我发现了你的问题——不幸的是,没有任何解决方案:-(几天后,a成功地解决了这个问题。因此,这是我的工作解决方案,适用于所有与同一问题作斗争的人:

  • 将远程IO的输入作为独立的音频单元进行准备,以便录制音频

  • 在输入中添加回调。我将其称为“麦克风回调”

    (注意:苹果称之为输入回调,而事实上,这只是一个通知回调,告诉你的应用程序样本可用,你必须“要求”输入单元显式地呈现它们…)

  • 建立AU图:转换器单元->过滤器->通用输出

    (注意:通用输出可以转换,但过滤器不能。因此,如果您希望在链中输入8.24格式以外的任何内容,则需要转换器。)

  • 将回调添加到转换器单元的输入。我将其称为“进程回调”

  • 现在关键的一点是,操作系统对麦克风回调的定期调用将驱动整个处理链:

  • 在麦克风回调中,准备一个缓冲区,该缓冲区与麦克风可渲染的输入样本数一样大,并“要求”通用输出(!)向其中渲染相同数量的样本(通过调用AudioUnitRender)。请注意,您不是要求输入单元渲染,而是要求输出单元在图形末尾渲染

  • 通用输出将转发呈现请求,直到它到达转换器单元的输入回调,即进程回调。在这个过程中,您在输入参数中得到一个指向缓冲区的指针,您必须在该缓冲区中填写请求的样本数。此时,请输入单元将样本准确呈现到该缓冲区上。

  • 维奥拉,你完成了。你只需启动/停止麦克风单元

    整个过程中的关键是,始终需要一个输出单元来驱动整个渲染过程,由于通用输出没有任何常规的“需要”来获取样本,因此您必须手动请求它渲染样本。这必须与麦克风的A/D转换器同步,该转换器希望以固定的时间间隔输出样本

    理论上,您可以将输入单位和图形链接起来,但存在两个问题:

  • 麦克风输入单元计为输出单元,图形中不能有两个输出单元

  • 当to单元连接在一起时,回调之间就不能存在。如果您将回调放在那里,它将永远不会被调用…因此您将回调放在链的末尾,并期望“样本可用”通知将从麦克风单元的输出传播到通用输出的输出。但是不会。因此,您必须将进程分为麦克风输入单元和处理链


  • 最后一点注意:如果您想直接将麦克风的样本渲染到转换器单元,则必须将相同的流格式(最好是远程io的标准输出格式(即16位整数)设置到转换器单元的输入和麦克风单元的输出(即远程io的输入范围,总线1).

    您的渲染链在没有带通的情况下工作吗?@Dave我以前使用经典音频单元初始化,但我开始切换到AUGraph。即使我不确定是否正确,我上面的代码似乎也能工作。