0

我们有一个读取缓冲区的音频单元,并且我在回调函数中有内存增长。它工作得很好,但我花了很多时间来解决这个泄漏。

消除问题后,我发现苹果编写的基本配置代码导致内存增长(每秒 100k)

这是我的回调,在拿完所有其他东西之后,有问题:

AudioComponentInstance audioUnit;


static OSStatus recordingCallback(void *inRefCon, 
                                  AudioUnitRenderActionFlags *ioActionFlags, 
                                  const AudioTimeStamp *inTimeStamp, 
                                  UInt32 inBusNumber, 
                                  UInt32 inNumberFrames, 
                                  AudioBufferList *ioData) 
{
    AudioBuffer buffer;
    buffer.mNumberChannels = 1;
    buffer.mDataByteSize = inNumberFrames * 2;
    buffer.mData = malloc( inNumberFrames * 2 );

    // Put buffer in a AudioBufferList
    AudioBufferList bufferList;
    bufferList.mNumberBuffers = 1;
    bufferList.mBuffers[0] = buffer;


    OSStatus status;

// problematic block   ******

    status = AudioUnitRender(audioUnit, 
                              ioActionFlags, 
                             inTimeStamp, 
                              inBusNumber, 
                             inNumberFrames, 
                              &bufferList); 


//end of problem block    ******


   free(buffer.mData); 
}

删除该块可以解决问题。

audioUnit 需要一个属性吗?我的基本问题可能是什么?谢谢。

4

2 回答 2

4

就像您在其他问题(http://stackoverflow.com/questions/10278516/memory-is-growth-in-audio-buffer-code)中所问的那样,您不应该在渲染回调中进行 malloc'ing。Malloc 外部,保存对缓冲区的引用,并通过将每个样本设置为零来清除缓冲区。2 for() 循环比 malloc() 快得多

由于内存管理的工作方式令人困惑,您(错误地)被引导相信对 AudioUnitRender() 的实际调用是导致您的问题的原因。它不是。这是上面的 malloc() 调用,再加上在进行下一次渲染回调时无法有效回收此内存的事实。因此引用被保留并且您的内存被泄露。

一般来说,任何音频编程的性能策略都是在渲染回调之外做尽可能多的工作。考虑到这个函数需要在大约 10 毫秒或更短的时间内完成,否则你会在音频流中听到 droupout。

如果您正在为桌面编程,您希望在初始化期间贪婪地 malloc() 大量内存,并保存对数据的引用以快速从中读取,这样您就不需要在渲染期间进行分配。同样,如果您需要计算任何常量或类似的东西,您希望在渲染开始之前进行。

如果你在移动设备上,策略是相似的,但你可能不希望 malloc() 如此激进。尽管如此,由于手机(或 iPad)的 CPU 功率和内存量都是有限的,因此您需要非常小心渲染回调的时间长度。越短越好。

于 2012-04-24T09:32:28.190 回答
2

如果您分配或 malloc() 您自己的音频缓冲区(应在音频单元回调之外完成),您可能想尝试在音频单元初始化或设置的某处禁用自动缓冲区分配。

// Disable buffer allocation for the recorder
UInt32 myDisable = 0;
err = AudioUnitSetProperty(audioUnit,
                           kAudioUnitProperty_ShouldAllocateBuffer,
                           kAudioUnitScope_Output,
                           kInputBus,
                           &myDisable,
                           sizeof(myDisable));
于 2012-04-24T18:46:59.617 回答