A p5.SoundFile holds audio loaded from a file — like an MP3 or WAV.
Loading takes time, so use preload() to fetch the file before
setup() runs. Call loadSound() with a path or URL.
Click the canvas to play it.
The examples below use an audio file stored in the project's /assets folder.
When you build your own sketch, put audio files in your project folder and use a path
like 'sounds/beat.mp3'.
Audio files don't appear instantly — loadSound() fetches the file in the
background. The code checks isPlaying() to decide whether to play or stop,
but it's also common to guard with isLoaded() to make sure the file is
ready before you call play(). If you try to play too early, nothing happens.
Use amp() to change the volume and rate() to change how fast
the sound plays. Here an IconButton from ProControls toggles the song on and
off, and a MultiSlider gives you two knobs — one for volume, one for speed.
Drag a slider while the song is playing to hear the difference in real time.
play() — play once from the startloop() — play on repeatpause() / play() — pause and resume from the same spotstop() — stop and reset to the beginningduration() — length of the file in secondscurrentTime() — where the playhead is right nowjump(time) — jump to a position in the filesetLoop(true/false) — turn looping on or off
When you host your own files, you can pass several formats in an array —
loadSound(['beat.mp3', 'beat.ogg']) — and the browser picks one that works.
See the
p5.SoundFile reference.
A sample pad is a set of buttons — press one and it immediately plays a sound, like
the pads on a real drum machine. Each button is wired to one audio file, so you can
tap out patterns in real time. This example uses GridPad from ProControls
with mode:"button", which means pads fire when you press them but don't
stay lit up — perfect for a performance-style pad.
The samples array holds the file path for each drum sound. Inside
preload(), a loop calls loadSound() on every path and pushes
the result into the drums array. By the time setup() runs,
all eight sounds are loaded and ready to go.
new GridPad({rows:2, cols:4, cellSize:60, mode:"button"}) draws a
2×4 grid of eight pads. mode:"button" is the key difference from
the sequencer below — pressing a pad triggers it once and it immediately goes dark
again, just like a real drum pad. There's no on/off toggle; every press is a fresh hit.
Every time you press a pad, onChange fires and receives an object with
three things: data1.r (which row, 0 or 1), data1.c (which
column, 0–3), and data1.state ("on" when the pad is first
pressed). The line let index = data1.r * 4 + data1.c converts that row
and column into a single number between 0 and 7 — the position of the right sound in
the drums array. When state is "on",
drums[index].play() fires the sound.
gridChanged with this version and change mode from "button" to "toggle" — pressing a pad starts the loop,
pressing it again stops it:
function gridChanged(data1, data2) {
let index = data1.r * 4 + data1.c;
if (data1.value == 1) {
drums[index].loop();
} else if (data1.value == 0) {
drums[index].stop();
}
}
A step sequencer is basically a drum machine. Imagine a grid where each row is a different drum sound and each column is a moment in time. Click a cell to switch it on — when the sequencer reaches that column, that drum plays. Click it again to switch it off.
GridPad from ProControls draws the whole grid for you and handles all the
clicking. You just tell it how many rows and columns you want. The preview on the right
shows a finished sequencer — try clicking the cells to build a beat.
new GridPad({rows:8, cols:16, mode:"toggle"}) creates an 8×16 button grid.
mode:"toggle" means every click flips a cell between on (lit) and off (dark).
hGroup:4 draws faint divider lines every 4 columns so you can count beats easily.
You don't write any drawing code — GridPad handles all of it automatically.
setInterval(() => { ... }, 250) runs a chunk of code every 250 milliseconds —
that's four times per second, which feels like a steady beat at 60 BPM.
Each time it fires it calls nextBeat() to move the playhead one step to the
right, then playBeat() to check which drums should play on that step.
Want it faster? Lower the number. Slower? Raise it.
There's one small catch: the timer starts the moment the page loads, but the grid
doesn't exist yet — it only gets created inside setup(), which runs
after all the samples have finished downloading. The line
if (!myGrid) return; inside the timer is a safety check: if the grid
isn't ready yet, just skip this tick and wait until it is.
myGrid.getValue(row, col) returns 1 if that cell is lit up, or
0 if it's dark. playBeat() loops through every row and plays the
drum sound for that row only when the value is 1. That's the whole playback
engine — just a loop and a number check.
myGrid.highlightCol(col, true) draws a glowing outline around that column so
you can see where the sequencer is. nextBeat() turns the highlight off on the
old column, adds one to beatCounter (wrapping back to 0 after column 15), then
turns the highlight on for the new column.
rows / cols — how many rows and columns the grid hasmode: 'toggle' — each click flips a cell on or offhGroup: 4 — draw a divider line every 4 columns to mark beatslabel — text that appears beneath the gridonChange(values) — a function that runs every time any cell is clicked; values is the full grid as a 2D array of 0s and 1smyGrid.getValue(row, col) — returns 1 if that cell is on, 0 if offmyGrid.highlightCol(col, true/false) — turn the playhead highlight on or off for a column