C++ 正在覆盖AudioBufferList.mBuffers[0].mData?
我有一个带有渲染回调的RemoteIO音频单元。我已经有了渲染音频的缓冲区,出于性能原因,我希望避免使用C++ 正在覆盖AudioBufferList.mBuffers[0].mData?,c++,ios,core-audio,audiounit,C++,Ios,Core Audio,Audiounit,我有一个带有渲染回调的RemoteIO音频单元。我已经有了渲染音频的缓冲区,出于性能原因,我希望避免使用memcpy OSStatus FMixerPlatformAudioUnit::AudioRenderCallback(void* RefCon, AudioUnitRenderActionFlags* ActionFlags, const AudioTimeStamp* Ti
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
是否有问题?我将从恼人的答案开始,只需memcpy
。我保证,这种类型的优化将无法衡量
现在回答你的问题
很难说没有度量,但是如果我像框架的作者那样公开一个缓冲列表指针,我会保留一个单独的指向内存的指针,以避免出现这种情况
这可能与他们所做的完全不同,只是为了说明如何保护您的框架免受此类漏洞的影响internalRender
正在传递clientRender
一个指向每次渲染时在堆栈上创建的局部变量的指针,因此您可以随意对其进行篡改(只要不尝试释放),并且不能使其丢失其原始指针(为简洁起见,以REFCON的形式传递)
判断的唯一方法是测量。打开Instruments应用程序并使用Leaks工具,您将得到答案。但实际上,正确的方法是只
memcpy
。除非你能证明它是预期用途,否则它的速度非常快。我将从恼人的答案开始,只要memcpy
。我保证,这种类型的优化将无法衡量
现在回答你的问题
很难说没有度量,但是如果我像框架的作者那样公开一个缓冲列表指针,我会保留一个单独的指向内存的指针,以避免出现这种情况
这可能与他们所做的完全不同,只是为了说明如何保护您的框架免受此类漏洞的影响internalRender
正在传递clientRender
一个指向每次渲染时在堆栈上创建的局部变量的指针,因此您可以随意对其进行篡改(只要不尝试释放),并且不能使其丢失其原始指针(为简洁起见,以REFCON的形式传递)
判断的唯一方法是测量。打开Instruments应用程序并使用Leaks工具,您将得到答案。但实际上,正确的方法是只
memcpy
。它的速度非常快,除非您能证明它是预期用途。在任何当前的Apple arm64 CPU上,每个样本的memcpy时间大约比采样率周期快10000倍,因此不太可能是音频单元回调率的可测量百分比。因此,交换缓冲区的速度不会明显加快
但更大的问题是,在iOS中,NumFrames不能保证在每个连续的音频单元回调之间保持不变,因此仅交换缓冲区指针并不等同于复制精确请求的采样数或音频帧数。根据iOS设备上的其他事件(省电模式、通知、电话、按键等),您的音频将出现故障
此外,如果您没有分配它,您就不知道所交换的IOData缓冲区的内存分配大小,如果音频单元采用不同的大小,这可能是内存损坏的另一个可能原因。在任何当前的Apple arm64 CPU上,每个采样到memcpy的时间大约比采样率周期快10000倍,因此不可能是音频单元回调率的可测量百分比。因此,交换缓冲区的速度不会明显加快 但更大的问题是,在iOS中,NumFrames不能保证在每个连续的音频单元回调之间保持不变,因此仅交换缓冲区指针并不等同于复制精确请求的采样数或音频帧数。根据iOS设备上的其他事件(省电模式、通知、电话、按键等),您的音频将出现故障
此外,如果您没有分配它,您不知道所交换的IOData缓冲区的内存分配大小,如果音频单元采用不同的大小,这可能是内存损坏的另一个可能原因。这取决于对象的类型
“renderedBufferPtr”
是,而IOData
类型是。这还取决于API建立的合同。谁拥有要开始的指针?这取决于对象的类型“renderedBufferPtr”
和IOData
类型。这还取决于API建立的合同。首先,谁拥有指针?
//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);
}