Как предоставить аудио буфер для AudioQueue для воспроизведения аудио? - PullRequest
2 голосов
/ 10 мая 2011

В моем приложении я получаю аудиоданные в формате LinearPCM, которые мне нужно воспроизвести. Я следую примеру iOS SpeakHere. Однако я не могу понять, как и где мне предоставить буфер для AudioQueue.

Может ли кто-нибудь предоставить мне рабочий пример воспроизведения аудио-буфера в iOS через AudioQueue?

1 Ответ

0 голосов
/ 16 января 2012

В примере SpeakHere воспроизведение выполняется с использованием AudioQueue.

В настройке AudioQueue указана функция, которая будет вызываться, когда очереди требуется больше данных.

Вы можете видеть, что в этом методе:

void AQPlayer::SetupNewQueue() 

Вот строка, которая определяет функцию обратного вызова:

    XThrowIfError(AudioQueueNewOutput(&mDataFormat, AQPlayer::AQBufferCallback, this, 
                                    CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &mQueue), "AudioQueueNew failed");

Если вы посмотрите на AQPlayer::AQBufferCallback, вы увидите, откуда он получает данные.В этом примере данные были записаны в файл на диске.Это хорошее решение, если вы хотите сэкономить память или если есть вероятность, что аудиофайл может быть довольно большим.

В любом случае, глядя на AQPlayer::AQBufferCallback, вы увидите вызов функции AudioFileReadPackets,Вот что читает аудиопакеты из файла на диске.Он считывает их прямо в буфер, который будет использовать AudioQueue:

    OSStatus result = AudioFileReadPackets(THIS->GetAudioFileID(), false, &numBytes, inCompleteAQBuffer->mPacketDescriptions, THIS->GetCurrentPacket(), &nPackets, 
                                       inCompleteAQBuffer->mAudioData);

Этот буфер равен inCompleteAQBuffer->mAudioData.

Наконец, функция обратного вызова должна поставить в буфер буфер следующим образом:

if (nPackets > 0) {
    inCompleteAQBuffer->mAudioDataByteSize = numBytes;      
    inCompleteAQBuffer->mPacketDescriptionCount = nPackets;     
    AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, 0, NULL);
    THIS->mCurrentPacket = (THIS->GetCurrentPacket() + nPackets);
} 

Сначала обратите внимание, что он должен проверить, что у нас есть несколько пакетов для воспроизведения.Также необходимо указать, сколько байтов находится в буфере.

Затем эта строка здесь:

THIS->mCurrentPacket = (THIS->GetCurrentPacket() + nPackets);

Это отслеживает, где мы находимся в целом внаш аудио буфер.Другими словами, по мере того, как из файла копируется больше данных, нам нужно поместить mCurrentPacket вперед, чтобы следующая копия поместила данные в правильное место.

...