Web Audio API

Низкоуровневый граф обработки звука: декодирование, синтез, эффекты, анализ спектра.

Что это

Граф из узлов (AudioNode), которые соединяются connect. Источники (AudioBufferSourceNode, MediaElementAudioSourceNode, OscillatorNode) → процессоры (GainNode, BiquadFilterNode, DelayNode) → анализатор/назначение (AudioDestinationNode). Всё работает через единый AudioContext.

Гораздо мощнее HTMLAudioElement: семплерная точность, синтез, эффекты, спектральный анализ для визуализаций.

Базовое использование

// 1. Контекст
const ctx = new AudioContext();

// 2. Загрузить и декодировать сэмпл
const res = await fetch('/sounds/clap.mp3');
const arrayBuf = await res.arrayBuffer();
const audioBuf = await ctx.decodeAudioData(arrayBuf);

// 3. Воспроизвести (одноразовый источник — нужно создавать каждый раз)
function play() {
  const src = ctx.createBufferSource;
  src.buffer = audioBuf;
  src.connect(ctx.destination);
  src.start();
}

// Связь с <audio>
const audioEl = document.querySelector('audio');
const source = ctx.createMediaElementSource(audioEl);
const gain = ctx.createGain;
gain.gain.value = 0.5;
source.connect(gain).connect(ctx.destination);

// Анализатор для визуализации (drum kit waveform)
const analyser = ctx.createAnalyser;
analyser.fftSize = 256;
source.connect(analyser);

const data = new Uint8Array(analyser.frequencyBinCount);
function draw() {
  requestAnimationFrame(draw);
  analyser.getByteFrequencyData(data);
  // нарисовать data на canvas
}
draw;

Основные узлы

Узел Что делает
AudioContext Корневой граф, sampleRate, currentTime
AudioBufferSourceNode Источник из декодированного буфера (one-shot)
MediaElementAudioSourceNode Источник из <audio>/<video>
OscillatorNode Синтез: sine/square/sawtooth/triangle
GainNode Громкость, fade in/out
BiquadFilterNode Low/high/bandpass фильтры
AnalyserNode FFT для визуализации
DelayNode / ConvolverNode Эффекты echo/reverb

Поддержка

Все современные браузеры. webkitAudioContext — legacy префикс для старых Safari.

Подводные камни

  • AudioContext создаётся в состоянии suspended — нужен user gesture + ctx.resume для запуска
  • AudioBufferSourceNodeодноразовый: после stop создавай новый
  • decodeAudioData копирует данные → большие файлы расходуют память; для стриминга лучше <audio> + MediaElementAudioSourceNode
  • Один и тот же <audio> нельзя подключить к двум MediaElementAudioSourceNode
  • На iOS контекст блокирован до тапа

Используется в bootcamp

  • JS30 — Drum Kit (#1) — простейший случай: можно ограничиться audio.currentTime = 0; audio.play(). Но если хочется визуализацию спектра — берём AnalyserNode.

Ссылки

См. также