Tutorial · Beginner · ~45 min
Web Audio API · Canvas 2D · Three.js

WebAudio API Spectrum Visualizer

The Web Audio API's AnalyserNode exposes real-time FFT data that you can render as bars, an oscilloscope, or a 3D frequency landscape — all without sending audio to a server. This tutorial wires a microphone input through the audio graph and draws several visualizations.

1Set up the AudioContext and AnalyserNode

const ctx = new AudioContext(); const analyser = ctx.createAnalyser(); // FFT size must be power of 2; frequencyBinCount = fftSize / 2 analyser.fftSize = 2048; // 1024 bins analyser.smoothingTimeConstant = 0.85; // 0 = no smoothing, 1 = sticky // buffers for data reads const freqData = new Uint8Array(analyser.frequencyBinCount); // 0–255 per bin const timeData = new Uint8Array(analyser.fftSize); // waveform // connectthe graph: source → analyser → destination analyser.connect(ctx.destination);
frequencyBinCount is half of fftSize. Each bin spans sampleRate / fftSize Hz. With fftSize = 2048 at 44100 Hz that's ~21.5 Hz per bin.

2Request microphone access

let source; document.getElementById('start').addEventListener('click', async () => { // Must be triggered by user gesture — no autoplay await ctx.resume(); try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false }); source = ctx.createMediaStreamSource(stream); source.connect(analyser); // NOTE: do NOT connect analyser to ctx.destination if you don't want audio feedback draw(); } catch (err) { console.error('Microphone denied:', err); } });

3Draw a 2D spectrum bar chart

const canvas = document.getElementById('spectrum'); const c2d = canvas.getContext('2d'); const W = canvas.width, H = canvas.height; function drawSpectrum() { analyser.getByteFrequencyData(freqData); c2d.clearRect(0, 0, W, H); const barW = W / freqData.length; for (let i = 0; i < freqData.length; i++) { const value = freqData[i]; // 0–255 const barH = (value / 255) * H; // Colour: low freq = blue, high = red const hue = 240 - (value / 255) * 240; c2d.fillStyle = `hsl(${hue},100%,50%)`; c2d.fillRect(i * barW, H - barH, barW - 1, barH); } } function draw() { requestAnimationFrame(draw); drawSpectrum(); }

4Draw an oscilloscope waveform

const waveCanvas = document.getElementById('waveform'); const wCtx = waveCanvas.getContext('2d'); function drawWaveform() { analyser.getByteTimeDomainData(timeData); wCtx.clearRect(0, 0, W, H); wCtx.lineWidth = 2; wCtx.strokeStyle = '#22c55e'; wCtx.beginPath(); const sliceW = W / timeData.length; let x = 0; for (let i = 0; i < timeData.length; i++) { const v = timeData[i] / 128.0; // normalise 0-2, centre at 1 const y = (v / 2) * H; if (i === 0) wCtx.moveTo(x, y); else wCtx.lineTo(x, y); x += sliceW; } wCtx.lineTo(W, H / 2); wCtx.stroke(); } // Call drawWaveform() inside the draw() loop alongside drawSpectrum()
getByteTimeDomainData returns the raw sample buffer (PCM). Values range 0–255 where 128 is silence. The oscilloscope is the simplest way to confirm audio is flowing.

53D bars with Three.js InstancedMesh

import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.160/build/three.module.js'; const BINS = 128; // use first 128 frequency bins const geo = new THREE.BoxGeometry(0.8, 1, 0.8); const mat = new THREE.MeshStandardMaterial({ color: 0x22c55e }); const mesh = new THREE.InstancedMesh(geo, mat, BINS); scene.add(mesh); const dummy = new THREE.Object3D(); const colors = new THREE.Color(); function update3DBars() { analyser.getByteFrequencyData(freqData); for (let i = 0; i < BINS; i++) { const v = freqData[i] / 255; // 0–1 const barH = Math.max(0.05, v * 20); const x = (i - BINS / 2) * 1.1; dummy.position.set(x, barH / 2, 0); dummy.scale.set(1, barH, 1); dummy.updateMatrix(); mesh.setMatrixAt(i, dummy.matrix); // Colour gradient by frequency colors.setHSL((1 - v) * 0.66, 1, 0.5); mesh.setColorAt(i, colors); } mesh.instanceMatrix.needsUpdate = true; if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true; } // Call update3DBars() in the render loop
Using InstancedMesh collapses all 128 bars into a single draw call, keeping the GPU happy even at high frame rates.

Frequently Asked Questions

What will I learn in this tutorial?

Build a real-time audio spectrum visualizer with the Web Audio API — FFT analysis, bar chart, waveform oscilloscope, and Three.js 3D bars.

What topics are covered in this tutorial?

This tutorial covers: Set up the AudioContext and AnalyserNode, Request microphone access, Draw a 2D spectrum bar chart, Draw an oscilloscope waveform, 3D bars with Three.js InstancedMesh.

What tools and technologies does this tutorial use?

This tutorial uses Web Audio API, Canvas 2D, Three.js.

How long does this tutorial take?

This tutorial takes approximately 45 minutes to complete.

What prerequisites do I need before starting?

This is a Beginner-level tutorial — no special preparation beyond basic JavaScript is assumed.