版本3 AudioUnits:internalRenderBlock

时间:2017-08-01 22:22:02

标签: audio core-audio audiounit

用于创建版本3 AudioUnit的示例代码演示了实现如何返回用于渲染处理的功能块。该块将从前一个获取样本 通过pullInputBlock在链中的AxudioUnit,并为输出缓冲区提供已处理的样本。它还必须提供一些输出缓冲区,如果链上的单元没有。以下是AudioUnit子类的代码摘录:

- (AUInternalRenderBlock)internalRenderBlock {
    /*
        Capture in locals to avoid ObjC member lookups.
    */
    // Specify captured objects are mutable.
    __block FilterDSPKernel *state = &_kernel;
    __block BufferedInputBus *input = &_inputBus;

    return Block_copy(^AUAudioUnitStatus(
             AudioUnitRenderActionFlags *actionFlags,
             const AudioTimeStamp       *timestamp,
             AVAudioFrameCount           frameCount,
             NSInteger                   outputBusNumber,
             AudioBufferList            *outputData,
             const AURenderEvent        *realtimeEventListHead,
             AURenderPullInputBlock      pullInputBlock) {
         ...
    });

如果处理在调用此块之前不需要知道frameCount,这很好,但许多应用程序确实需要在此块之前知道frameCount以便分配内存,准备处理参数等等。

解决这个问题的一种方法是累积过去的输出缓冲区,每次调用块只输出frameCount个样本,但这仅在已知最小frameCount时才有效。必须使用大于此帧数的大小初始化处理才能工作。有没有办法为frameCount指定或获取最小值或强制它为特定值?

示例代码取自:https://github.com/WildDylan/appleSample/blob/master/AudioUnitV3ExampleABasicAudioUnitExtensionandHostImplementation/FilterDemoFramework/FilterDemo.mm

1 个答案:

答案 0 :(得分:0)

在iOS下,音频单元回调必须能够处理变量frameCounts。你不能强迫它成为常数。

因此,任何需要固定大小缓冲区的处理都应在音频单元回调之外完成。您可以使用无锁循环缓冲区/ fifo或在回调中不需要内存管理的类似结构将数据传递到处理线程。

您可以通过使用AVAudioSession API设置缓冲区持续时间来建议frameCount为特定大小。但操作系统可以随意忽略这一点,具体取决于系统中的其他音频需求(省电模式,系统声音等)。根据我的经验,音频驱动程序只会增加您的建议尺寸,而不是减少它(超过一个如果重新采样不是2的幂,那么情侣样本。