Skip to content

EZ Web Audio / PolySynth

Class: PolySynth

Defined in: packages/core/src/poly-synth.ts:226

Polyphonic synthesizer with automatic voice pool management.

PolySynth manages a pool of Oscillator voices, handling allocation, recycling, and voice stealing automatically. All voices route through a shared output bus with master gain/pan controls and effect chain support.

PolySynth has no musical identity — it works with frequencies, not note names. Use frequencyMap at the application layer to convert note names to frequencies.

Example

typescript
import { createPolySynth, frequencyMap } from 'ez-web-audio'

const synth = await createPolySynth({
  maxVoices: 8,
  type: 'sawtooth',
  envelope: { attack: 0.01, decay: 0.2, sustain: 0.5, release: 0.3 },
  lowpass: { frequency: 2000, q: 1 }
})

// Play a chord
synth.play({ frequency: 261.63 }) // C4
synth.play({ frequency: 329.63 }) // E4
synth.play({ frequency: 392.00 }) // G4

// Add effects to all voices
const delay = createDelay({ time: 0.3, feedback: 0.4, wet: 0.3 })
synth.addEffect(delay)

// Master volume
synth.update('gain').to(0.5).as('ratio')

Extends

Constructors

Constructor

new PolySynth(audioContext, options?): PolySynth

Defined in: packages/core/src/poly-synth.ts:242

Parameters

audioContext

AudioContext

options?

PolySynthOptions

Returns

PolySynth

Overrides

TypedEventEmitter.constructor

Properties

audioContext

readonly audioContext: AudioContext

Defined in: packages/core/src/poly-synth.ts:243

Accessors

activeVoices

Get Signature

get activeVoices(): number

Defined in: packages/core/src/poly-synth.ts:343

Number of currently active voices.

Returns

number


availableVoices

Get Signature

get availableVoices(): number

Defined in: packages/core/src/poly-synth.ts:348

Number of available voice slots.

Returns

number


disposed

Get Signature

get disposed(): boolean

Defined in: packages/core/src/poly-synth.ts:353

Whether this PolySynth has been disposed.

Returns

boolean


maxVoices

Get Signature

get maxVoices(): number

Defined in: packages/core/src/poly-synth.ts:340

Maximum number of simultaneous voices.

Returns

number

Methods

_clearListeners()

protected _clearListeners(): void

Defined in: packages/core/src/events/typed-event-emitter.ts:192

Remove every listener registered through this emitter (via addEventListener(), on(), or once()), regardless of how many or what event type they're bound to.

Native EventTarget has no removeAllListeners(). This works around that by aborting a shared AbortSignal threaded through every addEventListener() call this class makes, then swapping in a fresh AbortController so the instance can keep accepting new listeners afterward (e.g. if it's reused before being garbage collected).

Subclasses call this from their dispose() alongside neutering dispatchEvent — the neuter stops future emits, this stops stale listener closures from being retained/invoked at all.

Returns

void

Inherited from

TypedEventEmitter._clearListeners


addEffect()

addEffect(effect, position?): this

Defined in: packages/core/src/poly-synth.ts:793

Add an effect to the shared output bus. All voices are affected.

Parameters

effect

Effect

The Effect instance to add

position?

number

Optional index to insert at

Returns

this

this for chaining


addEventListener()

Call Signature

addEventListener<K>(type, listener, options?): void

Defined in: packages/core/src/events/typed-event-emitter.ts:44

Add a typed event listener for known event types. Overloaded to provide type safety for known event types while remaining compatible with the native EventTarget API.

Type Parameters
K

K extends "dispose" | "voicestolen"

Parameters
type

K

The event type (key of TMap)

listener

(event) => void

Typed event handler

options?

Standard addEventListener options

boolean | AddEventListenerOptions

Returns

void

Inherited from

TypedEventEmitter.addEventListener

Call Signature

addEventListener(type, listener, options?): void

Defined in: packages/core/src/events/typed-event-emitter.ts:49

Add a typed event listener for known event types. Overloaded to provide type safety for known event types while remaining compatible with the native EventTarget API.

Parameters
type

string

The event type (key of TMap)

listener

Typed event handler

EventListenerOrEventListenerObject | null

options?

Standard addEventListener options

boolean | AddEventListenerOptions

Returns

void

Inherited from

TypedEventEmitter.addEventListener


changeGainTo()

changeGainTo(value): this

Defined in: packages/core/src/poly-synth.ts:768

Set the master gain for all voices.

Parameters

value

number

Gain from 0 (silent) to 1 (full volume)

Returns

this


changePanTo()

changePanTo(value): this

Defined in: packages/core/src/poly-synth.ts:778

Set the master pan for all voices.

Parameters

value

number

Pan from -1 (left) to 1 (right)

Returns

this


dispose()

dispose(): void

Defined in: packages/core/src/poly-synth.ts:865

Dispose this PolySynth, releasing all audio resources.

Stops all voices, disconnects the shared bus, and marks the instance as unusable. Dispose is idempotent.

Returns

void


emit()

protected emit<K>(type, detail): void

Defined in: packages/core/src/events/typed-event-emitter.ts:95

Emit a typed event with the given detail.

Creates a CustomEvent with the provided detail and dispatches it on this target. Subclasses call this internally to fire lifecycle events.

Type Parameters

K

K extends "dispose" | "voicestolen"

Parameters

type

K

The event type to emit (key of TMap)

detail

PolySynthEventMap[K]["detail"]

The event detail object (typed by TMap)

Returns

void

Inherited from

TypedEventEmitter.emit


getAnalyzer()

getAnalyzer(): Analyzer | null

Defined in: packages/core/src/poly-synth.ts:841

Get the currently attached analyzer.

Returns

Analyzer | null


getEffects()

getEffects(): readonly Effect[]

Defined in: packages/core/src/poly-synth.ts:822

Get a readonly copy of the current effects array.

Returns

readonly Effect[]


getGainNode()

getGainNode(): GainNode

Defined in: packages/core/src/poly-synth.ts:358

Returns the master GainNode (for LFO targeting and external routing).

Returns

GainNode


getPannerNode()

getPannerNode(): StereoPannerNode

Defined in: packages/core/src/poly-synth.ts:361

Returns the master StereoPannerNode (for LFO targeting and external routing).

Returns

StereoPannerNode


off()

off<K>(type, listener): this

Defined in: packages/core/src/events/typed-event-emitter.ts:167

Unsubscribe from an event.

Note: Due to native EventTarget limitations, you must provide the same listener function reference that was used when subscribing.

Type Parameters

K

K extends "dispose" | "voicestolen"

Parameters

type

K

The event type to unsubscribe from

listener

(event) => void

The event handler function to remove

Returns

this

this for chaining

Example

typescript
const handler = (e) => console.log(e.detail)
emitter.on('play', handler)
// later...
emitter.off('play', handler)

Inherited from

TypedEventEmitter.off


on()

on<K>(type, listener): this

Defined in: packages/core/src/events/typed-event-emitter.ts:116

Subscribe to one or more events. Supports chaining.

Type Parameters

K

K extends "dispose" | "voicestolen"

Parameters

type

The event type(s) to subscribe to (key or array of keys of TMap)

K | K[]

listener

(event) => void

The event handler function

Returns

this

this for chaining

Example

typescript
emitter.on('play', handlePlay).on('stop', handleStop)
emitter.on(['play', 'stop'], handleBoth)

Inherited from

TypedEventEmitter.on


once()

once<K>(type, listener): this

Defined in: packages/core/src/events/typed-event-emitter.ts:141

Subscribe to an event once. Handler is removed after first invocation.

Type Parameters

K

K extends "dispose" | "voicestolen"

Parameters

type

K

The event type to subscribe to

listener

(event) => void

The event handler function

Returns

this

this for chaining

Example

typescript
emitter.once('end', () => console.log('Finished'))

Inherited from

TypedEventEmitter.once


play()

play(options): VoiceHandle

Defined in: packages/core/src/poly-synth.ts:376

Play a note at the given frequency. Returns a VoiceHandle for per-voice control.

Parameters

options

PlayOptions

Frequency and optional per-voice gain

Returns

VoiceHandle

VoiceHandle for controlling the voice

Example

typescript
const handle = synth.play({ frequency: 440 })
handle.update('gain').to(0.5).as('ratio')
await handle.stop()

removeEffect()

removeEffect(effect): this

Defined in: packages/core/src/poly-synth.ts:810

Remove an effect from the shared output bus.

Parameters

effect

Effect

The Effect instance to remove

Returns

this

this for chaining


removeEventListener()

Call Signature

removeEventListener<K>(type, listener, options?): void

Defined in: packages/core/src/events/typed-event-emitter.ts:70

Remove a typed event listener for known event types. Overloaded to provide type safety for known event types while remaining compatible with the native EventTarget API.

Type Parameters
K

K extends "dispose" | "voicestolen"

Parameters
type

K

The event type (key of TMap)

listener

(event) => void

Typed event handler to remove

options?

Standard removeEventListener options

boolean | EventListenerOptions

Returns

void

Inherited from

TypedEventEmitter.removeEventListener

Call Signature

removeEventListener(type, listener, options?): void

Defined in: packages/core/src/events/typed-event-emitter.ts:75

Remove a typed event listener for known event types. Overloaded to provide type safety for known event types while remaining compatible with the native EventTarget API.

Parameters
type

string

The event type (key of TMap)

listener

Typed event handler to remove

EventListenerOrEventListenerObject | null

options?

Standard removeEventListener options

boolean | EventListenerOptions

Returns

void

Inherited from

TypedEventEmitter.removeEventListener


setAnalyzer()

setAnalyzer(analyzer): this

Defined in: packages/core/src/poly-synth.ts:832

Attach an analyzer to the shared bus output for visualization.

Parameters

analyzer

The Analyzer instance, or null to detach

Analyzer | null

Returns

this

this for chaining


setDestination()

setDestination(node): this

Defined in: packages/core/src/poly-synth.ts:851

Set a custom destination for audio output.

Parameters

node

AudioNode

The AudioNode to route output to

Returns

this

this for chaining


stopAll()

stopAll(): void

Defined in: packages/core/src/poly-synth.ts:682

Stop all active voices immediately, including voices already mid-release from an earlier stop() call. All handles become stale.

State is updated synchronously here rather than deferred to the oscillator's own 'stop'/'end' events (as setupVoiceListeners does for a normal single-voice stop) — those events depend on Oscillator's own async play/stop machinery (e.g. an AudioContext.resume() still in flight), which panic can't afford to wait on. Recycling the slot immediately is click-safe: G1's Oscillator.setup() already detects a still-audible outgoing node (via _isPlaying/_releaseTailEndsAt) on the NEXT play() and routes it through a release-gain handoff instead of a hard cut, regardless of whether this method's synchronous bookkeeping or the oscillator's own async event fires first.

Returns

void

Example

typescript
synth.stopAll() // Panic button

update()

update(type): object

Defined in: packages/core/src/poly-synth.ts:748

Update a master bus parameter immediately.

Note: unlike GrainPlayer, PolySynth's master bus intentionally does NOT have onPlaySet()/onPlayRamp() (R1#6 evaluated this and skipped it) — PolySynth has no singular "play()" for the whole instance to hook a consume-once schedule onto; play(options) triggers one voice at a time and each returned VoiceHandle already exposes its own onPlaySet()/onPlayRamp() (delegating to the voice's Oscillator) for per-note envelopes. Use those for per-note fades, or update('gain') / changeGainTo() here for master-bus-wide immediate changes.

Parameters

type

'gain' or 'pan'

"gain" | "pan"

Returns

object

Fluent builder

to()

to: (value) => object

Parameters
value

number

Returns

object

as()

as: (method) => void

Parameters
method

RatioType

Returns

void

Example

typescript
synth.update('gain').to(0.5).as('ratio')