Change Tone.js Player Speed Without Pitch Shift
This article explains how to alter the playback rate of an audio file
in Tone.js without affecting its pitch. While the standard
Tone.Player node changes both speed and pitch
simultaneously, you can achieve independent time-stretching by utilizing
the Tone.GrainPlayer node instead. Below, you will find a
direct explanation and code examples demonstrating how to implement this
solution.
The Problem with Tone.Player
In Tone.js, the standard Tone.Player simulates a
traditional tape player. When you increase the
playbackRate, the audio plays faster, but the pitch rises.
When you decrease it, the audio slows down and the pitch drops.
To change the speed of your audio while maintaining the original
pitch, you must use granular synthesis. Tone.js provides a dedicated
node for this called Tone.GrainPlayer.
The Solution: Tone.GrainPlayer
Tone.GrainPlayer splits the audio buffer into small
segments (grains) and plays them back in a way that allows you to adjust
the playback speed and the pitch independently.
Here is how to set up and use Tone.GrainPlayer to change
the speed without changing the pitch:
// Create and load the GrainPlayer
const player = new Tone.GrainPlayer({
url: "path/to/your/audio.mp3",
onload: () => {
// Start playback once the file is loaded
player.start();
}
}).toDestination();
// Increase speed by 50% (pitch remains unchanged)
player.playbackRate = 1.5; Fine-Tuning the Audio Quality
Because granular synthesis slices the audio into small pieces,
time-stretching can sometimes introduce artifacts or a “jittery” sound.
You can optimize the audio quality of your speed-adjusted playback by
tweaking the following properties on your Tone.GrainPlayer
instance:
grainSize: Defines the duration of each grain (default is 0.2 seconds). For speech or transient-heavy sounds, smaller grain sizes often sound better. For pads and continuous tones, larger grain sizes are ideal.overlap: Defines the amount of overlap between grains (default is 0.1 seconds). Adjusting this helps smooth out transitions between the audio slices.
// Adjusting grain parameters for smoother playback
player.grainSize = 0.08; // 80 milliseconds
player.overlap = 0.04; // 40 millisecondsBy substituting Tone.Player with
Tone.GrainPlayer, you gain complete control over your
audio’s playback speed without compromising its original key or
pitch.