How to Crossfade Audio in Howler.js
Implementing a seamless transition between two audio tracks is a common requirement for web-based games, music players, and interactive applications. This article provides a straightforward guide on how to create a cross-fade effect using the howler.js library. You will learn how to use howler.js’s built-in fade methods to smoothly transition the volume of an outgoing track down to zero while simultaneously increasing the volume of an incoming track.
Step 1: Initialize the Howl Instances
To perform a cross-fade, you need two separate Howl
instances representing the audio tracks. Start by defining your audio
files and setting the initial volume of the second track to
0.
const trackA = new Howl({
src: ['track-a.mp3'],
volume: 1.0,
loop: true
});
const trackB = new Howl({
src: ['track-b.mp3'],
volume: 0.0,
loop: true
});
// Start playing the first track
trackA.play();Step 2: Write the Cross-Fade Function
Howler.js provides a native
.fade(from, to, duration, [id]) method that handles the
volume interpolation automatically.
Here is the function to transition from trackA to
trackB:
function crossFade(soundOut, soundIn, durationMs) {
// 1. Start playing the incoming track at 0 volume
soundIn.volume(0);
soundIn.play();
// 2. Fade out the outgoing track to 0
soundOut.fade(soundOut.volume(), 0, durationMs);
// 3. Fade in the incoming track to 1 (full volume)
soundIn.fade(0, 1, durationMs);
// 4. Stop the outgoing track once the fade is complete to save resources
soundOut.once('fade', () => {
soundOut.stop();
});
}Step 3: Trigger the Transition
You can call the crossFade function whenever an event
occurs, such as a user clicking a button or a new level loading in a
game.
// Cross-fade from trackA to trackB over 2000 milliseconds (2 seconds)
crossFade(trackA, trackB, 2000);Key Considerations
- Resource Management: Always call
.stop()on the outgoing track after the fade completes (as shown in theonce('fade')event listener). Leaving multiple tracks “playing” at 0 volume consumes unnecessary CPU and memory resources. - Volume Levels: If your tracks have different
baseline volumes, replace the hardcoded
1insoundIn.fade(0, 1, durationMs)with the target volume level of your destination track.