iPhone: запуск и выпуск AudioBufferList - PullRequest
10 голосов
/ 22 сентября 2010

Каковы правильные способы инициализации (выделения памяти) и освобождения (освобождения) AudioBufferList с 3 AudioBuffers? (Я знаю, что может быть несколько способов сделать это.)

Я бы хотел использовать эти 3 буфера для считывания в них последовательных частей аудиофайла и воспроизведения их с использованием аудиоустройств.

Ответы [ 2 ]

16 голосов
/ 26 сентября 2010

Вот как я это делаю:

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;
}
12 голосов
/ 22 сентября 2010

Прежде всего, я думаю, что вы на самом деле хотите 3 AudioBufferList, а не один AudioBufferList с 3 членами AudioBuffer.AudioBuffer представляет один канал данных, поэтому, если у вас есть 3 стереофонических аудиофайла, вы должны поместить их в 3 AudioBufferLists, каждый список имеет 2 AudioBuffers, один буфер для левого канала и один для правого.Ваш код будет затем обрабатывать каждый список (и соответствующие ему данные канала) отдельно, и вы можете хранить списки в NSArray или что-то в этом роде.

Технически, нет причин, по которым у вас не может быть одного списка буферов.с 3 чередующимися аудиоканалами (это означает, что левый и правый каналы хранятся в одном буфере данных), но это идет вразрез с обычным использованием API и немного сбивает с толку.

В любом случае, эточасть CoreAudio API более C-ish, чем Objective-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);

Приведенный выше код предполагает, что вы читаете данные как плавающую точку.Если вы не выполняете никакой специальной обработки файлов, более эффективно считывать их как SInt16 (необработанные данные PCM), поскольку в iPhone нет FPU.

Кроме того, если вы не 'Если использовать списки вне одного метода, то имеет смысл размещать их в стеке, а не в куче, объявляя их как обычный объект, а не как указатель.Вам все еще нужно выполнить malloc () фактического члена mData AudioBuffer, но, по крайней мере, вам не нужно беспокоиться о free () с самим фактическим AudioBufferList.

...