用于创建版本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

最佳答案

在iOS下,音频单元回调必须能够处理可变的frameCounts。您不能强制它为常数。

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

您可以通过使用AVAudioSession API设置缓冲区持续时间来建议frameCount为一定大小。但是OS可以随意忽略它,具体取决于系统中的其他音频需求(省电模式,系统声音等)。以我的经验,音频驱动程序只会增加您建议的大小,而不会减小建议的大小(超过如果重新采样到2的幂,则对采样进行耦合。

关于audio - 版本3 AudioUnits:internalRenderBlock中的最小frameCount,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45448570/

10-12 14:30