Использование API веб-аудио: где программирование встречается со звуковой инженерией

Прежде чем я обнаружил свою любовь к программированию, я пошел в школу по записи музыки и много узнал об обработке звука. Когда я только начал учиться программировать, мне очень хотелось объединить два моих интереса в одном проекте. Недавно я создавал барабанный секвенсор с помощью React и немного узнал об API веб-аудио. Изучая этот проект, я обнаружил, что во время проекта было много моментов, из-за которых я был рад иметь опыт работы со звуком.

Начиная

Чтобы начать работу с API веб-аудио, вам необходимо инициализировать AudioContext. AudioContext - это объект, который будет содержать все необходимое для работы с API веб-аудио. Это даст нам доступ ко всем функциям и функциям, которые нам понадобятся для декодирования, управления и воспроизведения звуков. Чтобы настроить AudioContext, используйте приведенный ниже код. Первая строка - обеспечить более широкую поддержку браузером.

Загрузка предварительно записанных звуков

Есть два основных способа воспроизведения предварительно записанных звуков в веб-браузере. Самый простой способ - использовать тег <audio>. Этот метод работает лучше всего, если вам нужен только базовый контроль над воспроизводимым звуком. Если вы хотите обработать звук перед его воспроизведением или для вашего приложения важна точность воспроизведения, тег <audio> - это не тот путь, по которому вы хотите идти.

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

Другой вариант воспроизведения предварительно записанных звуков - это предварительная буферизация звука и сохранение буферизованного звука в переменной, где он будет готов к воспроизведению при необходимости. Для этого вам нужно будет получить данные заранее, используя fetch() или XMLHttpRequest(). (Я предпочитаю использовать fetch(), поэтому я подробно расскажу об этом процессе, но процесс XMLHttpRequest() аналогичен, и я приведу пример ниже, если вы предпочитаете.) В ответе от fetch() вызовите arrayBuffer(), чтобы поместить ответ в arrayBuffer . В arrayBuffer вы можете декодировать данные, используя decodeAudioData(), который предоставляется audioContext. Затем вы можете сохранить эти данные в переменной для дальнейшего использования. См. Ниже примеры использования fetch() или XMLHttpRequest():

Воспроизведение звуков

Теперь, когда мы буферизовали наш звук, мы, вероятно, захотим воспроизвести его, чтобы пользователь мог слышать звук. Для этого нам нужно создать буферный источник и подключить его к динамикам пользователя. Мы можем использовать функцию createBufferSource(), предоставленную audioContext, для создания источника буфера. Это создает audioNode, которым мы можем управлять, используя различные звуковые эффекты, или мы можем подключаться к пользовательским динамикам, чтобы воспроизводить звук как есть. А пока мы подключим audioNode к пользовательским динамикам без каких-либо манипуляций со звуком, используя функцию connect(). См. Пример ниже:

Установление связей

В звуковой инженерии существует понятие, называемое потоком сигналов. Идея заключается в том, что звуковой сигнал следует по пути от своего источника (инструмент, микрофон, синтезатор и т. Д.) Через несколько аудиопроцессоров (микрофонные предусилители, эквалайзер, реверберация и т. Д.) И, наконец, попадает в динамики. Источник должен быть подключен ко входу аудиопроцессора, а затем выходной сигнал аудиопроцессора направляется на следующий процессор или на динамики. API веб-аудио работает аналогичным образом. Источники звука (аудиобуфер, генераторы или потоковое аудио) подключаются к различным аудиопроцессорам (усиление, панорамирование, фильтры, реверберация), а от этих аудиопроцессоров они подключаются к пользовательским динамикам (audioContext.destination).

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

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

Звуковые манипуляции

Поздравляю. Теперь вы можете воспроизводить звуки в веб-браузере. Теперь давайте обработаем эти звуки до того, как пользователь их услышит. Самая распространенная манипуляция со звуком, которую вы хотели бы использовать, - это усиление. Усиление - это звуковой термин, обозначающий громкость. Чтобы добавить к своим звукам регулятор громкости, вам нужно создать узел усиления и подключить к нему свой audioBuffer, а затем подключить gainNode к audioContext.destination.

Включите его

Чтобы добавить узел усиления, используйте функцию createGain(), предоставленную audioContext, и сохраните ее в переменной. Затем установите значение узла усиления, используя gain.value и присвоив ему значение. Значение 1 не изменит звук. Все, что ниже 1, приведет к уменьшению громкости звука, а 0 означает отсутствие звука. Верхний предел находится где-то между 3 и 4, но я бы не рекомендовал слишком много выше 1,5, чтобы избежать обрезки и искажения (если только источник звука не является особенно низким по громкости). См. Ниже нашу обновленную функцию playSample():

Звуковое пространство

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

В API веб-аудио есть 2 способа обработки пространственного звучания: PannerNode и StereoPannerNode. Панорамирование - это звуковой термин для обозначения пространственного звучания. StereoPannerNode часто бывает достаточно для большинства ситуаций, когда вам нужно расположить звук. Он ограничен стереопозиционированием (установка с двумя динамиками). PannerNode позволяет выполнять более сложную пространственную настройку, такую ​​как размещение в более крупных динамиках (четырехъядерный, 5.1), позиционирование звуков, перемещающихся во времени, перемещение слушателя по отношению к звукам, добавление эффекта Доплера (представьте себе звук проезжающей мимо пожарной машины с его сирена) и многие другие.

Поскольку эта статья предназначена для людей, которые плохо знакомы с API веб-аудио, я буду объяснять только более простые StereoPannerNode. Настройка StereoPannerNode очень похожа на настройку GainNode. AudioContext дает нам еще одну функцию для создания стерео панорамирования, createStereoPanner(). Сохраните это в переменной, а затем установите значение панорамирования, задав pan.value желаемое значение. Это значение может находиться в диапазоне от -1 до 1, где -1 - крайний левый угол, 1 - крайний правый угол, а 0 - центральное положение. После создания StereoPannerNode и присвоения ему значения вы можете подключить его к источнику звука с помощью функции connect(). Я добавил панорамирование к нашей функции playSample() ранее:

Больше аудио исследований

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

Этого должно быть достаточно, чтобы вы начали добавлять звуки в свои веб-приложения. API веб-аудио довольно мощный и предоставляет множество функций, которые обычно встречаются только в профессиональном аудио программном обеспечении. Тот факт, что все это доступно "из коробки" в большинстве браузеров, довольно удивительно, и я с нетерпением жду возможности изучить другие его возможности. Удачного кодирования!