Audio Analysis

iHearYouCanCode — by David Stein
Visualize sound — waveforms, frequency spectra, and loudness
↗ p5.FFT Docs
Haven't set things up yet? Do Getting Started first — it shows you how to add p5.js, p5.sound, and ProControls.

1. Visualize amplitude with a circle

The simplest thing you can do with audio analysis is measure how loud the sound is at any moment — that's called amplitude. p5.Amplitude listens to the audio and gives you a number between 0 (silence) and 1 (max volume) each frame via getLevel(). Map that number to the size of a circle and you've got a visualizer. Click the preview to start the music.

Try editing the code — the preview updates as you type

How it works

new p5.Amplitude() created in setup() automatically listens to everything your sketch is playing. Each frame in draw(), amp.getLevel() returns the current loudness as a number between 0 and 1. map(level, 0, 1, 0, width) stretches that tiny number into a pixel size — so silence gives a dot and a loud beat fills the canvas.

2. Draw a frequency spectrum with p5.FFT

Amplitude tells you how loud, but not what is playing. A Fast Fourier Transform breaks the sound apart into frequency slices — low bass on the left, high treble on the right. p5.FFT does this for you. Call fft.analyze() each frame and you get back an array of values (0–255), one per frequency bin. Draw a bar for each bin and you have a classic spectrum display. Click the preview to start the music.

Try editing the code — the preview updates as you type

How it works

new p5.FFT(0.8, 64) creates an FFT analyser. The first number (0.8) is smoothing — higher values make the bars rise and fall more slowly, which looks nicer. The second number (64) is how many bins (bars) to use; it must be a power of 2. More bins = more detail, but slower to draw.

Each frame, fft.analyze() returns an array of 64 numbers. The loop draws one rectangle per bin: i * barW positions it across the canvas, and map(spectrum[i], 0, 255, 0, height) sets its height. Drawing from the bottom up with height - barH gives the classic equaliser look.

3. Five frequency bands as circles

Instead of drawing every bin, you can ask the FFT for the energy in named frequency ranges. fft.getEnergy("bass") returns a single number (0–255) representing how much low-end power is in the signal right now. p5.FFT has five built-in ranges: "bass", "lowMid", "mid", "highMid", and "treble". Draw one circle per band and each one pulses to its own part of the music. Click the preview to start.

Try editing the code — the preview updates as you type

How it works

You must call fft.analyze() once per frame before calling getEnergy() — it updates the internal snapshot that getEnergy reads from. Each band name maps to a fixed Hz range: bass is the lowest frequencies, treble is the highest. The circles are drawn on top of each other from largest to smallest so all five are always visible. The 180 alpha value makes them slightly transparent so the layers blend together.

4. Beat detection with p5.PeakDetect

p5.sound has a built-in beat detector called p5.PeakDetect. You tell it which frequency range to watch and it handles the averaging and threshold logic for you. Each frame, check peakDetect.isDetected — it's true on the exact frame a beat hits, and false every other frame. Click to start.

Try editing the code — the preview updates as you type

How it works

new p5.PeakDetect(20, 200) watches the frequency range from 20 Hz to 200 Hz — the bass band where kick drums live. You must call fft.analyze() first, then peakDetect.update(fft) to feed it fresh data each frame. When a spike is detected, peakDetect.isDetected flips to true for one frame only. The circle snaps to full size on that frame, then shrinks each frame with radius *= 0.85 until the next hit. You can tune the detector with two extra arguments: new p5.PeakDetect(20, 200, threshold, framesPerPeak) — lower the threshold (default 0.35) to catch quieter beats, or raise framesPerPeak (default 20) to ignore rapid double-hits.