Заметки

  1. Микшеры Direct Audio всегда используются в Windows по умолчанию. Они используются по умолчанию в Solaris, если включен аудиомикшер Solaris (см. Справочную страницу Solaris для микшера). В Linux они используются по умолчанию, только если есть устройство, поддерживающее микширование.
  2. Поскольку микшеры Direct Audio являются «прямыми», они не поддерживают элемент управления SAMPLE_RATE.
  3. Микшер по умолчанию можно выбрать в файле sound.properties .

 

В этой главе представлено введение в архитектуру цифрового звука Java Sound API, доступ к которой осуществляется через пакет javax.sound.sampled . Во-первых, дается объяснение направленности пакета: воспроизведение и захват форматированных аудиоданных. Затем в этой главе описываются три основных компонента, необходимых для воспроизведения или захвата: формат аудиоданных, линия и микшер. Кратко представлены интерфейс Line и его подынтерфейсы.

Цели проектирования

Прежде чем исследовать элементы Java Sound API, это помогает понять ориентацию пакета javax.sound.sampled.

Акцент на перенос данных

Пакет javax.sound.sampled в основном занимается передачей звука, другими словами, Java Sound API ориентирован на воспроизведение и захват. Центральная задача, которую решает Java Sound API, - как перемещать байты форматированных аудиоданных в систему и из нее. Эта задача включает открытие устройств ввода и вывода звука и управление буферами, которые заполняются звуковыми данными в реальном времени. Он также может включать смешивание нескольких потоков звука в один поток (как для ввода, так и для вывода). Транспортировка звука в систему или из нее должна быть правильно обработана, когда пользователь запрашивает запуск, приостановку, возобновление или остановку потока звука.

Чтобы поддержать этот фокус на базовом аудиовходе и выходе, Java Sound API предоставляет методы преобразования между различными форматами аудиоданных, а также для чтения и записи общих типов звуковых файлов. Однако он не пытается быть всеобъемлющим инструментарием звуковых файлов. Конкретная реализация Java Sound API не должна поддерживать обширный набор типов файлов или преобразований форматов данных. Сторонние поставщики услуг могут поставлять модули, которые "подключаются" к существующей реализации для поддержки дополнительных типов файлов и преобразований.

Буферизованная и небуферизованная обработка звука

Java Sound API может обрабатывать передачу звука как в потоковом режиме с буферизацией, так и без буферизации в памяти. «Потоковая передача» используется здесь в общем смысле для обозначения обработки байтов аудио в реальном времени; это не относится к конкретному, хорошо известному случаю отправки аудио через Интернет в определенном формате. Другими словами, поток аудио - это просто непрерывный набор байтов аудио, которые прибывают более или менее с той же скоростью, с которой они должны обрабатываться (воспроизводиться, записываться и т. Д.). Операции с байтами начинаются до того, как будут получены все данные. В модели потоковой передачи, особенно в случае аудиовхода, а не аудиовыхода, необязательно заранее знать, как долго длится звук и когда он закончится. Вы просто обрабатываете один буфер аудиоданных за раз, пока операция не будет остановлена. В случае вывода звука (воспроизведения) вам также необходимо буферизовать данные, если звук, который вы хотите воспроизвести, слишком велик, чтобы поместиться в памяти сразу. Другими словами, вы доставляете звуковые байты в звуковой движок по частям, и он заботится о воспроизведении каждого семпла в нужное время. Предоставляются механизмы, которые позволяют легко узнать, сколько данных нужно доставить в каждом блоке.

Java Sound API также разрешает небуферизованный транспорт только в случае воспроизведения, если у вас уже есть все аудиоданные, и они не слишком велики, чтобы поместиться в памяти. В этой ситуации прикладной программе нет необходимости буферизовать звук, хотя при желании по-прежнему доступен подход с буферизацией в реальном времени. Вместо этого весь звук можно сразу предварительно загрузить в память для последующего воспроизведения. Поскольку все звуковые данные загружаются заранее, воспроизведение может начаться немедленно, например, как только пользователь нажимает кнопку «Пуск». Это может быть преимуществом по сравнению с буферизованной моделью, где воспроизведение должно ждать заполнения первого буфера. Кроме того, небуферизованная модель в памяти позволяет легко зацикливать (циклически) звуки или устанавливать произвольные позиции в данных.

Эти две модели воспроизведения обсуждаются далее в главе 4 "Воспроизведение аудио." Буферизованная запись обсуждается в главе 5 "Захват аудио."

Основы: Format, Mixer, и Line

Для воспроизведения или записи звука с помощью Java Sound API вам понадобятся как минимум три вещи: отформатированные аудиоданные, микшер и линия. Каждый из них объясняется ниже.

Что такое форматированные аудиоданные?

Отформатированные аудиоданные относятся к звуку в любом из ряда стандартных форматов. Java Sound API различает форматы данных и форматы файлов.

Форматы данных

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

В Java Sound API формат данных представлен объектом AudioFormat, который включает следующие атрибуты:

  • Метод кодирования, обычно импульсно-кодовая модуляция (PCM)
  • Количество каналов (1 для моно, 2 для стерео и т. д.)
  • Частота дискретизации (количество выборок в секунду, на канал)
  • Количество бит на выборку (на канал)
  • Частота кадров
  • Размер кадра в байтах
  • Порядок байтов (прямой или прямой порядок байтов)

PCM - это один из видов кодирования звуковой волны. Java Sound API включает две кодировки PCM, которые используют линейное квантование амплитуды и целочисленные значения со знаком или без знака. Линейное квантование означает, что число, хранящееся в каждом сэмпле, прямо пропорционально (за исключением любых искажений) исходному звуковому давлению в этот момент и так же пропорционально смещению громкоговорителя или барабанной перепонки, которые вибрируют со звуком в этот момент. Компакт-диски, например, используют звук в формате линейной PCM. Кодирование по мю-закону и кодирование по закону А - это распространенные нелинейные кодировки, которые обеспечивают более сжатую версию аудиоданных; эти кодировки обычно используются для телефонной связи или записи речи. Нелинейное кодирование преобразует амплитуду исходного звука в сохраненное значение с помощью нелинейной функции, которая может быть спроектирована так, чтобы дать большее разрешение по амплитуде тихим звукам, чем громким.

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

Для других типов кодировок кадр может содержать дополнительную информацию помимо выборок, и частота кадров может полностью отличаться от частоты дискретизации. Например, рассмотрим кодировку MP3 (MPEG-1 Audio Layer 3), которая явно не упоминается в текущей версии Java Sound API, но которая может поддерживаться реализацией Java Sound API или сторонним поставщиком услуг. В MP3 каждый кадр содержит пакет сжатых данных для серии сэмплов, а не только один сэмпл на канал. Поскольку каждый кадр инкапсулирует целую серию выборок, частота кадров ниже, чем частота дискретизации. Фрейм также содержит заголовок. Несмотря на заголовок, размер кадра в байтах меньше, чем размер в байтах эквивалентного числа кадров PCM. (В конце концов, цель MP3-быть более компактным, чем данные PCM.) Для такого кодирования частота дискретизации и размер выборки относятся к данным PCM, в которые кодированный звук в конечном итоге будет преобразован перед передачей в цифроаналоговый преобразователь (ЦАП).

Форматы файлов

Формат файла определяет структуру звукового файла, включая не только формат необработанных аудиоданных в файле, но и другую информацию, которая может храниться в файле. Звуковые файлы бывают различных стандартных типов, таких как WAVE (также известный как WAV и часто связанный с ПК), AIFF (часто связанный с Macintosh) и AU (часто связанный с системами UNIX). Различные типы звуковых файлов имеют разную структуру. Например, они могут иметь другое расположение данных в «заголовке» файла. Заголовок содержит описательную информацию, которая обычно предшествует фактическим аудиосэмплам файла, хотя некоторые форматы файлов допускают последовательные «порции» описательных и аудиоданных. Заголовок включает спецификацию формата данных, который использовался для хранения звука в звуковом файле. Любой из этих типов звуковых файлов может содержать различные форматы данных (хотя обычно в одном файле есть только один формат данных), и один и тот же формат данных может использоваться в файлах с разными форматами файлов.

В Java Sound API формат файла представлен объектом AudioFileFormat, который содержит:

  • Тип файла (WAVE, AIFF и т. Д.)
  • Длина файла в байтах
  • Длина в кадрах аудиоданных, содержащихся в файле.
  • Объект AudioFormat, указывающий формат аудиоданных, содержащихся в файле.

Класс AudioSystem (описанный в главе 3 "Доступ к ресурсам аудиосистемы") предоставляет методы для чтения и записи звуков в различных форматах файлов, а также для преобразования между разными форматами данных. Некоторые методы позволяют получить доступ к содержимому файла через своего рода поток, называемый AudioInputStream. AudioInputStream - это подкласс универсального класса Java InputStream , который инкапсулирует серию байтов, которые могут быть прочитаны последовательно. К своему суперклассу класс AudioInputStream добавляет информацию о байтовом формате аудиоданных (представленном объектом AudioFormat). Читая звуковой файл как AudioInputStream, вы получаете немедленный доступ к семплам, не беспокоясь о структуре звукового файла (его заголовке, фрагментах и ​​т. Д.). Вызов одного метода дает вам всю необходимую информацию о формате данных и типе файла.

Что такое микшер?

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

В Java Sound API устройства представлены объектами Mixer. Назначение микшера - обрабатывать один или несколько потоков аудиовхода и один или несколько потоков аудиовыхода. В типичном случае он фактически смешивает несколько входящих потоков в один исходящий поток. Объект Mixer может представлять возможности микширования звука физического устройства, такого как звуковая карта, которому может потребоваться микшировать звук, поступающий на компьютер с различных входов, или звук, поступающий из прикладных программ и поступающий на выходы.

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

В Java Sound API компонент, такой как вход микрофона на звуковой карте, сам по себе не считается устройством, то есть микшером, а скорее портом в микшер или из него. Порт обычно обеспечивает одиночный поток звука в микшер или из него (хотя поток может быть многоканальным, например стерео). В микшере может быть несколько таких портов. Например, микшер, представляющий выходные возможности звуковой карты, может смешивать несколько потоков звука вместе, а затем отправлять смешанный сигнал на любой или все различные выходные порты, подключенные к микшеру. Эти выходные порты могут быть (например) разъемом для наушников, встроенным динамиком или линейным выходом.

Чтобы понять понятие микшера в Java Sound API, он помогает визуализировать физическую микшерную консоль, например, те, которые используются на живых концертах и ​​в студиях звукозаписи. (См. Иллюстрацию ниже.)

Physical mixing console

Консоль физического микширования

В физическом микшере есть «полосы» (также называемые «срезами»), каждая из которых представляет путь, по которому отдельный аудиосигнал поступает в микшер для обработки. На полосе есть ручки и другие элементы управления, с помощью которых вы можете регулировать громкость и панораму (размещение в стереоизображении) сигнала в этой полосе. Кроме того, микшер может иметь отдельную шину для таких эффектов, как реверберация, и эта шина может быть подключена к внутреннему или внешнему блоку реверберации. У каждой полосы есть потенциометр, который контролирует, какая часть сигнала этой полосы попадает в реверберированный микс. Затем реверберированная («влажная») смесь смешивается с «сухими» сигналами от полосок. Физический микшер отправляет эту финальную смесь на шину вывода, которая обычно идет на магнитофон (или систему записи на диск) и / или динамики.

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

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

Эти два примера иллюстрируют два различных использования микшера: для захвата нескольких входных каналов, объединения их в меньшее количество дорожек и сохранения смеси или для воспроизведения нескольких дорожек при сведении их к меньшему количеству дорожек.

В Java Sound API микшер может аналогичным образом использоваться для ввода (захват звука) или вывода (воспроизведение звука). В случае ввода источником, из которого микшер получает звук для микширования, является один или несколько входных портов. Микшер отправляет захваченные и смешанные аудиопотоки своей цели, которая представляет собой объект с буфером, из которого прикладная программа может извлечь эти смешанные аудиоданные. В случае аудиовыхода ситуация обратная. Источником звука микшера является один или несколько объектов, содержащих буферы, в которые одна или несколько прикладных программ записывают свои звуковые данные; а целью микшера является один или несколько выходных портов.

Что такое линия?

Метафора физического микшерного пульта также полезна для понимания концепции линии Java Sound API.

Линия - это элемент «конвейера» цифрового звука, то есть путь для передачи звука в систему или из нее. Обычно линия - это путь в микшер или из него (хотя технически сам микшер также является своего рода линией).

Порты аудиовхода и вывода - линейные. Они аналогичны микрофонам и динамикам, подключенным к физической микшерной консоли. Другой вид линии - это путь к данным, по которому прикладная программа может получать входной звук от микшера или отправлять выходной звук на него. Эти пути данных аналогичны дорожкам многодорожечного записывающего устройства, подключенного к физической микшерной консоли.

Одно различие между линиями в Java Sound API и линиями физического микшера состоит в том, что аудиоданные, проходящие через линию в Java Sound API, могут быть монофоническими или многоканальными (например, стерео). Напротив, каждый из входов и выходов физического микшера обычно представляет собой один канал звука. Чтобы получить два или более каналов вывода от физического микшера, обычно используются два или более физических выхода (по крайней мере, в случае аналогового звука; гнездо цифрового вывода часто является многоканальным). В Java Sound API количество каналов в линии определяется AudioFormat данных, которые в данный момент проходят через линию.

Линии в конфигурации аудиовыхода

Давайте теперь рассмотрим некоторые конкретные виды линий и микшеров. На следующей диаграмме показаны различные типы линий в простой системе вывода звука, которая может быть частью реализации Java Sound API:

Possible configuration of lines for audio output

Возможная конфигурация линий для аудиовыхода

В этом примере прикладная программа получила доступ к некоторым доступным входам микшера аудиовхода: одному или нескольким клипам и линиям исходных данных. Клип - это вход микшера (своего рода линия), в который вы можете загружать аудиоданные перед воспроизведением; линия исходных данных - это вход микшера, который принимает поток аудиоданных в реальном времени. Прикладная программа предварительно загружает аудиоданные из звукового файла в клипы. Затем он помещает другие аудиоданные в линии исходных данных, буфер за раз. Микшер считывает данные со всех этих линий, каждая из которых может иметь свои собственные регуляторы реверберации, усиления и панорамирования, и смешивает сухие аудиосигналы с влажным (реверберированным) миксом. Микшерный пульт подает окончательный выходной сигнал на один или несколько выходных портов, таких как динамик, разъем для наушников и разъем линейного выхода.

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

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

Линии в конфигурации аудиовхода

Простая система аудиовхода может быть похожей:

Possible configuration of lines for audio input

Возможная конфигурация линий для аудиовхода

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

Иерархия линейного интерфейса

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

Line interface hierarchy

Иерархия линейного интерфейса

Базовый интерфейс Line описывает минимальную функциональность, общую для всех линий:

  • Элементы управления Линии данных и порты часто имеют набор элементов управления, которые влияют на аудиосигнал, проходящий по линии. Java Sound API определяет классы управления, которые можно использовать для управления такими аспектами звука, как: усиление (которое влияет на громкость сигнала в децибелах), панорамирование (которое влияет на позиционирование звука вправо-влево, реверберация (которая добавляет к звуку реверберацию). имитировать различные виды акустики комнаты) и частоту дискретизации (которая влияет на скорость воспроизведения, а также на высоту звука).
  • Статус «Открыто» или «Закрыто». Успешное открытие линии гарантирует выделение ресурсов линии. У микшера есть конечное количество линий, поэтому в какой-то момент несколько прикладных программ (или одна и та же) могут соперничать за использование линий микшера. Закрытие линии означает, что теперь можно освободить любые ресурсы, используемые линией.
  • События Линия генерирует события, когда открывается или закрывается. Подынтерфейсы Line могут вводить другие типы событий. Когда линия генерирует событие, событие отправляется всем зарегистрированным объектам для «прослушивания» событий в этой линии. Прикладная программа может создавать эти объекты, регистрировать их для прослушивания событий линии и реагировать на события по желанию.

Теперь мы исследуем подынтерфейсы интерфейса Line.

Ports - это простые линии для ввода или вывода звука на аудиоустройства или от них. Как упоминалось ранее, наиболее распространенными типами портов являются микрофон, линейный вход, привод CD-ROM, динамик, наушники и линейный выход.

Интерфейс Mixer , конечно же, представляет собой микшер, который, как мы видели, представляет собой аппаратное или программное устройство. Интерфейс Mixer предоставляет методы для получения линий микшера. К ним относятся  линии источников, которые подают звук в микшер, и целевые линии, на которые микшер передает свой смешанный звук. Для микшера аудиовхода  линиями источников являются входные порты, такие как вход микрофона, а целевыми линиями являются TargetDataLines (описанные ниже), которые доставляют звук в прикладную программу. С другой стороны, для микшера аудиовыхода линии источников  - это Clips или SourceDataLines (описанные ниже), в которые прикладная программа передает аудиоданные, а целевые линии - это выходные порты, такие как динамик.

Mixer определяется как имеющий одну или несколько исходных линий и одну или несколько целевых линий. Обратите внимание, что это определение означает, что микшеру не обязательно смешивать данные; он может иметь только одну исходную линию. API  Mixer предназначен для охвата множества устройств, но в типичном случае поддерживается смешивание.

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

Общий интерфейс Line не предоставляет средств для запуска и остановки воспроизведения или записи. Для этого вам понадобится линия передачи данных. Интерфейс DataLine предоставляет следующие дополнительные функции, связанные с мультимедиа, помимо функций Line:

  • Аудиоформат Каждая линия данных имеет аудиоформат, связанный с ее потоком данных.
  • Позиция носителя линии данных может сообщать о своем текущем положении на носителе, выраженном в кадрах выборки. Он представляет собой количество образцов кадров, захваченных или визуализированных из линии данных с момента ее открытия.
  • Размер буфера Это размер внутреннего буфера линии данных в байтах. Для исходной линии  данных внутренний буфер - это буфер, в который могут быть записаны данные, а для целевой линии данных - это буфер, из которого можно читать данные.
  • Уровень (текущая амплитуда звукового сигнала)
  • Запуск и остановка воспроизведения или захвата
  • Пауза и возобновление воспроизведения или захвата
  • Очистить (удалить необработанные данные из очереди)
  • Слить (блокировать до тех пор, пока все необработанные данные будут удалены из очереди, а буфер линии данных не станет пустым)
  • Активный статус - Линия данных считается активной, если она занята активным представлением или захватом аудиоданных в или из микшера.
  • События События START и STOP создаются, когда начинается или останавливается активное представление или захват данных из или в линию данных.

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

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

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

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

 

Предыдущая Следующая