The Complete Guide to Building Audio Features with the Web Audio API in 2026
The Web Audio API became a powerful tool for building audio experiences in the browser by 2025-2026 — from music production apps to real-time audio effects, voice changers, and audio visualization. Combined with the MediaStream API, it enables real-time voice processing in the browser.
Here's the practical guide.
Audio Context
const audioCtx = new AudioContext();
// Create nodes
const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
// Connect: source → effects → destination
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
// Configure
oscillator.type = "sine"; // sine, square, sawtooth, triangle
oscillator.frequency.value = 440; // A4 note
// Start and stop
oscillator.start();
oscillator.stop(audioCtx.currentTime + 1); // 1 second
Audio Buffer Playback
async function loadAndPlay(url) {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
const source = audioCtx.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioCtx.destination);
source.start();
return source;
}
Gain and Volume Control
const gainNode = audioCtx.createGain();
// Fade in over 2 seconds
gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
gainNode.gain.linearRampToValueAtTime(1, audioCtx.currentTime + 2);
// Fade out over 1 second
gainNode.gain.setValueAtTime(1, audioCtx.currentTime + 3);
gainNode.gain.linearRampToValueAtTime(0, audioCtx.currentTime + 4);
Filters
const filter = audioCtx.createBiquadFilter();
filter.type = "lowpass"; // lowpass, highpass, bandpass
filter.frequency.value = 1000; // Hz
filter.Q.value = 1; // Resonance
// Sweep the filter
filter.frequency.setValueAtTime(200, audioCtx.currentTime);
filter.frequency.exponentialRampToValueAtTime(8000, audioCtx.currentTime + 1);
Analyser (Visualization)
const analyser = audioCtx.createAnalyser();
analyser.fftSize = 2048;
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
source.connect(analyser);
function draw() {
analyser.getByteFrequencyData(dataArray);
// Draw using canvas or WebGL
ctx.clearRect(0, 0, canvas.width, canvas.height);
const barWidth = canvas.width / bufferLength;
let x = 0;
for (let i = 0; i < bufferLength; i++) {
const barHeight = dataArray[i];
ctx.fillStyle = `rgb(${barHeight}, 100, 50)`;
ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
x += barWidth;
}
requestAnimationFrame(draw);
}
draw();
Reverb (Convolver)
// Create impulse response for reverb
function createReverb(duration = 2, decay = 2) {
const sampleRate = audioCtx.sampleRate;
const length = sampleRate * duration;
const impulse = audioCtx.createBuffer(2, length, sampleRate);
for (let channel = 0; channel < 2; channel++) {
const channelData = impulse.getChannelData(channel);
for (let i = 0; i < length; i++) {
channelData[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / length, decay);
}
}
const convolver = audioCtx.createConvolver();
convolver.buffer = impulse;
return convolver;
}
source.connect(reverb);
reverb.connect(audioCtx.destination);
MediaStream (Microphone)
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const micSource = audioCtx.createMediaStreamSource(stream);
// Add effects chain
micSource.connect(analyser);
analyser.connect(audioCtx.destination);
// Later: stop the stream
stream.getTracks().forEach(track => track.stop());
This article contains affiliate links. If you sign up through the links above, I may earn a commission at no additional cost to you.
Ready to Build Your Online Business?
Get started with Systeme.io for free — All-in-one platform for building your online business with AI tools.
Top comments (0)