Change Tone.js Instrument Volume Dynamically
This article explains how to dynamically adjust the volume of a Tone.js instrument during playback. You will learn how to manipulate the volume property using decibels, perform smooth volume transitions to avoid audio artifacts, and use ramping methods for real-time control.
Understanding the Volume Property in Tone.js
In Tone.js, instruments have a built-in volume property
which is a Tone.Signal object. Unlike standard Web Audio
nodes that use linear gain (0 to 1), Tone.js measures volume in
decibels (dB).
- 0 dB is the default, unattenuated volume.
- Negative values (e.g., -10, -20) decrease the volume.
- -Infinity (or extremely low values like -100) mutes the instrument entirely.
Because the volume property is a signal, you should not assign a
number directly to instrument.volume. Instead, you must
manipulate its .value property or use signal methods.
Method 1: Changing Volume Immediately
To change the volume instantly, update the .value of the
instrument’s volume signal.
// Create a synth and connect it to the main output
const synth = new Tone.Synth().toDestination();
// Set the volume to -12 decibels instantly
synth.volume.value = -12;Note: Changing the volume instantly while a note is playing can cause an audible click or pop in the audio.
Method 2: Changing Volume Smoothly (Recommended)
To avoid audio artifacts like pops and clicks, you should ramp the volume over a short period of time. Tone.js provides helper methods on its signal objects to make this easy.
Using rampTo()
The rampTo method smoothly transitions the volume from
its current level to a new level over a specified duration (in
seconds).
// Smoothly fade the volume to -20 dB over 2 seconds
synth.volume.rampTo(-20, 2);Using AudioParam Scheduling
For precise scheduling relative to the Tone.js transport timeline, you can use standard AudioParam automation methods:
const now = Tone.now();
// Ramp to -30 dB exponentially over 1 second, starting from the current time
synth.volume.exponentialRampToValueAtTime(-30, now + 1);Practical Example: Linking Volume to an HTML Slider
A common use case is controlling an instrument’s volume using an HTML
<input type="range"> slider.
HTML
<input type="range" id="volume-slider" min="-60" max="0" value="-10" step="1">JavaScript
const synth = new Tone.Synth().toDestination();
const slider = document.getElementById('volume-slider');
// Set initial volume based on slider value
synth.volume.value = parseFloat(slider.value);
// Update volume dynamically on input
slider.addEventListener('input', (e) => {
const dbValue = parseFloat(e.target.value);
// Use a tiny ramp time (0.05s) to prevent clicking during rapid slider movement
synth.volume.rampTo(dbValue, 0.05);
});