Запись аудио

Когда Вы записываете использование Audio Queue Services, место назначения может быть примерно чем-либо — дисковый файл, сетевое соединение, объект в памяти, и т.д. В этой главе описываются наиболее распространенный сценарий: основная запись к дисковому файлу.

Для добавления функциональности записи к приложению Вы обычно выполняете следующие шаги:

  1. Определите пользовательскую структуру для управления состоянием, форматом и информацией о пути.

  2. Запишите функцию обратного вызова аудио-очереди для выполнения фактической записи.

  3. Дополнительно запишите код для определения хорошего размера для буферов аудио-очереди. Запишите код для работы с волшебными cookie, если Вы будете записывать в формате, использующем cookie.

  4. Заполните поля пользовательской структуры. Это включает указание потока данных, который аудио-очередь отправляет в файл, который это записывает в, а также путь к тому файлу.

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

  6. Скажите аудио-очереди начинать записывать.

  7. Когда сделано, скажите аудио-очереди останавливаться и затем избавляться от него. Аудио-очередь избавляется от своих буферов.

Остаток от этой главы описывает каждый из этих шагов подробно.

Определите пользовательскую структуру для управления состоянием

Первый шаг в разработке использования решения для записи Audio Queue Services должен определить пользовательскую структуру. Вы будете использовать эту структуру для управления форматом аудио и информацией о состоянии аудио-очереди. Перечисление 2-1 иллюстрирует такую структуру:

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

static const int kNumberBuffers = 3;                            // 1
struct AQRecorderState {
    AudioStreamBasicDescription  mDataFormat;                   // 2
    AudioQueueRef                mQueue;                        // 3
    AudioQueueBufferRef          mBuffers[kNumberBuffers];      // 4
    AudioFileID                  mAudioFile;                    // 5
    UInt32                       bufferByteSize;                // 6
    SInt64                       mCurrentPacket;                // 7
    bool                         mIsRunning;                    // 8
};

Вот описание полей в этой структуре:

  1. Определяет номер буферов аудио-очереди для использования.

  2. AudioStreamBasicDescription структура (от CoreAudioTypes.h) представление аудиоданных форматирует для записи в диск. Этот формат привыкает аудио-очередью, указанной в mQueue поле.

    mDataFormat поле заполняется первоначально кодом в Вашей программе, как описано в Установленном Формат аудио для Записи. Это - хорошая практика, чтобы тогда обновить значение этого поля путем запросов аудио-очереди kAudioQueueProperty_StreamDescription свойство, как описано в Получении Полного Формата аудио от Аудио-очереди. На Mac OS X v10.5, используйте kAudioConverterCurrentInputStreamDescription свойство вместо этого.

    Для получения дополнительной информации на AudioStreamBasicDescription структура, посмотрите Ссылку Типов данных Core Audio.

  3. Аудио-очередь записи создается Вашим приложением.

  4. Массив, содержащий указатели на буферы аудио-очереди, которыми управляет аудио-очередь.

  5. Представление объекта аудиофайла файла, в который Ваша программа записывает аудиоданные.

  6. Размер, в байтах, для каждого буфера аудио-очереди. Это значение вычисляется в этих примерах в DeriveBufferSize функция, после того, как аудио-очередь создается и прежде чем это будет запущено. Посмотрите Запись Функция для Получения Размера буфера Аудио-очереди Записи.

  7. Пакетный индекс для первого пакета, который будет записан из текущего буфера аудио-очереди.

  8. Булево значение, указывающее, работает ли аудио-очередь.

Запишите обратный вызов аудио-очереди записи

Затем, запишите функцию обратного вызова аудио-очереди записи. Этот обратный вызов делает два главное:

Этот раздел показывает объявление обратного вызова в качестве примера, затем описывает эти две задачи отдельно, и наконец представляет весь обратный вызов записи. Для иллюстрации роли обратного вызова аудио-очереди записи можно вернуться к рисунку 1-3.

Объявление обратного вызова аудио-очереди записи

Перечисление 2-2 показывает объявление в качестве примера для функции обратного вызова аудио-очереди записи, объявленной как AudioQueueInputCallback в AudioQueue.h заголовочный файл:

Перечисление 2-2  объявление обратного вызова аудио-очереди записи

static void HandleInputBuffer (
    void                                *aqData,             // 1
    AudioQueueRef                       inAQ,                // 2
    AudioQueueBufferRef                 inBuffer,            // 3
    const AudioTimeStamp                *inStartTime,        // 4
    UInt32                              inNumPackets,        // 5
    const AudioStreamPacketDescription  *inPacketDesc        // 6
)

Вот то, как работает этот код:

  1. Как правило, aqData пользовательская структура, содержащая данные состояния для аудио-очереди, как описано в Определяют Пользовательскую Структуру для Управления состоянием.

  2. Аудио-очередь, которой принадлежит этот обратный вызов.

  3. Буфер аудио-очереди, содержащий входящие аудиоданные для записи.

  4. Демонстрационное время первой выборки в буфере аудио-очереди (не необходимый для простой записи).

  5. Число описаний пакета в inPacketDesc параметре. Значение 0 указывает данные CBR.

  6. Для сжатых форматов аудиоданных, требующих описаний пакета, описаний пакета, произведенных кодером для пакетов в буфере.

Запись буфера аудио-очереди к диску

Первая задача обратного вызова аудио-очереди записи состоит в том, чтобы записать буфер аудио-очереди в диск. Этот буфер является тем, который аудио-очередь обратного вызова только что закончила заполнять новыми аудиоданными от устройства ввода данных. Обратный вызов использует AudioFileWritePackets функция от AudioFile.h заголовочный файл, как показано в Перечислении 2-3.

Перечисление 2-3  Пишущий аудио-очередь буферизует к диску

AudioFileWritePackets (                     // 1
    pAqData->mAudioFile,                    // 2
    false,                                  // 3
    inBuffer->mAudioDataByteSize,           // 4
    inPacketDesc,                           // 5
    pAqData->mCurrentPacket,                // 6
    &inNumPackets,                          // 7
    inBuffer->mAudioData                    // 8
);

Вот то, как работает этот код:

  1. AudioFileWritePackets функция, объявленная в AudioFile.h заголовочный файл, пишет содержание буфера к файлу аудиоданных.

  2. Объект аудиофайла (типа AudioFileID) это представляет аудиофайл для записи в. pAqData переменная является указателем на структуру данных, описанную в Перечислении 2-1.

  3. Использует значение false указать, что функция не должна кэшировать данные при записи.

  4. Число байтов записанных аудиоданных. inBuffer переменная представляет буфер аудио-очереди, врученный обратному вызову аудио-очередью.

  5. Массив описаний пакета для аудиоданных. Значение NULL указывает, что никакие описания пакета не требуются (такой что касается аудиоданных CBR).

  6. Пакетный индекс для первого пакета, который будет записан.

  7. На вводе, числе пакетов для записи. На выводе, числе пакетов, фактически записанных.

  8. Новые аудиоданные для записи в аудиофайл.

Постановка в очередь буфера аудио-очереди

Теперь, когда аудиоданные от буфера аудио-очереди были записаны в аудиофайл, обратный вызов ставит в очередь буфер, как показано в Перечислении 2-4. Один раз назад в буферной очереди, буфер в гармонии и готов принять более входящие аудиоданные.

Перечисление 2-4  , Ставящее в очередь буфер аудио-очереди после записи в диск

AudioQueueEnqueueBuffer (                    // 1
    pAqData->mQueue,                         // 2
    inBuffer,                                // 3
    0,                                       // 4
    NULL                                     // 5
);

Вот то, как работает этот код:

  1. AudioQueueEnqueueBuffer функция добавляет буфер аудио-очереди к буферной очереди аудио-очереди.

  2. Аудио-очередь для добавления определяемой аудио-очереди буферизует к. pAqData переменная является указателем на структуру данных, описанную в Перечислении 2-1.

  3. Буфер аудио-очереди для постановки в очередь.

  4. Число описаний пакета в данных буфера аудио-очереди. Набор к 0 потому что этот параметр не использован для записи.

  5. Массив описаний пакета, описывающих данные буфера аудио-очереди. Набор к NULL потому что этот параметр не использован для записи.

Полный обратный вызов аудио-очереди записи

Перечисление 2-5 показывает базовую версию полного обратного вызова аудио-очереди записи. Как с остальной частью примеров кода в этом документе, это перечисление исключает обработку ошибок.

Перечисление 2-5  функция обратного вызова аудио-очереди записи

 
static void HandleInputBuffer (
    void                                 *aqData,
    AudioQueueRef                        inAQ,
    AudioQueueBufferRef                  inBuffer,
    const AudioTimeStamp                 *inStartTime,
    UInt32                               inNumPackets,
    const AudioStreamPacketDescription   *inPacketDesc
) {
    AQRecorderState *pAqData = (AQRecorderState *) aqData;               // 1
 
    if (inNumPackets == 0 &&                                             // 2
          pAqData->mDataFormat.mBytesPerPacket != 0)
       inNumPackets =
           inBuffer->mAudioDataByteSize / pAqData->mDataFormat.mBytesPerPacket;
 
    if (AudioFileWritePackets (                                          // 3
            pAqData->mAudioFile,
            false,
            inBuffer->mAudioDataByteSize,
            inPacketDesc,
            pAqData->mCurrentPacket,
            &inNumPackets,
            inBuffer->mAudioData
        ) == noErr) {
            pAqData->mCurrentPacket += inNumPackets;                     // 4
    }
   if (pAqData->mIsRunning == 0)                                         // 5
      return;
 
    AudioQueueEnqueueBuffer (                                            // 6
        pAqData->mQueue,
        inBuffer,
        0,
        NULL
    );
}

Вот то, как работает этот код:

  1. Пользовательская структура, предоставленная аудио-очереди, возражает после инстанцирования, включая объект аудиофайла представление аудиофайла для записи в, а также множество данных состояния. Посмотрите Определяют Пользовательскую Структуру для Управления состоянием.

  2. Если буфер аудио-очереди содержит данные CBR, вычислите число пакетов в буфере. Это число равняется общим байтам данных в буфере, разделенном на (постоянное) число байтов на пакет. Для данных VBR аудио-очередь предоставляет число пакетов в буфере, когда это вызывает обратный вызов.

  3. Пишет содержание буфера к файлу аудиоданных. Для подробного описания посмотрите Запись Буфера Аудио-очереди к Диску.

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

  5. Если аудио-очередь остановилась, возвратиться.

  6. Ставит в очередь буфер аудио-очереди, содержание которого было просто записано в аудиофайл. Для подробного описания посмотрите Постановку в очередь Буфера Аудио-очереди.

Запишите функцию для получения размера буфера аудио-очереди записи

Audio Queue Services ожидает, что Ваше приложение укажет, что размер для аудио-очереди буферизует Вас использование. Перечисление 2-6 показывает один способ сделать это. Это получает размер буфера, достаточно большой для содержания данной продолжительности аудиоданных.

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

Перечисление 2-6  , Получающее размер буфера аудио-очереди записи

void DeriveBufferSize (
    AudioQueueRef                audioQueue,                  // 1
    AudioStreamBasicDescription  &ASBDescription,             // 2
    Float64                      seconds,                     // 3
    UInt32                       *outBufferSize               // 4
) {
    static const int maxBufferSize = 0x50000;                 // 5
 
    int maxPacketSize = ASBDescription.mBytesPerPacket;       // 6
    if (maxPacketSize == 0) {                                 // 7
        UInt32 maxVBRPacketSize = sizeof(maxPacketSize);
        AudioQueueGetProperty (
                audioQueue,
                kAudioQueueProperty_MaximumOutputPacketSize,
                // in Mac OS X v10.5, instead use
                //   kAudioConverterPropertyMaximumOutputPacketSize
                &maxPacketSize,
                &maxVBRPacketSize
        );
    }
 
    Float64 numBytesForTime =
        ASBDescription.mSampleRate * maxPacketSize * seconds; // 8
    *outBufferSize =
    UInt32 (numBytesForTime < maxBufferSize ?
        numBytesForTime : maxBufferSize);                     // 9
}

Вот то, как работает этот код:

  1. Аудио-очередь, которой принадлежат буферы, размер которых Вы хотите указать.

  2. AudioStreamBasicDescription структура для аудио-очереди.

  3. Размер Вы указываете для каждого буфера аудио-очереди, с точки зрения секунд аудио.

  4. На выводе, размере для каждого буфера аудио-очереди, с точки зрения байтов.

  5. Верхняя граница для размера буфера аудио-очереди, в байтах. В этом примере верхняя граница установлена в 320 КБ. Это соответствует приблизительно пяти секундам стерео, аудио на 24 бита в частоте дискретизации 96 кГц.

  6. Для аудиоданных CBR получите (постоянный) размер пакета от AudioStreamBasicDescription структура. Используйте это значение в качестве максимального размера пакета.

    Это присвоение имеет побочный эффект определения, если аудиоданными, которые будут зарегистрированы, является CBR или VBR. Если это - VBR, аудио-очередь AudioStreamBasicDescription структура перечисляет значение байтов на пакет как 0.

  7. Для аудиоданных VBR запросите аудио-очередь для получения предполагаемого максимального размера пакета.

  8. Получите размер буфера в байтах.

  9. Ограничьте размер буфера, в случае необходимости, к ранее верхняя граница набора.

Установите волшебный Cookie для аудиофайла

Некоторые сжатые форматы аудио, такие как MPEG 4 AAC, используют структуры, содержащие аудио метаданные. Эти структуры вызывают волшебными cookie. При записи к такому использованию формата Audio Queue Services необходимо получить волшебный cookie от аудио-очереди и добавить его к аудиофайлу, прежде чем Вы начнете записывать.

Перечисление 2-7 показывает, как получить волшебный cookie из аудио-очереди и применить его к аудиофайлу. Ваш код вызвал бы функцию как это перед записью, и с другой стороны после записи — некоторые кодеки обновляют волшебные cookie-данные, когда остановилась запись.

Перечисление 2-7  , Устанавливающее волшебный cookie для аудиофайла

OSStatus SetMagicCookieForFile (
    AudioQueueRef inQueue,                                      // 1
    AudioFileID   inFile                                        // 2
) {
    OSStatus result = noErr;                                    // 3
    UInt32 cookieSize;                                          // 4
 
    if (
            AudioQueueGetPropertySize (                         // 5
                inQueue,
                kAudioQueueProperty_MagicCookie,
                &cookieSize
            ) == noErr
    ) {
        char* magicCookie =
            (char *) malloc (cookieSize);                       // 6
        if (
                AudioQueueGetProperty (                         // 7
                    inQueue,
                    kAudioQueueProperty_MagicCookie,
                    magicCookie,
                    &cookieSize
                ) == noErr
        )
            result =    AudioFileSetProperty (                  // 8
                            inFile,
                            kAudioFilePropertyMagicCookieData,
                            cookieSize,
                            magicCookie
                        );
        free (magicCookie);                                     // 9
    }
    return result;                                              // 10
}

Вот то, как работает этот код:

  1. Аудио-очередь Вы используете для записи.

  2. Аудиофайл Вы записываете в.

  3. Переменная результата, указывающая успешность или неуспешность этой функции.

  4. Переменная для содержания волшебного размера cookie-данных.

  5. Получает размер данных волшебного cookie от аудио-очереди и хранит его в cookieSize переменная.

  6. Выделяет массив байтов для содержания волшебной информации о cookie.

  7. Получает волшебный cookie путем запросов аудио-очереди kAudioQueueProperty_MagicCookie свойство.

  8. Устанавливает волшебный cookie для аудиофайла, в который Вы записываете. AudioFileSetProperty функция объявляется в AudioFile.h заголовочный файл.

  9. Освобождает память для временной переменной cookie.

  10. Возвращает успешность или неуспешность этой функции.

Установите формат аудио для записи

В этом разделе описывается Вы устанавливаете формат аудиоданных для аудио-очереди. Аудио-очередь использует этот формат для записи к файлу.

Для установки формата аудиоданных Вы указываете:

Перечисление 2-8 иллюстрирует установку формата аудио для записи, с помощью фиксированного выбора для каждого атрибута. В производственном коде Вы обычно позволяли бы пользователю указывать некоторых или все аспекты формата аудио. С любым подходом цель состоит в том, чтобы заполниться mDataFormat поле AQRecorderState пользовательская структура, описанная в, Определяет Пользовательскую Структуру для Управления состоянием.

Перечисление 2-8  , Указывающее формат аудиоданных аудио-очереди

AQRecorderState aqData;                                       // 1
 
aqData.mDataFormat.mFormatID         = kAudioFormatLinearPCM; // 2
aqData.mDataFormat.mSampleRate       = 44100.0;               // 3
aqData.mDataFormat.mChannelsPerFrame = 2;                     // 4
aqData.mDataFormat.mBitsPerChannel   = 16;                    // 5
aqData.mDataFormat.mBytesPerPacket   =                        // 6
   aqData.mDataFormat.mBytesPerFrame =
      aqData.mDataFormat.mChannelsPerFrame * sizeof (SInt16);
aqData.mDataFormat.mFramesPerPacket  = 1;                     // 7
 
AudioFileTypeID fileType             = kAudioFileAIFFType;    // 8
aqData.mDataFormat.mFormatFlags =                             // 9
    kLinearPCMFormatFlagIsBigEndian
    | kLinearPCMFormatFlagIsSignedInteger
    | kLinearPCMFormatFlagIsPacked;

Вот то, как работает этот код:

  1. Создает экземпляр AQRecorderState пользовательская структура. Структура mDataFormat поле содержит AudioStreamBasicDescription структура. Значения начинаются mDataFormat поле обеспечивает первоначальное определение формата аудио для аудио-очереди — который является также форматом аудио для файла, в который Вы записываете. В Перечислении 2-10 Вы получаете более полную спецификацию формата аудио, который Core Audio предоставляет Вам на основе типа формата и типа файла.

  2. Определяет тип формата аудиоданных как линейный PCM. Посмотрите Ссылку Типов данных Core Audio для полного списка доступных форматов данных.

  3. Определяет частоту дискретизации как 44,1 кГц.

  4. Определяет число каналов как 2.

  5. Определяет битовую глубину на канал как 16.

  6. Определяет число байтов на пакет и число байтов на кадр, к 4 (т.е. 2 раза каналов 2 байта за выборку).

  7. Определяет число кадров на пакет как 1.

  8. Определяет тип файла как AIFF. Посмотрите, что аудиофайл вводит перечисление AudioFile.h заголовочный файл для полного списка доступных типов файлов. Можно указать любой тип файла, для которого существует установленный кодек, как описано в Использовании Форматы Аудиоданных и Кодеки.

  9. Устанавливает флаги формата, необходимые для указанного типа файла.

Создайте аудио-очередь записи

Теперь, с обратным вызовом записи и установленным форматом аудиоданных, Вы создаете и конфигурируете аудио-очередь для записи.

Создание аудио-очереди записи

Перечисление 2-9 иллюстрирует, как создать аудио-очередь записи. Заметьте что AudioQueueNewInput функционируйте использует обратный вызов, пользовательскую структуру и формат аудиоданных, которые были сконфигурированы на предыдущих шагах.

Перечисление 2-9  , Создающее аудио-очередь записи

AudioQueueNewInput (                              // 1
    &aqData.mDataFormat,                          // 2
    HandleInputBuffer,                            // 3
    &aqData,                                      // 4
    NULL,                                         // 5
    kCFRunLoopCommonModes,                        // 6
    0,                                            // 7
    &aqData.mQueue                                // 8
);

Вот то, как работает этот код:

  1. AudioQueueNewInput функция создает новую аудио-очередь записи.

  2. Аудиоданные форматируют для использования для записи. Посмотрите Установленный Формат аудио для Записи.

  3. Функция обратного вызова для использования с аудио-очередью записи. Посмотрите Запись Обратный вызов Аудио-очереди Записи.

  4. Пользовательская структура данных для аудио-очереди записи. Посмотрите Определяют Пользовательскую Структуру для Управления состоянием.

  5. Цикл выполнения, на который будет вызван обратный вызов. Использовать NULL указать поведение по умолчанию, в котором обратный вызов будет вызван на поток, внутренний к аудио-очереди. Это - типичное использование — оно позволяет аудио-очереди записывать, в то время как поток пользовательского интерфейса Вашего приложения ожидает ввода данных пользователем для остановки записи.

  6. Режимы цикла выполнения, в которых может быть вызван обратный вызов. Обычно, используйте kCFRunLoopCommonModes постоянный здесь.

  7. Зарезервированный. Должен быть 0.

  8. На выводе, недавно выделенной аудио-очереди записи.

Получение полного формата аудио от аудио-очереди

Когда аудио-очередь появилась (см. Создание Аудио-очереди Записи), это, возможно, заполнило AudioStreamBasicDescription структура более полностью, чем Вы имеет, особенно для сжатых форматов. Для получения полного описания формата вызовите AudioQueueGetProperty функционируйте как показано в Перечислении 2-10. Вы используете полный формат аудио при создании аудиофайла для записи в (см., Создают Аудиофайл).

Перечисление 2-10  , Получающее формат аудио от аудио-очереди

UInt32 dataFormatSize = sizeof (aqData.mDataFormat);       // 1
 
AudioQueueGetProperty (                                    // 2
    aqData.mQueue,                                         // 3
    kAudioQueueProperty_StreamDescription,                 // 4
    // in Mac OS X, instead use
    //    kAudioConverterCurrentInputStreamDescription
    &aqData.mDataFormat,                                   // 5
    &dataFormatSize                                        // 6
);

Вот то, как работает этот код:

  1. Заставляет ожидаемый размер значения свойства использовать при запросах аудио-очереди о ее формате аудиоданных.

  2. AudioQueueGetProperty функция получает значение для указанного свойства в аудио-очереди.

  3. Аудио-очередь для получения формата аудиоданных из.

  4. Свойство ID для получения значения формата данных аудио-очереди.

  5. На выводе, полном формате аудиоданных, в форме AudioStreamBasicDescription структура, полученная из аудио-очереди.

  6. На вводе, ожидаемом размере AudioStreamBasicDescription структура. На выводе, фактическом размере. Ваше приложение записи не должно использовать это значение.

Создайте аудиофайл

С аудио-очередью, создаваемой и сконфигурированной, Вы создаете аудиофайл, что Вы запишете аудиоданные в, как показано в Перечислении 2-11. Аудиофайл использует формат данных и спецификации формата файла, ранее сохраненные в пользовательской структуре аудио-очереди.

Перечисление 2-11  , Создающее аудиофайл для записи

CFURLRef audioFileURL =
    CFURLCreateFromFileSystemRepresentation (            // 1
        NULL,                                            // 2
        (const UInt8 *) filePath,                        // 3
        strlen (filePath),                               // 4
        false                                            // 5
    );
 
AudioFileCreateWithURL (                                 // 6
    audioFileURL,                                        // 7
    fileType,                                            // 8
    &aqData.mDataFormat,                                 // 9
    kAudioFileFlags_EraseFile,                           // 10
    &aqData.mAudioFile                                   // 11
);

Вот то, как работает этот код:

  1. CFURLCreateFromFileSystemRepresentation функция, объявленная в CFURL.h заголовочный файл, создает объект CFURL представление файла для записи в.

  2. Использовать NULL (или kCFAllocatorDefault) использовать текущее средство выделения памяти по умолчанию.

  3. Путь файловой системы Вы хотите преобразовать в объект CFURL. В производственном коде Вы обычно получали бы значение для filePath от пользователя.

  4. Число байтов по пути файловой системы.

  5. Значение false указывает это filePath представляет файл, не каталог.

  6. AudioFileCreateWithURL функция, от AudioFile.h заголовочный файл, создает новый аудиофайл или инициализирует существующий файл.

  7. URL, в котором можно создать новый аудиофайл, или инициализировать в случае существующего файла. URL был получен из CFURLCreateFromFileSystemRepresentation на шаге 1.

  8. Тип файла для нового файла. В примере кода в этой главе это было ранее установлено в AIFF посредством kAudioFileAIFFType постоянный тип файла. Посмотрите Установленный Формат аудио для Записи.

  9. Формат данных аудио, которое будет зарегистрировано в файл, указал как AudioStreamBasicDescription структура. В примере кода для этой главы это было также установлено в Установленном Формат аудио для Записи.

  10. Стирает файл, в случае, что уже существует файл.

  11. На выводе, объект аудиофайла (типа AudioFileID) представление аудиофайла для записи в.

Установите размер буфера аудио-очереди

Перед подготовкой ряда буферов аудио-очереди, которые Вы будете использовать при записи, Вы используете DeriveBufferSize функция, которую Вы записали ранее (см. Запись Функция для Получения Размера буфера Аудио-очереди Записи). Вы присваиваете этот размер аудио-очереди записи, которую Вы используете. Перечисление 2-12 иллюстрирует это:

Перечисление 2-12  , Устанавливающее размер буфера аудио-очереди

DeriveBufferSize (                               // 1
    aqData.mQueue,                               // 2
    aqData.mDataFormat,                          // 3
    0.5,                                         // 4
    &aqData.bufferByteSize                       // 5
);

Вот то, как работает этот код:

  1. DeriveBufferSize функция, описанная в Записи Функция для Получения Размера буфера Аудио-очереди Записи, устанавливает надлежащий размер буфера аудио-очереди.

  2. Аудио-очередь, для которой Вы устанавливаете размер буфера.

  3. Аудиоданные форматируют для файла, который Вы записываете. Посмотрите Установленный Формат аудио для Записи.

  4. Число секунд аудио, которое должен содержать каждый буфер аудио-очереди. Один наполовину второй, как установлено здесь, обычно хороший выбор.

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

Подготовьте ряд буферов аудио-очереди

Вы теперь спрашиваете аудио-очередь, которую Вы создали (в, Создают Аудио-очередь Записи) подготавливать ряд буферов аудио-очереди. Перечисление 2-13 демонстрирует, как сделать это.

Перечисление 2-13  , Подготавливающее ряд буферов аудио-очереди

for (int i = 0; i < kNumberBuffers; ++i) {           // 1
    AudioQueueAllocateBuffer (                       // 2
        aqData.mQueue,                               // 3
        aqData.bufferByteSize,                       // 4
        &aqData.mBuffers[i]                          // 5
    );
 
    AudioQueueEnqueueBuffer (                        // 6
        aqData.mQueue,                               // 7
        aqData.mBuffers[i],                          // 8
        0,                                           // 9
        NULL                                         // 10
    );
}

Вот то, как работает этот код:

  1. Выполняет итерации, чтобы выделить и ставить в очередь каждый буфер аудио-очереди.

  2. AudioQueueAllocateBuffer функция просит, чтобы аудио-очередь выделила буфер аудио-очереди.

  3. Аудио-очередь, выполняющая выделение и этому будет принадлежать буфер.

  4. Размер, в байтах, для нового выделяемого буфера аудио-очереди. Посмотрите Запись Функция для Получения Размера буфера Аудио-очереди Записи.

  5. На выводе, недавно выделенном буфере аудио-очереди. Указатель на буфер помещается в пользовательскую структуру, которую Вы используете с аудио-очередью.

  6. AudioQueueEnqueueBuffer функция добавляет буфер аудио-очереди до конца буферной очереди.

  7. Аудио-очередь, к буферной очереди которой Вы добавляете буфер.

  8. Буфер аудио-очереди Вы ставите в очередь.

  9. Этот параметр не использован при постановке в очередь буфера для записи.

  10. Этот параметр не использован при постановке в очередь буфера для записи.

Рекордное аудио

Весь предыдущий код привел к очень простому процессу записи, как показано в Перечислении 2-14.

Перечисление 2-14  , Записывающее аудио

aqData.mCurrentPacket = 0;                           // 1
aqData.mIsRunning = true;                            // 2
 
AudioQueueStart (                                    // 3
    aqData.mQueue,                                   // 4
    NULL                                             // 5
);
// Wait, on user interface thread, until user stops the recording
AudioQueueStop (                                     // 6
    aqData.mQueue,                                   // 7
    true                                             // 8
);
 
aqData.mIsRunning = false;                           // 9

Вот то, как работает этот код:

  1. Инициализирует пакетный индекс к 0 начать записывать в начале аудиофайла.

  2. Устанавливает флаг в пользовательской структуре, чтобы указать, что работает аудио-очередь. Этот флаг используется обратным вызовом аудио-очереди записи.

  3. AudioQueueStart функция запускает аудио-очередь на ее собственном потоке.

  4. Аудио-очередь для запуска.

  5. Использование NULL указать, что аудио-очередь должна начать записывать сразу.

  6. AudioQueueStop функционируйте останавливает и сбрасывает аудио-очередь записи.

  7. Аудио-очередь для остановки.

  8. Использовать true использовать синхронную остановку. Посмотрите Управление Аудио-очередью и состояние для объяснения синхронной и асинхронной остановки.

  9. Устанавливает флаг в пользовательской структуре, чтобы указать, что не работает аудио-очередь.

Очистите после записи

Когда Вы закончены с записью, избавляетесь от аудио-очереди и закрываете аудиофайл. Перечисление 2-15 иллюстрирует эти шаги.

Перечисление 2-15  , Очищающее после записи

AudioQueueDispose (                                 // 1
    aqData.mQueue,                                  // 2
    true                                            // 3
);
 
AudioFileClose (aqData.mAudioFile);                 // 4

Вот то, как работает этот код:

  1. AudioQueueDispose функция избавляется от аудио-очереди и всех ее ресурсов, включая ее буферы.

  2. Аудио-очередь Вы хотите избавиться.

  3. Использовать true избавляться от аудио-очереди синхронно (т.е. сразу).

  4. Закрывает аудиофайл, использовавшийся для записи. AudioFileClose функция объявляется в AudioFile.h заголовочный файл.