Web Audio API w JavaScript – możliwości i zastosowania
Współczesne aplikacje webowe coraz częściej wymagają zaawansowanego przetwarzania dźwięku — od prostego odtwarzania muzyki, przez analizę dźwięku w czasie rzeczywistym, aż po interaktywne efekty audio w grach i wizualizacjach. Web Audio API to potężne narzędzie w JavaScript, które pozwala programistom tworzyć, manipulować i analizować dźwięk bezpośrednio w przeglądarce.
Czym jest Web Audio API?
Web Audio API to wysokopoziomowe API udostępniane przez przeglądarki, które umożliwia:
- generowanie dźwięków,
- przetwarzanie i modyfikowanie strumieni audio,
- analizowanie częstotliwości i amplitudy,
- tworzenie efektów dźwiękowych,
- miksowanie wielu źródeł dźwięku.
Architektura opiera się na grafie audio, zbudowanym z węzłów (audio nodes), które można łączyć w różnorodne sposoby.
Podstawowe składniki Web Audio API
- AudioContext – główny kontekst zarządzający całym systemem audio.
- AudioBufferSourceNode – odtwarzanie dźwięków z bufora.
- GainNode – kontrola głośności.
- BiquadFilterNode – różne typy filtrów (np. dolnoprzepustowy).
- AnalyserNode – analiza widma i amplitudy.
- OscillatorNode – generowanie syntetycznych dźwięków.
Przykład podstawowego odtwarzania dźwięku
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.type = 'sine';
oscillator.frequency.value = 440;
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.start();
Zastosowania Web Audio API
- Odtwarzanie i miksowanie muzyki
- Gry i efekty dźwiękowe
- Wizualizacje audio
- Edukacja i badania
- Aplikacje muzyczne i DAW
Integracja z Web MIDI API
Web MIDI API umożliwia komunikację z urządzeniami MIDI (takimi jak klawiatury, kontrolery, syntezatory) bezpośrednio z poziomu przeglądarki. W połączeniu z Web Audio API pozwala tworzyć interaktywne aplikacje muzyczne o niskim opóźnieniu.
Jak to działa?
- Web MIDI API odbiera dane z urządzenia MIDI (np. naciśnięcie klawisza).
- Dane są interpretowane w JavaScript.
- Web Audio API generuje odpowiedni dźwięk lub uruchamia efekt.
Przykład: Klawiatura MIDI sterująca Oscillatorem
navigator.requestMIDIAccess().then((midiAccess) => {
for (let input of midiAccess.inputs.values()) {
input.onmidimessage = (message) => {
const [status, note, velocity] = message.data;
if (status === 144 && velocity > 0) { // Note On
playNote(note);
}
};
}
});
function playNote(midiNote) {
const freq = 440 * Math.pow(2, (midiNote - 69) / 12);
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.frequency.value = freq;
oscillator.type = 'sawtooth';
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.start();
gainNode.gain.setValueAtTime(1, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 1);
oscillator.stop(audioContext.currentTime + 1);
}
Przykładowe zastosowania:
- Wirtualne instrumenty (np. syntezatory, bębny).
- Rejestracja i odtwarzanie sekwencji MIDI.
- Wizualne syntezatory reagujące na kontrolery MIDI.
- Edukacyjne aplikacje muzyczne (np. nauka gry na klawiszach).
Zalety Web Audio + Web MIDI
- Reagowanie w czasie rzeczywistym
- Możliwość wykorzystania istniejącego sprzętu MIDI
- Idealne dla twórców muzyki elektronicznej
- Współpraca z DAW i innymi aplikacjami MIDI
Praktyczne przykłady
Przykład 1: Interaktywny Oscylator z Pokrętłem Głośności
Ten przykład pokazuje prosty generator dźwięku z kontrolą głośności, sterowaną przez suwak.
HTML + CSS
<div>
<button id="start">Start</button>
<button id="stop">Stop</button>
<label>
Głośność:
<input type="range" id="volume" min="0" max="1" step="0.01" value="0.5">
</label>
</div>
JavaScript
let audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let oscillator, gainNode;
document.getElementById("start").onclick = () => {
oscillator = audioCtx.createOscillator();
gainNode = audioCtx.createGain();
oscillator.type = "square";
oscillator.frequency.value = 440;
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
gainNode.gain.value = document.getElementById("volume").value;
oscillator.start();
};
document.getElementById("stop").onclick = () => {
oscillator.stop();
};
document.getElementById("volume").oninput = (e) => {
if (gainNode) gainNode.gain.value = e.target.value;
};
Przetestuj ten interaktywny oscylator
Przykład 2: Klawiatura wirtualna z MIDI i Web Audio API
Ten przykład prezentuje klawiaturę ekranową z możliwością użycia MIDI i generowania tonu przy kliknięciu lub naciśnięciu klawisza.
HTML
<div id="keyboard">
<button data-note="60">C</button>
<button data-note="62">D</button>
<button data-note="64">E</button>
<button data-note="65">F</button>
<button data-note="67">G</button>
</div>
CSS (dla prostego układu)
#keyboard button {
width: 60px;
height: 100px;
margin: 2px;
font-size: 20px;
}
JavaScript (Web Audio + MIDI + GUI)
const context = new (window.AudioContext || window.webkitAudioContext)();
function playNote(midiNote) {
const osc = context.createOscillator();
const gain = context.createGain();
const freq = 440 * Math.pow(2, (midiNote - 69) / 12);
osc.type = 'sawtooth';
osc.frequency.value = freq;
osc.connect(gain);
gain.connect(context.destination);
gain.gain.setValueAtTime(0.8, context.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 1);
osc.start();
osc.stop(context.currentTime + 1);
}
document.querySelectorAll('#keyboard button').forEach(btn => {
btn.onclick = () => {
const note = parseInt(btn.dataset.note);
playNote(note);
};
});
// MIDI obsługa
navigator.requestMIDIAccess().then((access) => {
for (let input of access.inputs.values()) {
input.onmidimessage = (msg) => {
const [command, note, velocity] = msg.data;
if (command === 144 && velocity > 0) playNote(note);
};
}
});
Przetestuj tą klawiaturę
Przykład 3: Modulacja częstotliwości (FM)
Poniżej znajdziesz kompletny przykład strony HTML wykorzystującej:
- Bootstrap 5.3 (dla stylu),
- JavaScript Web Audio API (do odtwarzania dźwięku zmodulowanego częstotliwościowo – FM).
Co robi ten kod:
- Tworzy sygnał FM: częstotliwość oscylatora nośnego zmienia się w czasie według sygnału modulującego.
- Użytkownik może kliknąć przycisk "Odtwórz FM", by usłyszeć efekt.
HTML + JS Web Audio API — FM Synth
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Modulacja FM - Web Audio API</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background-color: #f8f9fa; }
.container { margin-top: 100px; }
</style>
</head>
<body>
<div class="container text-center">
<h1 class="mb-4">Modulacja Częstotliwości (FM) – Web Audio</h1>
<button id="playBtn" class="btn btn-primary btn-lg">Odtwórz FM</button>
</div>
<script>
document.getElementById("playBtn").addEventListener("click", () => {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const duration = 2; // sekundy
const carrierFreq = 440; // Hz (nośna, np. A4)
const modFreq = 5; // Hz (modulująca)
const modIndex = 100; // indeks modulacji = max deviation
// Oscylator modulujący
const modulator = audioCtx.createOscillator();
modulator.frequency.value = modFreq;
// Gain do skalowania sygnału modulującego
const modulationGain = audioCtx.createGain();
modulationGain.gain.value = modIndex;
// Oscylator nośny
const carrier = audioCtx.createOscillator();
carrier.frequency.value = carrierFreq;
// Połącz: modulator → gain → częstotliwość nośnej
modulator.connect(modulationGain);
modulationGain.connect(carrier.frequency);
// Wyjście do głośnika
carrier.connect(audioCtx.destination);
// Start
modulator.start();
carrier.start();
// Zatrzymaj po czasie
setTimeout(() => {
modulator.stop();
carrier.stop();
}, duration * 1000);
});
</script>
</body>
</html>
Jak działa modulacja FM w Web Audio API:
Formuła FM:
$$ s_{FM}(t) = A \cdot \sin\left(2\pi f_c t + \beta \cdot \sin(2\pi f_m t)\right) $$
Gdzie:
- \( s_{FM}(t) \) sygnał zmodulowany częstotliwościowo,
- \( A \) – amplituda sygnału (stała),
- \( f_c \) – częstotliwość nośna (carrier),
- \( f_m \) – częstotliwość modulująca (modulator),
- \( \beta \) – indeks modulacji:
$$ \beta = \frac{\Delta f}{f_m} $$
gdzie \( \Delta f \) to maksymalne odchylenie częstotliwości nośnej.
Parametry do zabawy:
carrierFreq
– częstotliwość podstawowa (np. 440 Hz – dźwięk A).modFreq
– jak szybko zmienia się częstotliwość.modIndex
– jak silna jest modulacja (czyli zakres zmiany częstotliwości).
Przetestuj modulację FM
Przykład 4: Modulacja amplitudy (AM)
Poniżej znajdziesz przykład HTML z Web Audio API, ale tym razem wykorzystujący modulację amplitudy (AM) zamiast częstotliwości.
Co robi ten kod:
- Odtwarza sygnał, w którym amplituda nośnej jest modulowana przez wolniejszy oscylator (sygnał modulujący).
- Sygnał modulujący zmienia głośność nośnej w czasie.
HTML + JS Web Audio API — AM Synth
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Modulacja AM - Web Audio API</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background-color: #f8f9fa; }
.container { margin-top: 100px; }
</style>
</head>
<body>
<div class="container text-center">
<h1 class="mb-4">Modulacja Amplitudy (AM) – Web Audio</h1>
<button id="playBtn" class="btn btn-success btn-lg">Odtwórz AM</button>
</div>
<script>
document.getElementById("playBtn").addEventListener("click", () => {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const duration = 2; // sekundy
const carrierFreq = 440; // Hz (nośna)
const modFreq = 5; // Hz (modulująca)
const depth = 0.5; // głębokość modulacji (0 do 1)
// Oscylator nośny
const carrier = audioCtx.createOscillator();
carrier.frequency.value = carrierFreq;
// Oscylator modulujący
const modulator = audioCtx.createOscillator();
modulator.frequency.value = modFreq;
// Gain do skalowania sygnału modulującego
const modulationGain = audioCtx.createGain();
modulationGain.gain.value = depth;
// Offset = DC gain (żeby sygnał był dodatni)
const dcGain = audioCtx.createGain();
dcGain.gain.value = 1 - depth;
// Suma (DC + modulacja) → steruje amplitudą nośnej
const amplitude = audioCtx.createGain();
modulator.connect(modulationGain);
modulationGain.connect(amplitude.gain);
dcGain.connect(amplitude.gain);
// Stałe napięcie 1 (DC)
const dc = audioCtx.createConstantSource();
dc.offset.value = 1.0;
// Połączenia
dc.connect(dcGain);
carrier.connect(amplitude);
amplitude.connect(audioCtx.destination);
// Start
dc.start();
modulator.start();
carrier.start();
// Zatrzymaj po czasie
setTimeout(() => {
dc.stop();
modulator.stop();
carrier.stop();
}, duration * 1000);
});
</script>
</body>
</html>
Jak działa modulacja AM w Web Audio API:
Formuła AM:
$$ s_{AM}(t) = [1 + m \cdot \sin(2\pi f_m t)] \cdot \sin(2\pi f_c t) $$
Gdzie:
- \( s_{AM}(t) \) – sygnał zmodulowany amplitudowo,
- \( m \) – głębokość modulacji (modulation index, \( 0 \leq m \leq 1 \)),
- \( f_m \) – częstotliwość sygnału modulującego,
- \( f_c \) – częstotliwość nośna.
Przetestuj modulację AM
Podsumowanie
Połączenie Web Audio API z Web MIDI API otwiera zupełnie nowe możliwości dla twórców aplikacji muzycznych w przeglądarce. Od prostych syntezatorów po zaawansowane narzędzia produkcyjne – JavaScript daje programistom nie tylko pełną kontrolę nad dźwiękiem, ale i natychmiastowy dostęp do sprzętu muzycznego użytkownika.