Tone.js Step Sequencer Tutorial with Tone.Sequence
This tutorial provides a quick, hands-on guide to building a basic
web-based step sequencer loop using Tone.js. You will learn how to
initialize a synthesizer, configure the Tone.Sequence class
to schedule and play musical notes, and control the global audio
transport to loop your sequence seamlessly in the browser.
1. Import Tone.js and Create a Play Button
Modern browsers require a user interaction (like a click) to start audio. Create a simple HTML button to initialize and start the sequencer:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tone.js Step Sequencer</title>
<!-- Import Tone.js via CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script>
</head>
<body>
<button id="start-btn">Play Sequencer</button>
<script>
// JavaScript code will go here
</script>
</body>
</html>2. Set Up the Instrument
Inside your <script> tag, initialize a basic
synthesizer and connect it to the main audio destination (your
speakers):
const synth = new Tone.Synth().toDestination();3. Define the Sequence Array
Create an array representing the steps of your sequencer. Each
element in the array represents a step in time. You can use note names
(like “C4”) for active steps, and null to represent
rests:
const notes = ["C4", "E4", "G4", "B4", null, "A4", "F4", "D4"];4. Initialize Tone.Sequence
The Tone.Sequence object takes three arguments: 1.
Callback function: Executed at every step. It receives
the current time (crucial for precise scheduling) and the
note value from your array. 2. Events
array: The sequence array you defined in the previous step. 3.
Subdivision: The duration of each step (e.g.,
"8n" for eighth notes).
const seq = new Tone.Sequence((time, note) => {
// Only play a sound if the step is not a rest (null)
if (note !== null) {
synth.triggerAttackRelease(note, "8n", time);
}
}, notes, "8n");5. Control the Transport and Start Audio
To hear the sequence, you must start both the individual sequence and
Tone.js’s global timing system, Tone.Transport. Wrap this
logic inside a click event listener to comply with browser audio
policies:
document.getElementById("start-btn").addEventListener("click", async () => {
// Start the Tone.js audio context
await Tone.start();
console.log("Audio context active");
// Configure loop points and tempo (optional)
Tone.Transport.bpm.value = 120; // Set tempo to 120 BPM
// Start the sequence at the beginning of the transport timeline
seq.start(0);
// Start the transport timeline
Tone.Transport.start();
});Once you click the button, Tone.js will continuously loop through your array, playing the defined notes at the specified 120 BPM tempo.