До появления элемента HTML5 <audio>
для нарушения тишины в сети требовался Flash или другой плагин. Хотя аудио в Интернете больше не требует плагина, тег audio накладывает существенные ограничения на реализацию сложных игр и интерактивных приложений.
API веб-аудио — это API JavaScript высокого уровня для обработки и синтеза звука в веб-приложениях. Цель этого API — включить возможности, имеющиеся в современных игровых звуковых движках, а также некоторые задачи микширования, обработки и фильтрации, которые имеются в современных настольных приложениях для создания звука. Далее следует краткое введение в использование этого мощного API.
Начало работы с AudioContext
AudioContext предназначен для управления и воспроизведения всех звуков. Чтобы создать звук с помощью API веб-аудио, создайте один или несколько источников звука и подключите их к назначению звука, предоставленному экземпляром AudioContext
. Это соединение не обязательно должно быть прямым и может проходить через любое количество промежуточных AudioNodes , которые действуют как модули обработки аудиосигнала. Более подробно эта маршрутизация описана в спецификации Web Audio.
Один экземпляр AudioContext
может поддерживать несколько звуковых входов и сложные аудиографы, поэтому нам понадобится только один из них для каждого создаваемого нами аудиоприложения.
Следующий фрагмент создает AudioContext
:
var context;
window.addEventListener('load', init, false);
function init() {
try {
context = new AudioContext();
}
catch(e) {
alert('Web Audio API is not supported in this browser');
}
}
Для более старых браузеров на основе WebKit используйте префикс webkit
, как и в случае с webkitAudioContext
.
Многие интересные функции Web Audio API, такие как создание AudioNodes и декодирование данных аудиофайлов, являются методами AudioContext
.
Загрузка звуков
API веб-аудио использует AudioBuffer для звуков короткой и средней длины. Основной подход заключается в использовании XMLHttpRequest для получения звуковых файлов.
API поддерживает загрузку данных аудиофайлов в нескольких форматах, таких как WAV, MP3, AAC, OGG и других . Поддержка браузерами различных аудиоформатов различается .
Следующий фрагмент демонстрирует загрузку образца звука:
var dogBarkingBuffer = null;
var context = new AudioContext();
function loadDogSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
request.send();
}
Данные аудиофайла являются двоичными (не текстовыми), поэтому мы устанавливаем тип responseType
запроса на 'arraybuffer'
. Дополнительные сведения о ArrayBuffers
см. в этой статье о XHR2 .
После получения (некодированных) данных аудиофайла их можно сохранить для последующего декодирования или можно декодировать сразу с помощью метода AudioContext decodeAudioData()
. Этот метод принимает ArrayBuffer
данных аудиофайла, хранящихся в request.response
, и декодирует его асинхронно (не блокируя основной поток выполнения JavaScript).
Когда decodeAudioData()
завершается, он вызывает функцию обратного вызова, которая предоставляет декодированные аудиоданные PCM в виде AudioBuffer
.
Воспроизведение звуков

Как только один или несколько AudioBuffers
загружены, мы готовы воспроизводить звуки. Предположим, мы только что загрузили AudioBuffer
со звуком лая собаки и загрузка завершилась. Затем мы можем воспроизвести этот буфер с помощью следующего кода.
var context = new AudioContext();
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.noteOn(0); // play the source now
}
Эту функцию playSound()
можно вызывать каждый раз, когда кто-то нажимает клавишу или щелкает что-нибудь мышью.
Функция noteOn(time)
позволяет легко запланировать точное воспроизведение звука для игр и других приложений, критичных по времени. Однако, чтобы это планирование работало правильно, убедитесь, что ваши звуковые буферы предварительно загружены.
Абстрагирование API веб-аудио
Конечно, было бы лучше создать более общую систему загрузки, которая не была бы жестко запрограммирована на загрузку этого конкретного звука. Существует множество подходов к работе со звуками короткой и средней длины, которые могут использоваться в аудиоприложении или игре — вот один из способов использования BufferLoader (не является частью веб-стандарта).
Ниже приведен пример использования класса BufferLoader
. Давайте создадим два AudioBuffers
; и, как только они загрузятся, давайте одновременно их воспроизведем.
window.onload = init;
var context;
var bufferLoader;
function init() {
context = new AudioContext();
bufferLoader = new BufferLoader(
context,
[
'../sounds/hyper-reality/br-jam-loop.wav',
'../sounds/hyper-reality/laughter.wav',
],
finishedLoading
);
bufferLoader.load();
}
function finishedLoading(bufferList) {
// Create two sources and play them both together.
var source1 = context.createBufferSource();
var source2 = context.createBufferSource();
source1.buffer = bufferList[0];
source2.buffer = bufferList[1];
source1.connect(context.destination);
source2.connect(context.destination);
source1.noteOn(0);
source2.noteOn(0);
}
Работа со временем: ритмичное воспроизведение звуков
API веб-аудио позволяет разработчикам точно планировать воспроизведение. Чтобы продемонстрировать это, давайте настроим простой ритм-трек. Вероятно, наиболее широко известным паттерном ударной установки является следующий:

в котором хэт исполняется каждую восьмую ноту, а кик и малый барабан исполняются попеременно каждую четверть, в размере 4/4.
Предположим, мы загрузили буферы kick
, snare
и hihat
, код для этого прост:
for (var bar = 0; bar < 2; bar++) {
var time = startTime + bar * 8 * eighthNoteTime;
// Play the bass (kick) drum on beats 1, 5
playSound(kick, time);
playSound(kick, time + 4 * eighthNoteTime);
// Play the snare drum on beats 3, 7
playSound(snare, time + 2 * eighthNoteTime);
playSound(snare, time + 6 * eighthNoteTime);
// Play the hi-hat every eighth note.
for (var i = 0; i < 8; ++i) {
playSound(hihat, time + i * eighthNoteTime);
}
}
Здесь мы делаем только один повтор вместо неограниченного цикла, который мы видим в нотах. Функция playSound
— это метод, который воспроизводит буфер в указанное время следующим образом:
function playSound(buffer, time) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.noteOn(time);
}
Изменение громкости звука
Одна из самых основных операций, которые вы, возможно, захотите выполнить со звуком, — это изменение его громкости. Используя API веб-аудио, мы можем направить наш источник к месту назначения через AudioGainNode , чтобы управлять громкостью:

Эту настройку соединения можно осуществить следующим образом:
// Create a gain node.
var gainNode = context.createGainNode();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);
После настройки графика вы можете программно изменить громкость, манипулируя параметром gainNode.gain.value
следующим образом:
// Reduce the volume.
gainNode.gain.value = 0.5;
Переход между двумя звуками
Теперь предположим, что у нас немного более сложный сценарий, в котором мы воспроизводим несколько звуков, но хотим плавно затухать между ними. Это обычный случай в диджейском приложении, где у нас есть два проигрывателя и мы хотим иметь возможность панорамировать от одного источника звука к другому.
Это можно сделать с помощью следующего аудиографика:

Чтобы настроить это, мы просто создаем два AudioGainNodes и подключаем каждый источник через узлы, используя что-то вроде этой функции:
function createSource(buffer) {
var source = context.createBufferSource();
// Create a gain node.
var gainNode = context.createGainNode();
source.buffer = buffer;
// Turn on looping.
source.loop = true;
// Connect source to gain.
source.connect(gainNode);
// Connect gain to destination.
gainNode.connect(context.destination);
return {
source: source,
gainNode: gainNode
};
}
Равномерное плавное затухание
Наивный метод линейного кроссфейда демонстрирует провал громкости при панорамировании между сэмплами.

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

Плавное затухание плейлиста
Еще одно распространенное приложение кроссфейдера — приложение музыкального проигрывателя. Когда песня меняется, мы хотим заглушить текущий трек и добавить новый, чтобы избежать резкого перехода. Для этого запланируйте переход в будущее. Хотя мы могли бы использовать setTimeout
для такого планирования, это неточно . С помощью API веб-аудио мы можем использовать интерфейс AudioParam для планирования будущих значений таких параметров, как значение усиления AudioGainNode
.
Таким образом, имея список воспроизведения, мы можем переходить между треками, запланировав уменьшение усиления для воспроизводимого в данный момент трека и увеличение усиления для следующего, и то и другое немного раньше, чем закончится воспроизведение текущего трека:
function playHelper(bufferNow, bufferLater) {
var playNow = createSource(bufferNow);
var source = playNow.source;
var gainNode = playNow.gainNode;
var duration = bufferNow.duration;
var currTime = context.currentTime;
// Fade the playNow track in.
gainNode.gain.linearRampToValueAtTime(0, currTime);
gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
// Play the playNow track.
source.noteOn(0);
// At the end of the track, fade it out.
gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
// Schedule a recursive track change with the tracks swapped.
var recurse = arguments.callee;
ctx.timer = setTimeout(function() {
recurse(bufferLater, bufferNow);
}, (duration - ctx.FADE_TIME) - 1000);
}
API веб-аудио предоставляет удобный набор методов RampToValue
для постепенного изменения значения параметра, например linearRampToValueAtTime
и exponentialRampToValueAtTime
.
Хотя функцию времени перехода можно выбрать из встроенных линейных и экспоненциальных функций (как указано выше), вы также можете указать свою собственную кривую значений через массив значений с помощью функции setValueCurveAtTime
.
Применение простого эффекта фильтра к звуку

API веб-аудио позволяет передавать звук из одного аудиоузла в другой, создавая потенциально сложную цепочку процессоров для добавления сложных эффектов к вашим звуковым формам.
Один из способов сделать это — разместить BiquadFilterNode между источником звука и местом назначения. Этот тип аудиоузла может выполнять различные фильтры низкого порядка, которые можно использовать для создания графических эквалайзеров и даже более сложных эффектов, в основном связанных с выбором, какие части частотного спектра звука подчеркнуть, а какие приглушить.
Поддерживаемые типы фильтров:
- Фильтр нижних частот
- Фильтр верхних частот
- Полосовой фильтр
- Фильтр низкой полки
- Фильтр с высокой полкой
- Пиковый фильтр
- Режекторный фильтр
- Все проходной фильтр
И все фильтры включают параметры, определяющие некоторую величину усиления , частоту применения фильтра и коэффициент качества. Фильтр нижних частот сохраняет нижний частотный диапазон, но отбрасывает высокие частоты. Точка обрыва определяется значением частоты, а добротность безразмерна и определяет форму графика. Усиление влияет только на определенные фильтры, такие как фильтры нижних частот и пиковые фильтры, но не на этот фильтр нижних частот.
Давайте настроим простой фильтр нижних частот, чтобы извлекать из звукового сэмпла только основы:
// Create the filter
var filter = context.createBiquadFilter();
// Create the audio graph.
source.connect(filter);
filter.connect(context.destination);
// Create and specify parameters for the low-pass filter.
filter.type = 0; // Low-pass filter. See BiquadFilterNode docs
filter.frequency.value = 440; // Set cutoff to 440 HZ
// Playback the sound.
source.noteOn(0);
В общем, регуляторы частоты необходимо настроить так, чтобы они работали в логарифмическом масштабе, поскольку сам человеческий слух работает по тому же принципу (то есть A4 — это 440 Гц, а A5 — 880 Гц). Дополнительные сведения см. в функции FilterSample.changeFrequency
по ссылке на исходный код выше.
Наконец, обратите внимание, что пример кода позволяет подключать и отключать фильтр, динамически изменяя график AudioContext. Мы можем отключить AudioNodes от графа, вызвав node.disconnect(outputNumber)
. Например, чтобы перенаправить граф с прохождения через фильтр на прямое соединение, мы можем сделать следующее:
// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);
Дальнейшее прослушивание
Мы рассмотрели основы API, включая загрузку и воспроизведение аудиосэмплов. Мы построили аудиографики с узлами усиления и фильтрами, а также запланировали настройки звуков и параметров звука, чтобы включить некоторые распространенные звуковые эффекты. На этом этапе вы готовы приступить к созданию замечательных веб-аудиоприложений!
Если вы ищете вдохновение, многие разработчики уже создали отличные работы, используя API веб-аудио. Некоторые из моих любимых включают в себя:
- AudioJedit — инструмент для склейки звука в браузере, использующий постоянные ссылки SoundCloud.
- ToneCraft — звуковой секвенсор, в котором звуки создаются путем наложения 3D-блоков.
- Plink — игра для совместного создания музыки с использованием веб-аудио и веб-сокетов.
До появления элемента HTML5 <audio>
для нарушения тишины в сети требовался Flash или другой плагин. Хотя аудио в Интернете больше не требует плагина, тег audio накладывает существенные ограничения на реализацию сложных игр и интерактивных приложений.
API веб-аудио — это API JavaScript высокого уровня для обработки и синтеза звука в веб-приложениях. Цель этого API — включить возможности, имеющиеся в современных игровых звуковых движках, а также некоторые задачи микширования, обработки и фильтрации, которые имеются в современных настольных приложениях для создания звука. Далее следует краткое введение в использование этого мощного API.
Начало работы с AudioContext
AudioContext предназначен для управления и воспроизведения всех звуков. Чтобы создать звук с помощью API веб-аудио, создайте один или несколько источников звука и подключите их к назначению звука, предоставленному экземпляром AudioContext
. Это соединение не обязательно должно быть прямым и может проходить через любое количество промежуточных AudioNodes , которые действуют как модули обработки аудиосигнала. Более подробно эта маршрутизация описана в спецификации Web Audio.
Один экземпляр AudioContext
может поддерживать несколько звуковых входов и сложные аудиографы, поэтому нам понадобится только один из них для каждого создаваемого нами аудиоприложения.
Следующий фрагмент создает AudioContext
:
var context;
window.addEventListener('load', init, false);
function init() {
try {
context = new AudioContext();
}
catch(e) {
alert('Web Audio API is not supported in this browser');
}
}
Для более старых браузеров на основе WebKit используйте префикс webkit
, как и в случае с webkitAudioContext
.
Многие интересные функции Web Audio API, такие как создание AudioNodes и декодирование данных аудиофайлов, являются методами AudioContext
.
Загрузка звуков
API веб-аудио использует AudioBuffer для звуков короткой и средней длины. Основной подход заключается в использовании XMLHttpRequest для получения звуковых файлов.
API поддерживает загрузку данных аудиофайлов в нескольких форматах, таких как WAV, MP3, AAC, OGG и других . Поддержка браузерами различных аудиоформатов различается .
Следующий фрагмент демонстрирует загрузку образца звука:
var dogBarkingBuffer = null;
var context = new AudioContext();
function loadDogSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
request.send();
}
Данные аудиофайла являются двоичными (не текстовыми), поэтому мы устанавливаем тип responseType
запроса на 'arraybuffer'
. Дополнительные сведения о ArrayBuffers
см. в этой статье о XHR2 .
После получения (некодированных) данных аудиофайла их можно сохранить для последующего декодирования или можно декодировать сразу с помощью метода AudioContext decodeAudioData()
. Этот метод принимает ArrayBuffer
данных аудиофайла, хранящихся в request.response
, и декодирует его асинхронно (не блокируя основной поток выполнения JavaScript).
Когда decodeAudioData()
завершается, он вызывает функцию обратного вызова, которая предоставляет декодированные аудиоданные PCM в виде AudioBuffer
.
Воспроизведение звуков

Как только один или несколько AudioBuffers
загружены, мы готовы воспроизводить звуки. Предположим, мы только что загрузили AudioBuffer
со звуком лая собаки и загрузка завершилась. Затем мы можем воспроизвести этот буфер с помощью следующего кода.
var context = new AudioContext();
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.noteOn(0); // play the source now
}
Эту функцию playSound()
можно вызывать каждый раз, когда кто-то нажимает клавишу или щелкает что-нибудь мышью.
Функция noteOn(time)
позволяет легко запланировать точное воспроизведение звука для игр и других приложений, критичных по времени. Однако, чтобы это планирование работало правильно, убедитесь, что ваши звуковые буферы предварительно загружены.
Абстрагирование API веб-аудио
Конечно, было бы лучше создать более общую систему загрузки, которая не была бы жестко запрограммирована на загрузку этого конкретного звука. Существует множество подходов к работе со звуками короткой и средней длины, которые могут использоваться в аудиоприложении или игре — вот один из способов использования BufferLoader (не является частью веб-стандарта).
Ниже приведен пример использования класса BufferLoader
. Давайте создадим два AudioBuffers
; и, как только они загрузятся, давайте одновременно их воспроизведем.
window.onload = init;
var context;
var bufferLoader;
function init() {
context = new AudioContext();
bufferLoader = new BufferLoader(
context,
[
'../sounds/hyper-reality/br-jam-loop.wav',
'../sounds/hyper-reality/laughter.wav',
],
finishedLoading
);
bufferLoader.load();
}
function finishedLoading(bufferList) {
// Create two sources and play them both together.
var source1 = context.createBufferSource();
var source2 = context.createBufferSource();
source1.buffer = bufferList[0];
source2.buffer = bufferList[1];
source1.connect(context.destination);
source2.connect(context.destination);
source1.noteOn(0);
source2.noteOn(0);
}
Работа со временем: ритмичное воспроизведение звуков
API веб-аудио позволяет разработчикам точно планировать воспроизведение. Чтобы продемонстрировать это, давайте настроим простой ритм-трек. Вероятно, наиболее широко известным паттерном ударной установки является следующий:

в котором хэт исполняется каждую восьмую ноту, а кик и малый барабан исполняются попеременно каждую четверть, в размере 4/4.
Предположим, мы загрузили буферы kick
, snare
и hihat
, код для этого прост:
for (var bar = 0; bar < 2; bar++) {
var time = startTime + bar * 8 * eighthNoteTime;
// Play the bass (kick) drum on beats 1, 5
playSound(kick, time);
playSound(kick, time + 4 * eighthNoteTime);
// Play the snare drum on beats 3, 7
playSound(snare, time + 2 * eighthNoteTime);
playSound(snare, time + 6 * eighthNoteTime);
// Play the hi-hat every eighth note.
for (var i = 0; i < 8; ++i) {
playSound(hihat, time + i * eighthNoteTime);
}
}
Здесь мы делаем только один повтор вместо неограниченного цикла, который мы видим в нотах. Функция playSound
— это метод, который воспроизводит буфер в указанное время следующим образом:
function playSound(buffer, time) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.noteOn(time);
}
Изменение громкости звука
Одна из самых основных операций, которые вы, возможно, захотите выполнить со звуком, — это изменение его громкости. Используя API веб-аудио, мы можем направить наш источник к месту назначения через AudioGainNode , чтобы управлять громкостью:

Эту настройку соединения можно осуществить следующим образом:
// Create a gain node.
var gainNode = context.createGainNode();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);
После настройки графика вы можете программно изменить громкость, манипулируя параметром gainNode.gain.value
следующим образом:
// Reduce the volume.
gainNode.gain.value = 0.5;
Переход между двумя звуками
Теперь предположим, что у нас немного более сложный сценарий, в котором мы воспроизводим несколько звуков, но хотим плавно затухать между ними. Это обычный случай в диджейском приложении, где у нас есть два проигрывателя и мы хотим иметь возможность панорамировать от одного источника звука к другому.
Это можно сделать с помощью следующего аудиографика:

Чтобы настроить это, мы просто создаем два AudioGainNodes и подключаем каждый источник через узлы, используя что-то вроде этой функции:
function createSource(buffer) {
var source = context.createBufferSource();
// Create a gain node.
var gainNode = context.createGainNode();
source.buffer = buffer;
// Turn on looping.
source.loop = true;
// Connect source to gain.
source.connect(gainNode);
// Connect gain to destination.
gainNode.connect(context.destination);
return {
source: source,
gainNode: gainNode
};
}
Равномерное плавное затухание
Наивный метод линейного кроссфейда демонстрирует провал громкости при панорамировании между сэмплами.

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

Плавное затухание плейлиста
Еще одно распространенное приложение кроссфейдера — приложение музыкального проигрывателя. Когда песня меняется, мы хотим заглушить текущий трек и добавить новый, чтобы избежать резкого перехода. Для этого запланируйте переход в будущее. Хотя мы могли бы использовать setTimeout
для такого планирования, это неточно . С помощью API веб-аудио мы можем использовать интерфейс AudioParam для планирования будущих значений таких параметров, как значение усиления AudioGainNode
.
Таким образом, имея список воспроизведения, мы можем переходить между треками, запланировав уменьшение усиления для воспроизводимого в данный момент трека и увеличение усиления для следующего, и то и другое немного раньше, чем закончится воспроизведение текущего трека:
function playHelper(bufferNow, bufferLater) {
var playNow = createSource(bufferNow);
var source = playNow.source;
var gainNode = playNow.gainNode;
var duration = bufferNow.duration;
var currTime = context.currentTime;
// Fade the playNow track in.
gainNode.gain.linearRampToValueAtTime(0, currTime);
gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
// Play the playNow track.
source.noteOn(0);
// At the end of the track, fade it out.
gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
// Schedule a recursive track change with the tracks swapped.
var recurse = arguments.callee;
ctx.timer = setTimeout(function() {
recurse(bufferLater, bufferNow);
}, (duration - ctx.FADE_TIME) - 1000);
}
API веб-аудио предоставляет удобный набор методов RampToValue
для постепенного изменения значения параметра, например linearRampToValueAtTime
и exponentialRampToValueAtTime
.
Хотя функцию времени перехода можно выбрать из встроенных линейных и экспоненциальных функций (как указано выше), вы также можете указать свою собственную кривую значений через массив значений с помощью функции setValueCurveAtTime
.
Применение простого эффекта фильтра к звуку

API веб-аудио позволяет передавать звук из одного аудиоузла в другой, создавая потенциально сложную цепочку процессоров для добавления сложных эффектов к вашим звуковым формам.
Один из способов сделать это — разместить BiquadFilterNode между источником звука и местом назначения. Этот тип аудиоузла может выполнять различные фильтры низкого порядка, которые можно использовать для создания графических эквалайзеров и даже более сложных эффектов, в основном связанных с выбором, какие части частотного спектра звука подчеркнуть, а какие приглушить.
Поддерживаемые типы фильтров:
- Фильтр нижних частот
- Фильтр верхних частот
- Полосовой фильтр
- Фильтр низкой полки
- Фильтр с высокой полкой
- Пиковый фильтр
- Режекторный фильтр
- Все проходной фильтр
И все фильтры включают параметры, определяющие некоторую величину усиления , частоту применения фильтра и коэффициент качества. Фильтр нижних частот сохраняет нижний частотный диапазон, но отбрасывает высокие частоты. Точка обрыва определяется значением частоты, а добротность безразмерна и определяет форму графика. Усиление влияет только на определенные фильтры, такие как фильтры нижних частот и пиковые фильтры, но не на этот фильтр нижних частот.
Давайте настроим простой фильтр нижних частот, чтобы извлекать из звукового сэмпла только основы:
// Create the filter
var filter = context.createBiquadFilter();
// Create the audio graph.
source.connect(filter);
filter.connect(context.destination);
// Create and specify parameters for the low-pass filter.
filter.type = 0; // Low-pass filter. See BiquadFilterNode docs
filter.frequency.value = 440; // Set cutoff to 440 HZ
// Playback the sound.
source.noteOn(0);
В общем, регуляторы частоты необходимо настроить так, чтобы они работали в логарифмическом масштабе, поскольку сам человеческий слух работает по тому же принципу (то есть A4 — это 440 Гц, а A5 — 880 Гц). Дополнительные сведения см. в функции FilterSample.changeFrequency
по ссылке на исходный код выше.
Наконец, обратите внимание, что пример кода позволяет подключать и отключать фильтр, динамически изменяя график AudioContext. Мы можем отключить AudioNodes от графа, вызвав node.disconnect(outputNumber)
. Например, чтобы перенаправить граф с прохождения через фильтр на прямое соединение, мы можем сделать следующее:
// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);
Дальнейшее прослушивание
Мы рассмотрели основы API, включая загрузку и воспроизведение аудиосэмплов. Мы построили аудиографики с узлами усиления и фильтрами, а также запланировали настройки звуков и параметров звука, чтобы включить некоторые распространенные звуковые эффекты. На этом этапе вы готовы приступить к созданию замечательных веб-аудиоприложений!
Если вы ищете вдохновение, многие разработчики уже создали отличные работы, используя API веб-аудио. Некоторые из моих любимых включают в себя:
- AudioJedit — инструмент для склейки звука в браузере, использующий постоянные ссылки SoundCloud.
- ToneCraft — звуковой секвенсор, в котором звуки создаются путем наложения 3D-блоков.
- Plink — игра для совместного создания музыки с использованием веб-аудио и веб-сокетов.
До появления элемента HTML5 <audio>
для нарушения тишины в сети требовался Flash или другой плагин. Хотя аудио в Интернете больше не требует плагина, тег audio накладывает существенные ограничения на реализацию сложных игр и интерактивных приложений.
API веб-аудио — это API JavaScript высокого уровня для обработки и синтеза звука в веб-приложениях. Цель этого API — включить возможности, имеющиеся в современных игровых звуковых движках, а также некоторые задачи микширования, обработки и фильтрации, которые имеются в современных настольных приложениях для создания звука. Далее следует краткое введение в использование этого мощного API.
Начало работы с AudioContext
AudioContext предназначен для управления и воспроизведения всех звуков. Чтобы создать звук с помощью API веб-аудио, создайте один или несколько источников звука и подключите их к назначению звука, предоставленному экземпляром AudioContext
. Это соединение не обязательно должно быть прямым и может проходить через любое количество промежуточных AudioNodes , которые действуют как модули обработки аудиосигнала. Более подробно эта маршрутизация описана в спецификации Web Audio.
Один экземпляр AudioContext
может поддерживать несколько звуковых входов и сложные аудиографы, поэтому нам понадобится только один из них для каждого создаваемого нами аудиоприложения.
Следующий фрагмент создает AudioContext
:
var context;
window.addEventListener('load', init, false);
function init() {
try {
context = new AudioContext();
}
catch(e) {
alert('Web Audio API is not supported in this browser');
}
}
Для более старых браузеров на основе WebKit используйте префикс webkit
, как и в случае с webkitAudioContext
.
Многие интересные функции Web Audio API, такие как создание AudioNodes и декодирование данных аудиофайлов, являются методами AudioContext
.
Загрузка звуков
API веб-аудио использует AudioBuffer для звуков короткой и средней длины. Основной подход заключается в использовании XMLHttpRequest для получения звуковых файлов.
API поддерживает загрузку данных аудиофайлов в нескольких форматах, таких как WAV, MP3, AAC, OGG и других . Поддержка браузерами различных аудиоформатов различается .
Следующий фрагмент демонстрирует загрузку образца звука:
var dogBarkingBuffer = null;
var context = new AudioContext();
function loadDogSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
request.send();
}
Данные аудиофайла являются двоичными (не текстовыми), поэтому мы устанавливаем тип responseType
запроса на 'arraybuffer'
. Дополнительные сведения о ArrayBuffers
см. в этой статье о XHR2 .
После получения (некодированных) данных аудиофайла их можно сохранить для последующего декодирования или можно декодировать сразу с помощью метода AudioContext decodeAudioData()
. Этот метод принимает ArrayBuffer
данных аудиофайла, хранящихся в request.response
, и декодирует его асинхронно (не блокируя основной поток выполнения JavaScript).
Когда decodeAudioData()
завершается, он вызывает функцию обратного вызова, которая предоставляет декодированные аудиоданные PCM в виде AudioBuffer
.
Воспроизведение звуков

Как только один или несколько AudioBuffers
загружены, мы готовы воспроизводить звуки. Предположим, мы только что загрузили AudioBuffer
со звуком лая собаки и загрузка завершилась. Затем мы можем воспроизвести этот буфер с помощью следующего кода.
var context = new AudioContext();
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.noteOn(0); // play the source now
}
Эту функцию playSound()
можно вызывать каждый раз, когда кто-то нажимает клавишу или щелкает что-нибудь мышью.
Функция noteOn(time)
позволяет легко запланировать точное воспроизведение звука для игр и других приложений, критичных по времени. Однако, чтобы это планирование работало правильно, убедитесь, что ваши звуковые буферы предварительно загружены.
Абстрагирование API веб-аудио
Конечно, было бы лучше создать более общую систему загрузки, которая не была бы жестко запрограммирована на загрузку этого конкретного звука. Существует множество подходов к работе со звуками короткой и средней длины, которые могут использоваться в аудиоприложении или игре — вот один из способов использования BufferLoader (не является частью веб-стандарта).
Ниже приведен пример использования класса BufferLoader
. Давайте создадим два AudioBuffers
; и, как только они загрузятся, давайте одновременно их воспроизведем.
window.onload = init;
var context;
var bufferLoader;
function init() {
context = new AudioContext();
bufferLoader = new BufferLoader(
context,
[
'../sounds/hyper-reality/br-jam-loop.wav',
'../sounds/hyper-reality/laughter.wav',
],
finishedLoading
);
bufferLoader.load();
}
function finishedLoading(bufferList) {
// Create two sources and play them both together.
var source1 = context.createBufferSource();
var source2 = context.createBufferSource();
source1.buffer = bufferList[0];
source2.buffer = bufferList[1];
source1.connect(context.destination);
source2.connect(context.destination);
source1.noteOn(0);
source2.noteOn(0);
}
Работа со временем: ритмичное воспроизведение звуков
API веб-аудио позволяет разработчикам точно планировать воспроизведение. Чтобы продемонстрировать это, давайте настроим простой ритм-трек. Вероятно, наиболее широко известным паттерном ударной установки является следующий:

в котором хэт исполняется каждую восьмую ноту, а кик и малый барабан исполняются попеременно каждую четверть, в размере 4/4.
Предположим, мы загрузили буферы kick
, snare
и hihat
, код для этого прост:
for (var bar = 0; bar < 2; bar++) {
var time = startTime + bar * 8 * eighthNoteTime;
// Play the bass (kick) drum on beats 1, 5
playSound(kick, time);
playSound(kick, time + 4 * eighthNoteTime);
// Play the snare drum on beats 3, 7
playSound(snare, time + 2 * eighthNoteTime);
playSound(snare, time + 6 * eighthNoteTime);
// Play the hi-hat every eighth note.
for (var i = 0; i < 8; ++i) {
playSound(hihat, time + i * eighthNoteTime);
}
}
Здесь мы делаем только один повтор вместо неограниченного цикла, который мы видим в нотах. Функция playSound
— это метод, который воспроизводит буфер в указанное время следующим образом:
function playSound(buffer, time) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.noteOn(time);
}
Изменение громкости звука
Одна из самых основных операций, которые вы, возможно, захотите выполнить со звуком, — это изменение его громкости. Используя API веб-аудио, мы можем направить наш источник к месту назначения через AudioGainNode , чтобы управлять громкостью:

Эту настройку соединения можно осуществить следующим образом:
// Create a gain node.
var gainNode = context.createGainNode();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);
После настройки графика вы можете программно изменить громкость, манипулируя параметром gainNode.gain.value
следующим образом:
// Reduce the volume.
gainNode.gain.value = 0.5;
Переход между двумя звуками
Теперь предположим, что у нас немного более сложный сценарий, в котором мы воспроизводим несколько звуков, но хотим плавно затухать между ними. Это обычный случай в диджейском приложении, где у нас есть два проигрывателя и мы хотим иметь возможность панорамировать от одного источника звука к другому.
Это можно сделать с помощью следующего аудиографика:

Чтобы настроить это, мы просто создаем два AudioGainNodes и подключаем каждый источник через узлы, используя что-то вроде этой функции:
function createSource(buffer) {
var source = context.createBufferSource();
// Create a gain node.
var gainNode = context.createGainNode();
source.buffer = buffer;
// Turn on looping.
source.loop = true;
// Connect source to gain.
source.connect(gainNode);
// Connect gain to destination.
gainNode.connect(context.destination);
return {
source: source,
gainNode: gainNode
};
}
Равномерное плавное затухание
Наивный метод линейного кроссфейда демонстрирует провал громкости при панорамировании между сэмплами.

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

Плавное затухание плейлиста
Еще одно распространенное приложение кроссфейдера — приложение музыкального проигрывателя. Когда песня меняется, мы хотим заглушить текущий трек и добавить новый, чтобы избежать резкого перехода. Для этого запланируйте переход в будущее. Хотя мы могли бы использовать setTimeout
для такого планирования, это неточно . С помощью API веб-аудио мы можем использовать интерфейс AudioParam для планирования будущих значений таких параметров, как значение усиления AudioGainNode
.
Таким образом, имея список воспроизведения, мы можем переходить между треками, запланировав уменьшение усиления для воспроизводимого в данный момент трека и увеличение усиления для следующего, и то и другое немного раньше, чем закончится воспроизведение текущего трека:
function playHelper(bufferNow, bufferLater) {
var playNow = createSource(bufferNow);
var source = playNow.source;
var gainNode = playNow.gainNode;
var duration = bufferNow.duration;
var currTime = context.currentTime;
// Fade the playNow track in.
gainNode.gain.linearRampToValueAtTime(0, currTime);
gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
// Play the playNow track.
source.noteOn(0);
// At the end of the track, fade it out.
gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
// Schedule a recursive track change with the tracks swapped.
var recurse = arguments.callee;
ctx.timer = setTimeout(function() {
recurse(bufferLater, bufferNow);
}, (duration - ctx.FADE_TIME) - 1000);
}
API веб-аудио предоставляет удобный набор методов RampToValue
для постепенного изменения значения параметра, например linearRampToValueAtTime
и exponentialRampToValueAtTime
.
Хотя функцию времени перехода можно выбрать из встроенных линейных и экспоненциальных функций (как указано выше), вы также можете указать свою собственную кривую значений через массив значений с помощью функции setValueCurveAtTime
.
Применение простого эффекта фильтра к звуку

API веб-аудио позволяет передавать звук из одного аудиоузла в другой, создавая потенциально сложную цепочку процессоров для добавления сложных эффектов к вашим звуковым формам.
Один из способов сделать это — разместить BiquadFilterNode между источником звука и местом назначения. Этот тип аудиоузла может выполнять множество фильтров низкого порядка, которые можно использовать для создания графических эквалайзеров и даже более сложных эффектов, в основном связанных с выбором, какие части частотного спектра звука подчеркнуть, а какие приглушить.
Поддерживаемые типы фильтров:
- Фильтр нижних частот
- Фильтр верхних частот
- Полосовой фильтр
- Фильтр низкой полки
- Фильтр с высокой полкой
- Пиковый фильтр
- Режекторный фильтр
- Все проходной фильтр
И все фильтры включают параметры, определяющие некоторую величину усиления , частоту применения фильтра и коэффициент качества. Фильтр нижних частот сохраняет нижний частотный диапазон, но отбрасывает высокие частоты. Точка обрыва определяется значением частоты, а добротность безразмерна и определяет форму графика. Усиление влияет только на определенные фильтры, такие как фильтры нижних частот и пиковые фильтры, но не на этот фильтр нижних частот.
Давайте настроим простой фильтр нижних частот, чтобы извлекать из звукового сэмпла только основы:
// Create the filter
var filter = context.createBiquadFilter();
// Create the audio graph.
source.connect(filter);
filter.connect(context.destination);
// Create and specify parameters for the low-pass filter.
filter.type = 0; // Low-pass filter. See BiquadFilterNode docs
filter.frequency.value = 440; // Set cutoff to 440 HZ
// Playback the sound.
source.noteOn(0);
В общем, регуляторы частоты необходимо настроить так, чтобы они работали в логарифмическом масштабе, поскольку сам человеческий слух работает по тому же принципу (то есть A4 — это 440 Гц, а A5 — 880 Гц). Дополнительные сведения см. в функции FilterSample.changeFrequency
по ссылке на исходный код выше.
Наконец, обратите внимание, что пример кода позволяет подключать и отключать фильтр, динамически изменяя график AudioContext. Мы можем отключить AudioNodes от графа, вызвав node.disconnect(outputNumber)
. Например, чтобы перенаправить граф с прохождения через фильтр на прямое соединение, мы можем сделать следующее:
// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);
Дальнейшее прослушивание
Мы рассмотрели основы API, включая загрузку и воспроизведение аудиосэмплов. Мы построили аудиографики с узлами усиления и фильтрами, а также запланировали настройки звуков и параметров звука, чтобы включить некоторые распространенные звуковые эффекты. На этом этапе вы готовы приступить к созданию замечательных веб-аудиоприложений!
Если вы ищете вдохновение, многие разработчики уже создали отличные работы, используя API веб-аудио. Некоторые из моих любимых включают в себя:
- AudioJedit — инструмент для склейки звука в браузере, использующий постоянные ссылки SoundCloud.
- ToneCraft — звуковой секвенсор, в котором звуки создаются путем наложения 3D-блоков.
- Plink — игра для совместного создания музыки с использованием веб-аудио и веб-сокетов.
До появления элемента HTML5 <audio>
для нарушения тишины в сети требовался Flash или другой плагин. Хотя аудио в Интернете больше не требует плагина, тег audio накладывает существенные ограничения на реализацию сложных игр и интерактивных приложений.
API веб-аудио — это API JavaScript высокого уровня для обработки и синтеза звука в веб-приложениях. Цель этого API — включить возможности, имеющиеся в современных игровых звуковых движках, а также некоторые задачи микширования, обработки и фильтрации, которые имеются в современных настольных приложениях для создания звука. Далее следует краткое введение в использование этого мощного API.
Начало работы с AudioContext
AudioContext предназначен для управления и воспроизведения всех звуков. Чтобы создать звук с помощью API веб-аудио, создайте один или несколько источников звука и подключите их к назначению звука, предоставленному экземпляром AudioContext
. Это соединение не обязательно должно быть прямым и может проходить через любое количество промежуточных AudioNodes , которые действуют как модули обработки аудиосигнала. Более подробно эта маршрутизация описана в спецификации Web Audio.
Один экземпляр AudioContext
может поддерживать несколько звуковых входов и сложные аудиографы, поэтому нам понадобится только один из них для каждого создаваемого нами аудиоприложения.
Следующий фрагмент создает AudioContext
:
var context;
window.addEventListener('load', init, false);
function init() {
try {
context = new AudioContext();
}
catch(e) {
alert('Web Audio API is not supported in this browser');
}
}
Для более старых браузеров на основе WebKit используйте префикс webkit
, как и в случае с webkitAudioContext
.
Многие интересные функции Web Audio API, такие как создание AudioNodes и декодирование данных аудиофайлов, являются методами AudioContext
.
Загрузка звуков
API веб-аудио использует AudioBuffer для звуков короткой и средней длины. Основной подход заключается в использовании XMLHttpRequest для получения звуковых файлов.
API поддерживает загрузку данных аудиофайлов в нескольких форматах, таких как WAV, MP3, AAC, OGG и других . Поддержка браузерами различных аудиоформатов различается .
Следующий фрагмент демонстрирует загрузку образца звука:
var dogBarkingBuffer = null;
var context = new AudioContext();
function loadDogSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
request.send();
}
Данные аудиофайла являются двоичными (не текстовыми), поэтому мы устанавливаем responseType
на запрос на 'arraybuffer'
. Для получения дополнительной информации о ArrayBuffers
см. В этой статье о XHR2 .
После получения (неосвещенных) данных аудиофайл, их можно сохранить для последующего декодирования, или их можно сразу декодировать с помощью метода аудиоконтексов decodeAudioData()
. Этот метод принимает ArrayBuffer
аудиофайл -данных, хранящихся в request.response
и декодирует его асинхронно (не блокируя основной поток выполнения JavaScript).
Когда decodeAudioData()
завершен, он вызывает функцию обратного вызова, которая предоставляет аудиоданные декодированного PCM в качестве AudioBuffer
.
Играет звуки

После того, как один или несколько AudioBuffers
загружаются, мы готовы воспроизводить звуки. Давайте предположим, что мы только что загрузили AudioBuffer
с звуком лая собаки и что загрузка завершилась. Затем мы можем сыграть в этот буфер со следующим кодом.
var context = new AudioContext();
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.noteOn(0); // play the source now
}
Эта функция playSound()
может быть вызвана каждый раз, когда кто -то нажимает на клавишу или нажимает что -то с помощью мыши.
Функция noteOn(time)
позволяет легко планировать точное воспроизведение звука для игр и других критических приложений. Тем не менее, чтобы это планировалось правильно работать, убедитесь, что ваши звуковые буферы предварительно загружены.
Абстрагирование API веб -аудио
Конечно, было бы лучше создать более общую систему загрузки, которая не имеет жесткой кодировки для загрузки этого конкретного звука. Существует много подходов к решению многих звуков короткой и средней длины, которые аудио-приложение или игра будет использовать- это один из способов использования буферного загрузчика (не часть веб-стандарта).
Ниже приведен пример того, как вы можете использовать класс BufferLoader
. Давайте создадим двух AudioBuffers
; И, как только они загружены, давайте воспользуемся ими одновременно.
window.onload = init;
var context;
var bufferLoader;
function init() {
context = new AudioContext();
bufferLoader = new BufferLoader(
context,
[
'../sounds/hyper-reality/br-jam-loop.wav',
'../sounds/hyper-reality/laughter.wav',
],
finishedLoading
);
bufferLoader.load();
}
function finishedLoading(bufferList) {
// Create two sources and play them both together.
var source1 = context.createBufferSource();
var source2 = context.createBufferSource();
source1.buffer = bufferList[0];
source2.buffer = bufferList[1];
source1.connect(context.destination);
source2.connect(context.destination);
source1.noteOn(0);
source2.noteOn(0);
}
Работа со временем: играет звуки с ритмом
Web Audio API позволяет разработчикам точно запланировать воспроизведение. Чтобы продемонстрировать это, давайте настроим простой ритм -трек. Наверное, наиболее широко известный шаблон бамкита является следующим:

в котором воспроизводится каждую восьмую ноту, а удар и ловушка играют чередующиеся каждый квартал, в 4/4 времени.
Предположим, что мы загрузили буферы kick
, snare
и hihat
, код сделать это прост:
for (var bar = 0; bar < 2; bar++) {
var time = startTime + bar * 8 * eighthNoteTime;
// Play the bass (kick) drum on beats 1, 5
playSound(kick, time);
playSound(kick, time + 4 * eighthNoteTime);
// Play the snare drum on beats 3, 7
playSound(snare, time + 2 * eighthNoteTime);
playSound(snare, time + 6 * eighthNoteTime);
// Play the hi-hat every eighth note.
for (var i = 0; i < 8; ++i) {
playSound(hihat, time + i * eighthNoteTime);
}
}
Здесь мы делаем только один повтор, а не неограниченную петлю, которую мы видим в нотах. Функция playSound
- это метод, который играет буфер в указанное время, следующим образом:
function playSound(buffer, time) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.noteOn(time);
}
Изменение громкости звука
Одна из самых основных операций, которые вы можете сделать для звука, - это изменить громкость. Используя API веб -аудио, мы можем направить наш источник в его назначение через аудиогнод , чтобы манипулировать громкостью:

Эта настройка соединения может быть достигнута следующим образом:
// Create a gain node.
var gainNode = context.createGainNode();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);
После того, как график был настроен, вы можете программно изменить громкость, манипулируя gainNode.gain.value
следующим образом:
// Reduce the volume.
gainNode.gain.value = 0.5;
Перекрестный флекс между двумя звуками
Теперь, предположим, у нас есть немного более сложный сценарий, где мы играем несколько звуков, но хотим пересечь затухание между ними. Это распространенный случай в приложении, похожих на диджея, где у нас есть два проигрывателя и мы хотим иметь возможность паном из одного источника звука к другому.
Это можно сделать со следующим аудио графиком:

Чтобы настроить это, мы просто создаем две аудиогноды и подключаем каждый источник через узлы, используя что -то вроде этой функции:
function createSource(buffer) {
var source = context.createBufferSource();
// Create a gain node.
var gainNode = context.createGainNode();
source.buffer = buffer;
// Turn on looping.
source.loop = true;
// Connect source to gain.
source.connect(gainNode);
// Connect gain to destination.
gainNode.connect(context.destination);
return {
source: source,
gainNode: gainNode
};
}
Равная мощность перекрестка
На наивный линейный подход поперечного фарта демонстрирует объемный падение, когда вы панируете между образцами.

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

Плейлист пересекается
Еще одно распространенное приложение CrossFader предназначено для приложения для музыкального проигрывателя. Когда песня меняется, мы хотим исчезнуть текущий трек и исчезнуть новую, чтобы избежать резкого перехода. Чтобы сделать это, запланируйте перекрестный фон в будущее. Хотя мы могли бы использовать setTimeout
для выполнения этого планирования, это не точнее . С помощью веб -аудио -API мы можем использовать интерфейс Audioparam для планирования будущих значений для таких параметров, как значение усиления AudioGainNode
.
Таким образом, учитывая плейлист, мы можем переходить между треками, планируя уменьшение усиления на игровой трассе в настоящее время, и увеличение усиления на следующем, оба немного до того, как текущий трек заканчивает игру:
function playHelper(bufferNow, bufferLater) {
var playNow = createSource(bufferNow);
var source = playNow.source;
var gainNode = playNow.gainNode;
var duration = bufferNow.duration;
var currTime = context.currentTime;
// Fade the playNow track in.
gainNode.gain.linearRampToValueAtTime(0, currTime);
gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
// Play the playNow track.
source.noteOn(0);
// At the end of the track, fade it out.
gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
// Schedule a recursive track change with the tracks swapped.
var recurse = arguments.callee;
ctx.timer = setTimeout(function() {
recurse(bufferLater, bufferNow);
}, (duration - ctx.FADE_TIME) - 1000);
}
Web Audio API предоставляет удобный набор методов RampToValue
для постепенного изменения значения параметра, такого как linearRampToValueAtTime
и exponentialRampToValueAtTime
.
В то время как функция времени перехода может быть выбрана из встроенных линейных и экспоненциальных (как указано выше), вы также можете указать свою собственную кривую значения через массив значений, используя функцию setValueCurveAtTime
.
Применение простого эффекта фильтра к звуку

Веб -аудио API позволяет вам поднять звук из одного аудио -узла в другой, создавая потенциально сложную цепочку процессоров, чтобы добавить сложные эффекты в ваши звуковые формы.
Один из способов сделать это - разместить Biquadfilternode S между источником звука и пунктом назначения. Этот тип аудио-узла может выполнять различные фильтры низкого порядка, которые можно использовать для построения графических эквалайзеров и даже более сложных эффектов, в основном связанных с выбором, какие части частотного спектра звука следует подчеркнуть, а какие-подчинить.
Поддерживаемые типы фильтров включают:
- Низкий проходной фильтр
- Фильтр высокого прохода
- Групповой фильтр
- Фильтр низкого полки
- Фильтр высокого шельфа
- Пиковой фильтр
- Notch Filter
- Все прохождение фильтра
И все фильтры включают параметры для определения некоторого количества усиления , частоты, с помощью которого можно применять фильтр, и коэффициент качества. Фильтр низкого частоты сохраняет более низкий диапазон частот, но отбрасывает высокие частоты. Точка разрыва определяется значением частоты, а коэффициент Q является единодушным и определяет форму графика. Усиление влияет только на определенные фильтры, такие как низкопользовые и пиковые фильтры, а не на этот фильтр низкого уровня.
Давайте настроим простой фильтр низкого уровня для извлечения только основы из образца звука:
// Create the filter
var filter = context.createBiquadFilter();
// Create the audio graph.
source.connect(filter);
filter.connect(context.destination);
// Create and specify parameters for the low-pass filter.
filter.type = 0; // Low-pass filter. See BiquadFilterNode docs
filter.frequency.value = 440; // Set cutoff to 440 HZ
// Playback the sound.
source.noteOn(0);
В целом, частотные элементы управления необходимо настраивать для работы в логарифмическом масштабе, поскольку сам слух человека работает по тому же принципу (то есть A4 составляет 440 Гц, а A5 - 880 Гц). Для получения более подробной информации см. Функцию FilterSample.changeFrequency
.
Наконец, обратите внимание, что пример кода позволяет подключать и отключать фильтр, динамически изменяя график аудиоконтекса. Мы можем отключить Audionodes от графика, вызывая node.disconnect(outputNumber)
. Например, чтобы перенаправить график от прохождения фильтра, на прямое соединение, мы можем сделать следующее:
// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);
Дальнейшее прослушивание
Мы рассмотрели основы API, включая загрузку и воспроизведение образцов аудио. Мы создали аудио графики с узлами усиления и фильтрами, а также запланированные звуки и звуковые параметры, чтобы обеспечить некоторые общие звуковые эффекты. На этом этапе вы готовы пойти и создать несколько сладких приложений для веб -аудио!
Если вы ищете вдохновение, многие разработчики уже создали отличную работу, используя API веб -аудио. Некоторые из моих любимых включают:
- AudioJedit , инструмент для сплайсинга звука в браузере, который использует постоянные ссылки на звуковой Cloud.
- Tonecraft , звуковой секвенсор, где звуки создаются путем укладки 3D -блоков.
- PLINK , совместная музыка для создания музыки с использованием веб-аудио и веб-сокетов.