Connect Custom Web Audio Nodes to Howler.js

Howler.js is a robust library for managing web audio, but its default features may not cover advanced digital signal processing (DSP) needs. Fortunately, because Howler.js is built on top of the native Web Audio API, you can access its underlying AudioContext and master output nodes. This guide demonstrates how to intercept Howler’s audio pipeline and insert custom Web Audio API nodes—such as filters, delay lines, or panners—to create custom audio effects.

Step 1: Initialize Howler.js

Before accessing the Web Audio API context, you must initialize Howler.js by creating a new Howl instance or playing a sound. Howler.js creates its global AudioContext automatically upon initialization.

import { Howl, Howler } from 'howler';

const sound = new Howl({
  src: ['audio-file.mp3'],
  html5: false // Must be false to use the Web Audio API pipeline
});

Note: Ensure html5 is set to false (which is the default). HTML5 Audio routing does not support Web Audio API node connections.

Step 2: Access the AudioContext and Master Gain

Howler.js exposes its global AudioContext via Howler.ctx and its master output node via Howler.masterGain.

To insert a custom node, you must disconnect Howler.masterGain from the default destination and route it through your custom node instead.

Step 3: Create and Connect Your Custom Node

In this example, we will create a BiquadFilterNode (a low-pass filter) using the native Web Audio API and insert it into the Howler.js audio chain.

// 1. Ensure the AudioContext is running (required by some browsers)
if (Howler.ctx && Howler.ctx.state === 'suspended') {
  Howler.ctx.resume();
}

// 2. Create the custom Web Audio API node
const filterNode = Howler.ctx.createBiquadFilter();
filterNode.type = 'lowpass';
filterNode.frequency.setValueAtTime(800, Howler.ctx.currentTime);

// 3. Disconnect Howler's master gain from the speakers
Howler.masterGain.disconnect();

// 4. Reconnect the nodes to form the new chain:
// Master Gain -> Custom Filter -> Destination (Speakers)
Howler.masterGain.connect(filterNode);
filterNode.connect(Howler.ctx.destination);

Step 4: Play the Sound

Once the routing is established, any sound played through Howler.js will automatically pass through your custom filter node.

sound.play();

You can now dynamically update the parameters of your custom node (e.g., changing filterNode.frequency.value) in real-time, and Howler.js will output the processed audio.