Przede wszystkim, myślę, że faktycznie chcesz 3 AudioBufferLists, a nie jednego AudioBufferList z 3 członami AudioBuffer. AudioBuffer reprezentuje pojedynczy kanał danych, więc jeśli masz 3 stereofoniczne pliki audio, powinieneś umieścić je w 3 AudioBufferListach, z których każda ma 2 AudioBuffers, jeden bufor dla lewego kanału i jeden dla prawego. Twój kod będzie następnie przetwarzał każdą listę (i dane jej kanału) osobno, i możesz przechowywać listy w NSArray lub coś w tym stylu.
Z technicznego punktu widzenia nie ma powodu, dla którego nie można mieć pojedynczej listy buforów z 3 przeplecionymi kanałami audio (co oznacza, że zarówno prawy kanał lewy & jest przechowywany w pojedynczym buforze danych), ale jest to sprzeczne z konwencjonalnym wykorzystaniem API i będzie nieco mylące.
W każdym razie ta część CoreAudio API jest bardziej C-ish niż Objective-C-ish, więc używałbyś malloc/free zamiast alloc/release. Kod wyglądałby tak:
#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);
Powyższy kod zakłada, że dane są wczytywane jako zmiennoprzecinkowe. Jeśli nie robisz żadnego specjalnego przetwarzania plików, bardziej efektywnie jest je czytać jako SInt16 (surowe dane PCM), ponieważ iPhone nie ma jednostki FPU.
Ponadto, jeśli nie używasz list poza pojedynczą metodą, bardziej sensowne jest przydzielanie ich na stosie zamiast stosu przez deklarowanie go jako zwykłego obiektu, a nie wskaźnika. Nadal musisz malloc() faktycznego członka mData AudioBuffer, ale przynajmniej nie musisz martwić się o free() samego faktycznego AudioBufferList.
Dzięki. Więc jeśli mam przeplecione kanały audio, powinienem utworzyć 3 osobne AudioBufferListy z jednym AudioBufferem, prawda? Ale jaki jest sens używania AudioBufferLists? Jeśli dobrze zrozumiem, co mówisz, lepiej będzie dla 3 AudioBufferów (i bez AudioBufferLists) - przynajmniej w tym przypadku. –
Tak, to byłoby poprawne. Celem korzystania z AudioBufferLists jest ułatwienie zarządzania danymi wielokanałowymi, ponieważ zwykle dane z przeplotem są prawdziwym problemem przy wykonywaniu operacji DSP. O wiele lepiej jest mieć oddzielone kanały stereo z każdym kanałem we własnym buforze. Wyobraź sobie, że pracujesz z sygnałem stereo 4.1 - wtedy masz jeden bufor z 5 kanałami z przeplotem! Niezbyt przyjemnie się z tym pracuje. –
Ah, ale nie powiedziałem, żeby całkowicie nie używać AudioBufferList. Choć może wydawać się głupio przekazać pojedynczy AudioBuffer wewnątrz AudioBufferList, są one znacznie łatwiejsze do przekazania w interfejsie API CoreAudio. Poza tym sama struktura AudioBufferList nie narzuca dużego nakładu pamięci. –