Технические вопросы и ответы QA1562

Аудио-очередь - оффлайновый рендеринг

Q: Есть ли какие-либо инструкции, за которыми я должен следовать при попытке представить оффлайн Аудио-очередь использования?

A: Оффлайн рендеринг с выводом аудио-очереди позволяет приложениям представлять аудио к буферу вместо непосредственно к устройству вывода. Это особенно полезно с iPhone OS, начиная с Аудио Преобразователя и Расширенного Аудиофайла, который APIs в настоящее время не делает (до iPhone OS 2.2), поддержка, распаковывающая AAC, ALAC или MP3, закодировала аудио к LPCM, если желаема последующая обработка.

Если необходимо генерировать буферы данных LPCM от AAC, ALAC или MP3 закодировали аудио, с помощью аудио-очереди, оффлайновый рендеринг является рекомендуемым подходом.

Установка

При установке выходного объекта аудио-очереди для оффлайнового рендеринга следуйте этим немногим простым инструкциям для успешного использования AudioQueueOfflineRender функция.

Выделение буферов

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

Буферная очередь, используемая для ввода (продвигающий данные в аудио-очередь), является стандартной очередью буфера воспроизведения, как описано в разделе Playback Process Руководства по программированию Audio Queue Services.

Ваш AudioQueueOutputCallback функция получит AudioQueueBufferRef к свободному буферу от этой очереди входного буфера; это - то, как входными данными снабжают к выходному объекту аудио-очереди. Распределение буферов выполняется путем вызова AudioQueueAllocateBuffer с размером буфера, вычисленным для представления некоторой суммы входных аудиоданных на основе исходного формата аудио, обычно между 16k и 64k.

  Выделение Входного буфера перечисления 1.

AudioQueueAllocateBuffer(myInfo.mQueue, bufferByteSize, &myInfo.mBuffer);

Буфер (ы) вывода является целевым буфером для оффлайновой работы рендеринга (вытаскивающий данные из аудио-очереди). Это AudioQueueBufferRef Вы передаете AudioQueueOfflineRender. Выделение того или большего количества этих буферов также сделано с помощью AudioQueueAllocateBuffer.

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

При нормальной необходимости в многократных входных буферах один буфер вывода почти всегда будет достаточен.

  Выделение Буфера вывода перечисления 2.

/*
    Allocate the output (capture) buffer keeping it at half the size of the enqueue (input) buffer.
    This ensures we don't pull data out any faster than we can push data in for render,
    and keeps the Audio Queue Offline Render happy.
*/
 
const UInt32 captureBufferByteSize = bufferByteSize / 2;
AudioQueueBufferRef captureBuffer;
AudioBufferList captureABL;
 
AudioQueueAllocateBuffer(myInfo.mQueue, captureBufferByteSize, &captureBuffer);
captureABL.mNumberBuffers = 1;
captureABL.mBuffers[0].mData = captureBuffer->mAudioData;
captureABL.mBuffers[0].mNumberChannels = captureFormat.mChannelsPerFrame;

Рендеринг вывода

Попросите нулевые кадры сразу после того, как запустится аудио-очередь

Одно из текущих требований для оффлайнового механизма рендеринга является единственным начальным вызовом AudioQueueOfflineRender выяснение 0 кадры. Это должно быть сделано, как только аудио-очередь была запущена, другими словами, сразу после вызова AudioQueueStart.

  Вызов перечисления 3 AudioQueueOfflineRender один раз для 0 кадров.

/*
    Lets start the queue - stop is called in the input buffer callback when there is no more data to read.
*/
AudioQueueStart(myInfo.mQueue, NULL);
 
AudioTimeStamp theTimeStamp;
theTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
theTimeStamp.mSampleTime = 0;
 
/*
    Important - We need to call this once asking for 0 frames!
*/
AudioQueueOfflineRender(myInfo.mQueue, &theTimeStamp, captureBuffer, 0);
 
...

Ставьте в очередь входные буферы.

Один раз AudioQueueOfflineRender был вызван первоначально, можно тогда ставить в очередь один или несколько входных буферов с относительно большими количествами кадров, например 16K или больше. Это обычно делается путем прямого вызова Вашего AudioQueueOutputCallback функция.

Перечисление 4  Первоначально ставит в очередь входные буферы

/*
    We need to enqueue a buffer after the queue has started.
*/
AQEnqueueBufferCallback(&myInfo, myInfo.mQueue, myInfo.mBuffer);
 
...

Рендеринг оффлайн

Можно теперь вызвать AudioQueueOfflineRender запрос относительно небольшое количество выходных кадров, обычно между 4k и 8k.

Вне размера нажатий входного буфера и размера выходных получений по запросу, имеет значение, сколько входных буферов сохранено в очереди. В частности необходимо заботиться для не получения по запросу (путем вызова AudioQueueOfflineRender) поскольку больше кадров, чем Вы продвинуло через AudioQueueEnqueueBuffer функция. Можно также хотеть отслеживать то, сколько кадров Вы ожидаете декодировать так, чтобы Вы знали, когда прекратить вызывать AudioQueueOfflineRender.

Правило состоит в том в любой момент времени при продвижении числа N кадров Вы не должны вытягивать для больше, чем числа N кадров.

  Вывод Listing 5 Rendering.

/* Start Rendering Offline */
while (true) {
    UInt32 reqFrames = captureBufferByteSize / captureFormat.mBytesPerFrame;
 
    AudioQueueOfflineRender(myInfo.mQueue, &theTimeStamp, captureBuffer, reqFrames);
 
    captureABL.mBuffers[0].mData = captureBuffer->mAudioData;
    captureABL.mBuffers[0].mDataByteSize = captureBuffer->mAudioDataByteSize;
 
    UInt32 writeFrames = captureABL.mBuffers[0].mDataByteSize / captureFormat.mBytesPerFrame;
 
    /* We may not get any frames so check this here - are we done? */
    if (writeFrames == 0) break;
 
    /* Do Something With The Returned Audio Data - Maybe Write it to a file, ok let's do that. */
    ExtAudioFileWrite(captureFile, writeFrames, &captureABL);
 
    /* This flag ensures that the Audio Queue was flushed by a call to AudioQueueFlush in the
       AudioQueueOutputCallback just before the call to AudioQueueStop and ensures we get all the data out.
       If the queue has been flushed we are done. */
    if (myInfo.mFlushed) break;
 
    theTimeStamp.mSampleTime += writeFrames;
}

Сводка

Установка для аудио-очереди, оффлайновый рендеринг очень подобен тому, как Вы обычно устанавливали бы выходной объект аудио-очереди для воспроизведения. Помните распределение буферов и удостоверьтесь, что вызвали AudioQueueOfflineRender выяснение 0 кадры сразу после вызова к AudioQueueStart. Никогда не вытягивайте для большего количества данных, чем Вы продвинули в очередь и вызов AudioQueueFlush прежде AudioQueueStop чтобы гарантировать Вам выводят все данные.

main:
    AudioQueueNewOutput
    AudioQueueSetProperty(kAudioQueueProperty_MagicCookie) // as required
    AudioQueueSetProperty(kAudioQueueProperty_ChannelLayout) // as required
    AudioQueueAllocateBuffer    // input buffer(s)
    AudioQueueSetOfflineRenderFormat
    AudioQueueAllocateBuffer    // output buffer
    AudioQueueStart
    AudioQueueOfflineRender(0) // mandatory call asking for 0 frames
    myAQEnqueueBufferCallback  // enqueue some input buffers
 
    loop:
        AudioQueueOfflineRender(n)
        ...
 
AudioQueueOutputCallback function:
    myAQEnqueueBufferCallback

Посмотрите aqrender.cpp файл для дальнейшей ссылки.

Ссылка

Руководство по программированию служб аудио-очереди

Downloadables



История версии документа


ДатаПримечания
02.01.2013

Передовая статья

13.02.2009

Новый документ, описывающий, как установить Аудио-очередь для Оффлайнового Рендеринга