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

标签 ios audio callback core-audio audiounit

在我的应用中,我正在渲染回调中进行音频处理(仅输入,无输出)。
这是我初始化音频的方法:

-(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;

但是我没有设法正确地创建/连接节点来完成这项工作...
谢谢你的帮助 !

最佳答案

当我想做类似的事情时,我发现了您的问题-不幸的是,没有任何解决方案:-(现在几天后,一位经理设法做到了。所以这是我的工作解决方案,适用于所有遇到相同问题的人:

  • 将Remote_IO的输入准备为STANDALONE音频单元,以记录音频。
  • 向输入中添加回调。我将其称为“麦克风回调”。
    (注意:Apple将其称为输入回调,而实际上,这只是一个NOTIFICATION回调,以告知您的应用示例可用,并且您必须显式“询问”输入单元以呈现它们...)
  • 建立AU图:转换器单位->过滤器->通用输出
    (注意:通用输出可以转换,但是过滤器不能转换。因此,如果您想将8.24格式以外的任何其他内容输入链中,则需要转换器。)
  • 向转换器单元的输入添加回调。我将其称为“流程回调”。

  • 现在的关键是,操作系统对Mic Callback的常规调用将驱动整个处理链:
  • 在麦克风回调中,准备一个缓冲区,该缓冲区与麦克风可用于渲染的输入样本的数量一样大,然后“询问” GENERIC OUTPUT(!)以渲染相同数量的样本(通过调用AudioUnitRender ) 进去。请注意,在图的末尾,您并不是在要求输入单元渲染,而是要求输出单元!
  • 通用输出将转发渲染请求,直到它到达转换器单元的输入回调,即流程回调。在此示例中,您将在输入参数中获得一个指向缓冲区的指针,您必须在其中填写请求的样本数。此时,请输入单元将样本精确渲染到此缓冲区上。

  • 中提琴,您完成了。您只需要启动/停止麦克风!
    整个过程的关键在于,始终需要一个输出单元来驱动整个渲染过程,并且由于通用输出不需要任何常规的“需要”来获取样本,因此您必须手动要求它来渲染样本。并且必须将其同步到麦克风的A / D转换器,该麦克风要以固定的时间间隔输出采样。
    从理论上讲,您可以链接输入单元和图形,但是有两个问题:
  • 麦克风输入单位算作输出单位,图中不能有两个输出单位...
  • 当将单元连接在一起时,回调之间就不能存在。如果您在其中放置一个,它将永远不会被调用...因此,您应将回调放置在链的末尾,并期望“采样可用”通知将从麦克风单元的输出传播到麦克风的输出。通用输出。但是不会。因此,您必须将过程分为麦克风输入单元和处理链。

  • 最后说明:如果要将麦克风的样本直接呈现到转换器单元中,则必须将相同的流格式(最好是远程io的规范输出格式(即16位,整数))设置为转换器单元的输入和麦克风单元的输出(即,远程io的输入范围,总线1)。

    关于ios - iOS在渲染回调处理之前添加音频效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33901569/

    相关文章:

    iOS:使用 UIBlurEffect 的过渡动画?

    ios - 带有分页 ScrollView 的自定义页面控件

    c++ - 在使用 C++ 和 qt 的实时音频服务器中,在哪里将 Wav header 添加到数据中?

    python - 使用python从给定的音频文件中检测静音索引

    c++ - SQLite 的 sqlite3_exec 和回调作为类成员

    java在内部函数中调用父级的回调函数

    objective-c - 关闭在 iphone SDK 中选择的 Popover 行上的模态视图

    ios - 如何使用 'fetchData' 方法使用 iOS 的 POST 方法对 native 进行身份验证 header 和正文

    audio - 我的世界资源包听起来不起作用

    ruby-on-rails - rails :before_create callback not working for my Model