iPhone:AudioBufferList初始化和发布

iPhone:AudioBufferList初始化和发布,iphone,ios,core-audio,audiounit,Iphone,Ios,Core Audio,Audiounit,初始化(分配内存)和释放(释放)带有3个音频缓冲区的音频缓冲区列表的正确方法是什么?(我知道可能有多种方法可以做到这一点。) 我想使用这3个缓冲区将音频文件的顺序部分读入其中,并使用音频单元播放它们。首先,我认为您实际上需要3个AudioBufferList,而不是一个包含3个AudioBuffer成员的AudioBufferList。一个AudioBuffer代表一个单声道的数据,因此如果您有3个立体声音频文件,您应该将它们放在3个AudioBufferList中,每个列表有2个AudioBu

初始化(分配内存)和释放(释放)带有3个音频缓冲区的音频缓冲区列表的正确方法是什么?(我知道可能有多种方法可以做到这一点。)


我想使用这3个缓冲区将音频文件的顺序部分读入其中,并使用音频单元播放它们。

首先,我认为您实际上需要3个AudioBufferList,而不是一个包含3个AudioBuffer成员的AudioBufferList。一个AudioBuffer代表一个单声道的数据,因此如果您有3个立体声音频文件,您应该将它们放在3个AudioBufferList中,每个列表有2个AudioBuffers,一个用于左声道,一个用于右声道。然后,您的代码将分别处理每个列表(及其各自的通道数据),您可以将列表存储在NSArray或类似的东西中

从技术上讲,没有理由不能有一个包含3个交错音频通道的单一缓冲区列表(这意味着左声道和右声道都存储在一个数据缓冲区中),但这与API的常规使用背道而驰,会有点混乱

无论如何,CoreAudio API的这一部分比Objective-C-ish更接近C-ish,因此您应该使用malloc/free而不是alloc/release。代码如下所示:

#define kNumChannels 2
AudioBufferList *bufferList = (AudioBufferList*)malloc(sizeof(AudioBufferList) * kNumChannels);
bufferList->mNumberBuffers = kNumChannels; // 2 for stereo, 1 for mono
for(int i = 0; i < 2; i++) {
  int numSamples = 123456; // Number of sample frames in the buffer
  bufferList->mBuffers[i].mNumberChannels = 1;
  bufferList->mBuffers[i].mDataByteSize = numSamples * sizeof(Float32);
  bufferList->mBuffers[i].mData = (Float32*)malloc(sizeof(Float32) * numSamples);
}

// Do stuff...

for(int i = 0; i < 2; i++) {
  free(bufferList->mBuffers[i].mData);
}
free(bufferList);
#定义KNumChannel 2
AudioBufferList*bufferList=(AudioBufferList*)malloc(sizeof(AudioBufferList)*kNumChannels);
bufferList->mNumberBuffers=kNumChannels;//2个用于立体声,1个用于单声道
对于(int i=0;i<2;i++){
int numSamples=123456;//缓冲区中的采样帧数
bufferList->mBuffers[i].mNumberChannels=1;
bufferList->mBuffers[i].mDataByteSize=numSamples*sizeof(Float32);
bufferList->mBuffers[i].mData=(Float32*)malloc(sizeof(Float32)*numSamples);
}
//做些事情。。。
对于(int i=0;i<2;i++){
空闲(bufferList->mBuffers[i].mData);
}
免费(缓冲列表);
上面的代码假设您正在以浮点形式读入数据。如果您没有对文件进行任何特殊处理,那么将其作为SInt16(原始PCM数据)读入会更高效,因为iPhone没有FPU

此外,如果您没有在单个方法之外使用列表,那么在堆栈上而不是在堆上分配列表会更有意义,因为它将声明为常规对象,而不是指针。您仍然需要malloc()AudioBuffer的实际mData成员,但至少不需要担心实际AudioBufferList本身的free()。

我是这样做的:

AudioBufferList *
AllocateABL(UInt32 channelsPerFrame, UInt32 bytesPerFrame, bool interleaved, UInt32 capacityFrames)
{
    AudioBufferList *bufferList = NULL;

    UInt32 numBuffers = interleaved ? 1 : channelsPerFrame;
    UInt32 channelsPerBuffer = interleaved ? channelsPerFrame : 1;

    bufferList = static_cast<AudioBufferList *>(calloc(1, offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * numBuffers)));

    bufferList->mNumberBuffers = numBuffers;

    for(UInt32 bufferIndex = 0; bufferIndex < bufferList->mNumberBuffers; ++bufferIndex) {
        bufferList->mBuffers[bufferIndex].mData = static_cast<void *>(calloc(capacityFrames, bytesPerFrame));
        bufferList->mBuffers[bufferIndex].mDataByteSize = capacityFrames * bytesPerFrame;
        bufferList->mBuffers[bufferIndex].mNumberChannels = channelsPerBuffer;
    }

    return bufferList;
}
AudioBufferList*
可分配(UInt32信道帧、UInt32字节帧、布尔交织、UInt32容量帧)
{
AudioBufferList*bufferList=NULL;
UInt32 numBuffers=交织?1:信道帧;
UInt32 channelsPerBuffer=交织?channelsPerFrame:1;
bufferList=静态_cast(calloc(1,offsetof(AudioBufferList,mbuffer)+(sizeof(AudioBuffer)*numBuffers));
bufferList->mNumberBuffers=numBuffers;
对于(UInt32 bufferIndex=0;bufferIndexmNumberBuffers;++bufferIndex){
bufferList->mBuffers[bufferIndex].mData=static_cast(calloc(capacityFrames,bytesPerFrame));
bufferList->Mbuffer[bufferIndex].mDataByteSize=capacityFrames*bytesPerFrame;
bufferList->mbuffer[bufferIndex].mNumberChannels=channelsPerBuffer;
}
返回缓冲区列表;
}

谢谢。所以如果我有交错的音频通道,我应该创建3个单独的AudioBufferList,其中有一个AudioBuffer,对吗?但是使用音频缓冲列表有什么意义呢?如果我能正确理解你所说的,我最好有3个音频缓冲区(并且没有音频缓冲区列表)——至少在这种情况下是这样。是的,那是正确的。使用AudioBufferList的目的是使多通道数据的管理更加容易,因为通常隔行扫描的数据是在DSP上执行操作的一大难题。最好将立体声通道分开,每个通道都在自己的缓冲区中。想象一下,使用4.1立体声信号时,你会有一个带有5个交错通道的缓冲区!工作没有太多乐趣。啊,但我没说不要完全使用音频缓冲列表。尽管在AudioBufferList中传递单个AudioBuffer看起来很愚蠢,但在CoreAudio API中传递它们要容易得多。此外,AudioBufferList结构本身不会造成太多内存开销。这段代码可能会破坏内存。分配的ABL只有足够的空间容纳单个音频缓冲区,但您正在存储两个。您需要将ABL的分配大小增加一个AudioBuffer。@Nik您修复了内存抖动,但分配大小仍然不正确。看见