What is Tone.Signal in Tone.js
In Web Audio development, managing control signals with audio-rate
precision is crucial for creating smooth, glitch-free synthesizers and
effects. This article explores Tone.Signal in the Tone.js
library, explaining how it represents audio-rate values, why it is
essential for dynamic audio modulation, and how to use it to control
parameters programmatically.
Understanding Tone.Signal
At its core, Tone.Signal is a wrapper around the Web
Audio API’s native AudioParam. In digital audio, parameters
like frequency, volume, or filter cutoff can be changed in two ways: at
control rate (using standard JavaScript timers, which are prone to
jitter) or at audio rate (processed at the sample rate of the audio
context, typically 44,100 or 48,000 times per second).
Tone.Signal represents values at this high audio rate,
enabling sample-accurate scheduling and continuous transitions.
Why Audio-Rate Values are Essential
Using standard JavaScript variables to update synthesizer parameters in real-time often results in audible artifacts known as “zipper noise” or clicking. Because JavaScript execution runs on the main browser thread, rapid value updates cannot sync perfectly with the audio thread.
By representing values as audio-rate signals,
Tone.Signal solves this. It allows you to:
- Eliminate Glitches: Transition smoothly between values using sample-accurate interpolation.
- Perform Audio-Rate Modulation: Connect the output of one signal source (like an LFO or an envelope) directly into the parameter of another node (like a filter’s cutoff frequency) for vibrato, tremolo, or FM synthesis.
- Apply Signal Math: Perform real-time mathematical operations (such as addition, multiplication, and scaling) on control values directly on the audio thread.
Key Methods and Usage
Tone.Signal provides a suite of scheduling methods that
allow you to program precise changes over time:
setValueAtTime(value, time): Sets the signal to an exact value at a specific time.linearRampTo(value, duration, startTime): Transitions the signal to a new value linearly over a set duration.exponentialRampTo(value, duration, startTime): Transitions to a new value exponentially, which is ideal for parameters like pitch and volume that human ears perceive logarithmically.
Example of Tone.Signal in Action
Here is a basic example of how Tone.Signal is used to
modulate an oscillator’s frequency:
// Create a signal with an initial value of 440 (A4 frequency)
const frequencySignal = new Tone.Signal(440);
// Connect this signal to an oscillator's frequency parameter
const osc = new Tone.Oscillator().toDestination().start();
frequencySignal.connect(osc.frequency);
// Ramp the frequency signal to 880Hz over 2 seconds, starting now
frequencySignal.rampTo(880, 2);By treating parameters as continuous audio streams rather than static
numbers, Tone.Signal gives developers the power to build
complex, responsive, and high-fidelity web synthesizers.