覆盖AudioBufferList.mBuffers [0] .mData?

时间:2017-06-15 23:20:02

标签: c++ ios core-audio audiounit

我有一个带有渲染回调的RemoteIO音频设备。我已经有一个渲染音频的缓冲区,出于性能原因,我想避免使用memcpy

OSStatus FMixerPlatformAudioUnit::AudioRenderCallback(void* RefCon, AudioUnitRenderActionFlags* ActionFlags,
                                                          const AudioTimeStamp* TimeStamp, UInt32 BusNumber,
                                                          UInt32 NumFrames, AudioBufferList* IOData) 
{
   IOData->mBuffers[0].mData = RenderedBufferPtr;
   RefreshRenderedBufferPtr();
}

这很有效。但是,我担心通过覆盖IOData->mBuffers[0].mData,我可能会离开mData指向悬空的原始缓冲区,因此可能导致内存泄漏。在InputCallback proc中重写IOData->mBuffers[0].mData是一个问题吗?

2 个答案:

答案 0 :(得分:2)

在任何当前的Apple arm64 CPU上,每个样本的memcpy时间比采样率周期快10,000倍,因此不太可能是音频单元回调率的可测量百分比。因此,交换缓冲区的速度不会明显加快。

但是你的更大问题是,不能保证NumFrame在iOS中每个连续的音频单元回调之间保持相同,所以只是交换缓冲区指针与复制所需的确切数量的样本或音频帧不同。根据iOS设备上的其他事件,您的音频会出现故障(省电模式,通知,电话,按键点击等)。

此外,如果你没有分配它,你不知道你换出的IOData缓冲区的内存分配大小,如果音频单元采用不同的大小,这可能是内存损坏的另一个可能来源。

答案 1 :(得分:1)

我将从烦人的答案开始,只是memcpy。这种类型的优化是无法衡量的,我保证。

现在回答你的问题。

很难说没有测量,但如果我要公开一个像框架的作者那样的缓冲区列表指针,我会保留一个单独的指针指向内存以避免这种情况。

这可能与他们正在做的事情完全不同,只是为了说明如何保护您的框架免受此类漏洞的侵害。 internalRender传递clientRender指向每次渲染在堆栈上创建的局部变量的指针,因此您可以根据需要对其进行修改(只要您不尝试释放它)并且你不能让它失去它的原始指针(为简洁而传入RefoCon)。

//this is your callback
OSStatus clientRender(void* RefCon, AudioUnitRenderActionFlags* ActionFlags,
                  const AudioTimeStamp* TimeStamp, UInt32 BusNumber,
                  UInt32 NumFrames, AudioBufferList* IOData){

    IOData->mBuffers[0].mData = nil;

    return noErr;
}

//Framework calls this
OSStatus internalRender(void* RefCon, AudioUnitRenderActionFlags* ActionFlags,
                  const AudioTimeStamp* TimeStamp, UInt32 BusNumber,
                  UInt32 NumFrames, AudioBufferList* IOData){

    void *internalMemory = RefCon;
    AudioBufferList clientBufferlist;
    clientBufferlist.mBuffers[0].mData = internalMemory;


    return clientRender(RefCon,ActionFlags,TimeStamp,BusNumber,NumFrames,&clientBufferlist);
}

要告诉的唯一方法是衡量。打开Instruments应用程序并使用Leaks工具,您就可以得到答案。但实际上,正确的做法是memcpy。除非您能证明其他用途并且是预期用途,否则速度非常快。