12

3つのAudioBufferを使用してAudioBufferListを初期化(メモリを割り当てる)および解放(解放)する正しい方法は何ですか?(これを行うには複数の方法がある可能性があることを認識しています。)

これらの3つのバッファーを使用して、オーディオファイルの連続した部分を読み込み、AudioUnitsを使用して再生したいと思います。

4

2 に答える 2

17

これが私がそれをする方法です:

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;
}
于 2010-09-26T05:41:50.340 に答える
13

まず、3つのAudioBufferメンバーを持つ1つのAudioBufferListではなく、実際には3つのAudioBufferListが必要だと思います。AudioBufferはデータの単一チャネルを表すため、ステレオオーディオファイルが3つある場合は、それらを3つのAudioBufferListに配置する必要があります。各リストには、2つのAudioBufferがあり、1つは左チャネル用、もう1つは右チャネル用です。次に、コードは各リスト(およびそれぞれのチャネルデータ)を個別に処理し、リストをNSArrayなどに保存できます。

技術的には、3つのインターリーブされたオーディオチャネルを持つ単一のバッファリストを作成できない理由はありません(つまり、左右のチャネルの両方が単一のデータバッファに格納されます)が、これはAPIの従来の使用に反します。少し混乱します。

とにかく、CoreAudio APIのこの部分はObjective-C-ishよりもC-ishなので、alloc/releaseの代わりにmalloc/freeを使用します。コードは次のようになります。

#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);

上記のコードは、データを浮動小数点として読み込んでいることを前提としています。ファイルに対して特別な処理を行っていない場合、iPhoneにはFPUがないため、ファイルをSInt16(生のPCMデータ)として読み込む方が効率的です。

また、単一のメソッドの外部でリストを使用していない場合は、ポインターではなく通常のオブジェクトとして宣言することにより、ヒープではなくスタックにリストを割り当てる方が理にかなっています。AudioBufferの実際のmDataメンバーをmalloc()する必要がありますが、少なくとも実際のAudioBufferList自体をfree()することを心配する必要はありません。

于 2010-09-22T11:50:24.940 に答える