Использование 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 веб-аудио довольно мощный и предоставляет множество функций, которые обычно встречаются только в профессиональном аудио программном обеспечении. Тот факт, что все это доступно "из коробки" в большинстве браузеров, довольно удивительно, и я с нетерпением жду возможности изучить другие его возможности. Удачного кодирования!