The Role of Tone.Event in Tone.js Scheduling
This article explores the role of Tone.Event in Tone.js,
a powerful class designed for scheduling general-purpose events along
the audio timeline. You will learn how Tone.Event works,
how it differs from other scheduling utilities, and how to implement it
to trigger custom callback functions precisely in sync with the Tone.js
Transport.
What is Tone.Event?
In Tone.js, Tone.Event is a flexible, low-level class
used to schedule a callback function at a specific time along the
Transport timeline. While classes like Tone.Sequence are
tailored for step-sequencing and Tone.Part is built for
multi-note musical scores, Tone.Event is the foundational
tool for general-purpose, time-aligned actions.
It allows developers to trigger non-audio events—such as UI animations, state changes, or custom JavaScript logic—precisely synchronized with audio playback.
Key Features of Tone.Event
Tone.Event provides several features that make it
superior to basic timeout functions or raw Transport scheduling:
- Timeline Synchronization: Events are bound to the
Tone.Transport. If the Transport pauses, speeds up, or slows down, the execution of theTone.Eventadjusts accordingly. - Looping Capabilities: You can easily configure an event to loop at a set interval for a specific duration or indefinitely.
- Playback Control: Each
Tone.Eventinstance can be started, stopped, canceled, or muted individually without affecting the rest of the timeline. - State Tracking: It provides built-in properties
like
progressto track how far along a looping event is in its current iteration.
How to Use Tone.Event
To use Tone.Event, you instantiate the class with a
callback function and then schedule its start time. The callback
function receives two arguments: the precise audio time at
which the event occurs, and an optional value payload.
Here is a basic implementation:
import * as Tone from "tone";
// Create a synth to play a sound
const synth = new Tone.Synth().toDestination();
// Define the event
const myEvent = new Tone.Event((time, pitch) => {
// Use the precise audio time to trigger the synth
synth.triggerAttackRelease(pitch, "8n", time);
console.log(`Triggered ${pitch} at transport time: ${time}`);
}, "C4");
// Schedule the event to start at the beginning of the Transport timeline
myEvent.start(0);
// Start the Transport to hear the event
Tone.Transport.start();Creating Looping Events
Tone.Event is highly effective for creating repeating
patterns that are more complex than standard metronomes but simpler than
full musical parts.
const loopingEvent = new Tone.Event((time) => {
// Your recurring action here
console.log("Loop event fired at", time);
});
// Configure the loop settings
loopingEvent.loop = true;
loopingEvent.loopEnd = "1m"; // Loop every 1 measure
loopingEvent.playbackRate = 1;
// Start looping at the 2nd measure
loopingEvent.start("2:0:0");Tone.Event vs. Transport.schedule
While you can schedule callbacks directly using
Tone.Transport.schedule(), using Tone.Event
offers distinct advantages:
- Encapsulation:
Tone.Eventwraps the event logic, timing, and state into a single object. - Dynamic Manipulation: With
Transport.schedule(), once an event is scheduled, you must use an ID to cancel it. WithTone.Event, you can call.stop(),.start(), or mutate properties like.playbackRatedirectly on the object instance at any time during runtime.