Skip to content

EZ Web Audio / LayeredSound

Class: LayeredSound ​

Defined in: packages/core/src/layered-sound.ts:45

LayeredSound synchronizes multiple Sound/Oscillator instances for simultaneous playback with master gain/pan control and individual layer access.

All layers start at exactly the same audioContext.currentTime for precise sync. Layers end independently - LayeredSound emits 'end' when the last layer finishes.

Layers are constructor-only. There is no addLayer()/removeLayer() — the layer set passed to the constructor is fixed for the lifetime of the instance. To change layers at runtime, dispose this instance and construct a new LayeredSound with the desired layer array.

Example ​

typescript
const bass = await createSound('bass.mp3')
const melody = await createSound('melody.mp3')
const synth = await createOscillator({ frequency: 440 })

const layered = new LayeredSound(audioContext, [bass, melody, synth])
layered.play() // All layers start at exact same time
layered.changeGainTo(0.5) // Affects all layers
layered.getLayer(2)?.changeGainTo(0.8) // Control individual layer

Extends ​

Constructors ​

Constructor ​

new LayeredSound(audioContext, layers, opts?): LayeredSound

Defined in: packages/core/src/layered-sound.ts:57

Parameters ​

audioContext ​

AudioContext

layers ​

(Oscillator | Sound<BaseSoundEventMap> | null | undefined)[]

opts? ​

LayeredSoundOptions

Returns ​

LayeredSound

Overrides ​

TypedEventEmitter.constructor

Properties ​

name ​

name: string

Defined in: packages/core/src/layered-sound.ts:55

Accessors ​

disposed ​

Get Signature ​

get disposed(): boolean

Defined in: packages/core/src/layered-sound.ts:108

Whether this LayeredSound has been disposed.

Returns ​

boolean


layerCount ​

Get Signature ​

get layerCount(): number

Defined in: packages/core/src/layered-sound.ts:125

Get the number of valid layers in this LayeredSound.

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/layered-sound.ts:279

Add an effect to the shared output bus. All layers route through this bus, so the effect applies to all layers.

Parameters ​

effect ​

Effect

The effect to add

position? ​

number

Optional insert position (defaults to end)

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 "play" | "dispose" | "stop" | "end" | "warning"

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/layered-sound.ts:224

Set the gain for all layers via the shared output bus.

Validated identically to BaseSound.changeGainTo: throws a ValidationError for negative values, warns on the console for values above 1 (R1#1 — previously this bypassed validation entirely via a raw setValueAtTime call).

Parameters ​

value ​

number

The gain value (0-1 typical range)

Returns ​

this

this for chaining


changePanTo() ​

changePanTo(value): this

Defined in: packages/core/src/layered-sound.ts:252

Set the pan for all layers.

Validated identically to BaseSound.changePanTo: warns on the console for values outside [-1, 1] (R1#1).

Parameters ​

value ​

number

The pan value (-1 to 1, where -1 is full left, 1 is full right)

Returns ​

this

this for chaining


dispose() ​

dispose(): void

Defined in: packages/core/src/layered-sound.ts:332

Stop all layers and dispose them. Releases resources and prevents further use.

After disposal, calling play() will throw an error. Dispose is idempotent — calling it multiple times is safe.

Returns ​

void

Example ​

typescript
const layered = await createLayeredSound([bass, melody])
layered.play()
// When done:
layered.dispose()

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 "play" | "dispose" | "stop" | "end" | "warning"

Parameters ​

type ​

K

The event type to emit (key of TMap)

detail ​

LayeredSoundEventMap[K]["detail"]

The event detail object (typed by TMap)

Returns ​

void

Inherited from ​

TypedEventEmitter.emit


getEffects() ​

getEffects(): readonly Effect[]

Defined in: packages/core/src/layered-sound.ts:314

Get a readonly copy of the effects array.

Returns ​

readonly Effect[]

A copy of the effects array


getLayer() ​

getLayer(index): Oscillator | Sound<BaseSoundEventMap> | undefined

Defined in: packages/core/src/layered-sound.ts:118

Get a layer by index for individual control.

Parameters ​

index ​

number

The layer index (0-based)

Returns ​

Oscillator | Sound<BaseSoundEventMap> | undefined

The Sound or Oscillator at that index, or undefined if out of bounds


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 "play" | "dispose" | "stop" | "end" | "warning"

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 "play" | "dispose" | "stop" | "end" | "warning"

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 "play" | "dispose" | "stop" | "end" | "warning"

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(): Promise<void>

Defined in: packages/core/src/layered-sound.ts:133

Play all layers simultaneously at exactly the same audioContext.currentTime. This ensures perfect synchronization across all layers.

Returns ​

Promise<void>


playFor() ​

playFor(duration): Promise<void>

Defined in: packages/core/src/layered-sound.ts:191

Play all layers simultaneously for a specified duration, then stop.

Parameters ​

duration ​

number

Duration in seconds before stopping all layers

Returns ​

Promise<void>

Example ​

typescript
const layered = await createLayeredSound([kick, snare])
layered.playFor(0.1) // Play for 100ms then auto-stop

removeEffect() ​

removeEffect(effect): this

Defined in: packages/core/src/layered-sound.ts:298

Remove an effect from the shared output bus.

Parameters ​

effect ​

Effect

The effect 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 "play" | "dispose" | "stop" | "end" | "warning"

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


setGain() ​

setGain(value): void

Defined in: packages/core/src/layered-sound.ts:239

Parameters ​

value ​

number

The gain value (0-1 typical range)

Returns ​

void

Deprecated ​

Use changeGainTo instead — identical behavior, renamed for API symmetry with BaseSound/Sampler (R1#1). Will be removed in a future major version.


setPan() ​

setPan(value): void

Defined in: packages/core/src/layered-sound.ts:267

Parameters ​

value ​

number

The pan value (-1 to 1, where -1 is full left, 1 is full right)

Returns ​

void

Deprecated ​

Use changePanTo instead — identical behavior, renamed for API symmetry with BaseSound/Sampler (R1#1). Will be removed in a future major version.


stop() ​

stop(): Promise<void>

Defined in: packages/core/src/layered-sound.ts:202

Stop all layers.

Returns ​

Promise<void>