Web Audio и объёмный звуковой ландшафт: реализация

Рассказывает Si Robertson


В этом руководстве мы создадим простой Web Audio API для воспроизведения звуков в объёмном пространстве, который можно использовать в интерактивных приложениях с эффектом погружения.

Это вторая и последняя часть этого руководства. Если вы ещё не прочитали первую часть руководства, вам стоит это сделать: в ней разбираются принципы работы основных элементов Web Audio.

Демонстрация

Прежде чем мы начнём, вот небольшая демка, использующая упрощённый API, о котором пойдёт речь. Звуки (представленные квадратиками) позиционируются случайным образом и воспроизводятся при помощи функции HRTF, предоставляемой Web Audio.

Обзор

Поскольку упрощённый API (AudioPlayer) уже был создан и доступен для загрузки, мы внимательно ознакомимся с AudioPlayer API и его кодом.

AudioPlayer

Класс AudioPlayer содержит наш API и внедрен в объект window , а также в стандартные классы Web Audio, но только если Web Audio поддерживается браузером. Это значит, что мы должны удостовериться в существовании класса, прежде чем пытаться работать с ним.

Мы могли бы попробовать создать новый объект AudioPlayer внутри try...catch, но простая проверка тоже прекрасно работает.

За кадром: audioPlayer создаёт новые объекты AudioContext и AudioGainNode и подключает объект GainNode к ноде destination, внедрённой в объект AudioContext.

При создании и воспроизведении звуки будут подключены к ноде m_gain, что позволит нам контролировать их громкость.

audioPlayer также конфигурирует listener, внедрённый в m_context, таким образом, чтобы его система координат соответствовала в WebGL. Ось z направлена из экрана, ось y — вверх, ось x — вправо.

Позиция listener — всегда ноль; он расположен в центре координат.

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

Набор поддерживаемых звуковых форматов зависит от браузера. Например, Chrome и Firefox поддерживают OGG Vorbis, а IE — нет. Все три браузера поддерживают MP3, но проблемой MP3 является отсутствие возможности бесшовно зацикливать аудио, которая есть в OGG Vorbis.

Вызывая функцию load(...) несколько раз, audioPlayer создает очередь запросов и загружает их по очереди. Когда все звуки загружены и декодированы, вызывается хэндлер onloadcomplete.

За кадром: audioPlayer использует один объект XMLHttpRequest для загрузки звуков. responseType запроса установлен в "arraybuffer", и, когда файл загружен, буфер отправляется в m_context для декодирования.

Если файл был успешно загружен и декодирован, audioPlayer либо загрузит следующий файл в очереди, либо даст знать, что все файлы загружены.

Теперь, когда мы загрузили звуковые файлы, мы можем создавать и воспроизводить звуки. Сначала мы должны дать команду audioPlayer создать звуки, что можно сделать, используя функцию create(...), внедрённую в audioPlayer.

Мы можем создавать сколько угодно звуков, даже если у нас есть всего один звуковой файл.

Путь, передаваемый функции create(...), говорит audioPlayer, какой файл должен использовать созданный звук. Если при вызове create(...) соответствующий файл не был загружен, будет выброшена ошибка выполнения.

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

После создания одного или нескольких звуков мы можем воспроизводить их в любое время. Для этого мы используем функцию play(...), внедрённую в audioPlayer.

Для того, чтобы понять, нужно ли зациклить звук, мы можем также передать функции play(...) булевскую величину. Если она равна true, звук будет повторяться до принудительного выключения.

Для остановки воспроизведения используется функция stop(...).

Функция isPlaying(...) показывает, воспроизводится ли сейчас тот или иной звук.

За кадром: audioPlayer приходится делать немало работы для воспроизведения звука из-за модульной структуры Web Audio. При получения запроса на воспроизведение звука audioPlayer создаёт новые объекты AudioSourceBufferNode и PannerNode, настраивает и подключает их, а затем подключает звук к ноде m_gain. К счастью, Web Audio хорошо оптимизирован, поэтому создание и настройка новых аудиоузлов несильно нагружает систему.

Воспроизведение звуков — штука, безусловно, полезная, но назначением audioPlayer является воспроизведение звуков в объёмной системе координат, поэтому сперва нам нужно задать позиции звуков. audioPlayer содержит для этого несколько функций.

Позиционирование звуков

  • Функции setX(...) и getX(...), внедрённые в audioPlayer, используются для установки и получения координаты звука по оси x.
  • Функции setY(...) и getY(...) используются для установки и получения координаты звука по оси y.
  • Функции setZ(...) и getZ(...) используются для установки и получения координаты звука по оси z.
  • И наконец, функция setPosition(...) используется для установки координат звука в пространстве.
Чем дальше звук от центра, тем он тише. На расстоянии 10000 (стандарт Web Audio) громкость будет равна нулю.

Громкость

Мы можем управлять громкостью звуков, используя функции setVolume(...) и getVolume(...) , внедренные в audioPlayer.

Функция setVolume(...) имеет второй параметр, который использует для постепенного затихания звука. Например, чтобы звук затих за две секунды, мы можем сделать следующее:

Это используется в демке для плавного затухания звуков.

За кадром: audioPlayer просто отдает ноде m_gain команду линейно изменять значение gain.

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

Заключение

В этом руководстве мы взглянули на способ создания простого Web Audio API, который используется для воспроизведения звуков в трёхмерной системе координат.

Файлы AudioPlayer и демки доступны на GitHub. Исходники снабжены хорошими комментариями, поэтому в них стоит заглянуть.

Оригинал: tuts+