Trigger ADSR Envelope with Tone.Synth in Tone.js
Controlling the volume of a sound over time is essential for creating
realistic or expressive synthesizer sounds. This article explains how to
configure and trigger an Attack-Decay-Sustain-Release (ADSR) envelope
using the Tone.Synth instrument in the Tone.js framework,
allowing you to easily shape the dynamics of your web audio
projects.
Understanding ADSR in Tone.Synth
In Tone.js, Tone.Synth comes pre-packaged with an
amplitude envelope. You can customize the envelope by passing an
envelope configuration object when instantiating the
synth.
- Attack: The time it takes for the sound to go from silent to its peak volume (in seconds).
- Decay: The time it takes for the sound to drop from the peak volume to the sustain level (in seconds).
- Sustain: The volume level maintained after the decay phase until the note is released (scalar value from 0 to 1).
- Release: The time it takes for the sound to fade out to silence after the note is released (in seconds).
Configuring the ADSR Envelope
To set custom ADSR values, pass them into the envelope
property of the Tone.Synth constructor:
const synth = new Tone.Synth({
oscillator: {
type: "sine" // Choose oscillator type (sine, square, triangle, saw)
},
envelope: {
attack: 0.1, // 100ms fade-in
decay: 0.2, // 200ms decay
sustain: 0.5, // hold at 50% volume
release: 1.2 // 1.2 seconds fade-out
}
}).toDestination();Triggering the Envelope
There are two primary methods to trigger the ADSR envelope: automatically scheduling both the attack and release, or triggering them manually with separate events.
Method 1:
Automatic Triggering (triggerAttackRelease)
The most common way to trigger a note is using
triggerAttackRelease(). This method plays a note for a set
duration, automatically handling the transition from the sustain phase
to the release phase.
// Start Tone.js audio context on user interaction
document.body.addEventListener('click', async () => {
await Tone.start();
// Play note C4 for the duration of a quarter note ("4n")
synth.triggerAttackRelease("C4", "4n");
});Method
2: Manual Triggering (triggerAttack and
triggerRelease)
For interactive applications like a MIDI keyboard, you need to start
the sound when a key is pressed and stop it when the key is released.
You achieve this using separate triggerAttack() and
triggerRelease() calls.
// Trigger the attack phase (initiates attack, decay, and holds at sustain)
synth.triggerAttack("E4");
// Trigger the release phase (initiates release fade-out) after 2 seconds
setTimeout(() => {
synth.triggerRelease();
}, 2000);