Общие задачи в OS X

В этой главе описываются, как можно объединить части Core Audio для выполнения некоторых общих задач в OS X.

Core Audio является чрезвычайно модульным с немногими ограничениями на то, как использовать его различные части. Другими словами, можно часто делать вещи больше чем одним способом. Например, Ваше приложение Mac может вызвать Audio File Services для чтения сжатого звукового файла из диска, Audio Converter Services для преобразования данных в линейный PCM и Audio Queue Services для игры его. Также Вы могли загрузить встроенное аудиоустройство Проигрывателя Файла в свое приложение. Каждый подход имеет свои преимущества и возможности.

Чтение и запись аудиоданных

Много приложений, обрабатывающих аудио, должны считать и записать данные, или к диску или к буферу. Вы обычно хотите считать содержавшие данные файла и преобразовать их в линейный PCM. Можно сделать так за один шаг использование Extended Audio File Services.

Как показано на рисунке 3-1, Extended Audio File Services использует Audio File Services для чтения аудиоданных и затем вызывает Audio Converter Services для преобразования его в линейный PCM (предполагающий, что данные уже не находятся в том формате).

Рисунок 3-1  Читая аудиоданные
Extended Audio File Services encapsulates features from Audio File Services and Audio Converter Services.

При необходимости в большем количестве управления чтением файла и процедурой преобразования можно вызвать Аудиофайл, или Аудио Преобразователь функционирует непосредственно. Вы используете Audio File Services для чтения файла из диска или буфера. Эти данные могут быть в сжатом формате, когда они могут быть преобразованы в линейный PCM использование аудио преобразователя. Можно также использовать аудио преобразователь для обработки изменений в битовой глубине, частоте дискретизации, и т.д. в линейном формате PCM. Вы обрабатываете преобразования при помощи Audio Converter Services для создания аудио объекта преобразователя, указывая, что ввод и вывод форматирует Вас желание. Каждый формат определяется в ASBD (см. Универсальные Типы данных в Core Audio).

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

Если Вы хотите вывести аудиоданные, Вы отправляете их в модуль I/O. Модуль I/O может принять только линейные данные формата PCM. Такое аудиоустройство обычно является прокси для устройства, но это не требование.

Преобразование форматов аудиоданных

Core Audio использует линейный PCM в качестве промежуточного формата, разрешающего много перестановок преобразований. Чтобы определить, возможно ли определенное преобразование формата, необходимо удостовериться, что оба декодер (формат A к линейному PCM) и кодер (линейный PCM к формату B) доступны. Например, если бы Вы хотели преобразовать данные от MP3 до AAC, то Вам были бы нужны два аудио преобразователя: один для преобразования от MP3 до линейного PCM и другого для преобразования линейного PCM в AAC, как показано на рисунке 3-2.

Рисунок 3-2  , Преобразовывающий аудиоданные с помощью двух преобразователей
One audio converter turns MP3 data to linear PCM data, which the next audio converter turns to AAC data.One audio converter turns MP3 data to linear PCM data, which the next audio converter turns to AAC data.

Для примеров использования Аудиофайла и Аудио Преобразователя APIs, посмотрите SimpleSDK/ConvertFile и Services/AudioFileTools выборки в Core Audio SDK. Если Вам интересно в письменной форме пользовательский аудио кодек преобразователя, посмотрите выборки в AudioCodec папка.

Взаимодействие через интерфейс с аппаратными средствами

Большинство аудиоприложений соединяется с внешними аппаратными средствами, любой, чтобы вывести звук (например, к усилителю и громкоговорителю) или получить его (такой как через микрофон). Нижний уровень Core Audio делает эти соединения, говоря с Набором I/O и драйверами. OS X обеспечивает интерфейс для этих соединений, названных аудио уровнем аппаратной абстракции или аудио HAL. Вы считаете аудио интерфейсы HAL’s объявленными в AudioHardware.h заголовочный файл в платформе Core Audio.

Однако во многих случаях приложения не должны использовать аудио HAL непосредственно. Apple обеспечивает три стандартных аудиоустройства, которые должны удовлетворить большинство аппаратных потребностей: устройство вывода по умолчанию, системное устройство вывода и модуль AUHAL. Ваше приложение должно явно загрузить эти аудиоустройства, прежде чем можно будет использовать их.

Значение по умолчанию и система модули I/O

Модуль I/O по умолчанию и система, которую модуль I/O отправляет аудиоданным в вывод по умолчанию (как выбрано пользователем) или системный вывод (где предупреждения и другие системные звуки играются), соответственно. Когда для вывода нужны данные, при соединении вывода аудиоустройства с одним из этих модулей I/O — такого как в графике обработки аудиоданных — функцию обратного вызова рендеринга аудиоустройства вызывают. Модуль I/O направляет данные через HAL к надлежащему устройству вывода, автоматически обрабатывая следующие задачи, как показано на рисунке 3-3.

Рисунок 3-3  В модуле I/O
An I/O unit (sometimes called an "output unit") encapsulates an audio converter, channel mapping, and start/stop control.
  • Любое требуемое линейное преобразование данных PCM. Устройство вывода содержит аудио преобразователь, который может перевести Ваши аудиоданные в линейный вариант PCM, требуемый аппаратными средствами.

  • Любое требуемое отображение канала. Например, если Ваш модуль предоставит два данные канала, но устройство вывода может обработать пять, то Вы, вероятно, захотите отобразиться, какие каналы переходят в который. Можно сделать так путем указания карты канала с помощью kAudioOutputUnitProperty_ChannelMap свойство на устройстве вывода. Если Вы не предоставляете карту канала, значение по умолчанию должно отобразить первый звуковой канал на первый канал устройства, второе к второму, и т.д. Эффективная выходная мощность слышала, тогда определяется тем, как пользователь сконфигурировал динамики устройства в Аудио Приложение установки MIDI.

  • Сигнал Запускает/Останавливает. Устройства вывода являются единственными аудиоустройствами, которые могут управлять потоком аудиоданных в сигнальной цепочке.

Для примера использования устройства вывода по умолчанию для игры аудио посмотрите SimpleSDK/DefaultOutputUnit в Core Audio SDK.

Модуль AUHAL

Если необходимо соединиться с устройством ввода данных или устройством кроме устройства вывода по умолчанию, необходимо использовать AUHAL. Несмотря на то, что определяется как устройство вывода, можно сконфигурировать AUHAL для принятия введенный также путем установки kAudioOutputUnitProperty_EnableIO свойство на вводе. Для большего количества специфических особенностей посмотрите Техническое примечание TN2091: Ввод Устройства Используя Выходное Аудиоустройство HAL. Когда ввод принятия, AUHAL поддерживает отображение канала ввода и использует аудио преобразователь (если необходимый) для перевода входящих данных в линейный формат PCM.

AUHAL является более обобщенной версией устройства вывода по умолчанию. В дополнение к аудио преобразователю и возможностям отображения канала, можно указать устройство для соединения с путем установки kAudioOutputUnitProperty_CurrentDevice свойство к ID AudioDevice объект в HAL. После того, как соединенный, можно также управлять свойствами, связанными с AudioDevice объект путем обращения AUHAL; AUHAL автоматически проводит любые вызовы свойства, предназначенные для аудиоустройства.

Экземпляр AUHAL может соединиться только с одним устройством за один раз, таким образом, можно включить оба ввода и вывода, только если устройство может принять обоих. Например, встроенное аудио для основанных на PowerPC компьютеров Macintosh сконфигурировано как единое устройство, которое может оба принять входные аудиоданные (через Микрометр в) и вывести аудио (через динамик).

В целях потока сигналов AUHAL, сконфигурированный для обоих вводов и выводов, ведет себя как два аудиоустройства. Например, когда выведенный включен, AUHAL вызывает обратный вызов рендеринга предыдущего аудиоустройства. Если аудиоустройство должно ввести данные от устройства, это вызывает обратный вызов рендеринга AUHAL. Рисунок 3-4 показывает AUHAL, используемый для обоих вводов и выводов.

Рисунок 3-4  AUHAL используется для ввода и вывода
The AUHAL unit simultaneously receives data from I/O Kit and sends processed data back to I/O kit.

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

Для примеров использования AUHAL для ввода и вывода посмотрите пример кода CAPlayThrough. CAPlayThrough показывает, как реализовать ввод и вывод с помощью AUHAL для ввода и устройства вывода по умолчанию для вывода.

Используя составные устройства

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

Пользователи могут создать составные устройства в Аудио Приложение установки MIDI путем выбора пункта меню Audio> Open Aggregate Device Editor. После выбора sub устройств для объединения как составное устройство пользователь может сконфигурировать каналы ввода и вывода устройства как любое другое устройство. Пользователь также должен указать, какие часы sub устройства должны действовать как ведущее устройство в целях синхронизации.

Любые составные устройства, которые создает пользователь, являются глобальной переменной к системе. Можно создать составные устройства, которые локальны для порядка подачи заявки программно с помощью вызовов функции HAL Services. Составное устройство появляется как AudioAggregateDevice объект (подкласс AudioDevice) в HAL.

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

Составные устройства имеют некоторые ограничения:

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

Для получения дальнейшей информации о создании аудиоустройств, см. Руководство по программированию Аудиоустройства.

Хостинг аудиоустройств

Аудиоустройства, будучи плагинами, требуют, чтобы хост-приложение загрузило и управляло ими.

Поскольку аудиоустройства являются компонентами Component Manager, хост-приложение должно вызвать Менеджер компонентов для загрузки их. Хост-приложение может найти и инстанцировать аудиоустройств, если они установлены в одной из следующих папок:

Если необходимо получить список доступных аудиоустройств (для отображения пользователю, например), необходимо вызвать функцию Менеджера компонентов CountComponents для определения, сколько аудиоустройств определенного типа доступно, затем выполните итерации использования FindNextComponent получить информацию о каждом модуле. A ComponentDescription структура содержит идентификаторы для каждого аудиоустройства (его тип, подтип и коды производителя). Посмотрите Предоставленные систему Аудиоустройства в OS X для списка типов Менеджера компонентов и подтипов для предоставленных Apple аудиоустройств. Узел может также открыть каждый модуль (путем вызова OpenComponent) таким образом, это может запросить его для различной информации о свойстве, такой как форматы данных ввода и вывода аудиоустройства по умолчанию, которые узел может тогда кэшировать и представить пользователю.

В большинстве случаев график обработки аудиоданных является самым простым способом подключить аудиоустройства. Одно преимущество использования графика обработки состоит в том, что API заботится о совершении отдельных звонков Менеджера компонентов, чтобы инстанцировать или уничтожить аудиоустройства. Для создания графика вызвать NewAUGraph, который возвращает новый объект диаграмм. Тогда можно добавить аудиоустройства к графику путем вызова AUGraphNewNode. График должен закончиться в устройстве вывода, или аппаратный интерфейс (такой как устройство вывода по умолчанию или AUHAL) или универсальное устройство вывода.

После добавления модулей, которые составят график обработки, вызвать AUGraphOpen. Эта функция эквивалентна вызову OpenComponent на каждом из аудиоустройств в графике. В это время можно установить свойства аудиоустройства, такие как расположение канала, частота дискретизации или свойства, определенные для определенного модуля (такие как число вводов и выводов, которые это содержит).

Для создания конкретных соединений между аудиоустройствами вызвать AUGraphConnectNodeInput, указание вывода и ввода для соединения. Цепочка аудиоустройства должна закончиться в устройстве вывода; иначе хост-приложение не имеет никакого способа запустить и остановить обработку аудиоданных.

Если аудиоустройство имеет пользовательский интерфейс, хост-приложение ответственно за отображение его. Аудиоустройства могут предоставить Какао или Основанный на углероде интерфейс (или оба). Код для пользовательского интерфейса обычно связывается вместе с аудиоустройством.

После создания сигнальной цепочки можно инициализировать аудиоустройства путем вызова AUGraphInitialize. Выполнение так вызывает функцию инициализации для каждого аудиоустройства, позволяя ему выделить память для рендеринга, сконфигурировать информацию о канале, и т.д. Тогда можно вызвать AUGraphStart, который инициирует обработку. Устройство вывода тогда запрашивает аудиоданные от предыдущего модуля в цепочке (посредством обратного вызова), который тогда вызывает его предшественника и т.д. Источник аудио может быть аудиоустройством (таким как модуль генератора или AUHAL), или хост-приложение может предоставить сами аудиоданные путем регистрации обратного вызова в первом аудиоустройстве в сигнальной цепочке (путем установки модуля kAudioUnitProperty_SetRenderCallback свойство).

В то время как аудиоустройство инстанцируют, хост-приложение может хотеть знать об изменениях в значениях параметров или значениях свойств; это может зарегистрировать объект прослушивателя, который будет уведомлен, когда происходят изменения. Для получения дополнительной информации о том, как реализовать такого слушателя, посмотрите Техническое примечание TN2104: Обработка Событий Аудиоустройства.

Когда узел хочет к обработке стопового сигнала, он вызывает AUGraphStop.

Для деинициализации всех аудиоустройств в графике вызвать AUGraphUninitialize. Когда назад в неинициализированном состоянии, можно все еще изменить свойства аудиоустройства и сделать или изменить соединения. Если Вы вызываете AUGraphClose, каждое аудиоустройство в графике освобождено a CloseComponent вызвать. Однако график все еще сохраняет узловую информацию, относительно которого модулей он содержит.

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

Для примеров хостинга аудиоустройств посмотрите Services/AudioUnitHosting и Services/CocoaAUHost примеры в Core Audio SDK.

Для примера реализации пользовательского интерфейса аудиоустройства посмотрите AudioUnits/CarbonGenericView пример в Core Audio SDK. Можно использовать этот пример с любым аудиоустройством, содержащим корректируемые пользователем параметры.

Обработка данных MIDI

При работе с данными MIDI приложение, возможно, должно было бы загрузить данные дорожки из стандартного файла MIDI (SMF). Можно вызвать функцию Music Player (MusicSequenceLoadSMFWithFlags или MusicSequenceLoadSMFDataWithFlags) считать в данных в Стандарте Формат MIDI, как показано на рисунке 3-5.

Рисунок 3-5  Читая стандартный файл MIDI
A MID file gets parsed into a tempo track and an event track, both of which get played by a music player object.

В зависимости от типа файла MIDI и набора флагов при загрузке файла, можно хранить все данные MIDI в одноколейном пути или сохранить каждый канал MIDI как отдельную дорожку в последовательности. По умолчанию каждый канал MIDI отображается последовательно на новой дорожке в последовательности. Например, если данные MIDI содержат каналы 1, 3, и, 4, три новых дорожки добавляются к последовательности, содержа данные для каналов 1, 3, и 4 соответственно. Эти дорожки добавляются к последовательности в конце любых существующих дорожек. Каждая дорожка в последовательности присваивается основанное на нуле индексное значение.

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

Как только Вы загрузили данные MIDI в последовательность, можно присвоить экземпляр аудиоплеера для игры его, как показано на рисунке 3-6.

Рисунок 3-6  Играя данные MIDI
Connections between a music sequence, a music player, and an audio processing graph.

Последовательность должна быть связана с определенным графиком обработки аудиоданных, и дорожки в последовательности могут быть присвоены одному или более модулям инструментов в графике. (Если Вы не указываете отображение дорожки, аудиоплеер отправляет все данные MIDI в первый модуль инструментов, который это находит в графике.) Аудиоплеер, присвоенный последовательности автоматически, связывается с устройством вывода графика, чтобы удостовериться, что должным образом синхронизируются исходящие аудиоданные. Компрессорная установка, в то время как не требуемый, полезна для обеспечения, что динамический диапазон вывода модуля инструментов остается непротиворечивым.

Данные MIDI в последовательности могут также перейти к внешним аппаратным средствам MIDI (или программное обеспечение, сконфигурированное как виртуальное место назначения MIDI), как показано на рисунке 3-7.

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

Рисунок 3-7  , Отправляющий данные MIDI в MIDI-устройство
Connections between a music sequence, a music player and a MIDI endpoint object.

Последовательность дорожек может быть присвоена комбинации модулей инструментов и MIDI-устройств. Например, в то время как другие дорожки проходят через Core MIDI для проигрывания внешних MIDI-устройств, как показано на рисунке 3-8, можно присвоить некоторые дорожки для проигрывания модуля инструментов.

Рисунок 3-8  Играя оба MIDI-устройства и виртуальный инструмент
Playing MIDI data: connections between MIDI endpoints, a music sequence and music player, and an audio processing graph.

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

Другой общий сценарий уже должен воспроизвести существующие данные дорожки при принятии нового ввода MIDI, как показано на рисунке 3-9.

Рисунок 3-9  , Принимающий новую дорожку, вводится
Receiving MIDI data: connections between MIDI endpoints, a music sequence and music player, and an audio processing graph.

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

Для примеров обработки и игры данных MIDI, посмотрите следующие примеры в Core Audio SDK:

Обработка аудио и данных MIDI вместе

Иногда Вы хотите объединить аудиоданные с аудио, синтезируемым от данных MIDI и воспроизвести результат. Например, аудио для многих игр состоит из фоновой музыки, которая сохранена как аудиофайл на диске, вместе с шумами, инициированными событиями (шаги, орудийный огонь, и т.д.), которые сгенерированы как данные MIDI. Рисунок 3-10 показывает, как можно использовать Core Audio для объединения двух.

  Аудио Объединения рисунка 3-10 и данные MIDI
Mixing audio and MIDI for playback: connections between an extended audio file object, a music sequence and music player, and an audio processing graph.

Аудиоданные звуковой дорожки получены от диска или памяти и преобразованы в линейный PCM использование Расширенного Аудиофайла API. Данные MIDI, хранившие как дорожки в музыкальной последовательности, отправляются в виртуальный модуль инструментов. Вывод от виртуального модуля инструментов находится в линейном формате PCM и может тогда быть объединен с данными звуковой дорожки. Этот пример использует 3D модуль микшера, который может расположить источники аудиосигналов в трехмерное пространство. Одна из дорожек в последовательности отправляет данные о событии в модуль микшера, изменяющий параметры расположения, заставляя звук, казаться, перемещаться в течение долгого времени. Приложение должно было бы контролировать перемещения проигрывателя и добавить события к специальной дорожке перемещения по мере необходимости.

Для примера загрузки и игры основанных на файле аудиоданных, посмотрите SimpleSDK/PlayFile в Core Audio SDK.