Tone.PolySynth: Managing Polyphony in Tone.js
In web audio development, creating rich harmonic structures requires
the ability to play multiple notes simultaneously. This article explains
the purpose of Tone.PolySynth in Tone.js and details how it
manages polyphony through dynamic voice allocation and recycling,
allowing developers to easily trigger chords and complex synthesizer
arrangements.
The Purpose of Tone.PolySynth
Most basic synthesizer instruments in Tone.js, such as
Tone.Synth, Tone.FMSynth, or
Tone.AMSynth, are inherently monophonic. This means they
can only output a single pitch at any given time. If you attempt to
trigger a new note while a previous one is still sounding, the engine
will cut off or glide the original note to play the new one.
Tone.PolySynth solves this limitation. Rather than being
a unique synthesizer engine itself, it acts as a polyphonic controller
or wrapper. It takes a monophonic voice class as an argument (defaulting
to Tone.Synth if none is specified) and handles the complex
logic required to play chords, overlapping melodies, and lush ambient
pads.
How PolySynth Manages Polyphony
Managing polyphony in web browsers is highly resource-intensive. If an application constantly creates new synthesizer objects for every note played, memory usage will spike, leading to garbage collection pauses and audio glitches.
To prevent this, Tone.PolySynth utilizes an efficient
voice-allocation and recycling system:
- Internal Voice Pool: Instead of creating synths on
the fly,
Tone.PolySynthmaintains an internal pool of monophonic synthesizer instances. - Dynamic Allocation: When you trigger a chord—such
as calling
triggerAttack(["C4", "E4", "G4"])—thePolySynthchecks its pool for idle voices. If it finds idle synthesizers, it assigns one to each note in the chord. - Voice Creation and Limits: If there are no idle
voices in the pool,
Tone.PolySynthwill instantiate new ones, but only up to a set limit. This limit is defined by themaxPolyphonyoption (which defaults to 32). - Voice Stealing: If the maximum polyphony threshold is reached and a new note is triggered, the controller performs “voice stealing.” It will automatically release the oldest active note to free up a synthesizer instance for the incoming pitch.
- Recycling: Once a note’s envelope completes its release phase and falls to silence, the controller marks that specific synthesizer voice as idle. The idle voice remains in memory, waiting to be reused for the next note trigger rather than being destroyed.
By automating this entire lifecycle behind the scenes,
Tone.PolySynth allows developers to focus on musical
composition and interactive audio logic without having to manually
track, trigger, and dispose of individual synthesizer instances.