我设置了一个带有渲染回调的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进程中重写IOData->mBuffers[0].mData有问题吗?
发布于 2017-06-17 00:54:20
在任何当前的苹果arm64处理器上,每个样本的memcpy时间大约是采样率周期的10,000倍,因此不太可能是音频单元回调率的可测量百分比。因此,交换缓冲区的速度不会有明显的提高。
但更大的问题是,在iOS中,不能保证每个连续的音频单元回调之间的NumFrames保持不变,因此仅仅交换缓冲区指针并不等同于复制所请求的确切数量的样本或音频帧。您的音频可能会因iOS设备上的其他事件(省电模式、通知、电话呼叫、按键单击等)而出现故障。
此外,如果您没有分配它,您就不知道您换出的IOData缓冲区的内存分配大小,如果音频单元采用不同的大小,这可能是内存损坏的另一个可能来源。
发布于 2017-06-16 08:38:23
我将从恼人的答案开始,就是memcpy。我保证,这种类型的优化是不可能衡量的。
现在回答你的问题。
很难说没有测量,但如果我像框架的作者那样公开一个bufferlist指针,我会保留一个指向内存的单独指针,以避免出现这种情况。
这可能与他们正在做的事情完全不同,只是为了说明如何保护您的框架不受此类漏洞的影响。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。它的速度非常快,除非你能证明不是这样的,而且是你的目标用途。
https://stackoverflow.com/questions/44578439
复制相似问题