5 ноября рабочая группа по аудио опубликовала первый публичный рабочий проект API веб-аудио 1.1. Эта спецификация описывает высокоуровневый веб-API для обработки и синтеза звука в веб-приложениях. Основная парадигма — это граф маршрутизации звука, где несколько объектов AudioNode соединены вместе для определения общего рендеринга звука. Фактическая обработка будет в основном происходить в базовой реализации (обычно оптимизированный код Assembly / C / C++), но также поддерживается прямая обработка и синтез скриптов.
Этот API предназначен для использования совместно с другими API и элементами на веб-платформе, в частности: XMLHttpRequest [XHR] (с использованием атрибутов responseType
и response
). Для игр и интерактивных приложений ожидается использование с API-интерфейсами Canvas 2D [2dcontext] и WebGL [WEBGL] 3D-графики.
Модульная маршрутизация допускает произвольные соединения между различными объектами AudioNode. Каждый узел может иметь входы и/или выходы. Узел-источник не имеет входов и один выход. Узел назначения имеет один вход и нет выходов. Другие узлы, такие как фильтры, могут быть размещены между узлами-источником и узлом-получателем. Разработчику не нужно беспокоиться о деталях формата потока низкого уровня, когда два объекта соединены вместе; все просто происходит правильно. Например, если монофонический аудиопоток подключен к стереовходу, он должен просто смешиваться с левым и правым каналами соответствующим образом.
В простейшем случае один источник может быть направлен непосредственно на выход. Вся маршрутизация происходит в AudioContext, содержащем один AudioDestinationNode:
Пример воспроизведения одного звука:
const context = new AudioContext();
function playSound() {
const source = context.createBufferSource();
source.buffer = dogBarkingBuffer;
source.connect(context.destination);
source.start(0);
}
Более сложный пример с тремя источниками и посылом сверточного ревербератора с динамическим компрессором на конечном выходном этапе:
let context;
let compressor;
let reverb;
let source1, source2, source3;
let lowpassFilter;
let waveShaper;
let panner;
let dry1, dry2, dry3;
let wet1, wet2, wet3;
let mainDry;
let mainWet;
function setupRoutingGraph () {
context = new AudioContext();
// Создание nodes эффектов.
lowpassFilter = context.createBiquadFilter();
waveShaper = context.createWaveShaper();
panner = context.createPanner();
compressor = context.createDynamicsCompressor();
reverb = context.createConvolver();
// Создание main wet и dry.
mainDry = context.createGain();
mainWet = context.createGain();
// Подключение конечного компрессора к конечному пункту назначения.
compressor.connect(context.destination);
// Подключение main dry and wet к compressor.
mainDry.connect(compressor);
mainWet.connect(compressor);
// Подключение reverb к main wet.
reverb.connect(mainWet);
// Добавление несколько источников.
source1 = context.createBufferSource();
source2 = context.createBufferSource();
source3 = context.createOscillator();
source1.buffer = manTalkingBuffer;
source2.buffer = footstepsBuffer;
source3.frequency.value = 440;
// Подключение источника 1
dry1 = context.createGain();
wet1 = context.createGain();
source1.connect(lowpassFilter);
lowpassFilter.connect(dry1);
lowpassFilter.connect(wet1);
dry1.connect(mainDry);
wet1.connect(reverb);
// Подключение источника 2
dry2 = context.createGain();
wet2 = context.createGain();
source2.connect(waveShaper);
waveShaper.connect(dry2);
waveShaper.connect(wet2);
dry2.connect(mainDry);
wet2.connect(reverb);
// Подключение источника 3
dry3 = context.createGain();
wet3 = context.createGain();
source3.connect(panner);
panner.connect(dry3);
panner.connect(wet3);
dry3.connect(mainDry);
wet3.connect(reverb);
// Запуск исходников сейчас.
source1.start(0);
source2.start(0);
source3.start(0);
}