Tone.js Volume and Sub-mixing Guide

This article explains the function of the Tone.Volume node in Tone.js and demonstrates how it serves as an essential tool for sub-mixing. You will learn how to control audio levels using logarithmic decibel values and group multiple audio sources into a single bus for streamlined volume management in your web audio applications.

What is Tone.Volume?

Tone.Volume is a dedicated audio node in Tone.js designed specifically for controlling the volume of an audio signal. Unlike standard gain nodes that scale audio linearly (from 0 to 1), Tone.Volume operates on a decibel (dB) scale.

Decibels are logarithmic, which aligns closely with how human ears perceive changes in loudness. In Tone.Volume: * 0 dB represents unity gain, meaning the input signal passes through unaltered. * Negative values (e.g., -10 dB, -20 dB) decrease the volume. * Positive values (e.g., +3 dB) boost the volume. * -Infinity (represented as -Infinity or a very low number like -100) completely mutes the signal.

To adjust the volume dynamically, you manipulate the .volume property, which is a Tone.Signal. This allows you to schedule volume changes over time using methods like rampTo() or linearRampToValueAtTime().

// Create a volume node set to -12 decibels
const volumeNode = new Tone.Volume(-12).toDestination();

How Tone.Volume Assists in Sub-mixing

Sub-mixing (also known as busing or grouping) is the practice of routing multiple individual audio sources into a single, intermediate channel before sending them to the main output (Tone.Destination). This technique is crucial for managing complex audio environments, such as separating drum tracks, synthesizers, and sound effects.

Tone.Volume acts as the perfect sub-mix bus. By routing multiple instruments into one Tone.Volume node, you gain collective control over that entire group.

Benefits of Sub-mixing with Tone.Volume

  1. Group Level Control: You can adjust the overall volume of a group of instruments (for example, lowering all percussion elements at once) without disrupting the relative volume levels established between the individual instruments themselves.
  2. Simplified Effects Processing: By routing multiple instruments to a single Tone.Volume node, you can insert effects (like reverb or delay) right after the volume node. This processes the combined signal, saving CPU resources.
  3. Global Muting and Fading: You can easily fade out or mute an entire category of sounds (like background music during a voiceover) by ramping the single Tone.Volume node to -Infinity.

Implementation Example

In this example, three separate drum instruments are routed into a single “drum bus” using Tone.Volume. This allows you to control the entire drum mix with one variable.

// 1. Create the sub-mix bus using Tone.Volume and connect it to the main output
const drumBus = new Tone.Volume(-6).toDestination();

// 2. Create individual instruments
const kick = new Tone.MembraneSynth();
const snare = new Tone.NoiseSynth();
const hihat = new Tone.MetalSynth();

// 3. Connect the instruments to the sub-mix bus instead of the main output
kick.connect(drumBus);
snare.connect(drumBus);
hihat.connect(drumBus);

// 4. Adjust the volume of the entire drum mix dynamically
// This lowers the volume of the kick, snare, and hihat simultaneously over 2 seconds
drumBus.volume.rampTo(-18, 2);

By leveraging Tone.Volume for sub-mixing, you can create a highly organized, scalable, and responsive audio architecture in your Tone.js projects.