Howler.js Multiple Instances of Same Sound

This article explains how the howler.js JavaScript audio library manages playing multiple instances of the same sound simultaneously. We will explore how howler.js utilizes unique sound IDs, leverages the Web Audio API for efficient node creation, falls back to HTML5 Audio pooling, and allows you to control individual sound instances independently.

The Sound ID System

When you play a sound using howler.js by calling the play() method on a Howl object, the library does not play the global object itself. Instead, it generates and returns a unique integer known as a soundId.

This soundId acts as a pointer to that specific playback instance. If you call play() three times in rapid succession, howler.js will play three overlapping instances of the audio and return three distinct IDs. You can use these IDs to modify, pause, fade, or stop specific instances without affecting the others. For example:

const sound = new Howl({ src: ['explosion.mp3'] });

// Play two instances of the same sound simultaneously
const id1 = sound.play();
const id2 = sound.play();

// Change the volume of only the first instance
sound.volume(0.5, id1);

// Pause only the second instance
sound.pause(id2);

Web Audio API Implementation

By default, howler.js uses the Web Audio API, which makes simultaneous playback highly efficient.

  1. Single Buffer Loading: Howler.js loads the audio file once and decodes it into an AudioBuffer stored in system memory.
  2. Multiple Source Nodes: Every time you call play(), howler.js creates a new AudioBufferSourceNode, points it to the shared AudioBuffer, and connects it to the global Web Audio destination.
  3. Automated Cleanup: Once a specific instance finishes playing, howler.js automatically disconnects and destroys that specific source node, freeing up system memory.

Because multiple source nodes can read from the exact same memory buffer at the same time, playing dozens of overlapping sounds (such as rapid-fire sound effects in a game) incurs almost no performance overhead.

HTML5 Audio Fallback

In cases where the Web Audio API is unavailable or explicitly disabled (by setting the html5: true option), howler.js falls back to standard HTML5 <audio> elements.

A single HTML5 <audio> element can only have one playback position at a time, meaning it cannot play over itself. To bypass this limitation, howler.js uses an internal pool of audio nodes:

While this fallback mechanism successfully achieves simultaneous playback, it is more resource-intensive than the Web Audio API because each concurrent sound requires its own HTML5 Audio element in memory.