Главная » iPhone » "Другая" аудиоочередь: для звука, генерируемого приложением iPhone

0

Класс AVQueue из Celestial, описанный в последнем разделе, подходит для постановки в очередь самосодержащих, заранее записанных аудиодорожек. Но сообщество разработчиков iPhone не раз озвучивало настоятельные требования добавления инструментов, которые могли бы воспроизводить аудиопотоки, генерируемые приложениями в процессе своей работы, например, играми.

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

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

В отличие от очереди Celestial, очередь Audio Toolbox строго придерживается принципа "первым прибыл — первым обслужен" (first in, first out). В то время как очередь Celestial позволяет вам переупорядочивать аудиодорожки в очереди, конвейер Audio Toolbox воспроизводит дорожки строго в том порядке, в котором они были добавлены.

Аудиоочередь Audio Toolbox работает следующим образом:

1.      Создается аудиоочередь, и задаются свойства, определяющие тип звука, который будет воспроизводиться (формат, частота дорожки и т. д.)

2.       К очереди прикрепляются звуковые буферы, которые будут содержать сами звуковые фреймы для воспроизводства. Звуковой фрейм можно рассматривать как отдельный ящик, заполненный звуком, а дорожку — как отдельную часть цифрового звука внутри фрейма.

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

Структура аудиоочереди

Поскольку платформа Audio Toolbox использует низкоуровневые интерфейсы С, то в ней нет понятия класса. Существует множество движущихся частей, вовлеченных в подготовку аудиоочереди, и чтобы сделать наши примеры более понятными, все эти используемые различные переменные будут инкапсулированы в единую, задаваемую пользователем структуру, которую мы назовем AQCallbackStruct: typedef struct AQCallbackStruct {

AudioQueueRef queue;

UInt32 frameCount;

AudioQueueBufferRef mBuffers[AUDIO_BUFFERS] ;

AudioStreamBasicDescription mDataFormat; } AQCallbackStruct;

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

П AudioQueueRef queue — указатель на объект аудиоочереди, который создаст ваша программа;

? uint32 frameCount — общее число дорожек, копируемых за одну аудио- синхронизацию. Это полностью отдается на откуп реализующему;

?   AudioQueueBuf ferRef mBuf fers — массив, содержащий общее число звуковых буферов, которые будут использоваться. Точное количество элементов будет обсуждаться в разд. "Звуковые буферы" далее в этой главе;

?   AudioStreamBasicDescription mDataFormat — информация О формате аудио, которое будет воспроизводиться.

Прежде чем аудиоочередь может быть создана, вы обязаны инициализировать экземпляры следующих переменных:

AQCallbackStruct aqc;

aqc.mDataFormat.mSampleRate = 44100.0;

aqc.mDataFormat.mFormatID = kAudioFormatLinearPCM;

aqc.mDataFormat.mFormatFlags = kLinearPCMFormatFlaglsSignedlnteger

I kAudioFormatFlaglsPacked; aqc.mDataFormat.mBytesPerPacket = 4; aqc.mDataFormat.mFramesPerPacket = 1; aqc.mDataFormat.mBytesPerFrame = 4; aqc.mDataFormat.mChanneIsPerFrame = 2; aqc.mDataFormat.mBitsPerChannel = 16; aqc.frameCount = 735;

В данном примере мы подготавливаем структуру для 16-битного (два байта на дорожку) стереозвука (два канала) с частотой дорожки 44 кГц (44 100). Наша выходная дорожка будет представлена в форме двух двухбайтных коротких целых чисел, а, следовательно, четыре полных байта на фрейм (по два байта для левого и правого каналов).

Частота дорожки и размер фрейма определяют то, как часто iPhone будет запрашивать звук. С частотой в 44 100 дорожки в секунду мы можем заставить наше приложение синхронизировать звук каждую 1/60-ую часть секунды, определив размер фрейма в 735 дорожек (44 100/60 = 735).

Формат, используемый в этом примере, — РСМ (необработанные данные), но iPhone поддерживает и другие форматы:

?   kAudioFormatLinearPCM;

?   kAudioFormatApplelMA4;

?   kAudioFormatMPEG4AAC;

?   kAudioFormatULaw;

?   kAudioFormatALaw;

?   kAudioFormatMPEGLayer3;

?   kAudioFormatAppleLossless;

?   kAudioFormatAMR.

Подготовка аудиовывода

После того как свойства аудиоочереди будут определены, можно подготовить объект новой аудиоочереди. За подготовку выходного канала и прикрепление его к очереди отвечает функция AudioQueueNewOutput. Прототип функции выглядит следующим образом:

AudioQueueNewOutput(

const AudioStreamBasicDescription *inFormat, AudioQueueOutputCa11baсk inCa11backProc, void * inUserData, CFRunLoopRef inCallbackRunLoop, CFStringRef inCallbackRunLoopMode, UInt32 inFlags, AudioQueueRef * outAQ);

Здесь:

?   inFormat — указатель на структуру, описывающую аудиоформат, который будет воспроизводиться. Мы определили эту структуру ранее как члена типа данных AudioStreamBasicDescription в рамках нашей структуры AQCallbackStruct;

?   inCallbackProc — имя функции обратного вызова, которая будет вызываться, когда буфер аудиоочереди окажется пустым и потребует данных;

?   inUserData — указатель на данные, которые разработчик при желании может передавать в функцию обратного вызова. Он будет содержать указатель на экземпляр определяемой пользователем структуры AQCallbackStruct, которая должна содержать информацию как об аудиоочереди, так и любую другую относящуюся к приложению информацию о воспроизводимых дорожках;

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

?   inFlags — не используется, зарезервировано;

?   outAO— когда функция AudioQueueNewOutput возвращает результат, данный указатель устанавливается на только что созданную аудиоочередь. Присутствие данного аргумента позволяет коду ошибки использоваться в качестве возвращаемого значения данной функции.

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

AudioQueueNewOutputUaqc.mDataFonnat, AQBufferCallback, &aqc,

NULL, kCFRunLoopCommonModes, 0, &aqc.queue);

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

Источник: Здзиарски Дж. iPhone. Разработка приложений с открытым кодом: Пер„с англ. — 2-е изд., перераб. и доп. — СПб.: БХВ-Петербург, 2009. — 368 е.: ил.

По теме:

  • Комментарии