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