Аудио проект семьи
Все драйверы аудио, независимо от платформы, должны выполнить те же общие действия. Для входных потоков драйверы получают данные цифрового аудио от аппаратных средств в потоке кадров, соответствующих текущей частоте дискретизации и формату аудио. Они изменяют данные, при необходимости, к форме, приемлемой для клиентов устройства (скажите, 32-разрядная плавающая точка), и сделайте измененные кадры доступными для тех клиентов на текущей частоте дискретизации. В реверсе (вывод) направление задание драйвера аудио является по существу тем же. Это принимает данные цифрового аудио от клиентов устройства, изменения, что поток демонстрационных кадров к форме, требуемой аппаратными средствами (говорят, 16-разрядное целое число), и, дает данные контроллеру устройства на текущей частоте дискретизации.
Когда некоторый атрибут или состояние аудиоустройства изменились, драйверы должны также первоначально сконфигурировать аппаратные средства, реагировать на клиентские запросы, чтобы изменить атрибуты устройств (например, объем), и уведомить клиенты. Они должны принять меры против повреждения данных в многопоточной среде, и они должны быть подготовлены реагировать на события в масштабе всей системы, такие как уведомления сна/следа.
Семья Audio обеспечивает объектно-ориентированные абстракции, чтобы помочь Вашему драйверу иметь дело со многими из этих вещей. Сама семья заботится о большой части работы для Вас; Вы просто предоставляете поведение, которое является определенным для Ваших аппаратных средств. Чтобы сделать это, полезно знать, как Ваш код совмещается с реализацией семьи, которая является тем, о чем эта глава.
Классы аудио семьи
Поскольку Вы можете с любой объектно-ориентированной системой, можно приехать в понимание проекта семьи I/O Kit Audio путем исследования классов семьи. Исследование в этом разделе смотрит на роли семьи, свойства, которые они инкапсулируют, аудио объекты, которые они представляют, и отношения, которые они имеют друг с другом. Отношения, которые рассматривают, не являются только статическими отношениями, наложенными наследованием, но также и динамическими отношениями, охарактеризованными включением, зависимостью и управлением.
Семья Audio состоит приблизительно из дюжины классов, все имеющие префикс «IOAudio»:
IOAudioEngineUserClient
IOAudioControlUserClient
IOAudioSelectorControl
Отношения наследования среди этих классов, как изображено на рисунке 2-1, несложны.
Все классы семьи Audio прямо или косвенно наследовались от IOService
; таким образом объекты этих классов являются законченными объектами драйвера с возможностью ответа на сообщения жизненного цикла драйвера и участия в процессе соответствия. На практике, однако, экземпляр IOAudioDevice
подкласс, как корневой объект драйвера аудио, обычно соответствия против куска провайдера (провайдер, являющийся контроллером PCI или FireWire или USB-устройством, в большинстве случаев). Драйверы аудио обычно являются «листовыми» объектами в штабеле драйвера, и обычно их единственным клиентом является Аудио HAL в пространстве пользователя. Поэтому они не публикуют собственные куски.
Два класса, IOAudioEngineUserClient
и IOAudioControlUserClient
, наследуйтесь от IOUserClient
класс. Объекты этих классов представляют пользовательские соединения клиента, позволяющие семье Audio передать с Аудио HAL. Пять из классов семьи Audio являются подклассами IOAudioControl
, обеспечивая поведение, определенное для определенных типов средств управления аудиоустройства (отключают звук переключателей, регуляторов громкости, и т.д.). Для получения дальнейшей информации на пользователе-клиенте и классах управления Аудио семьи, посмотрите Роли Аудио Объектов семьи.
Понимание статических отношений наследования между классами семьи Audio идет только до сих пор для разъяснения то, что экземпляры тех классов делают в типичном драйвере аудио. Это больше освещает для рассмотрения динамических отношений среди этих объектов.
Динамические отношения в аудио семье
Драйвер аудио Набора I/O состоит из переменного числа объектов, представляющих или инкапсулирующих определенные аспекты аудиоустройства. Многим из этих объектов принадлежат ссылки на другие объекты. Старшие значащие объекты в «живом» драйвере аудио происходят из четырех классов семьи Audio:
Рисунок 2-2 иллюстрирует динамические отношения этих объектов.
Корневой объект в драйвере аудио является экземпляром пользовательского подкласса IOAudioDevice
. Это представляет аудиоустройство в общем, полном смысле. IOAudioDevice
объект является корневым объектом по нескольким причинам: это создает и координирует многие из других объектов в драйвере, и это обычно - объект, который должен соответствовать против куска провайдера.
Пользовательский подкласс IOAudioDevice
добавляют атрибуты и реализуют поведение, которые являются определенными для устройства. Это ответственно за идентификацию, конфигурирование, и создание всех необходимых объектов аудио механизма и присоединение тех объектов к себе. Это должно отобразить все аппаратные ресурсы от куска провайдера и, когда требуется системой, это должно изменить значения средств управления.
Кроме того, IOAudioDevice
объект является контроллером мощности и производителем политики управления питанием для драйвера; при взаимодействии с IOAudioEngine
объекты, это должно должным образом определить системное безделье и соглашение с переходами состояния электропитания (сон и след), деактивировавшись и повторно активировав его аудио механизмы по мере необходимости. (См. Уведомления Сна/Следа Обработки для получения дополнительной информации.)
Водительское IOAudioDevice
объект содержит один или больше IOAudioEngine
объекты как переменные экземпляра. Каждый из этих объектов является экземпляром пользовательского подкласса IOAudioEngine
. IOAudioEngine
объект представляет механизм I/O (обычно механизм DMA) аудиоустройства; его задание должно передать аудиоданные или от одного или более демонстрационных буферов и аппаратных средств. Объект запускает и останавливает аудио механизм I/O, когда требуется; после того, как запущенный, это должно работать постоянно, цикличное выполнение через демонстрационные буферы, пока не остановлено. В то время как это работает, IOAudioEngine
берет метку времени и постепенно увеличивается, цикл рассчитывают каждый раз, когда это «переносит» демонстрационный буфер (см. Аудио Модель I/O Близко). Платформа Core Audio (Аудио HAL) использует эту информацию синхронизации для вычисления точной позиции аудио механизма в любое время.
Драйверу аудио нужен только один IOAudioEngine
возразите, если это не должно управлять демонстрационными буферами различных размеров или иметь демонстрационные кадры, переданные на различных уровнях. В этих случаях это должно инстанцировать и сконфигурировать требуемое число IOAudioEngine
экземпляры.
IOAudioEngine
сам объект содержит один или несколько экземпляров IOAudioStream
класс. IOAudioStream
объект прежде всего представляет демонстрационный буфер, который он инкапсулирует. Это также инкапсулирует буфер соединения для выходного аудиопотока. Это описывает направление потока, а также данных о формате, которые могут быть применены к демонстрационному буферу. Данные о формате включают такие данные как число каналов, выбирая формат и битовую глубину. Если демонстрационный буфер имеет многократные каналы, каналы обычно чередуются (несмотря на то, что отдельный IOAudioStream
экземпляры могут использоваться для представления нечередующихся различных каналов). Часто аудио механизм имеет тот IOAudioStream
объект для входного потока и другой для потока вывода.
IOAudioEngine
также содержит один или больше IOAudioControl
объекты как переменные экземпляра. Такой объект представляет управляемый атрибут аудиоустройства, такого как бесшумный режим, объем или основное усиление. IOAudioControl
обычно связывается с определенным каналом в определенном потоке. Однако это может управлять всеми каналами IOAudioStream
или даже все каналы IOAudioEngine
. Во время инициализации аппаратного обеспечения, IOAudioEngine
(или возможно водительское IOAudioDevice
объект), создает необходимое IOAudioControl
объекты и добавляют их к надлежащему IOAudioEngine
.
Каждый IOAudioControl
известен как “управление по умолчанию”, потому что Аудио HAL распознает и использует его на основе его атрибутов. Большинство изменений значения в средствах управления порождает с клиентами Аудио HAL, передающий их через интерфейс пользователя-клиента к определяемым обработчикам изменения значения в драйвере. Уведомления об изменениях значения в регулировках звука могут также переместиться другим способом; например, если пользователь поворачивает кнопку объема на динамике, драйвер передает это изменение в Аудио клиенты HAL.
Аудио семья и реестр I/O
Поскольку это делает со всеми драйверами Набора I/O, Реестр I/O получает отношения клиентского провайдера и свойства драйверов аудио. При помощи приложения Проводника Реестра I/O или ioreg
инструмент командной строки, можно просмотреть объекты «живых» драйверов аудио в Реестре I/O и исследовать свойства тех объектов. Визуальное представление, которое обеспечивают эти инструменты, разъясняет отношения клиентского провайдера среди объектов аудио семьи и отношения между аудио объектами и другими объектами в штабеле драйвера. Можно использовать эти инструменты для проверки состояния драйвера и для отладки проблем.
Рисунок 2-3 показывает, как некоторые объекты в драйвере аудио USB появляются в Реестре I/O.
В дополнение к этому использованию программирования Реестр I/O также служит критической функции в архитектуре аудиосистемы OS X. Свойства элементов управления драйвера аудио — объем, бесшумный режим, настройки усиления — сохранены в Реестре I/O и связаны с IOAudioControl
объект. Аудио, которое ищет HAL, распознает и использует основанное на объектах на своих атрибутах, которые оно обнаруживает через Реестр I/O. Посмотрите IOAudioControl для получения дополнительной информации.
Для получения дополнительной информации при соответствии свойств, атрибуты устройств и другие Ключи реестра I/O, видят заголовочный файл Kernel.framework/Headers/IOKit/audio/IOAudioDefines.h
или связанная справочная документация для IOAudioDefines.h
.
Роли аудио объектов семьи
Предыдущий раздел смотрел общим способом на главные объекты в «живом» драйвере аудио, описывая то, что в основном делают те объекты и что их отношения друг с другом. Этот раздел зондирует немного глубже и исследует роли всех классов семьи Audio (и объекты) более подробно.
IOAudioDevice
Каждый драйвер аудио на основе семьи Audio должен иметь один экземпляр пользовательского подкласса IOAudioDevice
. Водительское IOAudioDevice
объект является центральным, координирующим узлом водительского дерева объектов — «корневой» объект. Все другие объекты в конечном счете зависят от него или содержатся им.
Из-за его состояния как корневой объект, IOAudioDevice
объект обычно представляет аудио аппаратные средства. Эта центральная позиция дает ему несколько ролей:
Это - объект, обычно соответствующий против куска провайдера.
Это инициализирует устройство, отображая аппаратные ресурсы от куска провайдера, и иначе читает и пишет в регистры устройства по мере необходимости.
Это создает
IOAudioEngine
объекты драйвера и могут создатьIOAudioControl
объекты используются драйвером.Это обычно управляет синхронизацией значений между аппаратными средствами управления и связанным программным управлением, связанным с его объектами аудио механизма.
Это действует как контроллер мощности и влиятельный политик для аудио аппаратных средств; в этой роли это должно реагировать на системный сон, системный след и доменные переходы безделья путем деактивации и повторной активации его аудио механизмов по мере необходимости.
Водительское IOAudioDevice
объект выполняет другие функции. Это управляет доступом к аудио аппаратным средствам, чтобы гарантировать в водительской многопоточной среде, что аппаратные средства не входят в противоречивое состояние. К этому концу, IOAudioDevice
суперкласс обеспечивает отдельный цикл работы (IOWorkLoop
) и логический элемент команды (IOCommandGate
) синхронизировать доступ всеми объектами в драйвере. Все другие объекты в драйвере —IOAudioEngine
, IOAudioStream
, и IOAudioControl
— содержите ссылки на IOAudioDevice
цикл работы и команда пропускают как переменные экземпляра. Все классы семьи Audio заботятся о выполнении I/O и связанного с аппаратными средствами кода логического элемента команды для всех вызовов в драйвер, о котором они знают. Обычно драйверы должны гарантировать, что весь I/O и специфичные для аппаратных средств операции выполняются с закрытым логическим элементом команды.
IOAudioDevice
также предлагает услуги таймера к драйверу аудио. Эти службы позволяют различным объектам в драйвере получать уведомления, которые, как гарантируют, будут поставлены в требуемом интервале таймера, если не раньше. Различные целевые объекты могут зарегистрироваться для обратных вызовов таймера в определенном интервале; однако, IOAudioDevice
делает фактический интервал таймера самым маленьким из тех, которых требуют.
Идея позади этого проекта состоит в том, что нет никакого вреда в том, что синхронизировал события в драйвере аудио, происходят раньше, чем требуемый. Путем объединения интервалов обратного вызова семья Audio устраняет издержки многократных таймеров в единственном драйвере.
В некоторых случаях, однако, это может привести к неожиданному поведению при создании предположений на основе количества времени истекшими, такие как предположение, что аппаратные средства играли определенное число выборок. Необходимо таким образом всегда удостоверяться для тестирования, чтобы удостовериться, что условия являются надлежащими прежде, чем выполнить такие операции.
Ваш драйвер сам может иметь локализованные строки, которые доступны Аудио HAL. Эти строки могут включать такие вещи как имя, производителя, и ввести источники. Выполните процедуру локализации OS X для этих строк, поместив их в названный файл Localizable.strings
в специфичных для локали подкаталогах Вашего пакета. Драйверу нужно назвать свойство IOAudioDeviceLocalizedBundleKey
, который имеет значение пути пакета или расширения ядра, содержащего локализованные строки, относительно /System/Library/Extensions
. Водительское IOAudioDevice
объект должен установить это свойство в своей реализации initHardware
метод.
IOAudioEngine
Аудио объект механизма представляет и управляет механизмом I/O аудиоустройства. В драйвере аудио объект является экземпляром пользовательского подкласса IOAudioEngine
. Аудио механизм имеет две основных роли:
Сконфигурировать аппаратные средства механизм DMA для передачи аудиоданных (в форме потока демонстрационных кадров) между устройством и демонстрационным буфером на определенной частоте дискретизации. (В отсутствие аппаратных средств механизм DMA аудио механизм может эмулировать эту функциональность в программном обеспечении.)
Перемещать данные между демонстрационным буфером и буфером соединения после надлежащего преобразования данных к формату, ожидаемому клиентом или аппаратными средствами (в зависимости от направления).
Можно счесть больше информации об этой теме в Аудио Моделью I/O Близко.)
Экземпляр IOAudioStream
(описанный в IOAudioStream), представляет и инкапсулирует демонстрационный буфер в драйвере (и буфер соединения для потоков вывода). Каждый IOAudioEngine
в драйвере должен создать один или больше IOAudioStream
объекты для каждого демонстрационного буфера требуются механизмом I/O. Типичный драйвер имеет, по крайней мере, ввод IOAudioStream
и вывод IOAudioStream
.
IOAudioEngine
объект может также создать объекты регулировки звука (IOAudioControl
) требуемый устройством, несмотря на то, что эта задача может быть обработана водительским IOAudioDevice
. Во время фазы инициализации драйвер должен добавить все создаваемые IOAudioStream
экземпляры и IOAudioControl
экземпляры к IOAudioEngine
как переменные экземпляра с помощью надлежащего IOAudioEngine
методы. Это должно произойти, прежде чем это активируется IOAudioEngine
(с activateAudioEngine
метод).
В дополнение к упрощению передачи аудиоданных в и из выборки и буферов соединения, IOAudioEngine
имеет много функций:
Это должно остановить и запустить двигатель I/O, когда требуется.
Когда двигатель I/O запущен,
IOAudioEngine
объект должен гарантировать, что работает постоянно и, в конце демонстрационного буфера, циклов к началу буфера. Как циклы механизма,IOAudioEngine
берет метку времени и постепенно увеличивает количество цикла.Это должно обеспечить текущую выборку по требованию.
Если
IOAudioEngine
когда формат или уровень изменяются, поддержки многократные потоковые форматы или частоты дискретизации, это должно изменить аппаратные средства соответственно.
IOAudioEngine
имеет несколько атрибутов и структур, связанных с ним. Самый важный из них буфер состояния (IOAudioEngineStatus
) то, что это совместно использует с Аудио HAL. Этот буфер состояния является структурой что IOAudioEngine
должен обновить каждый раз циклы механизма I/O вокруг к запуску демонстрационного буфера. Структура содержит четыре поля, три из которых содержат критические значения:
Число раз аудио механизм циклично выполнилось к запуску демонстрационного буфера
Метка времени нового возникновения этого цикличного выполнения
Текущее расположение стирающей головки (с точки зрения демонстрационного кадра)
Важно что эти поля, особенно поле метки времени, быть максимально точным. Платформа Core Audio (Аудио HAL) использует эту информацию синхронизации для вычисления точной позиции аудио механизма в любое время. Совместно используемый буфер состояния является таким образом основанием для таймера и механизма синхронизации, используемого подсистемой аудио OS X.
Стирающая головка, упомянутая в предыдущем абзаце, является другим атрибутом IOAudioEngine
объект. Стирающая головка является конструкцией программного обеспечения, обнуляющей соединение и демонстрационные буферы сразу после того, как демонстрационные кадры игрались в потоке вывода. Это всегда перемещается только позади аудио механизма, чтобы избежать еще стирать не игравшиеся данные. Однако это также должно остаться хорошо перед IOAudioEngine
отсечение и подпрограммы преобразования, преобразовывающие аудиоданные в буфере соединения, чтобы гарантировать, что никакие устаревшие данные от предыдущей итерации цикла не смешаны или отсечены.
IOAudioEngine
объект выполняет много инициализаций для подстраивания механизма синхронизации, описанного выше. Например, это обеспечивает методы для установки задержки аудио механизма и для варьирования смещения между Аудио HAL и верхней частью I/O аудио механизма.
IOAudioStream
IOAudioStream
объект представляет единственный, независимо адресуемый аудиовход или поток вывода (который может включать многократные каналы). Это содержит следующий (как переменные экземпляра):
Демонстрационный буфер
Буфер соединения (для потоков вывода)
Информация о поддерживаемом формате (частота дискретизации, битовая глубина и число каналов)
Стартовый идентификатор канала
Число текущих клиентов
Все
IOAudioControl
объекты, влияющие на каналы потока
IOAudioStream
переменная экземпляра IOAudioEngine
объект, создающий его. Когда аудио механизм создает IOAudioStream
объект, это должно перечислить все поддерживаемые демонстрационные форматы, а также все поддерживаемые частоты дискретизации для каждого формата. Текущий формат должен быть явно установлен.
Если демонстрационный буфер имеет многократные каналы, каналы обычно чередуются на покадровой основе. Если Ваши аппаратные средства используют отдельные буферы для каждого канала, однако, можно использовать отдельный IOAudioStream
экземпляры для различных каналов.
IOAudioStream
класс определяет AudioIOFunction
введите для обратных вызовов (обычно реализованный владением IOAudioEngine
) тот клип и преобразовывает выходные аудиоданные с буфера соединения плавающего на демонстрационный буфер в формате, требуемом аппаратными средствами. Посмотрите Аудио Модель I/O Близко для получения дополнительной информации.
IOAudioStream
включает удобные методы то разрешение IOAudioStream
объекты, которые будут созданы из и сохранены к OSDictionary
объекты.
IOAudioControl
IOAudioControl
объект представляет управляемый атрибут аудиоустройства, такого как бесшумный режим, объем, селектор ввода/вывода или основное усиление. Это обычно связывается с определенным каналом в определенном потоке, но может использоваться для управления всеми каналами в IOAudioStream
или даже все каналы в IOAudioEngine
.
IOAudioControl
объекты являются обычно переменными экземпляра владения IOAudioEngine
объект. Однако IOAudioControl
объекты, связанные с определенным потоком, могут также храниться в соответствующем IOAudioStream
объект.
Обычно экземпляр IOAudioEngine
подкласс создает IOAudioControl
экземпляры, когда это инициализирует аппаратные средства (в initHardware
метод). Однако водительское IOAudioDevice
объект может быть объектом, создающим необходимое IOAudioControl
объекты. В любом случае драйвер должен добавить объекты управления к надлежащему IOAudioEngine
использование addDefaultAudioControl
метод.
Таким образом IOAudioControl
объект связан с IOAudioEngine
объект, IOAudioStream
объект и канал потока. Все его атрибуты сохранены в Реестре I/O. Это известно как “управление по умолчанию”, потому что Аудио HAL распознает и использует его на основе его атрибутов, обнаруженных через Реестр I/O.
Когда IOAudioEngine
(или IOAudioDevice
) объект создает IOAudioControl
объекты, это должно получить из аудиоустройства стартовый идентификатор канала (целое число) для аудиопотока. Когда драйвер создает первое IOAudioControl
для потока это присваивает этот идентификатор канала ему. Когда это создает IOAudioControl
объекты для любых других каналов потока (на основе числа каналов потоковые поддержки), это просто постепенно увеличивает ID канала, связанного с управлением.
Для аудиоустройств больше чем с одним аудиопотоком каждый поток должен запуститься в следующем свободном ID вне самого высокого пронумерованного ID, который мог содержать предыдущий поток. Это может быть получено путем добавления максимального количества каналов в любом данном потоковом формате к стартовому ID.
Семья Audio присваивается enum
идентификаторы к идентификаторам канала в IOAudioTypes.h
; они включают идентификаторы для левых, правильных, центральных, лево-задних, и правильных задних каналов, а также идентификатор для всех каналов.
В дополнение к идентификатору канала семья Audio использует многоуровневую систему классификации (определенный перечислениями в IOAudioTypes.h
) идентифицировать IOAudioControl
типы:
Аудио типы: вывод, ввод, микшер, передача и обработка
Аудио подтипы:
Для вывода: внутренний динамик, внешний громкоговоритель, наушники, строка и S/PDIF
Для ввода: внутренний микрофон, внешний микрофон, CD, строка и S/PDIF
Типы управления: уровень и селектор
Подтипы управления: объем, бесшумный режим, ввод, вывод, синхронизирует службы
Тип использования: ввод, вывод и передача
Когда Вы создаете IOAudioControl
объект, Вы указываете тип управления, подтип управления, тип использования и название канала (в дополнение к идентификатору канала).
Уровень и селекторные типы управления соответствуют подклассам IOAudioControl
, описанный в Таблице 2-1.
Подкласс |
Описание |
---|---|
Реализует регулировку звука на основе минимального и максимального значения. Подтип управления в частности создает регулятор громкости с помощью минимальных и максимальных децибелов, связанных с этими уровнями. |
|
|
Реализует регулировку звука на основе выбора дискретных элементов. Подтипы управления включают тех для бесшумного режима, ввода/вывода, и синхронизируют службы. |
Реализует регулировку звука на основе двоичных значений (прочь и на, запустите и остановитесь, и т.д.), те, которые могли бы принадлежать бесшумной регулировке. |
Некоторые объекты в драйвере аудио — обычно IOAudioDevice
объект из-за его центральной роли — должен реализовать то, что известно как “обработчики изменения значения”. Обработчик изменения значения является подпрограммой обратного вызова, соответствующей одному из трех прототипов, определенных в IOAudioControl.h
на основе типа имеющего значение (целое число, OSObject
, или void *
данные). Когда вызвано, обработчик изменения значения должен записать изменение в значении к аудио аппаратным средствам.
Изменения для управления значениями, порождающими с клиентами Аудио HAL — например, пользователь, перемещающий регулятор громкости в строку меню — инициируют длинный ряд действий в Аудио HAL и семья Audio:
Аудио HAL проходит через Реестр I/O для определения свойства или свойств, связанных с изменением значения.
Через
IOAudioEngineUserClient
объект,IOAudioControl
реализация суперклассаsetProperties
вызывается.Используя словарь свойств, переданных в
setProperties
,IOAudioControl
определяет местоположение целевого объекта управления и вызововsetValueAction
на нем.setValueAction
вызовы методаsetValue
на водительском цикле работы при содержании водительского логического элемента команды.setValue
метод сначала вызываетperformValueChange
, который делает две вещи:Это вызывает обработчик изменения значения для
IOAudioControl
(который должен соответствовать надлежащему прототипу функции для обратного вызова).Это отправляет уведомление об изменении во всех клиентах
IOAudioControl
(sendValueChangeNotification
).
Наконец,
setValue
вызовыupdateValue
обновить Реестр I/O с новым значением.
То, когда изменение физически внесено в аудио аппаратные средства — например, пользователь поворачивает набор объема на внешнем громкоговорителе — что должно быть сделано, очень сокращено. Когда драйвер обнаруживает изменение значения управления в аппаратных средствах, он просто вызывает hardwareValueChanged
на водительском цикле работы. Этот метод обновляет значение в IOAudioControl
экземпляр и в Реестре I/O, и затем отправляет уведомление всем заинтересованным клиентам.
Пользовательские клиентские классы
Семья Audio обеспечивает два класса пользователя-клиента, IOAudioEngineUserClient
и IOAudioControlUserClient
. Семья Audio автоматически инстанцирует объектов каждого класса для каждого IOAudioEngine
возразите и каждый IOAudioControl
в драйвере. Эти объекты включают коммуникацию аудиоданных и уведомлений между драйвером и Аудио HAL. Вам ничего не придется сделать явно в Вашем коде для создавания пользовательских объектов клиента по умолчанию для, и используемый, драйвер.
Для получения дальнейшей информации посмотрите Пользовательские Объекты клиента.
IOAudioPort
IOAudioPort
класс инстанцирует объектов, представляющих логический или физический порт или функциональный блок в аудиоустройстве. IOAudioPort
объект представляет элемент в сигнальной цепочке в аудиоустройстве и может содержать один или больше IOAudioControl
объекты, через которые различные атрибуты порта могут быть представлены и скорректированы.
IOAudioPort
класс осуждается и может в конечном счете быть сделан устаревшим. Класс в настоящее время общедоступен для поддержания совместимости. Писатели драйвера отговорены использовать IOAudioPort
объекты в их коде.
Аудио Модель I/O Закрывается
В предыдущей главе раздел The Audio I/O Model по OS X описал аудио OS X модель I/O с точки зрения того, как та модель сравнивает с Mac OS 9 моделей. Поскольку это был сравнительный обзор, то описание не учло некоторые важные подробные данные. Следующее обсуждение предоставляет те подробные данные с намерением, которое более полное понимает аудио модели I/O, имеет определенное преимущество для писателей драйвера аудио.
Кольцевые буферы и метки времени
В OS X водительский аудио механизм программирует механизм DMA аудиоустройства, чтобы читать из или записать в единственный (обычно большой) кольцевой буфер. В кольцевом буфере механизм DMA (или эмуляция программного обеспечения этого) повторяется к запуску буфера, когда это заканчивает писать в (или читать из) конец буфера. Таким образом механизм DMA постоянно циклы через демонстрационный буфер, читая или пишущий аудиоданные, в зависимости от направления. Поскольку это переносится, механизм DMA, как ожидают, запустит прерывание. Драйвер (в IOAudioEngine
объект), записывает время, когда это прерывание происходит путем вызова takeTimeStamp
в водительском цикле работы.
В вызове takeTimeStamp
, драйвер пишет две критических части данных к области памяти, совместно использованной IOAudioEngine
и его Аудио клиенты HAL. Первой является чрезвычайно точная метка времени (на основе utime
), и другой постепенно увеличенное количество цикла. Структура, определяющая их (и другой) поля, IOAudioEngineStatus
. Пользовательский объект клиента механизма отображает память, содержащую IOAudioEngineStatus
информация в адресные пространства Аудио клиенты HAL.
Для получения информации об обработке приближения метки времени посмотрите Метки времени Фальсифицирования.
Аудио HAL предсказывает
HAL Аудио использует накопленные метки времени и количества цикла в сложном вычислении, предсказывающем, когда механизм I/O будет в любом расположении в демонстрационном буфере; в результате это может также предсказать, когда каждый клиент определенного механизма I/O должен быть готов обеспечить аудиоданные для аппаратных средств или принять аудиоданные от него. Это вычисление принимает во внимание не только текущую позицию демонстрационного кадра механизма I/O, но также и буферные размеры клиентов, которые могут варьироваться.
У каждого клиента Аудио HAL есть его собственный поток I/O. Аудио HAL помещает этот поток для сна до времени, прибывает для клиента, чтобы считать или записать аудиоданные. Тогда Аудио HAL будит клиентский поток. Это - своего рода моделируемое программным обеспечением прерывание, включающее намного меньше наверху, чем аппаратное прерывание.
Интерполяция
Прежде, чем идти далее, стоит рассмотреть часть теории позади этого проекта. Аудиосистема OS X делает предположение, что аппаратные средства механизм I/O, поскольку это обрабатывает аудиоданные в демонстрационном буфере, продолжаются постоянно на более или менее постоянном уровне. «Более или менее» квалификация важна здесь потому что, в действительности, будут небольшие изменения в этом уровне по различным причинам, таким как недостатки в источниках часов. Таким образом, механизм, которым Аудио HAL постоянно использует метки времени, чтобы вычислить и предсказать время пробуждения для каждого его клиента потоки I/O, можно считать механизмом интерполяции. Это - очень точный прогнозирующий механизм, «сглаживающий» эти небольшие изменения в уровне механизма, создающем в некотором запасе времени так, чтобы не было никакого заметного эффекта на качество звука.
Клиентские Буферы и Процедуры I/O
Как отмечено ранее, каждый клиент Аудио HAL может определить размер его аудио буфера. Нет никаких ограничений, за исключением того, что буфер может быть не более крупным, чем размер аппаратного демонстрационного буфера. По причинам производительности почти все клиенты предпочитают буферные размеры, которые значительно меньше. Буферные размеры обычно являются питанием два. HAL Аудио принимает буферные размеры во внимание его клиентов, когда это вычисляет следующий цикл I/O для тех клиентов.
Каждый клиент Аудио HAL должен также реализовать функцию обратного вызова, соответствующую типу AudioDeviceIOProc
. Когда Аудио, HAL будит спящий клиент поток I/O, он вызывает эту функцию, передающую в буферах (ввод и вывод), размеры которого были указаны клиентом. Это находится в этой реализации AudioDeviceIOProc
подпрограмма, что клиент дает аудиоданные аппаратным средствам или получает его от аппаратных средств.
Следующий раздел, Обход Через Модель I/O, обсуждает то, что происходит затем подробно.
Обход через модель I/O
С существенным механизмом синхронизации, используемым для аудио I/O в памяти, мы можем теперь следовать за циклом того, что I/O через аудиосистему для наблюдения точно, что происходит. То, что происходит, отличается между аудиопотоками ввода и вывода. Поток вывода включает более сложный путь, потому что каждый клиент способствует, кадр кадром, к заключительному звуку, играемому динамиками или зарегистрированному некоторым устройством.
Потоки вывода
Давайте начнем с потока вывода. Рисунок 2-4 иллюстрирует отношение между буферами Аудио клиенты HAL и буферы драйвера аудио во время выходного цикла. Обратитесь к этой схеме во время следующего обсуждения.
Для каждого из его клиентов Аудио HAL вычисляет интервалы, основывающиеся на накопленных метках времени и количествах цикла, связанных с механизмом I/O, а также клиентскими буферными размерами. HAL Аудио спит потоки I/O его клиентов для этих интервалов, будя каждый поток, когда это - время для клиента, чтобы дать аппаратным средствам его данные. В пробуждении потока это вызывает AudioDeviceIOProc
подпрограмма, реализованная клиентом, передающим во многих буферах и метках времени:
Список входных буферов вместе с меткой времени, указывающей, когда были зарегистрированы данные
Список буферов вывода вместе с меткой времени, указывающей, когда будут играться данные
Метка времени, которая будет использоваться для «теперь», а не часы устройства
Метки времени ввода и вывода позволяют клиенту делать различные вычисления, такой как, сколько времени это имеет, прежде чем данные играются. Включение обоих параметров ввода и вывода включает клиентам, которые являются и производителями и потребителями аудиоданных (например, блок регистрации с возможностями воспроизведения) для обработки обоих потоков одновременно. В этом случае клиент сначала берет данные в списке входных буферов прежде, чем заполнить буферы вывода 32-разрядными выборками с плавающей точкой.
Когда клиент возвращается в AudioDeviceIOProc
подпрограмма, Аудио, HAL помещает поток I/O для сна до следующего раза данные, требуется от клиента. Аудио HAL дает выборки в буфере вывода к связанному IOAudioEngineUserClient
объект, вызывающий надлежащее IOAudioStream
объект переместить выборки от клиента буферизует к надлежащим кадрам в буфере соединения механизма. Другие клиенты могут также депонировать данные в тех же расположениях в буфере соединения. Если другой клиент уже депонировал данные в тех кадрах, значения нового клиента с плавающей точкой просто добавляются к существующим значениям.
Клиенты могут внести выходные данные в кадр почти, пока механизм I/O не готов к тем данным. IOAudioEngine
объект, содержащий буфер соединения, знает, сколько клиентов это имеет и когда каждый внес его долю данных к любому кадру буфера соединения (для текущего цикла через него). Кроме того, драйвер (через семью Audio) поддерживает «сторожевой» таймер, отслеживающий текущее расположение каждого клиента относительно механизма I/O. Если клиент не обеспечил аудиоданные к тому времени, когда механизму I/O нужны к доступам они, сторожевой таймер запускает и отсекает все в настоящее время смешанные выборки в демонстрационный буфер.
Поскольку некоторое время необходимо для выполнения этой работы клипа, сторожевой таймер фактически запускает короткий срок, прежде чем будут необходимы данные. Возможно, что «покойный» клиент мог попытаться поместить данные в расположение буфера соединения после того, как сторожевой таймер стрелял, но прежде чем механизм I/O обработал данные. Для размещения этой ситуации драйвер копирует и ремиксы и отсекает данные в попытке получить «последние» выборки к механизму I/O своевременно.
Затем, водительская подпрограмма клипа, clipOutputSamples
, вызывается. В его реализации этого метода драйвер должен отсечь любые избыточные значения с плавающей точкой под –1.0 и более чем 1,0 — который может произойти, когда многократные клиенты добавляют свои значения к существующим значениям в том же кадре — и затем преобразовывают эти значения в любой формат, требуется аппаратными средствами. Когда clipOutputSamples
возвраты, преобразованные значения были записаны в соответствующие расположения в демонстрационном буфере. Механизм DMA захватывает кадры, в то время как он развивается через демонстрационный буфер, и аппаратные средства играют их как звук.
Так как изображение стоит тысячу слов, взаимодействие этих процессов описано на рисунке 2-5.
Erase Heads and Timer Services
Семья Audio включает дальнейшее улучшение в синхронизируемые действия, описанные в предыдущих абзацах. Между механизмом I/O и отсечением и преобразованием, сделанным драйвером, это идет параллельно «стирающие головки» и в соединении и в демонстрационных буферах. Эти стирающие головки просто заполняют нулями соответствующие кадры одновременно. Эта предосторожность сокращает возможность, что любой кадр мог стать загрязненным с оставшимися битами.
Стирающие головки выполняются в отдельном потоке и имеют свой собственный таймер. Они программируются для выполнения четыре раза на демонстрационно-буферный цикл. Они не стирают весь диапазон кадров между текущими расположениями механизма DMA и водительской подпрограммы клипа, предоставляя немного пространства для делания ремикс данных от поздних клиентов.
Таймер стирающей головки выполняется с помощью IOAudioDevice
службы таймера. Его интервал, конечно, близко связывается к уровню механизма I/O и меток времени, взятых IOAudioEngine
.
Входные потоки
С входными аудиопотоками изображение намного более просто. Нет никакого буфера соединения и нет никаких стирающих головок. Клиенты HAL Аудио являются потребителями данных в этом случае, и не производителями его, таким образом, нет никакой потребности в этих вещах.
Ни один не там никакая потребность в подпрограмме клипа. Драйвер должен преобразовать целочисленные данные, прибывающие от аппаратных средств до 32-разрядной плавающей точки, требуемой Аудио HAL. Но во входном направлении, драйвер имеет возможность соответствовать преобразованным данным в –1.0 к 1,0 максимальным диапазонам с плавающей точкой.
Таким образом, упрощенная последовательность - это: вскоре после того, как механизм I/O пишет входные данные в демонстрационный буфер, драйвер — в его реализации IOAudioEngine
метод convertInputSamples
— преобразовывает те данные в 32-разрядную плавающую точку. Тогда данные даны, через IOAudioEngineUserClient
интерфейс, к каждому Аудио клиент HAL в том клиенте AudioDeviceIOProc
подпрограмма обратного вызова.
Интерфейсы с аудио HAL
Драйверы аудио передают с Аудио HAL и его клиенты, использующие два механизма. Основной механизм использует пользовательские объекты клиента для передачи аудиоданных, изменений значения управления и уведомлений через границу пространства пользователя ядра. Другой механизм позволяет писателям драйвера экспортировать свойства отдельного устройства в Аудио клиенты HAL.
Пользовательские объекты клиента
Как описано ранее в Пользовательских Клиентских Классах, семья Audio автоматически конфигурирует и создает надлежащее число пользовательских объектов клиента для драйвера. Эти объекты включают коммуникацию аудиоданных и уведомлений между драйвером и Аудио HAL. Объекты обычно являются экземплярами любого IOAudioEngineUserClient
класс или IOAudioControlUserClient
класс. Один IOAudioEngineUserClient
объект создается для каждого IOAudioEngine
в драйвере, и один IOAudioControlUserClient
объект создается для каждого IOAudioControl
.
IOAudioEngineUserClient
возразите действиям как кабелепроводу, через который аудиоданные передаются между драйвером аудио и Аудио HAL. Это - также агент, отображающий буфер, сохраняемый IOAudioEngine
в память, совместно использованную со связанным Аудио устройство HAL. (Как можно вспомнить, этот буфер содержит метку времени и количество новой «обертки» демонстрационного буфера механизмом I/O.) Наконец, IOAudioEngineUserClient
реагирует на запросы Аудио клиенты HAL, чтобы получить и установить свойства аппаратных средств. IOAudioControlUserClient
объект имеет более ограниченную роль по сравнению с a IOAudioEngineUserClient
объект. Это просто отправляет уведомление заинтересованным клиентам Аудио HAL когда значение управления (представленный IOAudioControl
) изменения.
Взаимодействие этих пользовательских клиентов с Аудио HAL и другие части Вашего драйвера показано на рисунке 2-6.
Вы ничего не должны делать явно в Вашем коде, чтобы сделать, чтобы семья Audio создала пользовательские объекты клиента по умолчанию для Вашего драйвера, и при этом Вы не должны писать код, чтобы позволить Вашему драйверу использовать эти объекты. Все это происходит автоматически для Вашего драйвера. Но это могло произойти, что Вы хотите пользовательское поведение от своих пользовательских клиентов; например, Вы могли бы хотеть, чтобы пользовательский клиент выполнил аппаратное смешивание, пишущий объединенные выборки в новый буфер, используемый единственным клиентом. Когда Вы хотите пользовательское поведение пользователя-клиента, можно разделить на подклассы IOAudioEngineUserClient
класс или IOAudioControlUserClient
класс. Эти классы описаны в IOAppleEngineUserClient.h
и IOAppleControlUserClient.h
.
Пользовательские свойства Core Audio
Иногда у Вас могло бы быть аудиоустройство со свойствами, не покрытыми тем, что Аудио указывает HAL (в платформе Core Audio AudioHardware.h
). Для этих ситуаций можно создать пакет, содержащий код, реализовывая эти специфичные для устройства свойства от имени Аудио HAL. Тогда можно поместить этот пакет в расположение, куда он может быть экспортирован в пространство пользователя. Пакет должен быть доступным Core Foundation Bundle Services APIs (CFBundle).
Для предоставления Аудио доступ HAL к коду свойства устройства пакет должен также представить программируемый интерфейс, определенный в заголовочном файле Core Audio AudioDriverPlugIn.h
. Эти подпрограммы разрешают Аудио клиенты HAL, чтобы открыть и закрыть устройство и получить и установить свойства устройства. Когда драйвер изменяет свойство, он вызывает один из двух обратных вызовов уведомления, реализованных клиентами (один определенный для Аудио свойства устройства HAL и другой для потоковых свойств) для уведомления их относительно изменения.
Когда Вы создали пакет, соответствующий интерфейсу в AudioDriverPlugIn.h
, Вы обычно устанавливаете его в своем водительском расширении ядра в /System/Library/Extensions
. Поскольку это - пакет, это может также содержать локализации строк, относящихся к новым свойствам. Аудио HAL находит пакет путем взгляда в Реестре I/O для двух ключей: kIOAudioEngineCoreAudioPlugInKey
и kIOAudioDeviceLocalizedBundleKey
.