Довідник · Web Audio · JavaScript
📅 Березень 2026⏱ 12 хв читання⚙️ Браузерний API

Шпаргалка з Web Audio API

Web Audio API моделює звук як орієнтований граф: джерела → вузли обробки → призначення. Кожна операція (підсилення, фільтрація, реверберація, синтез, FFT-аналіз) — це вузол. Ця шпаргалка охоплює основні вузли, автоматизацію параметрів, власний DSP через AudioWorklet та аналіз спектра в реальному часі.

Архітектура графа AudioContext

Кожен звуковий конвеєр починається зі створення контексту та зʼєднання вузлів, наче ланцюг сигналу:

// Always create on user gesture (click/keypress) — browsers require it
const ctx = new AudioContext();

// Source → [effect nodes] → destination (speakers)
source.connect(gainNode);
gainNode.connect(filterNode);
filterNode.connect(ctx.destination);
Призупинений контекст: браузери призупиняють AudioContext до жесту користувача. Перевіряйте ctx.state === 'suspended' і викликайте ctx.resume() усередині обробника кліку. Поширений патерн — створювати контекст під час першого кліку на канвас.
Тип вузла Клас Роль
Джерело OscillatorNode, AudioBufferSourceNode, MediaStreamSourceNode Генерує аудіосигнал
Ефект GainNode, BiquadFilterNode, ConvolverNode, DynamicsCompressorNode Обробляє сигнал
Аналіз AnalyserNode Знімає сигнал, не змінюючи його
Розгалужувач/Зливач ChannelSplitterNode, ChannelMergerNode Багатоканальна маршрутизація
Призначення AudioDestinationNode Кінцевий вихід (динаміки/навушники)

OscillatorNode — синтез

const osc = ctx.createOscillator();
osc.type      = 'sine';   // sine | square | sawtooth | triangle | custom
osc.frequency.setValueAtTime(440, ctx.currentTime); // 440 Hz = A4

const gain = ctx.createGain();
gain.gain.value = 0.3;  // -1..1 safe range; >1 clips

osc.connect(gain);
gain.connect(ctx.destination);
osc.start();
osc.stop(ctx.currentTime + 2.0);  // plays for 2 seconds

// Custom waveform via PeriodicWave:
const real = new Float32Array([0, 1, 0.5, 0.25]); // cosine terms (DC, f, 2f, 3f)
const imag = new Float32Array([0, 0, 0,   0]);
const wave = ctx.createPeriodicWave(real, imag);
osc.type = 'custom';
osc.setPeriodicWave(wave);

GainNode & BiquadFilterNode

// Gain: simple volume control
const gain = ctx.createGain();
gain.gain.value = 0.5;   // linear amplitude; decibels: 10^(dB/20)

// BiquadFilter: EQ / tone control
const filter = ctx.createBiquadFilter();
filter.type            = 'lowpass';   // lowpass|highpass|bandpass|notch|peaking|lowshelf|highshelf|allpass
filter.frequency.value = 1000;        // cutoff freq (Hz)
filter.Q.value         = 1.0;         // resonance; >10 → ringing; Q=0.707 = Butterworth
filter.gain.value      = 6;           // only for peaking/shelf types (dB)

// Telephone effect (band-limited to 300–3400 Hz)
const lowCut = ctx.createBiquadFilter();
lowCut.type = 'highpass';
lowCut.frequency.value = 300;
const highCut = ctx.createBiquadFilter();
highCut.type = 'lowpass';
highCut.frequency.value = 3400;
source.connect(lowCut).connect(highCut).connect(ctx.destination);

ConvolverNode — реверберація на імпульсній характеристиці

Згорткова реверберація множить кожен семпл на записану імпульсну характеристику приміщення (IR), додаючи реалістичну акустику. IR-файли (.wav) вимірюють пострілом зі стартового пістолета або синусоїдальним свіпом у цільовому просторі.

async function loadReverb(url) {
  const resp   = await fetch(url);
  const arrBuf = await resp.arrayBuffer();
  const audioBuf = await ctx.decodeAudioData(arrBuf);
  const conv = ctx.createConvolver();
  conv.buffer = audioBuf;
  conv.normalize = true;  // auto-scale IR to prevent clipping
  return conv;
}

// Wet/dry mix with GainNodes:
const dry = ctx.createGain(); dry.gain.value = 0.7;
const wet = ctx.createGain(); wet.gain.value = 0.3;
source.connect(dry).connect(ctx.destination);
source.connect(conv).connect(wet).connect(ctx.destination);
Fetch не потрібен: ви можете синтезувати IR реверберації, використовуючи буфер білого шуму з експоненційним згасанням. Візьміть 2–3-секундний буфер шуму, помножений на exp(-4 * t / duration) — це дає природне розсіяне звучання зали, достатньо добре для ігор.

AnalyserNode — FFT у реальному часі

const analyser = ctx.createAnalyser();
analyser.fftSize           = 2048;   // must be power of 2; 32–32768
analyser.smoothingTimeConstant = 0.8; // 0=no smoothing, 1=max (sluggish)
analyser.minDecibels       = -90;
analyser.maxDecibels       = -10;

source.connect(analyser);
analyser.connect(ctx.destination); // analyser passes audio through unmodified

const bufLen  = analyser.frequencyBinCount;  // = fftSize / 2
const freqBuf = new Uint8Array(bufLen);      // 0–255 per bin (magnitude)
const timeBuf = new Uint8Array(bufLen);      // waveform (time domain)

function drawSpectrum(canvas) {
  analyser.getByteFrequencyData(freqBuf);   // fill freq data
  const ctx2 = canvas.getContext('2d');
  ctx2.clearRect(0, 0, canvas.width, canvas.height);
  const barW = canvas.width / bufLen;
  freqBuf.forEach((val, i) => {
    const pct = val / 255;
    ctx2.fillStyle = `hsl(${200 + pct * 160}, 80%, 50%)`;
    ctx2.fillRect(i * barW, canvas.height * (1 - pct), barW - 1, canvas.height * pct);
  });
  requestAnimationFrame(() => drawSpectrum(canvas));
}

Частота біна i: f = i × sampleRate / fftSize. Усталена частота дискретизації — 44100 Гц, тож при fftSize=2048: бін 0 = 0 Гц, бін 1 = 21,5 Гц, бін 1024 = 22050 Гц (частота Найквіста).

AudioWorkletProcessor — власний DSP

ScriptProcessorNode застарів. AudioWorkletProcessor працює у виділеному аудіопотоці (без пауз на збирання сміття) і обробляє звук блоками по 128 семплів:

// worklet-processor.js (separate file, served as script)
class WhiteNoiseProcessor extends AudioWorkletProcessor {
  process(inputs, outputs, parameters) {
    const output = outputs[0];
    for (const channel of output) {
      for (let i = 0; i < channel.length; i++) {
        channel[i] = (Math.random() * 2 - 1) * 0.3;
      }
    }
    return true; // return false to deactivate node
  }
}
registerProcessor('white-noise', WhiteNoiseProcessor);

// In main script:
await ctx.audioWorklet.addModule('worklet-processor.js');
const noise = new AudioWorkletNode(ctx, 'white-noise');
noise.connect(ctx.destination);
Обмеження cross-origin: addModule() вимагає, щоб файл ворклета був з того самого походження або мав заголовки CORS. Під час локальної розробки роздавайте файли через локальний HTTP-сервер — не використовуйте протокол file://.

Автоматизація AudioParam

Усі AudioParam підтримують планування з точністю до семпла — набагато точніше за setTimeout:

const g = ctx.createGain();
const t = ctx.currentTime;

g.gain.setValueAtTime(0,  t);          // instant jump
g.gain.linearRampToValueAtTime(1, t + 0.01); // attack
g.gain.exponentialRampToValueAtTime(0.7, t + 0.3); // decay (must be >0)
g.gain.setTargetAtTime(0.5, t + 0.3, 0.1); // sustain (time constant)
g.gain.cancelScheduledValues(t + 2.0);
g.gain.linearRampToValueAtTime(0, t + 2.5); // release

// LFO modulating pitch:
const lfo = ctx.createOscillator();
lfo.frequency.value = 5;  // 5 Hz vibrato
const lfoGain = ctx.createGain();
lfoGain.gain.value = 15; // ±15 Hz pitch deviation
lfo.connect(lfoGain).connect(osc.frequency);

Поширені підводні камені