Построение приложений аудиоустройства

Теперь, когда Вы понимаете, как хостинг аудиоустройства работает, как объяснено в Основных принципах Хостинга Аудиоустройства, Вы хорошо подготовлены создать часть аудиоустройства своего приложения. Основные шаги выбирают шаблон разработки и затем пишут код для реализации того образца.

Запустите путем выбора шаблона разработки

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

Установка потоковых форматов правильно важна для установления потока аудиоданных. Большинство этих образцов полагается на автоматическое распространение форматов аудиопотока от источника до места назначения, в соответствии с соединением аудиоустройства. Используйте в своих интересах это распространение, когда Вы можете, потому что оно сокращает объем кода, чтобы записать и поддержать. Одновременно, убедитесь, что Вы понимаете, где это требуется для Вас установить потоковые форматы. Например, необходимо установить полный потоковый формат на вводе и выводе iPod модуль EQ. Обратитесь к таблицам использования в Использовании Определенных Аудиоустройств для всех потоковых требований формата аудиоустройства iOS.

В большинстве случаев шаблоны разработки в этой главе используют график обработки аудиоданных (типа AUGraph). Вы могли реализовать любой из этих образцов, не используя график, но с помощью каждого упрощает код и поддерживает динамическое реконфигурирование, как описано в Обработке аудиоданных, Графики Управляют Аудиоустройствами.

I/O Проходит

Образец передачи I/O отправляет входящее аудио непосредственно в выходные аппаратные средства без опции работать с аудиоданными. Несмотря на то, что это не имеет большого количества практического значения, создавание приложения хостинга аудиоустройства на основе этого образца является хорошим способом проверить и цементировать Ваше понимание понятий аудиоустройства. Рисунок 2-1 иллюстрирует этот образец.

Рисунок 2-1  Одновременный I/O проходит

Как Вы видите в числе, аппаратные средства аудиовхода налагают свой потоковый формат на обращающуюся исходящим образом сторону Удаленного входного элемента модуля I/O. Вы, в свою очередь, укажите формат, который Вы хотите использовать на внутрь обращающейся стороне этого элемента. Аудиоустройство выполняет преобразование формата по мере необходимости. Избегать ненужного преобразования частоты дискретизации, убеждаться использовать аудио аппаратную частоту дискретизации при определении потокового формата.

Входной элемент отключен по умолчанию, так убедиться включить его; иначе, аудио не может течь.

Образец, показанный на рисунке 2-1, использует в своих интересах соединение аудиоустройства между двумя Удаленными элементами I/O. В частности Вы не устанавливаете потоковый формат на входном объеме выходного элемента аудиоустройства. Соединение распространяет формат, который Вы указали для входного элемента.

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

Используя этот образец, Вы не должны конфигурировать буферы аудиоданных.

I/O Без Функции обратного вызова Рендеринга

Добавление одного или более других аудиоустройств между Удаленными элементами модуля I/O позволяет Вам создать более интересное приложение. Например, Вы могли использовать Многоканальный модуль Микшера, чтобы расположить входящее аудио микрофона в стереополе или обеспечить выходной регулятор громкости. В этом шаблоне разработки нет все еще никакой функции обратного вызова в игре, как показано на рисунке 2-2. Это упрощает образец, но ограничивает его утилиту. Без функции обратного вызова рендеринга у Вас нет средних значений для управления аудио непосредственно.

Рисунок 2-2  Одновременный I/O без функции обратного вызова рендеринга

В этом образце Вы конфигурируете оба элемента Удаленного модуля I/O, как Вы делаете в образце передачи. Для установки Многоканального модуля Микшера необходимо установить частоту дискретизации потокового формата на выводе микшера, как обозначено на рисунке 2-2.

Входной потоковый формат микшера установлен автоматически распространением от вывода Удаленного входного элемента модуля I/O посредством соединения аудиоустройства. Точно так же потоковый формат для входного объема Удаленного выходного элемента модуля I/O установлен соединением аудиоустройства благодаря распространению от вывода модуля микшера.

В любом экземпляре этого образца — действительно, каждый раз, когда Вы используете другие аудиоустройства в дополнение к модулю I/O — необходимо установить kAudioUnitProperty_MaximumFramesPerSlice свойство, как описано в Ссылке Свойств Аудиоустройства.

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

I/O с Функцией обратного вызова Рендеринга

Путем размещения функции обратного вызова рендеринга между элементами ввода и вывода Удаленного модуля I/O можно управлять входящим аудио, прежде чем это достигнет выходных аппаратных средств. В очень простом случае Вы могли использовать функцию обратного вызова рендеринга для корректировки выходного объема. Однако Вы могли добавить тремоло, кольцевую модуляцию, эхо или другие эффекты. Путем использования преобразований Фурье и функций свертки, доступных в Ускорять платформе (см., Ускоряют Ссылку Платформы), возможности бесконечны. Этот образец изображен на рисунке 2-3.

Рисунок 2-3  Одновременный I/O с функцией обратного вызова рендеринга

Как Вы видите в числе, этот образец использует оба элемента Удаленного модуля I/O, как в предыдущих образцах в этой главе. Присоедините свою функцию обратного вызова рендеринга к входному объему выходного элемента. Когда тому элементу нужен другой набор значений аудиосэмпла, это вызывает Ваш обратный вызов. Ваш обратный вызов, в свою очередь, получает новые выборки путем вызова функции обратного вызова рендеринга Удаленного входного элемента модуля I/O.

Так же, как для других образцов I/O, необходимо явно включить ввод на Удаленном модуле I/O, потому что введенный отключен по умолчанию. И, что касается других образцов I/O, Вы не должны конфигурировать буферы аудиоданных.

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

Только для вывода с функцией обратного вызова рендеринга

Выберите этот образец для музыкальных игр и синтезаторов — приложения, для которых Вы генерируете звуки и нуждаетесь в максимальной скорости отклика. В его самом простом этот образец включает одну функцию обратного вызова рендеринга, подключенную непосредственно к входному объему Удаленного выходного элемента модуля I/O, как показано на рисунке 2-4.

Рисунок 2-4  , Только для вывода с функцией обратного вызова рендеринга

Можно использовать этот тот же образец для создания приложения с более сложной аудио структурой. Например, Вы могли бы хотеть генерировать несколько звуков, смешать их вместе, и затем играть их через выходные аппаратные средства устройства. Рисунок 2-5 показывает такой случай. Здесь, образец использует график обработки аудиоданных и два дополнительных аудиоустройства, Многоканальный Микшер и iPod EQ.

Рисунок 2-5  более сложный пример только для вывода с функцией обратного вызова рендеринга

В числе заметьте, что iPod EQ требует, чтобы Вы установили свой полный потоковый формат на обоих вводах и выводах. Многоканальному Микшеру, с другой стороны, нужна только корректная частота дискретизации, которая будет установлена на ее выводе. Полный потоковый формат тогда распространен соединением аудиоустройства от вывода микшера до входного объема Удаленного выходного элемента модуля I/O. Эти подробные данные использования и другие специфические особенности использования различных аудиоустройств iOS, описаны в Использовании Определенных Аудиоустройств.

Для каждого из Многоканальных вводов модуля Микшера, как Вы видите на рисунке 2-5, установлен полный потоковый формат. Для ввода 0, Вы устанавливаете его явно. Для ввода 1, формат распространен соединением аудиоустройства от вывода iPod модуль EQ. В целом необходимо составить потребности потокового формата каждого аудиоустройства индивидуально.

Другое аудиоустройство, размещающее шаблоны разработки

Существует два других основных шаблона разработки для хостинга аудиоустройств. Чтобы записать или проанализировать аудио, создайте приложение только для ввода с функцией обратного вызова рендеринга. Функция обратного вызова вызывается Вашим приложением, и это поочередно вызывает метод рендеринга Удаленного входного элемента модуля I/O. Однако в большинстве случаев лучший выбор для приложения как это состоит в том, чтобы использовать входной объект аудио-очереди (типа AudioQueueRef инстанцированное использование AudioQueueNewInput функция), как объяснено в Руководстве по программированию Audio Queue Services. Используя аудио-очередь объект обеспечивает гораздо больше гибкости, потому что ее функция обратного вызова рендеринга не находится на потоке в реальном времени.

Для выполнения оффлайновой обработки аудиоданных используйте Универсальное Устройство вывода. В отличие от Удаленного модуля I/O, это аудиоустройство не соединяется с аудио аппаратными средствами устройства. При использовании его для отправки аудио в приложение, это зависит от приложения для вызова его метода рендеринга.

Построение Вашего приложения

Независимо от того, который шаблон разработки Вы выбираете, шаги для построения приложения хостинга аудиоустройства являются в основном тем же:

  1. Сконфигурируйте свой аудио сеанс.

  2. Укажите аудиоустройства.

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

  4. Сконфигурируйте аудиоустройства.

  5. Соедините узлы аудиоустройства.

  6. Обеспечьте пользовательский интерфейс.

  7. Инициализируйте и затем запустите график обработки аудиоданных.

Сконфигурируйте свой аудио сеанс

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

self.graphSampleRate = 44100.0; // Hertz

Затем, используйте аудио объект сеанса запросить, чтобы система использовала Вашу предпочтительную частоту дискретизации в качестве частоты дискретизации оборудования устройства, как показано в Перечислении 2-1. Намерение здесь состоит в том, чтобы избежать преобразования частоты дискретизации между аппаратными средствами и Вашим приложением. Это максимизирует производительность ЦП и качество звука, и минимизирует разрядку батареи.

Перечисление 2-1  , Конфигурирующее аудио сеанс

NSError *audioSessionError = nil;
AVAudioSession *mySession = [AVAudioSession sharedInstance];     // 1
[mySession setPreferredHardwareSampleRate: graphSampleRate       // 2
                                    error: &audioSessionError];
[mySession setCategory: AVAudioSessionCategoryPlayAndRecord      // 3
                                    error: &audioSessionError];
[mySession setActive: YES                                        // 4
               error: &audioSessionError];
self.graphSampleRate = [mySession currentHardwareSampleRate];    // 5

Предыдущие строки делают следующее:

  1. Получите ссылку на одноэлементный объект сеанса аудио для Вашего приложения.

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

  3. Запросите аудио категорию сеанса, которую Вы хотите. “Игра и рекордная” категория, указанная здесь, поддерживают аудиовход и вывод.

  4. Активация запроса Вашего аудио сеанса.

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

Существует одна другая характеристика оборудования, которую можно хотеть сконфигурировать: аудио аппаратные средства I/O буферизуют продолжительность. Продолжительность по умолчанию составляет приблизительно 23 мс в частоте дискретизации на 44,1 кГц, эквивалентной размеру части 1 024 выборок. Если задержка I/O критически важна в Вашем приложении, можно запросить меньшую продолжительность, вниз приблизительно к 0,005 мс (эквивалентный 256 выборкам), как показано здесь:

self.ioBufferDuration = 0.005;
[mySession setPreferredIOBufferDuration: ioBufferDuration
                                  error: &audioSessionError];

Для полного объяснения того, как сконфигурировать и использовать аудио объект сеанса, см. Аудио Руководство по программированию Сеанса.

Укажите аудиоустройства, которые Вы хотите

Во время выполнения, после того, как работал Ваш аудио код конфигурации сеанса, Ваше приложение еще не получило аудиоустройства. Вы указываете каждого, что Вы хотите при помощи AudioComponentDescription структура. Посмотрите Идентификаторы Использования, чтобы Указать и Получить Аудиоустройства для того, как сделать это. Ключи идентификатора для каждого аудиоустройства iOS перечислены в Ключах Идентификатора для Аудиоустройств.

Спецификаторы аудиоустройства в руке, Вы тогда создаете график обработки аудиоданных согласно образцу, который Вы выбрали.

Создайте график обработки аудиоданных

На этом шаге Вы создаете скелет одного из шаблонов разработки, объясненных в первой части этой главы. В частности, Вы:

  1. Инстанцируйте AUGraph непрозрачный тип. Экземпляр представляет график обработки аудиоданных.

  2. Инстанцируйте один или больше AUNode непрозрачные типы, каждый из которых представляет одно аудиоустройство в графике.

  3. Добавьте узлы к графику.

  4. Откройте график и инстанцируйте аудиоустройств.

  5. Получите ссылки на аудиоустройства.

Перечисление 2-2 показывает, как выполнить эти шаги для графика, содержащего Удаленный модуль I/O и Многоканальный модуль Микшера. Это предполагает, что Вы уже определили AudioComponentDescription структура для каждого из этих аудиоустройств.

Перечисление 2-2  , Создающее график обработки аудиоданных

AUGraph processingGraph;
NewAUGraph (&processingGraph);
 
AUNode ioNode;
AUNode mixerNode;
 
AUGraphAddNode (processingGraph, &ioUnitDesc, &ioNode);
AUGraphAddNode (processingGraph, &mixerDesc, &mixerNode);

AUGraphAddNode вызовы функции используют спецификаторы аудиоустройства ioUnitDesc и mixerDesc. В этой точке график инстанцируют и владеет узлами, которые Вы будете использовать в своем приложении. Чтобы открыть график и инстанцировать аудиоустройств, вызвать AUGraphOpen:

AUGraphOpen (processingGraph);

Затем получите ссылки на экземпляры аудиоустройства посредством AUGraphNodeInfo функция, как показано здесь:

AudioUnit ioUnit;
AudioUnit mixerUnit;
 
AUGraphNodeInfo (processingGraph, ioNode, NULL, &ioUnit);
AUGraphNodeInfo (processingGraph, mixerNode, NULL, &mixerUnit);

ioUnit и mixerUnit переменные теперь содержат ссылки на экземпляры аудиоустройства в графике, позволяя Вам сконфигурировать и затем соединить аудиоустройства.

Сконфигурируйте аудиоустройства

Каждое аудиоустройство iOS требует своей собственной конфигурации, как описано в Использовании Определенных Аудиоустройств. Однако некоторые конфигурации достаточно распространены, что все разработчики аудио iOS должны быть знакомы с ними.

Удаленный модуль I/O, по умолчанию, вывел, включил и отключенный ввод. Если Ваше приложение выполняет одновременный I/O или использует ввод только, необходимо реконфигурировать модуль I/O соответственно. Для получения дополнительной информации посмотрите kAudioOutputUnitProperty_EnableIO свойство в Ссылке Свойств Аудиоустройства.

Всем аудиоустройствам iOS, за исключением Удаленного I/O и Обработки речи модули I/O, нужен их kAudioUnitProperty_MaximumFramesPerSlice свойство сконфигурировано. Это свойство гарантирует, что аудиоустройство подготовлено произвести достаточное число кадров аудиоданных в ответ на вызов рендеринга. Для получения дополнительной информации посмотрите kAudioUnitProperty_MaximumFramesPerSlice в ссылке свойств аудиоустройства.

Все аудиоустройства нуждаются в своем формате аудиопотока, определенном на вводе, выводят, или оба. Для объяснения форматов аудиопотока посмотрите, что Форматы Аудиопотока Включают Поток данных. Для определенных потоковых требований формата различных аудиоустройств iOS посмотрите Используя Определенные Аудиоустройства.

Запишите и присоедините функции обратного вызова рендеринга

Для шаблонов разработки, использующих функции обратного вызова рендеринга, необходимо записать те функции и затем присоединить их в корректных точках. Представьте Аудио Канала Функций обратного вызова к Аудиоустройствам, описывает то, что делают эти обратные вызовы и объясняет, как они работают. Для примеров рабочих обратных вызовов просмотрите различные проекты примера кода аудиоустройства в Ссылочной Библиотеке iOS включая Аудио Микшер (MixerHost) и aurioTouch и SynthHost.

Когда аудио не течет, можно сразу присоединить обратный вызов рендеринга при помощи аудиоустройства API, как показано в Перечислении 2-3.

Перечисление 2-3  , Присоединяющее обратный вызов рендеринга сразу

AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc        = &renderCallback;
callbackStruct.inputProcRefCon  = soundStructArray;
 
AudioUnitSetProperty (
    myIOUnit,
    kAudioUnitProperty_SetRenderCallback,
    kAudioUnitScope_Input,
    0,                 // output element
    &callbackStruct,
    sizeof (callbackStruct)
);

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

Перечисление 2-4  , Присоединяющее обратный вызов рендеринга ориентированным на многопотоковое исполнение способом

AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc        = &renderCallback;
callbackStruct.inputProcRefCon  = soundStructArray;
 
AUGraphSetNodeInputCallback (
    processingGraph,
    myIONode,
    0,                 // output element
    &callbackStruct
);
// ... some time later
Boolean graphUpdated;
AUGraphUpdate (processingGraph, &graphUpdated);

Соедините узлы аудиоустройства

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

Перечисление 2-5 показывает, как соединить вывод узла микшера к вводу выходного элемента модуля I/O с помощью графика обработки аудиоданных API.

Перечисление 2-5  , Соединяющееся два узла аудиоустройства с помощью графика обработки аудиоданных API

AudioUnitElement mixerUnitOutputBus  = 0;
AudioUnitElement ioUnitOutputElement = 0;
 
AUGraphConnectNodeInput (
    processingGraph,
    mixerNode,           // source node
    mixerUnitOutputBus,  // source node bus
    iONode,              // destination node
    ioUnitOutputElement  // desinatation node element
);

Можно, альтернативно, установить и повредить соединения между аудиоустройствами непосредственно при помощи механизма свойства аудиоустройства. Для этого используйте AudioUnitSetProperty функция вместе с kAudioUnitProperty_MakeConnection свойство, как показано в Перечислении 2-6. Этот подход требует, чтобы Вы определили AudioUnitConnection структура для каждого соединения для служения в качестве его значения свойства.

Перечисление 2-6  , Подключающее два аудиоустройства непосредственно

AudioUnitElement mixerUnitOutputBus  = 0;
AudioUnitElement ioUnitOutputElement = 0;
 
AudioUnitConnection mixerOutToIoUnitIn;
mixerOutToIoUnitIn.sourceAudioUnit    = mixerUnitInstance;
mixerOutToIoUnitIn.sourceOutputNumber = mixerUnitOutputBus;
mixerOutToIoUnitIn.destInputNumber    = ioUnitOutputElement;
 
AudioUnitSetProperty (
    ioUnitInstance,                     // connection destination
    kAudioUnitProperty_MakeConnection,  // property key
    kAudioUnitScope_Input,              // destination scope
    ioUnitOutputElement,                // destination element
    &mixerOutToIoUnitIn,                // connection definition
    sizeof (mixerOutToIoUnitIn)
);

Обеспечьте пользовательский интерфейс

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

Используйте Параметры, и UIKit для Предоставления Пользовательского Контроля объясняет основы построения пользовательского интерфейса для разрешения контролю за работой пользователей значение параметра. Для рабочего примера просмотрите проект примера кода Аудио Микшер (MixerHost).

IPod модуль EQ является одним из необычных случаев в этом, для изменения его активной кривой выравнивания, Вы изменяете значение kAudioUnitProperty_PresentPreset свойство. Можно сделать это, работает ли аудио. Для рабочего примера просмотрите Тест микшера iPodEQ AUGraph проекта примера кода.

Инициализируйте и запустите график обработки аудиоданных

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

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

  • Проверяет соединения графика и форматы потока аудиоданных.

  • Распространяет потоковые форматы через соединения аудиоустройства.

Перечисление 2-7 показывает, как использовать AUGraphInitialize.

  Инициализация перечисления 2-7 и запуск графика обработки аудиоданных

OSStatus result = AUGraphInitialize (processingGraph);
// Check for error. On successful initialization, start the graph...
AUGraphStart (processingGraph);
 
// Some time later
AUGraphStop (processingGraph);

Советы по устранению неисправностей

Каждый раз, когда функция Core Audio обеспечивает возвращаемое значение, получите то значение и проверку на успешность или неуспешность. При отказе используйте функции отладки XCode, как описано в Руководстве по Отладке XCode. Если использование метода Objective C в Вашем приложении, такой что касается конфигурирования Вашего аудио сеанса, пользуется преимуществом параметр ошибок таким же образом.

Знайте о зависимостях между вызовами функции. Например, можно запустить график обработки аудиоданных только после успешной инициализации его. Проверьте возвращаемое значение AUGraphInitialize. Если функция возвращается успешно, можно запустить график. Если это перестало работать, определите то, что пошло не так, как надо. Проверьте, что все Ваше продвижение вызовов функции аудиоустройства до инициализации возвратилось успешно. Для примера того, как сделать это, посмотрите на -configureAndInitializeAudioProcessingGraph метод в проекте примера кода Аудио Микшер (MixerHost).

Во-вторых, если инициализация графика перестала работать, используйте в своих интересах CAShow функция. Эта функция распечатывает состояние графика к консоли Xcode. Проект примера кода Аудио Микшер (MixerHost) демонстрирует этот метод также.

Гарантируйте инициализацию каждого из Вашего AudioStreamBasicDescription структуры к 0, следующим образом:

AudioStreamBasicDescription stereoStreamFormat = {0};

Инициализация полей ASBD к 0 гарантирует, чтобы никакие поля не содержали данные мусора. (В случае объявления структуры данных во внешнем хранении — например, как переменная экземпляра в объявлении класса — его поля автоматически инициализируются к 0, и Вы не должны инициализировать их сами.)

Распечатать значения полей AudioStreamBasicDescription структура к консоли Xcode, которая может быть очень полезной во время разработки, использует код как показанный в Перечислении 2-8.

Перечисление 2-8  служебный метод распечатать значения полей для AudioStreamBasicDescription структура

- (void) printASBD: (AudioStreamBasicDescription) asbd {
 
    char formatIDString[5];
    UInt32 formatID = CFSwapInt32HostToBig (asbd.mFormatID);
    bcopy (&formatID, formatIDString, 4);
    formatIDString[4] = '\0';
 
    NSLog (@"  Sample Rate:         %10.0f",  asbd.mSampleRate);
    NSLog (@"  Format ID:           %10s",    formatIDString);
    NSLog (@"  Format Flags:        %10X",    asbd.mFormatFlags);
    NSLog (@"  Bytes per Packet:    %10d",    asbd.mBytesPerPacket);
    NSLog (@"  Frames per Packet:   %10d",    asbd.mFramesPerPacket);
    NSLog (@"  Bytes per Frame:     %10d",    asbd.mBytesPerFrame);
    NSLog (@"  Channels per Frame:  %10d",    asbd.mChannelsPerFrame);
    NSLog (@"  Bits per Channel:    %10d",    asbd.mBitsPerChannel);
}

Этот служебный метод может быстро показать проблемы в ASBD.

При определении ASBD для потокового формата аудиоустройства заботьтесь, чтобы гарантировать, что Вы следуете за «Рекомендуемыми потоковыми атрибутами формата” и “Потоковыми примечаниями формата” в таблицах использования в Использовании Определенных Аудиоустройств. Не отклоняйтесь от тех рекомендаций, если у Вас нет определенной причины для.