--- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/Player.md' --- [EZ Web Audio](../index.md) / Player # ~~Type Alias: Player~~ > **Player** = [`InteractionTarget`](../interfaces/InteractionTarget.md) Defined in: [packages/core/src/index.ts:1400](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1400) ## Deprecated Use `InteractionTarget` instead. --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/SoundEventMap.md' --- [EZ Web Audio](../index.md) / SoundEventMap # ~~Type Alias: SoundEventMap~~ > **SoundEventMap** = [`TrackEventMap`](../interfaces/TrackEventMap.md) Defined in: [packages/core/src/events/event-types.ts:153](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L153) Full event map including Track-specific events. ## Deprecated Use [BaseSoundEventMap](../interfaces/BaseSoundEventMap.md) for Sound instances or [TrackEventMap](../interfaces/TrackEventMap.md) for Track instances. This type includes pause/resume/seek events that only Track emits — using it on Sound allows registering listeners for events that will never fire. Retained for backward compatibility. --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/BaseEffect.md' --- [EZ Web Audio](../index.md) / BaseEffect # Abstract Class: BaseEffect Defined in: [packages/core/src/effects/base-effect.ts:46](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L46) Abstract base class for audio effects that provides shared wet/dry mixing, bypass, and parameter ramping functionality. Subclasses must: 1. Call `super(audioContext)` in their constructor 2. Wire their effect chain: `this.inputNode -> [effect nodes] -> this.wetGain` 3. Implement `getAudioParam()` to map parameter names to AudioParams BaseEffect handles: * Wet/dry mixing via equal-power crossfade * Bypass (routes signal fully dry) * `rampTo()` for smooth parameter transitions ## Example ```typescript class MyEffect extends BaseEffect { private readonly myNode: GainNode constructor(audioContext: AudioContext) { super(audioContext) this.myNode = audioContext.createGain() this.inputNode.connect(this.myNode) this.myNode.connect(this.wetGain) } protected getAudioParam(name: string): AudioParam | null { if (name === 'gain') return this.myNode.gain return null } } ``` ## Extends * [`TypedEventEmitter`](TypedEventEmitter.md)<`BaseEffectEventMap`> ## Extended by * [`CompressorEffect`](CompressorEffect.md) * [`DelayEffect`](DelayEffect.md) * [`DistortionEffect`](DistortionEffect.md) * [`EQEffect`](EQEffect.md) * [`FilterEffect`](FilterEffect.md) * [`ReverbEffect`](ReverbEffect.md) ## Implements * [`Effect`](../interfaces/Effect.md) ## Constructors ### Constructor > **new BaseEffect**(`audioContext`): `BaseEffect` Defined in: [packages/core/src/effects/base-effect.ts:62](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L62) #### Parameters ##### audioContext `AudioContext` #### Returns `BaseEffect` #### Overrides [`TypedEventEmitter`](TypedEventEmitter.md).[`constructor`](TypedEventEmitter.md#constructor) ## Accessors ### bypass #### Get Signature > **get** **bypass**(): `boolean` Defined in: [packages/core/src/effects/base-effect.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L95) When true, signal bypasses the effect entirely (100% dry). ##### Returns `boolean` #### Set Signature > **set** **bypass**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L99) When true, effect is bypassed (passthrough) ##### Parameters ###### v `boolean` ##### Returns `void` When true, effect is bypassed (passthrough) #### Implementation of [`Effect`](../interfaces/Effect.md).[`bypass`](../interfaces/Effect.md#bypass) *** ### input #### Get Signature > **get** **input**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:83](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L83) The input AudioNode (receives signal from chain) ##### Returns `AudioNode` The input AudioNode that receives signal from the chain #### Implementation of [`Effect`](../interfaces/Effect.md).[`input`](../interfaces/Effect.md#input) *** ### mix #### Get Signature > **get** **mix**(): `number` Defined in: [packages/core/src/effects/base-effect.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L108) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (all through effect). Uses equal-power crossfade for natural mixing. ##### Returns `number` #### Set Signature > **set** **mix**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:112](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L112) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) ##### Parameters ###### v `number` ##### Returns `void` Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) #### Implementation of [`Effect`](../interfaces/Effect.md).[`mix`](../interfaces/Effect.md#mix) *** ### output #### Get Signature > **get** **output**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:88](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L88) The output AudioNode (sends signal to next in chain) ##### Returns `AudioNode` The output AudioNode that sends signal to the next in chain #### Implementation of [`Effect`](../interfaces/Effect.md).[`output`](../interfaces/Effect.md#output) ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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`](TypedEventEmitter.md).[`_clearListeners`](TypedEventEmitter.md#clearlisteners) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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"` ##### 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/effects/base-effect.ts:272](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L272) Disconnect all internal audio nodes and emit a 'dispose' event. **Subclass disposal contract:** Subclasses that create additional audio nodes (e.g., BiquadFilterNode, DynamicsCompressorNode, WaveShaperNode) MUST override dispose() to disconnect those nodes before calling super.dispose(). #### Returns `void` #### Example ```typescript public override dispose(): void { try { this.myNode.disconnect() } catch { /* already disconnected */ } super.dispose() } ``` Idempotent — safe to call multiple times. #### Implementation of [`Effect`](../interfaces/Effect.md).[`dispose`](../interfaces/Effect.md#dispose) *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail `BaseEffectEventMap`\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`TypedEventEmitter`](TypedEventEmitter.md).[`emit`](TypedEventEmitter.md#emit) *** ### getAudioContext() > **getAudioContext**(): `AudioContext` Defined in: [packages/core/src/effects/base-effect.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L121) Get the AudioContext used by this effect. Useful for external tools (e.g., LFO) that need the context. #### Returns `AudioContext` *** ### getAudioParam() > `abstract` `protected` **getAudioParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/base-effect.ts:308](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L308) Map a parameter name to its underlying AudioParam. Subclasses implement this to expose their effect-specific parameters. #### Parameters ##### name `string` The parameter name #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized *** ### getParam() > **getParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/base-effect.ts:134](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L134) Get a named AudioParam from this effect for external modulation. Delegates to the subclass's getAudioParam() implementation. Returns null if the parameter name is not recognized. #### Parameters ##### name `string` The parameter name (e.g., 'frequency', 'time', 'feedback') #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized *** ### getUnrampableParams() > `protected` **getUnrampableParams**(): readonly `string`\[] Defined in: [packages/core/src/effects/base-effect.ts:243](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L243) Names of documented effect properties that are NOT backed by a single AudioParam (e.g. WaveShaper curve swaps, multi-node comb/allpass networks) and therefore cannot be smoothly ramped via `rampTo()`. `rampTo()` warns instead of silently no-op-ing when called with one of these names, so callers don't mistake "no-op" for "it worked." Default: none. Subclasses override where applicable. #### Returns readonly `string`\[] *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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"` #### 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`](TypedEventEmitter.md).[`off`](TypedEventEmitter.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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`](TypedEventEmitter.md).[`on`](TypedEventEmitter.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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`](TypedEventEmitter.md).[`once`](TypedEventEmitter.md#once) *** ### onParamRamped() > `protected` **onParamRamped**(`_param`, `value`): `number` Defined in: [packages/core/src/effects/base-effect.ts:230](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L230) Hook invoked by `rampTo()` for every recognized non-`'mix'` parameter, immediately before the value is written to the AudioParam. Subclasses that expose shadow-state getters (any param whose setter uses `smoothParamSet`/clamping instead of a raw AudioParam) MUST override this to: 1. Apply the exact same validation/clamping their public setter uses 2. Store the clamped value in the shadow field so the getter stays honest 3. Return the clamped value `rampTo()` writes the value this hook returns to the AudioParam — so the ramped path can never write (or report via the getter) a value the synchronous setter would have rejected/clamped. Default: identity passthrough (no shadow state to keep in sync). #### Parameters ##### \_param `string` The parameter name being ramped ##### value `number` The raw, caller-supplied target value #### Returns `number` The value actually written to the AudioParam (and getter) *** ### rampTo() > **rampTo**(`param`, `value`, `duration`): `void` Defined in: [packages/core/src/effects/base-effect.ts:164](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L164) Smoothly ramp a parameter to a target value over a duration. Uses `AudioParam.setTargetAtTime` for glitch-free transitions. If the parameter name is not recognized, this is a no-op (a `console.warn` is emitted if the name is a real, documented effect property that just isn't backed by a single AudioParam — see [getUnrampableParams](#getunrampableparams)). **Single write path:** every ramped write is funneled through [onParamRamped](#onparamramped), the same hook subclasses use to keep their shadow getters honest. This guarantees `effect.someParam` reflects the ramp target immediately after calling `rampTo()`, and that the exact same validation/clamping a synchronous property-set would apply is also applied to ramped writes — the AudioParam and the getter can never diverge from each other. #### Parameters ##### param `string` Parameter name (e.g., 'frequency', 'time', 'feedback') ##### value `number` Target value ##### duration `number` Ramp duration in seconds #### Returns `void` #### Example ```typescript delay.rampTo('time', 0.5, 2) // Ramp delay time to 0.5s over 2 seconds filter.rampTo('frequency', 800, 1) // Ramp cutoff to 800Hz over 1 second ``` *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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"` ##### 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/ambient-generator.md' description: >- Create ambient soundscapes with layered oscillators and randomized parameters. Demonstrates generative audio techniques with the Web Audio API. --- # Ambient Sound Generator Create layered ambient soundscapes by combining oscillators and filtered white noise. This demo shows how to build complex, evolving textures from simple synthesis building blocks. Ambient soundscape generator with layered detuned oscillators, randomized panning, and fade-in/fade-out controls. ## How It Works This ambient generator combines three distinct layers to create a rich, evolving soundscape: ### 1. Drone Layer A low-frequency sine wave (60-120 Hz) provides the foundation. The drone uses a slow ADSR envelope with: * **Long attack (1s)**: Fades in gently * **High sustain (0.8)**: Maintains presence * **Long release (2s)**: Fades out smoothly This creates a pad-like quality that feels organic rather than mechanical. ### 2. Texture Layer White noise filtered through a lowpass filter creates atmospheric texture. By adjusting the filter cutoff frequency (200-4000 Hz), you can transform the sound from: * **Low frequencies (200-600 Hz)**: Deep rumble, like distant thunder * **Mid frequencies (600-1500 Hz)**: Wind or ocean waves * **High frequencies (1500-4000 Hz)**: Airy hiss or rain ### 3. Shimmer Layer A high-frequency triangle wave (400-800 Hz) adds ethereal overtones. Set to very low gain (0.08), it creates subtle brightness without dominating the mix. The long envelope (attack: 1.5s, release: 2.5s) ensures smooth transitions. ## Code Example Here's how to build an ambient generator from scratch: ```typescript import { createFilterEffect, createOscillator, createWhiteNoise } from 'ez-web-audio' // Create drone layer - low sine wave const drone = await createOscillator({ frequency: 80, type: 'sine', envelope: { attack: 1.0, decay: 0.5, sustain: 0.8, release: 2.0 } }) drone.changeGainTo(0.4) // Set mix level // Create texture layer - filtered white noise const texture = await createWhiteNoise() const lowpass = createFilterEffect('lowpass', { frequency: 800, q: 1.0 }) texture.addEffect(lowpass) texture.changeGainTo(0.15) // Create shimmer layer - high triangle wave const shimmer = await createOscillator({ frequency: 600, type: 'triangle', envelope: { attack: 1.5, decay: 0.3, sustain: 0.9, release: 2.5 } }) shimmer.changeGainTo(0.08) // Start all layers drone.play() texture.play() shimmer.play() // Wire sliders for real-time control droneSlider.addEventListener('input', (e) => { drone.update('frequency').to(Number(e.target.value)).as('ratio') }) textureSlider.addEventListener('input', (e) => { lowpass.frequency = Number(e.target.value) // 200–4000 Hz }) shimmerSlider.addEventListener('input', (e) => { shimmer.update('frequency').to(Number(e.target.value)).as('ratio') }) // Stop all layers drone.stop() texture.stop() shimmer.stop() ``` Oscillator frequencies use `update().to().as('ratio')` for smooth transitions. Filter parameters like `frequency` and `q` can be assigned directly. ## API Used This example demonstrates: * `createOscillator()` - Create synthesized tones with configurable waveforms and envelopes * `createWhiteNoise()` - Generate white noise for texture and atmosphere * `createFilterEffect()` - Create filters for tone shaping * `changeGainTo()` - Control volume levels for mixing * `update().to().as()` - Real-time parameter changes * `addEffect()` - Route audio through effects ## Next Steps * **[Effects](/examples/effects)** - Learn more about filter types and parameters * **[Synth Keyboard](/examples/synth-keyboard)** - Explore ADSR envelopes in musical context * **[Audio Routing](/examples/audio-routing)** - Advanced effect routing techniques --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/effects.md' description: >- Add audio effects to sounds using the Web Audio API. Interactive filter demo with lowpass, highpass, bandpass, and distortion with custom waveshaper curves. --- # Effects Shape your audio with filters, gain effects, and custom audio processing. This page covers the built-in effects, effect chains, and integrating external effect libraries. ## Try It: Real-Time Filter Control Experiment with different filter types and parameters. Try switching between the oscillator and white noise sources to hear how filters affect different signals. Interactive audio filter demo: apply lowpass, highpass, bandpass, and notch filters to a loaded audio sample. Adjust frequency cutoff and Q factor with sliders. ### Replicating This Demo The demo above creates a filter, adds it to a sound, and updates parameters from slider inputs: ```typescript import { createFilterEffect, createOscillator } from 'ez-web-audio' // Create an audio source const osc = await createOscillator({ frequency: 200, type: 'sawtooth' }) osc.changeGainTo(0.3) // Create a filter and add it to the source const filter = createFilterEffect('lowpass', { frequency: 1000, q: 1 }) osc.addEffect(filter) osc.play() // Wire UI controls to filter parameters — updates are instant frequencySlider.addEventListener('input', (e) => { filter.frequency = Number(e.target.value) }) qSlider.addEventListener('input', (e) => { filter.q = Number(e.target.value) }) // Toggle bypass for A/B comparison bypassCheckbox.addEventListener('change', (e) => { filter.bypass = e.target.checked }) ``` Filter properties (`frequency`, `q`, `gain`, `bypass`) are mutable — assign new values and the audio updates immediately. No scheduling or method calls needed. ## Effect Types EZ Web Audio provides two built-in effect types and a wrapper for external effects: | Effect | Purpose | Use Cases | |--------|---------|-----------| | `FilterEffect` | Frequency-based tone shaping | EQ, bass boost, removing harshness | | `GainEffect` | Volume control in effect chain | Ducking, sidechain, level matching | | `EffectWrapper` | Wrap external effects | Tuna.js, custom AudioNodes | ## FilterEffect Filters modify the frequency content of audio. The FilterEffect wraps the Web Audio BiquadFilterNode with wet/dry mixing and bypass controls. ### Filter Types | Type | Description | Key Parameters | |------|-------------|----------------| | `lowpass` | Passes frequencies below cutoff | frequency, q | | `highpass` | Passes frequencies above cutoff | frequency, q | | `bandpass` | Passes frequencies around center | frequency, q | | `lowshelf` | Boosts/cuts below frequency | frequency, gain | | `highshelf` | Boosts/cuts above frequency | frequency, gain | | `peaking` | Boosts/cuts around frequency | frequency, q, gain | | `notch` | Removes specific frequency | frequency, q | | `allpass` | Phase shift at frequency | frequency, q | ### Creating Filters ```typescript import { createFilterEffect, createSound } from 'ez-web-audio' const sound = await createSound('/audio/music.mp3') // Lowpass filter - remove high frequencies const lowpass = createFilterEffect('lowpass', { frequency: 1000, // Cutoff frequency in Hz q: 1 // Resonance (default: 1) }) sound.addEffect(lowpass) sound.play() ``` ### Shelf and Peaking Filters Shelf and peaking filters have an additional `gain` parameter (in dB) that controls boost/cut: ```typescript const shelf = createFilterEffect('highshelf', { frequency: 3000, gain: 6 // Boost by 6dB above 3000 Hz }) // Adjust gain in real-time shelf.gain = -3 // Cut by 3dB instead ``` ### Common Filter Recipes #### Bass Boost ```typescript const bassBoost = createFilterEffect('lowshelf', { frequency: 200, gain: 8 // +8dB boost below 200Hz }) ``` #### Remove Harsh Frequencies ```typescript const deHarsh = createFilterEffect('lowpass', { frequency: 8000, q: 0.7 // Gentle rolloff }) ``` #### Telephone/Radio Effect ```typescript // Remove lows const highpass = createFilterEffect('highpass', { frequency: 300 }) // Remove highs const lowpass = createFilterEffect('lowpass', { frequency: 3400 }) sound.addEffect(highpass) sound.addEffect(lowpass) ``` #### Notch Filter (Remove Hum) ```typescript const removeHum = createFilterEffect('notch', { frequency: 60, // 60Hz power line hum q: 30 // Narrow notch }) ``` ## GainEffect GainEffect provides volume control within the effect chain. Unlike the sound's built-in gain, this can be positioned anywhere in the effect chain. ```typescript import { createGainEffect } from 'ez-web-audio' const gainEffect = createGainEffect(0.5) // 50% volume // Adjust volume gainEffect.value = 0.8 // 80% volume gainEffect.value = 1.5 // 150% (boost) ``` ### Gain Before vs After Filter ```typescript // Gain BEFORE filter: affects what goes into the filter const preGain = createGainEffect(2.0) const filter = createFilterEffect('lowpass', { frequency: 1000 }) sound.addEffect(preGain) // First: boost signal sound.addEffect(filter) // Second: filter boosted signal // Gain AFTER filter: affects final output const postGain = createGainEffect(0.5) sound.addEffect(filter) sound.addEffect(postGain) ``` ## Effect Chains Effects are processed in order. The audio signal flows through each effect sequentially. ``` Audio Source -> Effect 1 -> Effect 2 -> Effect 3 -> Gain -> Pan -> Destination ``` ### Building an Effect Chain ```typescript const sound = await createSound('/audio/sample.mp3') // Create effects const highpass = createFilterEffect('highpass', { frequency: 80 }) const lowpass = createFilterEffect('lowpass', { frequency: 8000 }) const boost = createGainEffect(1.2) // Add in order (highpass first, then lowpass, then boost) sound.addEffect(highpass) sound.addEffect(lowpass) sound.addEffect(boost) sound.play() ``` ### Managing Effects ```typescript // Get current effects const effects = sound.getEffects() console.log(`${effects.length} effects in chain`) // Remove a specific effect sound.removeEffect(lowpass) // Insert effect at specific position const newEffect = createFilterEffect('peaking', { frequency: 1000 }) sound.addEffect(newEffect, 0) // Insert at beginning ``` ## Bypass and Mix Controls Every effect supports bypass (on/off) and mix (wet/dry blend): ```typescript const filter = createFilterEffect('lowpass', { frequency: 800 }) // Bypass: temporarily disable the effect filter.bypass = true // Effect is bypassed (100% dry signal) filter.bypass = false // Effect is active // Mix: blend between dry (original) and wet (processed) signal filter.mix = 0 // 0% wet = original signal only filter.mix = 0.5 // 50% wet = equal blend filter.mix = 1 // 100% wet = fully processed (default) ``` ::: tip Wet/Dry Mixing The mix control uses equal-power crossfade for natural-sounding blending. This prevents volume dips when mixing between dry and wet signals. ::: ### Toggling Effects On/Off ```typescript const filter = createFilterEffect('lowpass', { frequency: 800 }) sound.addEffect(filter) // Toggle effect bypass function toggleFilter() { filter.bypass = !filter.bypass // Effect chain rewires automatically when bypass is toggled } ``` ## External Effects with wrapEffect Use `wrapEffect` to integrate effects from external libraries (like Tuna.js) or custom AudioNodes. ### Wrapping a WaveShaper (Distortion) ```typescript import { getAudioContext, wrapEffect } from 'ez-web-audio' const ctx = await getAudioContext() // Create a WaveShaperNode for distortion const distortion = ctx.createWaveShaper() distortion.curve = makeDistortionCurve(400) distortion.oversample = '4x' // Wrap it to get bypass/mix controls const wrapped = wrapEffect(distortion) wrapped.mix = 0.7 // 70% distortion sound.addEffect(wrapped) ``` ### Wrapping Tuna.js Effects [Tuna.js](https://github.com/Theodeus/tuna) provides additional effects like chorus, phaser, and tremolo. ```typescript import { getAudioContext, wrapEffect } from 'ez-web-audio' import Tuna from 'tunajs' const ctx = await getAudioContext() const tuna = new Tuna(ctx) // Create a chorus effect const chorus = new tuna.Chorus({ rate: 1.5, feedback: 0.2, delay: 0.0045, bypass: false }) // Wrap it for standard Effect interface const wrapped = wrapEffect(chorus) wrapped.mix = 0.5 // 50% chorus blend sound.addEffect(wrapped) // Access original effect parameters wrapped.effect.rate = 2.0 // Adjust Tuna's parameters ``` ### The ExternalEffect Interface Any object with a `connect()` method can be wrapped: ```typescript interface ExternalEffect { connect: (destination: AudioNode) => void } ``` This includes: * Native AudioNodes (WaveShaperNode, ConvolverNode, DelayNode) * Tuna.js effects * Custom effect chains * Third-party Web Audio libraries ## Using an Analyzer for Visualization Attach an Analyzer to visualize the processed audio signal: ```typescript import { createAnalyzer, createFilterEffect, createSound, getAudioContext } from 'ez-web-audio' const sound = await createSound('/audio/music.mp3') const ctx = await getAudioContext() // Add effects const filter = createFilterEffect('lowpass', { frequency: 2000 }) sound.addEffect(filter) // Create and attach analyzer const analyzer = await createAnalyzer(ctx, { fftSize: 2048, smoothingTimeConstant: 0.8 }) sound.setAnalyzer(analyzer) function draw() { requestAnimationFrame(draw) const dataArray = analyzer.getFrequencyData() // Use dataArray to draw visualization } sound.play() draw() ``` ::: info Analyzer Position The analyzer is always at the end of the signal chain (after all effects, gain, and pan). This means it visualizes the fully processed audio that you hear. ::: ## Complete Example: DJ-Style EQ ```typescript import { createFilterEffect, createTrack } from 'ez-web-audio' const track = await createTrack('/audio/song.mp3') // Three-band EQ const lowEQ = createFilterEffect('lowshelf', { frequency: 320, gain: 0 // Will be adjusted by user }) const midEQ = createFilterEffect('peaking', { frequency: 1000, q: 0.5, gain: 0 }) const highEQ = createFilterEffect('highshelf', { frequency: 3200, gain: 0 }) track.addEffect(lowEQ) track.addEffect(midEQ) track.addEffect(highEQ) // Adjust EQ from UI sliders function updateEQ(band: 'low' | 'mid' | 'high', dB: number) { switch (band) { case 'low': lowEQ.gain = dB; break case 'mid': midEQ.gain = dB; break case 'high': highEQ.gain = dB; break } } track.play() ``` ## Next Steps * [Basic Playback](/examples/basic-playback) - Load and play audio files * [Synthesis](/examples/synthesis) - Generate sounds with oscillators * [Audio Routing](/examples/audio-routing) - Connect sounds to custom effects * [Synth Drum Kit](/examples/synth-drum-kit) - Build synthesized percussion * [Core Concepts](/guide/concepts) - Understand the audio system architecture --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/audio-routing.md' description: >- Route audio through custom effect chains with gain, filters, and distortion. Visualize the signal path from source through effects to output. --- # Audio Routing & Custom Effects Learn how to integrate custom Web Audio effects into your signal chain using the adapter pattern. *The chain every sound flows through, from source to speakers.* Audio routing demo with distortion effect: toggle distortion on/off, adjust distortion amount, and hear the effect on a loaded audio sample. ### Replicating This Demo The demo above creates an oscillator, wraps a WaveShaper as an effect, and wires sliders to update parameters in real-time: ```typescript import { createOscillator, getAudioContext, wrapEffect } from 'ez-web-audio' const osc = await createOscillator({ frequency: 200, type: 'sine' }) osc.changeGainTo(0.3) osc.play() // Create and wrap a WaveShaper distortion effect const ctx = await getAudioContext() const distNode = ctx.createWaveShaper() distNode.curve = makeDistortionCurve(400) distNode.oversample = '4x' const effect = wrapEffect(distNode) effect.mix = 0.7 osc.addEffect(effect) // Wire sliders to effect parameters amountSlider.addEventListener('input', (e) => { // Update the underlying WaveShaper curve distNode.curve = makeDistortionCurve(Number(e.target.value)) }) mixSlider.addEventListener('input', (e) => { effect.mix = Number(e.target.value) // 0 = dry, 1 = wet }) bypassCheckbox.addEventListener('change', (e) => { effect.bypass = e.target.checked // Routes audio around the effect }) // Dynamically remove the effect osc.removeEffect(effect) // Signal chain reconnects automatically ``` The key pattern: `wrapEffect()` gives any AudioNode a consistent interface with `mix` and `bypass` properties. Update `mix` and `bypass` directly — changes apply immediately. For the underlying node's own parameters (like WaveShaper's `curve`), access it via `effect.effect`. ## How Effects Work Every sound in ez-web-audio has a signal chain: ``` Source → [Effects] → Gain → Pan → Destination ``` The **`wrapEffect()`** function is an adapter that makes any Web Audio `AudioNode` work with ez-web-audio's effect system. It handles routing, gain mixing, and bypass switching automatically. ### The Adapter Pattern Web Audio nodes have `input` and `output` points. The `wrapEffect()` function wraps any node with a consistent interface: ```typescript interface Effect { input: AudioNode // Connect audio to this output: AudioNode // Connect this to next node bypass: boolean // true = route around effect mix: number // 0-1, wet/dry balance } ``` This means you can use **any** Web Audio effect — built-in or from a library — with the same API. ## Basic Effect Integration Here's how to add a WaveShaper distortion effect: ```typescript import { createOscillator, getAudioContext, wrapEffect } from 'ez-web-audio' // Create audio source const oscillator = await createOscillator({ frequency: 200, type: 'sawtooth' }) // Get the AudioContext const ctx = await getAudioContext() // Create a WaveShaper node for distortion const distortionNode = ctx.createWaveShaper() distortionNode.curve = makeDistortionCurve(400) distortionNode.oversample = '4x' // Wrap it with ez-web-audio's effect interface const effect = wrapEffect(distortionNode) effect.mix = 0.7 // 70% wet, 30% dry // Add to the signal chain oscillator.addEffect(effect) // Start playback oscillator.play() ``` ### Creating a Distortion Curve The WaveShaper distortion curve is a mathematical function that shapes the waveform: ```typescript function makeDistortionCurve(amount: number): Float32Array { const samples = 44100 const curve = new Float32Array(samples) const deg = Math.PI / 180 for (let i = 0; i < samples; i++) { const x = (i * 2) / samples - 1 curve[i] = ((3 + amount) * x * 20 * deg) / (Math.PI + amount * Math.abs(x)) } return curve } ``` Higher `amount` values create more aggressive distortion by applying a steeper transfer function. ## Mix and Bypass Controls Every wrapped effect has built-in wet/dry mixing and bypass: ```typescript // Adjust wet/dry balance (0 = dry only, 1 = wet only) effect.mix = 0.5 // 50/50 blend // Bypass the effect entirely (routes audio around it) effect.bypass = true // Re-enable effect.bypass = false ``` This makes it easy to implement A/B comparison and effect intensity controls. ## Removing Effects Effects can be dynamically added and removed: ```typescript // Add effect oscillator.addEffect(effect) // Remove effect oscillator.removeEffect(effect) ``` The signal chain automatically reconnects when effects are removed. ## Beyond Distortion The adapter pattern works with **any** Web Audio node: ### Reverb (ConvolverNode) ```typescript const convolver = ctx.createConvolver() convolver.buffer = await loadImpulseResponse('/audio/hall-reverb.wav') const reverb = wrapEffect(convolver) reverb.mix = 0.3 sound.addEffect(reverb) ``` ### Delay (DelayNode + Feedback) ```typescript const delay = ctx.createDelay() delay.delayTime.value = 0.5 const feedback = ctx.createGain() feedback.gain.value = 0.4 // Connect delay output to feedback, feedback to delay input delay.connect(feedback) feedback.connect(delay) const delayEffect = wrapEffect(delay) sound.addEffect(delayEffect) ``` ### Third-Party Effect Libraries You can also integrate external effect libraries like [Tuna.js](https://github.com/Theodeus/tuna): ```typescript import Tuna from 'tunajs' const tuna = new Tuna(ctx) const chorus = new tuna.Chorus({ rate: 1.5, feedback: 0.2, delay: 0.0045 }) const chorusEffect = wrapEffect(chorus) sound.addEffect(chorusEffect) ``` ## API Used * **`wrapEffect(node)`** — Wrap any AudioNode with ez-web-audio's effect interface * **`sound.addEffect(effect)`** — Add effect to signal chain * **`sound.removeEffect(effect)`** — Remove effect from signal chain * **`effect.bypass`** — Boolean to bypass effect * **`effect.mix`** — Number (0-1) for wet/dry balance * **`getAudioContext()`** — Get the global AudioContext ## Next Steps * [Sampled Drum Kit](/examples/sampled-drum-kit) — Multi-zone velocity-sensitive pads * [Synth Keyboard](/examples/synth-keyboard) — Oscillator playground with filter controls * [Why Timing Drifts](/examples/timing) — Master Web Audio's scheduling system --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/audio-sprite.md' description: >- Pack multiple sounds into a single audio file and play each by name. Supports both Howler.js and audiosprite manifest formats. --- # Audio Sprites — Multiple Sounds from One File Audio sprites bundle multiple short sounds into one file, reducing HTTP requests. Click below to hear how it works. Audio sprite player: plays the full combined audio file, then individual named segments from a sprite manifest. Visual timeline shows colored segments with highlight on play. ## What Just Happened? All 6 sounds you heard — beep, cannon, whoosh, bling, punch, fanfare — are packed into **a single MP3 file**. Instead of 6 HTTP requests, the browser loads one file and plays named segments within it. A **manifest** maps each name to a time region: ``` ┌──────┬────────┬───────┬──────┬───────┬─────────┐ │ beep │ cannon │ whoosh│ bling│ punch │ fanfare │ │ 0.0s │ 0.67s │ 2.9s │ 4.2s │ 6.7s │ 7.7s │ └──────┴────────┴───────┴──────┴───────┴─────────┘ ``` `createSprite()` loads the file once, then plays segments by name. This technique is especially useful for games and interactive apps with many short sound effects — fewer requests means faster loading. ## Sprite Formats EZ Web Audio accepts two popular manifest formats. Format detection is automatic based on the top-level key. ### audiosprite format Uses `spritemap` with second-based `{start, end}` objects: ```json { "spritemap": { "laser": { "start": 0, "end": 0.3 }, "explosion": { "start": 1.0, "end": 2.5, "loop": false } } } ``` ### Howler.js format Uses `sprite` with millisecond-based tuples `[offset_ms, duration_ms]`: ```json { "sprite": { "laser": [0, 300], "explosion": [1000, 1500], "powerup": [4000, 500, true] } } ``` Howler tuples are `[offset_ms, duration_ms]` with an optional third boolean for looping. EZ Web Audio detects which format you're using and normalizes internally — you don't need to convert anything. ## Basic Usage ```typescript import { createSprite } from 'ez-web-audio' // audiosprite format const sprite = await createSprite('sounds.mp3', { spritemap: { laser: { start: 0, end: 0.3 }, explosion: { start: 1.0, end: 2.5 }, }, }) // Or Howler format — works the same way const sprite2 = await createSprite('sounds.mp3', { sprite: { laser: [0, 300], explosion: [1000, 1500], }, }) sprite.play('laser') sprite.play('explosion', { gain: 0.7 }) ``` ## Looping and Stopping Set `loop: true` in the sprite definition to enable seamless looping: ```typescript const sprite = await createSprite('sounds.mp3', { spritemap: { engine: { start: 0.0, end: 2.0, loop: true }, hit: { start: 2.5, end: 2.8 }, }, }) // Start looping engine sound sprite.play('engine') // Stop the loop when done sprite.stop('engine') // Stop all active playback sprite.stopAll() ``` ## Creating Sprites You can create sprite files manually or use tools: * **[audiosprite CLI](https://github.com/tonistiigi/audiosprite)** — Concatenates audio files and generates manifest JSON automatically. Install with `npm install -g audiosprite`, then run `audiosprite -o output -e mp3 sound1.mp3 sound2.mp3`. * **[soundfx](https://github.com/rse/soundfx)** — A ready-made collection of CC-licensed sound effects, perfect for prototyping and demos. ::: tip Silence Gaps When creating sprites manually, add ~200ms of silence between sounds to prevent bleed from MP3 encoding artifacts. ::: ## Attribution > Sound effects in the demo from the [soundfx](https://github.com/rse/soundfx) collection. Individual sounds by JustinBW, dersuperanton, and *MC5* via [FreeSound](https://freesound.org) (CC-BY-3.0), and nps.gov and Vladimir via [SoundBible](https://soundbible.com) (CC-0). ## Next Steps * [Basic Playback](/examples/basic-playback) — Playing individual sounds * [Sampled Drum Kit](/examples/synth-drum-kit) — Using `createSampler()` for round-robin playback * [LayeredSound](/examples/layered-sound) — Play multiple sounds in perfect sync --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/timing.md' description: >- Learn precise audio scheduling with play(), playIn(), and playAt() methods. Interactive demo showing immediate, delayed, and scheduled sound playback. --- # Why Timing Drifts Master Web Audio's scheduling system for precise, synchronized playback. ## Quick Reference The interactive demo below shows four timing methods: ```typescript // 1. Immediate playback sound.play() // 2. Delayed playback (relative) sound.playIn(1) // plays in 1 second // 3. Precise scheduling (absolute) const ctx = await getAudioContext() sound.playAt(ctx.currentTime + 0.5) // plays at exact time // 4. Perfect sync - multiple sounds at same time const now = ctx.currentTime osc1.playAt(now) osc2.playAt(now) osc3.playAt(now) ``` Timing and scheduling demo: immediate playback with play(), delayed playback with playIn(), and precise scheduled playback with playAt(). ## Why Timing Matters JavaScript's `setTimeout` and `setInterval` are unreliable for audio timing. They can drift by hundreds of milliseconds due to browser throttling, event loop congestion, and background tab deprioritization. Web Audio's timing system runs on a separate, high-priority thread with **sample-accurate precision**. The `AudioContext.currentTime` clock is independent of the JavaScript main thread and always advances at exactly the audio sample rate. This means: * No drift or jitter * Perfect synchronization across multiple sounds * Accurate scheduling even in background tabs * Reliable timing for musical applications ## Timing Methods | Method | Use Case | Example | |--------|----------|---------| | `play()` | Immediate playback | `sound.play()` | | `playIn(seconds)` | Delayed playback (relative) | `sound.playIn(1)` plays in 1 second | | `playAt(time)` | Scheduled playback (absolute) | `sound.playAt(ctx.currentTime + 0.5)` | ## Perfect Synchronization When you need multiple sounds to start at exactly the same moment, use `playAt()` with `audioContext.currentTime`: ```typescript import { createOscillator, getAudioContext } from 'ez-web-audio' const ctx = await getAudioContext() const now = ctx.currentTime // All three oscillators start at EXACTLY the same sample const c = await createOscillator({ frequency: 261.63 }) const e = await createOscillator({ frequency: 329.63 }) const g = await createOscillator({ frequency: 392.00 }) c.playAt(now) e.playAt(now) g.playAt(now) ``` This achieves **sample-perfect synchronization** — the kind of precision impossible with JavaScript timers. ## Immediate Playback For simple cases where you just want to play a sound right now: ```typescript import { createSound } from 'ez-web-audio' // Must be called in response to user interaction (e.g., button click) const sound = await createSound('/audio/click.mp3') sound.play() ``` ## Delayed Playback Schedule a sound to play after a delay using `playIn()`: ```typescript const sound = await createSound('/audio/kick.mp3') // Play in 1 second sound.playIn(1) // Play in 500ms sound.playIn(0.5) ``` Behind the scenes, `playIn()` converts the relative delay to an absolute time using `audioContext.currentTime + seconds`. ## Scheduled Playback For precise control, use `playAt()` with absolute times from the audio clock: ```typescript import { createSound, getAudioContext } from 'ez-web-audio' const ctx = await getAudioContext() const now = ctx.currentTime const kick = await createSound('/audio/kick.mp3') const snare = await createSound('/audio/snare.mp3') const hihat = await createSound('/audio/hihat.mp3') // Schedule a drum pattern kick.playAt(now + 0.0) // Beat 1 hihat.playAt(now + 0.25) // 16th note later snare.playAt(now + 0.5) // Beat 2 hihat.playAt(now + 0.75) // Another 16th kick.playAt(now + 1.0) // Beat 3 ``` All scheduling happens instantly in JavaScript. The sounds will play at their scheduled times with sample-accurate precision, even if your JavaScript code blocks or the tab loses focus. ## API Used * **`play()`** — Play sound immediately * **`playIn(seconds)`** — Play sound after a delay * **`playAt(time)`** — Play sound at specific audio clock time * **`getAudioContext()`** — Get the global AudioContext * **`audioContext.currentTime`** — Current time on the audio clock (in seconds) ## Next Steps * [Drum Machine](/examples/drum-machine) — Build rhythmic patterns with `BeatTrack` * [Sampled Drum Kit](/examples/sampled-drum-kit) — Multi-zone drum pad with velocity layers * [Audio Routing](/examples/audio-routing) — Add custom effects to the signal chain --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/visualization.md' description: >- Visualize audio in real-time with frequency spectrum and waveform displays using the Web Audio AnalyserNode. Canvas-based rendering with customizable FFT size. --- # Audio Visualization Visualize audio in real-time using the Analyzer API. This demo shows both frequency spectrum (FFT) and time-domain waveform visualization. Real-time audio visualization demo: waveform and frequency spectrum displays rendered on canvas using AnalyserNode with configurable FFT size. ## How It Works Audio visualization uses the Web Audio API's `AnalyserNode` to extract frequency and waveform data from any audio source. EZ Web Audio provides a simple interface through the `Analyzer` class. ### Frequency Spectrum (FFT) The frequency spectrum visualization shows the amplitude of different frequencies present in the audio. It uses Fast Fourier Transform (FFT) to convert time-domain audio data into frequency-domain data. * **Lower frequencies** (left side) represent bass tones * **Higher frequencies** (right side) represent treble tones * **Bar height** represents amplitude at that frequency * **FFT size** controls resolution (more bars = higher detail) ### Time-Domain Waveform The waveform visualization shows the actual audio signal over time. This is the "raw" audio data before FFT processing. * **X-axis** represents time * **Y-axis** represents amplitude * Different **waveform types** produce distinctive shapes: * **Sine**: Smooth wave * **Square**: Flat tops and bottoms * **Sawtooth**: Sharp, ramp-like pattern * **Triangle**: Linear rise and fall ## Code Example Here's how to set up audio visualization from scratch: ```typescript import { createAnalyzer, createOscillator, getAudioContext } from 'ez-web-audio' // Create an audio source (oscillator in this case) const oscillator = await createOscillator({ frequency: 440, type: 'sine' }) oscillator.changeGainTo(0.3) // Create an analyzer with FFT size const audioContext = await getAudioContext() const analyzer = await createAnalyzer(audioContext, { fftSize: 1024 }) // Connect the oscillator to the analyzer oscillator.setAnalyzer(analyzer) // Start playing oscillator.play() // Set up canvas const canvas = document.getElementById('visualizer') as HTMLCanvasElement const ctx = canvas.getContext('2d')! canvas.width = 800 canvas.height = 200 // Animation loop for frequency spectrum function drawFrequencySpectrum() { const frequencyData = analyzer.getFrequencyData() const barWidth = canvas.width / frequencyData.length // Clear canvas ctx.fillStyle = '#000' ctx.fillRect(0, 0, canvas.width, canvas.height) // Draw bars for (let i = 0; i < frequencyData.length; i++) { const barHeight = (frequencyData[i] / 255) * canvas.height const x = i * barWidth const y = canvas.height - barHeight // Color gradient based on frequency const hue = (i / frequencyData.length) * 240 ctx.fillStyle = `hsl(${240 - hue}, 70%, 50%)` ctx.fillRect(x, y, barWidth - 1, barHeight) } requestAnimationFrame(drawFrequencySpectrum) } drawFrequencySpectrum() ``` ### Waveform Visualization ```typescript // Same analyzer from above function drawWaveform() { const waveformData = analyzer.getTimeDomainData() // Clear canvas ctx.fillStyle = '#000' ctx.fillRect(0, 0, canvas.width, canvas.height) // Draw waveform line ctx.lineWidth = 2 ctx.strokeStyle = '#0f0' ctx.beginPath() const sliceWidth = canvas.width / waveformData.length let x = 0 for (let i = 0; i < waveformData.length; i++) { const v = waveformData[i] / 128.0 // Normalize to 0-2 const y = (v * canvas.height) / 2 if (i === 0) { ctx.moveTo(x, y) } else { ctx.lineTo(x, y) } x += sliceWidth } ctx.stroke() requestAnimationFrame(drawWaveform) } drawWaveform() ``` ## Using Analyzer with Different Sound Sources The analyzer works with any sound type: ```typescript import { createAnalyzer, createSound, getAudioContext } from 'ez-web-audio' // Visualize a music track const track = await createSound('music.mp3') const audioContext = await getAudioContext() const analyzer = await createAnalyzer(audioContext, { fftSize: 2048 }) track.setAnalyzer(analyzer) track.play() // Now use analyzer.getFrequencyData() or analyzer.getTimeDomainData() // in your animation loop as shown above ``` ## FFT Size and Resolution The FFT size determines the resolution of frequency analysis: | FFT Size | Frequency Bins | Time Resolution | Best For | |----------|----------------|-----------------|----------| | 256 | 128 | Fastest | Simple visualizers, performance-critical | | 512 | 256 | Fast | Most visualizers | | 1024 | 512 | Balanced | Detailed frequency analysis | | 2048 | 1024 | Slower | Maximum detail, music analysis | Higher FFT sizes provide more frequency detail but update slightly slower. Most visualizations work best with 512-1024. ## API Used This example demonstrates: * `createAnalyzer()` - Create an analyzer for audio visualization * `setAnalyzer()` - Connect a sound to an analyzer * `getFrequencyData()` - Get frequency spectrum data (0-255 for each frequency bin) * `getTimeDomainData()` - Get waveform data (0-255 for each time sample) * Canvas rendering with `requestAnimationFrame()` for smooth animation ## Next Steps * **[Ambient Generator](/examples/ambient-generator)** - Create layered ambient soundscapes * **[Effects](/examples/effects)** - Apply filters and see their effect on the spectrum * **[Synth Keyboard](/examples/synth-keyboard)** - Try different waveforms and envelopes --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/basic-playback.md' description: >- Learn how to load and play audio files in the browser using JavaScript. Simple one-shot playback, music tracks with pause/resume/seek, and oscillator synthesis. --- # Basic Playback Learn how to load and play audio files with EZ Web Audio. This page covers the two main ways to play audio: **Sound** for one-shot effects and **Track** for music with playback control. ## Try It: Sound Demo Click the button to play a sound effect. Adjust volume and pan before or after playing. Basic audio playback demo: click to load and play a sound effect with volume and pan controls. ### Code ```typescript import { createSound } from 'ez-web-audio' // Load and play a sound on user interaction button.addEventListener('click', async () => { const click = await createSound('/audio/click.mp3') click.play() }) ``` ## Try It: Track Demo Tracks provide full playback control for music: play, pause, resume, seek, and position tracking. The demo above is built with the code below. Music track demo with play/pause/stop controls, seek slider, and real-time position display showing current time and progress percentage. ### Code ```typescript import { createTrack } from 'ez-web-audio' const track = await createTrack('/audio/music.mp3') // Play / pause toggle function playPause() { if (track.isPlaying) { track.pause() } else { track.play() } } // Stop resets to the beginning function stop() { track.stop() } // Seek to a specific time (e.g. from a slider's value) function onSeek(seconds: number) { track.seek(seconds).as('seconds') } // Live position tracking with requestAnimationFrame function updateDisplay() { if (track.isPlaying) { console.log(track.position.string) // '0:45' console.log(track.percentPlayed) // 25 requestAnimationFrame(updateDisplay) } } // Start the display loop whenever playback begins or resumes track.on('play', updateDisplay) track.on('resume', updateDisplay) ``` ## Sound vs Track Choose the right class for your use case: | Feature | Sound | Track | |---------|-------|-------| | **Use case** | Sound effects, UI sounds | Music, podcasts, long audio | | **Overlapping plays** | Yes - each `play()` creates new source | No - one playback at a time | | **Pause/Resume** | No | Yes | | **Seek** | No | Yes | | **Position tracking** | No | Yes (position, percentPlayed) | | **Duration** | Available | Available | | **Events** | play, stop, end | play, stop, end, pause, resume | ### When to Use Sound ```typescript // Sound effects that may overlap const laser = await createSound('laser.mp3') // Rapid fire - each call creates a new playback laser.play() laser.play() // Overlaps with previous laser.play() // All three play simultaneously ``` ### When to Use Track ```typescript // Music with playback control const song = await createTrack('song.mp3') song.play() // User clicks pause button song.pause() // User clicks play button song.resume() // Continues from where it paused ``` ## Volume and Pan Control Both Sound and Track support volume (gain) and stereo position (pan): ```typescript const sound = await createSound('click.mp3') // Volume: 0 (silent) to 1 (full volume), can exceed 1 for boost sound.changeGainTo(0.5) // 50% volume // Pan: -1 (left) to 1 (right), 0 is center sound.changePanTo(-1) // Full left sound.changePanTo(0) // Center sound.changePanTo(1) // Full right sound.play() ``` ## Track Position and Duration Track provides timing info in multiple formats: ```typescript const track = await createTrack('song.mp3') // Duration track.duration.raw // 180.5 (seconds) track.duration.string // '3:00' track.duration.pojo // { minutes: 3, seconds: 0 } // Current position (updates during playback) track.position.raw // 45.2 (seconds) track.position.string // '0:45' // Progress as percentage (0–100) track.percentPlayed // 25 ``` ## Track Events ```typescript track.on('play', () => { /* playback started */ }) track.on('pause', () => { /* paused */ }) track.on('resume', () => { /* resumed after pause */ }) track.on('stop', () => { /* stopped programmatically */ }) track.on('end', () => { /* reached the end naturally */ }) ``` ## Preloading Audio For better user experience, preload audio before it's needed: ```typescript import { createSound, isPreloaded, preload } from 'ez-web-audio' // Preload during app initialization await preload([ '/audio/click.mp3', '/audio/success.mp3', '/audio/error.mp3' ]) // Later, createSound uses cached data const click = await createSound('/audio/click.mp3') // Fast! // Check if a file is preloaded if (isPreloaded('/audio/music.mp3')) { console.log('Ready to play immediately') } ``` ## Error Handling Handle loading and playback errors gracefully: ```typescript import { AudioContextError, AudioLoadError, createSound } from 'ez-web-audio' try { const sound = await createSound('/audio/missing.mp3') sound.play() } catch (error) { if (error instanceof AudioLoadError) { console.error('Failed to load audio:', error.url) } else if (error instanceof AudioContextError) { console.error('Audio system error:', error.message) } } ``` ## Next Steps * [Synthesis](/examples/synthesis) - Generate sounds with oscillators * [Effects](/examples/effects) - Add filters and effects to your audio * [Core Concepts](/guide/concepts) - Understand the audio system architecture --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/classes/AggregateAudioLoadError.md --- [EZ Web Audio](../index.md) / AggregateAudioLoadError # Class: AggregateAudioLoadError Defined in: [packages/core/src/errors/load-error.ts:61](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/load-error.ts#L61) Error thrown when `preload()` fails to load one or more URLs in a batch. Extends [AudioError](AudioError.md) (so `instanceof AudioError` still matches — see the catch-all pattern documented there) while preserving the individual per-URL failures via [errors](#errors), so callers that need to know exactly which URLs failed (and why) don't have to string-parse the aggregate message. ## Example ```typescript try { await preload(['a.mp3', 'b.mp3']); } catch (e) { if (e instanceof AggregateAudioLoadError) { for (const err of e.errors) { console.error(`Failed: ${err.url} — ${err.message}`); } } } ``` ## Extends * [`AudioError`](AudioError.md) ## Constructors ### Constructor > **new AggregateAudioLoadError**(`message`, `errors`): `AggregateAudioLoadError` Defined in: [packages/core/src/errors/load-error.ts:68](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/load-error.ts#L68) Create a new AggregateAudioLoadError. #### Parameters ##### message `string` Human-readable summary of the batch failure ##### errors [`AudioLoadError`](AudioLoadError.md)\[] The individual per-URL AudioLoadError failures #### Returns `AggregateAudioLoadError` #### Overrides [`AudioError`](AudioError.md).[`constructor`](AudioError.md#constructor) ## Properties ### code? > `readonly` `optional` **code**: `string` Defined in: [packages/core/src/errors/audio-error.ts:34](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/audio-error.ts#L34) Optional error code for programmatic handling #### Inherited from [`AudioError`](AudioError.md).[`code`](AudioError.md#code) *** ### errors > `readonly` **errors**: [`AudioLoadError`](AudioLoadError.md)\[] Defined in: [packages/core/src/errors/load-error.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/load-error.ts#L70) The individual per-URL AudioLoadError failures --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Analyzer.md' --- [EZ Web Audio](../index.md) / Analyzer # Class: Analyzer Defined in: [packages/core/src/analyzer.ts:61](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L61) Analyzer class for audio visualization. Wraps the Web Audio AnalyserNode with a convenient API for getting frequency and waveform data. Uses pre-allocated typed arrays for zero-allocation polling. ## Example ```typescript const analyzer = createAnalyzer(audioContext, { fftSize: 2048 }) sound.setAnalyzer(analyzer) function draw() { const freqData = analyzer.getFrequencyData() // Draw frequency bars using freqData values (0-255) const waveData = analyzer.getTimeDomainData() // Draw oscilloscope waveform using waveData (128 = zero crossing) requestAnimationFrame(draw) } draw() ``` ## Constructors ### Constructor > **new Analyzer**(`audioContext`, `options?`): `Analyzer` Defined in: [packages/core/src/analyzer.ts:73](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L73) #### Parameters ##### audioContext `AudioContext` ##### options? [`AnalyzerOptions`](../interfaces/AnalyzerOptions.md) #### Returns `Analyzer` ## Properties ### input > `readonly` **input**: `AnalyserNode` Defined in: [packages/core/src/analyzer.ts:66](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L66) The underlying AnalyserNode. Connect audio to this node for analysis. Use this as the input when integrating with effect chains. ## Accessors ### fftSize #### Get Signature > **get** **fftSize**(): `number` Defined in: [packages/core/src/analyzer.ts:113](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L113) The FFT size used for frequency analysis. Must be a power of 2 between 32 and 32768. ##### Returns `number` #### Set Signature > **set** **fftSize**(`value`): `void` Defined in: [packages/core/src/analyzer.ts:117](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L117) ##### Parameters ###### value `number` ##### Returns `void` *** ### frequencyBinCount #### Get Signature > **get** **frequencyBinCount**(): `number` Defined in: [packages/core/src/analyzer.ts:105](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L105) The number of data points available for visualization. Equal to fftSize / 2. ##### Returns `number` *** ### maxDecibels #### Get Signature > **get** **maxDecibels**(): `number` Defined in: [packages/core/src/analyzer.ts:143](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L143) Maximum decibel value for frequency data scaling. ##### Returns `number` #### Set Signature > **set** **maxDecibels**(`value`): `void` Defined in: [packages/core/src/analyzer.ts:147](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L147) ##### Parameters ###### value `number` ##### Returns `void` *** ### minDecibels #### Get Signature > **get** **minDecibels**(): `number` Defined in: [packages/core/src/analyzer.ts:132](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L132) Minimum decibel value for frequency data scaling. ##### Returns `number` #### Set Signature > **set** **minDecibels**(`value`): `void` Defined in: [packages/core/src/analyzer.ts:136](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L136) ##### Parameters ###### value `number` ##### Returns `void` *** ### smoothingTimeConstant #### Get Signature > **get** **smoothingTimeConstant**(): `number` Defined in: [packages/core/src/analyzer.ts:154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L154) Smoothing time constant (0-1). Higher values smooth data over time. ##### Returns `number` #### Set Signature > **set** **smoothingTimeConstant**(`value`): `void` Defined in: [packages/core/src/analyzer.ts:158](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L158) ##### Parameters ###### value `number` ##### Returns `void` ## Methods ### getFloatFrequencyData() > **getFloatFrequencyData**(): `Float32Array` Defined in: [packages/core/src/analyzer.ts:229](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L229) Get precise frequency data as Float32Array with dB values. Use when you need accurate dB readings rather than normalized 0-255 values. Values are in decibels, typically ranging from minDecibels to maxDecibels. #### Returns `Float32Array` Float32Array of dB values (same reference, use immediately or copy) #### Example ```typescript const data = analyzer.getFloatFrequencyData() const peakDb = Math.max(...data) console.log(`Peak frequency at ${peakDb} dB`) ``` *** ### getFrequencyData() > **getFrequencyData**(): `Uint8Array` Defined in: [packages/core/src/analyzer.ts:183](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L183) Get frequency data as unsigned byte array (0-255). Call this in requestAnimationFrame for smooth animations. Each value represents the amplitude at that frequency bin. Lower indices = lower frequencies, higher indices = higher frequencies. #### Returns `Uint8Array` Uint8Array of frequency amplitudes (same reference, use immediately or copy) #### Example ```typescript function draw() { const data = analyzer.getFrequencyData() for (let i = 0; i < data.length; i++) { const barHeight = data[i] / 255 * canvas.height // Draw bar at position i with height barHeight } requestAnimationFrame(draw) } ``` *** ### getTimeDomainData() > **getTimeDomainData**(): `Uint8Array` Defined in: [packages/core/src/analyzer.ts:209](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L209) Get waveform (time domain) data as unsigned byte array. Call this in requestAnimationFrame for oscilloscope visualization. Value of 128 represents zero crossing (silence). Values above 128 = positive amplitude, below 128 = negative amplitude. #### Returns `Uint8Array` Uint8Array of waveform samples (same reference, use immediately or copy) #### Example ```typescript function draw() { const data = analyzer.getTimeDomainData() for (let i = 0; i < data.length; i++) { const y = data[i] / 255 * canvas.height // Draw point at (i, y) for oscilloscope line } requestAnimationFrame(draw) } ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/AudioContextError.md' --- [EZ Web Audio](../index.md) / AudioContextError # Class: AudioContextError Defined in: [packages/core/src/errors/context-error.ts:20](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/context-error.ts#L20) Error thrown when AudioContext is in an invalid state. Common causes: * AudioContext suspended (not yet resumed after user interaction) * AudioContext closed ## Example ```typescript if (audioContext.state === 'suspended') { throw new AudioContextError( 'AudioContext suspended. Call initAudio() after user interaction (click, tap).', audioContext.state ); } ``` ## Extends * [`AudioError`](AudioError.md) ## Constructors ### Constructor > **new AudioContextError**(`message`, `state`): `AudioContextError` Defined in: [packages/core/src/errors/context-error.ts:27](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/context-error.ts#L27) Create a new AudioContextError. #### Parameters ##### message `string` Human-readable error description with actionable fix ##### state `AudioContextState` The current AudioContext state when the error occurred #### Returns `AudioContextError` #### Overrides [`AudioError`](AudioError.md).[`constructor`](AudioError.md#constructor) ## Properties ### code? > `readonly` `optional` **code**: `string` Defined in: [packages/core/src/errors/audio-error.ts:34](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/audio-error.ts#L34) Optional error code for programmatic handling #### Inherited from [`AudioError`](AudioError.md).[`code`](AudioError.md#code) *** ### state > `readonly` **state**: `AudioContextState` Defined in: [packages/core/src/errors/context-error.ts:29](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/context-error.ts#L29) The current AudioContext state when the error occurred --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/AudioError.md' --- [EZ Web Audio](../index.md) / AudioError # Class: AudioError Defined in: [packages/core/src/errors/audio-error.ts:25](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/audio-error.ts#L25) Base error class for all audio-related errors. Provides a consistent error structure with optional error codes for programmatic error handling. Subclasses add specific context like URL, note identifier, or AudioContext state. Subclasses include [ValidationError](ValidationError.md) (invalid parameters or API misuse), [AudioLoadError](AudioLoadError.md) (fetch/decode failures), [AudioContextError](AudioContextError.md) (AudioContext state issues), and [InvalidNoteError](InvalidNoteError.md) (bad note identifiers). ## Example ```typescript import { AudioError } from 'ez-web-audio' try { await sound.play() } catch (e) { if (e instanceof AudioError) { console.error(`Audio error [${e.code}]: ${e.message}`) } } ``` ## Extends * `Error` ## Extended by * [`AggregateAudioLoadError`](AggregateAudioLoadError.md) * [`AudioContextError`](AudioContextError.md) * [`AudioLoadError`](AudioLoadError.md) * [`InvalidNoteError`](InvalidNoteError.md) * [`ValidationError`](ValidationError.md) ## Constructors ### Constructor > **new AudioError**(`message`, `code?`): `AudioError` Defined in: [packages/core/src/errors/audio-error.ts:32](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/audio-error.ts#L32) Create a new AudioError. #### Parameters ##### message `string` Human-readable error description with actionable fix ##### code? `string` Optional error code for programmatic handling #### Returns `AudioError` #### Overrides `Error.constructor` ## Properties ### code? > `readonly` `optional` **code**: `string` Defined in: [packages/core/src/errors/audio-error.ts:34](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/audio-error.ts#L34) Optional error code for programmatic handling --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/AudioLoadError.md' --- [EZ Web Audio](../index.md) / AudioLoadError # Class: AudioLoadError Defined in: [packages/core/src/errors/load-error.ts:23](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/load-error.ts#L23) Error thrown when audio loading fails. Common causes: * Invalid URL (404, network error) * CORS headers missing or misconfigured * Unsupported audio format * Audio decoding failure ## Example ```typescript try { await loadAudio(url); } catch (e) { if (e instanceof AudioLoadError) { console.error(`Failed to load: ${e.url}`); } } ``` ## Extends * [`AudioError`](AudioError.md) ## Constructors ### Constructor > **new AudioLoadError**(`message`, `url`): `AudioLoadError` Defined in: [packages/core/src/errors/load-error.ts:30](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/load-error.ts#L30) Create a new AudioLoadError. #### Parameters ##### message `string` Human-readable error description with actionable fix ##### url `string` The URL that failed to load #### Returns `AudioLoadError` #### Overrides [`AudioError`](AudioError.md).[`constructor`](AudioError.md#constructor) ## Properties ### code? > `readonly` `optional` **code**: `string` Defined in: [packages/core/src/errors/audio-error.ts:34](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/audio-error.ts#L34) Optional error code for programmatic handling #### Inherited from [`AudioError`](AudioError.md).[`code`](AudioError.md#code) *** ### url > `readonly` **url**: `string` Defined in: [packages/core/src/errors/load-error.ts:32](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/load-error.ts#L32) The URL that failed to load --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/AudioSprite.md' --- [EZ Web Audio](../index.md) / AudioSprite # Class: AudioSprite Defined in: [packages/core/src/sprite.ts:160](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L160) AudioSprite enables playing segments of a single audio file by name. Use sprites to bundle multiple short sounds into one file, reducing HTTP requests. Compatible with the audiosprite JSON format. ## Example ```typescript import { createSprite } from 'ez-web-audio' const sprite = await createSprite('sounds.mp3', { spritemap: { laser: { start: 0, end: 0.3 }, explosion: { start: 1.0, end: 2.5 }, powerup: { start: 3.0, end: 3.5 } } }) // Play specific sounds by name sprite.play('laser') sprite.play('explosion', { gain: 0.7 }) // Check available sprites console.log(sprite.names) // ['laser', 'explosion', 'powerup'] ``` ## Constructors ### Constructor > **new AudioSprite**(`audioContext`, `audioBuffer`, `manifest`): `AudioSprite` Defined in: [packages/core/src/sprite.ts:171](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L171) #### Parameters ##### audioContext `AudioContext` ##### audioBuffer `AudioBuffer` ##### manifest [`AudiospriteManifest`](../interfaces/AudiospriteManifest.md) #### Returns `AudioSprite` ## Accessors ### names #### Get Signature > **get** **names**(): `string`\[] Defined in: [packages/core/src/sprite.ts:215](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L215) List of available sprite names defined in the manifest. ##### Example ```typescript sprite.names.forEach(name => console.log(name)) ``` ##### Returns `string`\[] ## Methods ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/sprite.ts:442](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L442) Release the audio buffer and stop all active sources. After disposal, calling play() will throw an error. Use this to free memory when the sprite is no longer needed. #### Returns `void` #### Example ```typescript const sprite = await createSprite('sounds.mp3', manifest) sprite.play('laser') // When done with the sprite sprite.dispose() // sprite.play('laser') // throws: AudioSprite has been disposed ``` *** ### getDuration() > **getDuration**(`name`): `number` Defined in: [packages/core/src/sprite.ts:249](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L249) Get the duration of a sprite in seconds. #### Parameters ##### name `string` The sprite name #### Returns `number` Duration in seconds #### Throws Error if sprite name not found #### Example ```typescript const duration = sprite.getDuration('explosion') console.log(`Explosion lasts ${duration} seconds`) ``` *** ### has() > **has**(`name`): `boolean` Defined in: [packages/core/src/sprite.ts:232](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L232) Check if a sprite with the given name exists. #### Parameters ##### name `string` The sprite name to check #### Returns `boolean` true if the sprite exists #### Example ```typescript if (sprite.has('laser')) { sprite.play('laser') } ``` *** ### play() > **play**(`name`, `options`): `void` Defined in: [packages/core/src/sprite.ts:281](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L281) Play a sprite by name. Each call creates a new AudioBufferSourceNode, allowing concurrent playback of the same sprite. Use options to control gain and pan. #### Parameters ##### name `string` The sprite name to play ##### options [`SpritePlayOptions`](../interfaces/SpritePlayOptions.md) = `{}` Optional gain (0-1) and pan (-1 to 1) settings #### Returns `void` #### Throws Error if sprite name not found #### Example ```typescript // Simple playback sprite.play('laser') // With options sprite.play('explosion', { gain: 0.5, pan: -0.5 }) // Rapid fire (each creates new source) sprite.play('laser') sprite.play('laser') sprite.play('laser') ``` *** ### stop() > **stop**(`name`): `void` Defined in: [packages/core/src/sprite.ts:397](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L397) Stop all active playback of the named sprite. Only useful for sprites defined with `loop: true`, since non-looping sprites stop automatically when their duration elapses. #### Parameters ##### name `string` The sprite name to stop #### Returns `void` #### Example ```typescript sprite.play('bgmusic') // starts looping // later... sprite.stop('bgmusic') // stops the loop ``` *** ### stopAll() > **stopAll**(): `void` Defined in: [packages/core/src/sprite.ts:420](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L420) Stop all active looping sprites. #### Returns `void` #### Example ```typescript sprite.play('bgmusic') sprite.play('ambient') sprite.stopAll() // stops both ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Beat.md' --- [EZ Web Audio](../index.md) / Beat # Class: Beat Defined in: [packages/core/src/beat.ts:33](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L33) ## Constructors ### Constructor > **new Beat**(`audioContext`, `opts`): `Beat` Defined in: [packages/core/src/beat.ts:34](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L34) #### Parameters ##### audioContext `AudioContext` ##### opts `BeatOptions` #### Returns `Beat` ## Properties ### active > **active**: `boolean` = `false` Defined in: [packages/core/src/beat.ts:61](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L61) Whether this beat should play when triggered. When false, the beat position becomes a rest (silence). #### Default ```ts false ``` *** ### currentTimeIsPlaying > **currentTimeIsPlaying**: `boolean` = `false` Defined in: [packages/core/src/beat.ts:69](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L69) Whether this beat's time position is currently active (playing or resting). True for both active beats and rests during their time slot. Automatically resets to false after `duration` milliseconds. #### Default ```ts false ``` *** ### duration > **duration**: `number` Defined in: [packages/core/src/beat.ts:84](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L84) How long (in milliseconds) the `isPlaying` flags stay true. Useful for controlling visual feedback duration. #### Default ```ts 100 ``` *** ### isPlaying > **isPlaying**: `boolean` = `false` Defined in: [packages/core/src/beat.ts:77](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L77) Whether this beat is currently playing audio (only true for active beats). Automatically resets to false after `duration` milliseconds. Use this for visual feedback that should only appear when sound plays. #### Default ```ts false ``` ## Accessors ### velocity #### Get Signature > **get** **velocity**(): `number` Defined in: [packages/core/src/beat.ts:98](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L98) Playback velocity (0–1) applied as a gain multiplier when this beat plays. 1 = full volume, lower values are quieter hits (e.g. ghost notes at 0.4). Set directly or via BeatTrack.setPattern numeric values. Assignments are silently clamped to \[0, 1] rather than throwing — matching BeatTrack.setPattern's clamping posture, so out-of-range values (e.g. a velocity of 5) can never produce a gain spike. Default: 1 ##### Returns `number` #### Set Signature > **set** **velocity**(`value`): `void` Defined in: [packages/core/src/beat.ts:102](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L102) ##### Parameters ###### value `number` ##### Returns `void` ## Methods ### cancelPendingTimers() > **cancelPendingTimers**(): `void` Defined in: [packages/core/src/beat.ts:230](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L230) Cancel all pending timers and reset visual state. Called by BeatTrack.stop() to prevent stale callbacks. #### Returns `void` *** ### play() > **play**(): `void` Defined in: [packages/core/src/beat.ts:160](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L160) Play this beat immediately. Sets `isPlaying` and `currentTimeIsPlaying` to true immediately, then resets them after `duration` milliseconds. #### Returns `void` #### Example ```typescript beat.play() // plays immediately ``` *** ### playIfActive() > **playIfActive**(): `void` Defined in: [packages/core/src/beat.ts:172](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L172) Play this beat immediately, but only if active. If active, plays and sets `isPlaying` to true. Always sets `currentTimeIsPlaying` to true (for UI beat indicators). #### Returns `void` *** ### playIn() > **playIn**(`offset`): `void` Defined in: [packages/core/src/beat.ts:119](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L119) Play this beat after a delay. Sets `isPlaying` and `currentTimeIsPlaying` to true after the offset elapses, then resets them after `duration` milliseconds. #### Parameters ##### offset `number` = `0` Number of seconds from now to play #### Returns `void` #### Example ```typescript beat.playIn(0.5) // plays in 0.5 seconds ``` *** ### playInIfActive() > **playInIfActive**(`offset`): `void` Defined in: [packages/core/src/beat.ts:138](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L138) Play this beat after a delay, but only if active. If active, plays and sets `isPlaying` to true after the offset. Always sets `currentTimeIsPlaying` to true (for UI beat indicators). #### Parameters ##### offset `number` = `0` Number of seconds from now to play #### Returns `void` *** ### triggerVisualOnly() > **triggerVisualOnly**(): `void` Defined in: [packages/core/src/beat.ts:186](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat.ts#L186) Trigger visual-only state (currentTimeIsPlaying) without audio playback. Used by BeatTrack when muted or not soloed — the beat's time position is still visually indicated even though no sound plays. #### Returns `void` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/BeatTrack.md' --- [EZ Web Audio](../index.md) / BeatTrack # Class: BeatTrack Defined in: [packages/core/src/beat-track.ts:55](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L55) Drum machine lane with rhythmic beat patterns. BeatTrack manages an array of Beat instances for creating drum patterns. It extends Sampler for round-robin sample variation and adds tempo-synced playback with beat events for visual synchronization. ## Example ```typescript import { createBeatTrack } from 'ez-web-audio' const kick = await createBeatTrack(['kick.mp3'], { numBeats: 8 }) // Set a basic 4-on-the-floor pattern kick.beats[0].active = true // beat 1 kick.beats[2].active = true // beat 3 kick.beats[4].active = true // beat 5 kick.beats[6].active = true // beat 7 kick.playBeats(120, 1/4) // Play quarter notes at 120 BPM // Listen for beat events kick.on('beat', (e) => { console.log(`Beat ${e.detail.beatIndex}`) }) ``` ## Extends * [`Sampler`](Sampler.md) ## Implements * `SyncableBeatTrack` ## Constructors ### Constructor > **new BeatTrack**(`audioContext`, `sounds`, `opts?`): `BeatTrack` Defined in: [packages/core/src/beat-track.ts:118](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L118) #### Parameters ##### audioContext `AudioContext` ##### sounds [`Playable`](../interfaces/Playable.md) & [`Connectable`](../interfaces/Connectable.md)\[] ##### opts? [`BeatTrackOptions`](../interfaces/BeatTrackOptions.md) #### Returns `BeatTrack` #### Overrides [`Sampler`](Sampler.md).[`constructor`](Sampler.md#constructor) ## Properties ### duration > **duration**: `number` = `100` Defined in: [packages/core/src/beat-track.ts:154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L154) How long (in milliseconds) the `isPlaying` flag stays true after a beat plays. Useful for visual feedback in the UI. #### Default ```ts 100 ``` *** ### muted > **muted**: `boolean` = `false` Defined in: [packages/core/src/beat-track.ts:100](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L100) Whether this track is muted. When muted, beat scheduling continues (events still fire for UI sync) but audio playback is silenced. *** ### name > **name**: `string` Defined in: [packages/core/src/sampler.ts:53](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L53) Optional name to aid in identification. #### Inherited from [`Sampler`](Sampler.md).[`name`](Sampler.md#name) *** ### numBeats > **numBeats**: `number` = `4` Defined in: [packages/core/src/beat-track.ts:147](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L147) Number of beats in this track. #### Default ```ts 4 ``` *** ### solo > **solo**: `boolean` = `false` Defined in: [packages/core/src/beat-track.ts:107](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L107) Whether this track is soloed. Solo is stackable — when any synced track has solo=true, only soloed tracks produce audio. When no tracks are soloed, all unmuted tracks produce audio. ## Accessors ### beats #### Get Signature > **get** **beats**(): [`Beat`](Beat.md)\[] Defined in: [packages/core/src/beat-track.ts:174](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L174) Array of Beat instances in this track. The array length always matches `numBeats`. Beats are reused when the count changes, preserving their `active` state. ##### Example ```typescript // Toggle individual beats track.beats[0].active = true track.beats[1].active = false // Check all beat states track.beats.forEach((beat, i) => { console.log(`Beat ${i}: ${beat.active ? 'on' : 'off'}`) }) ``` ##### Returns [`Beat`](Beat.md)\[] #### Implementation of `SyncableBeatTrack.beats` *** ### gain #### Get Signature > **get** **gain**(): `number` Defined in: [packages/core/src/sampler.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L75) Gain level applied to each sample when played. This value is applied to the underlying Sound on every play() call, overriding any per-sound gain customization. Validated the same way as [Sampler.changeGainTo](Sampler.md#changegainto) / `BaseSound.changeGainTo`: throws a [ValidationError](ValidationError.md) for negative values, warns on the console for values above 1 (R1#1 — previously this was a raw mutable field with no validation at all). Defaults to 1. ##### Returns `number` #### Set Signature > **set** **gain**(`value`): `void` Defined in: [packages/core/src/sampler.ts:79](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L79) ##### Parameters ###### value `number` ##### Returns `void` #### Inherited from [`Sampler`](Sampler.md).[`gain`](Sampler.md#gain) *** ### isSynced #### Get Signature > **get** **isSynced**(): `boolean` Defined in: [packages/core/src/beat-track.ts:411](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L411) Whether this BeatTrack is currently synced to a Transport. ##### Returns `boolean` *** ### pan #### Get Signature > **get** **pan**(): `number` Defined in: [packages/core/src/sampler.ts:92](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L92) Stereo pan position applied to each sample (-1 = left, 0 = center, 1 = right). This value is applied to the underlying Sound on every play() call, overriding any per-sound pan customization. Validated the same way as [Sampler.changePanTo](Sampler.md#changepanto) / `BaseSound.changePanTo`: warns on the console for values outside \[-1, 1] (R1#1). Defaults to 0. ##### Returns `number` #### Set Signature > **set** **pan**(`value`): `void` Defined in: [packages/core/src/sampler.ts:96](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L96) ##### Parameters ###### value `number` ##### Returns `void` #### Inherited from [`Sampler`](Sampler.md).[`pan`](Sampler.md#pan) ## Methods ### addEventListener() > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/beat-track.ts:710](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L710) Add a typed event listener for BeatTrack lifecycle events. #### Type Parameters ##### K `K` *extends* keyof [`BeatTrackEventMap`](../interfaces/BeatTrackEventMap.md) #### Parameters ##### type `K` Event type: 'beat', 'stop', 'pause', 'resume' ##### listener (`event`) => `void` Handler function ##### options? Standard addEventListener options `boolean` | `AddEventListenerOptions` #### Returns `void` *** ### changeGainTo() > **changeGainTo**(`value`): `this` Defined in: [packages/core/src/sampler.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L108) Set the gain level applied to each sample. Equivalent to `sampler.gain = value`, provided for API symmetry with `BaseSound.changeGainTo()` / `LayeredSound.changeGainTo()`. #### Parameters ##### value `number` The gain value (0-1 typical range) #### Returns `this` this for chaining #### Inherited from [`Sampler`](Sampler.md).[`changeGainTo`](Sampler.md#changegainto) *** ### changePanTo() > **changePanTo**(`value`): `this` Defined in: [packages/core/src/sampler.ts:120](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L120) Set the pan position applied to each sample. Equivalent to `sampler.pan = value`, provided for API symmetry with `BaseSound.changePanTo()` / `LayeredSound.changePanTo()`. #### Parameters ##### value `number` The pan value (-1 to 1) #### Returns `this` this for chaining #### Inherited from [`Sampler`](Sampler.md).[`changePanTo`](Sampler.md#changepanto) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/beat-track.ts:747](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L747) Dispose this BeatTrack, stopping playback, clearing beats, and releasing all audio resources. After disposal, the BeatTrack should not be used. Create a new instance instead. #### Returns `void` #### Example ```typescript const track = await createBeatTrack(['kick.mp3'], { numBeats: 8 }) track.playBeats(120, 1/4) // When done: track.dispose() ``` *** ### getSounds() > **getSounds**(): readonly [`Playable`](../interfaces/Playable.md) & [`Connectable`](../interfaces/Connectable.md)\[] Defined in: [packages/core/src/sampler.ts:208](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L208) Get a readonly snapshot of the sampler's sounds. Returns a shallow copy as an array so callers can inspect which sounds are loaded without mutating the internal Set. #### Returns readonly [`Playable`](../interfaces/Playable.md) & [`Connectable`](../interfaces/Connectable.md)\[] Readonly array of sounds in the sampler #### Example ```typescript const sampler = await createSampler(['kick-1.mp3', 'kick-2.mp3']) const sounds = sampler.getSounds() console.log(sounds.length) // 2 ``` #### Inherited from [`Sampler`](Sampler.md).[`getSounds`](Sampler.md#getsounds) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/beat-track.ts:806](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L806) Unsubscribe from an event. Supports chaining. #### Type Parameters ##### K `K` *extends* keyof [`BeatTrackEventMap`](../interfaces/BeatTrackEventMap.md) #### Parameters ##### type `K` Event type to unsubscribe from ##### listener (`event`) => `void` Handler function to remove #### Returns `this` this for chaining *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/beat-track.ts:791](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L791) Subscribe to an event. Supports chaining. #### Type Parameters ##### K `K` *extends* keyof [`BeatTrackEventMap`](../interfaces/BeatTrackEventMap.md) #### Parameters ##### type `K` Event type: 'beat', 'stop', 'pause', 'resume' ##### listener (`event`) => `void` Handler function #### Returns `this` this for chaining #### Example ```typescript track.on('beat', (e) => { console.log(`Beat ${e.detail.beatIndex}`) highlightBeat(e.detail.beatIndex) }).on('stop', () => { console.log('Stopped') }) ``` *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/beat-track.ts:828](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L828) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* keyof [`BeatTrackEventMap`](../interfaces/BeatTrackEventMap.md) #### Parameters ##### type `K` Event type to listen for ##### listener (`event`) => `void` Handler function (called only once) #### Returns `this` this for chaining #### Example ```typescript track.once('stop', () => { console.log('Track stopped for the first time') }) ``` *** ### pause() > **pause**(): `void` Defined in: [packages/core/src/beat-track.ts:340](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L340) Pause playback at the current position. Emits a 'pause' event with the current beat index. Use resume() to continue from where you left off. #### Returns `void` #### Example ```typescript track.pause() // later... track.resume() ``` *** ### play() > **play**(`velocity`): `void` Defined in: [packages/core/src/sampler.ts:149](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L149) Play the next sound in the rotation immediately. #### Parameters ##### velocity `number` = `1` Gain multiplier (0–1) applied on top of the sampler's `gain`. Defaults to 1 (no attenuation). #### Returns `void` #### Example ```typescript sampler.play() // plays sound 1 sampler.play() // plays sound 2 sampler.play(0.4) // plays sound 3 at 40% of the sampler's gain (then wraps to 1) ``` #### Inherited from [`Sampler`](Sampler.md).[`play`](Sampler.md#play) *** ### playActiveBeats() > **playActiveBeats**(`bpm`, `noteType`): `void` Defined in: [packages/core/src/beat-track.ts:292](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L292) Start playing only active beats in the pattern continuously. Same as playBeats(), but only plays beats where `active === true`. Inactive beats become rests (silence), maintaining timing. #### Parameters ##### bpm `number` Tempo in beats per minute ##### noteType `number` Rhythmic subdivision as a fraction. Common values: 1/4 (quarter notes), 1/8 (eighth notes), 1/16 (sixteenth notes). The beat duration in seconds is calculated as: (240 \* noteType) / bpm. #### Returns `void` #### Example ```typescript // Set up a pattern with rests track.beats[0].active = true track.beats[2].active = true track.playActiveBeats(120, 1/4) // Only beats 0 and 2 play ``` *** ### playAt() > **playAt**(`time`, `velocity`): `void` Defined in: [packages/core/src/sampler.ts:186](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L186) Play the next sound at a specific AudioContext time. #### Parameters ##### time `number` The AudioContext.currentTime value when to play ##### velocity `number` = `1` Gain multiplier (0–1) applied on top of the sampler's `gain`. Defaults to 1 (no attenuation). #### Returns `void` #### Example ```typescript const startTime = audioContext.currentTime + 1 sampler.playAt(startTime) // plays next sound at exactly startTime sampler.playAt(startTime, 0.8) // plays next sound at exactly startTime at 80% gain ``` #### Inherited from [`Sampler`](Sampler.md).[`playAt`](Sampler.md#playat) *** ### playBeats() > **playBeats**(`bpm`, `noteType`): `void` Defined in: [packages/core/src/beat-track.ts:256](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L256) Start playing all beats in the pattern continuously. Starts a lookahead scheduler that triggers beats at precise audio times. Emits 'beat' events for UI synchronization. Unlike `playActiveBeats()`, this plays ALL beats regardless of their `active` flag. #### Parameters ##### bpm `number` Tempo in beats per minute ##### noteType `number` Rhythmic subdivision as a fraction. Common values: 1/4 (quarter notes), 1/8 (eighth notes), 1/16 (sixteenth notes). The beat duration in seconds is calculated as: (240 \* noteType) / bpm. #### Returns `void` #### Example ```typescript track.playBeats(120, 1/4) // 120 BPM, quarter notes — all beats play track.playBeats(140, 1/8) // 140 BPM, eighth notes ``` *** ### playIn() > **playIn**(`seconds`, `velocity`): `void` Defined in: [packages/core/src/sampler.ts:169](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L169) Play the next sound in the rotation after a delay. #### Parameters ##### seconds `number` Number of seconds from now to play the sound ##### velocity `number` = `1` Gain multiplier (0–1) applied on top of the sampler's `gain`. Defaults to 1 (no attenuation). #### Returns `void` #### Example ```typescript sampler.playIn(0.5) // plays next sound in 0.5 seconds sampler.playIn(0.5, 0.6) // plays next sound in 0.5 seconds at 60% gain ``` #### Inherited from [`Sampler`](Sampler.md).[`playIn`](Sampler.md#playin) *** ### removeEventListener() > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/beat-track.ts:725](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L725) Remove a typed event listener. #### Type Parameters ##### K `K` *extends* keyof [`BeatTrackEventMap`](../interfaces/BeatTrackEventMap.md) #### Parameters ##### type `K` Event type to unsubscribe from ##### listener (`event`) => `void` Handler function to remove ##### options? Standard removeEventListener options `boolean` | `EventListenerOptions` #### Returns `void` *** ### resume() > **resume**(): `void` Defined in: [packages/core/src/beat-track.ts:366](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L366) Resume playback from where it was paused. Emits a 'resume' event with the beat index where playback resumes. Has no effect if not paused. #### Returns `void` #### Example ```typescript track.pause() // ...user clicks play button... track.resume() // continues from paused position ``` *** ### setPattern() > **setPattern**(`pattern`): `this` Defined in: [packages/core/src/beat-track.ts:227](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L227) Set beat active states (and velocities) from a pattern array. Each element maps to a beat: truthy values (1, true) set the beat active, falsy values (0, false) set it inactive. If the array is shorter than the number of beats, remaining beats are set inactive. If longer, extra values are ignored. Numeric values greater than 0 also set the beat's `velocity` — a gain multiplier for that hit (clamped to a max of 1). Booleans, and numbers that are 0 or negative, leave `velocity` at its current/default value of 1, matching prior boolean-only behavior. #### Parameters ##### pattern (`number` | `boolean`)\[] Array of numbers (0-1 velocity, or any non-zero value as "on") or booleans representing the beat pattern #### Returns `this` this for chaining #### Example ```typescript const kick = await createBeatTrack(['kick.mp3'], { numBeats: 8 }) // 4-on-the-floor pattern kick.setPattern([1, 0, 1, 0, 1, 0, 1, 0]) // Ghost notes via velocity — 0.6 = quieter hit kick.setPattern([1, 0, 0.6, 0]) // Shorter array — remaining beats inactive kick.setPattern([1, 0, 1]) // beats 3-7 become inactive // Chainable kick.setPattern([1, 0, 1, 0]).playActiveBeats(120, 1/4) ``` *** ### setTempo() > **setTempo**(`bpm`): `void` Defined in: [packages/core/src/beat-track.ts:400](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L400) Change the tempo while playing. The new tempo takes effect on the next scheduled beat. #### Parameters ##### bpm `number` New tempo in beats per minute #### Returns `void` #### Example ```typescript track.playBeats(120, 1/4) // later, speed up... track.setTempo(140) ``` *** ### stop() > **stop**(): `void` Defined in: [packages/core/src/beat-track.ts:322](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L322) Stop playback and reset to the beginning. Emits a 'stop' event. Use pause() instead if you want to resume later. #### Returns `void` #### Example ```typescript track.stop() track.on('stop', () => console.log('Stopped')) ``` *** ### syncTo() > **syncTo**(`transport`, `opts`): `void` Defined in: [packages/core/src/beat-track.ts:435](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L435) Sync this BeatTrack to a Transport for clock-driven playback. When synced, the Transport's scheduler drives this track's beats. Standalone methods (playBeats, playActiveBeats, stop, pause, resume, setTempo) throw an error while synced — use transport.start()/stop() instead. #### Parameters ##### transport [`Transport`](Transport.md) The Transport to sync to ##### opts Sync options ###### noteType `number` Rhythmic subdivision (e.g., 1/4, 1/16) #### Returns `void` #### Example ```typescript const transport = await createTransport({ bpm: 120 }) const kick = await createBeatTrack(['kick.mp3'], { numBeats: 4 }) kick.syncTo(transport, { noteType: 1/4 }) transport.start() // kicks play quarter notes at 120 BPM ``` *** ### unsync() > **unsync**(): `void` Defined in: [packages/core/src/beat-track.ts:457](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L457) Unsync this BeatTrack from its Transport. Re-enables standalone methods (playBeats, playActiveBeats, stop, etc.). If the track was playing via Transport, it stops cleanly. #### Returns `void` #### Example ```typescript kick.unsync() kick.playBeats(120, 1/4) // standalone mode works again ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/CompressorEffect.md' --- [EZ Web Audio](../index.md) / CompressorEffect # Class: CompressorEffect Defined in: [packages/core/src/effects/compressor-effect.ts:50](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L50) CompressorEffect - Dynamics compression using the native DynamicsCompressorNode. Reduces the dynamic range of audio by attenuating signals above the threshold. All parameters map 1:1 to the DynamicsCompressorNode API. Extends BaseEffect for shared wet/dry mixing, bypass, and rampTo() functionality. ## Example ```typescript import { createCompressor, createSound } from 'ez-web-audio' const sound = await createSound('drums.mp3') const comp = createCompressor({ threshold: -24, ratio: 4, knee: 30, attack: 0.003, release: 0.25 }) sound.addEffect(comp) sound.play() // Check gain reduction console.log(comp.reduction) // -6.5 (dB) ``` ## Extends * [`BaseEffect`](BaseEffect.md) ## Constructors ### Constructor > **new CompressorEffect**(`audioContext`, `options`): `CompressorEffect` Defined in: [packages/core/src/effects/compressor-effect.ts:61](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L61) #### Parameters ##### audioContext `AudioContext` ##### options [`CompressorOptions`](../interfaces/CompressorOptions.md) = `{}` #### Returns `CompressorEffect` #### Overrides [`BaseEffect`](BaseEffect.md).[`constructor`](BaseEffect.md#constructor) ## Accessors ### attack #### Get Signature > **get** **attack**(): `number` Defined in: [packages/core/src/effects/compressor-effect.ts:122](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L122) Attack time in seconds ##### Returns `number` #### Set Signature > **set** **attack**(`v`): `void` Defined in: [packages/core/src/effects/compressor-effect.ts:126](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L126) ##### Parameters ###### v `number` ##### Returns `void` *** ### bypass #### Get Signature > **get** **bypass**(): `boolean` Defined in: [packages/core/src/effects/base-effect.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L95) When true, signal bypasses the effect entirely (100% dry). ##### Returns `boolean` #### Set Signature > **set** **bypass**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L99) When true, effect is bypassed (passthrough) ##### Parameters ###### v `boolean` ##### Returns `void` When true, effect is bypassed (passthrough) #### Inherited from [`BaseEffect`](BaseEffect.md).[`bypass`](BaseEffect.md#bypass) *** ### input #### Get Signature > **get** **input**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:83](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L83) The input AudioNode (receives signal from chain) ##### Returns `AudioNode` The input AudioNode that receives signal from the chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`input`](BaseEffect.md#input) *** ### knee #### Get Signature > **get** **knee**(): `number` Defined in: [packages/core/src/effects/compressor-effect.ts:111](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L111) Knee width in dB ##### Returns `number` #### Set Signature > **set** **knee**(`v`): `void` Defined in: [packages/core/src/effects/compressor-effect.ts:115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L115) ##### Parameters ###### v `number` ##### Returns `void` *** ### mix #### Get Signature > **get** **mix**(): `number` Defined in: [packages/core/src/effects/base-effect.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L108) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (all through effect). Uses equal-power crossfade for natural mixing. ##### Returns `number` #### Set Signature > **set** **mix**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:112](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L112) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) ##### Parameters ###### v `number` ##### Returns `void` Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) #### Inherited from [`BaseEffect`](BaseEffect.md).[`mix`](BaseEffect.md#mix) *** ### output #### Get Signature > **get** **output**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:88](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L88) The output AudioNode (sends signal to next in chain) ##### Returns `AudioNode` The output AudioNode that sends signal to the next in chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`output`](BaseEffect.md#output) *** ### ratio #### Get Signature > **get** **ratio**(): `number` Defined in: [packages/core/src/effects/compressor-effect.ts:100](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L100) Compression ratio (e.g., 4 = 4:1) ##### Returns `number` #### Set Signature > **set** **ratio**(`v`): `void` Defined in: [packages/core/src/effects/compressor-effect.ts:104](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L104) ##### Parameters ###### v `number` ##### Returns `void` *** ### reduction #### Get Signature > **get** **reduction**(): `number` Defined in: [packages/core/src/effects/compressor-effect.ts:144](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L144) Current gain reduction in dB (read-only). Useful for metering ##### Returns `number` *** ### release #### Get Signature > **get** **release**(): `number` Defined in: [packages/core/src/effects/compressor-effect.ts:133](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L133) Release time in seconds ##### Returns `number` #### Set Signature > **set** **release**(`v`): `void` Defined in: [packages/core/src/effects/compressor-effect.ts:137](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L137) ##### Parameters ###### v `number` ##### Returns `void` *** ### threshold #### Get Signature > **get** **threshold**(): `number` Defined in: [packages/core/src/effects/compressor-effect.ts:89](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L89) Threshold in dB above which compression starts ##### Returns `number` #### Set Signature > **set** **threshold**(`v`): `void` Defined in: [packages/core/src/effects/compressor-effect.ts:93](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L93) ##### Parameters ###### v `number` ##### Returns `void` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 [`BaseEffect`](BaseEffect.md).[`_clearListeners`](BaseEffect.md#clearlisteners) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/effects/compressor-effect.ts:148](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L148) Disconnect all internal audio nodes and emit a 'dispose' event. **Subclass disposal contract:** Subclasses that create additional audio nodes (e.g., BiquadFilterNode, DynamicsCompressorNode, WaveShaperNode) MUST override dispose() to disconnect those nodes before calling super.dispose(). #### Returns `void` #### Example ```typescript public override dispose(): void { try { this.myNode.disconnect() } catch { /* already disconnected */ } super.dispose() } ``` Idempotent — safe to call multiple times. #### Overrides [`BaseEffect`](BaseEffect.md).[`dispose`](BaseEffect.md#dispose) *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail `BaseEffectEventMap`\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`BaseEffect`](BaseEffect.md).[`emit`](BaseEffect.md#emit) *** ### getAudioContext() > **getAudioContext**(): `AudioContext` Defined in: [packages/core/src/effects/base-effect.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L121) Get the AudioContext used by this effect. Useful for external tools (e.g., LFO) that need the context. #### Returns `AudioContext` #### Inherited from [`BaseEffect`](BaseEffect.md).[`getAudioContext`](BaseEffect.md#getaudiocontext) *** ### getAudioParam() > `protected` **getAudioParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/compressor-effect.ts:156](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L156) Map a parameter name to its underlying AudioParam. Subclasses implement this to expose their effect-specific parameters. #### Parameters ##### name `string` The parameter name #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Overrides [`BaseEffect`](BaseEffect.md).[`getAudioParam`](BaseEffect.md#getaudioparam) *** ### getParam() > **getParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/base-effect.ts:134](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L134) Get a named AudioParam from this effect for external modulation. Delegates to the subclass's getAudioParam() implementation. Returns null if the parameter name is not recognized. #### Parameters ##### name `string` The parameter name (e.g., 'frequency', 'time', 'feedback') #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Inherited from [`BaseEffect`](BaseEffect.md).[`getParam`](BaseEffect.md#getparam) *** ### getUnrampableParams() > `protected` **getUnrampableParams**(): readonly `string`\[] Defined in: [packages/core/src/effects/base-effect.ts:243](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L243) Names of documented effect properties that are NOT backed by a single AudioParam (e.g. WaveShaper curve swaps, multi-node comb/allpass networks) and therefore cannot be smoothly ramped via `rampTo()`. `rampTo()` warns instead of silently no-op-ing when called with one of these names, so callers don't mistake "no-op" for "it worked." Default: none. Subclasses override where applicable. #### Returns readonly `string`\[] #### Inherited from [`BaseEffect`](BaseEffect.md).[`getUnrampableParams`](BaseEffect.md#getunrampableparams) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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"` #### 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 [`BaseEffect`](BaseEffect.md).[`off`](BaseEffect.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`on`](BaseEffect.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`once`](BaseEffect.md#once) *** ### onParamRamped() > `protected` **onParamRamped**(`param`, `value`): `number` Defined in: [packages/core/src/effects/compressor-effect.ts:173](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L173) ramp-setter-desync fix: rampTo() re-applies the same clamp each property setter uses and updates the shadow field, so getters stay honest after a ramp and the AudioParam can never receive an out-of-range value the setter would have rejected. #### Parameters ##### param `string` ##### value `number` #### Returns `number` #### Overrides [`BaseEffect`](BaseEffect.md).[`onParamRamped`](BaseEffect.md#onparamramped) *** ### rampTo() > **rampTo**(`param`, `value`, `duration`): `void` Defined in: [packages/core/src/effects/base-effect.ts:164](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L164) Smoothly ramp a parameter to a target value over a duration. Uses `AudioParam.setTargetAtTime` for glitch-free transitions. If the parameter name is not recognized, this is a no-op (a `console.warn` is emitted if the name is a real, documented effect property that just isn't backed by a single AudioParam — see [getUnrampableParams](BaseEffect.md#getunrampableparams)). **Single write path:** every ramped write is funneled through [onParamRamped](BaseEffect.md#onparamramped), the same hook subclasses use to keep their shadow getters honest. This guarantees `effect.someParam` reflects the ramp target immediately after calling `rampTo()`, and that the exact same validation/clamping a synchronous property-set would apply is also applied to ramped writes — the AudioParam and the getter can never diverge from each other. #### Parameters ##### param `string` Parameter name (e.g., 'frequency', 'time', 'feedback') ##### value `number` Target value ##### duration `number` Ramp duration in seconds #### Returns `void` #### Example ```typescript delay.rampTo('time', 0.5, 2) // Ramp delay time to 0.5s over 2 seconds filter.rampTo('frequency', 800, 1) // Ramp cutoff to 800Hz over 1 second ``` #### Inherited from [`BaseEffect`](BaseEffect.md).[`rampTo`](BaseEffect.md#rampto) *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/DelayEffect.md' --- [EZ Web Audio](../index.md) / DelayEffect # Class: DelayEffect Defined in: [packages/core/src/effects/delay-effect.ts:42](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L42) DelayEffect - Echo/delay effect with configurable time, feedback, and wet/dry mix. Uses a DelayNode with a feedback loop to create repeating echoes. Feedback is clamped to \[0, 0.99] to prevent infinite volume growth. Extends BaseEffect for shared wet/dry mixing, bypass, and rampTo() functionality. ## Example ```typescript import { createDelay, createSound } from 'ez-web-audio' const sound = await createSound('guitar.mp3') const delay = createDelay({ time: 0.3, feedback: 0.5, mix: 0.4 }) sound.addEffect(delay) sound.play() // Real-time control delay.time = 0.5 delay.feedback = 0.7 delay.rampTo('time', 0.1, 2) // Smooth ramp over 2 seconds ``` ## Extends * [`BaseEffect`](BaseEffect.md) ## Constructors ### Constructor > **new DelayEffect**(`audioContext`, `options`): `DelayEffect` Defined in: [packages/core/src/effects/delay-effect.ts:52](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L52) #### Parameters ##### audioContext `AudioContext` ##### options [`DelayOptions`](../interfaces/DelayOptions.md) = `{}` #### Returns `DelayEffect` #### Overrides [`BaseEffect`](BaseEffect.md).[`constructor`](BaseEffect.md#constructor) ## Accessors ### bypass #### Get Signature > **get** **bypass**(): `boolean` Defined in: [packages/core/src/effects/base-effect.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L95) When true, signal bypasses the effect entirely (100% dry). ##### Returns `boolean` #### Set Signature > **set** **bypass**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L99) When true, effect is bypassed (passthrough) ##### Parameters ###### v `boolean` ##### Returns `void` When true, effect is bypassed (passthrough) #### Inherited from [`BaseEffect`](BaseEffect.md).[`bypass`](BaseEffect.md#bypass) *** ### feedback #### Get Signature > **get** **feedback**(): `number` Defined in: [packages/core/src/effects/delay-effect.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L99) Feedback amount (0-0.99). Higher values = more repeats ##### Returns `number` #### Set Signature > **set** **feedback**(`v`): `void` Defined in: [packages/core/src/effects/delay-effect.ts:103](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L103) ##### Parameters ###### v `number` ##### Returns `void` *** ### input #### Get Signature > **get** **input**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:83](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L83) The input AudioNode (receives signal from chain) ##### Returns `AudioNode` The input AudioNode that receives signal from the chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`input`](BaseEffect.md#input) *** ### maxTime #### Get Signature > **get** **maxTime**(): `number` Defined in: [packages/core/src/effects/delay-effect.ts:109](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L109) Maximum delay time in seconds (read-only, set at construction) ##### Returns `number` *** ### mix #### Get Signature > **get** **mix**(): `number` Defined in: [packages/core/src/effects/base-effect.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L108) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (all through effect). Uses equal-power crossfade for natural mixing. ##### Returns `number` #### Set Signature > **set** **mix**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:112](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L112) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) ##### Parameters ###### v `number` ##### Returns `void` Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) #### Inherited from [`BaseEffect`](BaseEffect.md).[`mix`](BaseEffect.md#mix) *** ### output #### Get Signature > **get** **output**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:88](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L88) The output AudioNode (sends signal to next in chain) ##### Returns `AudioNode` The output AudioNode that sends signal to the next in chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`output`](BaseEffect.md#output) *** ### time #### Get Signature > **get** **time**(): `number` Defined in: [packages/core/src/effects/delay-effect.ts:88](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L88) Delay time in seconds ##### Returns `number` #### Set Signature > **set** **time**(`v`): `void` Defined in: [packages/core/src/effects/delay-effect.ts:92](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L92) ##### Parameters ###### v `number` ##### Returns `void` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 [`BaseEffect`](BaseEffect.md).[`_clearListeners`](BaseEffect.md#clearlisteners) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/effects/delay-effect.ts:113](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L113) Disconnect all internal audio nodes and emit a 'dispose' event. **Subclass disposal contract:** Subclasses that create additional audio nodes (e.g., BiquadFilterNode, DynamicsCompressorNode, WaveShaperNode) MUST override dispose() to disconnect those nodes before calling super.dispose(). #### Returns `void` #### Example ```typescript public override dispose(): void { try { this.myNode.disconnect() } catch { /* already disconnected */ } super.dispose() } ``` Idempotent — safe to call multiple times. #### Overrides [`BaseEffect`](BaseEffect.md).[`dispose`](BaseEffect.md#dispose) *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail `BaseEffectEventMap`\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`BaseEffect`](BaseEffect.md).[`emit`](BaseEffect.md#emit) *** ### getAudioContext() > **getAudioContext**(): `AudioContext` Defined in: [packages/core/src/effects/base-effect.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L121) Get the AudioContext used by this effect. Useful for external tools (e.g., LFO) that need the context. #### Returns `AudioContext` #### Inherited from [`BaseEffect`](BaseEffect.md).[`getAudioContext`](BaseEffect.md#getaudiocontext) *** ### getAudioParam() > `protected` **getAudioParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/delay-effect.ts:125](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L125) Map a parameter name to its underlying AudioParam. Subclasses implement this to expose their effect-specific parameters. #### Parameters ##### name `string` The parameter name #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Overrides [`BaseEffect`](BaseEffect.md).[`getAudioParam`](BaseEffect.md#getaudioparam) *** ### getParam() > **getParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/base-effect.ts:134](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L134) Get a named AudioParam from this effect for external modulation. Delegates to the subclass's getAudioParam() implementation. Returns null if the parameter name is not recognized. #### Parameters ##### name `string` The parameter name (e.g., 'frequency', 'time', 'feedback') #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Inherited from [`BaseEffect`](BaseEffect.md).[`getParam`](BaseEffect.md#getparam) *** ### getUnrampableParams() > `protected` **getUnrampableParams**(): readonly `string`\[] Defined in: [packages/core/src/effects/base-effect.ts:243](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L243) Names of documented effect properties that are NOT backed by a single AudioParam (e.g. WaveShaper curve swaps, multi-node comb/allpass networks) and therefore cannot be smoothly ramped via `rampTo()`. `rampTo()` warns instead of silently no-op-ing when called with one of these names, so callers don't mistake "no-op" for "it worked." Default: none. Subclasses override where applicable. #### Returns readonly `string`\[] #### Inherited from [`BaseEffect`](BaseEffect.md).[`getUnrampableParams`](BaseEffect.md#getunrampableparams) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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"` #### 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 [`BaseEffect`](BaseEffect.md).[`off`](BaseEffect.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`on`](BaseEffect.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`once`](BaseEffect.md#once) *** ### onParamRamped() > `protected` **onParamRamped**(`param`, `value`): `number` Defined in: [packages/core/src/effects/delay-effect.ts:138](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L138) ramp-setter-desync fix: rampTo('time'/'feedback', ...) routes through these same clamp functions the property setters use, and updates the shadow field, so the getter and the AudioParam can never diverge. #### Parameters ##### param `string` ##### value `number` #### Returns `number` #### Overrides [`BaseEffect`](BaseEffect.md).[`onParamRamped`](BaseEffect.md#onparamramped) *** ### rampTo() > **rampTo**(`param`, `value`, `duration`): `void` Defined in: [packages/core/src/effects/base-effect.ts:164](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L164) Smoothly ramp a parameter to a target value over a duration. Uses `AudioParam.setTargetAtTime` for glitch-free transitions. If the parameter name is not recognized, this is a no-op (a `console.warn` is emitted if the name is a real, documented effect property that just isn't backed by a single AudioParam — see [getUnrampableParams](BaseEffect.md#getunrampableparams)). **Single write path:** every ramped write is funneled through [onParamRamped](BaseEffect.md#onparamramped), the same hook subclasses use to keep their shadow getters honest. This guarantees `effect.someParam` reflects the ramp target immediately after calling `rampTo()`, and that the exact same validation/clamping a synchronous property-set would apply is also applied to ramped writes — the AudioParam and the getter can never diverge from each other. #### Parameters ##### param `string` Parameter name (e.g., 'frequency', 'time', 'feedback') ##### value `number` Target value ##### duration `number` Ramp duration in seconds #### Returns `void` #### Example ```typescript delay.rampTo('time', 0.5, 2) // Ramp delay time to 0.5s over 2 seconds filter.rampTo('frequency', 800, 1) // Ramp cutoff to 800Hz over 1 second ``` #### Inherited from [`BaseEffect`](BaseEffect.md).[`rampTo`](BaseEffect.md#rampto) *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/DistortionEffect.md' --- [EZ Web Audio](../index.md) / DistortionEffect # Class: DistortionEffect Defined in: [packages/core/src/effects/distortion-effect.ts:110](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L110) DistortionEffect - WaveShaper-based distortion with selectable curve types and tone control. Supports four built-in curve types (soft, hard, fuzz, overdrive) plus custom curves. Includes a post-distortion tone control (lowpass filter) to shape the output. Uses 4x oversampling by default to prevent aliasing artifacts. Extends BaseEffect for shared wet/dry mixing, bypass, and rampTo() functionality. ## Example ```typescript import { createDistortion, createSound } from 'ez-web-audio' const sound = await createSound('guitar.mp3') const dist = createDistortion({ type: 'overdrive', amount: 50, tone: 0.6, mix: 0.7 }) sound.addEffect(dist) sound.play() // Real-time control dist.amount = 80 dist.tone = 0.3 // Darker tone dist.type = 'fuzz' // Switch curve type ``` ## Extends * [`BaseEffect`](BaseEffect.md) ## Constructors ### Constructor > **new DistortionEffect**(`audioContext`, `options`): `DistortionEffect` Defined in: [packages/core/src/effects/distortion-effect.ts:131](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L131) #### Parameters ##### audioContext `AudioContext` ##### options [`DistortionOptions`](../interfaces/DistortionOptions.md) = `{}` #### Returns `DistortionEffect` #### Overrides [`BaseEffect`](BaseEffect.md).[`constructor`](BaseEffect.md#constructor) ## Accessors ### amount #### Get Signature > **get** **amount**(): `number` Defined in: [packages/core/src/effects/distortion-effect.ts:203](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L203) Distortion amount (0-100). **M8 fix (dual-waveshaper crossfade):** `curve` is a plain array property, not an AudioParam, so it can't be smoothed with `setTargetAtTime` the way every other effect parameter in this library is — a synchronous swap on a single WaveShaperNode is a hard discontinuity in the transfer function and clicks if audio is actively flowing through it. This setter instead writes the new curve into the currently-inactive of two parallel WaveShaperNodes, then crossfades the two nodes' gains over ~15ms via `setTargetAtTime` so the swap is masked rather than heard. See crossfadeToCurve. The crossfade is entirely internal — `amount` still isn't rampable via `rampTo()` (it's not a single AudioParam), but ordinary synchronous sets like `effect.amount = 80` are now click-free at knob-drag rates, including rapid successive changes mid-crossfade. ##### Returns `number` #### Set Signature > **set** **amount**(`v`): `void` Defined in: [packages/core/src/effects/distortion-effect.ts:207](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L207) ##### Parameters ###### v `number` ##### Returns `void` *** ### bypass #### Get Signature > **get** **bypass**(): `boolean` Defined in: [packages/core/src/effects/base-effect.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L95) When true, signal bypasses the effect entirely (100% dry). ##### Returns `boolean` #### Set Signature > **set** **bypass**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L99) When true, effect is bypassed (passthrough) ##### Parameters ###### v `boolean` ##### Returns `void` When true, effect is bypassed (passthrough) #### Inherited from [`BaseEffect`](BaseEffect.md).[`bypass`](BaseEffect.md#bypass) *** ### input #### Get Signature > **get** **input**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:83](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L83) The input AudioNode (receives signal from chain) ##### Returns `AudioNode` The input AudioNode that receives signal from the chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`input`](BaseEffect.md#input) *** ### mix #### Get Signature > **get** **mix**(): `number` Defined in: [packages/core/src/effects/base-effect.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L108) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (all through effect). Uses equal-power crossfade for natural mixing. ##### Returns `number` #### Set Signature > **set** **mix**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:112](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L112) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) ##### Parameters ###### v `number` ##### Returns `void` Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) #### Inherited from [`BaseEffect`](BaseEffect.md).[`mix`](BaseEffect.md#mix) *** ### output #### Get Signature > **get** **output**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:88](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L88) The output AudioNode (sends signal to next in chain) ##### Returns `AudioNode` The output AudioNode that sends signal to the next in chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`output`](BaseEffect.md#output) *** ### oversample #### Get Signature > **get** **oversample**(): `OverSampleType` Defined in: [packages/core/src/effects/distortion-effect.ts:249](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L249) Oversampling mode for aliasing prevention ##### Returns `OverSampleType` #### Set Signature > **set** **oversample**(`v`): `void` Defined in: [packages/core/src/effects/distortion-effect.ts:253](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L253) ##### Parameters ###### v `OverSampleType` ##### Returns `void` *** ### tone #### Get Signature > **get** **tone**(): `number` Defined in: [packages/core/src/effects/distortion-effect.ts:239](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L239) Post-distortion tone control (0 = dark/200Hz, 1 = bright/8000Hz) ##### Returns `number` #### Set Signature > **set** **tone**(`v`): `void` Defined in: [packages/core/src/effects/distortion-effect.ts:243](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L243) ##### Parameters ###### v `number` ##### Returns `void` *** ### type #### Get Signature > **get** **type**(): [`DistortionType`](../type-aliases/DistortionType.md) Defined in: [packages/core/src/effects/distortion-effect.ts:220](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L220) Distortion curve type. **M8 fix:** same dual-waveshaper crossfade as [amount](#amount) — see its JSDoc for the full explanation. ##### Returns [`DistortionType`](../type-aliases/DistortionType.md) #### Set Signature > **set** **type**(`v`): `void` Defined in: [packages/core/src/effects/distortion-effect.ts:224](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L224) ##### Parameters ###### v [`DistortionType`](../type-aliases/DistortionType.md) ##### Returns `void` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 [`BaseEffect`](BaseEffect.md).[`_clearListeners`](BaseEffect.md#clearlisteners) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/effects/distortion-effect.ts:258](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L258) Disconnect all internal audio nodes and emit a 'dispose' event. **Subclass disposal contract:** Subclasses that create additional audio nodes (e.g., BiquadFilterNode, DynamicsCompressorNode, WaveShaperNode) MUST override dispose() to disconnect those nodes before calling super.dispose(). #### Returns `void` #### Example ```typescript public override dispose(): void { try { this.myNode.disconnect() } catch { /* already disconnected */ } super.dispose() } ``` Idempotent — safe to call multiple times. #### Overrides [`BaseEffect`](BaseEffect.md).[`dispose`](BaseEffect.md#dispose) *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail `BaseEffectEventMap`\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`BaseEffect`](BaseEffect.md).[`emit`](BaseEffect.md#emit) *** ### getAudioContext() > **getAudioContext**(): `AudioContext` Defined in: [packages/core/src/effects/base-effect.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L121) Get the AudioContext used by this effect. Useful for external tools (e.g., LFO) that need the context. #### Returns `AudioContext` #### Inherited from [`BaseEffect`](BaseEffect.md).[`getAudioContext`](BaseEffect.md#getaudiocontext) *** ### getAudioParam() > `protected` **getAudioParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/distortion-effect.ts:282](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L282) Map a parameter name to its underlying AudioParam. Subclasses implement this to expose their effect-specific parameters. #### Parameters ##### name `string` The parameter name #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Overrides [`BaseEffect`](BaseEffect.md).[`getAudioParam`](BaseEffect.md#getaudioparam) *** ### getParam() > **getParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/base-effect.ts:134](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L134) Get a named AudioParam from this effect for external modulation. Delegates to the subclass's getAudioParam() implementation. Returns null if the parameter name is not recognized. #### Parameters ##### name `string` The parameter name (e.g., 'frequency', 'time', 'feedback') #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Inherited from [`BaseEffect`](BaseEffect.md).[`getParam`](BaseEffect.md#getparam) *** ### getUnrampableParams() > `protected` **getUnrampableParams**(): readonly `string`\[] Defined in: [packages/core/src/effects/distortion-effect.ts:298](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L298) `amount` and `type` are documented DistortionEffect properties but aren't backed by a single AudioParam — they drive a curve swap on one of two internal WaveShaperNodes, crossfaded via `crossfadeToCurve()` (see the M8 JSDoc on those setters). That crossfade is internal machinery, not something `rampTo()` can drive over an arbitrary caller duration, so rampTo() warns rather than silently no-op-ing if called with either name. #### Returns readonly `string`\[] #### Overrides [`BaseEffect`](BaseEffect.md).[`getUnrampableParams`](BaseEffect.md#getunrampableparams) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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"` #### 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 [`BaseEffect`](BaseEffect.md).[`off`](BaseEffect.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`on`](BaseEffect.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`once`](BaseEffect.md#once) *** ### onParamRamped() > `protected` **onParamRamped**(`param`, `value`): `number` Defined in: [packages/core/src/effects/distortion-effect.ts:312](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L312) ramp-setter-desync fix: `tone`'s public domain is 0-1 (mapped exponentially to the toneFilter's Hz range by `applyTone()`), but `getAudioParam('tone')` exposes the underlying Hz-valued AudioParam directly — before this fix, `rampTo('tone', v, duration)` wrote the raw 0-1 `v` straight into the Hz AudioParam (e.g. `rampTo('tone', 0.8, 1)` set the filter to 0.8 Hz, not ~3.5kHz), silently diverging from what `effect.tone = 0.8` actually does. This re-applies the exact same clamp + Hz mapping the `tone` setter uses, so both paths agree. #### Parameters ##### param `string` ##### value `number` #### Returns `number` #### Overrides [`BaseEffect`](BaseEffect.md).[`onParamRamped`](BaseEffect.md#onparamramped) *** ### rampTo() > **rampTo**(`param`, `value`, `duration`): `void` Defined in: [packages/core/src/effects/base-effect.ts:164](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L164) Smoothly ramp a parameter to a target value over a duration. Uses `AudioParam.setTargetAtTime` for glitch-free transitions. If the parameter name is not recognized, this is a no-op (a `console.warn` is emitted if the name is a real, documented effect property that just isn't backed by a single AudioParam — see [getUnrampableParams](BaseEffect.md#getunrampableparams)). **Single write path:** every ramped write is funneled through [onParamRamped](BaseEffect.md#onparamramped), the same hook subclasses use to keep their shadow getters honest. This guarantees `effect.someParam` reflects the ramp target immediately after calling `rampTo()`, and that the exact same validation/clamping a synchronous property-set would apply is also applied to ramped writes — the AudioParam and the getter can never diverge from each other. #### Parameters ##### param `string` Parameter name (e.g., 'frequency', 'time', 'feedback') ##### value `number` Target value ##### duration `number` Ramp duration in seconds #### Returns `void` #### Example ```typescript delay.rampTo('time', 0.5, 2) // Ramp delay time to 0.5s over 2 seconds filter.rampTo('frequency', 800, 1) // Ramp cutoff to 800Hz over 1 second ``` #### Inherited from [`BaseEffect`](BaseEffect.md).[`rampTo`](BaseEffect.md#rampto) *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/EffectWrapper.md' --- [EZ Web Audio](../index.md) / EffectWrapper # Class: EffectWrapper Defined in: [packages/core/src/effects/effect-wrapper.ts:50](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L50) EffectWrapper - Wraps external effects (like Tuna.js, custom WaveShaperNode, etc.) to provide a standard Effect interface with bypass and wet/dry mix controls. External effects only need a connect() method to be wrapped. The wrapper creates the necessary infrastructure for wet/dry mixing and bypass functionality. ## Supported Effect Types Supports three types of external effects: 1. **Tuna.js effects** — Have an `input` AudioNode property 2. **Native AudioNodes** — WaveShaperNode, ConvolverNode, etc. 3. **Any object with connect()** — Minimum interface requirement Routing: * Dry path: input -> dryGain -> output * Wet path: input -> externalEffect -> wetGain -> output ## Example ```typescript // Wrap a Tuna.js effect const tuna = new Tuna(audioContext) const chorus = tuna.Chorus({ rate: 1.5 }) const wrapped = wrapEffect(audioContext, chorus) // Now use standard Effect interface wrapped.bypass = true // Bypass the effect wrapped.mix = 0.5 // 50% wet/dry blend // Access original effect wrapped.effect.rate = 2.0 ``` ## Implements * [`Effect`](../interfaces/Effect.md) ## Constructors ### Constructor > **new EffectWrapper**(`audioContext`, `externalEffect`): `EffectWrapper` Defined in: [packages/core/src/effects/effect-wrapper.ts:62](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L62) #### Parameters ##### audioContext `AudioContext` ##### externalEffect [`ExternalEffect`](../interfaces/ExternalEffect.md) #### Returns `EffectWrapper` ## Accessors ### bypass #### Get Signature > **get** **bypass**(): `boolean` Defined in: [packages/core/src/effects/effect-wrapper.ts:136](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L136) When true, signal bypasses the effect entirely (100% dry). ##### Returns `boolean` #### Set Signature > **set** **bypass**(`v`): `void` Defined in: [packages/core/src/effects/effect-wrapper.ts:140](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L140) When true, effect is bypassed (passthrough) ##### Parameters ###### v `boolean` ##### Returns `void` When true, effect is bypassed (passthrough) #### Implementation of [`Effect`](../interfaces/Effect.md).[`bypass`](../interfaces/Effect.md#bypass) *** ### effect #### Get Signature > **get** **effect**(): [`ExternalEffect`](../interfaces/ExternalEffect.md) Defined in: [packages/core/src/effects/effect-wrapper.ts:162](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L162) Access the wrapped external effect for configuration. This allows direct manipulation of the effect's native properties. ##### Returns [`ExternalEffect`](../interfaces/ExternalEffect.md) *** ### input #### Get Signature > **get** **input**(): `AudioNode` Defined in: [packages/core/src/effects/effect-wrapper.ts:124](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L124) The input AudioNode (receives signal from chain) ##### Returns `AudioNode` The input AudioNode that receives signal from the chain #### Implementation of [`Effect`](../interfaces/Effect.md).[`input`](../interfaces/Effect.md#input) *** ### mix #### Get Signature > **get** **mix**(): `number` Defined in: [packages/core/src/effects/effect-wrapper.ts:149](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L149) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (all through effect). Uses equal-power crossfade for natural mixing. ##### Returns `number` #### Set Signature > **set** **mix**(`v`): `void` Defined in: [packages/core/src/effects/effect-wrapper.ts:153](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L153) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) ##### Parameters ###### v `number` ##### Returns `void` Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) #### Implementation of [`Effect`](../interfaces/Effect.md).[`mix`](../interfaces/Effect.md#mix) *** ### output #### Get Signature > **get** **output**(): `AudioNode` Defined in: [packages/core/src/effects/effect-wrapper.ts:129](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L129) The output AudioNode (sends signal to next in chain) ##### Returns `AudioNode` The output AudioNode that sends signal to the next in chain #### Implementation of [`Effect`](../interfaces/Effect.md).[`output`](../interfaces/Effect.md#output) ## Methods ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/effects/effect-wrapper.ts:185](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L185) Disconnect all internal audio nodes (input/output/dry/wet) and, if the wrapped external effect exposes a `disconnect()` method, disconnect it too. Idempotent — safe to call multiple times. #### Returns `void` #### Implementation of [`Effect`](../interfaces/Effect.md).[`dispose`](../interfaces/Effect.md#dispose) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Envelope.md' --- [EZ Web Audio](../index.md) / Envelope # Class: Envelope Defined in: [packages/core/src/envelope.ts:60](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L60) ADSR Envelope class for managing amplitude envelope scheduling. The envelope controls how a sound's amplitude evolves over time: * **Attack**: Ramp from 0 to peak (the sound's target gain, 1.0 by default) * **Decay**: Ramp from peak to sustain level * **Sustain**: Hold at sustain level until release() called * **Release**: Exponential decay to silence Supports clickless retriggering: when a note is retriggered while the envelope is still active, it picks up from the current value instead of jumping to zero, preventing audible clicks. ## Example ```typescript const envelope = new Envelope({ attack: 0.05, decay: 0.1, sustain: 0.7, release: 0.3 }) // Apply on note start envelope.applyTo(gainNode.gain, audioContext.currentTime) // Release on note end envelope.triggerRelease(gainNode.gain, audioContext.currentTime) ``` ## Constructors ### Constructor > **new Envelope**(`options`): `Envelope` Defined in: [packages/core/src/envelope.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L99) Creates a new Envelope with the specified ADSR parameters. #### Parameters ##### options [`EnvelopeOptions`](../interfaces/EnvelopeOptions.md) = `{}` ADSR configuration options #### Returns `Envelope` ## Properties ### attack > `readonly` **attack**: `number` Defined in: [packages/core/src/envelope.ts:62](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L62) Duration in seconds to ramp from 0 to peak (1.0) *** ### decay > `readonly` **decay**: `number` Defined in: [packages/core/src/envelope.ts:65](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L65) Duration in seconds to ramp from peak to sustain level *** ### release > `readonly` **release**: `number` Defined in: [packages/core/src/envelope.ts:71](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L71) Duration in seconds for release to silence *** ### sustain > `readonly` **sustain**: `number` Defined in: [packages/core/src/envelope.ts:68](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L68) Amplitude level (0-1) held during sustain phase ## Accessors ### isActive #### Get Signature > **get** **isActive**(): `boolean` Defined in: [packages/core/src/envelope.ts:109](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L109) Whether the envelope is currently active (between applyTo and release). ##### Returns `boolean` ## Methods ### applyTo() > **applyTo**(`gainParam`, `startTime`, `peak`): `void` Defined in: [packages/core/src/envelope.ts:200](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L200) Applies the attack-decay-sustain phases to an AudioParam. Schedules: 1. setValueAtTime(startValue, startTime) - Start from current value (0 for first trigger) 2. linearRampToValueAtTime(peak, startTime + attackTime) - Attack to peak 3. linearRampToValueAtTime(sustain \* peak, startTime + attackTime + decayTime) - Decay to sustain If retriggering (envelope already active), cancels scheduled values and starts the attack from the current estimated value to prevent clicks. #### Parameters ##### gainParam `AudioParam` The AudioParam to schedule the envelope on (typically gainNode.gain) ##### startTime `number` The audio context time to start the envelope ##### peak `number` = `1` Absolute amplitude the attack ramps to — the sound's target gain (default: 1) #### Returns `void` *** ### estimateCurrentValue() > **estimateCurrentValue**(`currentTime`): `number` Defined in: [packages/core/src/envelope.ts:122](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L122) Estimates the current envelope value at a given time. Used for retriggering to determine where to pick up from. Returns 0 if envelope is not active. #### Parameters ##### currentTime `number` The time to estimate the value at #### Returns `number` The estimated absolute envelope value (0 to peak) *** ### triggerRelease() > **triggerRelease**(`gainParam`, `startTime`): `void` Defined in: [packages/core/src/envelope.ts:254](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L254) Applies the release phase to an AudioParam. Cancels any in-progress attack/decay automation (preserving the current value via cancelAndHoldAtTime) and schedules a linear ramp to zero over the release duration. A linear ramp is used instead of setTargetAtTime because setTargetAtTime is an asymptotic exponential that never reaches zero — the residual amplitude causes an audible click when the oscillator node is stopped, especially on smooth waveforms (sine, triangle). #### Parameters ##### gainParam `AudioParam` The AudioParam to schedule the release on ##### startTime `number` The audio context time to start the release phase #### Returns `void` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/EQEffect.md' --- [EZ Web Audio](../index.md) / EQEffect # Class: EQEffect Defined in: [packages/core/src/effects/eq-effect.ts:51](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L51) EQEffect - Three-band equalizer using cascaded BiquadFilterNodes. Uses lowshelf (low), peaking (mid), and highshelf (high) filters for independent control of three frequency bands. Gain values are in dB. Extends BaseEffect for shared wet/dry mixing, bypass, and rampTo() functionality. ## Example ```typescript import { createEQ, createSound } from 'ez-web-audio' const sound = await createSound('music.mp3') const eq = createEQ({ low: 3, mid: -2, high: 4 }) sound.addEffect(eq) sound.play() // Real-time control eq.low = 6 // Boost bass eq.mid = 0 // Flat mids eq.high = -3 // Cut highs eq.rampTo('low', 0, 2) // Smooth ramp back to flat over 2 seconds ``` ## Extends * [`BaseEffect`](BaseEffect.md) ## Constructors ### Constructor > **new EQEffect**(`audioContext`, `options`): `EQEffect` Defined in: [packages/core/src/effects/eq-effect.ts:66](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L66) #### Parameters ##### audioContext `AudioContext` ##### options [`EQOptions`](../interfaces/EQOptions.md) = `{}` #### Returns `EQEffect` #### Overrides [`BaseEffect`](BaseEffect.md).[`constructor`](BaseEffect.md#constructor) ## Accessors ### bypass #### Get Signature > **get** **bypass**(): `boolean` Defined in: [packages/core/src/effects/base-effect.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L95) When true, signal bypasses the effect entirely (100% dry). ##### Returns `boolean` #### Set Signature > **set** **bypass**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L99) When true, effect is bypassed (passthrough) ##### Parameters ###### v `boolean` ##### Returns `void` When true, effect is bypassed (passthrough) #### Inherited from [`BaseEffect`](BaseEffect.md).[`bypass`](BaseEffect.md#bypass) *** ### high #### Get Signature > **get** **high**(): `number` Defined in: [packages/core/src/effects/eq-effect.ts:126](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L126) High band gain in dB ##### Returns `number` #### Set Signature > **set** **high**(`v`): `void` Defined in: [packages/core/src/effects/eq-effect.ts:130](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L130) ##### Parameters ###### v `number` ##### Returns `void` *** ### highFrequency #### Get Signature > **get** **highFrequency**(): `number` Defined in: [packages/core/src/effects/eq-effect.ts:156](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L156) High band crossover frequency in Hz ##### Returns `number` #### Set Signature > **set** **highFrequency**(`v`): `void` Defined in: [packages/core/src/effects/eq-effect.ts:160](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L160) ##### Parameters ###### v `number` ##### Returns `void` *** ### input #### Get Signature > **get** **input**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:83](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L83) The input AudioNode (receives signal from chain) ##### Returns `AudioNode` The input AudioNode that receives signal from the chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`input`](BaseEffect.md#input) *** ### low #### Get Signature > **get** **low**(): `number` Defined in: [packages/core/src/effects/eq-effect.ts:106](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L106) Low band gain in dB ##### Returns `number` #### Set Signature > **set** **low**(`v`): `void` Defined in: [packages/core/src/effects/eq-effect.ts:110](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L110) ##### Parameters ###### v `number` ##### Returns `void` *** ### lowFrequency #### Get Signature > **get** **lowFrequency**(): `number` Defined in: [packages/core/src/effects/eq-effect.ts:136](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L136) Low band crossover frequency in Hz ##### Returns `number` #### Set Signature > **set** **lowFrequency**(`v`): `void` Defined in: [packages/core/src/effects/eq-effect.ts:140](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L140) ##### Parameters ###### v `number` ##### Returns `void` *** ### mid #### Get Signature > **get** **mid**(): `number` Defined in: [packages/core/src/effects/eq-effect.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L116) Mid band gain in dB ##### Returns `number` #### Set Signature > **set** **mid**(`v`): `void` Defined in: [packages/core/src/effects/eq-effect.ts:120](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L120) ##### Parameters ###### v `number` ##### Returns `void` *** ### midFrequency #### Get Signature > **get** **midFrequency**(): `number` Defined in: [packages/core/src/effects/eq-effect.ts:146](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L146) Mid band center frequency in Hz ##### Returns `number` #### Set Signature > **set** **midFrequency**(`v`): `void` Defined in: [packages/core/src/effects/eq-effect.ts:150](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L150) ##### Parameters ###### v `number` ##### Returns `void` *** ### midQ #### Get Signature > **get** **midQ**(): `number` Defined in: [packages/core/src/effects/eq-effect.ts:166](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L166) Mid band Q factor (bandwidth). Clamped positive; non-finite input is ignored. ##### Returns `number` #### Set Signature > **set** **midQ**(`v`): `void` Defined in: [packages/core/src/effects/eq-effect.ts:170](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L170) ##### Parameters ###### v `number` ##### Returns `void` *** ### mix #### Get Signature > **get** **mix**(): `number` Defined in: [packages/core/src/effects/base-effect.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L108) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (all through effect). Uses equal-power crossfade for natural mixing. ##### Returns `number` #### Set Signature > **set** **mix**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:112](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L112) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) ##### Parameters ###### v `number` ##### Returns `void` Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) #### Inherited from [`BaseEffect`](BaseEffect.md).[`mix`](BaseEffect.md#mix) *** ### output #### Get Signature > **get** **output**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:88](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L88) The output AudioNode (sends signal to next in chain) ##### Returns `AudioNode` The output AudioNode that sends signal to the next in chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`output`](BaseEffect.md#output) ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 [`BaseEffect`](BaseEffect.md).[`_clearListeners`](BaseEffect.md#clearlisteners) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/effects/eq-effect.ts:177](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L177) Disconnect all internal audio nodes and emit a 'dispose' event. **Subclass disposal contract:** Subclasses that create additional audio nodes (e.g., BiquadFilterNode, DynamicsCompressorNode, WaveShaperNode) MUST override dispose() to disconnect those nodes before calling super.dispose(). #### Returns `void` #### Example ```typescript public override dispose(): void { try { this.myNode.disconnect() } catch { /* already disconnected */ } super.dispose() } ``` Idempotent — safe to call multiple times. #### Overrides [`BaseEffect`](BaseEffect.md).[`dispose`](BaseEffect.md#dispose) *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail `BaseEffectEventMap`\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`BaseEffect`](BaseEffect.md).[`emit`](BaseEffect.md#emit) *** ### getAudioContext() > **getAudioContext**(): `AudioContext` Defined in: [packages/core/src/effects/base-effect.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L121) Get the AudioContext used by this effect. Useful for external tools (e.g., LFO) that need the context. #### Returns `AudioContext` #### Inherited from [`BaseEffect`](BaseEffect.md).[`getAudioContext`](BaseEffect.md#getaudiocontext) *** ### getAudioParam() > `protected` **getAudioParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/eq-effect.ts:193](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L193) Map a parameter name to its underlying AudioParam. Subclasses implement this to expose their effect-specific parameters. #### Parameters ##### name `string` The parameter name #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Overrides [`BaseEffect`](BaseEffect.md).[`getAudioParam`](BaseEffect.md#getaudioparam) *** ### getParam() > **getParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/base-effect.ts:134](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L134) Get a named AudioParam from this effect for external modulation. Delegates to the subclass's getAudioParam() implementation. Returns null if the parameter name is not recognized. #### Parameters ##### name `string` The parameter name (e.g., 'frequency', 'time', 'feedback') #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Inherited from [`BaseEffect`](BaseEffect.md).[`getParam`](BaseEffect.md#getparam) *** ### getUnrampableParams() > `protected` **getUnrampableParams**(): readonly `string`\[] Defined in: [packages/core/src/effects/base-effect.ts:243](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L243) Names of documented effect properties that are NOT backed by a single AudioParam (e.g. WaveShaper curve swaps, multi-node comb/allpass networks) and therefore cannot be smoothly ramped via `rampTo()`. `rampTo()` warns instead of silently no-op-ing when called with one of these names, so callers don't mistake "no-op" for "it worked." Default: none. Subclasses override where applicable. #### Returns readonly `string`\[] #### Inherited from [`BaseEffect`](BaseEffect.md).[`getUnrampableParams`](BaseEffect.md#getunrampableparams) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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"` #### 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 [`BaseEffect`](BaseEffect.md).[`off`](BaseEffect.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`on`](BaseEffect.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`once`](BaseEffect.md#once) *** ### onParamRamped() > `protected` **onParamRamped**(`param`, `value`): `number` Defined in: [packages/core/src/effects/eq-effect.ts:212](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L212) ramp-setter-desync fix: rampTo() on any of the 7 band params updates the matching shadow field (midQ additionally re-applies the same positive/finite clamp the setter uses) so getters stay honest after a ramp completes. #### Parameters ##### param `string` ##### value `number` #### Returns `number` #### Overrides [`BaseEffect`](BaseEffect.md).[`onParamRamped`](BaseEffect.md#onparamramped) *** ### rampTo() > **rampTo**(`param`, `value`, `duration`): `void` Defined in: [packages/core/src/effects/base-effect.ts:164](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L164) Smoothly ramp a parameter to a target value over a duration. Uses `AudioParam.setTargetAtTime` for glitch-free transitions. If the parameter name is not recognized, this is a no-op (a `console.warn` is emitted if the name is a real, documented effect property that just isn't backed by a single AudioParam — see [getUnrampableParams](BaseEffect.md#getunrampableparams)). **Single write path:** every ramped write is funneled through [onParamRamped](BaseEffect.md#onparamramped), the same hook subclasses use to keep their shadow getters honest. This guarantees `effect.someParam` reflects the ramp target immediately after calling `rampTo()`, and that the exact same validation/clamping a synchronous property-set would apply is also applied to ramped writes — the AudioParam and the getter can never diverge from each other. #### Parameters ##### param `string` Parameter name (e.g., 'frequency', 'time', 'feedback') ##### value `number` Target value ##### duration `number` Ramp duration in seconds #### Returns `void` #### Example ```typescript delay.rampTo('time', 0.5, 2) // Ramp delay time to 0.5s over 2 seconds filter.rampTo('frequency', 800, 1) // Ramp cutoff to 800Hz over 1 second ``` #### Inherited from [`BaseEffect`](BaseEffect.md).[`rampTo`](BaseEffect.md#rampto) *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/FilterEffect.md' --- [EZ Web Audio](../index.md) / FilterEffect # Class: FilterEffect Defined in: [packages/core/src/effects/filter-effect.ts:52](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L52) FilterEffect - A wrapper around BiquadFilterNode that implements the Effect interface. Supports all 8 BiquadFilter types with wet/dry mixing via equal-power crossfade. The bypass and mix controls allow smooth blending between filtered and dry signal. Extends BaseEffect for shared wet/dry mixing, bypass, and rampTo() functionality. ## Example ```typescript const filter = createFilterEffect(audioContext, 'lowpass', { frequency: 800, q: 2 }) filter.frequency = 1000 // Adjust cutoff filter.mix = 0.5 // 50% wet/dry filter.bypass = true // Bypass filter entirely filter.rampTo('frequency', 2000, 1) // Smooth ramp over 1 second ``` ## Extends * [`BaseEffect`](BaseEffect.md) ## Constructors ### Constructor > **new FilterEffect**(`audioContext`, `type`, `options`): `FilterEffect` Defined in: [packages/core/src/effects/filter-effect.ts:62](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L62) #### Parameters ##### audioContext `AudioContext` ##### type [`FilterType`](../type-aliases/FilterType.md) ##### options [`FilterEffectOptions`](../interfaces/FilterEffectOptions.md) = `{}` #### Returns `FilterEffect` #### Overrides [`BaseEffect`](BaseEffect.md).[`constructor`](BaseEffect.md#constructor) ## Accessors ### bypass #### Get Signature > **get** **bypass**(): `boolean` Defined in: [packages/core/src/effects/base-effect.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L95) When true, signal bypasses the effect entirely (100% dry). ##### Returns `boolean` #### Set Signature > **set** **bypass**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L99) When true, effect is bypassed (passthrough) ##### Parameters ###### v `boolean` ##### Returns `void` When true, effect is bypassed (passthrough) #### Inherited from [`BaseEffect`](BaseEffect.md).[`bypass`](BaseEffect.md#bypass) *** ### detune #### Get Signature > **get** **detune**(): `number` Defined in: [packages/core/src/effects/filter-effect.ts:136](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L136) Filter detune in cents ##### Returns `number` #### Set Signature > **set** **detune**(`v`): `void` Defined in: [packages/core/src/effects/filter-effect.ts:140](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L140) ##### Parameters ###### v `number` ##### Returns `void` *** ### frequency #### Get Signature > **get** **frequency**(): `number` Defined in: [packages/core/src/effects/filter-effect.ts:91](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L91) Filter frequency in Hz. Clamped to \[0, sampleRate / 2] (Nyquist) — BiquadFilterNode.frequency is spec'd over that range; anything outside it is meaningless (and some implementations clamp/misbehave silently). ##### Returns `number` #### Set Signature > **set** **frequency**(`v`): `void` Defined in: [packages/core/src/effects/filter-effect.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L95) ##### Parameters ###### v `number` ##### Returns `void` *** ### gain #### Get Signature > **get** **gain**(): `number` Defined in: [packages/core/src/effects/filter-effect.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L121) Filter gain in dB. Only affects `lowshelf`, `highshelf`, and `peaking` filter types — the other 5 types (lowpass, highpass, bandpass, notch, allpass) ignore gain entirely per the Web Audio spec. Setting gain on one of those types is a silent no-op audibly; a dev warning is emitted to catch the mistake early. ##### Returns `number` #### Set Signature > **set** **gain**(`v`): `void` Defined in: [packages/core/src/effects/filter-effect.ts:125](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L125) ##### Parameters ###### v `number` ##### Returns `void` *** ### input #### Get Signature > **get** **input**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:83](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L83) The input AudioNode (receives signal from chain) ##### Returns `AudioNode` The input AudioNode that receives signal from the chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`input`](BaseEffect.md#input) *** ### mix #### Get Signature > **get** **mix**(): `number` Defined in: [packages/core/src/effects/base-effect.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L108) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (all through effect). Uses equal-power crossfade for natural mixing. ##### Returns `number` #### Set Signature > **set** **mix**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:112](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L112) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) ##### Parameters ###### v `number` ##### Returns `void` Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) #### Inherited from [`BaseEffect`](BaseEffect.md).[`mix`](BaseEffect.md#mix) *** ### output #### Get Signature > **get** **output**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:88](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L88) The output AudioNode (sends signal to next in chain) ##### Returns `AudioNode` The output AudioNode that sends signal to the next in chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`output`](BaseEffect.md#output) *** ### q #### Get Signature > **get** **q**(): `number` Defined in: [packages/core/src/effects/filter-effect.ts:105](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L105) Filter Q factor (resonance). Floored just above 0 — a Q of exactly 0 (or negative) is undefined/unstable for resonant filter types (bandpass/notch/peaking). ##### Returns `number` #### Set Signature > **set** **q**(`v`): `void` Defined in: [packages/core/src/effects/filter-effect.ts:109](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L109) ##### Parameters ###### v `number` ##### Returns `void` *** ### type #### Get Signature > **get** **type**(): [`FilterType`](../type-aliases/FilterType.md) Defined in: [packages/core/src/effects/filter-effect.ts:156](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L156) The current filter type. **Hard-cut, not a crossfade:** changing type reconfigures the BiquadFilterNode's internal coefficients instantly — there is no ramp/interpolation between the old and new filter response. If audio is actively flowing through this effect when the type changes, expect an audible discontinuity (click/thump), the same class of pop that curve-swap effects (e.g. DistortionEffect) have. Wrap the change in a `mix` fade-to-0 / fade-back-to-target if that's audible in context. ##### Returns [`FilterType`](../type-aliases/FilterType.md) #### Set Signature > **set** **type**(`v`): `void` Defined in: [packages/core/src/effects/filter-effect.ts:160](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L160) ##### Parameters ###### v [`FilterType`](../type-aliases/FilterType.md) ##### Returns `void` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 [`BaseEffect`](BaseEffect.md).[`_clearListeners`](BaseEffect.md#clearlisteners) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/effects/filter-effect.ts:164](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L164) Disconnect all internal audio nodes and emit a 'dispose' event. **Subclass disposal contract:** Subclasses that create additional audio nodes (e.g., BiquadFilterNode, DynamicsCompressorNode, WaveShaperNode) MUST override dispose() to disconnect those nodes before calling super.dispose(). #### Returns `void` #### Example ```typescript public override dispose(): void { try { this.myNode.disconnect() } catch { /* already disconnected */ } super.dispose() } ``` Idempotent — safe to call multiple times. #### Overrides [`BaseEffect`](BaseEffect.md).[`dispose`](BaseEffect.md#dispose) *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail `BaseEffectEventMap`\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`BaseEffect`](BaseEffect.md).[`emit`](BaseEffect.md#emit) *** ### getAudioContext() > **getAudioContext**(): `AudioContext` Defined in: [packages/core/src/effects/base-effect.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L121) Get the AudioContext used by this effect. Useful for external tools (e.g., LFO) that need the context. #### Returns `AudioContext` #### Inherited from [`BaseEffect`](BaseEffect.md).[`getAudioContext`](BaseEffect.md#getaudiocontext) *** ### getAudioParam() > `protected` **getAudioParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/filter-effect.ts:172](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L172) Map a parameter name to its underlying AudioParam. Subclasses implement this to expose their effect-specific parameters. #### Parameters ##### name `string` The parameter name #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Overrides [`BaseEffect`](BaseEffect.md).[`getAudioParam`](BaseEffect.md#getaudioparam) *** ### getParam() > **getParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/base-effect.ts:134](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L134) Get a named AudioParam from this effect for external modulation. Delegates to the subclass's getAudioParam() implementation. Returns null if the parameter name is not recognized. #### Parameters ##### name `string` The parameter name (e.g., 'frequency', 'time', 'feedback') #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Inherited from [`BaseEffect`](BaseEffect.md).[`getParam`](BaseEffect.md#getparam) *** ### getUnrampableParams() > `protected` **getUnrampableParams**(): readonly `string`\[] Defined in: [packages/core/src/effects/base-effect.ts:243](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L243) Names of documented effect properties that are NOT backed by a single AudioParam (e.g. WaveShaper curve swaps, multi-node comb/allpass networks) and therefore cannot be smoothly ramped via `rampTo()`. `rampTo()` warns instead of silently no-op-ing when called with one of these names, so callers don't mistake "no-op" for "it worked." Default: none. Subclasses override where applicable. #### Returns readonly `string`\[] #### Inherited from [`BaseEffect`](BaseEffect.md).[`getUnrampableParams`](BaseEffect.md#getunrampableparams) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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"` #### 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 [`BaseEffect`](BaseEffect.md).[`off`](BaseEffect.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`on`](BaseEffect.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`once`](BaseEffect.md#once) *** ### onParamRamped() > `protected` **onParamRamped**(`param`, `value`): `number` Defined in: [packages/core/src/effects/filter-effect.ts:188](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L188) ramp-setter-desync fix: rampTo('frequency'/'q', ...) re-applies the same clamps the property setters use so the getter and AudioParam can never diverge; gain/detune have no range restriction so they pass through (matching their setters). #### Parameters ##### param `string` ##### value `number` #### Returns `number` #### Overrides [`BaseEffect`](BaseEffect.md).[`onParamRamped`](BaseEffect.md#onparamramped) *** ### rampTo() > **rampTo**(`param`, `value`, `duration`): `void` Defined in: [packages/core/src/effects/base-effect.ts:164](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L164) Smoothly ramp a parameter to a target value over a duration. Uses `AudioParam.setTargetAtTime` for glitch-free transitions. If the parameter name is not recognized, this is a no-op (a `console.warn` is emitted if the name is a real, documented effect property that just isn't backed by a single AudioParam — see [getUnrampableParams](BaseEffect.md#getunrampableparams)). **Single write path:** every ramped write is funneled through [onParamRamped](BaseEffect.md#onparamramped), the same hook subclasses use to keep their shadow getters honest. This guarantees `effect.someParam` reflects the ramp target immediately after calling `rampTo()`, and that the exact same validation/clamping a synchronous property-set would apply is also applied to ramped writes — the AudioParam and the getter can never diverge from each other. #### Parameters ##### param `string` Parameter name (e.g., 'frequency', 'time', 'feedback') ##### value `number` Target value ##### duration `number` Ramp duration in seconds #### Returns `void` #### Example ```typescript delay.rampTo('time', 0.5, 2) // Ramp delay time to 0.5s over 2 seconds filter.rampTo('frequency', 800, 1) // Ramp cutoff to 800Hz over 1 second ``` #### Inherited from [`BaseEffect`](BaseEffect.md).[`rampTo`](BaseEffect.md#rampto) *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Font.md' --- [EZ Web Audio](../index.md) / Font # Class: Font Defined in: [packages/core/src/font.ts:29](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/font.ts#L29) Collection of sampled notes for instrument playback. Font holds multiple SampledNote instances, typically loaded from a soundfont. Each note can be played by its identifier (e.g., "A4", "Bb3", "C#5"). ## Example ```typescript import { createFont } from 'ez-web-audio' const piano = await createFont('piano.js') // Play notes by identifier piano.play('C4') piano.play('E4') piano.play('G4') // Get a specific note for advanced control const note = piano.getNote('A4') note?.changeGainTo(0.5) note?.play() ``` ## Constructors ### Constructor > **new Font**(`notes`): `Font` Defined in: [packages/core/src/font.ts:35](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/font.ts#L35) #### Parameters ##### notes [`SampledNote`](SampledNote.md)\[] #### Returns `Font` ## Properties ### notes > **notes**: [`SampledNote`](SampledNote.md)\[] Defined in: [packages/core/src/font.ts:35](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/font.ts#L35) ## Methods ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/font.ts:103](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/font.ts#L103) Dispose every SampledNote owned by this Font, releasing their audio nodes/listeners. A Font can hold dozens of notes (a full soundfont) — without this, loading a Font and discarding it leaks every note's underlying AudioBufferSourceNode/gain/panner graph. Mirrors [BeatTrack.dispose](BeatTrack.md#dispose)'s owned-sounds cascade: the Font created (or was handed) these notes, so the Font disposes them. After disposal, the Font should not be used. Create a new instance (e.g., via `createFont()`) instead. #### Returns `void` #### Example ```typescript const piano = await createFont('piano.js') piano.play('C4') // When done: piano.dispose() ``` *** ### getNote() > **getNote**(`identifier`): [`SampledNote`](SampledNote.md) | `undefined` Defined in: [packages/core/src/font.ts:55](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/font.ts#L55) Get a note by its identifier. #### Parameters ##### identifier `string` Note identifier like "A4", "Bb3", "C#5" #### Returns [`SampledNote`](SampledNote.md) | `undefined` The SampledNote instance, or undefined if not found #### Example ```typescript const note = font.getNote('A4') if (note) { console.log(note.frequency) // 440 note.play() } ``` *** ### play() > **play**(`identifier`): `void` Defined in: [packages/core/src/font.ts:73](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/font.ts#L73) Play a note by its identifier. #### Parameters ##### identifier Note identifier like "A4", "Bb3", "C#5" `"C0"` | `"Db0"` | `"C#0"` | `"D0"` | `"Eb0"` | `"D#0"` | `"E0"` | `"F0"` | `"Gb0"` | `"F#0"` | `"G0"` | `"Ab0"` | `"G#0"` | `"A0"` | `"Bb0"` | `"A#0"` | `"B0"` | `"C1"` | `"Db1"` | `"C#1"` | `"D1"` | `"Eb1"` | `"D#1"` | `"E1"` | `"F1"` | `"Gb1"` | `"F#1"` | `"G1"` | `"Ab1"` | `"G#1"` | `"A1"` | `"Bb1"` | `"A#1"` | `"B1"` | `"C2"` | `"Db2"` | `"C#2"` | `"D2"` | `"Eb2"` | `"D#2"` | `"E2"` | `"F2"` | `"Gb2"` | `"F#2"` | `"G2"` | `"Ab2"` | `"G#2"` | `"A2"` | `"Bb2"` | `"A#2"` | `"B2"` | `"C3"` | `"Db3"` | `"C#3"` | `"D3"` | `"Eb3"` | `"D#3"` | `"E3"` | `"F3"` | `"Gb3"` | `"F#3"` | `"G3"` | `"Ab3"` | `"G#3"` | `"A3"` | `"Bb3"` | `"A#3"` | `"B3"` | `"C4"` | `"Db4"` | `"C#4"` | `"D4"` | `"Eb4"` | `"D#4"` | `"E4"` | `"F4"` | `"Gb4"` | `"F#4"` | `"G4"` | `"Ab4"` | `"G#4"` | `"A4"` | `"Bb4"` | `"A#4"` | `"B4"` | `"C5"` | `"Db5"` | `"C#5"` | `"D5"` | `"Eb5"` | `"D#5"` | `"E5"` | `"F5"` | `"Gb5"` | `"F#5"` | `"G5"` | `"Ab5"` | `"G#5"` | `"A5"` | `"Bb5"` | `"A#5"` | `"B5"` | `"C6"` | `"Db6"` | `"C#6"` | `"D6"` | `"Eb6"` | `"D#6"` | `"E6"` | `"F6"` | `"Gb6"` | `"F#6"` | `"G6"` | `"Ab6"` | `"G#6"` | `"A6"` | `"Bb6"` | `"A#6"` | `"B6"` | `"C7"` | `"Db7"` | `"C#7"` | `"D7"` | `"Eb7"` | `"D#7"` | `"E7"` | `"F7"` | `"Gb7"` | `"F#7"` | `"G7"` | `"Ab7"` | `"G#7"` | `"A7"` | `"Bb7"` | `"A#7"` | `"B7"` | `"C8"` | `"Db8"` | `"C#8"` | `"D8"` | `"Eb8"` | `"D#8"` #### Returns `void` #### Throws Error if note identifier not found in font #### Example ```typescript // Play a chord font.play('C4') font.play('E4') font.play('G4') ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/GainEffect.md' --- [EZ Web Audio](../index.md) / GainEffect # Class: GainEffect Defined in: [packages/core/src/effects/gain-effect.ts:22](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L22) GainEffect - A thin wrapper around GainNode that implements the Effect interface. For a single-node effect like GainEffect: * `input` and `output` both point to the same GainNode * `bypass` sets gain to 1.0 (passthrough), stores/restores the previous value * `mix` controls how much of the effect is applied (0=passthrough, 1=full effect) * `value` is the gain amount applied when not bypassed ## Example ```typescript const gain = createGainEffect(audioContext, 0.5) gain.value = 0.8 // Set gain to 80% gain.bypass = true // Passthrough (gain becomes 1.0) gain.bypass = false // Restore to 0.8 ``` ## Implements * [`Effect`](../interfaces/Effect.md) ## Constructors ### Constructor > **new GainEffect**(`audioContext`, `initialValue`): `GainEffect` Defined in: [packages/core/src/effects/gain-effect.ts:30](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L30) #### Parameters ##### audioContext `AudioContext` ##### initialValue `number` = `1.0` #### Returns `GainEffect` ## Accessors ### bypass #### Get Signature > **get** **bypass**(): `boolean` Defined in: [packages/core/src/effects/gain-effect.ts:63](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L63) When true, gain becomes 1.0 (passthrough). When false, restores the previous gain value. ##### Returns `boolean` #### Set Signature > **set** **bypass**(`v`): `void` Defined in: [packages/core/src/effects/gain-effect.ts:67](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L67) When true, effect is bypassed (passthrough) ##### Parameters ###### v `boolean` ##### Returns `void` When true, effect is bypassed (passthrough) #### Implementation of [`Effect`](../interfaces/Effect.md).[`bypass`](../interfaces/Effect.md#bypass) *** ### input #### Get Signature > **get** **input**(): `AudioNode` Defined in: [packages/core/src/effects/gain-effect.ts:38](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L38) The input AudioNode (same as output for single-node effect) ##### Returns `AudioNode` The input AudioNode that receives signal from the chain #### Implementation of [`Effect`](../interfaces/Effect.md).[`input`](../interfaces/Effect.md#input) *** ### mix #### Get Signature > **get** **mix**(): `number` Defined in: [packages/core/src/effects/gain-effect.ts:83](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L83) Wet/dry mix: 0 = passthrough (gain of 1.0), 1 = full effect. Mix interpolates between 1.0 and the set value. ##### Returns `number` #### Set Signature > **set** **mix**(`v`): `void` Defined in: [packages/core/src/effects/gain-effect.ts:87](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L87) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) ##### Parameters ###### v `number` ##### Returns `void` Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) #### Implementation of [`Effect`](../interfaces/Effect.md).[`mix`](../interfaces/Effect.md#mix) *** ### output #### Get Signature > **get** **output**(): `AudioNode` Defined in: [packages/core/src/effects/gain-effect.ts:43](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L43) The output AudioNode (same as input for single-node effect) ##### Returns `AudioNode` The output AudioNode that sends signal to the next in chain #### Implementation of [`Effect`](../interfaces/Effect.md).[`output`](../interfaces/Effect.md#output) *** ### value #### Get Signature > **get** **value**(): `number` Defined in: [packages/core/src/effects/gain-effect.ts:48](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L48) The gain value (0.0 to any positive number) ##### Returns `number` #### Set Signature > **set** **value**(`v`): `void` Defined in: [packages/core/src/effects/gain-effect.ts:52](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L52) ##### Parameters ###### v `number` ##### Returns `void` ## Methods ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/effects/gain-effect.ts:111](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L111) Disconnect the internal GainNode. Idempotent — safe to call multiple times. #### Returns `void` #### Implementation of [`Effect`](../interfaces/Effect.md).[`dispose`](../interfaces/Effect.md#dispose) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/GrainPlayer.md' --- [EZ Web Audio](../index.md) / GrainPlayer # Class: GrainPlayer Defined in: [packages/core/src/grain-player.ts:74](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L74) Granular synthesis player that generates continuous texture/pad sounds from an audio buffer. GrainPlayer works by scheduling many overlapping short "grains" of audio from a source buffer. Each grain gets a triangular window envelope (linear ramp up -> linear ramp down) to prevent clicks. Grains are scheduled slightly ahead of real time using a WorkerTimer for glitch-free playback even in background tabs. Provides independent control over: * **Position** (0-1): Which region of the buffer to sample grains from * **Pitch** (semitones): Pitch shift via playbackRate on each grain's BufferSourceNode * **Grain parameters**: grainSize, overlap, jitter — adjustable in real-time Note: Pitch shifting is implemented via playbackRate, which changes both pitch AND speed of each grain. The overlap system compensates for the changed grain duration, but extreme values (beyond +/-24 semitones) may affect texture quality. ## Example ```typescript import { createGrainPlayer, createSound } from 'ez-web-audio' const sound = await createSound('pad.mp3') const grains = await createGrainPlayer(sound.audioBuffer, { grainSize: 0.1, overlap: 0.05, jitter: 0.1 }) grains.play() grains.position = 0.5 // scrub to middle of buffer grains.pitch = 7 // pitch up a fifth ``` ## Extends * [`TypedEventEmitter`](TypedEventEmitter.md)<[`GrainPlayerEventMap`](../interfaces/GrainPlayerEventMap.md)> ## Constructors ### Constructor > **new GrainPlayer**(`audioContext`, `buffer`, `options?`): `GrainPlayer` Defined in: [packages/core/src/grain-player.ts:110](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L110) #### Parameters ##### audioContext `AudioContext` ##### buffer `AudioBuffer` ##### options? [`GrainPlayerOptions`](../interfaces/GrainPlayerOptions.md) #### Returns `GrainPlayer` #### Overrides [`TypedEventEmitter`](TypedEventEmitter.md).[`constructor`](TypedEventEmitter.md#constructor) ## Properties ### audioContext > `readonly` **audioContext**: `AudioContext` Defined in: [packages/core/src/grain-player.ts:111](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L111) ## Accessors ### activeGrainCount #### Get Signature > **get** **activeGrainCount**(): `number` Defined in: [packages/core/src/grain-player.ts:404](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L404) Number of currently active (playing) grains. ##### Returns `number` *** ### disposed #### Get Signature > **get** **disposed**(): `boolean` Defined in: [packages/core/src/grain-player.ts:401](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L401) Whether this GrainPlayer has been disposed. ##### Returns `boolean` *** ### grainSize #### Get Signature > **get** **grainSize**(): `number` Defined in: [packages/core/src/grain-player.ts:453](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L453) Duration of each grain in seconds. Minimum 0.01s. Changes take effect on the next grain. Note: Shrinking grainSize will re-clamp overlap to maintain valid hop size. ##### Returns `number` #### Set Signature > **set** **grainSize**(`value`): `void` Defined in: [packages/core/src/grain-player.ts:454](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L454) ##### Parameters ###### value `number` ##### Returns `void` *** ### jitter #### Get Signature > **get** **jitter**(): `number` Defined in: [packages/core/src/grain-player.ts:474](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L474) Random scatter around the position for organic texture, 0-1. 0 = no scatter, 1 = scatter across entire buffer. ##### Returns `number` #### Set Signature > **set** **jitter**(`value`): `void` Defined in: [packages/core/src/grain-player.ts:475](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L475) ##### Parameters ###### value `number` ##### Returns `void` *** ### loop #### Get Signature > **get** **loop**(): `boolean` Defined in: [packages/core/src/grain-player.ts:480](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L480) Whether to loop when reaching the buffer end. ##### Returns `boolean` #### Set Signature > **set** **loop**(`value`): `void` Defined in: [packages/core/src/grain-player.ts:481](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L481) ##### Parameters ###### value `boolean` ##### Returns `void` *** ### overlap #### Get Signature > **get** **overlap**(): `number` Defined in: [packages/core/src/grain-player.ts:465](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L465) Overlap between consecutive grains in seconds. Clamped to \[0, grainSize - 0.001] to ensure hop size never drops below 0.001s. Changes take effect on the next grain. ##### Returns `number` #### Set Signature > **set** **overlap**(`value`): `void` Defined in: [packages/core/src/grain-player.ts:466](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L466) ##### Parameters ###### value `number` ##### Returns `void` *** ### paused #### Get Signature > **get** **paused**(): `boolean` Defined in: [packages/core/src/grain-player.ts:398](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L398) Whether the grain player is paused. ##### Returns `boolean` *** ### pitch #### Get Signature > **get** **pitch**(): `number` Defined in: [packages/core/src/grain-player.ts:431](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L431) Pitch shift in semitones. 0 = original pitch. Internally converts to playbackRate via `2^(semitones/12)`. Note: This is playbackRate-based pitch shift. It changes grain duration, which the overlap system compensates for, but extreme values will affect texture quality. ##### Example ```typescript grainPlayer.pitch = 7 // up a fifth grainPlayer.pitch = 12 // up an octave grainPlayer.pitch = -12 // down an octave ``` ##### Returns `number` #### Set Signature > **set** **pitch**(`semitones`): `void` Defined in: [packages/core/src/grain-player.ts:432](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L432) ##### Parameters ###### semitones `number` ##### Returns `void` *** ### playbackRate #### Get Signature > **get** **playbackRate**(): `number` Defined in: [packages/core/src/grain-player.ts:441](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L441) Direct playback rate ratio. 1 = original speed, 2 = double speed (octave up). Setting this also updates the `pitch` property accordingly. ##### Returns `number` #### Set Signature > **set** **playbackRate**(`value`): `void` Defined in: [packages/core/src/grain-player.ts:442](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L442) ##### Parameters ###### value `number` ##### Returns `void` *** ### playing #### Get Signature > **get** **playing**(): `boolean` Defined in: [packages/core/src/grain-player.ts:395](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L395) Whether the grain player is currently playing. ##### Returns `boolean` *** ### position #### Get Signature > **get** **position**(): `number` Defined in: [packages/core/src/grain-player.ts:411](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L411) Playback position in the buffer, normalized 0-1. 0 = beginning of buffer, 1 = end of buffer. Changes take effect on the next grain. ##### Returns `number` #### Set Signature > **set** **position**(`value`): `void` Defined in: [packages/core/src/grain-player.ts:412](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L412) ##### Parameters ###### value `number` ##### Returns `void` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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`](TypedEventEmitter.md).[`_clearListeners`](TypedEventEmitter.md#clearlisteners) *** ### addEffect() > **addEffect**(`effect`, `position?`): `this` Defined in: [packages/core/src/grain-player.ts:669](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L669) Add an effect to the shared output bus. All grains are affected. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` ##### 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) *** ### changeGainTo() > **changeGainTo**(`value`): `this` Defined in: [packages/core/src/grain-player.ts:644](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L644) Set the master gain for all grains. #### Parameters ##### value `number` Gain from 0 (silent) to 1 (full volume) #### Returns `this` *** ### changePanTo() > **changePanTo**(`value`): `this` Defined in: [packages/core/src/grain-player.ts:654](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L654) Set the master pan for all grains. #### Parameters ##### value `number` Pan from -1 (left) to 1 (right) #### Returns `this` *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/grain-player.ts:741](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L741) Dispose this GrainPlayer, releasing all audio resources. Stops playback, 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail [`GrainPlayerEventMap`](../interfaces/GrainPlayerEventMap.md)\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`TypedEventEmitter`](TypedEventEmitter.md).[`emit`](TypedEventEmitter.md#emit) *** ### getAnalyzer() > **getAnalyzer**(): [`Analyzer`](Analyzer.md) | `null` Defined in: [packages/core/src/grain-player.ts:717](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L717) Get the currently attached analyzer. #### Returns [`Analyzer`](Analyzer.md) | `null` *** ### getEffects() > **getEffects**(): readonly [`Effect`](../interfaces/Effect.md)\[] Defined in: [packages/core/src/grain-player.ts:698](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L698) Get a readonly copy of the current effects array. #### Returns readonly [`Effect`](../interfaces/Effect.md)\[] *** ### getGainNode() > **getGainNode**(): `GainNode` Defined in: [packages/core/src/grain-player.ts:488](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L488) Returns the master GainNode (for LFO targeting and external routing). #### Returns `GainNode` *** ### getPannerNode() > **getPannerNode**(): `StereoPannerNode` Defined in: [packages/core/src/grain-player.ts:491](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L491) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` #### 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`](TypedEventEmitter.md).[`off`](TypedEventEmitter.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` #### 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`](TypedEventEmitter.md).[`on`](TypedEventEmitter.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` #### 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`](TypedEventEmitter.md).[`once`](TypedEventEmitter.md#once) *** ### onPlayRamp() > **onPlayRamp**(`type`, `rampType?`): `object` Defined in: [packages/core/src/grain-player.ts:581](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L581) Schedule a master gain/pan ramp when play() is called. Same fluent shape as `BaseSound.onPlayRamp()` (R1#6). Consume-once: the ramp is applied and cleared by the next play() call. #### Parameters ##### type 'gain' or 'pan' `"gain"` | `"pan"` ##### rampType? `RampType` 'linear' or 'exponential' (default: 'exponential') #### Returns `object` Fluent builder for setting start value, end value, and duration ##### from() > **from**: (`startValue`) => `object` ###### Parameters ###### startValue `number` ###### Returns `object` ###### to() > **to**: (`endValue`) => `object` ###### Parameters ###### endValue `number` ###### Returns `object` ###### in() > **in**: (`endTime`) => `void` ###### Parameters ###### endTime `number` ###### Returns `void` #### Example ```typescript grainPlayer.onPlayRamp('gain', 'linear').from(0).to(0.8).in(2) grainPlayer.play() ``` *** ### onPlaySet() > **onPlaySet**(`type`): `object` Defined in: [packages/core/src/grain-player.ts:540](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L540) Schedule a master gain/pan value to be set when play() is called. Same fluent shape as `BaseSound.onPlaySet()` (R1#6) — use `.at(time)` for an immediate `setValueAtTime`, or `.endingAt(time, rampType)` to ramp to the value. Consume-once: the schedule is applied and cleared by the next play() call. #### Parameters ##### type 'gain' or 'pan' `"gain"` | `"pan"` #### Returns `object` Fluent builder for setting value and timing ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### at() > **at**: (`time`) => `void` ###### Parameters ###### time `number` ###### Returns `void` ###### endingAt() > **endingAt**: (`time`, `rampType?`) => `void` ###### Parameters ###### time `number` ###### rampType? `RampType` ###### Returns `void` #### Example ```typescript // Fade the texture in over 2 seconds grainPlayer.onPlaySet('gain').to(0).at(0) grainPlayer.onPlaySet('gain').to(0.8).endingAt(2, 'linear') grainPlayer.play() ``` *** ### pause() > **pause**(): `void` Defined in: [packages/core/src/grain-player.ts:355](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L355) Pause grain playback. Active grains will finish naturally. Resume with [resume](#resume). #### Returns `void` #### Example ```typescript grainPlayer.pause() // later... grainPlayer.resume() ``` *** ### play() > **play**(): `void` Defined in: [packages/core/src/grain-player.ts:288](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L288) Start grain playback. If already playing, this is a no-op. #### Returns `void` #### Example ```typescript grainPlayer.play() ``` *** ### removeEffect() > **removeEffect**(`effect`): `this` Defined in: [packages/core/src/grain-player.ts:686](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L686) Remove an effect from the shared output bus. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` ##### 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) *** ### resume() > **resume**(): `void` Defined in: [packages/core/src/grain-player.ts:377](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L377) Resume grain playback from where it was paused. #### Returns `void` #### Example ```typescript grainPlayer.resume() ``` *** ### setAnalyzer() > **setAnalyzer**(`analyzer`): `this` Defined in: [packages/core/src/grain-player.ts:708](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L708) Attach an analyzer to the shared bus output for visualization. #### Parameters ##### analyzer The Analyzer instance, or null to detach [`Analyzer`](Analyzer.md) | `null` #### Returns `this` this for chaining *** ### setDestination() > **setDestination**(`node`): `this` Defined in: [packages/core/src/grain-player.ts:727](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L727) Set a custom destination for audio output. #### Parameters ##### node `AudioNode` The AudioNode to route output to #### Returns `this` this for chaining *** ### stop() > **stop**(): `void` Defined in: [packages/core/src/grain-player.ts:329](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L329) Stop grain playback. Active grains will decay naturally (they're very short). #### Returns `void` #### Example ```typescript grainPlayer.stop() ``` *** ### update() > **update**(`type`): `object` Defined in: [packages/core/src/grain-player.ts:506](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L506) Update a master bus parameter immediately. #### 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`](../type-aliases/RatioType.md) ###### Returns `void` #### Example ```typescript grainPlayer.update('gain').to(0.5).as('ratio') ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/InvalidNoteError.md' --- [EZ Web Audio](../index.md) / InvalidNoteError # Class: InvalidNoteError Defined in: [packages/core/src/errors/invalid-note-error.ts:26](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/invalid-note-error.ts#L26) Error thrown when a note identifier is invalid. Note identifiers follow the format: Letter + optional accidental + octave * Letters: A-G (case insensitive) * Accidentals: # (sharp), b (flat), or none (natural) * Octave: 0-8 Valid examples: A4, Bb3, C#5, D2, Eb6 Invalid examples: H4, A9, B##3, 4A ## Example ```typescript function parseNote(identifier: string) { if (!isValidNote(identifier)) { throw new InvalidNoteError( `Invalid note: "${identifier}". Expected format: Letter + optional accidental + octave (e.g., A4, Bb3, C#5).`, identifier ); } } ``` ## Extends * [`AudioError`](AudioError.md) ## Constructors ### Constructor > **new InvalidNoteError**(`message`, `identifier`): `InvalidNoteError` Defined in: [packages/core/src/errors/invalid-note-error.ts:33](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/invalid-note-error.ts#L33) Create a new InvalidNoteError. #### Parameters ##### message `string` Human-readable error description with actionable fix ##### identifier `string` The invalid note identifier that was provided #### Returns `InvalidNoteError` #### Overrides [`AudioError`](AudioError.md).[`constructor`](AudioError.md#constructor) ## Properties ### code? > `readonly` `optional` **code**: `string` Defined in: [packages/core/src/errors/audio-error.ts:34](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/audio-error.ts#L34) Optional error code for programmatic handling #### Inherited from [`AudioError`](AudioError.md).[`code`](AudioError.md#code) *** ### identifier > `readonly` **identifier**: `string` Defined in: [packages/core/src/errors/invalid-note-error.ts:35](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/invalid-note-error.ts#L35) The invalid note identifier that was provided --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/LayeredSound.md' --- [EZ Web Audio](../index.md) / LayeredSound # Class: LayeredSound Defined in: [packages/core/src/layered-sound.ts:45](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L45) 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 * [`TypedEventEmitter`](TypedEventEmitter.md)<[`LayeredSoundEventMap`](../interfaces/LayeredSoundEventMap.md)> ## Constructors ### Constructor > **new LayeredSound**(`audioContext`, `layers`, `opts?`): `LayeredSound` Defined in: [packages/core/src/layered-sound.ts:57](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L57) #### Parameters ##### audioContext `AudioContext` ##### layers ([`Oscillator`](Oscillator.md) | [`Sound`](Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)> | `null` | `undefined`)\[] ##### opts? [`LayeredSoundOptions`](../interfaces/LayeredSoundOptions.md) #### Returns `LayeredSound` #### Overrides [`TypedEventEmitter`](TypedEventEmitter.md).[`constructor`](TypedEventEmitter.md#constructor) ## Properties ### name > **name**: `string` Defined in: [packages/core/src/layered-sound.ts:55](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L55) ## Accessors ### disposed #### Get Signature > **get** **disposed**(): `boolean` Defined in: [packages/core/src/layered-sound.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L108) Whether this LayeredSound has been disposed. ##### Returns `boolean` *** ### layerCount #### Get Signature > **get** **layerCount**(): `number` Defined in: [packages/core/src/layered-sound.ts:125](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L125) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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`](TypedEventEmitter.md).[`_clearListeners`](TypedEventEmitter.md#clearlisteners) *** ### addEffect() > **addEffect**(`effect`, `position?`): `this` Defined in: [packages/core/src/layered-sound.ts:279](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L279) Add an effect to the shared output bus. All layers route through this bus, so the effect applies to all layers. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) *** ### changeGainTo() > **changeGainTo**(`value`): `this` Defined in: [packages/core/src/layered-sound.ts:224](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L224) Set the gain for all layers via the shared output bus. Validated identically to BaseSound.changeGainTo: throws a [ValidationError](ValidationError.md) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L252) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L332) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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`](../interfaces/LayeredSoundEventMap.md)\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`TypedEventEmitter`](TypedEventEmitter.md).[`emit`](TypedEventEmitter.md#emit) *** ### getEffects() > **getEffects**(): readonly [`Effect`](../interfaces/Effect.md)\[] Defined in: [packages/core/src/layered-sound.ts:314](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L314) Get a readonly copy of the effects array. #### Returns readonly [`Effect`](../interfaces/Effect.md)\[] A copy of the effects array *** ### getLayer() > **getLayer**(`index`): [`Oscillator`](Oscillator.md) | [`Sound`](Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)> | `undefined` Defined in: [packages/core/src/layered-sound.ts:118](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L118) Get a layer by index for individual control. #### Parameters ##### index `number` The layer index (0-based) #### Returns [`Oscillator`](Oscillator.md) | [`Sound`](Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)> | `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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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`](TypedEventEmitter.md).[`off`](TypedEventEmitter.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) 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`](TypedEventEmitter.md).[`on`](TypedEventEmitter.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) 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`](TypedEventEmitter.md).[`once`](TypedEventEmitter.md#once) *** ### play() > **play**(): `Promise`<`void`> Defined in: [packages/core/src/layered-sound.ts:133](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L133) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L191) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L298) Remove an effect from the shared output bus. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) *** ### ~~setGain()~~ > **setGain**(`value`): `void` Defined in: [packages/core/src/layered-sound.ts:239](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L239) #### Parameters ##### value `number` The gain value (0-1 typical range) #### Returns `void` #### Deprecated Use [changeGainTo](#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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L267) #### Parameters ##### value `number` The pan value (-1 to 1, where -1 is full left, 1 is full right) #### Returns `void` #### Deprecated Use [changePanTo](#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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L202) Stop all layers. #### Returns `Promise`<`void`> --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/LFO.md' --- [EZ Web Audio](../index.md) / LFO # Class: LFO Defined in: [packages/core/src/lfo.ts:115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L115) Low Frequency Oscillator (LFO) for modulating audio parameters. An LFO produces a slow oscillation that can be connected to any audio parameter (gain, pan, frequency, filter cutoff, etc.) to create effects like tremolo, vibrato, auto-pan, and auto-filter. ## Example ```typescript import { createLFO, createOscillator } from 'ez-web-audio' // Tremolo const synth = await createOscillator({ frequency: 440 }) const tremolo = createLFO({ frequency: 5, depth: 0.3, type: 'sine' }) tremolo.connect(synth, 'gain').start() synth.play() // Vibrato const vibrato = createLFO({ frequency: 6, depth: 50 }) vibrato.connect(synth, 'frequency').start() ``` ## Constructors ### Constructor > **new LFO**(`options?`): `LFO` Defined in: [packages/core/src/lfo.ts:126](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L126) #### Parameters ##### options? [`LFOOptions`](../interfaces/LFOOptions.md) #### Returns `LFO` ## Accessors ### depth #### Get Signature > **get** **depth**(): `number` Defined in: [packages/core/src/lfo.ts:161](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L161) Current modulation depth ##### Returns `number` #### Set Signature > **set** **depth**(`value`): `void` Defined in: [packages/core/src/lfo.ts:165](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L165) ##### Parameters ###### value `number` ##### Returns `void` *** ### frequency #### Get Signature > **get** **frequency**(): `number` Defined in: [packages/core/src/lfo.ts:135](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L135) Current oscillation frequency in Hz ##### Returns `number` #### Set Signature > **set** **frequency**(`value`): `void` Defined in: [packages/core/src/lfo.ts:139](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L139) ##### Parameters ###### value `number` ##### Returns `void` *** ### isRunning #### Get Signature > **get** **isRunning**(): `boolean` Defined in: [packages/core/src/lfo.ts:201](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L201) Whether the LFO oscillator is currently running ##### Returns `boolean` *** ### type #### Get Signature > **get** **type**(): [`LFOWaveform`](../type-aliases/LFOWaveform.md) | `PeriodicWave` Defined in: [packages/core/src/lfo.ts:174](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L174) Current waveform type ##### Returns [`LFOWaveform`](../type-aliases/LFOWaveform.md) | `PeriodicWave` #### Set Signature > **set** **type**(`value`): `void` Defined in: [packages/core/src/lfo.ts:178](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L178) ##### Parameters ###### value [`LFOWaveform`](../type-aliases/LFOWaveform.md) | `PeriodicWave` ##### Returns `void` ## Methods ### connect() > **connect**(`target`, `paramName`, `options?`): `this` Defined in: [packages/core/src/lfo.ts:215](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L215) Connect the LFO to a target's audio parameter. #### Parameters ##### target `LFOTarget` BaseSound or BaseEffect instance to modulate ##### paramName `string` Parameter name: 'gain', 'pan', 'frequency', 'detune', or effect-specific ##### options? [`LFOConnectOptions`](../interfaces/LFOConnectOptions.md) Connection options (syncLifecycle, retrigger, depthUnit, depth) #### Returns `this` this for chaining *** ### disconnect() > **disconnect**(`target?`, `paramName?`): `void` Defined in: [packages/core/src/lfo.ts:346](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L346) Disconnect from target(s). #### Parameters ##### target? `LFOTarget` If provided, disconnect all connections to this target ##### paramName? `string` If provided with target, disconnect only the specific param #### Returns `void` *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/lfo.ts:447](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L447) Dispose the LFO, releasing all resources. Stops the oscillator, disconnects all connections, and restores patched dispose methods. Idempotent — safe to call multiple times. #### Returns `void` *** ### rampDepth() > **rampDepth**(`value`, `duration`): `void` Defined in: [packages/core/src/lfo.ts:519](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L519) Smoothly ramp the modulation depth. #### Parameters ##### value `number` Target depth ##### duration `number` Ramp duration in seconds #### Returns `void` *** ### rampFrequency() > **rampFrequency**(`value`, `duration`): `void` Defined in: [packages/core/src/lfo.ts:501](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L501) Smoothly ramp the oscillation frequency. #### Parameters ##### value `number` Target frequency in Hz ##### duration `number` Ramp duration in seconds #### Returns `void` *** ### start() > **start**(): `this` Defined in: [packages/core/src/lfo.ts:376](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L376) Start the LFO oscillator. #### Returns `this` this for chaining #### Throws If no AudioContext available (call connect() first) *** ### stop() > **stop**(): `this` Defined in: [packages/core/src/lfo.ts:419](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L419) Stop the LFO oscillator. Can be restarted with start(). #### Returns `this` this for chaining *** ### syncToBPM() > **syncToBPM**(`bpm`, `noteLength`): `this` Defined in: [packages/core/src/lfo.ts:474](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L474) Set LFO frequency to match a musical note length at a given BPM. #### Parameters ##### bpm `number` Beats per minute ##### noteLength `string` Note length string (e.g., '1/4', '1/8', '1/16') #### Returns `this` this for chaining --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Note.md' --- [EZ Web Audio](../index.md) / Note # Class: Note Defined in: [packages/core/src/note.ts:30](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/note.ts#L30) A musical note without audio data. Note represents musical identity (letter, accidental, octave, frequency) without any audio capabilities. Use SampledNote for notes with audio. Note is useful for UI components that display note information. ## Example ```typescript import { Note } from 'ez-web-audio' const note = new Note({ letter: 'A', octave: '4' }) console.log(note.frequency) // 440 console.log(note.identifier) // "A4" // Or create from frequency const noteFromFreq = new Note({ frequency: 440 }) console.log(noteFromFreq.identifier) // "A4" // Or create from identifier const noteFromId = new Note({ identifier: 'Bb3' }) console.log(noteFromId.letter) // "B" console.log(noteFromId.accidental) // "b" console.log(noteFromId.octave) // "3" ``` ## Extends * `MusicalIdentity`<*typeof* `__class`, `this`> & `(Anonymous class)`<`this`> ## Implements * `IMusicallyAware` ## Indexable \[`key`: `string`]: `any` ## Constructors ### Constructor > **new Note**(`opts?`): `Note` Defined in: [packages/core/src/note.ts:31](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/note.ts#L31) #### Parameters ##### opts? ###### accidental? `Accidental` ###### frequency? `number` ###### identifier? `"C0"` | `"Db0"` | `"C#0"` | `"D0"` | `"Eb0"` | `"D#0"` | `"E0"` | `"F0"` | `"Gb0"` | `"F#0"` | `"G0"` | `"Ab0"` | `"G#0"` | `"A0"` | `"Bb0"` | `"A#0"` | `"B0"` | `"C1"` | `"Db1"` | `"C#1"` | `"D1"` | `"Eb1"` | `"D#1"` | `"E1"` | `"F1"` | `"Gb1"` | `"F#1"` | `"G1"` | `"Ab1"` | `"G#1"` | `"A1"` | `"Bb1"` | `"A#1"` | `"B1"` | `"C2"` | `"Db2"` | `"C#2"` | `"D2"` | `"Eb2"` | `"D#2"` | `"E2"` | `"F2"` | `"Gb2"` | `"F#2"` | `"G2"` | `"Ab2"` | `"G#2"` | `"A2"` | `"Bb2"` | `"A#2"` | `"B2"` | `"C3"` | `"Db3"` | `"C#3"` | `"D3"` | `"Eb3"` | `"D#3"` | `"E3"` | `"F3"` | `"Gb3"` | `"F#3"` | `"G3"` | `"Ab3"` | `"G#3"` | `"A3"` | `"Bb3"` | `"A#3"` | `"B3"` | `"C4"` | `"Db4"` | `"C#4"` | `"D4"` | `"Eb4"` | `"D#4"` | `"E4"` | `"F4"` | `"Gb4"` | `"F#4"` | `"G4"` | `"Ab4"` | `"G#4"` | `"A4"` | `"Bb4"` | `"A#4"` | `"B4"` | `"C5"` | `"Db5"` | `"C#5"` | `"D5"` | `"Eb5"` | `"D#5"` | `"E5"` | `"F5"` | `"Gb5"` | `"F#5"` | `"G5"` | `"Ab5"` | `"G#5"` | `"A5"` | `"Bb5"` | `"A#5"` | `"B5"` | `"C6"` | `"Db6"` | `"C#6"` | `"D6"` | `"Eb6"` | `"D#6"` | `"E6"` | `"F6"` | `"Gb6"` | `"F#6"` | `"G6"` | `"Ab6"` | `"G#6"` | `"A6"` | `"Bb6"` | `"A#6"` | `"B6"` | `"C7"` | `"Db7"` | `"C#7"` | `"D7"` | `"Eb7"` | `"D#7"` | `"E7"` | `"F7"` | `"Gb7"` | `"F#7"` | `"G7"` | `"Ab7"` | `"G#7"` | `"A7"` | `"Bb7"` | `"A#7"` | `"B7"` | `"C8"` | `"Db8"` | `"C#8"` | `"D8"` | `"Eb8"` | `"D#8"` ###### letter? `NoteLetter` ###### octave? `Octave` #### Returns `Note` #### Overrides `MusicallyAware(class {}).constructor` ## Properties ### accidental > **accidental**: `Accidental` = `''` Defined in: [packages/core/src/musical-identity.ts:110](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L110) The accidental: "" (natural), "b" (flat), or "#" (sharp). For note "Ab5", this would be "b". #### Implementation of `IMusicallyAware.accidental` #### Inherited from `MusicallyAware(class {}).accidental` *** ### letter > **letter**: `NoteLetter` = `'A'` Defined in: [packages/core/src/musical-identity.ts:104](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L104) The note letter (A-G). For note "Ab5", this would be "A". #### Implementation of `IMusicallyAware.letter` #### Inherited from `MusicallyAware(class {}).letter` *** ### octave > **octave**: `Octave` = `'0'` Defined in: [packages/core/src/musical-identity.ts:115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L115) The octave (0-8). For note "Ab5", this would be "5". #### Implementation of `IMusicallyAware.octave` #### Inherited from `MusicallyAware(class {}).octave` ## Accessors ### frequency #### Get Signature > **get** **frequency**(): `number` Defined in: [packages/core/src/musical-identity.ts:144](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L144) The frequency of the note in hertz. Computed from the note identifier using standard piano frequencies. Setting this value updates all other properties to match. ##### Example ```typescript note.frequency = 440 // Sets to A4 console.log(note.identifier) // "A4" ``` ##### Returns `number` #### Set Signature > **set** **frequency**(`value`): `void` Defined in: [packages/core/src/musical-identity.ts:159](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L159) Setting frequency resolves to the nearest tabled note within FREQUENCY\_MATCH\_TOLERANCE\_CENTS cents (a computed/synthesized frequency rarely lands on an exact table value). If nothing is close enough, a warning is logged and the identifier is left unchanged rather than silently going stale. ##### Parameters ###### value `number` ##### Returns `void` #### Implementation of `IMusicallyAware.frequency` #### Inherited from `MusicallyAware(class {}).frequency` *** ### identifier #### Get Signature > **get** **identifier**(): `"C0"` | `"Db0"` | `"C#0"` | `"D0"` | `"Eb0"` | `"D#0"` | `"E0"` | `"F0"` | `"Gb0"` | `"F#0"` | `"G0"` | `"Ab0"` | `"G#0"` | `"A0"` | `"Bb0"` | `"A#0"` | `"B0"` | `"C1"` | `"Db1"` | `"C#1"` | `"D1"` | `"Eb1"` | `"D#1"` | `"E1"` | `"F1"` | `"Gb1"` | `"F#1"` | `"G1"` | `"Ab1"` | `"G#1"` | `"A1"` | `"Bb1"` | `"A#1"` | `"B1"` | `"C2"` | `"Db2"` | `"C#2"` | `"D2"` | `"Eb2"` | `"D#2"` | `"E2"` | `"F2"` | `"Gb2"` | `"F#2"` | `"G2"` | `"Ab2"` | `"G#2"` | `"A2"` | `"Bb2"` | `"A#2"` | `"B2"` | `"C3"` | `"Db3"` | `"C#3"` | `"D3"` | `"Eb3"` | `"D#3"` | `"E3"` | `"F3"` | `"Gb3"` | `"F#3"` | `"G3"` | `"Ab3"` | `"G#3"` | `"A3"` | `"Bb3"` | `"A#3"` | `"B3"` | `"C4"` | `"Db4"` | `"C#4"` | `"D4"` | `"Eb4"` | `"D#4"` | `"E4"` | `"F4"` | `"Gb4"` | `"F#4"` | `"G4"` | `"Ab4"` | `"G#4"` | `"A4"` | `"Bb4"` | `"A#4"` | `"B4"` | `"C5"` | `"Db5"` | `"C#5"` | `"D5"` | `"Eb5"` | `"D#5"` | `"E5"` | `"F5"` | `"Gb5"` | `"F#5"` | `"G5"` | `"Ab5"` | `"G#5"` | `"A5"` | `"Bb5"` | `"A#5"` | `"B5"` | `"C6"` | `"Db6"` | `"C#6"` | `"D6"` | `"Eb6"` | `"D#6"` | `"E6"` | `"F6"` | `"Gb6"` | `"F#6"` | `"G6"` | `"Ab6"` | `"G#6"` | `"A6"` | `"Bb6"` | `"A#6"` | `"B6"` | `"C7"` | `"Db7"` | `"C#7"` | `"D7"` | `"Eb7"` | `"D#7"` | `"E7"` | `"F7"` | `"Gb7"` | `"F#7"` | `"G7"` | `"Ab7"` | `"G#7"` | `"A7"` | `"Bb7"` | `"A#7"` | `"B7"` | `"C8"` | `"Db8"` | `"C#8"` | `"D8"` | `"Eb8"` | `"D#8"` Defined in: [packages/core/src/musical-identity.ts:210](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L210) The full note identifier (e.g., "A4", "Bb3", "C#5"). Computed from letter, accidental, and octave. Setting this value updates all other properties to match. ##### Example ```typescript note.identifier = 'Bb3' console.log(note.letter) // "B" console.log(note.accidental) // "b" console.log(note.octave) // "3" console.log(note.frequency) // 233.08 ``` ##### Returns `"C0"` | `"Db0"` | `"C#0"` | `"D0"` | `"Eb0"` | `"D#0"` | `"E0"` | `"F0"` | `"Gb0"` | `"F#0"` | `"G0"` | `"Ab0"` | `"G#0"` | `"A0"` | `"Bb0"` | `"A#0"` | `"B0"` | `"C1"` | `"Db1"` | `"C#1"` | `"D1"` | `"Eb1"` | `"D#1"` | `"E1"` | `"F1"` | `"Gb1"` | `"F#1"` | `"G1"` | `"Ab1"` | `"G#1"` | `"A1"` | `"Bb1"` | `"A#1"` | `"B1"` | `"C2"` | `"Db2"` | `"C#2"` | `"D2"` | `"Eb2"` | `"D#2"` | `"E2"` | `"F2"` | `"Gb2"` | `"F#2"` | `"G2"` | `"Ab2"` | `"G#2"` | `"A2"` | `"Bb2"` | `"A#2"` | `"B2"` | `"C3"` | `"Db3"` | `"C#3"` | `"D3"` | `"Eb3"` | `"D#3"` | `"E3"` | `"F3"` | `"Gb3"` | `"F#3"` | `"G3"` | `"Ab3"` | `"G#3"` | `"A3"` | `"Bb3"` | `"A#3"` | `"B3"` | `"C4"` | `"Db4"` | `"C#4"` | `"D4"` | `"Eb4"` | `"D#4"` | `"E4"` | `"F4"` | `"Gb4"` | `"F#4"` | `"G4"` | `"Ab4"` | `"G#4"` | `"A4"` | `"Bb4"` | `"A#4"` | `"B4"` | `"C5"` | `"Db5"` | `"C#5"` | `"D5"` | `"Eb5"` | `"D#5"` | `"E5"` | `"F5"` | `"Gb5"` | `"F#5"` | `"G5"` | `"Ab5"` | `"G#5"` | `"A5"` | `"Bb5"` | `"A#5"` | `"B5"` | `"C6"` | `"Db6"` | `"C#6"` | `"D6"` | `"Eb6"` | `"D#6"` | `"E6"` | `"F6"` | `"Gb6"` | `"F#6"` | `"G6"` | `"Ab6"` | `"G#6"` | `"A6"` | `"Bb6"` | `"A#6"` | `"B6"` | `"C7"` | `"Db7"` | `"C#7"` | `"D7"` | `"Eb7"` | `"D#7"` | `"E7"` | `"F7"` | `"Gb7"` | `"F#7"` | `"G7"` | `"Ab7"` | `"G#7"` | `"A7"` | `"Bb7"` | `"A#7"` | `"B7"` | `"C8"` | `"Db8"` | `"C#8"` | `"D8"` | `"Eb8"` | `"D#8"` #### Set Signature > **set** **identifier**(`value`): `void` Defined in: [packages/core/src/musical-identity.ts:232](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L232) ##### Parameters ###### value `"C0"` | `"Db0"` | `"C#0"` | `"D0"` | `"Eb0"` | `"D#0"` | `"E0"` | `"F0"` | `"Gb0"` | `"F#0"` | `"G0"` | `"Ab0"` | `"G#0"` | `"A0"` | `"Bb0"` | `"A#0"` | `"B0"` | `"C1"` | `"Db1"` | `"C#1"` | `"D1"` | `"Eb1"` | `"D#1"` | `"E1"` | `"F1"` | `"Gb1"` | `"F#1"` | `"G1"` | `"Ab1"` | `"G#1"` | `"A1"` | `"Bb1"` | `"A#1"` | `"B1"` | `"C2"` | `"Db2"` | `"C#2"` | `"D2"` | `"Eb2"` | `"D#2"` | `"E2"` | `"F2"` | `"Gb2"` | `"F#2"` | `"G2"` | `"Ab2"` | `"G#2"` | `"A2"` | `"Bb2"` | `"A#2"` | `"B2"` | `"C3"` | `"Db3"` | `"C#3"` | `"D3"` | `"Eb3"` | `"D#3"` | `"E3"` | `"F3"` | `"Gb3"` | `"F#3"` | `"G3"` | `"Ab3"` | `"G#3"` | `"A3"` | `"Bb3"` | `"A#3"` | `"B3"` | `"C4"` | `"Db4"` | `"C#4"` | `"D4"` | `"Eb4"` | `"D#4"` | `"E4"` | `"F4"` | `"Gb4"` | `"F#4"` | `"G4"` | `"Ab4"` | `"G#4"` | `"A4"` | `"Bb4"` | `"A#4"` | `"B4"` | `"C5"` | `"Db5"` | `"C#5"` | `"D5"` | `"Eb5"` | `"D#5"` | `"E5"` | `"F5"` | `"Gb5"` | `"F#5"` | `"G5"` | `"Ab5"` | `"G#5"` | `"A5"` | `"Bb5"` | `"A#5"` | `"B5"` | `"C6"` | `"Db6"` | `"C#6"` | `"D6"` | `"Eb6"` | `"D#6"` | `"E6"` | `"F6"` | `"Gb6"` | `"F#6"` | `"G6"` | `"Ab6"` | `"G#6"` | `"A6"` | `"Bb6"` | `"A#6"` | `"B6"` | `"C7"` | `"Db7"` | `"C#7"` | `"D7"` | `"Eb7"` | `"D#7"` | `"E7"` | `"F7"` | `"Gb7"` | `"F#7"` | `"G7"` | `"Ab7"` | `"G#7"` | `"A7"` | `"Bb7"` | `"A#7"` | `"B7"` | `"C8"` | `"Db8"` | `"C#8"` | `"D8"` | `"Eb8"` | `"D#8"` ##### Returns `void` #### Implementation of `IMusicallyAware.identifier` #### Inherited from `MusicallyAware(class {}).identifier` *** ### name #### Get Signature > **get** **name**(): `string` Defined in: [packages/core/src/musical-identity.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L121) The note name without octave (e.g., "A" or "Ab"). Computed from letter and accidental. ##### Returns `string` #### Implementation of `IMusicallyAware.name` #### Inherited from `MusicallyAware(class {}).name` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Oscillator.md' --- [EZ Web Audio](../index.md) / Oscillator # Class: Oscillator Defined in: [packages/core/src/oscillator.ts:137](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L137) Synthesizer that generates audio from oscillator waveforms. Oscillator creates sound from scratch using sine, square, sawtooth, or triangle waves. Supports ADSR envelopes for professional-quality synthesis, filters for tone shaping, and all the gain/pan controls from BaseSound. Unlike [Sound](Sound.md) which plays pre-recorded audio, Oscillator generates audio in real-time. Oscillators have infinite duration and must be explicitly stopped. ## Example ```typescript import { createOscillator } from 'ez-web-audio' // Simple sine wave at 440Hz (A4) const synth = await createOscillator({ frequency: 440, type: 'sine' }) synth.play() setTimeout(() => synth.stop(), 500) // With ADSR envelope for piano-like decay const piano = await createOscillator({ frequency: 440, type: 'triangle', envelope: { attack: 0.01, decay: 0.1, sustain: 0.7, release: 0.3 } }) piano.play() setTimeout(() => piano.stop(), 500) // Release phase plays after stop // With lowpass filter const muted = await createOscillator({ frequency: 440, type: 'sawtooth', lowpass: { frequency: 800, q: 1 } }) muted.play() ``` ## Extends * `BaseSound` ## Constructors ### Constructor > **new Oscillator**(`audioContext`, `options?`): `Oscillator` Defined in: [packages/core/src/oscillator.ts:184](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L184) Create an Oscillator instance. Note: Use [createOscillator](../functions/createOscillator.md) factory function instead of calling this directly. #### Parameters ##### audioContext `AudioContext` The AudioContext to use for audio operations ##### options? [`OscillatorOptions`](../interfaces/OscillatorOptions.md) Oscillator configuration (frequency, type, filters, envelope) #### Returns `Oscillator` #### Overrides `BaseSound.constructor` ## Properties ### \_analyzer > `protected` **\_analyzer**: [`Analyzer`](Analyzer.md) | `null` = `null` Defined in: [packages/core/src/base-sound.ts:161](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L161) #### Inherited from [`SampledNote`](SampledNote.md).[`_analyzer`](SampledNote.md#analyzer) *** ### \_destination > `protected` **\_destination**: `AudioNode` Defined in: [packages/core/src/base-sound.ts:154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L154) #### Inherited from [`SampledNote`](SampledNote.md).[`_destination`](SampledNote.md#destination) *** ### \_isPlaying > `protected` **\_isPlaying**: `boolean` = `false` Defined in: [packages/core/src/base-sound.ts:84](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L84) #### Inherited from [`SampledNote`](SampledNote.md).[`_isPlaying`](SampledNote.md#isplaying) *** ### \_targetGain > `protected` **\_targetGain**: `number` = `1` Defined in: [packages/core/src/base-sound.ts:107](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L107) The user's intended gain level (0–1). Tracks the last value set via changeGainTo() / volume setter so that gain can be restored after a fadeOut() or Oscillator anti-click stop that ramps gainNode.gain to 0. #### Inherited from [`SampledNote`](SampledNote.md).[`_targetGain`](SampledNote.md#targetgain) *** ### audioContext > `readonly` **audioContext**: `AudioContext` Defined in: [packages/core/src/base-sound.ts:218](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L218) #### Inherited from [`SampledNote`](SampledNote.md).[`audioContext`](SampledNote.md#audiocontext) *** ### audioSourceNode > **audioSourceNode**: `OscillatorNode` Defined in: [packages/core/src/oscillator.ts:139](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L139) The underlying OscillatorNode that generates the audio signal. #### Overrides `BaseSound.audioSourceNode` *** ### clearTimeout() > `protected` **clearTimeout**: (`id`) => `void` Defined in: [packages/core/src/base-sound.ts:97](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L97) #### Parameters ##### id `number` #### Returns `void` #### Inherited from `BaseSound.clearTimeout` *** ### controller > `protected` **controller**: [`OscillatorController`](OscillatorController.md) Defined in: [packages/core/src/oscillator.ts:151](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L151) Controller for managing gain, pan, frequency, and detune parameters. #### Overrides `BaseSound.controller` *** ### debug? > `optional` **debug**: `boolean` Defined in: [packages/core/src/base-sound.ts:216](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L216) #### Default ```ts undefined (follows global debug mode) ``` #### Example ```ts sound.debug = true // enable debug for this sound sound.debug = false // silence this sound even when global debug is on ``` #### Inherited from [`SampledNote`](SampledNote.md).[`debug`](SampledNote.md#debug) *** ### effectChainInput > `protected` **effectChainInput**: `GainNode` Defined in: [packages/core/src/base-sound.ts:147](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L147) #### Inherited from [`SampledNote`](SampledNote.md).[`effectChainInput`](SampledNote.md#effectchaininput) *** ### effects > `protected` **effects**: [`Effect`](../interfaces/Effect.md)\[] = `[]` Defined in: [packages/core/src/base-sound.ts:140](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L140) #### Inherited from [`SampledNote`](SampledNote.md).[`effects`](SampledNote.md#effects) *** ### freq > `protected` **freq**: `number` Defined in: [packages/core/src/oscillator.ts:148](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L148) Base frequency in Hz. *** ### gainNode > `protected` **gainNode**: `GainNode` Defined in: [packages/core/src/base-sound.ts:93](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L93) The GainNode controlling this sound's volume. For simple volume control, use changeGainTo() or update('gain'). For advanced routing, use getGainNode(). #### Inherited from [`SampledNote`](SampledNote.md).[`gainNode`](SampledNote.md#gainnode) *** ### name > **name**: `string` Defined in: [packages/core/src/base-sound.ts:202](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L202) #### Inherited from [`Sound`](Sound.md).[`name`](Sound.md#name) *** ### pannerNode > `protected` **pannerNode**: `StereoPannerNode` Defined in: [packages/core/src/base-sound.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L95) #### Inherited from [`SampledNote`](SampledNote.md).[`pannerNode`](SampledNote.md#pannernode) *** ### setTimeout() > `protected` **setTimeout**: (`fn`, `delayMillis`) => `number` Defined in: [packages/core/src/base-sound.ts:96](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L96) #### Parameters ##### fn () => `void` ##### delayMillis `number` #### Returns `number` #### Inherited from `BaseSound.setTimeout` *** ### startedPlayingAt > `protected` **startedPlayingAt**: `number` = `0` Defined in: [packages/core/src/base-sound.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L99) #### Inherited from [`SampledNote`](SampledNote.md).[`startedPlayingAt`](SampledNote.md#startedplayingat) *** ### startOffset > `protected` **startOffset**: `number` = `0` Defined in: [packages/core/src/base-sound.ts:170](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L170) Offset in seconds from the beginning of the audio buffer where playback starts. Used internally by Track for seek/resume functionality. #### Default ```ts 0 ``` #### See https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/start #### Inherited from [`SampledNote`](SampledNote.md).[`startOffset`](SampledNote.md#startoffset) ## Accessors ### \_isLooping #### Get Signature > **get** `protected` **\_isLooping**(): `boolean` Defined in: [packages/core/src/base-sound.ts:1183](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1183) Protected getter for looping state. Override in subclasses that support looping. Used by playAt() to skip the duration timeout when looping is active. ##### Returns `boolean` #### Inherited from `BaseSound._isLooping` *** ### disposed #### Get Signature > **get** **disposed**(): `boolean` Defined in: [packages/core/src/base-sound.ts:1174](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1174) Whether this instance has been disposed. Once disposed, the instance cannot be used for playback. Create a new instance if you need to play the sound again. ##### Example ```typescript sound.dispose() console.log(sound.disposed) // true ``` ##### Returns `boolean` #### Inherited from [`SampledNote`](SampledNote.md).[`disposed`](SampledNote.md#disposed) *** ### duration #### Get Signature > **get** **duration**(): [`TimeObject`](../interfaces/TimeObject.md) Defined in: [packages/core/src/oscillator.ts:543](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L543) Get the duration of the oscillator. Oscillators have no inherent duration - they play indefinitely until stopped. Returns Infinity to indicate continuous playback, distinguishing from finite Sound/Track durations. ##### Example ```typescript const osc = await createOscillator({ frequency: 440 }) console.log(osc.duration.raw) // Infinity // Oscillators must be explicitly stopped osc.play() setTimeout(() => osc.stop(), 1000) ``` ##### Returns [`TimeObject`](../interfaces/TimeObject.md) #### Overrides `BaseSound.duration` *** ### durationRaw #### Get Signature > **get** **durationRaw**(): `number` Defined in: [packages/core/src/oscillator.ts:522](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L522) Get the duration in seconds without allocating a TimeObject. Oscillators have infinite duration. ##### Returns `number` #### Overrides `BaseSound.durationRaw` *** ### isPlaying #### Get Signature > **get** **isPlaying**(): `boolean` Defined in: [packages/core/src/base-sound.ts:1115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1115) Whether the sound is currently playing. ##### Example ```typescript if (sound.isPlaying) { await sound.stop() } ``` ##### Returns `boolean` #### Inherited from [`SampledNote`](SampledNote.md).[`isPlaying`](SampledNote.md#isplaying) *** ### percentGain #### Get Signature > **get** **percentGain**(): `number` Defined in: [packages/core/src/base-sound.ts:1127](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1127) Current gain as a percentage (0-100). ##### Example ```typescript console.log(`Volume: ${sound.percentGain}%`) // "Volume: 50%" ``` ##### Returns `number` #### Inherited from [`SampledNote`](SampledNote.md).[`percentGain`](SampledNote.md#percentgain) *** ### volume #### Get Signature > **get** **volume**(): `number` Defined in: [packages/core/src/base-sound.ts:1150](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1150) Alias for gain. Get/set the volume (0 = silent, 1 = full volume). Values above 1 amplify the signal and may cause distortion. The setter delegates to `changeGainTo()`, which throws if the value is negative and warns if it exceeds 1. Inherited by Sound, Track, and Oscillator. ##### Example ```typescript sound.volume = 0.5 // set to half volume console.log(sound.volume) // 0.5 // Works on all BaseSound subclasses const osc = await createOscillator() osc.volume = 0.8 ``` ##### Returns `number` #### Set Signature > **set** **volume**(`value`): `void` Defined in: [packages/core/src/base-sound.ts:1154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1154) ##### Parameters ###### value `number` ##### Returns `void` #### Inherited from `BaseSound.volume` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 `BaseSound._clearListeners` *** ### \_onPlaybackStarted() > `protected` **\_onPlaybackStarted**(): `void` Defined in: [packages/core/src/base-sound.ts:1000](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1000) Hook method called after playback starts. Override in subclasses to add behavior that runs for all play variants. #### Returns `void` #### Inherited from `BaseSound._onPlaybackStarted` *** ### addEffect() > **addEffect**(`effect`, `position?`): `this` Defined in: [packages/core/src/base-sound.ts:401](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L401) Add an effect to the effect chain. Effects persist across multiple play() calls. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) The Effect instance to add ##### position? `number` Optional index to insert at (defaults to end of chain) #### Returns `this` this for chaining #### Example ```ts const filter = createFilterEffect('lowpass', { frequency: 1000 }) sound.addEffect(filter) ``` #### Inherited from `BaseSound.addEffect` *** ### addEffects() > **addEffects**(`effects`, `position?`): `this` Defined in: [packages/core/src/base-sound.ts:471](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L471) Add multiple effects to the effect chain in one call. The chain is rewired only once after all effects are added, which is more efficient than calling addEffect() multiple times. #### Parameters ##### effects [`Effect`](../interfaces/Effect.md)\[] Array of Effect instances to add ##### position? `number` Optional index to insert at (defaults to end of chain) #### Returns `this` this for chaining #### Example ```typescript const filter = createFilterEffect('lowpass', { frequency: 800 }) const boost = createGainEffect(1.5) sound.addEffects([filter, boost]) ``` #### Inherited from `BaseSound.addEffects` *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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"` ##### 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 `BaseSound.addEventListener` #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 `BaseSound.addEventListener` *** ### changeGainTo() > **changeGainTo**(`value`): `this` Defined in: [packages/core/src/base-sound.ts:693](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L693) Set the gain (volume) immediately. Convenience method for `update('gain').to(value).as('ratio')`. #### Parameters ##### value `number` Gain from 0 (silent) to 1 (full volume) #### Returns `this` this for chaining #### Example ```typescript sound.changeGainTo(0.5) // Half volume sound.changeGainTo(0) // Muted sound.changeGainTo(1) // Full volume ``` #### Inherited from `BaseSound.changeGainTo` *** ### changePanTo() > **changePanTo**(`value`): `this` Defined in: [packages/core/src/base-sound.ts:670](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L670) Set the pan position immediately. Convenience method for `update('pan').to(value).as('ratio')`. #### Parameters ##### value `number` Pan position from -1 (left) to 1 (right), 0 is center #### Returns `this` this for chaining #### Example ```typescript sound.changePanTo(-1) // Hard left sound.changePanTo(0) // Center sound.changePanTo(1) // Hard right ``` #### Inherited from `BaseSound.changePanTo` *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/base-sound.ts:1270](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1270) Dispose this sound instance, releasing all audio resources. Disconnects all audio nodes, clears the effect chain, cancels pending timeouts, and marks the instance as unusable. After disposing, calling play() will throw an error. Dispose is idempotent — calling it multiple times is safe. After disposal, event listeners registered via `on()` / `addEventListener()` will no longer fire. To free listener references for garbage collection, call `off()` for each listener before calling `dispose()`. #### Returns `void` #### Example ```typescript const sound = await createSound('click.mp3') await sound.play() // When done with the sound sound.dispose() console.log(sound.disposed) // true // Attempting to play after dispose will throw // sound.play() // throws Error: Cannot play a disposed sound ``` #### Inherited from `BaseSound.dispose` *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail [`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from `BaseSound.emit` *** ### fadeIn() > **fadeIn**(`duration`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1202](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1202) Fade in the sound from silence to its current gain over `duration` seconds, then play. Schedules a gain ramp from 0 to the current gain value and calls play(). The current gain is restored after playback — use changeGainTo() to set a target volume before calling fadeIn(). #### Parameters ##### duration `number` Fade-in duration in seconds #### Returns `Promise`<`void`> Promise that resolves when playback begins #### Example ```typescript const sound = await createSound('music.mp3') await sound.fadeIn(2) // fade in over 2 seconds ``` #### Inherited from `BaseSound.fadeIn` *** ### fadeOut() > **fadeOut**(`duration`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1225](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1225) Fade out the sound from its current gain to silence over `duration` seconds, then stop. If the sound is not playing, this is a no-op. Returns a Promise that resolves after the fade completes and stop() has been called. #### Parameters ##### duration `number` Fade-out duration in seconds #### Returns `Promise`<`void`> Promise that resolves when the fade and stop are complete #### Example ```typescript const sound = await createSound('music.mp3') await sound.play() await sound.fadeOut(2) // fade out over 2 seconds then stop ``` #### Inherited from `BaseSound.fadeOut` *** ### getAnalyzer() > **getAnalyzer**(): [`Analyzer`](Analyzer.md) | `null` Defined in: [packages/core/src/base-sound.ts:578](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L578) Get the currently attached analyzer, if any. #### Returns [`Analyzer`](Analyzer.md) | `null` The attached Analyzer instance, or null if none attached #### Inherited from `BaseSound.getAnalyzer` *** ### getEffects() > **getEffects**(): readonly [`Effect`](../interfaces/Effect.md)\[] Defined in: [packages/core/src/base-sound.ts:514](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L514) Get a readonly copy of the current effects array. #### Returns readonly [`Effect`](../interfaces/Effect.md)\[] Shallow copy of the effects array #### Inherited from `BaseSound.getEffects` *** ### getFilters() > **getFilters**(): readonly `BiquadFilterNode`\[] Defined in: [packages/core/src/oscillator.ts:514](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L514) Get a readonly snapshot of the oscillator's filter nodes. Returns a shallow copy of the internal filters array so callers can inspect filter state (type, frequency, Q) without mutating the chain. #### Returns readonly `BiquadFilterNode`\[] Readonly array of BiquadFilterNode instances #### Example ```typescript const osc = await createOscillator({ frequency: 440, lowpass: { frequency: 800, q: 1 }, highpass: { frequency: 200 } }) const filters = osc.getFilters() console.log(filters.length) // 2 console.log(filters[0].type) // 'highpass' ``` *** ### getGainNode() > **getGainNode**(): `GainNode` Defined in: [packages/core/src/base-sound.ts:597](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L597) Get the GainNode for this sound. Provides controlled access to the underlying GainNode for advanced audio routing scenarios (e.g., crossfading between tracks). For simple volume control, use changeGainTo() or update('gain'). #### Returns `GainNode` The GainNode controlling this sound's volume #### Example ```typescript const node = sound.getGainNode() node.gain.linearRampToValueAtTime(0, ctx.currentTime + 2) ``` #### Inherited from `BaseSound.getGainNode` *** ### getPannerNode() > **getPannerNode**(): `StereoPannerNode` Defined in: [packages/core/src/base-sound.ts:610](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L610) Get the StereoPannerNode for this sound. Provides controlled access to the underlying StereoPannerNode for advanced audio routing scenarios (e.g., LFO modulation of pan position). For simple pan control, use changePanTo() or update('pan'). #### Returns `StereoPannerNode` The StereoPannerNode controlling this sound's pan position #### Inherited from `BaseSound.getPannerNode` *** ### later() > `protected` **later**(`fn`): `void` Defined in: [packages/core/src/base-sound.ts:1158](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1158) #### Parameters ##### fn () => `void` #### Returns `void` #### Inherited from `BaseSound.later` *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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"` #### 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 `BaseSound.off` *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"play"` | `"dispose"` | `"stop"` | `"end"` #### 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 `BaseSound.on` *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"play"` | `"dispose"` | `"stop"` | `"end"` #### 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 `BaseSound.once` *** ### onPlayRamp() > **onPlayRamp**(`type`, `rampType?`): `object` Defined in: [packages/core/src/oscillator.ts:311](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L311) Schedule a parameter ramp when play() is called. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The parameter to ramp ('gain', 'pan', 'frequency', 'detune') ##### rampType? `RampType` Type of ramp curve ('linear' or 'exponential') #### Returns `object` Fluent builder for setting start value, end value, and duration ##### from() > **from**: (`startValue`) => `object` ###### Parameters ###### startValue `number` ###### Returns `object` ###### to() > **to**: (`endValue`) => `object` ###### Parameters ###### endValue `number` ###### Returns `object` ###### in() > **in**: (`endTime`) => `void` ###### Parameters ###### endTime `number` ###### Returns `void` #### Example ```typescript // Vibrato effect: ramp frequency up and down osc.onPlayRamp('frequency', 'linear').from(440).to(450).in(0.1) osc.play() ``` #### Overrides `BaseSound.onPlayRamp` *** ### onPlaySet() > **onPlaySet**(`type`): `object` Defined in: [packages/core/src/oscillator.ts:293](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L293) Schedule a parameter value to be set when play() is called. Oscillator supports additional parameters beyond Sound: * 'gain': Volume level (0-1) * 'pan': Stereo position (-1 to 1) * 'frequency': Oscillator frequency in Hz * 'detune': Detune in cents #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The parameter to control #### Returns `object` Fluent builder for setting value and timing ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### at() > **at**: (`time`) => `void` ###### Parameters ###### time `number` ###### Returns `void` ###### endingAt() > **endingAt**: (`time`, `rampType?`) => `void` ###### Parameters ###### time `number` ###### rampType? `RampType` ###### Returns `void` #### Example ```typescript // Start at frequency 220, glide up to 440 over 0.5 seconds osc.onPlaySet('frequency').to(220).at(0) osc.onPlaySet('frequency').to(440).endingAt(0.5, 'linear') osc.play() ``` #### Overrides `BaseSound.onPlaySet` *** ### play() > **play**(): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:819](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L819) Play the sound immediately. Resumes the AudioContext if suspended, sets up the audio source, and starts playback. For finite-duration sounds (Sound, Track), automatically schedules an 'end' event when playback completes. #### Returns `Promise`<`void`> Promise that resolves when playback begins #### Example ```typescript const sound = await createSound('click.mp3') await sound.play() ``` #### Inherited from `BaseSound.play` *** ### playAt() > **playAt**(`time`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:895](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L895) Play the audio source at a specific time. This is the underlying method for all play variants. Time is measured in seconds from when the AudioContext was created (audioContext.currentTime). #### Parameters ##### time `number` The AudioContext time when playback should start #### Returns `Promise`<`void`> #### Example ```typescript // Play immediately sound.playAt(audioContext.currentTime) // Play in 2 seconds sound.playAt(audioContext.currentTime + 2) // Sync multiple sounds const startTime = audioContext.currentTime + 0.1 sound1.playAt(startTime) sound2.playAt(startTime) ``` #### Inherited from `BaseSound.playAt` *** ### playFor() > **playFor**(`duration`): `void` Defined in: [packages/core/src/base-sound.ts:849](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L849) Play for a specific duration, then stop automatically. #### Parameters ##### duration `number` Seconds of playback before stopping #### Returns `void` #### Example ```typescript // Play for 3 seconds sound.playFor(3) ``` #### Inherited from `BaseSound.playFor` *** ### playIn() > **playIn**(`when`): `void` Defined in: [packages/core/src/base-sound.ts:834](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L834) Schedule playback after a delay. #### Parameters ##### when `number` Seconds from now until playback starts #### Returns `void` #### Example ```typescript // Play in 2 seconds sound.playIn(2) ``` #### Inherited from `BaseSound.playIn` *** ### playInAndStopAfter() > **playInAndStopAfter**(`playIn`, `stopAfter`): `void` Defined in: [packages/core/src/base-sound.ts:868](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L868) Play after a delay, then stop after a duration. Combines playIn() and stopIn() for precise timed playback. #### Parameters ##### playIn `number` Seconds from now until playback starts ##### stopAfter `number` Seconds of playback before stopping (from play start) #### Returns `void` #### Example ```typescript // Start in 1 second, play for 3 seconds sound.playInAndStopAfter(1, 3) ``` #### Inherited from `BaseSound.playInAndStopAfter` *** ### removeEffect() > **removeEffect**(`effect`): `this` Defined in: [packages/core/src/base-sound.ts:435](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L435) Remove an effect from the effect chain. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) The Effect instance to remove #### Returns `this` this for chaining #### Example ```ts sound.removeEffect(filter) ``` #### Inherited from `BaseSound.removeEffect` *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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"` ##### 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 `BaseSound.removeEventListener` #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 `BaseSound.removeEventListener` *** ### rewireEffects() > **rewireEffects**(): `void` Defined in: [packages/core/src/base-sound.ts:540](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L540) Re-wire the effect chain. Call this after toggling effect.bypass to update the audio routing. #### Returns `void` #### Inherited from `BaseSound.rewireEffects` *** ### setAnalyzer() > **setAnalyzer**(`analyzer`): `this` Defined in: [packages/core/src/base-sound.ts:567](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L567) Attach an analyzer to this sound for visualization. The analyzer is inserted at the end of the signal chain (after effects and panner, before destination), showing the fully processed signal. The analyzer is a passthrough node - audio flows through it unchanged while providing frequency and waveform data for visualization. #### Parameters ##### analyzer The Analyzer instance to attach, or null to detach [`Analyzer`](Analyzer.md) | `null` #### Returns `this` this for chaining #### Example ```ts const analyzer = createAnalyzer(audioContext, { fftSize: 2048 }) sound.setAnalyzer(analyzer) function draw() { const freqData = analyzer.getFrequencyData() // Draw frequency bars requestAnimationFrame(draw) } ``` #### Inherited from `BaseSound.setAnalyzer` *** ### setDestination() > **setDestination**(`node`): `this` Defined in: [packages/core/src/base-sound.ts:530](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L530) Set a custom destination for audio output instead of audioContext.destination. Useful for routing to sub-mixes, analyzers, or other processing chains. #### Parameters ##### node `AudioNode` The AudioNode to route output to #### Returns `this` this for chaining #### Example ```ts const analyzer = audioContext.createAnalyser() analyzer.connect(audioContext.destination) sound.setDestination(analyzer) ``` #### Inherited from `BaseSound.setDestination` *** ### setup() > `protected` **setup**(): `void` Defined in: [packages/core/src/oscillator.ts:321](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L321) Set up a fresh OscillatorNode for playback. Called automatically before each play() since OscillatorNode is single-use. The GainNode is reused across plays to keep cached references from `getGainNode()` stable. #### Returns `void` #### Overrides `BaseSound.setup` *** ### stop() > **stop**(): `Promise`<`void`> Defined in: [packages/core/src/oscillator.ts:664](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L664) Stop the sound immediately. Emits a 'stop' event. Safe to call when not playing (no-op). #### Returns `Promise`<`void`> Promise that resolves when the stop is processed #### Example ```typescript await sound.stop() ``` #### Overrides `BaseSound.stop` *** ### stopAt() > **stopAt**(`time`): `Promise`<`void`> Defined in: [packages/core/src/oscillator.ts:586](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L586) Stop the oscillator at a specific AudioContext time. Applies a quick 10ms gain fade-out before stopping to prevent click/pop artifacts from abrupt waveform cutoff. If an ADSR envelope is active, the fade-out is skipped since the envelope's release handles it. For a future `time`, `isPlaying` stays `true` and the `'stop'` event fires at the actual stop time rather than immediately — mirroring BaseSound.stopAt's future/immediate split (H1). #### Parameters ##### time `number` The AudioContext time when playback should stop #### Returns `Promise`<`void`> #### Overrides `BaseSound.stopAt` *** ### stopIn() > **stopIn**(`seconds`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1016](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1016) Stop the audio source after a delay. #### Parameters ##### seconds `number` Seconds from now until playback stops #### Returns `Promise`<`void`> #### Example ```typescript sound.play() // Stop after 5 seconds sound.stopIn(5) ``` #### Inherited from `BaseSound.stopIn` *** ### update() > **update**(`type`): `object` Defined in: [packages/core/src/oscillator.ts:247](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L247) Update an audio parameter immediately. Overrides BaseSound.update() to accept the full ControlType including 'frequency', which is only valid on Oscillator instances. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The parameter to update ('gain', 'pan', 'detune', or 'frequency') #### Returns `object` Fluent builder: `.to(value).as(unit)` ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### as() > **as**: (`method`) => `void` ###### Parameters ###### method [`RatioType`](../type-aliases/RatioType.md) ###### Returns `void` #### Example ```typescript osc.update('frequency').to(880).as('ratio') osc.update('gain').to(0.5).as('ratio') ``` #### Overrides `BaseSound.update` *** ### wireConnections() > `protected` **wireConnections**(): `void` Defined in: [packages/core/src/oscillator.ts:473](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L473) Wire oscillator through filters to effect chain. #### Returns `void` #### Overrides `BaseSound.wireConnections` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/OscillatorController.md' --- [EZ Web Audio](../index.md) / OscillatorController # Class: OscillatorController Defined in: [packages/core/src/controllers/oscillator-controller.ts:11](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L11) Parameter controller for Oscillator instances. Extends BaseParamController with frequency control and ADSR envelope support. Created automatically by Oscillator's constructor. ## Extends * `BaseParamController` ## Implements * `ParamController` ## Constructors ### Constructor > **new OscillatorController**(`oscillator`, `gainNode`, `pannerNode`): `OscillatorController` Defined in: [packages/core/src/controllers/oscillator-controller.ts:17](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L17) #### Parameters ##### oscillator `OscillatorNode` ##### gainNode `GainNode` ##### pannerNode `StereoPannerNode` #### Returns `OscillatorController` #### Overrides `BaseParamController.constructor` ## Properties ### audioSource > `protected` **audioSource**: `AudioSource` Defined in: [packages/core/src/controllers/base-param-controller.ts:110](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L110) #### Inherited from `BaseParamController.audioSource` *** ### exponentialValues > `protected` **exponentialValues**: `ValueAtTime`\[] = `[]` Defined in: [packages/core/src/controllers/base-param-controller.ts:114](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L114) #### Inherited from `BaseParamController.exponentialValues` *** ### gainNode > `protected` **gainNode**: `GainNode` Defined in: [packages/core/src/controllers/oscillator-controller.ts:17](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L17) #### Inherited from `BaseParamController.gainNode` *** ### linearValues > `protected` **linearValues**: `ValueAtTime`\[] = `[]` Defined in: [packages/core/src/controllers/base-param-controller.ts:115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L115) #### Inherited from `BaseParamController.linearValues` *** ### pannerNode > `protected` **pannerNode**: `StereoPannerNode` Defined in: [packages/core/src/controllers/oscillator-controller.ts:17](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L17) #### Inherited from `BaseParamController.pannerNode` *** ### startingValues > `protected` **startingValues**: `ParamValue`\[] = `[]` Defined in: [packages/core/src/controllers/base-param-controller.ts:112](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L112) #### Inherited from `BaseParamController.startingValues` *** ### valuesAtTime > `protected` **valuesAtTime**: `ValueAtTime`\[] = `[]` Defined in: [packages/core/src/controllers/base-param-controller.ts:113](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L113) #### Inherited from `BaseParamController.valuesAtTime` ## Accessors ### gain #### Get Signature > **get** **gain**(): `number` Defined in: [packages/core/src/controllers/base-param-controller.ts:120](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L120) Current gain value (0-1 typical range). ##### Returns `number` #### Set Signature > **set** **gain**(`value`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:124](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L124) ##### Parameters ###### value `number` ##### Returns `void` #### Implementation of `ParamController.gain` #### Inherited from `BaseParamController.gain` *** ### pan #### Get Signature > **get** **pan**(): `number` Defined in: [packages/core/src/controllers/base-param-controller.ts:128](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L128) ##### Returns `number` #### Set Signature > **set** **pan**(`value`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:132](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L132) ##### Parameters ###### value `number` ##### Returns `void` #### Implementation of `ParamController.pan` #### Inherited from `BaseParamController.pan` ## Methods ### \_update() > `protected` **\_update**(`type`, `value`): `void` Defined in: [packages/core/src/controllers/oscillator-controller.ts:52](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L52) #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) ##### value `number` #### Returns `void` #### Overrides `BaseParamController._update` *** ### applyRampToParam() > `protected` **applyRampToParam**(`param`, `value`, `time`, `rampType`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:453](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L453) Apply a ramp to an AudioParam using the specified ramp type. Shared helper to eliminate duplication between controllers. #### Parameters ##### param `AudioParam` The AudioParam to apply the ramp to ##### value `number` The target value ##### time `number` The absolute audio context time to reach the target value ##### rampType 'exponential' or 'linear' ramp `"linear"` | `"exponential"` #### Returns `void` #### Inherited from `BaseParamController.applyRampToParam` *** ### applyRampValues() > `protected` **applyRampValues**(`values`, `currentTime`, `rampType`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:367](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L367) Apply a list of ramped parameter values relative to the current time. Uses resolveParam() to map control types to AudioParams. #### Parameters ##### values `ValueAtTime`\[] Array of ValueAtTime to apply ##### currentTime `number` The audio context current time ##### rampType The ramp curve type ('exponential' or 'linear') `"linear"` | `"exponential"` #### Returns `void` #### Inherited from `BaseParamController.applyRampValues` *** ### applyValues() > `protected` **applyValues**(`values`, `currentTime`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:352](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L352) Apply a list of immediate parameter values at the current time. Uses resolveParam() to map control types to AudioParams. #### Parameters ##### values `ParamValue`\[] Array of ParamValue to apply ##### currentTime `number` The audio context current time #### Returns `void` #### Inherited from `BaseParamController.applyValues` *** ### clampPendingZeroBeforeExponentialRamp() > `protected` **clampPendingZeroBeforeExponentialRamp**(): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:392](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L392) Clamp any zero-valued startingValues/valuesAtTime entries that share a control type with a pending exponential ramp, to SAFE\_NEAR\_ZERO. An exponentialRampToValueAtTime whose previous scheduled value is exactly 0 holds the param at 0 for the entire ramp duration and then jumps to the target right at the end — an audible pop. onPlayRamp()'s `.from()` already guards this (see SAFE\_NEAR\_ZERO above), but the documented two-call fade-in idiom — `onPlaySet('gain').to(0).at(0)` followed by `onPlaySet('gain').to(1).endingAt(1)` (default exponential) — pushes a raw, unclamped 0 via `.at()` and reproduces the same pop. Call this before applying startingValues/valuesAtTime so every path into an exponential ramp is protected consistently. #### Returns `void` #### See onPlaySet #### Inherited from `BaseParamController.clampPendingZeroBeforeExponentialRamp` *** ### clearScheduledValues() > `protected` **clearScheduledValues**(): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:419](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L419) Clear all scheduled parameter arrays after they have been applied. Called at the end of setValuesAtTimes() in each controller subclass to ensure that parameter schedules set via onPlaySet() and onPlayRamp() are consumed once per play() call. If the same schedule is needed on every play, call onPlaySet() or onPlayRamp() before each play() call. #### Returns `void` #### See * onPlaySet * onPlayRamp #### Inherited from `BaseParamController.clearScheduledValues` *** ### onPlayRamp() > **onPlayRamp**(`type`, `rampType?`): `object` Defined in: [packages/core/src/controllers/base-param-controller.ts:293](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L293) Schedule a parameter ramp when play() is called. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The parameter to ramp ##### rampType? `RampType` Ramp curve type ('linear' or 'exponential') #### Returns `object` Fluent builder: `.from(startValue).to(endValue).in(duration)` ##### from() > **from**: (`startValue`) => `object` ###### Parameters ###### startValue `number` ###### Returns `object` ###### to() > **to**: (`endValue`) => `object` ###### Parameters ###### endValue `number` ###### Returns `object` ###### in() > **in**: (`endTime`) => `void` ###### Parameters ###### endTime `number` ###### Returns `void` #### Example ```typescript // Fade out over 2 seconds controller.onPlayRamp('gain', 'linear').from(1).to(0).in(2) ``` #### Implementation of `ParamController.onPlayRamp` #### Inherited from `BaseParamController.onPlayRamp` *** ### onPlaySet() > **onPlaySet**(`type`): `object` Defined in: [packages/core/src/controllers/base-param-controller.ts:256](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L256) Schedule a parameter value to be set when play() is called. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The parameter to schedule #### Returns `object` Fluent builder: `.to(value).at(time)` or `.to(value).endingAt(time, rampType)` ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### at() > **at**: (`time`) => `void` ###### Parameters ###### time `number` ###### Returns `void` ###### endingAt() > **endingAt**: (`time`, `rampType?`) => `void` ###### Parameters ###### time `number` ###### rampType? `RampType` ###### Returns `void` #### Remarks Schedules set via onPlaySet() are consumed (cleared) after each play() call by [clearScheduledValues](#clearscheduledvalues). Re-schedule before each play() if you need repeated automation. Accumulate-vs-replace semantics differ by call shape: `.to(value)` alone (no `.at()`/`.endingAt()`) REPLACES any prior un-timed schedule for the same type — calling it twice before play() keeps only the latest value. `.at(time)` and `.endingAt(time)` ACCUMULATE instead — each call pushes a new timed/ramp event, so calling either twice before play() applies both the stale and the new event on the next play(). Call [onPlaySet](#onplayset) again per-type only once per play() cycle unless you intend to schedule multiple timed events for that type. #### Example ```typescript // Set gain to 0 at start, ramp to 1 over 0.5s controller.onPlaySet('gain').to(0).at(0) controller.onPlaySet('gain').to(1).endingAt(0.5, 'linear') ``` #### Implementation of `ParamController.onPlaySet` #### Inherited from `BaseParamController.onPlaySet` *** ### resolveParam() > `protected` **resolveParam**(`type`): `AudioParam` Defined in: [packages/core/src/controllers/oscillator-controller.ts:92](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L92) Resolve a control type to its corresponding AudioParam. Extends BaseParamController.resolveParam() with 'frequency' support. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The control type to resolve #### Returns `AudioParam` The AudioParam corresponding to the control type #### Overrides `BaseParamController.resolveParam` *** ### setEnvelope() > **setEnvelope**(`envelope`, `peak`): `void` Defined in: [packages/core/src/controllers/oscillator-controller.ts:26](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L26) Sets the envelope to be applied during playback. #### Parameters ##### envelope [`Envelope`](Envelope.md) The Envelope instance to use for ADSR control ##### peak `number` = `1` Absolute amplitude the attack ramps to — the sound's target gain (default: 1) #### Returns `void` *** ### setValuesAtTimes() > **setValuesAtTimes**(): `void` Defined in: [packages/core/src/controllers/oscillator-controller.ts:66](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L66) Apply all scheduled parameter values and envelope to the current audio nodes. Called by Oscillator.setup() before each play(). #### Returns `void` #### Implementation of `ParamController.setValuesAtTimes` *** ### transferDetuneTo() > `protected` **transferDetuneTo**(`newSource`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:172](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L172) Carry the current detune value over to a replacement audio source node. Unlike gain/pan (which live on the persistent gain/panner nodes and therefore survive node replacement automatically), detune lives on the audioSource itself — the single-use OscillatorNode/AudioBufferSourceNode that gets swapped out on every play(). Without this, `update('detune')` would silently revert to 0 the next time the source node is replaced. Mirrors the copy-before-swap pattern used by updateGainNode/updatePannerNode. Call this BEFORE reassigning `this.audioSource` to the new node. #### Parameters ##### newSource `AudioSource` The replacement audio source node #### Returns `void` #### Inherited from `BaseParamController.transferDetuneTo` *** ### triggerRelease() > **triggerRelease**(`releaseTime`): `void` Defined in: [packages/core/src/controllers/oscillator-controller.ts:35](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L35) Triggers the release phase of the envelope. #### Parameters ##### releaseTime `number` The audio context time to start the release phase #### Returns `void` *** ### update() > **update**(`type`): `object` Defined in: [packages/core/src/controllers/base-param-controller.ts:217](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L217) Update an audio parameter immediately. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The parameter to update ('gain', 'pan', 'detune', or 'frequency') #### Returns `object` Fluent builder: `.to(value).as(unit)` ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### as() > **as**: (`method`) => `void` ###### Parameters ###### method [`RatioType`](../type-aliases/RatioType.md) ###### Returns `void` #### Example ```typescript controller.update('gain').to(0.5).as('ratio') controller.update('gain').to(50).as('percent') ``` #### Implementation of `ParamController.update` #### Inherited from `BaseParamController.update` *** ### updateAudioSource() > **updateAudioSource**(`source`): `void` Defined in: [packages/core/src/controllers/oscillator-controller.ts:46](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/oscillator-controller.ts#L46) Replace the oscillator node (called on each play() since OscillatorNode is single-use). #### Parameters ##### source The new OscillatorNode `OscillatorNode` | `AudioBufferSourceNode` #### Returns `void` #### Implementation of `ParamController.updateAudioSource` *** ### updateGainNode() > **updateGainNode**(`gainNode`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:142](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L142) Replace the gain node, preserving the current gain value. Called by Oscillator.setup() when recreating nodes for each play(). #### Parameters ##### gainNode `GainNode` The new GainNode to use #### Returns `void` #### Implementation of `ParamController.updateGainNode` #### Inherited from `BaseParamController.updateGainNode` *** ### updatePannerNode() > **updatePannerNode**(`pannerNode`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:153](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L153) Replace the panner node, preserving the current pan value. Called by Oscillator.setup() when recreating nodes for each play(). #### Parameters ##### pannerNode `StereoPannerNode` The new StereoPannerNode to use #### Returns `void` #### Implementation of `ParamController.updatePannerNode` #### Inherited from `BaseParamController.updatePannerNode` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/PolySynth.md' --- [EZ Web Audio](../index.md) / PolySynth # Class: PolySynth Defined in: [packages/core/src/poly-synth.ts:226](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L226) 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 * [`TypedEventEmitter`](TypedEventEmitter.md)<[`PolySynthEventMap`](../interfaces/PolySynthEventMap.md)> ## Constructors ### Constructor > **new PolySynth**(`audioContext`, `options?`): `PolySynth` Defined in: [packages/core/src/poly-synth.ts:242](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L242) #### Parameters ##### audioContext `AudioContext` ##### options? [`PolySynthOptions`](../interfaces/PolySynthOptions.md) #### Returns `PolySynth` #### Overrides [`TypedEventEmitter`](TypedEventEmitter.md).[`constructor`](TypedEventEmitter.md#constructor) ## Properties ### audioContext > `readonly` **audioContext**: `AudioContext` Defined in: [packages/core/src/poly-synth.ts:243](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L243) ## Accessors ### activeVoices #### Get Signature > **get** **activeVoices**(): `number` Defined in: [packages/core/src/poly-synth.ts:343](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L343) Number of currently active voices. ##### Returns `number` *** ### availableVoices #### Get Signature > **get** **availableVoices**(): `number` Defined in: [packages/core/src/poly-synth.ts:348](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L348) Number of available voice slots. ##### Returns `number` *** ### disposed #### Get Signature > **get** **disposed**(): `boolean` Defined in: [packages/core/src/poly-synth.ts:353](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L353) Whether this PolySynth has been disposed. ##### Returns `boolean` *** ### maxVoices #### Get Signature > **get** **maxVoices**(): `number` Defined in: [packages/core/src/poly-synth.ts:340](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L340) Maximum number of simultaneous voices. ##### Returns `number` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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`](TypedEventEmitter.md).[`_clearListeners`](TypedEventEmitter.md#clearlisteners) *** ### addEffect() > **addEffect**(`effect`, `position?`): `this` Defined in: [packages/core/src/poly-synth.ts:793](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L793) Add an effect to the shared output bus. All voices are affected. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) *** ### changeGainTo() > **changeGainTo**(`value`): `this` Defined in: [packages/core/src/poly-synth.ts:768](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L768) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L778) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L865) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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`](../interfaces/PolySynthEventMap.md)\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`TypedEventEmitter`](TypedEventEmitter.md).[`emit`](TypedEventEmitter.md#emit) *** ### getAnalyzer() > **getAnalyzer**(): [`Analyzer`](Analyzer.md) | `null` Defined in: [packages/core/src/poly-synth.ts:841](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L841) Get the currently attached analyzer. #### Returns [`Analyzer`](Analyzer.md) | `null` *** ### getEffects() > **getEffects**(): readonly [`Effect`](../interfaces/Effect.md)\[] Defined in: [packages/core/src/poly-synth.ts:822](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L822) Get a readonly copy of the current effects array. #### Returns readonly [`Effect`](../interfaces/Effect.md)\[] *** ### getGainNode() > **getGainNode**(): `GainNode` Defined in: [packages/core/src/poly-synth.ts:358](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L358) Returns the master GainNode (for LFO targeting and external routing). #### Returns `GainNode` *** ### getPannerNode() > **getPannerNode**(): `StereoPannerNode` Defined in: [packages/core/src/poly-synth.ts:361](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L361) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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`](TypedEventEmitter.md).[`off`](TypedEventEmitter.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) 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`](TypedEventEmitter.md).[`on`](TypedEventEmitter.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) 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`](TypedEventEmitter.md).[`once`](TypedEventEmitter.md#once) *** ### play() > **play**(`options`): [`VoiceHandle`](VoiceHandle.md) Defined in: [packages/core/src/poly-synth.ts:376](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L376) Play a note at the given frequency. Returns a VoiceHandle for per-voice control. #### Parameters ##### options [`PlayOptions`](../interfaces/PlayOptions.md) Frequency and optional per-voice gain #### Returns [`VoiceHandle`](VoiceHandle.md) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L810) Remove an effect from the shared output bus. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) *** ### setAnalyzer() > **setAnalyzer**(`analyzer`): `this` Defined in: [packages/core/src/poly-synth.ts:832](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L832) Attach an analyzer to the shared bus output for visualization. #### Parameters ##### analyzer The Analyzer instance, or null to detach [`Analyzer`](Analyzer.md) | `null` #### Returns `this` this for chaining *** ### setDestination() > **setDestination**(`node`): `this` Defined in: [packages/core/src/poly-synth.ts:851](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L851) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L682) 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](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L748) Update a master bus parameter immediately. Note: unlike [GrainPlayer](GrainPlayer.md), 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](VoiceHandle.md) 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`](../type-aliases/RatioType.md) ###### Returns `void` #### Example ```typescript synth.update('gain').to(0.5).as('ratio') ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/ReverbEffect.md' --- [EZ Web Audio](../index.md) / ReverbEffect # Class: ReverbEffect Defined in: [packages/core/src/effects/reverb-effect.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L75) ReverbEffect - Reverb with two modes: algorithmic (Schroeder) and convolution. **Algorithmic mode:** Builds a Schroeder reverb network with 4 parallel comb filters and 2 series allpass filters. Configurable decay, pre-delay, and damping. **Convolution mode:** Uses a ConvolverNode with an impulse response buffer for realistic space simulation (halls, rooms, plates, etc.). Use `createReverb()` factory for ergonomic creation with auto-detection. Extends BaseEffect for shared wet/dry mixing, bypass, and rampTo() functionality. ## Example ```typescript import { createReverb, createSound } from 'ez-web-audio' // Algorithmic reverb (synchronous) const reverb = createReverb({ decay: 2, damping: 0.4 }) sound.addEffect(reverb) // Convolution reverb (async - loads impulse response) const hallReverb = await createReverb('hall.wav') sound.addEffect(hallReverb) ``` ## Extends * [`BaseEffect`](BaseEffect.md) ## Constructors ### Constructor > **new ReverbEffect**(`audioContext`, `options?`): `ReverbEffect` Defined in: [packages/core/src/effects/reverb-effect.ts:93](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L93) Create an algorithmic reverb. #### Parameters ##### audioContext `AudioContext` ##### options? [`AlgorithmicReverbOptions`](../interfaces/AlgorithmicReverbOptions.md) #### Returns `ReverbEffect` #### Overrides [`BaseEffect`](BaseEffect.md).[`constructor`](BaseEffect.md#constructor) ## Accessors ### bypass #### Get Signature > **get** **bypass**(): `boolean` Defined in: [packages/core/src/effects/base-effect.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L95) When true, signal bypasses the effect entirely (100% dry). ##### Returns `boolean` #### Set Signature > **set** **bypass**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L99) When true, effect is bypassed (passthrough) ##### Parameters ###### v `boolean` ##### Returns `void` When true, effect is bypassed (passthrough) #### Inherited from [`BaseEffect`](BaseEffect.md).[`bypass`](BaseEffect.md#bypass) *** ### damping #### Get Signature > **get** **damping**(): `number` Defined in: [packages/core/src/effects/reverb-effect.ts:261](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L261) Damping amount 0-1 (algorithmic mode only). Higher = darker ##### Returns `number` #### Set Signature > **set** **damping**(`v`): `void` Defined in: [packages/core/src/effects/reverb-effect.ts:265](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L265) ##### Parameters ###### v `number` ##### Returns `void` *** ### decay #### Get Signature > **get** **decay**(): `number` Defined in: [packages/core/src/effects/reverb-effect.ts:226](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L226) Decay time in seconds (algorithmic mode only) ##### Returns `number` #### Set Signature > **set** **decay**(`v`): `void` Defined in: [packages/core/src/effects/reverb-effect.ts:230](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L230) ##### Parameters ###### v `number` ##### Returns `void` *** ### input #### Get Signature > **get** **input**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:83](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L83) The input AudioNode (receives signal from chain) ##### Returns `AudioNode` The input AudioNode that receives signal from the chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`input`](BaseEffect.md#input) *** ### mix #### Get Signature > **get** **mix**(): `number` Defined in: [packages/core/src/effects/base-effect.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L108) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (all through effect). Uses equal-power crossfade for natural mixing. ##### Returns `number` #### Set Signature > **set** **mix**(`v`): `void` Defined in: [packages/core/src/effects/base-effect.ts:112](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L112) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) ##### Parameters ###### v `number` ##### Returns `void` Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) #### Inherited from [`BaseEffect`](BaseEffect.md).[`mix`](BaseEffect.md#mix) *** ### mode #### Get Signature > **get** **mode**(): `"algorithmic"` | `"convolution"` Defined in: [packages/core/src/effects/reverb-effect.ts:221](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L221) Reverb mode: 'algorithmic' or 'convolution' ##### Returns `"algorithmic"` | `"convolution"` *** ### normalize #### Get Signature > **get** **normalize**(): `boolean` Defined in: [packages/core/src/effects/reverb-effect.ts:278](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L278) Whether to normalize the impulse response (convolution mode only) ##### Returns `boolean` #### Set Signature > **set** **normalize**(`v`): `void` Defined in: [packages/core/src/effects/reverb-effect.ts:282](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L282) ##### Parameters ###### v `boolean` ##### Returns `void` *** ### output #### Get Signature > **get** **output**(): `AudioNode` Defined in: [packages/core/src/effects/base-effect.ts:88](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L88) The output AudioNode (sends signal to next in chain) ##### Returns `AudioNode` The output AudioNode that sends signal to the next in chain #### Inherited from [`BaseEffect`](BaseEffect.md).[`output`](BaseEffect.md#output) *** ### preDelay #### Get Signature > **get** **preDelay**(): `number` Defined in: [packages/core/src/effects/reverb-effect.ts:247](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L247) Pre-delay time in seconds (algorithmic mode only) ##### Returns `number` #### Set Signature > **set** **preDelay**(`v`): `void` Defined in: [packages/core/src/effects/reverb-effect.ts:251](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L251) ##### Parameters ###### v `number` ##### Returns `void` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 [`BaseEffect`](BaseEffect.md).[`_clearListeners`](BaseEffect.md#clearlisteners) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 [`BaseEffect`](BaseEffect.md).[`addEventListener`](BaseEffect.md#addeventlistener) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/effects/reverb-effect.ts:288](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L288) Disconnect all internal audio nodes and emit a 'dispose' event. **Subclass disposal contract:** Subclasses that create additional audio nodes (e.g., BiquadFilterNode, DynamicsCompressorNode, WaveShaperNode) MUST override dispose() to disconnect those nodes before calling super.dispose(). #### Returns `void` #### Example ```typescript public override dispose(): void { try { this.myNode.disconnect() } catch { /* already disconnected */ } super.dispose() } ``` Idempotent — safe to call multiple times. #### Overrides [`BaseEffect`](BaseEffect.md).[`dispose`](BaseEffect.md#dispose) *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail `BaseEffectEventMap`\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`BaseEffect`](BaseEffect.md).[`emit`](BaseEffect.md#emit) *** ### getAudioContext() > **getAudioContext**(): `AudioContext` Defined in: [packages/core/src/effects/base-effect.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L121) Get the AudioContext used by this effect. Useful for external tools (e.g., LFO) that need the context. #### Returns `AudioContext` #### Inherited from [`BaseEffect`](BaseEffect.md).[`getAudioContext`](BaseEffect.md#getaudiocontext) *** ### getAudioParam() > `protected` **getAudioParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/reverb-effect.ts:341](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L341) Map a parameter name to its underlying AudioParam. Subclasses implement this to expose their effect-specific parameters. #### Parameters ##### name `string` The parameter name #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Overrides [`BaseEffect`](BaseEffect.md).[`getAudioParam`](BaseEffect.md#getaudioparam) *** ### getParam() > **getParam**(`name`): `AudioParam` | `null` Defined in: [packages/core/src/effects/base-effect.ts:134](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L134) Get a named AudioParam from this effect for external modulation. Delegates to the subclass's getAudioParam() implementation. Returns null if the parameter name is not recognized. #### Parameters ##### name `string` The parameter name (e.g., 'frequency', 'time', 'feedback') #### Returns `AudioParam` | `null` The AudioParam, or null if not recognized #### Inherited from [`BaseEffect`](BaseEffect.md).[`getParam`](BaseEffect.md#getparam) *** ### getUnrampableParams() > `protected` **getUnrampableParams**(): readonly `string`\[] Defined in: [packages/core/src/effects/reverb-effect.ts:355](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L355) `decay` and `damping` are documented ReverbEffect properties but drive a multi-node comb-filter network (4 delay times + 4 biquad frequencies), not a single AudioParam — rampTo() warns rather than silently no-op-ing if called with either name. Use the direct property setters instead (they're already smoothed via setTargetAtTime). #### Returns readonly `string`\[] #### Overrides [`BaseEffect`](BaseEffect.md).[`getUnrampableParams`](BaseEffect.md#getunrampableparams) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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"` #### 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 [`BaseEffect`](BaseEffect.md).[`off`](BaseEffect.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`on`](BaseEffect.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"dispose"` #### 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 [`BaseEffect`](BaseEffect.md).[`once`](BaseEffect.md#once) *** ### onParamRamped() > `protected` **onParamRamped**(`param`, `value`): `number` Defined in: [packages/core/src/effects/reverb-effect.ts:363](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L363) ramp-setter-desync fix: rampTo('preDelay', ...) re-applies the same \[0, 0.1] clamp the `preDelay` setter uses and updates the shadow field. #### Parameters ##### param `string` ##### value `number` #### Returns `number` #### Overrides [`BaseEffect`](BaseEffect.md).[`onParamRamped`](BaseEffect.md#onparamramped) *** ### rampTo() > **rampTo**(`param`, `value`, `duration`): `void` Defined in: [packages/core/src/effects/base-effect.ts:164](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/base-effect.ts#L164) Smoothly ramp a parameter to a target value over a duration. Uses `AudioParam.setTargetAtTime` for glitch-free transitions. If the parameter name is not recognized, this is a no-op (a `console.warn` is emitted if the name is a real, documented effect property that just isn't backed by a single AudioParam — see [getUnrampableParams](BaseEffect.md#getunrampableparams)). **Single write path:** every ramped write is funneled through [onParamRamped](BaseEffect.md#onparamramped), the same hook subclasses use to keep their shadow getters honest. This guarantees `effect.someParam` reflects the ramp target immediately after calling `rampTo()`, and that the exact same validation/clamping a synchronous property-set would apply is also applied to ramped writes — the AudioParam and the getter can never diverge from each other. #### Parameters ##### param `string` Parameter name (e.g., 'frequency', 'time', 'feedback') ##### value `number` Target value ##### duration `number` Ramp duration in seconds #### Returns `void` #### Example ```typescript delay.rampTo('time', 0.5, 2) // Ramp delay time to 0.5s over 2 seconds filter.rampTo('frequency', 800, 1) // Ramp cutoff to 800Hz over 1 second ``` #### Inherited from [`BaseEffect`](BaseEffect.md).[`rampTo`](BaseEffect.md#rampto) *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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"` ##### 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 [`BaseEffect`](BaseEffect.md).[`removeEventListener`](BaseEffect.md#removeeventlistener) *** ### fromConvolution() > `static` **fromConvolution**(`audioContext`, `buffer`, `options`): `ReverbEffect` Defined in: [packages/core/src/effects/reverb-effect.ts:212](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L212) Create a convolution reverb from an existing AudioBuffer. #### Parameters ##### audioContext `AudioContext` ##### buffer `AudioBuffer` ##### options [`ConvolutionReverbOptions`](../interfaces/ConvolutionReverbOptions.md) = `{}` #### Returns `ReverbEffect` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/SampledNote.md' --- [EZ Web Audio](../index.md) / SampledNote # Class: SampledNote Defined in: [packages/core/src/sampled-note.ts:30](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampled-note.ts#L30) A Sound with musical identity. SampledNote extends Sound with musical properties (letter, accidental, octave, frequency) via the MusicallyAware mixin. Used in Font collections where each sound represents a specific musical note. ## Example ```typescript import { createFont } from 'ez-web-audio' // SampledNote is typically created via createFont(), not directly const piano = await createFont('piano.js') const noteA4 = piano.getNote('A4') // Access musical properties console.log(noteA4?.frequency) // 440 console.log(noteA4?.identifier) // "A4" console.log(noteA4?.letter) // "A" console.log(noteA4?.octave) // "4" // Use Sound methods noteA4?.changeGainTo(0.5) noteA4?.play() ``` ## Extends * `MusicalIdentity`<*typeof* [`Sound`](Sound.md), `this`> & [`Sound`](Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md), `this`> ## Indexable \[`key`: `string`]: `any` ## Constructors ### Constructor > **new SampledNote**(`audioContext`, `audioBuffer`, `opts?`): `SampledNote` Defined in: [packages/core/src/sound.ts:87](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L87) Create a Sound instance. Note: Use [createSound](../functions/createSound.md) factory function instead of calling this directly. #### Parameters ##### audioContext `AudioContext` The AudioContext to use for audio operations ##### audioBuffer `AudioBuffer` The decoded audio data to play ##### opts? `BaseSoundOptions` Optional configuration (name, setTimeout override) #### Returns `SampledNote` #### Inherited from `MusicallyAware(Sound).constructor` ## Properties ### \_analyzer > `protected` **\_analyzer**: [`Analyzer`](Analyzer.md) | `null` = `null` Defined in: [packages/core/src/base-sound.ts:161](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L161) #### Inherited from `MusicallyAware(Sound)._analyzer` *** ### \_destination > `protected` **\_destination**: `AudioNode` Defined in: [packages/core/src/base-sound.ts:154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L154) #### Inherited from `MusicallyAware(Sound)._destination` *** ### \_isPlaying > `protected` **\_isPlaying**: `boolean` = `false` Defined in: [packages/core/src/base-sound.ts:84](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L84) #### Inherited from `MusicallyAware(Sound)._isPlaying` *** ### \_targetGain > `protected` **\_targetGain**: `number` = `1` Defined in: [packages/core/src/base-sound.ts:107](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L107) The user's intended gain level (0–1). Tracks the last value set via changeGainTo() / volume setter so that gain can be restored after a fadeOut() or Oscillator anti-click stop that ramps gainNode.gain to 0. #### Inherited from `MusicallyAware(Sound)._targetGain` *** ### accidental > **accidental**: `Accidental` = `''` Defined in: [packages/core/src/musical-identity.ts:110](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L110) The accidental: "" (natural), "b" (flat), or "#" (sharp). For note "Ab5", this would be "b". #### Inherited from `MusicallyAware(Sound).accidental` *** ### audioBuffer > `readonly` **audioBuffer**: `AudioBuffer` Defined in: [packages/core/src/sound.ts:87](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L87) The decoded audio data to play #### Inherited from `MusicallyAware(Sound).audioBuffer` *** ### audioContext > `readonly` **audioContext**: `AudioContext` Defined in: [packages/core/src/base-sound.ts:218](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L218) #### Inherited from `MusicallyAware(Sound).audioContext` *** ### audioSourceNode > **audioSourceNode**: `AudioBufferSourceNode` Defined in: [packages/core/src/sound.ts:36](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L36) The underlying AudioBufferSourceNode that plays the audio. #### Inherited from `MusicallyAware(Sound).audioSourceNode` *** ### clearTimeout() > `protected` **clearTimeout**: (`id`) => `void` Defined in: [packages/core/src/base-sound.ts:97](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L97) #### Parameters ##### id `number` #### Returns `void` #### Inherited from `MusicallyAware(Sound).clearTimeout` *** ### controller > `protected` **controller**: [`SoundController`](SoundController.md) Defined in: [packages/core/src/sound.ts:39](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L39) Controller for managing gain, pan, and other audio parameters. #### Inherited from `MusicallyAware(Sound).controller` *** ### debug? > `optional` **debug**: `boolean` Defined in: [packages/core/src/base-sound.ts:216](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L216) #### Default ```ts undefined (follows global debug mode) ``` #### Example ```ts sound.debug = true // enable debug for this sound sound.debug = false // silence this sound even when global debug is on ``` #### Inherited from `MusicallyAware(Sound).debug` *** ### effectChainInput > `protected` **effectChainInput**: `GainNode` Defined in: [packages/core/src/base-sound.ts:147](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L147) #### Inherited from `MusicallyAware(Sound).effectChainInput` *** ### effects > `protected` **effects**: [`Effect`](../interfaces/Effect.md)\[] = `[]` Defined in: [packages/core/src/base-sound.ts:140](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L140) #### Inherited from `MusicallyAware(Sound).effects` *** ### gainNode > `protected` **gainNode**: `GainNode` Defined in: [packages/core/src/base-sound.ts:93](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L93) The GainNode controlling this sound's volume. For simple volume control, use changeGainTo() or update('gain'). For advanced routing, use getGainNode(). #### Inherited from `MusicallyAware(Sound).gainNode` *** ### letter > **letter**: `NoteLetter` = `'A'` Defined in: [packages/core/src/musical-identity.ts:104](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L104) The note letter (A-G). For note "Ab5", this would be "A". #### Inherited from `MusicallyAware(Sound).letter` *** ### name > **name**: `string` Defined in: [packages/core/src/musical-identity.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L121) #### Inherited from [`Note`](Note.md).[`name`](Note.md#name) *** ### octave > **octave**: `Octave` = `'0'` Defined in: [packages/core/src/musical-identity.ts:115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L115) The octave (0-8). For note "Ab5", this would be "5". #### Inherited from `MusicallyAware(Sound).octave` *** ### pannerNode > `protected` **pannerNode**: `StereoPannerNode` Defined in: [packages/core/src/base-sound.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L95) #### Inherited from `MusicallyAware(Sound).pannerNode` *** ### setTimeout() > `protected` **setTimeout**: (`fn`, `delayMillis`) => `number` Defined in: [packages/core/src/base-sound.ts:96](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L96) #### Parameters ##### fn () => `void` ##### delayMillis `number` #### Returns `number` #### Inherited from `MusicallyAware(Sound).setTimeout` *** ### startedPlayingAt > `protected` **startedPlayingAt**: `number` = `0` Defined in: [packages/core/src/base-sound.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L99) #### Inherited from `MusicallyAware(Sound).startedPlayingAt` *** ### startOffset > `protected` **startOffset**: `number` = `0` Defined in: [packages/core/src/base-sound.ts:170](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L170) Offset in seconds from the beginning of the audio buffer where playback starts. Used internally by Track for seek/resume functionality. #### Default ```ts 0 ``` #### See https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/start #### Inherited from `MusicallyAware(Sound).startOffset` ## Accessors ### \_isLooping #### Get Signature > **get** `protected` **\_isLooping**(): `boolean` Defined in: [packages/core/src/sound.ts:74](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L74) Returns whether this sound is set to loop. Used by BaseSound.playAt() to skip the duration timeout when looping is enabled. ##### Returns `boolean` #### Inherited from `MusicallyAware(Sound)._isLooping` *** ### disposed #### Get Signature > **get** **disposed**(): `boolean` Defined in: [packages/core/src/base-sound.ts:1174](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1174) Whether this instance has been disposed. Once disposed, the instance cannot be used for playback. Create a new instance if you need to play the sound again. ##### Example ```typescript sound.dispose() console.log(sound.disposed) // true ``` ##### Returns `boolean` #### Inherited from `MusicallyAware(Sound).disposed` *** ### duration #### Get Signature > **get** **duration**(): [`TimeObject`](../interfaces/TimeObject.md) Defined in: [packages/core/src/sound.ts:208](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L208) Get the duration of the audio buffer. Returns a TimeObject with the duration in multiple formats: * `raw`: Duration in seconds * `string`: Formatted as 'MM:SS' * `pojo`: Object with `minutes` and `seconds` properties ##### Example ```typescript const sound = await createSound('song.mp3') console.log(sound.duration.raw) // 180.5 console.log(sound.duration.string) // '3:00' console.log(sound.duration.pojo) // { minutes: 3, seconds: 0 } ``` ##### Returns [`TimeObject`](../interfaces/TimeObject.md) #### Inherited from `MusicallyAware(Sound).duration` *** ### durationRaw #### Get Signature > **get** **durationRaw**(): `number` Defined in: [packages/core/src/sound.ts:187](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L187) Get the duration of the audio buffer in seconds. Use this instead of `duration.raw` in performance-sensitive code paths to avoid allocating a TimeObject. ##### Returns `number` #### Inherited from `MusicallyAware(Sound).durationRaw` *** ### frequency #### Get Signature > **get** **frequency**(): `number` Defined in: [packages/core/src/musical-identity.ts:144](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L144) The frequency of the note in hertz. Computed from the note identifier using standard piano frequencies. Setting this value updates all other properties to match. ##### Example ```typescript note.frequency = 440 // Sets to A4 console.log(note.identifier) // "A4" ``` ##### Returns `number` #### Set Signature > **set** **frequency**(`value`): `void` Defined in: [packages/core/src/musical-identity.ts:159](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L159) Setting frequency resolves to the nearest tabled note within FREQUENCY\_MATCH\_TOLERANCE\_CENTS cents (a computed/synthesized frequency rarely lands on an exact table value). If nothing is close enough, a warning is logged and the identifier is left unchanged rather than silently going stale. ##### Parameters ###### value `number` ##### Returns `void` #### Inherited from `MusicallyAware(Sound).frequency` *** ### identifier #### Get Signature > **get** **identifier**(): `"C0"` | `"Db0"` | `"C#0"` | `"D0"` | `"Eb0"` | `"D#0"` | `"E0"` | `"F0"` | `"Gb0"` | `"F#0"` | `"G0"` | `"Ab0"` | `"G#0"` | `"A0"` | `"Bb0"` | `"A#0"` | `"B0"` | `"C1"` | `"Db1"` | `"C#1"` | `"D1"` | `"Eb1"` | `"D#1"` | `"E1"` | `"F1"` | `"Gb1"` | `"F#1"` | `"G1"` | `"Ab1"` | `"G#1"` | `"A1"` | `"Bb1"` | `"A#1"` | `"B1"` | `"C2"` | `"Db2"` | `"C#2"` | `"D2"` | `"Eb2"` | `"D#2"` | `"E2"` | `"F2"` | `"Gb2"` | `"F#2"` | `"G2"` | `"Ab2"` | `"G#2"` | `"A2"` | `"Bb2"` | `"A#2"` | `"B2"` | `"C3"` | `"Db3"` | `"C#3"` | `"D3"` | `"Eb3"` | `"D#3"` | `"E3"` | `"F3"` | `"Gb3"` | `"F#3"` | `"G3"` | `"Ab3"` | `"G#3"` | `"A3"` | `"Bb3"` | `"A#3"` | `"B3"` | `"C4"` | `"Db4"` | `"C#4"` | `"D4"` | `"Eb4"` | `"D#4"` | `"E4"` | `"F4"` | `"Gb4"` | `"F#4"` | `"G4"` | `"Ab4"` | `"G#4"` | `"A4"` | `"Bb4"` | `"A#4"` | `"B4"` | `"C5"` | `"Db5"` | `"C#5"` | `"D5"` | `"Eb5"` | `"D#5"` | `"E5"` | `"F5"` | `"Gb5"` | `"F#5"` | `"G5"` | `"Ab5"` | `"G#5"` | `"A5"` | `"Bb5"` | `"A#5"` | `"B5"` | `"C6"` | `"Db6"` | `"C#6"` | `"D6"` | `"Eb6"` | `"D#6"` | `"E6"` | `"F6"` | `"Gb6"` | `"F#6"` | `"G6"` | `"Ab6"` | `"G#6"` | `"A6"` | `"Bb6"` | `"A#6"` | `"B6"` | `"C7"` | `"Db7"` | `"C#7"` | `"D7"` | `"Eb7"` | `"D#7"` | `"E7"` | `"F7"` | `"Gb7"` | `"F#7"` | `"G7"` | `"Ab7"` | `"G#7"` | `"A7"` | `"Bb7"` | `"A#7"` | `"B7"` | `"C8"` | `"Db8"` | `"C#8"` | `"D8"` | `"Eb8"` | `"D#8"` Defined in: [packages/core/src/musical-identity.ts:210](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L210) The full note identifier (e.g., "A4", "Bb3", "C#5"). Computed from letter, accidental, and octave. Setting this value updates all other properties to match. ##### Example ```typescript note.identifier = 'Bb3' console.log(note.letter) // "B" console.log(note.accidental) // "b" console.log(note.octave) // "3" console.log(note.frequency) // 233.08 ``` ##### Returns `"C0"` | `"Db0"` | `"C#0"` | `"D0"` | `"Eb0"` | `"D#0"` | `"E0"` | `"F0"` | `"Gb0"` | `"F#0"` | `"G0"` | `"Ab0"` | `"G#0"` | `"A0"` | `"Bb0"` | `"A#0"` | `"B0"` | `"C1"` | `"Db1"` | `"C#1"` | `"D1"` | `"Eb1"` | `"D#1"` | `"E1"` | `"F1"` | `"Gb1"` | `"F#1"` | `"G1"` | `"Ab1"` | `"G#1"` | `"A1"` | `"Bb1"` | `"A#1"` | `"B1"` | `"C2"` | `"Db2"` | `"C#2"` | `"D2"` | `"Eb2"` | `"D#2"` | `"E2"` | `"F2"` | `"Gb2"` | `"F#2"` | `"G2"` | `"Ab2"` | `"G#2"` | `"A2"` | `"Bb2"` | `"A#2"` | `"B2"` | `"C3"` | `"Db3"` | `"C#3"` | `"D3"` | `"Eb3"` | `"D#3"` | `"E3"` | `"F3"` | `"Gb3"` | `"F#3"` | `"G3"` | `"Ab3"` | `"G#3"` | `"A3"` | `"Bb3"` | `"A#3"` | `"B3"` | `"C4"` | `"Db4"` | `"C#4"` | `"D4"` | `"Eb4"` | `"D#4"` | `"E4"` | `"F4"` | `"Gb4"` | `"F#4"` | `"G4"` | `"Ab4"` | `"G#4"` | `"A4"` | `"Bb4"` | `"A#4"` | `"B4"` | `"C5"` | `"Db5"` | `"C#5"` | `"D5"` | `"Eb5"` | `"D#5"` | `"E5"` | `"F5"` | `"Gb5"` | `"F#5"` | `"G5"` | `"Ab5"` | `"G#5"` | `"A5"` | `"Bb5"` | `"A#5"` | `"B5"` | `"C6"` | `"Db6"` | `"C#6"` | `"D6"` | `"Eb6"` | `"D#6"` | `"E6"` | `"F6"` | `"Gb6"` | `"F#6"` | `"G6"` | `"Ab6"` | `"G#6"` | `"A6"` | `"Bb6"` | `"A#6"` | `"B6"` | `"C7"` | `"Db7"` | `"C#7"` | `"D7"` | `"Eb7"` | `"D#7"` | `"E7"` | `"F7"` | `"Gb7"` | `"F#7"` | `"G7"` | `"Ab7"` | `"G#7"` | `"A7"` | `"Bb7"` | `"A#7"` | `"B7"` | `"C8"` | `"Db8"` | `"C#8"` | `"D8"` | `"Eb8"` | `"D#8"` #### Set Signature > **set** **identifier**(`value`): `void` Defined in: [packages/core/src/musical-identity.ts:232](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L232) ##### Parameters ###### value `"C0"` | `"Db0"` | `"C#0"` | `"D0"` | `"Eb0"` | `"D#0"` | `"E0"` | `"F0"` | `"Gb0"` | `"F#0"` | `"G0"` | `"Ab0"` | `"G#0"` | `"A0"` | `"Bb0"` | `"A#0"` | `"B0"` | `"C1"` | `"Db1"` | `"C#1"` | `"D1"` | `"Eb1"` | `"D#1"` | `"E1"` | `"F1"` | `"Gb1"` | `"F#1"` | `"G1"` | `"Ab1"` | `"G#1"` | `"A1"` | `"Bb1"` | `"A#1"` | `"B1"` | `"C2"` | `"Db2"` | `"C#2"` | `"D2"` | `"Eb2"` | `"D#2"` | `"E2"` | `"F2"` | `"Gb2"` | `"F#2"` | `"G2"` | `"Ab2"` | `"G#2"` | `"A2"` | `"Bb2"` | `"A#2"` | `"B2"` | `"C3"` | `"Db3"` | `"C#3"` | `"D3"` | `"Eb3"` | `"D#3"` | `"E3"` | `"F3"` | `"Gb3"` | `"F#3"` | `"G3"` | `"Ab3"` | `"G#3"` | `"A3"` | `"Bb3"` | `"A#3"` | `"B3"` | `"C4"` | `"Db4"` | `"C#4"` | `"D4"` | `"Eb4"` | `"D#4"` | `"E4"` | `"F4"` | `"Gb4"` | `"F#4"` | `"G4"` | `"Ab4"` | `"G#4"` | `"A4"` | `"Bb4"` | `"A#4"` | `"B4"` | `"C5"` | `"Db5"` | `"C#5"` | `"D5"` | `"Eb5"` | `"D#5"` | `"E5"` | `"F5"` | `"Gb5"` | `"F#5"` | `"G5"` | `"Ab5"` | `"G#5"` | `"A5"` | `"Bb5"` | `"A#5"` | `"B5"` | `"C6"` | `"Db6"` | `"C#6"` | `"D6"` | `"Eb6"` | `"D#6"` | `"E6"` | `"F6"` | `"Gb6"` | `"F#6"` | `"G6"` | `"Ab6"` | `"G#6"` | `"A6"` | `"Bb6"` | `"A#6"` | `"B6"` | `"C7"` | `"Db7"` | `"C#7"` | `"D7"` | `"Eb7"` | `"D#7"` | `"E7"` | `"F7"` | `"Gb7"` | `"F#7"` | `"G7"` | `"Ab7"` | `"G#7"` | `"A7"` | `"Bb7"` | `"A#7"` | `"B7"` | `"C8"` | `"Db8"` | `"C#8"` | `"D8"` | `"Eb8"` | `"D#8"` ##### Returns `void` #### Inherited from `MusicallyAware(Sound).identifier` *** ### isPlaying #### Get Signature > **get** **isPlaying**(): `boolean` Defined in: [packages/core/src/base-sound.ts:1115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1115) Whether the sound is currently playing. ##### Example ```typescript if (sound.isPlaying) { await sound.stop() } ``` ##### Returns `boolean` #### Inherited from `MusicallyAware(Sound).isPlaying` *** ### loop #### Get Signature > **get** **loop**(): `boolean` Defined in: [packages/core/src/sound.ts:61](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L61) Enable or disable native looping for this sound. When `loop` is true, the audio replays from the beginning when it reaches the end, providing gapless looping via the native `AudioBufferSourceNode.loop` property. Call `stop()` to end looped playback. ##### Example ```typescript const sfx = await createSound('rain.mp3') sfx.loop = true sfx.play() // plays continuously until stop() // Stop looped playback await sfx.stop() ``` ##### Returns `boolean` #### Set Signature > **set** **loop**(`value`): `void` Defined in: [packages/core/src/sound.ts:65](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L65) ##### Parameters ###### value `boolean` ##### Returns `void` #### Inherited from `MusicallyAware(Sound).loop` *** ### percentGain #### Get Signature > **get** **percentGain**(): `number` Defined in: [packages/core/src/base-sound.ts:1127](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1127) Current gain as a percentage (0-100). ##### Example ```typescript console.log(`Volume: ${sound.percentGain}%`) // "Volume: 50%" ``` ##### Returns `number` #### Inherited from `MusicallyAware(Sound).percentGain` *** ### volume #### Get Signature > **get** **volume**(): `number` Defined in: [packages/core/src/base-sound.ts:1150](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1150) Alias for gain. Get/set the volume (0 = silent, 1 = full volume). Values above 1 amplify the signal and may cause distortion. The setter delegates to `changeGainTo()`, which throws if the value is negative and warns if it exceeds 1. Inherited by Sound, Track, and Oscillator. ##### Example ```typescript sound.volume = 0.5 // set to half volume console.log(sound.volume) // 0.5 // Works on all BaseSound subclasses const osc = await createOscillator() osc.volume = 0.8 ``` ##### Returns `number` #### Set Signature > **set** **volume**(`value`): `void` Defined in: [packages/core/src/base-sound.ts:1154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1154) ##### Parameters ###### value `number` ##### Returns `void` #### Inherited from `MusicallyAware(Sound).volume` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 `MusicallyAware(Sound)._clearListeners` *** ### \_onPlaybackStarted() > `protected` **\_onPlaybackStarted**(): `void` Defined in: [packages/core/src/sampled-note.ts:46](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampled-note.ts#L46) Schedule a short gain fade that lands just before the buffer runs out. Soundfont samples are often trimmed hard at the end; without this, a note that plays to its natural end truncates audibly. Skipped for very short buffers (percussive one-shots) where a 150ms fade would eat the sound. #### Returns `void` #### Overrides `MusicallyAware(Sound)._onPlaybackStarted` *** ### addEffect() > **addEffect**(`effect`, `position?`): `this` Defined in: [packages/core/src/base-sound.ts:401](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L401) Add an effect to the effect chain. Effects persist across multiple play() calls. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) The Effect instance to add ##### position? `number` Optional index to insert at (defaults to end of chain) #### Returns `this` this for chaining #### Example ```ts const filter = createFilterEffect('lowpass', { frequency: 1000 }) sound.addEffect(filter) ``` #### Inherited from `MusicallyAware(Sound).addEffect` *** ### addEffects() > **addEffects**(`effects`, `position?`): `this` Defined in: [packages/core/src/base-sound.ts:471](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L471) Add multiple effects to the effect chain in one call. The chain is rewired only once after all effects are added, which is more efficient than calling addEffect() multiple times. #### Parameters ##### effects [`Effect`](../interfaces/Effect.md)\[] Array of Effect instances to add ##### position? `number` Optional index to insert at (defaults to end of chain) #### Returns `this` this for chaining #### Example ```typescript const filter = createFilterEffect('lowpass', { frequency: 800 }) const boost = createGainEffect(1.5) sound.addEffects([filter, boost]) ``` #### Inherited from `MusicallyAware(Sound).addEffects` *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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"` ##### 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 `MusicallyAware(Sound).addEventListener` #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 `MusicallyAware(Sound).addEventListener` *** ### changeGainTo() > **changeGainTo**(`value`): `this` Defined in: [packages/core/src/base-sound.ts:693](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L693) Set the gain (volume) immediately. Convenience method for `update('gain').to(value).as('ratio')`. #### Parameters ##### value `number` Gain from 0 (silent) to 1 (full volume) #### Returns `this` this for chaining #### Example ```typescript sound.changeGainTo(0.5) // Half volume sound.changeGainTo(0) // Muted sound.changeGainTo(1) // Full volume ``` #### Inherited from `MusicallyAware(Sound).changeGainTo` *** ### changePanTo() > **changePanTo**(`value`): `this` Defined in: [packages/core/src/base-sound.ts:670](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L670) Set the pan position immediately. Convenience method for `update('pan').to(value).as('ratio')`. #### Parameters ##### value `number` Pan position from -1 (left) to 1 (right), 0 is center #### Returns `this` this for chaining #### Example ```typescript sound.changePanTo(-1) // Hard left sound.changePanTo(0) // Center sound.changePanTo(1) // Hard right ``` #### Inherited from `MusicallyAware(Sound).changePanTo` *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/base-sound.ts:1270](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1270) Dispose this sound instance, releasing all audio resources. Disconnects all audio nodes, clears the effect chain, cancels pending timeouts, and marks the instance as unusable. After disposing, calling play() will throw an error. Dispose is idempotent — calling it multiple times is safe. After disposal, event listeners registered via `on()` / `addEventListener()` will no longer fire. To free listener references for garbage collection, call `off()` for each listener before calling `dispose()`. #### Returns `void` #### Example ```typescript const sound = await createSound('click.mp3') await sound.play() // When done with the sound sound.dispose() console.log(sound.disposed) // true // Attempting to play after dispose will throw // sound.play() // throws Error: Cannot play a disposed sound ``` #### Inherited from `MusicallyAware(Sound).dispose` *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail [`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from `MusicallyAware(Sound).emit` *** ### fadeIn() > **fadeIn**(`duration`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1202](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1202) Fade in the sound from silence to its current gain over `duration` seconds, then play. Schedules a gain ramp from 0 to the current gain value and calls play(). The current gain is restored after playback — use changeGainTo() to set a target volume before calling fadeIn(). #### Parameters ##### duration `number` Fade-in duration in seconds #### Returns `Promise`<`void`> Promise that resolves when playback begins #### Example ```typescript const sound = await createSound('music.mp3') await sound.fadeIn(2) // fade in over 2 seconds ``` #### Inherited from `MusicallyAware(Sound).fadeIn` *** ### fadeOut() > **fadeOut**(`duration`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1225](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1225) Fade out the sound from its current gain to silence over `duration` seconds, then stop. If the sound is not playing, this is a no-op. Returns a Promise that resolves after the fade completes and stop() has been called. #### Parameters ##### duration `number` Fade-out duration in seconds #### Returns `Promise`<`void`> Promise that resolves when the fade and stop are complete #### Example ```typescript const sound = await createSound('music.mp3') await sound.play() await sound.fadeOut(2) // fade out over 2 seconds then stop ``` #### Inherited from `MusicallyAware(Sound).fadeOut` *** ### getAnalyzer() > **getAnalyzer**(): [`Analyzer`](Analyzer.md) | `null` Defined in: [packages/core/src/base-sound.ts:578](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L578) Get the currently attached analyzer, if any. #### Returns [`Analyzer`](Analyzer.md) | `null` The attached Analyzer instance, or null if none attached #### Inherited from `MusicallyAware(Sound).getAnalyzer` *** ### getEffects() > **getEffects**(): readonly [`Effect`](../interfaces/Effect.md)\[] Defined in: [packages/core/src/base-sound.ts:514](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L514) Get a readonly copy of the current effects array. #### Returns readonly [`Effect`](../interfaces/Effect.md)\[] Shallow copy of the effects array #### Inherited from `MusicallyAware(Sound).getEffects` *** ### getGainNode() > **getGainNode**(): `GainNode` Defined in: [packages/core/src/base-sound.ts:597](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L597) Get the GainNode for this sound. Provides controlled access to the underlying GainNode for advanced audio routing scenarios (e.g., crossfading between tracks). For simple volume control, use changeGainTo() or update('gain'). #### Returns `GainNode` The GainNode controlling this sound's volume #### Example ```typescript const node = sound.getGainNode() node.gain.linearRampToValueAtTime(0, ctx.currentTime + 2) ``` #### Inherited from `MusicallyAware(Sound).getGainNode` *** ### getPannerNode() > **getPannerNode**(): `StereoPannerNode` Defined in: [packages/core/src/base-sound.ts:610](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L610) Get the StereoPannerNode for this sound. Provides controlled access to the underlying StereoPannerNode for advanced audio routing scenarios (e.g., LFO modulation of pan position). For simple pan control, use changePanTo() or update('pan'). #### Returns `StereoPannerNode` The StereoPannerNode controlling this sound's pan position #### Inherited from `MusicallyAware(Sound).getPannerNode` *** ### later() > `protected` **later**(`fn`): `void` Defined in: [packages/core/src/base-sound.ts:1158](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1158) #### Parameters ##### fn () => `void` #### Returns `void` #### Inherited from `MusicallyAware(Sound).later` *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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"` #### 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 `MusicallyAware(Sound).off` *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"play"` | `"dispose"` | `"stop"` | `"end"` #### 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 `MusicallyAware(Sound).on` *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"play"` | `"dispose"` | `"stop"` | `"end"` #### 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 `MusicallyAware(Sound).once` *** ### onPlayRamp() > **onPlayRamp**(`type`, `rampType?`): `object` Defined in: [packages/core/src/base-sound.ts:794](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L794) Schedule a parameter ramp when play() is called. Use this for smooth transitions like vibrato, tremolo, or automation. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) The parameter to ramp ('gain' or 'pan') ##### rampType? `RampType` Type of ramp curve ('linear' or 'exponential') #### Returns `object` Fluent builder for setting start value, end value, and duration ##### from() > **from**: (`startValue`) => `object` ###### Parameters ###### startValue `number` ###### Returns `object` ###### to() > **to**: (`endValue`) => `object` ###### Parameters ###### endValue `number` ###### Returns `object` ###### in() > **in**: (`endTime`) => `void` ###### Parameters ###### endTime `number` ###### Returns `void` #### Remarks **Important: Schedules are consumed after each play() call.** The ramp set via onPlayRamp() is applied once when play() runs, then cleared. If you need the same ramp on every play, call onPlayRamp() again before each play() call. ```typescript // This fade-out only applies to the FIRST play: sound.onPlayRamp('gain', 'linear').from(1).to(0).in(2) sound.play() // fades out over 2 seconds sound.play() // no fade — schedule was consumed // To repeat, re-schedule before each play: function playWithFadeOut() { sound.onPlayRamp('gain', 'linear').from(1).to(0).in(2) sound.play() } ``` #### Example ```typescript // Fade out over 2 seconds sound.onPlayRamp('gain', 'linear').from(1).to(0).in(2) sound.play() // Pan sweep from left to right over 4 seconds sound.onPlayRamp('pan', 'linear').from(-1).to(1).in(4) sound.play() ``` #### Inherited from `MusicallyAware(Sound).onPlayRamp` *** ### onPlaySet() > **onPlaySet**(`type`): `object` Defined in: [packages/core/src/base-sound.ts:746](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L746) Schedule a parameter value to be set when play() is called. Use this for fade-ins, fade-outs, or precise parameter timing. The value is applied relative to when play() is called. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) The parameter to control ('gain' or 'pan') #### Returns `object` Fluent builder for setting value and timing ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### at() > **at**: (`time`) => `void` ###### Parameters ###### time `number` ###### Returns `void` ###### endingAt() > **endingAt**: (`time`, `rampType?`) => `void` ###### Parameters ###### time `number` ###### rampType? `RampType` ###### Returns `void` #### Remarks **Important: Schedules are consumed after each play() call.** The values set via onPlaySet() are applied once when play() runs, then cleared. If you need the same schedule on every play, call onPlaySet() again before each play() call. ```typescript // This fade-in only applies to the FIRST play: sound.onPlaySet('gain').to(0).at(0) sound.onPlaySet('gain').to(1).endingAt(0.5, 'linear') sound.play() // fades in sound.play() // no fade — schedule was consumed // To repeat the schedule, re-call onPlaySet() before each play(): function playWithFadeIn() { sound.onPlaySet('gain').to(0).at(0) sound.onPlaySet('gain').to(1).endingAt(0.5, 'linear') sound.play() } ``` #### Example ```typescript // Fade in: start at 0, ramp to 1 over 0.5 seconds sound.onPlaySet('gain').to(0).at(0) sound.onPlaySet('gain').to(1).endingAt(0.5, 'linear') sound.play() // Start panned left, move to center over 2 seconds sound.onPlaySet('pan').to(-1).at(0) sound.onPlaySet('pan').to(0).endingAt(2, 'linear') sound.play() ``` #### Inherited from `MusicallyAware(Sound).onPlaySet` *** ### play() > **play**(): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:819](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L819) Play the sound immediately. Resumes the AudioContext if suspended, sets up the audio source, and starts playback. For finite-duration sounds (Sound, Track), automatically schedules an 'end' event when playback completes. #### Returns `Promise`<`void`> Promise that resolves when playback begins #### Example ```typescript const sound = await createSound('click.mp3') await sound.play() ``` #### Inherited from `MusicallyAware(Sound).play` *** ### playAt() > **playAt**(`time`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:895](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L895) Play the audio source at a specific time. This is the underlying method for all play variants. Time is measured in seconds from when the AudioContext was created (audioContext.currentTime). #### Parameters ##### time `number` The AudioContext time when playback should start #### Returns `Promise`<`void`> #### Example ```typescript // Play immediately sound.playAt(audioContext.currentTime) // Play in 2 seconds sound.playAt(audioContext.currentTime + 2) // Sync multiple sounds const startTime = audioContext.currentTime + 0.1 sound1.playAt(startTime) sound2.playAt(startTime) ``` #### Inherited from `MusicallyAware(Sound).playAt` *** ### playFor() > **playFor**(`duration`): `void` Defined in: [packages/core/src/base-sound.ts:849](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L849) Play for a specific duration, then stop automatically. #### Parameters ##### duration `number` Seconds of playback before stopping #### Returns `void` #### Example ```typescript // Play for 3 seconds sound.playFor(3) ``` #### Inherited from `MusicallyAware(Sound).playFor` *** ### playIn() > **playIn**(`when`): `void` Defined in: [packages/core/src/base-sound.ts:834](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L834) Schedule playback after a delay. #### Parameters ##### when `number` Seconds from now until playback starts #### Returns `void` #### Example ```typescript // Play in 2 seconds sound.playIn(2) ``` #### Inherited from `MusicallyAware(Sound).playIn` *** ### playInAndStopAfter() > **playInAndStopAfter**(`playIn`, `stopAfter`): `void` Defined in: [packages/core/src/base-sound.ts:868](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L868) Play after a delay, then stop after a duration. Combines playIn() and stopIn() for precise timed playback. #### Parameters ##### playIn `number` Seconds from now until playback starts ##### stopAfter `number` Seconds of playback before stopping (from play start) #### Returns `void` #### Example ```typescript // Start in 1 second, play for 3 seconds sound.playInAndStopAfter(1, 3) ``` #### Inherited from `MusicallyAware(Sound).playInAndStopAfter` *** ### removeEffect() > **removeEffect**(`effect`): `this` Defined in: [packages/core/src/base-sound.ts:435](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L435) Remove an effect from the effect chain. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) The Effect instance to remove #### Returns `this` this for chaining #### Example ```ts sound.removeEffect(filter) ``` #### Inherited from `MusicallyAware(Sound).removeEffect` *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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"` ##### 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 `MusicallyAware(Sound).removeEventListener` #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 `MusicallyAware(Sound).removeEventListener` *** ### rewireEffects() > **rewireEffects**(): `void` Defined in: [packages/core/src/base-sound.ts:540](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L540) Re-wire the effect chain. Call this after toggling effect.bypass to update the audio routing. #### Returns `void` #### Inherited from `MusicallyAware(Sound).rewireEffects` *** ### setAnalyzer() > **setAnalyzer**(`analyzer`): `this` Defined in: [packages/core/src/base-sound.ts:567](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L567) Attach an analyzer to this sound for visualization. The analyzer is inserted at the end of the signal chain (after effects and panner, before destination), showing the fully processed signal. The analyzer is a passthrough node - audio flows through it unchanged while providing frequency and waveform data for visualization. #### Parameters ##### analyzer The Analyzer instance to attach, or null to detach [`Analyzer`](Analyzer.md) | `null` #### Returns `this` this for chaining #### Example ```ts const analyzer = createAnalyzer(audioContext, { fftSize: 2048 }) sound.setAnalyzer(analyzer) function draw() { const freqData = analyzer.getFrequencyData() // Draw frequency bars requestAnimationFrame(draw) } ``` #### Inherited from `MusicallyAware(Sound).setAnalyzer` *** ### setDestination() > **setDestination**(`node`): `this` Defined in: [packages/core/src/base-sound.ts:530](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L530) Set a custom destination for audio output instead of audioContext.destination. Useful for routing to sub-mixes, analyzers, or other processing chains. #### Parameters ##### node `AudioNode` The AudioNode to route output to #### Returns `this` this for chaining #### Example ```ts const analyzer = audioContext.createAnalyser() analyzer.connect(audioContext.destination) sound.setDestination(analyzer) ``` #### Inherited from `MusicallyAware(Sound).setDestination` *** ### setup() > `protected` **setup**(): `void` Defined in: [packages/core/src/sound.ts:103](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L103) Set up a new AudioBufferSourceNode for playback. Called automatically before each play() - creates fresh source nodes since AudioBufferSourceNode is single-use. #### Returns `void` #### Inherited from `MusicallyAware(Sound).setup` *** ### stop() > **stop**(): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1101](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1101) Stop the sound immediately. Emits a 'stop' event. Safe to call when not playing (no-op). #### Returns `Promise`<`void`> Promise that resolves when the stop is processed #### Example ```typescript await sound.stop() ``` #### Inherited from `MusicallyAware(Sound).stop` *** ### stopAt() > **stopAt**(`time`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1037](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1037) Stop the audio source at a specific time. This is the underlying method for all stop variants. Time is measured in seconds from when the AudioContext was created (audioContext.currentTime). #### Parameters ##### time `number` The AudioContext time when playback should stop #### Returns `Promise`<`void`> #### Example ```typescript // Stop immediately sound.stopAt(audioContext.currentTime) // Stop in 5 seconds sound.stopAt(audioContext.currentTime + 5) ``` #### Inherited from `MusicallyAware(Sound).stopAt` *** ### stopIn() > **stopIn**(`seconds`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1016](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1016) Stop the audio source after a delay. #### Parameters ##### seconds `number` Seconds from now until playback stops #### Returns `Promise`<`void`> #### Example ```typescript sound.play() // Stop after 5 seconds sound.stopIn(5) ``` #### Inherited from `MusicallyAware(Sound).stopIn` *** ### update() > **update**(`type`): `object` Defined in: [packages/core/src/base-sound.ts:632](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L632) Update an audio parameter immediately. Returns a fluent builder for setting the parameter value. Use `.to(value)` to set the value, then `.as(unit)` for unit interpretation. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) The parameter to update ('gain' or 'pan') #### Returns `object` Fluent builder for setting the value ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### as() > **as**: (`method`) => `void` ###### Parameters ###### method [`RatioType`](../type-aliases/RatioType.md) ###### Returns `void` #### Example ```typescript // Set gain to 50% sound.update('gain').to(0.5).as('ratio') // Set pan to left sound.update('pan').to(-1).as('ratio') ``` #### Inherited from `MusicallyAware(Sound).update` *** ### wireConnections() > `protected` **wireConnections**(): `void` Defined in: [packages/core/src/sound.ts:175](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L175) Wire audio source to the effect chain input. #### Returns `void` #### Inherited from `MusicallyAware(Sound).wireConnections` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Sampler.md' --- [EZ Web Audio](../index.md) / Sampler # Class: Sampler Defined in: [packages/core/src/sampler.ts:35](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L35) Round-robin playback of multiple sounds. Sampler holds multiple Sound instances and automatically alternates between them on each play() call. This creates realistic variation when playing repeated samples (e.g., multiple recordings of the same drum hit). ## Example ```typescript import { createSampler } from 'ez-web-audio' // Load multiple kick drum samples for variation const kick = await createSampler([ 'kick-1.mp3', 'kick-2.mp3', 'kick-3.mp3' ]) // Each play() uses the next sample in rotation kick.play() // plays kick-1 kick.play() // plays kick-2 kick.play() // plays kick-3 kick.play() // back to kick-1 ``` ## Extended by * [`BeatTrack`](BeatTrack.md) ## Constructors ### Constructor > **new Sampler**(`sounds`, `opts?`): `Sampler` Defined in: [packages/core/src/sampler.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L44) #### Parameters ##### sounds [`Playable`](../interfaces/Playable.md) & [`Connectable`](../interfaces/Connectable.md)\[] Sound instances to cycle through. Stored internally as a `Set`, so duplicate references silently collapse: `[kick1, kick1, kick2]` becomes a 2-item rotation (kick1, kick2), not the 3-hit weighting a caller passing the same instance twice would expect (R7 low). Pass distinct instances — e.g. separately-loaded copies of the same sample — if you want one sound to play more often than others in the rotation. ##### opts? [`SamplerOptions`](../interfaces/SamplerOptions.md) #### Returns `Sampler` ## Properties ### name > **name**: `string` Defined in: [packages/core/src/sampler.ts:53](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L53) Optional name to aid in identification. ## Accessors ### gain #### Get Signature > **get** **gain**(): `number` Defined in: [packages/core/src/sampler.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L75) Gain level applied to each sample when played. This value is applied to the underlying Sound on every play() call, overriding any per-sound gain customization. Validated the same way as [Sampler.changeGainTo](#changegainto) / `BaseSound.changeGainTo`: throws a [ValidationError](ValidationError.md) for negative values, warns on the console for values above 1 (R1#1 — previously this was a raw mutable field with no validation at all). Defaults to 1. ##### Returns `number` #### Set Signature > **set** **gain**(`value`): `void` Defined in: [packages/core/src/sampler.ts:79](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L79) ##### Parameters ###### value `number` ##### Returns `void` *** ### pan #### Get Signature > **get** **pan**(): `number` Defined in: [packages/core/src/sampler.ts:92](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L92) Stereo pan position applied to each sample (-1 = left, 0 = center, 1 = right). This value is applied to the underlying Sound on every play() call, overriding any per-sound pan customization. Validated the same way as [Sampler.changePanTo](#changepanto) / `BaseSound.changePanTo`: warns on the console for values outside \[-1, 1] (R1#1). Defaults to 0. ##### Returns `number` #### Set Signature > **set** **pan**(`value`): `void` Defined in: [packages/core/src/sampler.ts:96](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L96) ##### Parameters ###### value `number` ##### Returns `void` ## Methods ### changeGainTo() > **changeGainTo**(`value`): `this` Defined in: [packages/core/src/sampler.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L108) Set the gain level applied to each sample. Equivalent to `sampler.gain = value`, provided for API symmetry with `BaseSound.changeGainTo()` / `LayeredSound.changeGainTo()`. #### Parameters ##### value `number` The gain value (0-1 typical range) #### Returns `this` this for chaining *** ### changePanTo() > **changePanTo**(`value`): `this` Defined in: [packages/core/src/sampler.ts:120](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L120) Set the pan position applied to each sample. Equivalent to `sampler.pan = value`, provided for API symmetry with `BaseSound.changePanTo()` / `LayeredSound.changePanTo()`. #### Parameters ##### value `number` The pan value (-1 to 1) #### Returns `this` this for chaining *** ### getSounds() > **getSounds**(): readonly [`Playable`](../interfaces/Playable.md) & [`Connectable`](../interfaces/Connectable.md)\[] Defined in: [packages/core/src/sampler.ts:208](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L208) Get a readonly snapshot of the sampler's sounds. Returns a shallow copy as an array so callers can inspect which sounds are loaded without mutating the internal Set. #### Returns readonly [`Playable`](../interfaces/Playable.md) & [`Connectable`](../interfaces/Connectable.md)\[] Readonly array of sounds in the sampler #### Example ```typescript const sampler = await createSampler(['kick-1.mp3', 'kick-2.mp3']) const sounds = sampler.getSounds() console.log(sounds.length) // 2 ``` *** ### play() > **play**(`velocity`): `void` Defined in: [packages/core/src/sampler.ts:149](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L149) Play the next sound in the rotation immediately. #### Parameters ##### velocity `number` = `1` Gain multiplier (0–1) applied on top of the sampler's `gain`. Defaults to 1 (no attenuation). #### Returns `void` #### Example ```typescript sampler.play() // plays sound 1 sampler.play() // plays sound 2 sampler.play(0.4) // plays sound 3 at 40% of the sampler's gain (then wraps to 1) ``` *** ### playAt() > **playAt**(`time`, `velocity`): `void` Defined in: [packages/core/src/sampler.ts:186](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L186) Play the next sound at a specific AudioContext time. #### Parameters ##### time `number` The AudioContext.currentTime value when to play ##### velocity `number` = `1` Gain multiplier (0–1) applied on top of the sampler's `gain`. Defaults to 1 (no attenuation). #### Returns `void` #### Example ```typescript const startTime = audioContext.currentTime + 1 sampler.playAt(startTime) // plays next sound at exactly startTime sampler.playAt(startTime, 0.8) // plays next sound at exactly startTime at 80% gain ``` *** ### playIn() > **playIn**(`seconds`, `velocity`): `void` Defined in: [packages/core/src/sampler.ts:169](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L169) Play the next sound in the rotation after a delay. #### Parameters ##### seconds `number` Number of seconds from now to play the sound ##### velocity `number` = `1` Gain multiplier (0–1) applied on top of the sampler's `gain`. Defaults to 1 (no attenuation). #### Returns `void` #### Example ```typescript sampler.playIn(0.5) // plays next sound in 0.5 seconds sampler.playIn(0.5, 0.6) // plays next sound in 0.5 seconds at 60% gain ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Sequence.md' --- [EZ Web Audio](../index.md) / Sequence # Class: Sequence Defined in: [packages/core/src/sequence.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L70) Sequence schedules arbitrary callbacks at musical time positions tied to a Transport. Events are stored as beat positions (not seconds) so that live BPM changes automatically affect subsequent event scheduling without re-scheduling. Sequences follow the Transport lifecycle: they play when the Transport plays, pause when it pauses, and reset when it stops. ## Example ```typescript import { createTransport, createSequence, createSound } from 'ez-web-audio' const transport = await createTransport({ bpm: 120, timeSignature: [4, 4] }) const kick = await createSound('kick.mp3') const seq = createSequence(transport, { length: '4m' }) // Schedule kick on beat 1 of each bar seq.at('1:1:0', (time) => kick.playIn(time - ctx.currentTime)) seq.at('2:1:0', (time) => kick.playIn(time - ctx.currentTime)) seq.at('3:1:0', (time) => kick.playIn(time - ctx.currentTime)) seq.at('4:1:0', (time) => kick.playIn(time - ctx.currentTime)) transport.start() // Events fire at correct musical positions // Change BPM — events automatically adjust timing transport.bpm = 140 ``` ## Extends * [`TypedEventEmitter`](TypedEventEmitter.md)<[`SequenceEventMap`](../interfaces/SequenceEventMap.md)> ## Constructors ### Constructor > **new Sequence**(`transport`, `options`): `Sequence` Defined in: [packages/core/src/sequence.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L99) #### Parameters ##### transport [`Transport`](Transport.md) ##### options [`SequenceOptions`](../interfaces/SequenceOptions.md) #### Returns `Sequence` #### Overrides [`TypedEventEmitter`](TypedEventEmitter.md).[`constructor`](TypedEventEmitter.md#constructor) ## Accessors ### length #### Get Signature > **get** **length**(): `number` Defined in: [packages/core/src/sequence.ts:135](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L135) Length of the sequence in beats. ##### Returns `number` *** ### loop #### Get Signature > **get** **loop**(): `boolean` Defined in: [packages/core/src/sequence.ts:130](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L130) Whether this sequence loops. ##### Returns `boolean` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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`](TypedEventEmitter.md).[`_clearListeners`](TypedEventEmitter.md#clearlisteners) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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* `"event"` | `"loop"` ##### 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) *** ### at() > **at**(`time`, `callback`): `string` Defined in: [packages/core/src/sequence.ts:153](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L153) Schedule a callback at a musical time position. #### Parameters ##### time [`MusicalTimeNotation`](../type-aliases/MusicalTimeNotation.md) Musical time notation (e.g., '4n', '2:1:0') or beats ##### callback [`SequenceCallback`](../type-aliases/SequenceCallback.md) Function to call when the event fires #### Returns `string` Event ID for later removal via .remove() #### Example ```typescript const id = seq.at('4n', (time, pos) => { console.log(`Event at bar ${pos.bar}, beat ${pos.beat}`) }) ``` *** ### clear() > **clear**(): `void` Defined in: [packages/core/src/sequence.ts:196](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L196) Remove all scheduled events. #### Returns `void` *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/sequence.ts:427](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L427) Dispose the Sequence, unregistering from Transport and releasing resources. After disposal, the Sequence should not be used. #### Returns `void` *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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* `"event"` | `"loop"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail [`SequenceEventMap`](../interfaces/SequenceEventMap.md)\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`TypedEventEmitter`](TypedEventEmitter.md).[`emit`](TypedEventEmitter.md#emit) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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* `"event"` | `"loop"` #### 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`](TypedEventEmitter.md).[`off`](TypedEventEmitter.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"event"` | `"loop"` #### 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`](TypedEventEmitter.md).[`on`](TypedEventEmitter.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"event"` | `"loop"` #### 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`](TypedEventEmitter.md).[`once`](TypedEventEmitter.md#once) *** ### remove() > **remove**(`id`): `boolean` Defined in: [packages/core/src/sequence.ts:185](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L185) Remove a previously scheduled event by its ID. #### Parameters ##### id `string` Event ID returned by .at() #### Returns `boolean` true if the event was found and removed *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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* `"event"` | `"loop"` ##### 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Sound.md' --- [EZ Web Audio](../index.md) / Sound # Class: Sound\ Defined in: [packages/core/src/sound.ts:34](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L34) One-shot audio playback from an AudioBuffer. Sound is the core class for playing audio files. Each `.play()` call creates a new AudioBufferSourceNode, allowing simultaneous overlapping playback. Use [Track](Track.md) instead if you need pause/resume/seek functionality. Sound extends BaseSound and inherits all audio parameter controls (gain, pan) and the fluent API for scheduling parameter changes. ## Example ```typescript import { createSound } from 'ez-web-audio' const sound = await createSound('click.mp3') sound.play() // Adjust volume before playing sound.changeGainTo(0.5) sound.play() // Schedule a fade-in sound.onPlaySet('gain').to(0).endingAt(1, 'exponential') sound.play() ``` ## Extends * `BaseSound`<`TMap`> ## Extended by * [`Track`](Track.md) ## Type Parameters ### TMap `TMap` *extends* [`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md) & `{ [K in keyof TMap]: CustomEvent }` = [`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md) ## Constructors ### Constructor > **new Sound**<`TMap`>(`audioContext`, `audioBuffer`, `opts?`): `Sound`<`TMap`> Defined in: [packages/core/src/sound.ts:87](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L87) Create a Sound instance. Note: Use [createSound](../functions/createSound.md) factory function instead of calling this directly. #### Parameters ##### audioContext `AudioContext` The AudioContext to use for audio operations ##### audioBuffer `AudioBuffer` The decoded audio data to play ##### opts? `BaseSoundOptions` Optional configuration (name, setTimeout override) #### Returns `Sound`<`TMap`> #### Overrides `BaseSound.constructor` ## Properties ### \_analyzer > `protected` **\_analyzer**: [`Analyzer`](Analyzer.md) | `null` = `null` Defined in: [packages/core/src/base-sound.ts:161](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L161) #### Inherited from `BaseSound._analyzer` *** ### \_destination > `protected` **\_destination**: `AudioNode` Defined in: [packages/core/src/base-sound.ts:154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L154) #### Inherited from `BaseSound._destination` *** ### \_isPlaying > `protected` **\_isPlaying**: `boolean` = `false` Defined in: [packages/core/src/base-sound.ts:84](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L84) #### Inherited from `BaseSound._isPlaying` *** ### \_targetGain > `protected` **\_targetGain**: `number` = `1` Defined in: [packages/core/src/base-sound.ts:107](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L107) The user's intended gain level (0–1). Tracks the last value set via changeGainTo() / volume setter so that gain can be restored after a fadeOut() or Oscillator anti-click stop that ramps gainNode.gain to 0. #### Inherited from `BaseSound._targetGain` *** ### audioBuffer > `readonly` **audioBuffer**: `AudioBuffer` Defined in: [packages/core/src/sound.ts:87](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L87) The decoded audio data to play *** ### audioContext > `readonly` **audioContext**: `AudioContext` Defined in: [packages/core/src/base-sound.ts:218](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L218) #### Inherited from `BaseSound.audioContext` *** ### audioSourceNode > **audioSourceNode**: `AudioBufferSourceNode` Defined in: [packages/core/src/sound.ts:36](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L36) The underlying AudioBufferSourceNode that plays the audio. #### Overrides `BaseSound.audioSourceNode` *** ### clearTimeout() > `protected` **clearTimeout**: (`id`) => `void` Defined in: [packages/core/src/base-sound.ts:97](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L97) #### Parameters ##### id `number` #### Returns `void` #### Inherited from `BaseSound.clearTimeout` *** ### controller > `protected` **controller**: [`SoundController`](SoundController.md) Defined in: [packages/core/src/sound.ts:39](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L39) Controller for managing gain, pan, and other audio parameters. #### Overrides `BaseSound.controller` *** ### debug? > `optional` **debug**: `boolean` Defined in: [packages/core/src/base-sound.ts:216](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L216) #### Default ```ts undefined (follows global debug mode) ``` #### Example ```ts sound.debug = true // enable debug for this sound sound.debug = false // silence this sound even when global debug is on ``` #### Inherited from `BaseSound.debug` *** ### effectChainInput > `protected` **effectChainInput**: `GainNode` Defined in: [packages/core/src/base-sound.ts:147](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L147) #### Inherited from `BaseSound.effectChainInput` *** ### effects > `protected` **effects**: [`Effect`](../interfaces/Effect.md)\[] = `[]` Defined in: [packages/core/src/base-sound.ts:140](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L140) #### Inherited from `BaseSound.effects` *** ### gainNode > `protected` **gainNode**: `GainNode` Defined in: [packages/core/src/base-sound.ts:93](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L93) The GainNode controlling this sound's volume. For simple volume control, use changeGainTo() or update('gain'). For advanced routing, use getGainNode(). #### Inherited from `BaseSound.gainNode` *** ### name > **name**: `string` Defined in: [packages/core/src/base-sound.ts:202](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L202) #### Inherited from `BaseSound.name` *** ### pannerNode > `protected` **pannerNode**: `StereoPannerNode` Defined in: [packages/core/src/base-sound.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L95) #### Inherited from `BaseSound.pannerNode` *** ### setTimeout() > `protected` **setTimeout**: (`fn`, `delayMillis`) => `number` Defined in: [packages/core/src/base-sound.ts:96](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L96) #### Parameters ##### fn () => `void` ##### delayMillis `number` #### Returns `number` #### Inherited from `BaseSound.setTimeout` *** ### startedPlayingAt > `protected` **startedPlayingAt**: `number` = `0` Defined in: [packages/core/src/base-sound.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L99) #### Inherited from `BaseSound.startedPlayingAt` *** ### startOffset > `protected` **startOffset**: `number` = `0` Defined in: [packages/core/src/base-sound.ts:170](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L170) Offset in seconds from the beginning of the audio buffer where playback starts. Used internally by Track for seek/resume functionality. #### Default ```ts 0 ``` #### See https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/start #### Inherited from `BaseSound.startOffset` ## Accessors ### \_isLooping #### Get Signature > **get** `protected` **\_isLooping**(): `boolean` Defined in: [packages/core/src/sound.ts:74](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L74) Returns whether this sound is set to loop. Used by BaseSound.playAt() to skip the duration timeout when looping is enabled. ##### Returns `boolean` #### Overrides `BaseSound._isLooping` *** ### disposed #### Get Signature > **get** **disposed**(): `boolean` Defined in: [packages/core/src/base-sound.ts:1174](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1174) Whether this instance has been disposed. Once disposed, the instance cannot be used for playback. Create a new instance if you need to play the sound again. ##### Example ```typescript sound.dispose() console.log(sound.disposed) // true ``` ##### Returns `boolean` #### Inherited from `BaseSound.disposed` *** ### duration #### Get Signature > **get** **duration**(): [`TimeObject`](../interfaces/TimeObject.md) Defined in: [packages/core/src/sound.ts:208](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L208) Get the duration of the audio buffer. Returns a TimeObject with the duration in multiple formats: * `raw`: Duration in seconds * `string`: Formatted as 'MM:SS' * `pojo`: Object with `minutes` and `seconds` properties ##### Example ```typescript const sound = await createSound('song.mp3') console.log(sound.duration.raw) // 180.5 console.log(sound.duration.string) // '3:00' console.log(sound.duration.pojo) // { minutes: 3, seconds: 0 } ``` ##### Returns [`TimeObject`](../interfaces/TimeObject.md) #### Overrides `BaseSound.duration` *** ### durationRaw #### Get Signature > **get** **durationRaw**(): `number` Defined in: [packages/core/src/sound.ts:187](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L187) Get the duration of the audio buffer in seconds. Use this instead of `duration.raw` in performance-sensitive code paths to avoid allocating a TimeObject. ##### Returns `number` #### Overrides `BaseSound.durationRaw` *** ### isPlaying #### Get Signature > **get** **isPlaying**(): `boolean` Defined in: [packages/core/src/base-sound.ts:1115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1115) Whether the sound is currently playing. ##### Example ```typescript if (sound.isPlaying) { await sound.stop() } ``` ##### Returns `boolean` #### Inherited from `BaseSound.isPlaying` *** ### loop #### Get Signature > **get** **loop**(): `boolean` Defined in: [packages/core/src/sound.ts:61](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L61) Enable or disable native looping for this sound. When `loop` is true, the audio replays from the beginning when it reaches the end, providing gapless looping via the native `AudioBufferSourceNode.loop` property. Call `stop()` to end looped playback. ##### Example ```typescript const sfx = await createSound('rain.mp3') sfx.loop = true sfx.play() // plays continuously until stop() // Stop looped playback await sfx.stop() ``` ##### Returns `boolean` #### Set Signature > **set** **loop**(`value`): `void` Defined in: [packages/core/src/sound.ts:65](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L65) ##### Parameters ###### value `boolean` ##### Returns `void` *** ### percentGain #### Get Signature > **get** **percentGain**(): `number` Defined in: [packages/core/src/base-sound.ts:1127](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1127) Current gain as a percentage (0-100). ##### Example ```typescript console.log(`Volume: ${sound.percentGain}%`) // "Volume: 50%" ``` ##### Returns `number` #### Inherited from `BaseSound.percentGain` *** ### volume #### Get Signature > **get** **volume**(): `number` Defined in: [packages/core/src/base-sound.ts:1150](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1150) Alias for gain. Get/set the volume (0 = silent, 1 = full volume). Values above 1 amplify the signal and may cause distortion. The setter delegates to `changeGainTo()`, which throws if the value is negative and warns if it exceeds 1. Inherited by Sound, Track, and Oscillator. ##### Example ```typescript sound.volume = 0.5 // set to half volume console.log(sound.volume) // 0.5 // Works on all BaseSound subclasses const osc = await createOscillator() osc.volume = 0.8 ``` ##### Returns `number` #### Set Signature > **set** **volume**(`value`): `void` Defined in: [packages/core/src/base-sound.ts:1154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1154) ##### Parameters ###### value `number` ##### Returns `void` #### Inherited from `BaseSound.volume` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 `BaseSound._clearListeners` *** ### \_onPlaybackStarted() > `protected` **\_onPlaybackStarted**(): `void` Defined in: [packages/core/src/base-sound.ts:1000](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1000) Hook method called after playback starts. Override in subclasses to add behavior that runs for all play variants. #### Returns `void` #### Inherited from `BaseSound._onPlaybackStarted` *** ### addEffect() > **addEffect**(`effect`, `position?`): `this` Defined in: [packages/core/src/base-sound.ts:401](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L401) Add an effect to the effect chain. Effects persist across multiple play() calls. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) The Effect instance to add ##### position? `number` Optional index to insert at (defaults to end of chain) #### Returns `this` this for chaining #### Example ```ts const filter = createFilterEffect('lowpass', { frequency: 1000 }) sound.addEffect(filter) ``` #### Inherited from `BaseSound.addEffect` *** ### addEffects() > **addEffects**(`effects`, `position?`): `this` Defined in: [packages/core/src/base-sound.ts:471](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L471) Add multiple effects to the effect chain in one call. The chain is rewired only once after all effects are added, which is more efficient than calling addEffect() multiple times. #### Parameters ##### effects [`Effect`](../interfaces/Effect.md)\[] Array of Effect instances to add ##### position? `number` Optional index to insert at (defaults to end of chain) #### Returns `this` this for chaining #### Example ```typescript const filter = createFilterEffect('lowpass', { frequency: 800 }) const boost = createGainEffect(1.5) sound.addEffects([filter, boost]) ``` #### Inherited from `BaseSound.addEffects` *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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* `string` ##### 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 `BaseSound.addEventListener` #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 `BaseSound.addEventListener` *** ### changeGainTo() > **changeGainTo**(`value`): `this` Defined in: [packages/core/src/base-sound.ts:693](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L693) Set the gain (volume) immediately. Convenience method for `update('gain').to(value).as('ratio')`. #### Parameters ##### value `number` Gain from 0 (silent) to 1 (full volume) #### Returns `this` this for chaining #### Example ```typescript sound.changeGainTo(0.5) // Half volume sound.changeGainTo(0) // Muted sound.changeGainTo(1) // Full volume ``` #### Inherited from `BaseSound.changeGainTo` *** ### changePanTo() > **changePanTo**(`value`): `this` Defined in: [packages/core/src/base-sound.ts:670](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L670) Set the pan position immediately. Convenience method for `update('pan').to(value).as('ratio')`. #### Parameters ##### value `number` Pan position from -1 (left) to 1 (right), 0 is center #### Returns `this` this for chaining #### Example ```typescript sound.changePanTo(-1) // Hard left sound.changePanTo(0) // Center sound.changePanTo(1) // Hard right ``` #### Inherited from `BaseSound.changePanTo` *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/base-sound.ts:1270](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1270) Dispose this sound instance, releasing all audio resources. Disconnects all audio nodes, clears the effect chain, cancels pending timeouts, and marks the instance as unusable. After disposing, calling play() will throw an error. Dispose is idempotent — calling it multiple times is safe. After disposal, event listeners registered via `on()` / `addEventListener()` will no longer fire. To free listener references for garbage collection, call `off()` for each listener before calling `dispose()`. #### Returns `void` #### Example ```typescript const sound = await createSound('click.mp3') await sound.play() // When done with the sound sound.dispose() console.log(sound.disposed) // true // Attempting to play after dispose will throw // sound.play() // throws Error: Cannot play a disposed sound ``` #### Inherited from `BaseSound.dispose` *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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* `string` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail `TMap`\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from `BaseSound.emit` *** ### fadeIn() > **fadeIn**(`duration`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1202](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1202) Fade in the sound from silence to its current gain over `duration` seconds, then play. Schedules a gain ramp from 0 to the current gain value and calls play(). The current gain is restored after playback — use changeGainTo() to set a target volume before calling fadeIn(). #### Parameters ##### duration `number` Fade-in duration in seconds #### Returns `Promise`<`void`> Promise that resolves when playback begins #### Example ```typescript const sound = await createSound('music.mp3') await sound.fadeIn(2) // fade in over 2 seconds ``` #### Inherited from `BaseSound.fadeIn` *** ### fadeOut() > **fadeOut**(`duration`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1225](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1225) Fade out the sound from its current gain to silence over `duration` seconds, then stop. If the sound is not playing, this is a no-op. Returns a Promise that resolves after the fade completes and stop() has been called. #### Parameters ##### duration `number` Fade-out duration in seconds #### Returns `Promise`<`void`> Promise that resolves when the fade and stop are complete #### Example ```typescript const sound = await createSound('music.mp3') await sound.play() await sound.fadeOut(2) // fade out over 2 seconds then stop ``` #### Inherited from `BaseSound.fadeOut` *** ### getAnalyzer() > **getAnalyzer**(): [`Analyzer`](Analyzer.md) | `null` Defined in: [packages/core/src/base-sound.ts:578](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L578) Get the currently attached analyzer, if any. #### Returns [`Analyzer`](Analyzer.md) | `null` The attached Analyzer instance, or null if none attached #### Inherited from `BaseSound.getAnalyzer` *** ### getEffects() > **getEffects**(): readonly [`Effect`](../interfaces/Effect.md)\[] Defined in: [packages/core/src/base-sound.ts:514](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L514) Get a readonly copy of the current effects array. #### Returns readonly [`Effect`](../interfaces/Effect.md)\[] Shallow copy of the effects array #### Inherited from `BaseSound.getEffects` *** ### getGainNode() > **getGainNode**(): `GainNode` Defined in: [packages/core/src/base-sound.ts:597](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L597) Get the GainNode for this sound. Provides controlled access to the underlying GainNode for advanced audio routing scenarios (e.g., crossfading between tracks). For simple volume control, use changeGainTo() or update('gain'). #### Returns `GainNode` The GainNode controlling this sound's volume #### Example ```typescript const node = sound.getGainNode() node.gain.linearRampToValueAtTime(0, ctx.currentTime + 2) ``` #### Inherited from `BaseSound.getGainNode` *** ### getPannerNode() > **getPannerNode**(): `StereoPannerNode` Defined in: [packages/core/src/base-sound.ts:610](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L610) Get the StereoPannerNode for this sound. Provides controlled access to the underlying StereoPannerNode for advanced audio routing scenarios (e.g., LFO modulation of pan position). For simple pan control, use changePanTo() or update('pan'). #### Returns `StereoPannerNode` The StereoPannerNode controlling this sound's pan position #### Inherited from `BaseSound.getPannerNode` *** ### later() > `protected` **later**(`fn`): `void` Defined in: [packages/core/src/base-sound.ts:1158](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1158) #### Parameters ##### fn () => `void` #### Returns `void` #### Inherited from `BaseSound.later` *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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* `string` #### 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 `BaseSound.off` *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `string` #### 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 `BaseSound.on` *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `string` #### 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 `BaseSound.once` *** ### onPlayRamp() > **onPlayRamp**(`type`, `rampType?`): `object` Defined in: [packages/core/src/base-sound.ts:794](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L794) Schedule a parameter ramp when play() is called. Use this for smooth transitions like vibrato, tremolo, or automation. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) The parameter to ramp ('gain' or 'pan') ##### rampType? `RampType` Type of ramp curve ('linear' or 'exponential') #### Returns `object` Fluent builder for setting start value, end value, and duration ##### from() > **from**: (`startValue`) => `object` ###### Parameters ###### startValue `number` ###### Returns `object` ###### to() > **to**: (`endValue`) => `object` ###### Parameters ###### endValue `number` ###### Returns `object` ###### in() > **in**: (`endTime`) => `void` ###### Parameters ###### endTime `number` ###### Returns `void` #### Remarks **Important: Schedules are consumed after each play() call.** The ramp set via onPlayRamp() is applied once when play() runs, then cleared. If you need the same ramp on every play, call onPlayRamp() again before each play() call. ```typescript // This fade-out only applies to the FIRST play: sound.onPlayRamp('gain', 'linear').from(1).to(0).in(2) sound.play() // fades out over 2 seconds sound.play() // no fade — schedule was consumed // To repeat, re-schedule before each play: function playWithFadeOut() { sound.onPlayRamp('gain', 'linear').from(1).to(0).in(2) sound.play() } ``` #### Example ```typescript // Fade out over 2 seconds sound.onPlayRamp('gain', 'linear').from(1).to(0).in(2) sound.play() // Pan sweep from left to right over 4 seconds sound.onPlayRamp('pan', 'linear').from(-1).to(1).in(4) sound.play() ``` #### Inherited from `BaseSound.onPlayRamp` *** ### onPlaySet() > **onPlaySet**(`type`): `object` Defined in: [packages/core/src/base-sound.ts:746](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L746) Schedule a parameter value to be set when play() is called. Use this for fade-ins, fade-outs, or precise parameter timing. The value is applied relative to when play() is called. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) The parameter to control ('gain' or 'pan') #### Returns `object` Fluent builder for setting value and timing ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### at() > **at**: (`time`) => `void` ###### Parameters ###### time `number` ###### Returns `void` ###### endingAt() > **endingAt**: (`time`, `rampType?`) => `void` ###### Parameters ###### time `number` ###### rampType? `RampType` ###### Returns `void` #### Remarks **Important: Schedules are consumed after each play() call.** The values set via onPlaySet() are applied once when play() runs, then cleared. If you need the same schedule on every play, call onPlaySet() again before each play() call. ```typescript // This fade-in only applies to the FIRST play: sound.onPlaySet('gain').to(0).at(0) sound.onPlaySet('gain').to(1).endingAt(0.5, 'linear') sound.play() // fades in sound.play() // no fade — schedule was consumed // To repeat the schedule, re-call onPlaySet() before each play(): function playWithFadeIn() { sound.onPlaySet('gain').to(0).at(0) sound.onPlaySet('gain').to(1).endingAt(0.5, 'linear') sound.play() } ``` #### Example ```typescript // Fade in: start at 0, ramp to 1 over 0.5 seconds sound.onPlaySet('gain').to(0).at(0) sound.onPlaySet('gain').to(1).endingAt(0.5, 'linear') sound.play() // Start panned left, move to center over 2 seconds sound.onPlaySet('pan').to(-1).at(0) sound.onPlaySet('pan').to(0).endingAt(2, 'linear') sound.play() ``` #### Inherited from `BaseSound.onPlaySet` *** ### play() > **play**(): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:819](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L819) Play the sound immediately. Resumes the AudioContext if suspended, sets up the audio source, and starts playback. For finite-duration sounds (Sound, Track), automatically schedules an 'end' event when playback completes. #### Returns `Promise`<`void`> Promise that resolves when playback begins #### Example ```typescript const sound = await createSound('click.mp3') await sound.play() ``` #### Inherited from `BaseSound.play` *** ### playAt() > **playAt**(`time`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:895](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L895) Play the audio source at a specific time. This is the underlying method for all play variants. Time is measured in seconds from when the AudioContext was created (audioContext.currentTime). #### Parameters ##### time `number` The AudioContext time when playback should start #### Returns `Promise`<`void`> #### Example ```typescript // Play immediately sound.playAt(audioContext.currentTime) // Play in 2 seconds sound.playAt(audioContext.currentTime + 2) // Sync multiple sounds const startTime = audioContext.currentTime + 0.1 sound1.playAt(startTime) sound2.playAt(startTime) ``` #### Inherited from `BaseSound.playAt` *** ### playFor() > **playFor**(`duration`): `void` Defined in: [packages/core/src/base-sound.ts:849](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L849) Play for a specific duration, then stop automatically. #### Parameters ##### duration `number` Seconds of playback before stopping #### Returns `void` #### Example ```typescript // Play for 3 seconds sound.playFor(3) ``` #### Inherited from `BaseSound.playFor` *** ### playIn() > **playIn**(`when`): `void` Defined in: [packages/core/src/base-sound.ts:834](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L834) Schedule playback after a delay. #### Parameters ##### when `number` Seconds from now until playback starts #### Returns `void` #### Example ```typescript // Play in 2 seconds sound.playIn(2) ``` #### Inherited from `BaseSound.playIn` *** ### playInAndStopAfter() > **playInAndStopAfter**(`playIn`, `stopAfter`): `void` Defined in: [packages/core/src/base-sound.ts:868](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L868) Play after a delay, then stop after a duration. Combines playIn() and stopIn() for precise timed playback. #### Parameters ##### playIn `number` Seconds from now until playback starts ##### stopAfter `number` Seconds of playback before stopping (from play start) #### Returns `void` #### Example ```typescript // Start in 1 second, play for 3 seconds sound.playInAndStopAfter(1, 3) ``` #### Inherited from `BaseSound.playInAndStopAfter` *** ### removeEffect() > **removeEffect**(`effect`): `this` Defined in: [packages/core/src/base-sound.ts:435](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L435) Remove an effect from the effect chain. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) The Effect instance to remove #### Returns `this` this for chaining #### Example ```ts sound.removeEffect(filter) ``` #### Inherited from `BaseSound.removeEffect` *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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* `string` ##### 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 `BaseSound.removeEventListener` #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 `BaseSound.removeEventListener` *** ### rewireEffects() > **rewireEffects**(): `void` Defined in: [packages/core/src/base-sound.ts:540](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L540) Re-wire the effect chain. Call this after toggling effect.bypass to update the audio routing. #### Returns `void` #### Inherited from `BaseSound.rewireEffects` *** ### setAnalyzer() > **setAnalyzer**(`analyzer`): `this` Defined in: [packages/core/src/base-sound.ts:567](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L567) Attach an analyzer to this sound for visualization. The analyzer is inserted at the end of the signal chain (after effects and panner, before destination), showing the fully processed signal. The analyzer is a passthrough node - audio flows through it unchanged while providing frequency and waveform data for visualization. #### Parameters ##### analyzer The Analyzer instance to attach, or null to detach [`Analyzer`](Analyzer.md) | `null` #### Returns `this` this for chaining #### Example ```ts const analyzer = createAnalyzer(audioContext, { fftSize: 2048 }) sound.setAnalyzer(analyzer) function draw() { const freqData = analyzer.getFrequencyData() // Draw frequency bars requestAnimationFrame(draw) } ``` #### Inherited from `BaseSound.setAnalyzer` *** ### setDestination() > **setDestination**(`node`): `this` Defined in: [packages/core/src/base-sound.ts:530](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L530) Set a custom destination for audio output instead of audioContext.destination. Useful for routing to sub-mixes, analyzers, or other processing chains. #### Parameters ##### node `AudioNode` The AudioNode to route output to #### Returns `this` this for chaining #### Example ```ts const analyzer = audioContext.createAnalyser() analyzer.connect(audioContext.destination) sound.setDestination(analyzer) ``` #### Inherited from `BaseSound.setDestination` *** ### setup() > `protected` **setup**(): `void` Defined in: [packages/core/src/sound.ts:103](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L103) Set up a new AudioBufferSourceNode for playback. Called automatically before each play() - creates fresh source nodes since AudioBufferSourceNode is single-use. #### Returns `void` #### Overrides `BaseSound.setup` *** ### stop() > **stop**(): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1101](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1101) Stop the sound immediately. Emits a 'stop' event. Safe to call when not playing (no-op). #### Returns `Promise`<`void`> Promise that resolves when the stop is processed #### Example ```typescript await sound.stop() ``` #### Inherited from `BaseSound.stop` *** ### stopAt() > **stopAt**(`time`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1037](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1037) Stop the audio source at a specific time. This is the underlying method for all stop variants. Time is measured in seconds from when the AudioContext was created (audioContext.currentTime). #### Parameters ##### time `number` The AudioContext time when playback should stop #### Returns `Promise`<`void`> #### Example ```typescript // Stop immediately sound.stopAt(audioContext.currentTime) // Stop in 5 seconds sound.stopAt(audioContext.currentTime + 5) ``` #### Inherited from `BaseSound.stopAt` *** ### stopIn() > **stopIn**(`seconds`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1016](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1016) Stop the audio source after a delay. #### Parameters ##### seconds `number` Seconds from now until playback stops #### Returns `Promise`<`void`> #### Example ```typescript sound.play() // Stop after 5 seconds sound.stopIn(5) ``` #### Inherited from `BaseSound.stopIn` *** ### update() > **update**(`type`): `object` Defined in: [packages/core/src/base-sound.ts:632](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L632) Update an audio parameter immediately. Returns a fluent builder for setting the parameter value. Use `.to(value)` to set the value, then `.as(unit)` for unit interpretation. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) The parameter to update ('gain' or 'pan') #### Returns `object` Fluent builder for setting the value ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### as() > **as**: (`method`) => `void` ###### Parameters ###### method [`RatioType`](../type-aliases/RatioType.md) ###### Returns `void` #### Example ```typescript // Set gain to 50% sound.update('gain').to(0.5).as('ratio') // Set pan to left sound.update('pan').to(-1).as('ratio') ``` #### Inherited from `BaseSound.update` *** ### wireConnections() > `protected` **wireConnections**(): `void` Defined in: [packages/core/src/sound.ts:175](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L175) Wire audio source to the effect chain input. #### Returns `void` #### Overrides `BaseSound.wireConnections` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/SoundController.md' --- [EZ Web Audio](../index.md) / SoundController # Class: SoundController Defined in: [packages/core/src/controllers/sound-controller.ts:9](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/sound-controller.ts#L9) Parameter controller for Sound and Track instances. Manages gain and detune parameters. Created automatically by Sound's constructor. ## Extends * `BaseParamController` ## Implements * `ParamController` ## Constructors ### Constructor > **new SoundController**(`bufferSourceNode`, `gainNode`, `pannerNode`): `SoundController` Defined in: [packages/core/src/controllers/sound-controller.ts:10](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/sound-controller.ts#L10) #### Parameters ##### bufferSourceNode `AudioBufferSourceNode` ##### gainNode `GainNode` ##### pannerNode `StereoPannerNode` #### Returns `SoundController` #### Overrides `BaseParamController.constructor` ## Properties ### audioSource > `protected` **audioSource**: `AudioSource` Defined in: [packages/core/src/controllers/base-param-controller.ts:110](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L110) #### Inherited from `BaseParamController.audioSource` *** ### exponentialValues > `protected` **exponentialValues**: `ValueAtTime`\[] = `[]` Defined in: [packages/core/src/controllers/base-param-controller.ts:114](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L114) #### Inherited from `BaseParamController.exponentialValues` *** ### gainNode > `protected` **gainNode**: `GainNode` Defined in: [packages/core/src/controllers/sound-controller.ts:10](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/sound-controller.ts#L10) #### Inherited from `BaseParamController.gainNode` *** ### linearValues > `protected` **linearValues**: `ValueAtTime`\[] = `[]` Defined in: [packages/core/src/controllers/base-param-controller.ts:115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L115) #### Inherited from `BaseParamController.linearValues` *** ### pannerNode > `protected` **pannerNode**: `StereoPannerNode` Defined in: [packages/core/src/controllers/sound-controller.ts:10](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/sound-controller.ts#L10) #### Inherited from `BaseParamController.pannerNode` *** ### startingValues > `protected` **startingValues**: `ParamValue`\[] = `[]` Defined in: [packages/core/src/controllers/base-param-controller.ts:112](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L112) #### Inherited from `BaseParamController.startingValues` *** ### valuesAtTime > `protected` **valuesAtTime**: `ValueAtTime`\[] = `[]` Defined in: [packages/core/src/controllers/base-param-controller.ts:113](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L113) #### Inherited from `BaseParamController.valuesAtTime` ## Accessors ### gain #### Get Signature > **get** **gain**(): `number` Defined in: [packages/core/src/controllers/base-param-controller.ts:120](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L120) Current gain value (0-1 typical range). ##### Returns `number` #### Set Signature > **set** **gain**(`value`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:124](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L124) ##### Parameters ###### value `number` ##### Returns `void` #### Implementation of `ParamController.gain` #### Inherited from `BaseParamController.gain` *** ### pan #### Get Signature > **get** **pan**(): `number` Defined in: [packages/core/src/controllers/base-param-controller.ts:128](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L128) ##### Returns `number` #### Set Signature > **set** **pan**(`value`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:132](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L132) ##### Parameters ###### value `number` ##### Returns `void` #### Implementation of `ParamController.pan` #### Inherited from `BaseParamController.pan` ## Methods ### \_update() > `protected` **\_update**(`type`, `value`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:178](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L178) #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) ##### value `number` #### Returns `void` #### Inherited from `BaseParamController._update` *** ### applyRampToParam() > `protected` **applyRampToParam**(`param`, `value`, `time`, `rampType`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:453](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L453) Apply a ramp to an AudioParam using the specified ramp type. Shared helper to eliminate duplication between controllers. #### Parameters ##### param `AudioParam` The AudioParam to apply the ramp to ##### value `number` The target value ##### time `number` The absolute audio context time to reach the target value ##### rampType 'exponential' or 'linear' ramp `"linear"` | `"exponential"` #### Returns `void` #### Inherited from `BaseParamController.applyRampToParam` *** ### applyRampValues() > `protected` **applyRampValues**(`values`, `currentTime`, `rampType`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:367](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L367) Apply a list of ramped parameter values relative to the current time. Uses resolveParam() to map control types to AudioParams. #### Parameters ##### values `ValueAtTime`\[] Array of ValueAtTime to apply ##### currentTime `number` The audio context current time ##### rampType The ramp curve type ('exponential' or 'linear') `"linear"` | `"exponential"` #### Returns `void` #### Inherited from `BaseParamController.applyRampValues` *** ### applyValues() > `protected` **applyValues**(`values`, `currentTime`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:352](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L352) Apply a list of immediate parameter values at the current time. Uses resolveParam() to map control types to AudioParams. #### Parameters ##### values `ParamValue`\[] Array of ParamValue to apply ##### currentTime `number` The audio context current time #### Returns `void` #### Inherited from `BaseParamController.applyValues` *** ### clampPendingZeroBeforeExponentialRamp() > `protected` **clampPendingZeroBeforeExponentialRamp**(): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:392](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L392) Clamp any zero-valued startingValues/valuesAtTime entries that share a control type with a pending exponential ramp, to SAFE\_NEAR\_ZERO. An exponentialRampToValueAtTime whose previous scheduled value is exactly 0 holds the param at 0 for the entire ramp duration and then jumps to the target right at the end — an audible pop. onPlayRamp()'s `.from()` already guards this (see SAFE\_NEAR\_ZERO above), but the documented two-call fade-in idiom — `onPlaySet('gain').to(0).at(0)` followed by `onPlaySet('gain').to(1).endingAt(1)` (default exponential) — pushes a raw, unclamped 0 via `.at()` and reproduces the same pop. Call this before applying startingValues/valuesAtTime so every path into an exponential ramp is protected consistently. #### Returns `void` #### See onPlaySet #### Inherited from `BaseParamController.clampPendingZeroBeforeExponentialRamp` *** ### clearScheduledValues() > `protected` **clearScheduledValues**(): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:419](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L419) Clear all scheduled parameter arrays after they have been applied. Called at the end of setValuesAtTimes() in each controller subclass to ensure that parameter schedules set via onPlaySet() and onPlayRamp() are consumed once per play() call. If the same schedule is needed on every play, call onPlaySet() or onPlayRamp() before each play() call. #### Returns `void` #### See * onPlaySet * onPlayRamp #### Inherited from `BaseParamController.clearScheduledValues` *** ### onPlayRamp() > **onPlayRamp**(`type`, `rampType?`): `object` Defined in: [packages/core/src/controllers/base-param-controller.ts:293](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L293) Schedule a parameter ramp when play() is called. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The parameter to ramp ##### rampType? `RampType` Ramp curve type ('linear' or 'exponential') #### Returns `object` Fluent builder: `.from(startValue).to(endValue).in(duration)` ##### from() > **from**: (`startValue`) => `object` ###### Parameters ###### startValue `number` ###### Returns `object` ###### to() > **to**: (`endValue`) => `object` ###### Parameters ###### endValue `number` ###### Returns `object` ###### in() > **in**: (`endTime`) => `void` ###### Parameters ###### endTime `number` ###### Returns `void` #### Example ```typescript // Fade out over 2 seconds controller.onPlayRamp('gain', 'linear').from(1).to(0).in(2) ``` #### Implementation of `ParamController.onPlayRamp` #### Inherited from `BaseParamController.onPlayRamp` *** ### onPlaySet() > **onPlaySet**(`type`): `object` Defined in: [packages/core/src/controllers/base-param-controller.ts:256](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L256) Schedule a parameter value to be set when play() is called. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The parameter to schedule #### Returns `object` Fluent builder: `.to(value).at(time)` or `.to(value).endingAt(time, rampType)` ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### at() > **at**: (`time`) => `void` ###### Parameters ###### time `number` ###### Returns `void` ###### endingAt() > **endingAt**: (`time`, `rampType?`) => `void` ###### Parameters ###### time `number` ###### rampType? `RampType` ###### Returns `void` #### Remarks Schedules set via onPlaySet() are consumed (cleared) after each play() call by [clearScheduledValues](OscillatorController.md#clearscheduledvalues). Re-schedule before each play() if you need repeated automation. Accumulate-vs-replace semantics differ by call shape: `.to(value)` alone (no `.at()`/`.endingAt()`) REPLACES any prior un-timed schedule for the same type — calling it twice before play() keeps only the latest value. `.at(time)` and `.endingAt(time)` ACCUMULATE instead — each call pushes a new timed/ramp event, so calling either twice before play() applies both the stale and the new event on the next play(). Call [onPlaySet](#onplayset) again per-type only once per play() cycle unless you intend to schedule multiple timed events for that type. #### Example ```typescript // Set gain to 0 at start, ramp to 1 over 0.5s controller.onPlaySet('gain').to(0).at(0) controller.onPlaySet('gain').to(1).endingAt(0.5, 'linear') ``` #### Implementation of `ParamController.onPlaySet` #### Inherited from `BaseParamController.onPlaySet` *** ### resolveParam() > `protected` **resolveParam**(`type`): `AudioParam` Defined in: [packages/core/src/controllers/base-param-controller.ts:331](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L331) Resolve a control type to its corresponding AudioParam. Override in subclasses to add type-specific params (e.g., frequency for Oscillator). #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The control type to resolve #### Returns `AudioParam` The AudioParam corresponding to the control type #### Throws if the type is not supported by this controller #### Inherited from `BaseParamController.resolveParam` *** ### setValuesAtTimes() > **setValuesAtTimes**(): `void` Defined in: [packages/core/src/controllers/sound-controller.ts:29](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/sound-controller.ts#L29) Apply all scheduled parameter values to the current audio nodes. Called by Sound.setup() before each play(). #### Returns `void` #### Implementation of `ParamController.setValuesAtTimes` *** ### transferDetuneTo() > `protected` **transferDetuneTo**(`newSource`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:172](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L172) Carry the current detune value over to a replacement audio source node. Unlike gain/pan (which live on the persistent gain/panner nodes and therefore survive node replacement automatically), detune lives on the audioSource itself — the single-use OscillatorNode/AudioBufferSourceNode that gets swapped out on every play(). Without this, `update('detune')` would silently revert to 0 the next time the source node is replaced. Mirrors the copy-before-swap pattern used by updateGainNode/updatePannerNode. Call this BEFORE reassigning `this.audioSource` to the new node. #### Parameters ##### newSource `AudioSource` The replacement audio source node #### Returns `void` #### Inherited from `BaseParamController.transferDetuneTo` *** ### update() > **update**(`type`): `object` Defined in: [packages/core/src/controllers/base-param-controller.ts:217](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L217) Update an audio parameter immediately. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) The parameter to update ('gain', 'pan', 'detune', or 'frequency') #### Returns `object` Fluent builder: `.to(value).as(unit)` ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### as() > **as**: (`method`) => `void` ###### Parameters ###### method [`RatioType`](../type-aliases/RatioType.md) ###### Returns `void` #### Example ```typescript controller.update('gain').to(0.5).as('ratio') controller.update('gain').to(50).as('percent') ``` #### Implementation of `ParamController.update` #### Inherited from `BaseParamController.update` *** ### updateAudioSource() > **updateAudioSource**(`source`): `void` Defined in: [packages/core/src/controllers/sound-controller.ts:19](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/sound-controller.ts#L19) Replace the audio source node (called on each play() since AudioBufferSourceNode is single-use). #### Parameters ##### source The new AudioBufferSourceNode `OscillatorNode` | `AudioBufferSourceNode` #### Returns `void` #### Implementation of `ParamController.updateAudioSource` *** ### updateGainNode() > **updateGainNode**(`gainNode`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:142](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L142) Replace the gain node, preserving the current gain value. Called by Oscillator.setup() when recreating nodes for each play(). #### Parameters ##### gainNode `GainNode` The new GainNode to use #### Returns `void` #### Implementation of `ParamController.updateGainNode` #### Inherited from `BaseParamController.updateGainNode` *** ### updatePannerNode() > **updatePannerNode**(`pannerNode`): `void` Defined in: [packages/core/src/controllers/base-param-controller.ts:153](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L153) Replace the panner node, preserving the current pan value. Called by Oscillator.setup() when recreating nodes for each play(). #### Parameters ##### pannerNode `StereoPannerNode` The new StereoPannerNode to use #### Returns `void` #### Implementation of `ParamController.updatePannerNode` #### Inherited from `BaseParamController.updatePannerNode` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Track.md' --- [EZ Web Audio](../index.md) / Track # Class: Track Defined in: [packages/core/src/track.ts:38](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/track.ts#L38) Music track with position tracking, pause/resume, and seeking. Track extends [Sound](Sound.md) with playback position awareness. Use Track for longer audio files where users need to pause, resume, or seek to specific positions. Each Track can only play once at a time (unlike Sound which allows overlap). ## Example ```typescript import { createTrack } from 'ez-web-audio' const track = await createTrack('song.mp3') track.play() // Pause and resume track.pause() track.resume() // Seek to 30 seconds track.seek(30).as('seconds') // Get current position console.log(track.position) // { raw: 30.5, string: '0:30', pojo: { minutes: 0, seconds: 30 } } // Check playback state console.log(track.isPlaying) // true console.log(track.percentPlayed) // 15.5 ``` ## Extends * [`Sound`](Sound.md)<[`TrackEventMap`](../interfaces/TrackEventMap.md)> ## Constructors ### Constructor > **new Track**(`audioContext`, `audioBuffer`, `opts?`): `Track` Defined in: [packages/core/src/sound.ts:87](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L87) Create a Sound instance. Note: Use [createSound](../functions/createSound.md) factory function instead of calling this directly. #### Parameters ##### audioContext `AudioContext` The AudioContext to use for audio operations ##### audioBuffer `AudioBuffer` The decoded audio data to play ##### opts? `BaseSoundOptions` Optional configuration (name, setTimeout override) #### Returns `Track` #### Inherited from [`Sound`](Sound.md).[`constructor`](Sound.md#constructor) ## Properties ### \_analyzer > `protected` **\_analyzer**: [`Analyzer`](Analyzer.md) | `null` = `null` Defined in: [packages/core/src/base-sound.ts:161](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L161) #### Inherited from [`Sound`](Sound.md).[`_analyzer`](Sound.md#analyzer) *** ### \_destination > `protected` **\_destination**: `AudioNode` Defined in: [packages/core/src/base-sound.ts:154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L154) #### Inherited from [`Sound`](Sound.md).[`_destination`](Sound.md#destination) *** ### \_isPlaying > `protected` **\_isPlaying**: `boolean` = `false` Defined in: [packages/core/src/base-sound.ts:84](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L84) #### Inherited from [`Sound`](Sound.md).[`_isPlaying`](Sound.md#isplaying) *** ### \_targetGain > `protected` **\_targetGain**: `number` = `1` Defined in: [packages/core/src/base-sound.ts:107](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L107) The user's intended gain level (0–1). Tracks the last value set via changeGainTo() / volume setter so that gain can be restored after a fadeOut() or Oscillator anti-click stop that ramps gainNode.gain to 0. #### Inherited from [`Sound`](Sound.md).[`_targetGain`](Sound.md#targetgain) *** ### audioBuffer > `readonly` **audioBuffer**: `AudioBuffer` Defined in: [packages/core/src/sound.ts:87](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L87) The decoded audio data to play #### Inherited from [`Sound`](Sound.md).[`audioBuffer`](Sound.md#audiobuffer) *** ### audioContext > `readonly` **audioContext**: `AudioContext` Defined in: [packages/core/src/base-sound.ts:218](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L218) #### Inherited from [`Sound`](Sound.md).[`audioContext`](Sound.md#audiocontext) *** ### audioSourceNode > **audioSourceNode**: `AudioBufferSourceNode` Defined in: [packages/core/src/sound.ts:36](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L36) The underlying AudioBufferSourceNode that plays the audio. #### Inherited from [`Sound`](Sound.md).[`audioSourceNode`](Sound.md#audiosourcenode) *** ### clearTimeout() > `protected` **clearTimeout**: (`id`) => `void` Defined in: [packages/core/src/base-sound.ts:97](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L97) #### Parameters ##### id `number` #### Returns `void` #### Inherited from [`Sound`](Sound.md).[`clearTimeout`](Sound.md#cleartimeout) *** ### controller > `protected` **controller**: [`SoundController`](SoundController.md) Defined in: [packages/core/src/sound.ts:39](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L39) Controller for managing gain, pan, and other audio parameters. #### Inherited from [`Sound`](Sound.md).[`controller`](Sound.md#controller) *** ### debug? > `optional` **debug**: `boolean` Defined in: [packages/core/src/base-sound.ts:216](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L216) #### Default ```ts undefined (follows global debug mode) ``` #### Example ```ts sound.debug = true // enable debug for this sound sound.debug = false // silence this sound even when global debug is on ``` #### Inherited from [`Sound`](Sound.md).[`debug`](Sound.md#debug) *** ### effectChainInput > `protected` **effectChainInput**: `GainNode` Defined in: [packages/core/src/base-sound.ts:147](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L147) #### Inherited from [`Sound`](Sound.md).[`effectChainInput`](Sound.md#effectchaininput) *** ### effects > `protected` **effects**: [`Effect`](../interfaces/Effect.md)\[] = `[]` Defined in: [packages/core/src/base-sound.ts:140](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L140) #### Inherited from [`Sound`](Sound.md).[`effects`](Sound.md#effects) *** ### gainNode > `protected` **gainNode**: `GainNode` Defined in: [packages/core/src/base-sound.ts:93](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L93) The GainNode controlling this sound's volume. For simple volume control, use changeGainTo() or update('gain'). For advanced routing, use getGainNode(). #### Inherited from [`Sound`](Sound.md).[`gainNode`](Sound.md#gainnode) *** ### name > **name**: `string` Defined in: [packages/core/src/base-sound.ts:202](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L202) #### Inherited from [`Sound`](Sound.md).[`name`](Sound.md#name) *** ### pannerNode > `protected` **pannerNode**: `StereoPannerNode` Defined in: [packages/core/src/base-sound.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L95) #### Inherited from [`Sound`](Sound.md).[`pannerNode`](Sound.md#pannernode) *** ### setTimeout() > `protected` **setTimeout**: (`fn`, `delayMillis`) => `number` Defined in: [packages/core/src/base-sound.ts:96](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L96) #### Parameters ##### fn () => `void` ##### delayMillis `number` #### Returns `number` #### Inherited from [`Sound`](Sound.md).[`setTimeout`](Sound.md#settimeout) *** ### startedPlayingAt > `protected` **startedPlayingAt**: `number` = `0` Defined in: [packages/core/src/base-sound.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L99) #### Inherited from [`Sound`](Sound.md).[`startedPlayingAt`](Sound.md#startedplayingat) *** ### startOffset > `protected` **startOffset**: `number` = `0` Defined in: [packages/core/src/base-sound.ts:170](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L170) Offset in seconds from the beginning of the audio buffer where playback starts. Used internally by Track for seek/resume functionality. #### Default ```ts 0 ``` #### See https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/start #### Inherited from [`Sound`](Sound.md).[`startOffset`](Sound.md#startoffset) ## Accessors ### \_isLooping #### Get Signature > **get** `protected` **\_isLooping**(): `boolean` Defined in: [packages/core/src/sound.ts:74](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L74) Returns whether this sound is set to loop. Used by BaseSound.playAt() to skip the duration timeout when looping is enabled. ##### Returns `boolean` #### Inherited from [`Sound`](Sound.md).[`_isLooping`](Sound.md#islooping) *** ### disposed #### Get Signature > **get** **disposed**(): `boolean` Defined in: [packages/core/src/base-sound.ts:1174](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1174) Whether this instance has been disposed. Once disposed, the instance cannot be used for playback. Create a new instance if you need to play the sound again. ##### Example ```typescript sound.dispose() console.log(sound.disposed) // true ``` ##### Returns `boolean` #### Inherited from [`Sound`](Sound.md).[`disposed`](Sound.md#disposed) *** ### duration #### Get Signature > **get** **duration**(): [`TimeObject`](../interfaces/TimeObject.md) Defined in: [packages/core/src/sound.ts:208](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L208) Get the duration of the audio buffer. Returns a TimeObject with the duration in multiple formats: * `raw`: Duration in seconds * `string`: Formatted as 'MM:SS' * `pojo`: Object with `minutes` and `seconds` properties ##### Example ```typescript const sound = await createSound('song.mp3') console.log(sound.duration.raw) // 180.5 console.log(sound.duration.string) // '3:00' console.log(sound.duration.pojo) // { minutes: 3, seconds: 0 } ``` ##### Returns [`TimeObject`](../interfaces/TimeObject.md) #### Inherited from [`Sound`](Sound.md).[`duration`](Sound.md#duration) *** ### durationRaw #### Get Signature > **get** **durationRaw**(): `number` Defined in: [packages/core/src/sound.ts:187](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L187) Get the duration of the audio buffer in seconds. Use this instead of `duration.raw` in performance-sensitive code paths to avoid allocating a TimeObject. ##### Returns `number` #### Inherited from [`Sound`](Sound.md).[`durationRaw`](Sound.md#durationraw) *** ### isPlaying #### Get Signature > **get** **isPlaying**(): `boolean` Defined in: [packages/core/src/base-sound.ts:1115](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1115) Whether the sound is currently playing. ##### Example ```typescript if (sound.isPlaying) { await sound.stop() } ``` ##### Returns `boolean` #### Inherited from [`Sound`](Sound.md).[`isPlaying`](Sound.md#isplaying) *** ### loop #### Get Signature > **get** **loop**(): `boolean` Defined in: [packages/core/src/sound.ts:61](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L61) Enable or disable native looping for this sound. When `loop` is true, the audio replays from the beginning when it reaches the end, providing gapless looping via the native `AudioBufferSourceNode.loop` property. Call `stop()` to end looped playback. ##### Example ```typescript const sfx = await createSound('rain.mp3') sfx.loop = true sfx.play() // plays continuously until stop() // Stop looped playback await sfx.stop() ``` ##### Returns `boolean` #### Set Signature > **set** **loop**(`value`): `void` Defined in: [packages/core/src/sound.ts:65](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L65) ##### Parameters ###### value `boolean` ##### Returns `void` #### Inherited from [`Sound`](Sound.md).[`loop`](Sound.md#loop) *** ### percentGain #### Get Signature > **get** **percentGain**(): `number` Defined in: [packages/core/src/base-sound.ts:1127](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1127) Current gain as a percentage (0-100). ##### Example ```typescript console.log(`Volume: ${sound.percentGain}%`) // "Volume: 50%" ``` ##### Returns `number` #### Inherited from [`Sound`](Sound.md).[`percentGain`](Sound.md#percentgain) *** ### percentPlayed #### Get Signature > **get** **percentPlayed**(): `number` Defined in: [packages/core/src/track.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/track.ts#L95) Get the current playback position as a percentage (0-100). ##### Example ```typescript const track = await createTrack('song.mp3') track.play() // Use for progress bar progressBar.style.width = `${track.percentPlayed}%` ``` ##### Returns `number` *** ### position #### Get Signature > **get** **position**(): [`TimeObject`](../interfaces/TimeObject.md) Defined in: [packages/core/src/track.ts:72](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/track.ts#L72) Get the current playback position. Returns a TimeObject with the position in multiple formats: * `raw`: Position in seconds * `string`: Formatted as 'MM:SS' * `pojo`: Object with `minutes` and `seconds` properties ##### Example ```typescript const track = await createTrack('song.mp3') track.play() // After playing for a while console.log(track.position.raw) // 65.5 console.log(track.position.string) // '1:05' console.log(track.position.pojo) // { minutes: 1, seconds: 5 } ``` ##### Returns [`TimeObject`](../interfaces/TimeObject.md) *** ### volume #### Get Signature > **get** **volume**(): `number` Defined in: [packages/core/src/base-sound.ts:1150](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1150) Alias for gain. Get/set the volume (0 = silent, 1 = full volume). Values above 1 amplify the signal and may cause distortion. The setter delegates to `changeGainTo()`, which throws if the value is negative and warns if it exceeds 1. Inherited by Sound, Track, and Oscillator. ##### Example ```typescript sound.volume = 0.5 // set to half volume console.log(sound.volume) // 0.5 // Works on all BaseSound subclasses const osc = await createOscillator() osc.volume = 0.8 ``` ##### Returns `number` #### Set Signature > **set** **volume**(`value`): `void` Defined in: [packages/core/src/base-sound.ts:1154](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1154) ##### Parameters ###### value `number` ##### Returns `void` #### Inherited from [`Sound`](Sound.md).[`volume`](Sound.md#volume) ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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 [`Sound`](Sound.md).[`_clearListeners`](Sound.md#clearlisteners) *** ### \_onPlaybackStarted() > `protected` **\_onPlaybackStarted**(): `void` Defined in: [packages/core/src/track.ts:108](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/track.ts#L108) Hook called after playback starts. Sets up the onended handler for natural completion detection and starts position tracking. Fixes H-2: emits 'end' event on natural completion instead of swallowing it. #### Returns `void` #### Overrides [`Sound`](Sound.md).[`_onPlaybackStarted`](Sound.md#onplaybackstarted) *** ### addEffect() > **addEffect**(`effect`, `position?`): `this` Defined in: [packages/core/src/base-sound.ts:401](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L401) Add an effect to the effect chain. Effects persist across multiple play() calls. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) The Effect instance to add ##### position? `number` Optional index to insert at (defaults to end of chain) #### Returns `this` this for chaining #### Example ```ts const filter = createFilterEffect('lowpass', { frequency: 1000 }) sound.addEffect(filter) ``` #### Inherited from [`Sound`](Sound.md).[`addEffect`](Sound.md#addeffect) *** ### addEffects() > **addEffects**(`effects`, `position?`): `this` Defined in: [packages/core/src/base-sound.ts:471](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L471) Add multiple effects to the effect chain in one call. The chain is rewired only once after all effects are added, which is more efficient than calling addEffect() multiple times. #### Parameters ##### effects [`Effect`](../interfaces/Effect.md)\[] Array of Effect instances to add ##### position? `number` Optional index to insert at (defaults to end of chain) #### Returns `this` this for chaining #### Example ```typescript const filter = createFilterEffect('lowpass', { frequency: 800 }) const boost = createGainEffect(1.5) sound.addEffects([filter, boost]) ``` #### Inherited from [`Sound`](Sound.md).[`addEffects`](Sound.md#addeffects) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` | `"end"` | `"seek"` ##### 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 [`Sound`](Sound.md).[`addEventListener`](Sound.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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 [`Sound`](Sound.md).[`addEventListener`](Sound.md#addeventlistener) *** ### changeGainTo() > **changeGainTo**(`value`): `this` Defined in: [packages/core/src/base-sound.ts:693](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L693) Set the gain (volume) immediately. Convenience method for `update('gain').to(value).as('ratio')`. #### Parameters ##### value `number` Gain from 0 (silent) to 1 (full volume) #### Returns `this` this for chaining #### Example ```typescript sound.changeGainTo(0.5) // Half volume sound.changeGainTo(0) // Muted sound.changeGainTo(1) // Full volume ``` #### Inherited from [`Sound`](Sound.md).[`changeGainTo`](Sound.md#changegainto) *** ### changePanTo() > **changePanTo**(`value`): `this` Defined in: [packages/core/src/base-sound.ts:670](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L670) Set the pan position immediately. Convenience method for `update('pan').to(value).as('ratio')`. #### Parameters ##### value `number` Pan position from -1 (left) to 1 (right), 0 is center #### Returns `this` this for chaining #### Example ```typescript sound.changePanTo(-1) // Hard left sound.changePanTo(0) // Center sound.changePanTo(1) // Hard right ``` #### Inherited from [`Sound`](Sound.md).[`changePanTo`](Sound.md#changepanto) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/base-sound.ts:1270](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1270) Dispose this sound instance, releasing all audio resources. Disconnects all audio nodes, clears the effect chain, cancels pending timeouts, and marks the instance as unusable. After disposing, calling play() will throw an error. Dispose is idempotent — calling it multiple times is safe. After disposal, event listeners registered via `on()` / `addEventListener()` will no longer fire. To free listener references for garbage collection, call `off()` for each listener before calling `dispose()`. #### Returns `void` #### Example ```typescript const sound = await createSound('click.mp3') await sound.play() // When done with the sound sound.dispose() console.log(sound.disposed) // true // Attempting to play after dispose will throw // sound.play() // throws Error: Cannot play a disposed sound ``` #### Inherited from [`Sound`](Sound.md).[`dispose`](Sound.md#dispose) *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` | `"end"` | `"seek"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail [`TrackEventMap`](../interfaces/TrackEventMap.md)\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`Sound`](Sound.md).[`emit`](Sound.md#emit) *** ### fadeIn() > **fadeIn**(`duration`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1202](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1202) Fade in the sound from silence to its current gain over `duration` seconds, then play. Schedules a gain ramp from 0 to the current gain value and calls play(). The current gain is restored after playback — use changeGainTo() to set a target volume before calling fadeIn(). #### Parameters ##### duration `number` Fade-in duration in seconds #### Returns `Promise`<`void`> Promise that resolves when playback begins #### Example ```typescript const sound = await createSound('music.mp3') await sound.fadeIn(2) // fade in over 2 seconds ``` #### Inherited from [`Sound`](Sound.md).[`fadeIn`](Sound.md#fadein) *** ### fadeOut() > **fadeOut**(`duration`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1225](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1225) Fade out the sound from its current gain to silence over `duration` seconds, then stop. If the sound is not playing, this is a no-op. Returns a Promise that resolves after the fade completes and stop() has been called. #### Parameters ##### duration `number` Fade-out duration in seconds #### Returns `Promise`<`void`> Promise that resolves when the fade and stop are complete #### Example ```typescript const sound = await createSound('music.mp3') await sound.play() await sound.fadeOut(2) // fade out over 2 seconds then stop ``` #### Inherited from [`Sound`](Sound.md).[`fadeOut`](Sound.md#fadeout) *** ### getAnalyzer() > **getAnalyzer**(): [`Analyzer`](Analyzer.md) | `null` Defined in: [packages/core/src/base-sound.ts:578](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L578) Get the currently attached analyzer, if any. #### Returns [`Analyzer`](Analyzer.md) | `null` The attached Analyzer instance, or null if none attached #### Inherited from [`Sound`](Sound.md).[`getAnalyzer`](Sound.md#getanalyzer) *** ### getEffects() > **getEffects**(): readonly [`Effect`](../interfaces/Effect.md)\[] Defined in: [packages/core/src/base-sound.ts:514](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L514) Get a readonly copy of the current effects array. #### Returns readonly [`Effect`](../interfaces/Effect.md)\[] Shallow copy of the effects array #### Inherited from [`Sound`](Sound.md).[`getEffects`](Sound.md#geteffects) *** ### getGainNode() > **getGainNode**(): `GainNode` Defined in: [packages/core/src/base-sound.ts:597](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L597) Get the GainNode for this sound. Provides controlled access to the underlying GainNode for advanced audio routing scenarios (e.g., crossfading between tracks). For simple volume control, use changeGainTo() or update('gain'). #### Returns `GainNode` The GainNode controlling this sound's volume #### Example ```typescript const node = sound.getGainNode() node.gain.linearRampToValueAtTime(0, ctx.currentTime + 2) ``` #### Inherited from [`Sound`](Sound.md).[`getGainNode`](Sound.md#getgainnode) *** ### getPannerNode() > **getPannerNode**(): `StereoPannerNode` Defined in: [packages/core/src/base-sound.ts:610](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L610) Get the StereoPannerNode for this sound. Provides controlled access to the underlying StereoPannerNode for advanced audio routing scenarios (e.g., LFO modulation of pan position). For simple pan control, use changePanTo() or update('pan'). #### Returns `StereoPannerNode` The StereoPannerNode controlling this sound's pan position #### Inherited from [`Sound`](Sound.md).[`getPannerNode`](Sound.md#getpannernode) *** ### later() > `protected` **later**(`fn`): `void` Defined in: [packages/core/src/base-sound.ts:1158](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1158) #### Parameters ##### fn () => `void` #### Returns `void` #### Inherited from [`Sound`](Sound.md).[`later`](Sound.md#later) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` | `"end"` | `"seek"` #### 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 [`Sound`](Sound.md).[`off`](Sound.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` | `"end"` | `"seek"` #### 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 [`Sound`](Sound.md).[`on`](Sound.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` | `"end"` | `"seek"` #### 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 [`Sound`](Sound.md).[`once`](Sound.md#once) *** ### onPlayRamp() > **onPlayRamp**(`type`, `rampType?`): `object` Defined in: [packages/core/src/base-sound.ts:794](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L794) Schedule a parameter ramp when play() is called. Use this for smooth transitions like vibrato, tremolo, or automation. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) The parameter to ramp ('gain' or 'pan') ##### rampType? `RampType` Type of ramp curve ('linear' or 'exponential') #### Returns `object` Fluent builder for setting start value, end value, and duration ##### from() > **from**: (`startValue`) => `object` ###### Parameters ###### startValue `number` ###### Returns `object` ###### to() > **to**: (`endValue`) => `object` ###### Parameters ###### endValue `number` ###### Returns `object` ###### in() > **in**: (`endTime`) => `void` ###### Parameters ###### endTime `number` ###### Returns `void` #### Remarks **Important: Schedules are consumed after each play() call.** The ramp set via onPlayRamp() is applied once when play() runs, then cleared. If you need the same ramp on every play, call onPlayRamp() again before each play() call. ```typescript // This fade-out only applies to the FIRST play: sound.onPlayRamp('gain', 'linear').from(1).to(0).in(2) sound.play() // fades out over 2 seconds sound.play() // no fade — schedule was consumed // To repeat, re-schedule before each play: function playWithFadeOut() { sound.onPlayRamp('gain', 'linear').from(1).to(0).in(2) sound.play() } ``` #### Example ```typescript // Fade out over 2 seconds sound.onPlayRamp('gain', 'linear').from(1).to(0).in(2) sound.play() // Pan sweep from left to right over 4 seconds sound.onPlayRamp('pan', 'linear').from(-1).to(1).in(4) sound.play() ``` #### Inherited from [`Sound`](Sound.md).[`onPlayRamp`](Sound.md#onplayramp) *** ### onPlaySet() > **onPlaySet**(`type`): `object` Defined in: [packages/core/src/base-sound.ts:746](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L746) Schedule a parameter value to be set when play() is called. Use this for fade-ins, fade-outs, or precise parameter timing. The value is applied relative to when play() is called. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) The parameter to control ('gain' or 'pan') #### Returns `object` Fluent builder for setting value and timing ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### at() > **at**: (`time`) => `void` ###### Parameters ###### time `number` ###### Returns `void` ###### endingAt() > **endingAt**: (`time`, `rampType?`) => `void` ###### Parameters ###### time `number` ###### rampType? `RampType` ###### Returns `void` #### Remarks **Important: Schedules are consumed after each play() call.** The values set via onPlaySet() are applied once when play() runs, then cleared. If you need the same schedule on every play, call onPlaySet() again before each play() call. ```typescript // This fade-in only applies to the FIRST play: sound.onPlaySet('gain').to(0).at(0) sound.onPlaySet('gain').to(1).endingAt(0.5, 'linear') sound.play() // fades in sound.play() // no fade — schedule was consumed // To repeat the schedule, re-call onPlaySet() before each play(): function playWithFadeIn() { sound.onPlaySet('gain').to(0).at(0) sound.onPlaySet('gain').to(1).endingAt(0.5, 'linear') sound.play() } ``` #### Example ```typescript // Fade in: start at 0, ramp to 1 over 0.5 seconds sound.onPlaySet('gain').to(0).at(0) sound.onPlaySet('gain').to(1).endingAt(0.5, 'linear') sound.play() // Start panned left, move to center over 2 seconds sound.onPlaySet('pan').to(-1).at(0) sound.onPlaySet('pan').to(0).endingAt(2, 'linear') sound.play() ``` #### Inherited from [`Sound`](Sound.md).[`onPlaySet`](Sound.md#onplayset) *** ### pause() > **pause**(): `void` Defined in: [packages/core/src/track.ts:179](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/track.ts#L179) Pause playback at the current position. The track remembers its position so it can be resumed later. Emits a 'pause' event with the current playback position. #### Returns `void` #### Example ```typescript const track = await createTrack('song.mp3') track.play() // Pause after 5 seconds setTimeout(() => track.pause(), 5000) // Listen for pause events track.on('pause', (e) => { console.log('Paused at', e.detail.position) }) ``` *** ### play() > **play**(): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:819](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L819) Play the sound immediately. Resumes the AudioContext if suspended, sets up the audio source, and starts playback. For finite-duration sounds (Sound, Track), automatically schedules an 'end' event when playback completes. #### Returns `Promise`<`void`> Promise that resolves when playback begins #### Example ```typescript const sound = await createSound('click.mp3') await sound.play() ``` #### Inherited from [`Sound`](Sound.md).[`play`](Sound.md#play) *** ### playAt() > **playAt**(`time`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:895](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L895) Play the audio source at a specific time. This is the underlying method for all play variants. Time is measured in seconds from when the AudioContext was created (audioContext.currentTime). #### Parameters ##### time `number` The AudioContext time when playback should start #### Returns `Promise`<`void`> #### Example ```typescript // Play immediately sound.playAt(audioContext.currentTime) // Play in 2 seconds sound.playAt(audioContext.currentTime + 2) // Sync multiple sounds const startTime = audioContext.currentTime + 0.1 sound1.playAt(startTime) sound2.playAt(startTime) ``` #### Inherited from [`Sound`](Sound.md).[`playAt`](Sound.md#playat) *** ### playFor() > **playFor**(`duration`): `void` Defined in: [packages/core/src/base-sound.ts:849](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L849) Play for a specific duration, then stop automatically. #### Parameters ##### duration `number` Seconds of playback before stopping #### Returns `void` #### Example ```typescript // Play for 3 seconds sound.playFor(3) ``` #### Inherited from [`Sound`](Sound.md).[`playFor`](Sound.md#playfor) *** ### playIn() > **playIn**(`when`): `void` Defined in: [packages/core/src/base-sound.ts:834](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L834) Schedule playback after a delay. #### Parameters ##### when `number` Seconds from now until playback starts #### Returns `void` #### Example ```typescript // Play in 2 seconds sound.playIn(2) ``` #### Inherited from [`Sound`](Sound.md).[`playIn`](Sound.md#playin) *** ### playInAndStopAfter() > **playInAndStopAfter**(`playIn`, `stopAfter`): `void` Defined in: [packages/core/src/base-sound.ts:868](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L868) Play after a delay, then stop after a duration. Combines playIn() and stopIn() for precise timed playback. #### Parameters ##### playIn `number` Seconds from now until playback starts ##### stopAfter `number` Seconds of playback before stopping (from play start) #### Returns `void` #### Example ```typescript // Start in 1 second, play for 3 seconds sound.playInAndStopAfter(1, 3) ``` #### Inherited from [`Sound`](Sound.md).[`playInAndStopAfter`](Sound.md#playinandstopafter) *** ### removeEffect() > **removeEffect**(`effect`): `this` Defined in: [packages/core/src/base-sound.ts:435](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L435) Remove an effect from the effect chain. #### Parameters ##### effect [`Effect`](../interfaces/Effect.md) The Effect instance to remove #### Returns `this` this for chaining #### Example ```ts sound.removeEffect(filter) ``` #### Inherited from [`Sound`](Sound.md).[`removeEffect`](Sound.md#removeeffect) *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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* `"pause"` | `"play"` | `"dispose"` | `"stop"` | `"resume"` | `"end"` | `"seek"` ##### 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 [`Sound`](Sound.md).[`removeEventListener`](Sound.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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 [`Sound`](Sound.md).[`removeEventListener`](Sound.md#removeeventlistener) *** ### resume() > **resume**(): `void` Defined in: [packages/core/src/track.ts:227](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/track.ts#L227) Resume playback from the paused position. If the track was paused, resumes from where it left off. Emits a 'resume' event with the playback position. Fixes H-4: now works correctly even when paused at position 0. #### Returns `void` #### Example ```typescript const track = await createTrack('song.mp3') track.play() track.pause() // Resume later track.resume() // Listen for resume events track.on('resume', (e) => { console.log('Resumed at', e.detail.position) }) ``` *** ### rewireEffects() > **rewireEffects**(): `void` Defined in: [packages/core/src/base-sound.ts:540](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L540) Re-wire the effect chain. Call this after toggling effect.bypass to update the audio routing. #### Returns `void` #### Inherited from [`Sound`](Sound.md).[`rewireEffects`](Sound.md#rewireeffects) *** ### seek() > **seek**(`amount`): `object` Defined in: [packages/core/src/track.ts:340](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/track.ts#L340) Seek to a specific position in the track. Returns a fluent builder with `.as(type)` to specify the unit of the value: * `'seconds'`: Absolute position in seconds * `'percent'`: Percentage of total duration (0-100) * `'ratio'`: Ratio of total duration (0-1) * `'inverseRatio'`: Distance from end as ratio (0 = end, 1 = start) Emits a 'seek' event with the new and previous positions. Fixes C-4: awaits stop() before setting new offset to prevent race condition. #### Parameters ##### amount `number` The position value (meaning depends on the `.as()` type) #### Returns `object` Fluent builder with `.as(type)` method returning `Promise` ##### as() > **as**: (`type`) => `Promise`<`void`> ###### Parameters ###### type [`SeekType`](../type-aliases/SeekType.md) ###### Returns `Promise`<`void`> #### Example ```typescript const track = await createTrack('song.mp3') // For a track with 100 second duration, all of these seek to 90 seconds: track.seek(90).as('seconds') track.seek(90).as('percent') track.seek(0.9).as('ratio') track.seek(0.1).as('inverseRatio') // Listen for seek events track.on('seek', (e) => { console.log('Seeked from', e.detail.previousPosition, 'to', e.detail.position) }) ``` *** ### setAnalyzer() > **setAnalyzer**(`analyzer`): `this` Defined in: [packages/core/src/base-sound.ts:567](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L567) Attach an analyzer to this sound for visualization. The analyzer is inserted at the end of the signal chain (after effects and panner, before destination), showing the fully processed signal. The analyzer is a passthrough node - audio flows through it unchanged while providing frequency and waveform data for visualization. #### Parameters ##### analyzer The Analyzer instance to attach, or null to detach [`Analyzer`](Analyzer.md) | `null` #### Returns `this` this for chaining #### Example ```ts const analyzer = createAnalyzer(audioContext, { fftSize: 2048 }) sound.setAnalyzer(analyzer) function draw() { const freqData = analyzer.getFrequencyData() // Draw frequency bars requestAnimationFrame(draw) } ``` #### Inherited from [`Sound`](Sound.md).[`setAnalyzer`](Sound.md#setanalyzer) *** ### setDestination() > **setDestination**(`node`): `this` Defined in: [packages/core/src/base-sound.ts:530](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L530) Set a custom destination for audio output instead of audioContext.destination. Useful for routing to sub-mixes, analyzers, or other processing chains. #### Parameters ##### node `AudioNode` The AudioNode to route output to #### Returns `this` this for chaining #### Example ```ts const analyzer = audioContext.createAnalyser() analyzer.connect(audioContext.destination) sound.setDestination(analyzer) ``` #### Inherited from [`Sound`](Sound.md).[`setDestination`](Sound.md#setdestination) *** ### setup() > `protected` **setup**(): `void` Defined in: [packages/core/src/sound.ts:103](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L103) Set up a new AudioBufferSourceNode for playback. Called automatically before each play() - creates fresh source nodes since AudioBufferSourceNode is single-use. #### Returns `void` #### Inherited from [`Sound`](Sound.md).[`setup`](Sound.md#setup) *** ### stop() > **stop**(): `Promise`<`void`> Defined in: [packages/core/src/track.ts:263](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/track.ts#L263) Stop playback and reset position to the beginning. Unlike pause(), stop() resets the playback position to 0. The next play() will start from the beginning. #### Returns `Promise`<`void`> #### Example ```typescript const track = await createTrack('song.mp3') track.play() // Stop and reset await track.stop() console.log(track.position.raw) // 0 ``` #### Overrides [`Sound`](Sound.md).[`stop`](Sound.md#stop) *** ### stopAt() > **stopAt**(`time`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1037](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1037) Stop the audio source at a specific time. This is the underlying method for all stop variants. Time is measured in seconds from when the AudioContext was created (audioContext.currentTime). #### Parameters ##### time `number` The AudioContext time when playback should stop #### Returns `Promise`<`void`> #### Example ```typescript // Stop immediately sound.stopAt(audioContext.currentTime) // Stop in 5 seconds sound.stopAt(audioContext.currentTime + 5) ``` #### Inherited from [`Sound`](Sound.md).[`stopAt`](Sound.md#stopat) *** ### stopIn() > **stopIn**(`seconds`): `Promise`<`void`> Defined in: [packages/core/src/base-sound.ts:1016](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L1016) Stop the audio source after a delay. #### Parameters ##### seconds `number` Seconds from now until playback stops #### Returns `Promise`<`void`> #### Example ```typescript sound.play() // Stop after 5 seconds sound.stopIn(5) ``` #### Inherited from [`Sound`](Sound.md).[`stopIn`](Sound.md#stopin) *** ### update() > **update**(`type`): `object` Defined in: [packages/core/src/base-sound.ts:632](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L632) Update an audio parameter immediately. Returns a fluent builder for setting the parameter value. Use `.to(value)` to set the value, then `.as(unit)` for unit interpretation. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) The parameter to update ('gain' or 'pan') #### Returns `object` Fluent builder for setting the value ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### as() > **as**: (`method`) => `void` ###### Parameters ###### method [`RatioType`](../type-aliases/RatioType.md) ###### Returns `void` #### Example ```typescript // Set gain to 50% sound.update('gain').to(0.5).as('ratio') // Set pan to left sound.update('pan').to(-1).as('ratio') ``` #### Inherited from [`Sound`](Sound.md).[`update`](Sound.md#update) *** ### wireConnections() > `protected` **wireConnections**(): `void` Defined in: [packages/core/src/sound.ts:175](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sound.ts#L175) Wire audio source to the effect chain input. #### Returns `void` #### Inherited from [`Sound`](Sound.md).[`wireConnections`](Sound.md#wireconnections) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/Transport.md' --- [EZ Web Audio](../index.md) / Transport # Class: Transport Defined in: [packages/core/src/transport.ts:101](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L101) Global Transport clock for multi-track synchronization. Transport provides a Worker-backed clock that multiple BeatTracks can lock to, enabling perfect multi-track synchronization that survives background tab throttling. It manages tempo, time signature, position tracking, and lifecycle events. ## Example ```typescript import { createTransport, createBeatTrack } from 'ez-web-audio' const transport = await createTransport({ bpm: 120, timeSignature: [4, 4] }) const kick = await createBeatTrack(['kick.mp3'], { numBeats: 4 }) const hihat = await createBeatTrack(['hihat.mp3'], { numBeats: 16 }) kick.setPattern([1, 0, 1, 0]) hihat.setPattern([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) kick.syncTo(transport, { noteType: 1/4 }) hihat.syncTo(transport, { noteType: 1/16 }) transport.on('tick', (e) => { console.log(`Position: ${e.detail.bar}:${e.detail.beat}:${e.detail.tick}`) }) transport.start() ``` ## Extends * [`TypedEventEmitter`](TypedEventEmitter.md)<[`TransportEventMap`](../interfaces/TransportEventMap.md)> ## Constructors ### Constructor > **new Transport**(`audioContext`, `options`): `Transport` Defined in: [packages/core/src/transport.ts:146](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L146) #### Parameters ##### audioContext `AudioContext` ##### options [`TransportOptions`](../interfaces/TransportOptions.md) #### Returns `Transport` #### Overrides [`TypedEventEmitter`](TypedEventEmitter.md).[`constructor`](TypedEventEmitter.md#constructor) ## Accessors ### bpm #### Get Signature > **get** **bpm**(): `number` Defined in: [packages/core/src/transport.ts:162](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L162) Current tempo in beats per minute. Can be changed during playback. ##### Returns `number` #### Set Signature > **set** **bpm**(`value`): `void` Defined in: [packages/core/src/transport.ts:166](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L166) ##### Parameters ###### value `number` ##### Returns `void` *** ### loop #### Get Signature > **get** **loop**(): `boolean` Defined in: [packages/core/src/transport.ts:279](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L279) Whether the transport loops over the region \[loopStart, loopEnd). When enabled, position and synced-track pattern indices wrap at loopEnd and a 'loop' event fires on each wrap. Sequences are not remapped — they loop at their own length; give them the same length as the loop region for lockstep. ##### Default false The \[loopStart, loopEnd) region is only validated (loopEnd must be greater than loopStart) at the moment playback actually (re)starts — see [start](#start). Setting `loop`, `loopStart`, or `loopEnd` to an invalid combination while the Transport is already playing does NOT throw immediately: playback silently continues without looping (as if `loop` were false) until the next `start()`/resume, at which point an invalid region throws. ##### Example ```typescript transport.loopEnd = '2m' transport.loop = true ``` ##### Returns `boolean` #### Set Signature > **set** **loop**(`value`): `void` Defined in: [packages/core/src/transport.ts:283](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L283) ##### Parameters ###### value `boolean` ##### Returns `void` *** ### loopEnd #### Get Signature > **get** **loopEnd**(): `number` Defined in: [packages/core/src/transport.ts:318](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L318) Loop region end. Set with musical notation (`'2m'`) or a numeric beat count; reads back as beats. Must be greater than [loopStart](#loopstart) when [loop](#loop) is enabled — validated only at the next [start](#start) call, not immediately on assignment; see [loop](#loop) for what happens to an invalid region set while already playing. ##### Example ```typescript transport.loopEnd = '2m' // 8 beats in 4/4 ``` ##### Returns `number` #### Set Signature > **set** **loopEnd**(`value`): `void` Defined in: [packages/core/src/transport.ts:322](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L322) ##### Parameters ###### value [`MusicalTimeNotation`](../type-aliases/MusicalTimeNotation.md) ##### Returns `void` *** ### loopStart #### Get Signature > **get** **loopStart**(): `number` Defined in: [packages/core/src/transport.ts:298](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L298) Loop region start. Set with musical notation (`'1m'`, `'2:1:0'`) or a numeric beat count; reads back as beats. Not validated against [loopEnd](#loopend) until the next [start](#start) call — see [loop](#loop). ##### Default ```ts ``` ##### Example ```typescript transport.loopStart = '1m' // 4 beats in 4/4 ``` ##### Returns `number` #### Set Signature > **set** **loopStart**(`value`): `void` Defined in: [packages/core/src/transport.ts:302](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L302) ##### Parameters ###### value [`MusicalTimeNotation`](../type-aliases/MusicalTimeNotation.md) ##### Returns `void` *** ### paused #### Get Signature > **get** **paused**(): `boolean` Defined in: [packages/core/src/transport.ts:194](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L194) Whether the Transport is currently paused. ##### Returns `boolean` *** ### playing #### Get Signature > **get** **playing**(): `boolean` Defined in: [packages/core/src/transport.ts:189](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L189) Whether the Transport is currently playing. ##### Returns `boolean` *** ### position #### Get Signature > **get** **position**(): [`TransportPosition`](../interfaces/TransportPosition.md) Defined in: [packages/core/src/transport.ts:184](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L184) Current playback position in musical time. ##### Returns [`TransportPosition`](../interfaces/TransportPosition.md) *** ### swing #### Get Signature > **get** **swing**(): `number` Defined in: [packages/core/src/transport.ts:225](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L225) Swing amount (0–1). 0 = straight; 1 = full triplet feel — every other swing subdivision is delayed to the triplet position. Applies to synced BeatTrack beats and Sequence events that land exactly on an odd subdivision; position/tick events are unaffected. Live-changeable — safe to set while the Transport is playing. For synced Sequences, event positions are sequence-relative rather than transport-absolute. Swing parity is only guaranteed correct when the Sequence starts on a bar boundary and its length is a whole, even number of subdivisions — true for all `Nm` (measure) lengths. Default: 0 ##### Example ```typescript transport.swing = 0.55 // MPC-style swing feel ``` ##### Returns `number` #### Set Signature > **set** **swing**(`value`): `void` Defined in: [packages/core/src/transport.ts:229](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L229) ##### Parameters ###### value `number` ##### Returns `void` *** ### swingSubdivision #### Get Signature > **get** **swingSubdivision**(): `number` Defined in: [packages/core/src/transport.ts:247](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L247) The subdivision swing applies to: `1/8` (eighth notes) or `1/16` (sixteenth notes, MPC-style). Default: 1/16 ##### Example ```typescript transport.swingSubdivision = 1 / 8 ``` ##### Returns `number` #### Set Signature > **set** **swingSubdivision**(`value`): `void` Defined in: [packages/core/src/transport.ts:251](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L251) ##### Parameters ###### value `number` ##### Returns `void` *** ### ticksPerBeat #### Get Signature > **get** **ticksPerBeat**(): `number` Defined in: [packages/core/src/transport.ts:179](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L179) Number of ticks per beat (position resolution). ##### Returns `number` *** ### timeSignature #### Get Signature > **get** **timeSignature**(): \[`number`, `number`] Defined in: [packages/core/src/transport.ts:174](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L174) Time signature as \[beatsPerBar, beatUnit]. ##### Returns \[`number`, `number`] *** ### tracks #### Get Signature > **get** **tracks**(): readonly `SyncableBeatTrack`\[] Defined in: [packages/core/src/transport.ts:199](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L199) Read-only array of BeatTracks currently synced to this Transport. Cached for performance. ##### Returns readonly `SyncableBeatTrack`\[] ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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`](TypedEventEmitter.md).[`_clearListeners`](TypedEventEmitter.md#clearlisteners) *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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* `"error"` | `"pause"` | `"loop"` | `"start"` | `"stop"` | `"resume"` | `"tick"` ##### 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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`](TypedEventEmitter.md).[`addEventListener`](TypedEventEmitter.md#addeventlistener) *** ### dispose() > **dispose**(): `void` Defined in: [packages/core/src/transport.ts:487](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L487) Dispose the Transport, terminating the Worker and releasing all resources. After disposal, the Transport should not be used. #### Returns `void` *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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* `"error"` | `"pause"` | `"loop"` | `"start"` | `"stop"` | `"resume"` | `"tick"` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail [`TransportEventMap`](../interfaces/TransportEventMap.md)\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` #### Inherited from [`TypedEventEmitter`](TypedEventEmitter.md).[`emit`](TypedEventEmitter.md#emit) *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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* `"error"` | `"pause"` | `"loop"` | `"start"` | `"stop"` | `"resume"` | `"tick"` #### 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`](TypedEventEmitter.md).[`off`](TypedEventEmitter.md#off) *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `"error"` | `"pause"` | `"loop"` | `"start"` | `"stop"` | `"resume"` | `"tick"` #### 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`](TypedEventEmitter.md).[`on`](TypedEventEmitter.md#on) *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `"error"` | `"pause"` | `"loop"` | `"start"` | `"stop"` | `"resume"` | `"tick"` #### 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`](TypedEventEmitter.md).[`once`](TypedEventEmitter.md#once) *** ### pause() > **pause**(): `void` Defined in: [packages/core/src/transport.ts:423](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L423) Pause playback. Freezes position for later resume via start(). No-op if not playing or already paused. #### Returns `void` *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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* `"error"` | `"pause"` | `"loop"` | `"start"` | `"stop"` | `"resume"` | `"tick"` ##### 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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`](TypedEventEmitter.md).[`removeEventListener`](TypedEventEmitter.md#removeeventlistener) *** ### start() > **start**(): `void` Defined in: [packages/core/src/transport.ts:332](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L332) Start playback. Begins the Worker-driven scheduler and starts all synced tracks. No-op if already playing. #### Returns `void` *** ### stop() > **stop**(): `void` Defined in: [packages/core/src/transport.ts:448](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L448) Stop playback and reset position to the beginning. #### Returns `void` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/TypedEventEmitter.md' --- [EZ Web Audio](../index.md) / TypedEventEmitter # Class: TypedEventEmitter\ Defined in: [packages/core/src/events/typed-event-emitter.ts:26](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L26) Typed event emitter base class for audio lifecycle events. Extends the native `EventTarget` API with: * Type-safe `addEventListener` / `removeEventListener` overloads * A protected `emit()` helper that creates and dispatches typed `CustomEvent` instances * Chainable `on()` / `once()` / `off()` convenience methods Usage — extend this class with a concrete event map: ```typescript interface MyEventMap { play: CustomEvent<{ time: number }> stop: CustomEvent<{ time: number }> } class MyEmitter extends TypedEventEmitter { trigger() { this.emit('play', { time: Date.now() }) } } ``` ## Extends * `EventTarget` ## Extended by * [`BaseEffect`](BaseEffect.md) * [`GrainPlayer`](GrainPlayer.md) * [`PolySynth`](PolySynth.md) * [`Sequence`](Sequence.md) * [`Transport`](Transport.md) * [`LayeredSound`](LayeredSound.md) ## Type Parameters ### TMap `TMap` *extends* `{ [K in keyof TMap]: CustomEvent }` Record mapping event name strings to `CustomEvent` types. ## Constructors ### Constructor > **new TypedEventEmitter**<`TMap`>(): `TypedEventEmitter` Defined in: node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.dom.d.ts:11586 #### Returns `TypedEventEmitter` #### Inherited from `EventTarget.constructor` ## Methods ### \_clearListeners() > `protected` **\_clearListeners**(): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:192](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L192) 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` *** ### addEventListener() #### Call Signature > **addEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L44) 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* `string` ##### Parameters ###### type `K` The event type (key of TMap) ###### listener (`event`) => `void` Typed event handler ###### options? Standard addEventListener options `boolean` | `AddEventListenerOptions` ##### Returns `void` ##### Overrides `EventTarget.addEventListener` #### Call Signature > **addEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L49) 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` ##### Overrides `EventTarget.addEventListener` *** ### emit() > `protected` **emit**<`K`>(`type`, `detail`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L95) 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* `string` #### Parameters ##### type `K` The event type to emit (key of TMap) ##### detail `TMap`\[`K`]\[`"detail"`] The event detail object (typed by TMap) #### Returns `void` *** ### off() > **off**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:167](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L167) 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* `string` #### 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) ``` *** ### on() > **on**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:116](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L116) Subscribe to one or more events. Supports chaining. #### Type Parameters ##### K `K` *extends* `string` #### 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) ``` *** ### once() > **once**<`K`>(`type`, `listener`): `this` Defined in: [packages/core/src/events/typed-event-emitter.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L141) Subscribe to an event once. Handler is removed after first invocation. #### Type Parameters ##### K `K` *extends* `string` #### 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')) ``` *** ### removeEventListener() #### Call Signature > **removeEventListener**<`K`>(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L70) 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* `string` ##### 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` ##### Overrides `EventTarget.removeEventListener` #### Call Signature > **removeEventListener**(`type`, `listener`, `options?`): `void` Defined in: [packages/core/src/events/typed-event-emitter.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/typed-event-emitter.ts#L75) 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` ##### Overrides `EventTarget.removeEventListener` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/ValidationError.md' --- [EZ Web Audio](../index.md) / ValidationError # Class: ValidationError Defined in: [packages/core/src/errors/validation-error.ts:27](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/validation-error.ts#L27) Error thrown when caller-supplied input fails validation, or an API is used in a way it does not support (calling a method after `dispose()`, mutating a synced `BeatTrack` directly, an out-of-range parameter, etc). This is the "you called this wrong" error class — as opposed to [AudioLoadError](AudioLoadError.md) (fetch/decode failures) or [AudioContextError](AudioContextError.md) (AudioContext state issues). Every parameter-range and misuse check across the library (gain, pan, BPM, frequency, control-type names, disposed instances, etc.) throws `ValidationError`. ## Example ```typescript import { ValidationError } from 'ez-web-audio' try { sound.changeGainTo(-1) } catch (e) { if (e instanceof ValidationError) { console.error(`Invalid input: ${e.message}`) } } ``` ## Extends * [`AudioError`](AudioError.md) ## Constructors ### Constructor > **new ValidationError**(`message`): `ValidationError` Defined in: [packages/core/src/errors/validation-error.ts:33](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/validation-error.ts#L33) Create a new ValidationError. #### Parameters ##### message `string` Human-readable error description with actionable fix #### Returns `ValidationError` #### Overrides [`AudioError`](AudioError.md).[`constructor`](AudioError.md#constructor) ## Properties ### code? > `readonly` `optional` **code**: `string` Defined in: [packages/core/src/errors/audio-error.ts:34](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/errors/audio-error.ts#L34) Optional error code for programmatic handling #### Inherited from [`AudioError`](AudioError.md).[`code`](AudioError.md#code) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/classes/VoiceHandle.md' --- [EZ Web Audio](../index.md) / VoiceHandle # Class: VoiceHandle Defined in: [packages/core/src/poly-synth.ts:96](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L96) Handle returned by PolySynth.play() representing a single playing voice. The handle provides per-voice control through the full Oscillator fluent API. When the voice is stolen or stopped, the handle becomes stale and all methods silently no-op — no errors thrown, no accidental modification of other voices. ## Example ```typescript const handle = synth.play({ frequency: 440 }) handle.update('gain').to(0.5).as('ratio') // per-voice volume handle.update('frequency').to(450).as('ratio') // pitch bend // After voice is stolen: handle.active // false handle.update('gain') // silently no-ops ``` ## Constructors ### Constructor > **new VoiceHandle**(`oscillator`, `onStop`): `VoiceHandle` Defined in: [packages/core/src/poly-synth.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L99) #### Parameters ##### oscillator [`Oscillator`](Oscillator.md) ##### onStop () => `void` #### Returns `VoiceHandle` ## Accessors ### active #### Get Signature > **get** **active**(): `boolean` Defined in: [packages/core/src/poly-synth.ts:105](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L105) Whether this handle still references an active voice. ##### Returns `boolean` ## Methods ### onPlayRamp() > **onPlayRamp**(`type`, `rampType?`): `object` Defined in: [packages/core/src/poly-synth.ts:140](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L140) Schedule a parameter ramp when the voice next plays. Returns no-op builder if handle is stale. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) ##### rampType? `RampType` #### Returns `object` ##### from() > **from**: (`startValue`) => `object` ###### Parameters ###### startValue `number` ###### Returns `object` ###### to() > **to**: (`endValue`) => `object` ###### Parameters ###### endValue `number` ###### Returns `object` ###### in() > **in**: (`endTime`) => `void` ###### Parameters ###### endTime `number` ###### Returns `void` *** ### onPlaySet() > **onPlaySet**(`type`): `object` Defined in: [packages/core/src/poly-synth.ts:125](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L125) Schedule a parameter value to be set when the voice next plays. Returns no-op builder if handle is stale. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) #### Returns `object` ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### at() > **at**: (`time`) => `void` ###### Parameters ###### time `number` ###### Returns `void` ###### endingAt() > **endingAt**: (`time`, `rampType?`) => `void` ###### Parameters ###### time `number` ###### rampType? `RampType` ###### Returns `void` *** ### stop() > **stop**(): `Promise`<`void`> Defined in: [packages/core/src/poly-synth.ts:158](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L158) Stop this voice. The handle becomes stale after stopping. With an ADSR envelope, the voice enters its release phase and keeps ringing until the tail completes — the pool reclaims it only then. #### Returns `Promise`<`void`> *** ### update() > **update**(`type`): `object` Defined in: [packages/core/src/poly-synth.ts:111](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L111) Update a voice parameter immediately. Returns no-op builder if handle is stale. #### Parameters ##### type [`ControlType`](../type-aliases/ControlType.md) #### Returns `object` ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### as() > **as**: (`method`) => `void` ###### Parameters ###### method [`RatioType`](../type-aliases/RatioType.md) ###### Returns `void` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/guide/concepts.md' description: >- Understand the core building blocks of EZ Web Audio — Sound for one-shot playback, Track for music with seeking, Oscillator for synthesis, effects chains, and event handling. --- # Core Concepts Understanding when to use each class and how they work together. ## The Class Hierarchy ``` BaseSound (abstract) ├── Sound - One-shot audio playback from file │ └── Track - Music with position tracking ├── Oscillator - Synthesized sound generation └── SampledNote - Musical notes with pitch identity ``` All sound classes share common functionality from `BaseSound`: volume control (gain), stereo positioning (pan), event emission (play, stop, end), and effect chain support. ## Sound: One-Shot Playback **Use Sound for:** Short audio files that may play multiple times simultaneously. ```typescript const click = await createSound('/sounds/click.mp3') // Each play() creates a new AudioBufferSourceNode — overlaps freely click.play() click.play() click.play() ``` Each `play()` creates a new `AudioBufferSourceNode` and cleans it up when finished. Perfect for UI feedback, game SFX, and drum samples. ### Looping Set `loop = true` for seamless looping — no gap between repeats. Looped sounds must be stopped manually: ```typescript click.loop = true click.play() click.stop() // Looped sounds don't end on their own ``` ## Track: Music Playback **Use Track for:** Longer audio files where you need playback control. ```typescript const song = await createTrack('/music/background.mp3') song.play() console.log(song.position.string) // "1:23" console.log(song.percentPlayed) // 35 (35% complete) song.pause() song.resume() song.seek(60).as('seconds') // Jump to 1 minute ``` Position is returned as a `TimeObject` with `raw` (seconds), `string` ("1:23"), and `pojo` (`{ minutes, seconds }`) fields. Track limitation: only one playback at a time — calling `play()` while playing restarts. ## Oscillator: Sound Synthesis **Use Oscillator for:** Generating sounds from scratch without audio files. ```typescript const synth = await createOscillator({ note: 'A4', // or use frequency: 440 type: 'sine', // sine, square, sawtooth, triangle envelope: { attack: 0.01, decay: 0.1, sustain: 0.7, release: 0.3 } }) synth.play() synth.stop() // Triggers ADSR release phase ``` The `note` option looks up frequency from the built-in frequency map. When both `note` and `frequency` are provided, `note` takes precedence. ### Waveform Types | Type | Sound Character | Use Case | |------|-----------------|----------| | `sine` | Pure, smooth | Flutes, whistles, sub bass | | `square` | Hollow, buzzy | Chiptune, clarinets | | `sawtooth` | Bright, aggressive | Synth leads, brass | | `triangle` | Soft, muted | Soft synths, bells | ### ADSR Envelope The envelope shapes volume over time (Attack / Decay / Sustain / Release). The `Envelope` class is also exported for direct use — see [Synthesis](/examples/synthesis) for details. ## AudioContext Lifecycle ### Lazy Initialization EZ Web Audio creates the AudioContext automatically when you first call a factory function inside a user interaction handler. For iOS mute workaround or pre-warming, call `await initAudio()` first. ### Single Context and States EZ Web Audio uses one shared AudioContext for all sounds. Context states: | State | Meaning | |-------|---------| | `running` | Normal operation | | `suspended` | Waiting for interaction — handled automatically via `play()` | | `interrupted` | iOS backgrounded — wait for foreground | | `closed` | Context destroyed — cannot recover | ## Volume Control All sounds have a `volume` getter/setter as a convenient alias for gain control: ```typescript sound.volume = 0.5 // Same as sound.changeGainTo(0.5) console.log(sound.volume) // 0.5 ``` `volume` delegates to `changeGainTo()` — the same validation applies (negative values throw, values above 1 log a warning). ## Audio Routing Each sound follows this signal path: ``` Source → [Effects] → Gain → Panner → Destination ``` ```typescript const sound = await createSound('/audio/guitar.mp3') const filter = createFilterEffect('lowpass', { frequency: 2000 }) sound.addEffect(filter) sound.changeGainTo(0.8) sound.changePanTo(-0.5) sound.play() ``` ### Effect Chain and Bypass Effects are processed in insertion order. Add multiple with `addEffects([a, b, c])`. Toggle `filter.bypass = true` to skip an effect — the chain rewires automatically. Wrap any raw Web Audio node with `wrapEffect(node)`. ## Events All playable sounds emit typed events via `on(event, handler)`: | Event | Trigger | Available on | |-------|---------|--------------| | `play` | `play()` called | All | | `stop` | `stop()` called | All | | `end` | Audio finished naturally | All | | `pause` | `pause()` called | Track, BeatTrack | | `resume` | `resume()` called | Track, BeatTrack | | `seek` | `seek()` called | Track only | | `beat` | Beat scheduled | BeatTrack only | | `warning` | Issue encountered | LayeredSound only | ```typescript sound.on('play', (e) => { console.log(e.detail.time) // audioContext.currentTime console.log(e.detail.source) // typed as AudioEventSource }) track.on('seek', e => console.log('Seeked to', e.detail.position)) ``` ### Event Types Event detail `source` fields are typed as `AudioEventSource` (a union of `BaseSound | BeatTrack | LayeredSound`). The library exports event map and detail types for type-safe handling: ```typescript import type { AudioEventSource, EventDetailFor, SoundEventMap, SoundEventType, } from 'ez-web-audio' import { TypedEventEmitter } from 'ez-web-audio' // Extract detail type from event name type PlayDetail = EventDetailFor<'play'> // PlayEventDetail ``` Also exported: `BeatTrackEventMap`, `LayeredSoundEventMap`, and all detail types (`PlayEventDetail`, `StopEventDetail`, etc.). `TypedEventEmitter` is available for building custom event-driven audio classes. ## Other Sound Types ### Sampler Round-robin playback cycles through multiple sounds on each `play()` call: ```typescript const gunshot = await createSampler(['shot1.mp3', 'shot2.mp3', 'shot3.mp3']) gunshot.play() // shot1 → shot2 → shot3 → shot1... ``` ### BeatTrack Drum machine patterns with per-beat active/inactive state: ```typescript const kick = await createBeatTrack(['kick.mp3']) kick.beats[0].active = true kick.beats[4].active = true ``` Use `setPattern()` to set all beats at once from an array (shorter arrays default remaining beats to inactive): ```typescript kick.setPattern([1, 0, 1, 0, 1, 0, 1, 0]) // Set all beats at once ``` ### LayeredSound Multiple sounds synchronized to start at the exact same AudioContext time: ```typescript const layer = await createLayeredSound([bass, melody, synth]) layer.play() ``` ### AudioSprite Pack multiple sounds into one audio file — play segments by name with `createSprite()`: ```typescript const sprite = await createSprite('/audio/ui-sounds.mp3', { spritemap: { click: { start: 0, end: 0.1 }, success: { start: 1.0, end: 1.8 } } }) sprite.play('click') ``` ### Noise Generation Generate noise procedurally with `createNoise()` — useful for ambience, sleep sounds, and synthesis building blocks: ```typescript const white = await createNoise('white') // Flat spectrum (hiss) const pink = await createNoise('pink') // 1/f — natural, balanced const brown = await createNoise('brown') // Deep rumble pink.loop = true pink.play() ``` All noise types return a 1-second `Sound` instance. Set `.loop = true` for continuous playback. You can also use `createWhiteNoise()` for the single-type shorthand. ## Error Classes The library exports typed error classes: `AudioError` (base), `AudioLoadError` (load/decode failure), `AudioContextError` (context issues), `InvalidNoteError` (invalid note name), and `ValidationError` (invalid parameters or API misuse — negative gain, non-positive BPM/frequency, calling a method after `dispose()`, unsupported control/ratio/ramp type names, and similar caller-input checks throughout the library). All extend `AudioError` for catch-all handling: ```typescript import { ValidationError } from 'ez-web-audio' try { sound.changeGainTo(-1) } catch (e) { if (e instanceof ValidationError) { console.error(`Invalid input: ${e.message}`) } } ``` ## Advanced Exports The library also exports: `MusicallyAware` (musical identity mixin), `createEffect` (low-level effect wrapper), `Connectable`/`Playable` (interfaces), options types (`AnalyzerOptions`, `BeatTrackOptions`, `EnvelopeOptions`, `FilterEffectOptions`, `OscillatorOptions`, `OscillatorFilterOptions`, `SamplerOptions`, `LayeredSoundOptions`), sprite types (`SpriteDefinition`, `SpriteManifest`, `SpritePlayOptions`), and unit types (`RatioType`, `SeekType`, `FilterType`). See the [API Reference](/api/) for details. ## Next Steps * [Parameter Control](/guide/parameter-control) - Automate gain, frequency, and pan over time * [Utilities](/guide/utilities) - Batch loading, crossfade, debug mode, and interaction helpers * [Interactive Examples](/examples/) - See concepts in action * [API Reference](/api/) - Detailed method documentation --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/crossfade.md' description: >- Learn how to crossfade smoothly between two audio tracks using equal-power curves. Create DJ-style transitions without volume dips using EZ Web Audio's crossfade function. --- # Crossfade — Smooth Transitions Between Tracks The `crossfade()` function creates a smooth, DJ-style transition between two Tracks using equal-power curves. The fading track fades out while the incoming track fades in, maintaining constant perceived loudness throughout the transition. **You'll learn:** * Using `crossfade(fromTrack, toTrack, duration)` for smooth transitions * How equal-power curves work and why they sound better than linear fades * Awaiting crossfade completion for sequenced transitions * Managing track state before and after crossfades ## Interactive Demo Crossfade between two audio tracks using equal-power curves. Adjustable crossfade duration with play controls for both tracks. ## Basic Usage Load two tracks and call `crossfade()` to transition between them: ```typescript import { createTrack, crossfade } from 'ez-web-audio' const trackA = await createTrack('song-a.mp3') const trackB = await createTrack('song-b.mp3') // Start Track A await trackA.play() // Later: crossfade from A to B over 2 seconds await crossfade(trackA, trackB, 2) // Track A is paused, Track B is playing at full gain ``` ## Outgoing Track Behavior By default, the outgoing track is **paused** after the fade, preserving its position. You can control this with the `afterFade` option: ```typescript // Default: pause the outgoing track (preserves position, frees resources) await crossfade(trackA, trackB, 2) await crossfade(trackA, trackB, 2, { afterFade: 'pause' }) // same as above // DJ-style: outgoing track keeps playing silently at gain 0 await crossfade(trackA, trackB, 2, { afterFade: 'continue' }) // When you crossfade back, trackA is right where it would naturally be // Full stop: reset outgoing track to the beginning await crossfade(trackA, trackB, 2, { afterFade: 'stop' }) ``` ::: tip When to use `'continue'` Use `afterFade: 'continue'` when crossfading back and forth between tracks (like a DJ mixer). The outgoing track keeps playing silently, so when you crossfade back to it, there's no jump in playback position. Keep in mind that the silent track still uses audio resources — if you're done with a track, `'pause'` or `'stop'` is more efficient. ::: ## Crossfade Behavior * **Source track** (first argument): fades out from current gain to 0 using equal-power curves * **Destination track** (second argument): fades in from 0 to full gain (or from current gain if already playing) * If the destination was previously paused (e.g., from an earlier crossfade), it resumes from its paused position * The `await` resolves when the fade duration completes ```typescript // Crossfade over different durations await crossfade(trackA, trackB, 0.5) // Fast 0.5-second crossfade await crossfade(trackA, trackB, 4) // Slow 4-second crossfade // Crossfade to a track that's already playing at a specific position await trackB.play() // Both tracks play during the crossfade await crossfade(trackA, trackB, 2) ``` ## Equal-Power Curves A naive linear crossfade creates a volume dip at the midpoint — when both tracks are at 50%, the total power drops. Equal-power crossfading uses trigonometric curves to maintain constant power: * **Fade out**: `cos(t × π/2)` — starts at full volume, drops slowly at first, then rapidly * **Fade in**: `sin(t × π/2)` — starts silent, rises rapidly at first, then levels off * The identity `cos²(x) + sin²(x) = 1` guarantees constant total power throughout ``` Linear crossfade: Equal-power crossfade: A: 1.0 → 0.5 → 0.0 A: 1.0 → 0.71 → 0.0 B: 0.0 → 0.5 → 1.0 B: 0.0 → 0.71 → 1.0 Total: 1.0 → 0.5 → 1.0 Total: 1.0 → 1.0 → 1.0 ↑ DIP ↑ NO DIP ``` ## Sequenced Transitions Chain crossfades by awaiting each one: ```typescript await trackA.play() // Crossfade A → B over 2 seconds await crossfade(trackA, trackB, 2) // Crossfade B → C over 3 seconds await crossfade(trackB, trackC, 3) // Now only trackC is playing ``` ## Managing Gain Before Crossfade If you've changed a track's gain, `crossfade()` fades from the current gain value: ```typescript // Track A is playing quietly trackA.changeGainTo(0.5) // Crossfade will fade A from 0.5 (not 1.0) to 0 await crossfade(trackA, trackB, 2) ``` ::: tip Looping Tracks For background music, set a track to loop before crossfading to it: ```typescript const bgMusicA = await createTrack('ambient-a.mp3') const bgMusicB = await createTrack('ambient-b.mp3') bgMusicA.loop = true bgMusicB.loop = true await bgMusicA.play() // Smooth transition to the next track await crossfade(bgMusicA, bgMusicB, 3) ``` ::: ## Next Steps * [Basic Playback](/examples/basic-playback) — Working with tracks (pause, resume, seek) * [LayeredSound](/examples/layered-sound) — Synchronized multi-layer playback * [Effects](/examples/effects) — Apply real-time audio effects --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/effects-chain.md' description: >- Build and tweak an audio effects chain with delay, reverb, compressor, and EQ. Toggle effects on/off, adjust parameters, and reorder effects in the signal path. --- # Effects Chain Chain delay, reverb, compressor, and EQ effects. Toggle each on/off, adjust parameters in real time, reorder them to hear the sonic difference, and switch between an oscillator and an audio file source. Interactive effects chain demo with four effects: Delay (time, feedback, mix), Reverb (decay, wet), Compressor (threshold, ratio), and EQ (low/mid/high gain). Each effect has bypass and reorder controls. A signal flow diagram shows the current chain order. Supports switching between an oscillator source and a loaded audio file. ## How It Works Audio flows through the effects in a fixed signal path: ``` Source → Effect 1 → Effect 2 → Effect 3 → Effect 4 → Output ``` Each effect is inserted using `addEffects()`, which wires the effects into the audio graph in order. Reordering the effects changes the signal path -- putting compression before reverb sounds different from reverb before compression. ### Building a Chain ```typescript import { createCompressor, createDelay, createEQ, createOscillator, createReverb, } from 'ez-web-audio' const source = await createOscillator({ frequency: 440, type: 'sawtooth' }) const delay = createDelay({ time: 0.3, feedback: 0.4, mix: 0.3 }) const reverb = createReverb({ decay: 2.5, wet: 0.35 }) const compressor = createCompressor({ threshold: -24, ratio: 4 }) const eq = createEQ({ low: 0, mid: 0, high: 2 }) // Effects are connected in array order source.addEffects([delay, reverb, compressor, eq]) source.play() ``` ### Bypassing an Effect ```typescript delay.bypass = true // Dry signal passes through unaffected delay.bypass = false // Effect re-enters the signal chain ``` ### Reordering Effects Reorder by removing and re-adding effects in the new order: ```typescript // Move compressor before reverb source.removeEffect(reverb) source.removeEffect(compressor) source.addEffects([compressor, reverb]) ``` ### Cleanup ```typescript source.stop() source.dispose() // Disconnects all effects and releases audio nodes ``` ## Effect Parameters | Effect | Key Parameters | Notes | |--------|---------------|-------| | **Delay** | `time` (0-1s), `feedback` (0-1), `mix` (0-1) | Higher feedback = longer echo tail | | **Reverb** | `decay` (seconds), `wet` (0-1) | Simulates room reflections | | **Compressor** | `threshold` (dBFS), `ratio` (N:1) | Reduces dynamic range | | **EQ** | `low`, `mid`, `high` (dB gain) | Three-band shelving/peak EQ | ## Further Reading * [LFO — One Knob, Three Effects](/examples/lfo-modulation) -- add tremolo or filter sweep to a signal in the chain * [Audio Routing](/examples/audio-routing) -- custom routing beyond the linear chain * [Effects](/examples/effects) -- individual effect deep-dives --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api.md' --- # EZ Web Audio ## Classes * [AggregateAudioLoadError](classes/AggregateAudioLoadError.md) * [Analyzer](classes/Analyzer.md) * [AudioContextError](classes/AudioContextError.md) * [AudioError](classes/AudioError.md) * [AudioLoadError](classes/AudioLoadError.md) * [AudioSprite](classes/AudioSprite.md) * [BaseEffect](classes/BaseEffect.md) * [Beat](classes/Beat.md) * [BeatTrack](classes/BeatTrack.md) * [CompressorEffect](classes/CompressorEffect.md) * [DelayEffect](classes/DelayEffect.md) * [DistortionEffect](classes/DistortionEffect.md) * [EffectWrapper](classes/EffectWrapper.md) * [Envelope](classes/Envelope.md) * [EQEffect](classes/EQEffect.md) * [FilterEffect](classes/FilterEffect.md) * [Font](classes/Font.md) * [GainEffect](classes/GainEffect.md) * [GrainPlayer](classes/GrainPlayer.md) * [InvalidNoteError](classes/InvalidNoteError.md) * [LayeredSound](classes/LayeredSound.md) * [LFO](classes/LFO.md) * [Note](classes/Note.md) * [Oscillator](classes/Oscillator.md) * [OscillatorController](classes/OscillatorController.md) * [PolySynth](classes/PolySynth.md) * [ReverbEffect](classes/ReverbEffect.md) * [SampledNote](classes/SampledNote.md) * [Sampler](classes/Sampler.md) * [Sequence](classes/Sequence.md) * [Sound](classes/Sound.md) * [SoundController](classes/SoundController.md) * [Track](classes/Track.md) * [Transport](classes/Transport.md) * [TypedEventEmitter](classes/TypedEventEmitter.md) * [ValidationError](classes/ValidationError.md) * [VoiceHandle](classes/VoiceHandle.md) ## Interfaces * [AlgorithmicReverbOptions](interfaces/AlgorithmicReverbOptions.md) * [AnalyzerOptions](interfaces/AnalyzerOptions.md) * [AudiospriteManifest](interfaces/AudiospriteManifest.md) * [BaseSoundEventMap](interfaces/BaseSoundEventMap.md) * [BeatEventDetail](interfaces/BeatEventDetail.md) * [BeatTrackEventMap](interfaces/BeatTrackEventMap.md) * [BeatTrackOptions](interfaces/BeatTrackOptions.md) * [CompressorOptions](interfaces/CompressorOptions.md) * [Connectable](interfaces/Connectable.md) * [ConvolutionReverbOptions](interfaces/ConvolutionReverbOptions.md) * [CrossfadeOptions](interfaces/CrossfadeOptions.md) * [DebugMessage](interfaces/DebugMessage.md) * [DelayOptions](interfaces/DelayOptions.md) * [DistortionOptions](interfaces/DistortionOptions.md) * [Effect](interfaces/Effect.md) * [EndEventDetail](interfaces/EndEventDetail.md) * [EnvelopeOptions](interfaces/EnvelopeOptions.md) * [EQOptions](interfaces/EQOptions.md) * [ExternalEffect](interfaces/ExternalEffect.md) * [FilterEffectOptions](interfaces/FilterEffectOptions.md) * [GrainPlayerEventMap](interfaces/GrainPlayerEventMap.md) * [GrainPlayerOptions](interfaces/GrainPlayerOptions.md) * [HowlerSpriteManifest](interfaces/HowlerSpriteManifest.md) * [InteractionTarget](interfaces/InteractionTarget.md) * [LayeredSoundEventMap](interfaces/LayeredSoundEventMap.md) * [LayeredSoundOptions](interfaces/LayeredSoundOptions.md) * [LFOConnectOptions](interfaces/LFOConnectOptions.md) * [LFOOptions](interfaces/LFOOptions.md) * [OscillatorFilterOptions](interfaces/OscillatorFilterOptions.md) * [OscillatorOptions](interfaces/OscillatorOptions.md) * [PauseEventDetail](interfaces/PauseEventDetail.md) * [Playable](interfaces/Playable.md) * [PlayEventDetail](interfaces/PlayEventDetail.md) * [PlayOptions](interfaces/PlayOptions.md) * [PolySynthEventMap](interfaces/PolySynthEventMap.md) * [PolySynthOptions](interfaces/PolySynthOptions.md) * [ResumeEventDetail](interfaces/ResumeEventDetail.md) * [SamplerOptions](interfaces/SamplerOptions.md) * [SeekEventDetail](interfaces/SeekEventDetail.md) * [SequenceEventDetail](interfaces/SequenceEventDetail.md) * [SequenceEventMap](interfaces/SequenceEventMap.md) * [SequenceLoopDetail](interfaces/SequenceLoopDetail.md) * [SequenceOptions](interfaces/SequenceOptions.md) * [SpriteDefinition](interfaces/SpriteDefinition.md) * [SpritePlayOptions](interfaces/SpritePlayOptions.md) * [StopEventDetail](interfaces/StopEventDetail.md) * [TimeObject](interfaces/TimeObject.md) * [TrackEventMap](interfaces/TrackEventMap.md) * [TransportErrorDetail](interfaces/TransportErrorDetail.md) * [TransportEventMap](interfaces/TransportEventMap.md) * [TransportLifecycleDetail](interfaces/TransportLifecycleDetail.md) * [TransportLoopDetail](interfaces/TransportLoopDetail.md) * [TransportOptions](interfaces/TransportOptions.md) * [TransportPosition](interfaces/TransportPosition.md) * [TransportTickDetail](interfaces/TransportTickDetail.md) * [VoiceStolenEventDetail](interfaces/VoiceStolenEventDetail.md) * [WarningEventDetail](interfaces/WarningEventDetail.md) ## Type Aliases * [AudioEventSource](type-aliases/AudioEventSource.md) * [AudioInput](type-aliases/AudioInput.md) * [ControlType](type-aliases/ControlType.md) * [DistortionType](type-aliases/DistortionType.md) * [EventDetailFor](type-aliases/EventDetailFor.md) * [FilterType](type-aliases/FilterType.md) * [HowlerSpriteTuple](type-aliases/HowlerSpriteTuple.md) * [LFOWaveform](type-aliases/LFOWaveform.md) * [MusicalTimeNotation](type-aliases/MusicalTimeNotation.md) * [OscillatorControlType](type-aliases/OscillatorControlType.md) * [~~Player~~](type-aliases/Player.md) * [RatioType](type-aliases/RatioType.md) * [SeekType](type-aliases/SeekType.md) * [SequenceCallback](type-aliases/SequenceCallback.md) * [SoundControlType](type-aliases/SoundControlType.md) * [~~SoundEventMap~~](type-aliases/SoundEventMap.md) * [SoundEventType](type-aliases/SoundEventType.md) * [SpriteManifest](type-aliases/SpriteManifest.md) * [StealStrategy](type-aliases/StealStrategy.md) ## Variables * [frequencyMap](variables/frequencyMap.md) ## Functions * [audioContextAwareTimeout](functions/audioContextAwareTimeout.md) * [clearPreloadCache](functions/clearPreloadCache.md) * [createAnalyzer](functions/createAnalyzer.md) * [createBeatTrack](functions/createBeatTrack.md) * [createCompressor](functions/createCompressor.md) * [createDelay](functions/createDelay.md) * [createDistortion](functions/createDistortion.md) * [createEffect](functions/createEffect.md) * [createEQ](functions/createEQ.md) * [createFilterEffect](functions/createFilterEffect.md) * [createFont](functions/createFont.md) * [createGainEffect](functions/createGainEffect.md) * [createGrainPlayer](functions/createGrainPlayer.md) * [createLayeredSound](functions/createLayeredSound.md) * [createLFO](functions/createLFO.md) * [createNoise](functions/createNoise.md) * [createNotes](functions/createNotes.md) * [createOscillator](functions/createOscillator.md) * [createPolySynth](functions/createPolySynth.md) * [createReverb](functions/createReverb.md) * [createSampler](functions/createSampler.md) * [createSequence](functions/createSequence.md) * [createSound](functions/createSound.md) * [createSounds](functions/createSounds.md) * [createSprite](functions/createSprite.md) * [createTrack](functions/createTrack.md) * [createTracks](functions/createTracks.md) * [createTransport](functions/createTransport.md) * [createWhiteNoise](functions/createWhiteNoise.md) * [crossfade](functions/crossfade.md) * [formatPosition](functions/formatPosition.md) * [getAudioContext](functions/getAudioContext.md) * [getAudioContextSync](functions/getAudioContextSync.md) * [getMasterDestination](functions/getMasterDestination.md) * [initAudio](functions/initAudio.md) * [isHowlerManifest](functions/isHowlerManifest.md) * [isMusicalTimeNotation](functions/isMusicalTimeNotation.md) * [isPreloaded](functions/isPreloaded.md) * [MusicallyAware](functions/MusicallyAware.md) * [musicalTimeToBeats](functions/musicalTimeToBeats.md) * [muteAll](functions/muteAll.md) * [normalizeManifest](functions/normalizeManifest.md) * [parseMusicalTime](functions/parseMusicalTime.md) * [pauseAll](functions/pauseAll.md) * [playAll](functions/playAll.md) * [playTogether](functions/playTogether.md) * [preload](functions/preload.md) * [preventEventDefaults](functions/preventEventDefaults.md) * [setDebugHandler](functions/setDebugHandler.md) * [setDebugMode](functions/setDebugMode.md) * [setGlobalVolume](functions/setGlobalVolume.md) * [setMasterDestination](functions/setMasterDestination.md) * [setPreloadCacheLimit](functions/setPreloadCacheLimit.md) * [stopAll](functions/stopAll.md) * [useInteractionMethods](functions/useInteractionMethods.md) * [wrapEffect](functions/wrapEffect.md) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/functions/audioContextAwareTimeout.md --- [EZ Web Audio](../index.md) / audioContextAwareTimeout # Function: audioContextAwareTimeout() > **audioContextAwareTimeout**(`audioContext`): `object` Defined in: [packages/core/src/utils/timeout.ts:109](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/timeout.ts#L109) Create AudioContext-aware `setTimeout` and `clearTimeout` functions that use `audioContext.currentTime` and `requestAnimationFrame` instead of native timers. Uses a shared singleton scheduler per AudioContext so that multiple sounds/beats share one RAF loop instead of each creating their own. Browser tabs that are backgrounded or hidden can have native `setTimeout` throttled to fire as infrequently as once per second, causing visual beat indicators and other UI timing to drift out of sync with audio playback. This utility avoids that drift by driving all timer checks through `requestAnimationFrame` and measuring elapsed time using `audioContext.currentTime`, which always advances at audio-clock speed regardless of tab visibility. **When to use:** Any UI timing that needs to stay in sync with audio playback — visual beat indicators, countdowns, progress bars, or any scheduled UI update tied to musical timing. **Graceful fallback:** If no `audioContext` is provided the function falls back to native `window.setTimeout`/`window.clearTimeout` and logs a warning. This keeps code working even if audio has not been initialized yet. ## Parameters ### audioContext `ContextLike` The AudioContext (or BaseAudioContext) driving playback ## Returns `object` An object with `setTimeout` and `clearTimeout` that mirror the native API ### clearTimeout() > **clearTimeout**: (`id`) => `void` #### Parameters ##### id `number` #### Returns `void` ### setTimeout() > **setTimeout**: (`fn`, `delayMillis`) => `number` #### Parameters ##### fn () => `void` ##### delayMillis `number` #### Returns `number` ## Example ```typescript import { getAudioContext, audioContextAwareTimeout } from 'ez-web-audio' // Get the shared AudioContext const ctx = await getAudioContext() // Create audio-aware timer functions const { setTimeout, clearTimeout } = audioContextAwareTimeout(ctx) // Use just like native timers — they stay in sync with audio even in background tabs const id = setTimeout(() => { flashBeatIndicator() }, 500) // Cancel if needed clearTimeout(id) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/clearPreloadCache.md' --- [EZ Web Audio](../index.md) / clearPreloadCache # Function: clearPreloadCache() > **clearPreloadCache**(`url?`): `void` Defined in: [packages/core/src/preload.ts:138](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/preload.ts#L138) Clear preload cache. ## Parameters ### url? `string` Optional specific URL to clear. If omitted, clears entire cache. ## Returns `void` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createAnalyzer.md' --- [EZ Web Audio](../index.md) / createAnalyzer # Function: createAnalyzer() ## Call Signature > **createAnalyzer**(`options?`): `Promise`<[`Analyzer`](../classes/Analyzer.md)> Defined in: [packages/core/src/index.ts:898](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L898) Create an Analyzer for audio visualization. The context-free overload uses the shared AudioContext created by the library, so you do not need to obtain an AudioContext manually. ### Parameters #### options? [`AnalyzerOptions`](../interfaces/AnalyzerOptions.md) Optional analyzer configuration (fftSize, minDecibels, maxDecibels, smoothingTimeConstant) ### Returns `Promise`<[`Analyzer`](../classes/Analyzer.md)> Analyzer instance ### Example ```typescript import { createAnalyzer } from 'ez-web-audio' // Context-free — no AudioContext needed const analyzer = await createAnalyzer({ fftSize: 1024 }) sound.setAnalyzer(analyzer) // With explicit AudioContext const ctx = await getAudioContext() const analyzer2 = await createAnalyzer(ctx, { fftSize: 2048 }) function visualize() { const freqData = analyzer.getFrequencyData() // Use freqData for visualization requestAnimationFrame(visualize) } visualize() ``` ## Call Signature > **createAnalyzer**(`audioContext`, `options?`): `Promise`<[`Analyzer`](../classes/Analyzer.md)> Defined in: [packages/core/src/index.ts:899](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L899) Create an Analyzer for audio visualization. The context-free overload uses the shared AudioContext created by the library, so you do not need to obtain an AudioContext manually. ### Parameters #### audioContext `BaseAudioContext` #### options? [`AnalyzerOptions`](../interfaces/AnalyzerOptions.md) Optional analyzer configuration (fftSize, minDecibels, maxDecibels, smoothingTimeConstant) ### Returns `Promise`<[`Analyzer`](../classes/Analyzer.md)> Analyzer instance ### Example ```typescript import { createAnalyzer } from 'ez-web-audio' // Context-free — no AudioContext needed const analyzer = await createAnalyzer({ fftSize: 1024 }) sound.setAnalyzer(analyzer) // With explicit AudioContext const ctx = await getAudioContext() const analyzer2 = await createAnalyzer(ctx, { fftSize: 2048 }) function visualize() { const freqData = analyzer.getFrequencyData() // Use freqData for visualization requestAnimationFrame(visualize) } visualize() ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createBeatTrack.md' --- [EZ Web Audio](../index.md) / createBeatTrack # Function: createBeatTrack() ## Call Signature > **createBeatTrack**(`inputs`, `opts?`): `Promise`<[`BeatTrack`](../classes/BeatTrack.md)> Defined in: [packages/core/src/index.ts:658](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L658) Create a BeatTrack for drum machine-style rhythmic patterns. A BeatTrack manages a sequence of Beats, where each Beat can be active (plays sound) or inactive (rest). Sounds are played in round-robin fashion to prevent overlapping. ### Parameters #### inputs [`AudioInput`](../type-aliases/AudioInput.md)\[] Array of audio file URLs, ArrayBuffers, Blobs, or Files to load as sound sources #### opts? [`BeatTrackOptions`](../interfaces/BeatTrackOptions.md) Optional BeatTrack configuration ### Returns `Promise`<[`BeatTrack`](../classes/BeatTrack.md)> Promise resolving to a BeatTrack instance ### Throws If any audio file cannot be loaded or decoded ### Example ```typescript import { createBeatTrack } from 'ez-web-audio' // From URLs const kick = await createBeatTrack(['kick1.mp3', 'kick2.mp3', 'kick3.mp3']) // From mixed inputs (URLs, ArrayBuffers, Files) const snare = await createBeatTrack([snareUrl, snareBuffer, snareFile]) // Set up a 4/4 beat pattern (kick on 1 and 3) kick.beats[0].active = true // Beat 1 kick.beats[2].active = true // Beat 3 // Play the pattern kick.play() ``` ## Call Signature > **createBeatTrack**(`audioContext`, `inputs`, `opts?`): `Promise`<[`BeatTrack`](../classes/BeatTrack.md)> Defined in: [packages/core/src/index.ts:659](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L659) Create a BeatTrack for drum machine-style rhythmic patterns. A BeatTrack manages a sequence of Beats, where each Beat can be active (plays sound) or inactive (rest). Sounds are played in round-robin fashion to prevent overlapping. ### Parameters #### audioContext `BaseAudioContext` #### inputs [`AudioInput`](../type-aliases/AudioInput.md)\[] Array of audio file URLs, ArrayBuffers, Blobs, or Files to load as sound sources #### opts? [`BeatTrackOptions`](../interfaces/BeatTrackOptions.md) Optional BeatTrack configuration ### Returns `Promise`<[`BeatTrack`](../classes/BeatTrack.md)> Promise resolving to a BeatTrack instance ### Throws If any audio file cannot be loaded or decoded ### Example ```typescript import { createBeatTrack } from 'ez-web-audio' // From URLs const kick = await createBeatTrack(['kick1.mp3', 'kick2.mp3', 'kick3.mp3']) // From mixed inputs (URLs, ArrayBuffers, Files) const snare = await createBeatTrack([snareUrl, snareBuffer, snareFile]) // Set up a 4/4 beat pattern (kick on 1 and 3) kick.beats[0].active = true // Beat 1 kick.beats[2].active = true // Beat 3 // Play the pattern kick.play() ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createCompressor.md' --- [EZ Web Audio](../index.md) / createCompressor # Function: createCompressor() ## Call Signature > **createCompressor**(`options?`): [`CompressorEffect`](../classes/CompressorEffect.md) Defined in: [packages/core/src/effects/compressor-effect.ts:236](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L236) Factory function to create a CompressorEffect. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### options? [`CompressorOptions`](../interfaces/CompressorOptions.md) Optional compressor parameters ### Returns [`CompressorEffect`](../classes/CompressorEffect.md) A new CompressorEffect instance ### Example ```typescript // Zero-config (good defaults) const comp = createCompressor() // With options const comp2 = createCompressor({ threshold: -30, ratio: 8, attack: 0.001 }) // With explicit AudioContext const comp3 = createCompressor(audioContext, { threshold: -20 }) ``` ## Call Signature > **createCompressor**(`audioContext`, `options?`): [`CompressorEffect`](../classes/CompressorEffect.md) Defined in: [packages/core/src/effects/compressor-effect.ts:237](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L237) Factory function to create a CompressorEffect. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### audioContext `BaseAudioContext` #### options? [`CompressorOptions`](../interfaces/CompressorOptions.md) Optional compressor parameters ### Returns [`CompressorEffect`](../classes/CompressorEffect.md) A new CompressorEffect instance ### Example ```typescript // Zero-config (good defaults) const comp = createCompressor() // With options const comp2 = createCompressor({ threshold: -30, ratio: 8, attack: 0.001 }) // With explicit AudioContext const comp3 = createCompressor(audioContext, { threshold: -20 }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createDelay.md' --- [EZ Web Audio](../index.md) / createDelay # Function: createDelay() ## Call Signature > **createDelay**(`options?`): [`DelayEffect`](../classes/DelayEffect.md) Defined in: [packages/core/src/effects/delay-effect.ts:180](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L180) Factory function to create a DelayEffect. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### options? [`DelayOptions`](../interfaces/DelayOptions.md) Optional delay parameters ### Returns [`DelayEffect`](../classes/DelayEffect.md) A new DelayEffect instance ### Example ```typescript // Without AudioContext (recommended) const delay = createDelay({ time: 0.3, feedback: 0.5, mix: 0.4 }) // With explicit AudioContext const delay2 = createDelay(audioContext, { time: 0.5 }) // Zero-config (good defaults) const delay3 = createDelay() ``` ## Call Signature > **createDelay**(`audioContext`, `options?`): [`DelayEffect`](../classes/DelayEffect.md) Defined in: [packages/core/src/effects/delay-effect.ts:181](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L181) Factory function to create a DelayEffect. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### audioContext `BaseAudioContext` #### options? [`DelayOptions`](../interfaces/DelayOptions.md) Optional delay parameters ### Returns [`DelayEffect`](../classes/DelayEffect.md) A new DelayEffect instance ### Example ```typescript // Without AudioContext (recommended) const delay = createDelay({ time: 0.3, feedback: 0.5, mix: 0.4 }) // With explicit AudioContext const delay2 = createDelay(audioContext, { time: 0.5 }) // Zero-config (good defaults) const delay3 = createDelay() ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createDistortion.md' --- [EZ Web Audio](../index.md) / createDistortion # Function: createDistortion() ## Call Signature > **createDistortion**(`options?`): [`DistortionEffect`](../classes/DistortionEffect.md) Defined in: [packages/core/src/effects/distortion-effect.ts:398](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L398) Factory function to create a DistortionEffect. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### options? [`DistortionOptions`](../interfaces/DistortionOptions.md) Optional distortion parameters ### Returns [`DistortionEffect`](../classes/DistortionEffect.md) A new DistortionEffect instance ### Example ```typescript // Zero-config (good defaults) const dist = createDistortion() // With options const dist2 = createDistortion({ type: 'overdrive', amount: 60, tone: 0.7, mix: 0.8 }) // Custom curve const dist3 = createDistortion({ type: 'custom', curve: myFloat32Array }) // With explicit AudioContext const dist4 = createDistortion(audioContext, { amount: 50 }) ``` ## Call Signature > **createDistortion**(`audioContext`, `options?`): [`DistortionEffect`](../classes/DistortionEffect.md) Defined in: [packages/core/src/effects/distortion-effect.ts:399](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L399) Factory function to create a DistortionEffect. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### audioContext `BaseAudioContext` #### options? [`DistortionOptions`](../interfaces/DistortionOptions.md) Optional distortion parameters ### Returns [`DistortionEffect`](../classes/DistortionEffect.md) A new DistortionEffect instance ### Example ```typescript // Zero-config (good defaults) const dist = createDistortion() // With options const dist2 = createDistortion({ type: 'overdrive', amount: 60, tone: 0.7, mix: 0.8 }) // Custom curve const dist3 = createDistortion({ type: 'custom', curve: myFloat32Array }) // With explicit AudioContext const dist4 = createDistortion(audioContext, { amount: 50 }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createEffect.md' --- [EZ Web Audio](../index.md) / createEffect # Function: createEffect() > **createEffect**(`node`, `audioContext?`): [`EffectWrapper`](../classes/EffectWrapper.md) Defined in: [packages/core/src/effects/effect-wrapper.ts:274](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L274) Factory function to wrap any AudioNode into the Effect interface. This is a convenience for wrapping native Web Audio API nodes (WaveShaperNode, ConvolverNode, etc.) that are already AudioNodes with connect/disconnect. AudioContext is optional. If omitted, uses the shared library AudioContext. ## Parameters ### node `AudioNode` The AudioNode to wrap ### audioContext? `AudioContext` Optional AudioContext (uses shared context if omitted) ## Returns [`EffectWrapper`](../classes/EffectWrapper.md) A new EffectWrapper instance implementing the Effect interface ## Example ```typescript import { createEffect } from 'ez-web-audio' const distortion = audioContext.createWaveShaper() distortion.curve = makeDistortionCurve(400) const effect = createEffect(distortion) sound.addEffect(effect) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createEQ.md' --- [EZ Web Audio](../index.md) / createEQ # Function: createEQ() ## Call Signature > **createEQ**(`options?`): [`EQEffect`](../classes/EQEffect.md) Defined in: [packages/core/src/effects/eq-effect.ts:268](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L268) Factory function to create an EQEffect. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### options? [`EQOptions`](../interfaces/EQOptions.md) Optional EQ parameters ### Returns [`EQEffect`](../classes/EQEffect.md) A new EQEffect instance ### Example ```typescript // Zero-config (flat EQ) const eq = createEQ() // With gain adjustments (dB) const eq2 = createEQ({ low: 3, mid: -2, high: 4 }) // With custom crossover frequencies const eq3 = createEQ({ low: 3, lowFrequency: 150, midFrequency: 800, highFrequency: 4000 }) // With explicit AudioContext const eq4 = createEQ(audioContext, { low: 6 }) ``` ## Call Signature > **createEQ**(`audioContext`, `options?`): [`EQEffect`](../classes/EQEffect.md) Defined in: [packages/core/src/effects/eq-effect.ts:269](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L269) Factory function to create an EQEffect. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### audioContext `BaseAudioContext` #### options? [`EQOptions`](../interfaces/EQOptions.md) Optional EQ parameters ### Returns [`EQEffect`](../classes/EQEffect.md) A new EQEffect instance ### Example ```typescript // Zero-config (flat EQ) const eq = createEQ() // With gain adjustments (dB) const eq2 = createEQ({ low: 3, mid: -2, high: 4 }) // With custom crossover frequencies const eq3 = createEQ({ low: 3, lowFrequency: 150, midFrequency: 800, highFrequency: 4000 }) // With explicit AudioContext const eq4 = createEQ(audioContext, { low: 6 }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createFilterEffect.md' --- [EZ Web Audio](../index.md) / createFilterEffect # Function: createFilterEffect() ## Call Signature > **createFilterEffect**(`type`, `options?`): [`FilterEffect`](../classes/FilterEffect.md) Defined in: [packages/core/src/effects/filter-effect.ts:240](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L240) Factory function to create a FilterEffect. AudioContext is optional. If omitted, uses the shared library AudioContext (created lazily on first use). ### Parameters #### type [`FilterType`](../type-aliases/FilterType.md) The BiquadFilterType string (or AudioContext as first arg for backwards compatibility) #### options? [`FilterEffectOptions`](../interfaces/FilterEffectOptions.md) Optional filter parameters ### Returns [`FilterEffect`](../classes/FilterEffect.md) A new FilterEffect instance ### Example ```typescript // Without AudioContext (recommended) const lowpass = createFilterEffect('lowpass', { frequency: 800 }) // With explicit AudioContext (backwards compatible) const highpass = createFilterEffect(audioContext, 'highpass', { frequency: 200, q: 2 }) ``` ## Call Signature > **createFilterEffect**(`audioContext`, `type`, `options?`): [`FilterEffect`](../classes/FilterEffect.md) Defined in: [packages/core/src/effects/filter-effect.ts:244](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L244) Factory function to create a FilterEffect. AudioContext is optional. If omitted, uses the shared library AudioContext (created lazily on first use). ### Parameters #### audioContext `BaseAudioContext` #### type [`FilterType`](../type-aliases/FilterType.md) The BiquadFilterType string (or AudioContext as first arg for backwards compatibility) #### options? [`FilterEffectOptions`](../interfaces/FilterEffectOptions.md) Optional filter parameters ### Returns [`FilterEffect`](../classes/FilterEffect.md) A new FilterEffect instance ### Example ```typescript // Without AudioContext (recommended) const lowpass = createFilterEffect('lowpass', { frequency: 800 }) // With explicit AudioContext (backwards compatible) const highpass = createFilterEffect(audioContext, 'highpass', { frequency: 200, q: 2 }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createFont.md' --- [EZ Web Audio](../index.md) / createFont # Function: createFont() ## Call Signature > **createFont**(`url`): `Promise`<[`Font`](../classes/Font.md)> Defined in: [packages/core/src/index.ts:1078](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1078) Create a Font from a soundfont file. A Font is a collection of sampled notes (like a piano or organ) that can be played by note name. Soundfont files contain base64-encoded audio samples for each note. ### Parameters #### url `string` URL to the soundfont JavaScript file ### Returns `Promise`<[`Font`](../classes/Font.md)> Promise resolving to a Font instance ### Throws If the soundfont cannot be loaded or decoded ### Example ```typescript import { createFont } from 'ez-web-audio' // Load a piano soundfont const piano = await createFont('acoustic_grand_piano-mp3.js') // Play notes by name piano.play('C4') // Middle C piano.play('E4') // E above middle C piano.play('G4') // G above middle C ``` ## Call Signature > **createFont**(`audioContext`, `url`): `Promise`<[`Font`](../classes/Font.md)> Defined in: [packages/core/src/index.ts:1079](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1079) Create a Font from a soundfont file. A Font is a collection of sampled notes (like a piano or organ) that can be played by note name. Soundfont files contain base64-encoded audio samples for each note. ### Parameters #### audioContext `BaseAudioContext` #### url `string` URL to the soundfont JavaScript file ### Returns `Promise`<[`Font`](../classes/Font.md)> Promise resolving to a Font instance ### Throws If the soundfont cannot be loaded or decoded ### Example ```typescript import { createFont } from 'ez-web-audio' // Load a piano soundfont const piano = await createFont('acoustic_grand_piano-mp3.js') // Play notes by name piano.play('C4') // Middle C piano.play('E4') // E above middle C piano.play('G4') // G above middle C ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createGainEffect.md' --- [EZ Web Audio](../index.md) / createGainEffect # Function: createGainEffect() ## Call Signature > **createGainEffect**(`initialValue?`): [`GainEffect`](../classes/GainEffect.md) Defined in: [packages/core/src/effects/gain-effect.ts:142](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L142) Factory function to create a GainEffect. AudioContext is optional. If omitted, uses the shared library AudioContext (created lazily on first use). ### Parameters #### initialValue? `number` Initial gain value (default: 1.0). Pass AudioContext as first arg for backwards compatibility. ### Returns [`GainEffect`](../classes/GainEffect.md) A new GainEffect instance ### Example ```typescript // Without AudioContext (recommended) const gain = createGainEffect(0.5) // With explicit AudioContext (backwards compatible) const gain = createGainEffect(audioContext, 0.5) ``` ## Call Signature > **createGainEffect**(`audioContext`, `initialValue?`): [`GainEffect`](../classes/GainEffect.md) Defined in: [packages/core/src/effects/gain-effect.ts:143](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/gain-effect.ts#L143) Factory function to create a GainEffect. AudioContext is optional. If omitted, uses the shared library AudioContext (created lazily on first use). ### Parameters #### audioContext `BaseAudioContext` #### initialValue? `number` Initial gain value (default: 1.0). Pass AudioContext as first arg for backwards compatibility. ### Returns [`GainEffect`](../classes/GainEffect.md) A new GainEffect instance ### Example ```typescript // Without AudioContext (recommended) const gain = createGainEffect(0.5) // With explicit AudioContext (backwards compatible) const gain = createGainEffect(audioContext, 0.5) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createGrainPlayer.md' --- [EZ Web Audio](../index.md) / createGrainPlayer # Function: createGrainPlayer() ## Call Signature > **createGrainPlayer**(`buffer`, `options?`): `Promise`<[`GrainPlayer`](../classes/GrainPlayer.md)> Defined in: [packages/core/src/index.ts:855](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L855) Create a GrainPlayer for granular synthesis from an audio buffer. GrainPlayer generates continuous texture/pad sounds by scheduling many overlapping short "grains" of audio from a source buffer. Provides independent control over pitch (via playbackRate per grain) and playback position (which region of the buffer to sample from). Note: Pitch shifting is implemented via playbackRate on each grain. This changes grain duration proportionally, which the overlap system compensates for. Extreme pitch values (beyond +/-24 semitones) may affect texture quality. ### Parameters #### buffer `AudioBuffer` The AudioBuffer to use as the grain source #### options? [`GrainPlayerOptions`](../interfaces/GrainPlayerOptions.md) Optional GrainPlayer configuration ### Returns `Promise`<[`GrainPlayer`](../classes/GrainPlayer.md)> Promise resolving to a GrainPlayer instance ### Example ```typescript import { createSound, createGrainPlayer } from 'ez-web-audio' // Load an audio file and create a grain player from its buffer const sound = await createSound('pad.mp3') const grains = await createGrainPlayer(sound.audioBuffer, { grainSize: 0.1, overlap: 0.05, pitch: 0, jitter: 0.1 }) grains.play() // Scrub through the buffer grains.position = 0.5 // middle of buffer // Pitch shift up a fifth grains.pitch = 7 // Add effects const reverb = createReverb({ decay: 3, wet: 0.5 }) grains.addEffect(reverb) ``` ## Call Signature > **createGrainPlayer**(`audioContext`, `buffer`, `options?`): `Promise`<[`GrainPlayer`](../classes/GrainPlayer.md)> Defined in: [packages/core/src/index.ts:856](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L856) Create a GrainPlayer for granular synthesis from an audio buffer. GrainPlayer generates continuous texture/pad sounds by scheduling many overlapping short "grains" of audio from a source buffer. Provides independent control over pitch (via playbackRate per grain) and playback position (which region of the buffer to sample from). Note: Pitch shifting is implemented via playbackRate on each grain. This changes grain duration proportionally, which the overlap system compensates for. Extreme pitch values (beyond +/-24 semitones) may affect texture quality. ### Parameters #### audioContext `BaseAudioContext` #### buffer `AudioBuffer` The AudioBuffer to use as the grain source #### options? [`GrainPlayerOptions`](../interfaces/GrainPlayerOptions.md) Optional GrainPlayer configuration ### Returns `Promise`<[`GrainPlayer`](../classes/GrainPlayer.md)> Promise resolving to a GrainPlayer instance ### Example ```typescript import { createSound, createGrainPlayer } from 'ez-web-audio' // Load an audio file and create a grain player from its buffer const sound = await createSound('pad.mp3') const grains = await createGrainPlayer(sound.audioBuffer, { grainSize: 0.1, overlap: 0.05, pitch: 0, jitter: 0.1 }) grains.play() // Scrub through the buffer grains.position = 0.5 // middle of buffer // Pitch shift up a fifth grains.pitch = 7 // Add effects const reverb = createReverb({ decay: 3, wet: 0.5 }) grains.addEffect(reverb) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createLayeredSound.md' --- [EZ Web Audio](../index.md) / createLayeredSound # Function: createLayeredSound() ## Call Signature > **createLayeredSound**(`layers`, `opts?`): `Promise`<[`LayeredSound`](../classes/LayeredSound.md)> Defined in: [packages/core/src/index.ts:1040](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1040) Create a LayeredSound that plays multiple Sound/Oscillator instances simultaneously. All layers start at exactly the same audioContext.currentTime for perfect sync. ### Parameters #### layers ([`Oscillator`](../classes/Oscillator.md) | [`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>)\[] Array of Sound or Oscillator instances to layer #### opts? [`LayeredSoundOptions`](../interfaces/LayeredSoundOptions.md) Optional configuration (name, warnLayerCount) ### Returns `Promise`<[`LayeredSound`](../classes/LayeredSound.md)> LayeredSound instance ### Example ```ts const bass = await createSound('bass.mp3') const melody = await createSound('melody.mp3') const synth = await createOscillator({ frequency: 440 }) const layered = await createLayeredSound([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 ``` ## Call Signature > **createLayeredSound**(`audioContext`, `layers`, `opts?`): `Promise`<[`LayeredSound`](../classes/LayeredSound.md)> Defined in: [packages/core/src/index.ts:1041](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1041) Create a LayeredSound that plays multiple Sound/Oscillator instances simultaneously. All layers start at exactly the same audioContext.currentTime for perfect sync. ### Parameters #### audioContext `BaseAudioContext` #### layers ([`Oscillator`](../classes/Oscillator.md) | [`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>)\[] Array of Sound or Oscillator instances to layer #### opts? [`LayeredSoundOptions`](../interfaces/LayeredSoundOptions.md) Optional configuration (name, warnLayerCount) ### Returns `Promise`<[`LayeredSound`](../classes/LayeredSound.md)> LayeredSound instance ### Example ```ts const bass = await createSound('bass.mp3') const melody = await createSound('melody.mp3') const synth = await createOscillator({ frequency: 440 }) const layered = await createLayeredSound([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 ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createLFO.md' --- [EZ Web Audio](../index.md) / createLFO # Function: createLFO() > **createLFO**(`options?`): [`LFO`](../classes/LFO.md) Defined in: [packages/core/src/index.ts:949](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L949) Create a Low Frequency Oscillator (LFO) for modulating audio parameters. An LFO produces a slow oscillation that can be connected to any audio parameter (gain, pan, frequency, filter cutoff, etc.) to create effects like tremolo, vibrato, auto-pan, and auto-filter. The LFO does not require an AudioContext upfront — it infers the context from the first target connected via connect(). ## Parameters ### options? [`LFOOptions`](../interfaces/LFOOptions.md) Optional LFO configuration (frequency, depth, waveform type) ## Returns [`LFO`](../classes/LFO.md) LFO instance ready to connect to audio targets ## Example ```typescript import { createLFO, createOscillator } from 'ez-web-audio' // Tremolo: modulate gain at 5 Hz const synth = await createOscillator({ frequency: 440 }) const tremolo = createLFO({ frequency: 5, depth: 0.3, type: 'sine' }) tremolo.connect(synth, 'gain') tremolo.start() synth.play() // Vibrato: modulate frequency in cents const vibrato = createLFO({ frequency: 6, depth: 50, type: 'sine' }) vibrato.connect(synth, 'frequency') // depth=50 cents by default for frequency vibrato.start() // Auto-pan: modulate pan position const autoPan = createLFO({ frequency: 0.5, depth: 0.8, type: 'triangle' }) autoPan.connect(synth, 'pan') autoPan.start() // BPM sync: set LFO rate to match quarter notes at 120 BPM tremolo.syncToBPM(120, '1/4') // sets frequency to 2 Hz ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createNoise.md' --- [EZ Web Audio](../index.md) / createNoise # Function: createNoise() ## Call Signature > **createNoise**(`type`): `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Defined in: [packages/core/src/index.ts:1269](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1269) Create a Sound containing a specific type of noise. A convenient unified API for all three noise types: * `'white'`: Equal energy across all frequencies (hiss/static) * `'pink'`: Equal energy per octave (1/f spectrum; sounds balanced and natural) * `'brown'`: Heavier bass, deeper rumble (cumulative random walk) All types return 1 second of loopable mono audio. ### Parameters #### type The noise type: 'white', 'pink', or 'brown' `"white"` | `"pink"` | `"brown"` ### Returns `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Promise resolving to a Sound containing the generated noise ### Example ```typescript import { createNoise } from 'ez-web-audio' // Pink noise for focus/sleep const pink = await createNoise('pink') pink.loop = true pink.play() // Brown noise for deep rumble const brown = await createNoise('brown') brown.play() // White noise (same as createWhiteNoise()) const white = await createNoise('white') white.play() ``` ## Call Signature > **createNoise**(`audioContext`, `type`): `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Defined in: [packages/core/src/index.ts:1270](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1270) Create a Sound containing a specific type of noise. A convenient unified API for all three noise types: * `'white'`: Equal energy across all frequencies (hiss/static) * `'pink'`: Equal energy per octave (1/f spectrum; sounds balanced and natural) * `'brown'`: Heavier bass, deeper rumble (cumulative random walk) All types return 1 second of loopable mono audio. ### Parameters #### audioContext `BaseAudioContext` #### type The noise type: 'white', 'pink', or 'brown' `"white"` | `"pink"` | `"brown"` ### Returns `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Promise resolving to a Sound containing the generated noise ### Example ```typescript import { createNoise } from 'ez-web-audio' // Pink noise for focus/sleep const pink = await createNoise('pink') pink.loop = true pink.play() // Brown noise for deep rumble const brown = await createNoise('brown') brown.play() // White noise (same as createWhiteNoise()) const white = await createNoise('white') white.play() ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createNotes.md' --- [EZ Web Audio](../index.md) / createNotes # Function: createNotes() > **createNotes**(`json?`): [`Note`](../classes/Note.md)\[] Defined in: [packages/core/src/index.ts:317](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L317) Create an array of Note objects from a frequency map. Notes represent musical pitches with letter, accidental, octave, and frequency. If no frequency map is provided, uses the default 12-TET frequency map. ## Parameters ### json? `Record`<`string`, `number`> Optional frequency map object (default: built-in frequencyMap) ## Returns [`Note`](../classes/Note.md)\[] Array of Note objects ## Example ```typescript import { createNotes } from 'ez-web-audio' // Create notes from default frequency map const notes = createNotes() const a4 = notes.find(n => n.frequency === 440) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createOscillator.md' --- [EZ Web Audio](../index.md) / createOscillator # Function: createOscillator() ## Call Signature > **createOscillator**(`options?`): `Promise`<[`Oscillator`](../classes/Oscillator.md)> Defined in: [packages/core/src/index.ts:756](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L756) Create an Oscillator for synthesizing audio from waveforms. Oscillators generate sound from sine, square, sawtooth, or triangle waves. They support filters for tone shaping and ADSR envelopes for professional-quality synthesis. ### Parameters #### options? [`OscillatorOptions`](../interfaces/OscillatorOptions.md) Optional oscillator configuration (frequency, type, filters, envelope) ### Returns `Promise`<[`Oscillator`](../classes/Oscillator.md)> Promise resolving to an Oscillator instance ### Example ```typescript import { createOscillator } from 'ez-web-audio' // Simple sine wave at 440Hz (A4) const synth = await createOscillator({ frequency: 440, type: 'sine' }) synth.play() setTimeout(() => synth.stop(), 500) // With ADSR envelope for piano-like decay const piano = await createOscillator({ frequency: 440, type: 'triangle', envelope: { attack: 0.01, decay: 0.3, sustain: 0.4, release: 0.5 } }) piano.play() // Using note name instead of frequency const a4 = await createOscillator({ note: 'A4', type: 'sine' }) a4.play() ``` ## Call Signature > **createOscillator**(`audioContext`, `options?`): `Promise`<[`Oscillator`](../classes/Oscillator.md)> Defined in: [packages/core/src/index.ts:757](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L757) Create an Oscillator for synthesizing audio from waveforms. Oscillators generate sound from sine, square, sawtooth, or triangle waves. They support filters for tone shaping and ADSR envelopes for professional-quality synthesis. ### Parameters #### audioContext `BaseAudioContext` #### options? [`OscillatorOptions`](../interfaces/OscillatorOptions.md) Optional oscillator configuration (frequency, type, filters, envelope) ### Returns `Promise`<[`Oscillator`](../classes/Oscillator.md)> Promise resolving to an Oscillator instance ### Example ```typescript import { createOscillator } from 'ez-web-audio' // Simple sine wave at 440Hz (A4) const synth = await createOscillator({ frequency: 440, type: 'sine' }) synth.play() setTimeout(() => synth.stop(), 500) // With ADSR envelope for piano-like decay const piano = await createOscillator({ frequency: 440, type: 'triangle', envelope: { attack: 0.01, decay: 0.3, sustain: 0.4, release: 0.5 } }) piano.play() // Using note name instead of frequency const a4 = await createOscillator({ note: 'A4', type: 'sine' }) a4.play() ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createPolySynth.md' --- [EZ Web Audio](../index.md) / createPolySynth # Function: createPolySynth() ## Call Signature > **createPolySynth**(`options?`): `Promise`<[`PolySynth`](../classes/PolySynth.md)> Defined in: [packages/core/src/index.ts:800](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L800) Create a PolySynth for polyphonic synthesis with automatic voice 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. ### Parameters #### options? [`PolySynthOptions`](../interfaces/PolySynthOptions.md) PolySynth configuration (maxVoices, stealStrategy, oscillator settings) ### Returns `Promise`<[`PolySynth`](../classes/PolySynth.md)> Promise resolving to a PolySynth instance ### Example ```typescript import { createPolySynth } 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) ``` ## Call Signature > **createPolySynth**(`audioContext`, `options?`): `Promise`<[`PolySynth`](../classes/PolySynth.md)> Defined in: [packages/core/src/index.ts:801](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L801) Create a PolySynth for polyphonic synthesis with automatic voice 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. ### Parameters #### audioContext `BaseAudioContext` #### options? [`PolySynthOptions`](../interfaces/PolySynthOptions.md) PolySynth configuration (maxVoices, stealStrategy, oscillator settings) ### Returns `Promise`<[`PolySynth`](../classes/PolySynth.md)> Promise resolving to a PolySynth instance ### Example ```typescript import { createPolySynth } 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) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createReverb.md' --- [EZ Web Audio](../index.md) / createReverb # Function: createReverb() ## Call Signature > **createReverb**(`options?`): [`ReverbEffect`](../classes/ReverbEffect.md) Defined in: [packages/core/src/effects/reverb-effect.ts:419](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L419) Factory function to create a ReverbEffect. Auto-detects mode from arguments: * No args or object → algorithmic reverb (synchronous) * String URL → convolution reverb (async, loads impulse response) * AudioBuffer → convolution reverb (synchronous) AudioContext is optional as the first argument. ### Parameters #### options? [`AlgorithmicReverbOptions`](../interfaces/AlgorithmicReverbOptions.md) ### Returns [`ReverbEffect`](../classes/ReverbEffect.md) ### Example ```typescript // Algorithmic reverb (good defaults) const reverb = createReverb() // Algorithmic with options const reverb2 = createReverb({ decay: 2, damping: 0.4 }) // Convolution from URL (async) const reverb3 = await createReverb('hall.wav') // Convolution from AudioBuffer const reverb4 = createReverb(audioBuffer) // With explicit AudioContext const reverb5 = createReverb(audioContext, { decay: 3 }) const reverb6 = await createReverb(audioContext, 'hall.wav') ``` ## Call Signature > **createReverb**(`audioContext`, `options?`): [`ReverbEffect`](../classes/ReverbEffect.md) Defined in: [packages/core/src/effects/reverb-effect.ts:420](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L420) Factory function to create a ReverbEffect. Auto-detects mode from arguments: * No args or object → algorithmic reverb (synchronous) * String URL → convolution reverb (async, loads impulse response) * AudioBuffer → convolution reverb (synchronous) AudioContext is optional as the first argument. ### Parameters #### audioContext `BaseAudioContext` #### options? [`AlgorithmicReverbOptions`](../interfaces/AlgorithmicReverbOptions.md) ### Returns [`ReverbEffect`](../classes/ReverbEffect.md) ### Example ```typescript // Algorithmic reverb (good defaults) const reverb = createReverb() // Algorithmic with options const reverb2 = createReverb({ decay: 2, damping: 0.4 }) // Convolution from URL (async) const reverb3 = await createReverb('hall.wav') // Convolution from AudioBuffer const reverb4 = createReverb(audioBuffer) // With explicit AudioContext const reverb5 = createReverb(audioContext, { decay: 3 }) const reverb6 = await createReverb(audioContext, 'hall.wav') ``` ## Call Signature > **createReverb**(`url`, `options?`): `Promise`<[`ReverbEffect`](../classes/ReverbEffect.md)> Defined in: [packages/core/src/effects/reverb-effect.ts:422](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L422) Factory function to create a ReverbEffect. Auto-detects mode from arguments: * No args or object → algorithmic reverb (synchronous) * String URL → convolution reverb (async, loads impulse response) * AudioBuffer → convolution reverb (synchronous) AudioContext is optional as the first argument. ### Parameters #### url `string` #### options? [`ConvolutionReverbOptions`](../interfaces/ConvolutionReverbOptions.md) ### Returns `Promise`<[`ReverbEffect`](../classes/ReverbEffect.md)> ### Example ```typescript // Algorithmic reverb (good defaults) const reverb = createReverb() // Algorithmic with options const reverb2 = createReverb({ decay: 2, damping: 0.4 }) // Convolution from URL (async) const reverb3 = await createReverb('hall.wav') // Convolution from AudioBuffer const reverb4 = createReverb(audioBuffer) // With explicit AudioContext const reverb5 = createReverb(audioContext, { decay: 3 }) const reverb6 = await createReverb(audioContext, 'hall.wav') ``` ## Call Signature > **createReverb**(`audioContext`, `url`, `options?`): `Promise`<[`ReverbEffect`](../classes/ReverbEffect.md)> Defined in: [packages/core/src/effects/reverb-effect.ts:423](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L423) Factory function to create a ReverbEffect. Auto-detects mode from arguments: * No args or object → algorithmic reverb (synchronous) * String URL → convolution reverb (async, loads impulse response) * AudioBuffer → convolution reverb (synchronous) AudioContext is optional as the first argument. ### Parameters #### audioContext `BaseAudioContext` #### url `string` #### options? [`ConvolutionReverbOptions`](../interfaces/ConvolutionReverbOptions.md) ### Returns `Promise`<[`ReverbEffect`](../classes/ReverbEffect.md)> ### Example ```typescript // Algorithmic reverb (good defaults) const reverb = createReverb() // Algorithmic with options const reverb2 = createReverb({ decay: 2, damping: 0.4 }) // Convolution from URL (async) const reverb3 = await createReverb('hall.wav') // Convolution from AudioBuffer const reverb4 = createReverb(audioBuffer) // With explicit AudioContext const reverb5 = createReverb(audioContext, { decay: 3 }) const reverb6 = await createReverb(audioContext, 'hall.wav') ``` ## Call Signature > **createReverb**(`buffer`, `options?`): [`ReverbEffect`](../classes/ReverbEffect.md) Defined in: [packages/core/src/effects/reverb-effect.ts:425](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L425) Factory function to create a ReverbEffect. Auto-detects mode from arguments: * No args or object → algorithmic reverb (synchronous) * String URL → convolution reverb (async, loads impulse response) * AudioBuffer → convolution reverb (synchronous) AudioContext is optional as the first argument. ### Parameters #### buffer `AudioBuffer` #### options? [`ConvolutionReverbOptions`](../interfaces/ConvolutionReverbOptions.md) ### Returns [`ReverbEffect`](../classes/ReverbEffect.md) ### Example ```typescript // Algorithmic reverb (good defaults) const reverb = createReverb() // Algorithmic with options const reverb2 = createReverb({ decay: 2, damping: 0.4 }) // Convolution from URL (async) const reverb3 = await createReverb('hall.wav') // Convolution from AudioBuffer const reverb4 = createReverb(audioBuffer) // With explicit AudioContext const reverb5 = createReverb(audioContext, { decay: 3 }) const reverb6 = await createReverb(audioContext, 'hall.wav') ``` ## Call Signature > **createReverb**(`audioContext`, `buffer`, `options?`): [`ReverbEffect`](../classes/ReverbEffect.md) Defined in: [packages/core/src/effects/reverb-effect.ts:426](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L426) Factory function to create a ReverbEffect. Auto-detects mode from arguments: * No args or object → algorithmic reverb (synchronous) * String URL → convolution reverb (async, loads impulse response) * AudioBuffer → convolution reverb (synchronous) AudioContext is optional as the first argument. ### Parameters #### audioContext `BaseAudioContext` #### buffer `AudioBuffer` #### options? [`ConvolutionReverbOptions`](../interfaces/ConvolutionReverbOptions.md) ### Returns [`ReverbEffect`](../classes/ReverbEffect.md) ### Example ```typescript // Algorithmic reverb (good defaults) const reverb = createReverb() // Algorithmic with options const reverb2 = createReverb({ decay: 2, damping: 0.4 }) // Convolution from URL (async) const reverb3 = await createReverb('hall.wav') // Convolution from AudioBuffer const reverb4 = createReverb(audioBuffer) // With explicit AudioContext const reverb5 = createReverb(audioContext, { decay: 3 }) const reverb6 = await createReverb(audioContext, 'hall.wav') ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createSampler.md' --- [EZ Web Audio](../index.md) / createSampler # Function: createSampler() ## Call Signature > **createSampler**(`inputs`, `opts?`): `Promise`<[`Sampler`](../classes/Sampler.md)> Defined in: [packages/core/src/index.ts:706](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L706) Create a Sampler for round-robin playback of multiple sounds. Sampler holds multiple Sound instances and cycles through them on each play, providing natural variation and preventing the "machine gun" effect of identical sounds played rapidly. ### Parameters #### inputs [`AudioInput`](../type-aliases/AudioInput.md)\[] Array of audio file URLs, ArrayBuffers, Blobs, or Files to load as sound sources #### opts? [`SamplerOptions`](../interfaces/SamplerOptions.md) Optional Sampler configuration ### Returns `Promise`<[`Sampler`](../classes/Sampler.md)> Promise resolving to a Sampler instance ### Throws If any audio file cannot be loaded or decoded ### Example ```typescript import { createSampler } from 'ez-web-audio' // From URLs const gunshot = await createSampler([ 'shot1.mp3', 'shot2.mp3', 'shot3.mp3' ]) // From mixed inputs (URLs, ArrayBuffers, Files) const snare = await createSampler([snareUrl, snareBuffer, snareFile]) // Each play uses the next sound in rotation gunshot.play() // shot1 gunshot.play() // shot2 gunshot.play() // shot3 gunshot.play() // shot1 (wraps around) ``` ## Call Signature > **createSampler**(`audioContext`, `inputs`, `opts?`): `Promise`<[`Sampler`](../classes/Sampler.md)> Defined in: [packages/core/src/index.ts:707](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L707) Create a Sampler for round-robin playback of multiple sounds. Sampler holds multiple Sound instances and cycles through them on each play, providing natural variation and preventing the "machine gun" effect of identical sounds played rapidly. ### Parameters #### audioContext `BaseAudioContext` #### inputs [`AudioInput`](../type-aliases/AudioInput.md)\[] Array of audio file URLs, ArrayBuffers, Blobs, or Files to load as sound sources #### opts? [`SamplerOptions`](../interfaces/SamplerOptions.md) Optional Sampler configuration ### Returns `Promise`<[`Sampler`](../classes/Sampler.md)> Promise resolving to a Sampler instance ### Throws If any audio file cannot be loaded or decoded ### Example ```typescript import { createSampler } from 'ez-web-audio' // From URLs const gunshot = await createSampler([ 'shot1.mp3', 'shot2.mp3', 'shot3.mp3' ]) // From mixed inputs (URLs, ArrayBuffers, Files) const snare = await createSampler([snareUrl, snareBuffer, snareFile]) // Each play uses the next sound in rotation gunshot.play() // shot1 gunshot.play() // shot2 gunshot.play() // shot3 gunshot.play() // shot1 (wraps around) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createSequence.md' --- [EZ Web Audio](../index.md) / createSequence # Function: createSequence() > **createSequence**(`transport`, `options`): [`Sequence`](../classes/Sequence.md) Defined in: [packages/core/src/index.ts:1018](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1018) Create a Sequence that schedules arbitrary callbacks at musical time positions. Sequences are tied to a Transport at creation and follow its lifecycle. Events are stored as beat positions, so live BPM changes automatically affect subsequent scheduling without re-scheduling. ## Parameters ### transport [`Transport`](../classes/Transport.md) The Transport to sync to ### options [`SequenceOptions`](../interfaces/SequenceOptions.md) Sequence configuration (length, loop, initial events) ## Returns [`Sequence`](../classes/Sequence.md) Sequence instance ## Example ```typescript import { createTransport, createSequence, createSound } from 'ez-web-audio' const transport = await createTransport({ bpm: 120, timeSignature: [4, 4] }) const kick = await createSound('kick.mp3') const seq = createSequence(transport, { length: '1m' }) seq.at('1:1:0', (time) => kick.playIn(time - ctx.currentTime)) seq.at('1:3:0', (time) => kick.playIn(time - ctx.currentTime)) transport.start() // Change BPM — events adjust automatically transport.bpm = 140 ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createSound.md' --- [EZ Web Audio](../index.md) / createSound # Function: createSound() ## Call Signature > **createSound**(`input`): `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Defined in: [packages/core/src/index.ts:435](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L435) Create a Sound from an audio file URL, ArrayBuffer, Blob, or File. Sound is for one-shot audio playback (sound effects, UI sounds). Each call to `.play()` creates a new audio source, allowing overlapping playback. Use [createTrack](createTrack.md) instead for music with pause/resume/seek. ### Parameters #### input [`AudioInput`](../type-aliases/AudioInput.md) URL string, ArrayBuffer, Blob, or File containing audio data ### Returns `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Promise resolving to a Sound instance ### Throws If the audio file cannot be loaded or decoded ### Example ```typescript import { createSound } from 'ez-web-audio' // From URL const click = await createSound('click.mp3') click.play() // From ArrayBuffer (e.g., from fetch or File API) const response = await fetch('click.mp3') const buffer = await response.arrayBuffer() const click2 = await createSound(buffer) // From File (e.g., drag-and-drop) input.addEventListener('change', async (e) => { const file = e.target.files[0] const sound = await createSound(file) sound.play() }) ``` ## Call Signature > **createSound**(`audioContext`, `input`): `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Defined in: [packages/core/src/index.ts:436](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L436) Create a Sound from an audio file URL, ArrayBuffer, Blob, or File. Sound is for one-shot audio playback (sound effects, UI sounds). Each call to `.play()` creates a new audio source, allowing overlapping playback. Use [createTrack](createTrack.md) instead for music with pause/resume/seek. ### Parameters #### audioContext `BaseAudioContext` #### input [`AudioInput`](../type-aliases/AudioInput.md) URL string, ArrayBuffer, Blob, or File containing audio data ### Returns `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Promise resolving to a Sound instance ### Throws If the audio file cannot be loaded or decoded ### Example ```typescript import { createSound } from 'ez-web-audio' // From URL const click = await createSound('click.mp3') click.play() // From ArrayBuffer (e.g., from fetch or File API) const response = await fetch('click.mp3') const buffer = await response.arrayBuffer() const click2 = await createSound(buffer) // From File (e.g., drag-and-drop) input.addEventListener('change', async (e) => { const file = e.target.files[0] const sound = await createSound(file) sound.play() }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createSounds.md' --- [EZ Web Audio](../index.md) / createSounds # Function: createSounds() ## Call Signature > **createSounds**(`urls`, `onProgress?`): `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>\[]> Defined in: [packages/core/src/index.ts:526](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L526) Load multiple sounds from an array of URLs with optional progress tracking. Loads all sounds in parallel for speed. Progress callback fires after each sound finishes loading, providing loaded count, total count, and the URL that just completed. ### Parameters #### urls `string`\[] Array of audio file URLs to load #### onProgress? (`loaded`, `total`, `url`) => `void` Optional callback fired after each sound loads ### Returns `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>\[]> Promise resolving to array of Sound instances ### Throws If any audio file cannot be loaded or decoded ### Example ```typescript import { createSounds } from 'ez-web-audio' const sounds = await createSounds( ['click.mp3', 'whoosh.mp3', 'ding.mp3'], (loaded, total, url) => console.log(`Loaded ${loaded}/${total}: ${url}`) ) ``` ## Call Signature > **createSounds**(`audioContext`, `urls`, `onProgress?`): `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>\[]> Defined in: [packages/core/src/index.ts:530](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L530) Load multiple sounds from an array of URLs with optional progress tracking. Loads all sounds in parallel for speed. Progress callback fires after each sound finishes loading, providing loaded count, total count, and the URL that just completed. ### Parameters #### audioContext `BaseAudioContext` #### urls `string`\[] Array of audio file URLs to load #### onProgress? (`loaded`, `total`, `url`) => `void` Optional callback fired after each sound loads ### Returns `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>\[]> Promise resolving to array of Sound instances ### Throws If any audio file cannot be loaded or decoded ### Example ```typescript import { createSounds } from 'ez-web-audio' const sounds = await createSounds( ['click.mp3', 'whoosh.mp3', 'ding.mp3'], (loaded, total, url) => console.log(`Loaded ${loaded}/${total}: ${url}`) ) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createSprite.md' --- [EZ Web Audio](../index.md) / createSprite # Function: createSprite() ## Call Signature > **createSprite**(`audioUrl`, `manifest`): `Promise`<[`AudioSprite`](../classes/AudioSprite.md)> Defined in: [packages/core/src/index.ts:1141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1141) Create an audio sprite from an audio file and manifest. Sprites allow playing segments of a single audio file by name. ### Parameters #### audioUrl `string` URL of the audio file #### manifest [`SpriteManifest`](../type-aliases/SpriteManifest.md) Sprite manifest with timing definitions ### Returns `Promise`<[`AudioSprite`](../classes/AudioSprite.md)> AudioSprite instance ### Example ```ts const sprite = await createSprite('sounds.mp3', { spritemap: { laser: { start: 0, end: 0.3 }, explosion: { start: 1.0, end: 2.5 } } }) sprite.play('laser', { gain: 0.5 }) ``` ## Call Signature > **createSprite**(`audioContext`, `audioUrl`, `manifest`): `Promise`<[`AudioSprite`](../classes/AudioSprite.md)> Defined in: [packages/core/src/index.ts:1142](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1142) Create an audio sprite from an audio file and manifest. Sprites allow playing segments of a single audio file by name. ### Parameters #### audioContext `BaseAudioContext` #### audioUrl `string` URL of the audio file #### manifest [`SpriteManifest`](../type-aliases/SpriteManifest.md) Sprite manifest with timing definitions ### Returns `Promise`<[`AudioSprite`](../classes/AudioSprite.md)> AudioSprite instance ### Example ```ts const sprite = await createSprite('sounds.mp3', { spritemap: { laser: { start: 0, end: 0.3 }, explosion: { start: 1.0, end: 2.5 } } }) sprite.play('laser', { gain: 0.5 }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createTrack.md' --- [EZ Web Audio](../index.md) / createTrack # Function: createTrack() ## Call Signature > **createTrack**(`input`): `Promise`<[`Track`](../classes/Track.md)> Defined in: [packages/core/src/index.ts:477](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L477) Create a Track from an audio file URL, ArrayBuffer, Blob, or File. Track extends Sound with position tracking, pause/resume, and seeking. Use Track for music or longer audio where users need playback control. Unlike Sound, only one playback can be active at a time. ### Parameters #### input [`AudioInput`](../type-aliases/AudioInput.md) URL string, ArrayBuffer, Blob, or File containing audio data ### Returns `Promise`<[`Track`](../classes/Track.md)> Promise resolving to a Track instance ### Throws If the audio file cannot be loaded or decoded ### Example ```typescript import { createTrack } from 'ez-web-audio' const song = await createTrack('song.mp3') song.play() // Pause and resume song.pause() song.resume() // From ArrayBuffer const buffer = await fetch('song.mp3').then(r => r.arrayBuffer()) const song2 = await createTrack(buffer) // Get current position console.log(song.position.string) // '0:30' ``` ## Call Signature > **createTrack**(`audioContext`, `input`): `Promise`<[`Track`](../classes/Track.md)> Defined in: [packages/core/src/index.ts:478](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L478) Create a Track from an audio file URL, ArrayBuffer, Blob, or File. Track extends Sound with position tracking, pause/resume, and seeking. Use Track for music or longer audio where users need playback control. Unlike Sound, only one playback can be active at a time. ### Parameters #### audioContext `BaseAudioContext` #### input [`AudioInput`](../type-aliases/AudioInput.md) URL string, ArrayBuffer, Blob, or File containing audio data ### Returns `Promise`<[`Track`](../classes/Track.md)> Promise resolving to a Track instance ### Throws If the audio file cannot be loaded or decoded ### Example ```typescript import { createTrack } from 'ez-web-audio' const song = await createTrack('song.mp3') song.play() // Pause and resume song.pause() song.resume() // From ArrayBuffer const buffer = await fetch('song.mp3').then(r => r.arrayBuffer()) const song2 = await createTrack(buffer) // Get current position console.log(song.position.string) // '0:30' ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createTracks.md' --- [EZ Web Audio](../index.md) / createTracks # Function: createTracks() ## Call Signature > **createTracks**(`urls`, `onProgress?`): `Promise`<[`Track`](../classes/Track.md)\[]> Defined in: [packages/core/src/index.ts:588](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L588) Load multiple tracks from an array of URLs with optional progress tracking. Mirrors [createSounds](createSounds.md) but returns Track instances. Loads all tracks in parallel for speed. Progress callback fires after each track finishes loading. ### Parameters #### urls `string`\[] Array of audio file URLs to load #### onProgress? (`loaded`, `total`, `url`) => `void` Optional callback fired after each track loads ### Returns `Promise`<[`Track`](../classes/Track.md)\[]> Promise resolving to array of Track instances ### Throws If any audio file cannot be loaded or decoded ### Example ```typescript import { createTracks } from 'ez-web-audio' const tracks = await createTracks( ['intro.mp3', 'verse.mp3', 'chorus.mp3'], (loaded, total, url) => console.log(`Loaded ${loaded}/${total}: ${url}`) ) ``` ## Call Signature > **createTracks**(`audioContext`, `urls`, `onProgress?`): `Promise`<[`Track`](../classes/Track.md)\[]> Defined in: [packages/core/src/index.ts:592](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L592) Load multiple tracks from an array of URLs with optional progress tracking. Mirrors [createSounds](createSounds.md) but returns Track instances. Loads all tracks in parallel for speed. Progress callback fires after each track finishes loading. ### Parameters #### audioContext `BaseAudioContext` #### urls `string`\[] Array of audio file URLs to load #### onProgress? (`loaded`, `total`, `url`) => `void` Optional callback fired after each track loads ### Returns `Promise`<[`Track`](../classes/Track.md)\[]> Promise resolving to array of Track instances ### Throws If any audio file cannot be loaded or decoded ### Example ```typescript import { createTracks } from 'ez-web-audio' const tracks = await createTracks( ['intro.mp3', 'verse.mp3', 'chorus.mp3'], (loaded, total, url) => console.log(`Loaded ${loaded}/${total}: ${url}`) ) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createTransport.md' --- [EZ Web Audio](../index.md) / createTransport # Function: createTransport() ## Call Signature > **createTransport**(`options`): `Promise`<[`Transport`](../classes/Transport.md)> Defined in: [packages/core/src/index.ts:977](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L977) Create a global Transport clock for multi-track synchronization. The Transport provides a Worker-backed clock that multiple BeatTracks can lock to, enabling perfect multi-track synchronization that survives background tab throttling. ### Parameters #### options [`TransportOptions`](../interfaces/TransportOptions.md) Transport configuration (bpm, timeSignature, ticksPerBeat) ### Returns `Promise`<[`Transport`](../classes/Transport.md)> Promise resolving to a Transport instance ### Example ```typescript import { createTransport, createBeatTrack } from 'ez-web-audio' const transport = await createTransport({ bpm: 120, timeSignature: [4, 4] }) const kick = await createBeatTrack(['kick.mp3'], { numBeats: 4 }) kick.syncTo(transport, { noteType: 1/4 }) transport.start() transport.on('tick', (e) => { console.log(`Position: ${e.detail.bar}:${e.detail.beat}:${e.detail.tick}`) }) ``` ## Call Signature > **createTransport**(`audioContext`, `options`): `Promise`<[`Transport`](../classes/Transport.md)> Defined in: [packages/core/src/index.ts:978](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L978) Create a global Transport clock for multi-track synchronization. The Transport provides a Worker-backed clock that multiple BeatTracks can lock to, enabling perfect multi-track synchronization that survives background tab throttling. ### Parameters #### audioContext `BaseAudioContext` #### options [`TransportOptions`](../interfaces/TransportOptions.md) Transport configuration (bpm, timeSignature, ticksPerBeat) ### Returns `Promise`<[`Transport`](../classes/Transport.md)> Promise resolving to a Transport instance ### Example ```typescript import { createTransport, createBeatTrack } from 'ez-web-audio' const transport = await createTransport({ bpm: 120, timeSignature: [4, 4] }) const kick = await createBeatTrack(['kick.mp3'], { numBeats: 4 }) kick.syncTo(transport, { noteType: 1/4 }) transport.start() transport.on('tick', (e) => { console.log(`Position: ${e.detail.bar}:${e.detail.beat}:${e.detail.tick}`) }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/createWhiteNoise.md' --- [EZ Web Audio](../index.md) / createWhiteNoise # Function: createWhiteNoise() ## Call Signature > **createWhiteNoise**(): `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Defined in: [packages/core/src/index.ts:1214](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1214) Create a Sound containing white noise. White noise is useful for sound effects (rain, static, wind) and as a synthesis building block when combined with filters. ### Returns `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Promise resolving to a Sound containing 1 second of white noise ### Example ```typescript import { createWhiteNoise, createFilterEffect } from 'ez-web-audio' // Create white noise const noise = await createWhiteNoise() noise.play() // Filter white noise to create wind-like sound const wind = await createWhiteNoise() const lowpass = createFilterEffect('lowpass', { frequency: 400 }) wind.addEffect(lowpass) wind.play() ``` ## Call Signature > **createWhiteNoise**(`audioContext`): `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Defined in: [packages/core/src/index.ts:1215](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1215) Create a Sound containing white noise. White noise is useful for sound effects (rain, static, wind) and as a synthesis building block when combined with filters. ### Parameters #### audioContext `BaseAudioContext` ### Returns `Promise`<[`Sound`](../classes/Sound.md)<[`BaseSoundEventMap`](../interfaces/BaseSoundEventMap.md)>> Promise resolving to a Sound containing 1 second of white noise ### Example ```typescript import { createWhiteNoise, createFilterEffect } from 'ez-web-audio' // Create white noise const noise = await createWhiteNoise() noise.play() // Filter white noise to create wind-like sound const wind = await createWhiteNoise() const lowpass = createFilterEffect('lowpass', { frequency: 400 }) wind.addEffect(lowpass) wind.play() ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/crossfade.md' --- [EZ Web Audio](../index.md) / crossfade # Function: crossfade() > **crossfade**(`fromTrack`, `toTrack`, `duration`, `options?`): `Promise`<`void`> Defined in: [packages/core/src/utils/crossfade.ts:121](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/crossfade.ts#L121) ## Parameters ### fromTrack [`Track`](../classes/Track.md) ### toTrack [`Track`](../classes/Track.md) ### duration `number` ### options? [`CrossfadeOptions`](../interfaces/CrossfadeOptions.md) ## Returns `Promise`<`void`> --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/formatPosition.md' --- [EZ Web Audio](../index.md) / formatPosition # Function: formatPosition() > **formatPosition**(`pos`): `string` Defined in: [packages/core/src/transport.ts:69](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L69) Format a TransportPosition as a "bar:beat:tick" string. ## Parameters ### pos [`TransportPosition`](../interfaces/TransportPosition.md) ## Returns `string` ## Example ```typescript formatPosition({ bar: 1, beat: 3, tick: 2, seconds: 1.5 }) // Returns "1:3:2" ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/getAudioContext.md' --- [EZ Web Audio](../index.md) / getAudioContext # Function: getAudioContext() > **getAudioContext**(): `Promise`<`AudioContext`> Defined in: [packages/core/src/index.ts:160](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L160) Get the shared AudioContext instance, creating it lazily if it doesn't exist. The library uses a single AudioContext instance for all audio operations. This function creates the context automatically on first call. ## Returns `Promise`<`AudioContext`> The shared AudioContext instance ## Example ```typescript import { getAudioContext } from 'ez-web-audio' // Get the AudioContext for custom Web Audio operations const ctx = await getAudioContext() const oscillator = ctx.createOscillator() ``` --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/functions/getAudioContextSync.md --- [EZ Web Audio](../index.md) / getAudioContextSync # Function: getAudioContextSync() > **getAudioContextSync**(): `AudioContext` Defined in: [packages/core/src/index.ts:193](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L193) Get the shared AudioContext synchronously, creating it if it does not exist. Unlike [getAudioContext](getAudioContext.md), this does NOT run `initAudio()` (no iOS unmute workaround, no suspended→running unlock). Prefer the async [getAudioContext](getAudioContext.md) for normal use. Reach for the sync variant only when you must obtain the context *before* the first sound is created and cannot await — for example installing a master bus via [setMasterDestination](setMasterDestination.md) synchronously inside a user-gesture handler so that instances created later in the same tick already route through it. If called before a user gesture the context will be `suspended`; a subsequent `getAudioContext()`/factory call (which does run `initAudio()`) resumes it. ## Returns `AudioContext` The shared AudioContext instance ## Example ```typescript import { getAudioContextSync, setMasterDestination } from 'ez-web-audio' document.addEventListener('pointerdown', () => { const ctx = getAudioContextSync() const limiter = ctx.createDynamicsCompressor() limiter.connect(ctx.destination) setMasterDestination(limiter) // set before any sound is created this gesture }, { capture: true, once: true }) ``` --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/functions/getMasterDestination.md --- [EZ Web Audio](../index.md) / getMasterDestination # Function: getMasterDestination() > **getMasterDestination**(): `AudioNode` | `null` Defined in: [packages/core/src/index.ts:241](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L241) Get the current global master destination set via [setMasterDestination](setMasterDestination.md), or `null` when audio routes directly to the hardware output. ## Returns `AudioNode` | `null` The master destination node, or `null` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/initAudio.md' --- [EZ Web Audio](../index.md) / initAudio # Function: initAudio() > **initAudio**(`useIosMuteWorkaround`): `Promise`<`void`> Defined in: [packages/core/src/index.ts:118](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L118) Optionally initialize the audio system explicitly. The library creates the AudioContext lazily on first use, so calling this function is not required. Use it when you need explicit control over initialization timing (iOS mute workaround, pre-warming the context). Note: If called explicitly, it must be in response to a user interaction (click, tap, keypress) due to browser autoplay policies. ## Parameters ### useIosMuteWorkaround `boolean` = `true` Whether to apply iOS mute switch workaround (default: true) ## Returns `Promise`<`void`> ## Throws If AudioContext cannot be created or is interrupted ## Example ```typescript import { initAudio, createSound } from 'ez-web-audio' // Optional explicit initialization button.addEventListener('click', async () => { await initAudio() // Optional — for explicit control const sound = await createSound('click.mp3') sound.play() }) // Or just use factory functions directly (AudioContext created automatically) button.addEventListener('click', async () => { const sound = await createSound('click.mp3') sound.play() }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/isHowlerManifest.md' --- [EZ Web Audio](../index.md) / isHowlerManifest # Function: isHowlerManifest() > **isHowlerManifest**(`manifest`): `manifest is HowlerSpriteManifest` Defined in: [packages/core/src/sprite.ts:87](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L87) Type guard that checks whether a manifest is in Howler.js format. ## Parameters ### manifest [`SpriteManifest`](../type-aliases/SpriteManifest.md) The manifest to check ## Returns `manifest is HowlerSpriteManifest` `true` if the manifest has a `sprite` key (Howler format) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/functions/isMusicalTimeNotation.md --- [EZ Web Audio](../index.md) / isMusicalTimeNotation # Function: isMusicalTimeNotation() > **isMusicalTimeNotation**(`value`): `value is string` Defined in: [packages/core/src/utils/musical-time.ts:170](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/musical-time.ts#L170) Type guard for valid musical time notation strings. Returns true if the value is a string that can be parsed as musical time notation. Does not accept numeric values (use `typeof value === 'number'` separately). ## Parameters ### value `unknown` Value to check ## Returns `value is string` true if value is a valid musical time notation string ## Example ```typescript isMusicalTimeNotation('4n') // true isMusicalTimeNotation('8t') // true isMusicalTimeNotation('1m') // true isMusicalTimeNotation('2:1:0') // true isMusicalTimeNotation('xyz') // false isMusicalTimeNotation(42) // false ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/isPreloaded.md' --- [EZ Web Audio](../index.md) / isPreloaded # Function: isPreloaded() > **isPreloaded**(`url`): `boolean` Defined in: [packages/core/src/preload.ts:130](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/preload.ts#L130) Check if a URL is already preloaded. ## Parameters ### url `string` URL to check ## Returns `boolean` true if URL is in cache --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/MusicallyAware.md' --- [EZ Web Audio](../index.md) / MusicallyAware # Function: MusicallyAware() > **MusicallyAware**<`TBase`>(`Base`): {(...`args`): `MusicalIdentity`<`TBase`>; `prototype`: `MusicalIdentity`<`any`>; } & `TBase` Defined in: [packages/core/src/musical-identity.ts:58](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/musical-identity.ts#L58) ## Type Parameters ### TBase `TBase` *extends* `Constructor`<`any`> ## Parameters ### Base `TBase` ## Returns --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/musicalTimeToBeats.md' --- [EZ Web Audio](../index.md) / musicalTimeToBeats # Function: musicalTimeToBeats() > **musicalTimeToBeats**(`notation`, `beatsPerBar`, `ticksPerBeat`): `number` Defined in: [packages/core/src/utils/musical-time.ts:50](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/musical-time.ts#L50) Convert musical time notation to beats (BPM-independent). Supports: * Note values: '1n' (whole=4), '2n' (half=2), '4n' (quarter=1), '8n', '16n', '32n' * Triplets: '4t', '8t', '16t' (2/3 of the base note value) * Dotted notes: '4n.', '8n.' (1.5x the base note value) * Measures: '1m', '2m', '4m' (beatsPerBar \* count) * Bar:beat:tick: '2:1:0' (positional, 1-indexed bar/beat, 0-indexed tick) * Numeric passthrough: number values returned as-is ## Parameters ### notation [`MusicalTimeNotation`](../type-aliases/MusicalTimeNotation.md) Musical time notation string or numeric beat value ### beatsPerBar `number` = `4` Beats per bar for measure/position calculations (default: 4) ### ticksPerBeat `number` = `4` Ticks per beat for position calculations (default: 4) ## Returns `number` Number of beats ## Throws if notation is invalid ## Example ```typescript musicalTimeToBeats('4n') // 1.0 (quarter note = 1 beat) musicalTimeToBeats('8t') // 0.333... (eighth triplet) musicalTimeToBeats('4n.') // 1.5 (dotted quarter) musicalTimeToBeats('2m') // 8 (two bars in 4/4) musicalTimeToBeats('2:1:0') // 4 (bar 2, beat 1 in 4/4) musicalTimeToBeats('1m', 3) // 3 (one bar in 3/4) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/muteAll.md' --- [EZ Web Audio](../index.md) / muteAll # Function: muteAll() > **muteAll**(`muted`): `void` Defined in: [packages/core/src/index.ts:295](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L295) Mute or unmute every sound routed through the shared master bus (R2#7). Sugar over [setMasterDestination](setMasterDestination.md) — see [setGlobalVolume](setGlobalVolume.md) for the "only instances created after the first call" caveat, which applies here too. Unmuting restores the volume last set via [setGlobalVolume](setGlobalVolume.md) (default 1). ## Parameters ### muted `boolean` `true` to silence everything, `false` to restore the last volume ## Returns `void` ## Example ```typescript import { muteAll } from 'ez-web-audio' document.getElementById('mute-btn')!.addEventListener('click', () => { isMuted = !isMuted muteAll(isMuted) }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/normalizeManifest.md' --- [EZ Web Audio](../index.md) / normalizeManifest # Function: normalizeManifest() > **normalizeManifest**(`manifest`): [`AudiospriteManifest`](../interfaces/AudiospriteManifest.md) Defined in: [packages/core/src/sprite.ts:109](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L109) Normalize any supported manifest format to audiosprite format. If the manifest is already in audiosprite format, it is returned as-is (same reference). Howler manifests are converted: ms tuples become seconds-based `{start, end, loop}` objects. ## Parameters ### manifest [`SpriteManifest`](../type-aliases/SpriteManifest.md) A manifest in either Howler or audiosprite format ## Returns [`AudiospriteManifest`](../interfaces/AudiospriteManifest.md) An `AudiospriteManifest` with all values in seconds ## Example ```typescript // Howler format is normalized automatically const normalized = normalizeManifest({ sprite: { laser: [0, 300], bgm: [4000, 500, true] } }) // Result: { spritemap: { laser: { start: 0, end: 0.3, loop: false }, bgm: { start: 4, end: 4.5, loop: true } } } ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/parseMusicalTime.md' --- [EZ Web Audio](../index.md) / parseMusicalTime # Function: parseMusicalTime() > **parseMusicalTime**(`notation`, `bpm`, `timeSignature`, `ticksPerBeat`): `number` Defined in: [packages/core/src/utils/musical-time.ts:130](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/musical-time.ts#L130) Convert musical time notation to seconds given BPM and time signature. This is the primary user-facing function. It converts any musical time notation to an absolute duration in seconds, accounting for BPM and time signature. ## Parameters ### notation [`MusicalTimeNotation`](../type-aliases/MusicalTimeNotation.md) Musical time notation string or numeric beat value ### bpm `number` Tempo in beats per minute (must be > 0) ### timeSignature \[`number`, `number`] = `...` Time signature as \[beatsPerBar, beatUnit] (default: \[4, 4]) ### ticksPerBeat `number` = `4` Ticks per beat for position calculations (default: 4) ## Returns `number` Duration in seconds ## Throws if BPM <= 0 or notation is invalid ## Example ```typescript parseMusicalTime('4n', 120) // 0.5 seconds parseMusicalTime('1m', 120) // 2.0 seconds (one bar of 4/4 at 120 BPM) parseMusicalTime('4n', 60) // 1.0 second parseMusicalTime('1m', 120, [3, 4]) // 1.5 seconds (one bar of 3/4 at 120 BPM) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/pauseAll.md' --- [EZ Web Audio](../index.md) / pauseAll # Function: pauseAll() > **pauseAll**(`tracks`): `Promise`<`void`> Defined in: [packages/core/src/utils/collections.ts:85](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/collections.ts#L85) Pauses all tracks in the provided array. Supports nested arrays which are recursively flattened. Skips items that don't have a pause method (only Track has pause). Uses best-effort error handling - attempts to pause all tracks even if some fail. ## Parameters ### tracks `NestedArray`<[`Track`](../classes/Track.md)> Array of Track instances or nested arrays of Tracks ## Returns `Promise`<`void`> ## Throws CollectionError if any tracks fail to pause ## Example ```typescript const tracks = [track1, track2, [track3, track4]] await pauseAll(tracks) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/playAll.md' --- [EZ Web Audio](../index.md) / playAll # Function: playAll() > **playAll**(`sounds`): `Promise`<`void`> Defined in: [packages/core/src/utils/collections.ts:125](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/collections.ts#L125) Plays all playable sounds in the provided array. Supports nested arrays which are recursively flattened. Uses best-effort error handling - attempts to play all sounds even if some fail. ## Parameters ### sounds `NestedArray`<[`Playable`](../interfaces/Playable.md)> Array of Playable instances or nested arrays of Playables ## Returns `Promise`<`void`> ## Throws CollectionError if any sounds fail to play ## Example ```typescript const sounds = [sound1, sound2, [sound3, sound4]] await playAll(sounds) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/playTogether.md' --- [EZ Web Audio](../index.md) / playTogether # Function: playTogether() ## Call Signature > **playTogether**(`playables`): `Promise`<`void`> Defined in: [packages/core/src/utils/play-together.ts:39](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/play-together.ts#L39) Play multiple sounds synchronized to the exact same AudioContext timestamp. Uses `playAt()` with a shared start time slightly in the future to ensure all sources begin at precisely the same moment. This is more accurate than calling `play()` on each sound sequentially, which would introduce tiny timing differences. ### Parameters #### playables [`Playable`](../interfaces/Playable.md)\[] Array of Playable instances (Sound, Track, Oscillator, etc.); an explicit BaseAudioContext may be passed as the first argument instead ### Returns `Promise`<`void`> Promise that resolves when all sounds have started ### Example ```typescript import { createSound, playTogether } from 'ez-web-audio' const kick = await createSound('kick.mp3') const snare = await createSound('snare.mp3') const hihat = await createSound('hihat.mp3') await playTogether([kick, snare, hihat]) // All three start at the exact same AudioContext time // With explicit AudioContext await playTogether(myAudioContext, [kick, snare, hihat]) ``` ## Call Signature > **playTogether**(`audioContext`, `playables`): `Promise`<`void`> Defined in: [packages/core/src/utils/play-together.ts:40](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/play-together.ts#L40) Play multiple sounds synchronized to the exact same AudioContext timestamp. Uses `playAt()` with a shared start time slightly in the future to ensure all sources begin at precisely the same moment. This is more accurate than calling `play()` on each sound sequentially, which would introduce tiny timing differences. ### Parameters #### audioContext `BaseAudioContext` #### playables [`Playable`](../interfaces/Playable.md)\[] Array of Playable instances (Sound, Track, Oscillator, etc.); an explicit BaseAudioContext may be passed as the first argument instead ### Returns `Promise`<`void`> Promise that resolves when all sounds have started ### Example ```typescript import { createSound, playTogether } from 'ez-web-audio' const kick = await createSound('kick.mp3') const snare = await createSound('snare.mp3') const hihat = await createSound('hihat.mp3') await playTogether([kick, snare, hihat]) // All three start at the exact same AudioContext time // With explicit AudioContext await playTogether(myAudioContext, [kick, snare, hihat]) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/preload.md' --- [EZ Web Audio](../index.md) / preload # Function: preload() > **preload**(`urls`, `signal?`): `Promise`<`void`> Defined in: [packages/core/src/preload.ts:64](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/preload.ts#L64) Preload audio URLs into cache for faster Sound/Track creation. ## Parameters ### urls Single URL or array of URLs to preload `string` | `string`\[] ### signal? `AbortSignal` Optional AbortSignal to cancel in-flight fetches ## Returns `Promise`<`void`> Promise that resolves when all URLs are cached ## Throws If any URL fails to load (after attempting all). `instanceof AudioError` still matches; `.errors` carries the per-URL [AudioLoadError](../classes/AudioLoadError.md) failures for callers that need to know which URLs failed and why. --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/functions/preventEventDefaults.md --- [EZ Web Audio](../index.md) / preventEventDefaults # Function: preventEventDefaults() > **preventEventDefaults**(`key`): () => `void` Defined in: [packages/core/src/index.ts:1426](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1426) Prevent default behavior for common interaction events on an element. Useful for piano keys or other interactive audio controls where you want to prevent text selection, context menus, and drag-and-drop behaviors. ## Parameters ### key `HTMLElement` HTML element to attach event prevention to ## Returns > (): `void` ### Returns `void` ## Remarks This is a plain DOM convenience — a thin `addEventListener`/`removeEventListener` wrapper around an `HTMLElement` — not a framework hook, despite living in the root package namespace alongside factory functions (R1#7). Safe to call from vanilla JS, React, Vue, or any other framework. May move under a `/dom` subpath at a future major version for clarity; kept in the root namespace for now (churn not worth it pre-1.0). ## Example ```typescript import { preventEventDefaults } from 'ez-web-audio' const pianoKey = document.getElementById('key-c4') preventEventDefaults(pianoKey) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/setDebugHandler.md' --- [EZ Web Audio](../index.md) / setDebugHandler # Function: setDebugHandler() > **setDebugHandler**(`handler`): `void` Defined in: [packages/core/src/debug/index.ts:59](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/debug/index.ts#L59) Set a custom debug handler. Pass null to restore the default console.log handler. ## Parameters ### handler Custom handler function, or null for default (`msg`) => `void` | `null` ## Returns `void` ## Example ```ts const messages: DebugMessage[] = [] setDebugHandler((msg) => messages.push(msg)) // ... run code ... console.log(messages) // All debug messages captured ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/setDebugMode.md' --- [EZ Web Audio](../index.md) / setDebugMode # Function: setDebugMode() > **setDebugMode**(`enabled`): `void` Defined in: [packages/core/src/debug/index.ts:42](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/debug/index.ts#L42) Enable or disable global debug mode. When enabled, all sounds will log lifecycle events (play, stop, end), connection changes, and warnings (like suspended AudioContext). ## Parameters ### enabled `boolean` Whether to enable debug mode ## Returns `void` ## Example ```ts setDebugMode(true) await sound.play() // Logs: [ez-audio:event] [0.000] mySound: play ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/setGlobalVolume.md' --- [EZ Web Audio](../index.md) / setGlobalVolume # Function: setGlobalVolume() > **setGlobalVolume**(`value`): `void` Defined in: [packages/core/src/index.ts:272](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L272) Set the global volume applied to every sound routed through the shared master bus (R2#7). This is sugar over [setMasterDestination](setMasterDestination.md): the first call lazily creates a managed `GainNode` wired to the hardware destination and installs it as the master destination, so instances created afterward pick it up automatically. Only instances created AFTER the first `setGlobalVolume()`/`muteAll()` call route through the managed bus — existing instances keep their prior routing (move one with `instance.setDestination(...)` if needed). If you already installed your own bus via [setMasterDestination](setMasterDestination.md) (e.g. a limiter), call `setGlobalVolume()`/`muteAll()` first so your own call wins, or chain your node in front of the managed gain yourself. ## Parameters ### value `number` Volume from 0 (silent) to 1 (full). Throws a [ValidationError](../classes/ValidationError.md) for negative values, warns on the console above 1 — same rule as `BaseSound.changeGainTo()`. ## Returns `void` ## Example ```typescript import { createSound, setGlobalVolume } from 'ez-web-audio' setGlobalVolume(0.5) // app-wide volume knob, set once at startup const music = await createSound('theme.mp3') music.play() // plays at half the master volume ``` --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/functions/setMasterDestination.md --- [EZ Web Audio](../index.md) / setMasterDestination # Function: setMasterDestination() > **setMasterDestination**(`node`): `void` Defined in: [packages/core/src/index.ts:231](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L231) Route all subsequently-created audio through a master destination node. By default every sound, oscillator, sampler, beat track, layered sound, grain player, poly synth, font, and sprite connects its final output to the hardware output (`audioContext.destination`). Call `setMasterDestination` with an `AudioNode` to insert a shared master stage in front of the hardware — a limiter, a peak meter, a master gain, or an offline-render target — so a whole mix routes through one place. Rules: * The `node` MUST belong to the shared library context ([getAudioContext](getAudioContext.md)). Web Audio nodes cannot connect across `AudioContext`s. * Only instances created AFTER this call pick up the destination. Move an existing instance with `instance.setDestination(node)`. * Pass `null` to restore direct-to-hardware routing for future instances. ## Parameters ### node The master destination node, or `null` to clear it `AudioNode` | `null` ## Returns `void` ## Example ```typescript import { getAudioContext, setMasterDestination, createSound } from 'ez-web-audio' const ctx = await getAudioContext() const limiter = ctx.createDynamicsCompressor() limiter.connect(ctx.destination) setMasterDestination(limiter) // everything created next runs through the limiter const sound = await createSound('hit.mp3') sound.play() // sound → ... → limiter → hardware setMasterDestination(null) // later instances go straight to hardware again ``` --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/functions/setPreloadCacheLimit.md --- [EZ Web Audio](../index.md) / setPreloadCacheLimit # Function: setPreloadCacheLimit() > **setPreloadCacheLimit**(`limit`): `void` Defined in: [packages/core/src/preload.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/preload.ts#L49) Set the maximum number of cached preload responses. Oldest entries are evicted when the limit is exceeded. ## Parameters ### limit `number` Maximum number of entries (default: 100) ## Returns `void` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/stopAll.md' --- [EZ Web Audio](../index.md) / stopAll # Function: stopAll() > **stopAll**(`sounds`): `Promise`<`void`> Defined in: [packages/core/src/utils/collections.ts:45](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/collections.ts#L45) Stops all playable sounds in the provided array. Supports nested arrays which are recursively flattened. Uses best-effort error handling - attempts to stop all sounds even if some fail. ## Parameters ### sounds `NestedArray`<[`Playable`](../interfaces/Playable.md)> Array of Playable instances or nested arrays of Playables ## Returns `Promise`<`void`> ## Throws CollectionError if any sounds fail to stop ## Example ```typescript const sounds = [sound1, sound2, [sound3, sound4]] await stopAll(sounds) ``` --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/functions/useInteractionMethods.md --- [EZ Web Audio](../index.md) / useInteractionMethods # Function: useInteractionMethods() > **useInteractionMethods**(`key`, `player`): `Promise`<() => `void`> Defined in: [packages/core/src/index.ts:1482](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1482) Attach play/stop handlers to an element for touch and mouse interactions. Binds touchstart/mousedown to play() and touchend/mouseup/mouseleave to stop(). Automatically initializes audio on first interaction. ## Parameters ### key `HTMLElement` HTML element to attach handlers to ### player [`InteractionTarget`](../interfaces/InteractionTarget.md) Object with play() and stop() methods ## Returns `Promise`<() => `void`> ## Remarks Like [preventEventDefaults](preventEventDefaults.md), this is a plain DOM convenience — not a framework hook — despite the `use*` prefix (R1#7). Framework-agnostic; safe to call from vanilla JS, React, Vue, etc. ## Example ```typescript import { useInteractionMethods, createOscillator } from 'ez-web-audio' const synth = await createOscillator({ frequency: 440 }) const pianoKey = document.getElementById('key-a4') await useInteractionMethods(pianoKey, synth) // Now touching/clicking the element plays the synth ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/functions/wrapEffect.md' --- [EZ Web Audio](../index.md) / wrapEffect # Function: wrapEffect() ## Call Signature > **wrapEffect**(`externalEffect`): [`EffectWrapper`](../classes/EffectWrapper.md) Defined in: [packages/core/src/effects/effect-wrapper.ts:238](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L238) Factory function to wrap an external effect with the Effect interface. Use this for effects from libraries like Tuna.js, or custom AudioNodes like WaveShaperNode that only have a connect() method. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### externalEffect [`ExternalEffect`](../interfaces/ExternalEffect.md) The external effect to wrap (or AudioContext as first arg for backwards compatibility) ### Returns [`EffectWrapper`](../classes/EffectWrapper.md) A new EffectWrapper instance implementing the Effect interface ### Example ```typescript // Without AudioContext (recommended) const wrapped = wrapEffect(distortion) // With explicit AudioContext (backwards compatible) const wrapped = wrapEffect(audioContext, distortion) ``` ## Call Signature > **wrapEffect**(`audioContext`, `externalEffect`): [`EffectWrapper`](../classes/EffectWrapper.md) Defined in: [packages/core/src/effects/effect-wrapper.ts:239](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L239) Factory function to wrap an external effect with the Effect interface. Use this for effects from libraries like Tuna.js, or custom AudioNodes like WaveShaperNode that only have a connect() method. AudioContext is optional. If omitted, uses the shared library AudioContext. ### Parameters #### audioContext `AudioContext` #### externalEffect [`ExternalEffect`](../interfaces/ExternalEffect.md) The external effect to wrap (or AudioContext as first arg for backwards compatibility) ### Returns [`EffectWrapper`](../classes/EffectWrapper.md) A new EffectWrapper instance implementing the Effect interface ### Example ```typescript // Without AudioContext (recommended) const wrapped = wrapEffect(distortion) // With explicit AudioContext (backwards compatible) const wrapped = wrapEffect(audioContext, distortion) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/guide/getting-started.md' description: >- Learn how to install and use EZ Web Audio to play sounds, create synthesizers, and build audio applications in JavaScript and TypeScript. Quick setup guide with code examples. --- # Getting Started Get up and running with EZ Web Audio in under 5 minutes. ## Installation ::: code-group ```bash [pnpm] pnpm add ez-web-audio ``` ```bash [npm] npm install ez-web-audio ``` ```bash [yarn] yarn add ez-web-audio ``` ::: ## Your First Sound Play a sound file with just a few lines of code: ```typescript import { createSound } from 'ez-web-audio' document.querySelector('button')?.addEventListener('click', async () => { const sound = await createSound('/sounds/click.mp3') sound.play() }) ``` ### Loading from Other Sources `createSound()` and `createTrack()` also accept `ArrayBuffer`, `Blob`, or `File` inputs — not just URL strings. This is useful for file uploads, drag-and-drop, or pre-fetched data: ```typescript // From a file input input.addEventListener('change', async (e) => { const file = (e.target as HTMLInputElement).files![0] const sound = await createSound(file) sound.play() }) // From a pre-fetched ArrayBuffer const buffer = await fetch('/sounds/click.mp3').then(r => r.arrayBuffer()) const sound = await createSound(buffer) ``` The `AudioInput` type (`string | ArrayBuffer | Blob | File`) is exported for use in your own function signatures. ### AudioContext & User Interaction Browsers require a user interaction (click, tap, keypress) before playing audio. This is a security feature to prevent auto-playing sounds. EZ Web Audio handles this automatically — the AudioContext is created lazily when you first call a factory function like `createSound()` or `createOscillator()`. ::: tip You don't need to call `initAudio()`. The library creates and manages the AudioContext automatically. Just make sure your first audio call happens inside a user interaction handler (click, tap, keypress). ::: ::: details Advanced: Explicit initialization If you want explicit control over initialization timing (e.g., pre-warming the context on a loading screen), you can call `initAudio()`. The same AudioContext is shared across the entire library — calling `initAudio()` early just ensures it's ready before any sound is created. ```typescript import { createSound, initAudio } from 'ez-web-audio' button.addEventListener('click', async () => { await initAudio() // Optional — for explicit control const sound = await createSound('/sounds/click.mp3') sound.play() }) ``` ::: ## Playing Music Tracks For longer audio files with pause/resume: ```typescript import { createTrack } from 'ez-web-audio' button.addEventListener('click', async () => { const track = await createTrack('/music/song.mp3') track.play() // Control playback pauseBtn.onclick = () => track.pause() resumeBtn.onclick = () => track.resume() seekBtn.onclick = () => track.seek(30).as('seconds') // Jump to 30 seconds }) ``` ### Sound vs Track | Feature | Sound | Track | |---------|-------|-------| | Use case | Short sounds (clicks, effects) | Music, long audio | | Overlap | Multiple plays overlap | One play at a time | | Pause/Resume | No | Yes | | Seek | No | Yes | | Position tracking | No | Yes | ## Generating Sounds Create sounds from scratch with oscillators: ```typescript import { createOscillator } from 'ez-web-audio' button.addEventListener('click', async () => { const synth = await createOscillator({ frequency: 440, // A4 note type: 'sine' // sine, square, sawtooth, or triangle }) synth.play() // Stop after 1 second setTimeout(() => synth.stop(), 1000) }) ``` ### With ADSR Envelope For more natural-sounding synthesis, add an envelope: ```typescript const piano = await createOscillator({ frequency: 440, type: 'triangle', envelope: { attack: 0.01, // Quick attack decay: 0.3, // Decay over 0.3 seconds sustain: 0.4, // Sustain at 40% volume release: 0.5 // Fade out over 0.5 seconds } }) piano.play() // Call stop() to trigger the release phase piano.stop() ``` ## Controlling Volume and Pan All sounds support gain (volume) and pan (stereo position): ```typescript const sound = await createSound('/sounds/effect.mp3') // Set volume to 50% sound.changeGainTo(0.5) // Pan to the left sound.changePanTo(-1) // -1 = left, 0 = center, 1 = right sound.play() ``` ### Scheduled Parameter Changes You can also schedule parameter changes relative to play time: ```typescript const sound = await createSound('/sounds/whoosh.mp3') // Fade in over 1 second sound.onPlaySet('gain').to(0).endingAt(1, 'exponential') sound.play() // Starts silent, fades in ``` ## Adding Effects Apply effects like filters to shape your sound: ```typescript import { createFilterEffect, createSound } from 'ez-web-audio' const sound = await createSound('/sounds/vocal.mp3') // Create a lowpass filter (no AudioContext needed) const filter = createFilterEffect('lowpass', { frequency: 800, // Cut frequencies above 800Hz q: 1.0 // Resonance }) sound.addEffect(filter) sound.play() // Sound plays through the filter ``` ### Built-in Effects EZ Web Audio includes five built-in effects that work with any sound: ```typescript import { createDelay, createReverb, createSound } from 'ez-web-audio' const guitar = await createSound('/sounds/guitar.mp3') // Add delay and reverb const delay = createDelay({ time: 0.3, feedback: 0.4, wet: 0.3 }) const reverb = createReverb({ decay: 2.0, wet: 0.2 }) guitar.addEffect(delay) guitar.addEffect(reverb) guitar.play() ``` Available effects: `createDelay`, `createReverb`, `createDistortion`, `createCompressor`, `createEQ`. All support wet/dry mix and bypass. ## Polyphonic Synth Play multiple notes simultaneously with PolySynth: ```typescript import { createPolySynth } from 'ez-web-audio' const synth = await createPolySynth({ type: 'sawtooth', maxVoices: 8, envelope: { attack: 0.01, decay: 0.3, sustain: 0.4, release: 0.5 } }) // Play a chord synth.play({ frequency: 261.6 }) // C4 synth.play({ frequency: 329.6 }) // E4 synth.play({ frequency: 392.0 }) // G4 ``` ## Transport & Sequencing Sync multiple BeatTracks to a shared clock: ```typescript import { createBeatTrack, createTransport } from 'ez-web-audio' const transport = await createTransport({ bpm: 120, timeSignature: [4, 4] }) const kick = await createBeatTrack(['/sounds/kick.wav'], { numBeats: 4 }) const hihat = await createBeatTrack(['/sounds/hihat.wav'], { numBeats: 8 }) kick.setPattern([1, 0, 1, 0]) hihat.setPattern([1, 1, 1, 1, 1, 1, 1, 1]) kick.syncTo(transport, { noteType: 1 / 4 }) hihat.syncTo(transport, { noteType: 1 / 8 }) transport.start() // Both tracks play in sync ``` Schedule callbacks at musical time divisions with Sequence: ```typescript import { createSequence, createSound, createTransport } from 'ez-web-audio' const transport = await createTransport({ bpm: 120 }) const bell = await createSound('/sounds/bell.mp3') const seq = createSequence(transport, { length: '2m', loop: true }) seq.at('1:1:0', () => bell.play()) // Beat 1 of bar 1 seq.at('2:1:0', () => bell.play()) // Beat 1 of bar 2 transport.start() ``` ## Preloading Audio For responsive applications, preload audio files before they're needed: ```typescript import { createSound, isPreloaded, preload } from 'ez-web-audio' // Preload during app initialization await preload(['/sounds/click.mp3', '/sounds/whoosh.mp3']) // Later, sounds load instantly from cache if (isPreloaded('/sounds/click.mp3')) { const sound = await createSound('/sounds/click.mp3') // Uses cached data sound.play() } ``` ### Batch Loading Load multiple sounds at once with progress tracking: ```typescript import { createSounds } from 'ez-web-audio' const sounds = await createSounds( ['/sounds/click.mp3', '/sounds/whoosh.mp3', '/sounds/ding.mp3'], (loaded, total) => console.log(`Loaded ${loaded}/${total}`) ) ``` ## Complete Example Here's a complete example combining multiple features: ```typescript import { createDelay, createOscillator, createSound, createTrack } from 'ez-web-audio' // Wait for user interaction document.getElementById('start')?.addEventListener('click', async () => { // Sound effect for UI feedback const click = await createSound('/sounds/click.mp3') click.changeGainTo(0.5) // Background music with delay effect const music = await createTrack('/music/background.mp3') music.changeGainTo(0.3) const delay = createDelay({ time: 0.25, feedback: 0.3, wet: 0.15 }) music.addEffect(delay) music.play() // Synthesized notification sound const notification = await createOscillator({ frequency: 880, type: 'sine', envelope: { attack: 0.01, decay: 0.1, sustain: 0, release: 0.1 } }) // Wire up UI document.querySelectorAll('button').forEach((btn) => { btn.addEventListener('click', () => click.play()) }) document.getElementById('notify')?.addEventListener('click', () => { notification.play() notification.stop() }) document.getElementById('pause')?.addEventListener('click', () => music.pause()) document.getElementById('resume')?.addEventListener('click', () => music.resume()) }) ``` ## Next Steps * [Core Concepts](/guide/concepts) - Understand the library architecture * [Transport & Sequencing](/guide/transport) - Sync tracks with a shared clock * [PolySynth](/guide/poly-synth) - Polyphonic synthesizer with voice management * [GrainPlayer](/guide/grain-player) - Granular synthesis from audio buffers * [LFO](/guide/lfo) - Modulate parameters with low-frequency oscillators * [Interactive Examples](/examples/) - Try features in your browser * [API Reference](/api/) - Complete documentation --- --- url: 'https://sethbrasile.github.io/ez-web-audio/guide/grain-player.md' description: >- Create evolving textures and pad sounds from audio buffers using granular synthesis with independent pitch, position, and grain parameter control. --- # GrainPlayer GrainPlayer creates continuous textures and pad sounds from an audio buffer using granular synthesis. It works by scheduling many overlapping short "grains" of audio, each with a smooth Hann window envelope to prevent clicks. ## Basic Usage ```typescript import { createGrainPlayer, createSound } from 'ez-web-audio' // Load an audio buffer const sound = await createSound('/sounds/pad.mp3') const grains = await createGrainPlayer(sound.audioBuffer, { grainSize: 0.1, // 100ms grains overlap: 0.05, // 50ms overlap jitter: 0.1 // Random scatter for organic texture }) grains.play() ``` ## Key Parameters All parameters can be changed in real-time during playback: ```typescript grains.position = 0.5 // Scrub to middle of buffer (0-1) grains.pitch = 7 // Pitch up a perfect fifth (semitones) grains.grainSize = 0.2 // Larger grains = smoother, more recognizable grains.overlap = 0.1 // More overlap = denser texture grains.jitter = 0.3 // More scatter = less repetitive ``` | Parameter | Range | Default | Effect | |-----------|-------|---------|--------| | `position` | 0-1 | 0 | Where in the buffer to sample grains | | `pitch` | semitones | 0 | Pitch shift (via playbackRate) | | `grainSize` | seconds (min 0.01) | 0.1 | Duration of each grain | | `overlap` | seconds | 0.05 | Time between grain starts | | `jitter` | 0-1 | 0 | Random position scatter | | `loop` | boolean | true | Loop when reaching buffer end | ## Playback Control ```typescript grains.play() grains.pause() // Freeze grain scheduling grains.play() // Resume from where you paused grains.stop() // Stop and reset ``` ## Effects and Volume ```typescript import { createGrainPlayer, createReverb } from 'ez-web-audio' const grains = await createGrainPlayer(buffer, { gain: 0.8 }) const reverb = createReverb({ decay: 3.0, wet: 0.4 }) grains.addEffect(reverb) grains.changeGainTo(0.5) grains.changePanTo(-0.3) ``` ## Limitations Pitch shifting is implemented via `playbackRate`, which changes both pitch and speed of each grain. The overlap system compensates for changed grain duration, but extreme values (beyond +/-24 semitones) may affect texture quality. ## Cleanup ```typescript grains.dispose() // Stops all grains, releases buffer reference ``` ## Next Steps * [LFO](/guide/lfo) -- Modulate grain position or pitch with an LFO * [API Reference](/api/) -- Full GrainPlayer API docs --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/grainplayer.md' description: >- Interactive granular synthesis demo — independently control pitch and playback speed, adjust grain parameters, and scrub the waveform canvas to explore granular textures. --- # GrainPlayer Granular synthesis lets you independently control **pitch** and **playback speed** -- something impossible with traditional audio playback. Drag the waveform to set the read position, adjust grain size for texture variation, and add jitter for organic randomness. Interactive granular synthesis demo with a waveform canvas showing the audio buffer. Click or drag to set the grain read position. Controls include pitch (semitones, independent of speed), playback speed (independent of pitch), grain size, overlap, and jitter. Preset buttons provide ready-made textures: Normal, Freeze, Slow Motion, Choppy, and Pitched. Play/Stop button triggers continuous granular playback. ## How It Works The `createGrainPlayer()` function reads tiny overlapping slices of audio (called **grains**) and plays them back continuously. Because each grain is independently pitch-shifted, the overall pitch can change without affecting how fast the buffer is being read -- and vice versa. ### Key API ```typescript import { createGrainPlayer, createSound } from 'ez-web-audio' const sound = await createSound('/audio/sample.mp3') const grain = await createGrainPlayer(sound.audioBuffer, { grainSize: 0.1, // seconds per grain overlap: 0.05, // grain crossfade overlap in seconds jitter: 0, // position randomization (0-1) loop: true, }) grain.play() grain.pitch = 7 // up a perfect fifth (semitones) -- speed unchanged grain.position = 0.5 // jump to middle of buffer grain.grainSize = 0.2 // larger grains = smoother texture ``` `pitch` is measured in **semitones**: 12 = one octave up, -12 = one octave down, 7 = a perfect fifth. ### Interactive Controls | Control | What It Does | |---------|-------------| | **Waveform canvas** | Click or drag to set the grain read position | | **Pitch** | Shifts pitch in semitones without changing speed | | **Speed** | Advances the read position faster or slower without changing pitch | | **Grain Size** | Larger = smoother; smaller = more granular artifacts | | **Overlap** | Crossfade between grains for smoother texture | | **Jitter** | Randomizes grain start position -- adds organic movement | ### Cleanup ```typescript grain.stop() grain.dispose() // Stops all scheduled grains and releases the buffer reference ``` ## Further Reading * [GrainPlayer Guide](/guide/grain-player) -- full API reference, effects, and parameter details * [LFO — One Knob, Three Effects](/examples/lfo-modulation) -- modulate grain position or pitch with an LFO * [Effects Chain](/examples/effects-chain) -- add reverb, delay, or compression to grain output --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples.md' description: >- Try interactive web audio demos: drum machines, synthesizers, piano keyboards, XY pads, audio visualization, and more. Each example includes source code using EZ Web Audio. --- # Interactive Examples Try EZ Web Audio features directly in your browser. Each example demonstrates core library features through interactive demos you can play with immediately. ## Audio Files ### [Basic Playback](/examples/basic-playback) Play sounds and music tracks with volume and pan control. Learn the difference between Sound (one-shot effects) and Track (music with pause/resume). **You'll learn:** * Loading and playing audio files * Controlling volume and stereo position * Pause, resume, and seek for music tracks * Position tracking and progress display ## Sampling ### [Sampled Drum Kit](/examples/sampled-drum-kit) Build a playable drum kit using audio samples with round-robin playback for natural variation. Play kick, snare, and hi-hat sounds by clicking pads or tapping on mobile. **You'll learn:** * Using `createSampler()` with multiple variations * Round-robin sample rotation * Loading states and async audio initialization * Touch and mouse event handling ### [Soundfont Piano](/examples/soundfont-piano) Play a full piano keyboard using a soundfont with real piano samples. Compare the difference between sampled instruments and synthesized sounds. **You'll learn:** * Loading and using soundfonts * Musical note mapping (letter, accidental, octave) * Computer keyboard input for musical instruments * Working with large audio assets (~1.4MB) ## Synthesis ### [Synth Keyboard](/examples/synth-keyboard) A polyphonic synthesizer keyboard with visual piano keys, ADSR envelope controls, and waveform selection. Hold multiple keys for chords. **You'll learn:** * Creating oscillators with different waveforms * Using ADSR envelopes for natural sound shaping * Polyphonic playback (multiple notes simultaneously) * Preset systems for common sounds ### [XY Pad](/examples/xy-pad) Control frequency and gain in real-time by dragging on a 2D canvas. See how continuous parameter modulation works with visual feedback. **You'll learn:** * Real-time parameter updates with `update()` * Logarithmic frequency scaling for musical perception * Canvas-based audio control interfaces * Frequency to note name conversion ### [Synth Drum Kit](/examples/synth-drum-kit) Create drum sounds entirely from synthesis without any audio files. Learn how to build kick, snare, and hi-hat sounds using oscillators, noise, and filters. **You'll learn:** * Synthesizing percussion with frequency sweeps * Creating noise-based sounds * Layering multiple oscillators * Using filters (highpass, bandpass) for tone shaping ## Timing & Sequencing ### [Why Timing Drifts](/examples/timing) Master the Web Audio timing model with examples of immediate playback, delayed playback, and precise scheduling for musical timing. **You'll learn:** * Playing sounds immediately with `play()` * Delayed playback with `playIn(seconds)` * Precise scheduling with `playAt(audioContext.currentTime)` * Perfect synchronization for chords and rhythms ### [Drum Machine](/examples/drum-machine) A step sequencer with multiple drum lanes, BPM control, and a visual playhead. Create and play rhythmic patterns by toggling beat cells. **You'll learn:** * Using `createBeatTrack()` for sequencing * Beat activation and pattern creation * Looping playback with tempo control * Visual feedback during playback ## Composition ### [Audio Sprite](/examples/audio-sprite) Pack multiple short sounds into a single audio file and play them by name. Reduce HTTP requests in audio-heavy applications by loading once and playing many. **You'll learn:** * Loading a sprite with `createSprite()` and a spritemap definition * Playing named segments with `sprite.play('name')` * Looping sprite segments and stopping them with `sprite.stop('name')` * Reducing HTTP requests with sprite bundling ### [Layered Sound](/examples/layered-sound) Play multiple audio layers in perfect synchronization using a shared `audioContext.currentTime`. Control all layers as a group or adjust each individually. **You'll learn:** * Creating synchronized playback with `createLayeredSound()` * Master gain/pan control affecting all layers at once * Individual layer access and per-layer gain control * Listening for `play`, `stop`, and `end` events ### [Crossfade](/examples/crossfade) Transition smoothly between two tracks using equal-power crossfade curves. Create DJ-style fades that maintain constant perceived loudness throughout. **You'll learn:** * Using `crossfade(fromTrack, toTrack, duration)` for smooth transitions * How equal-power curves prevent the volume dip of linear fades * Awaiting crossfade completion for sequenced transitions * Chaining multiple crossfades together ## Integration Patterns ### [Vue Reactive Pattern](/examples/drum-machine-vue) Build a drum machine using Vue 3's reactive system for automatic UI updates when beat states change. **You'll learn:** * Using `wrapWith: reactive` for Vue reactivity * Computed properties for beat state * Watch-based tempo control ### [Vanilla TypeScript Events](/examples/drum-machine-vanilla) Build a drum machine with vanilla TypeScript using DOM events and manual state management. **You'll learn:** * Event-based audio state management * Manual DOM updates on audio events * Framework-free audio integration ### [React Integration](/examples/react-integration) Integrate ez-web-audio into React applications with the official `@ez-web-audio/react` hooks package. **You'll learn:** * The uniform hook shape (`instance`, `loading`, `error`, `load`) shared with the Vue package * `useCleanup` for automatic disposal on unmount * SSR/Next.js safety (`'use client'`, no audio until interaction) * BeatTrack UI updates in React (rAF polling or the `beat` event) ## Effects & Routing ### [Effects](/examples/effects) Apply and control audio effects in real-time. Experiment with different filter types, frequencies, and resonance settings while audio plays. **You'll learn:** * Creating and applying filter effects * Adjusting filter parameters in real-time * Different filter types (lowpass, highpass, bandpass, notch) * Effect bypass and parameter automation ### [Audio Routing](/examples/audio-routing) Route audio through effects with control over bypass, wet/dry mix, and signal chain order. Visualize how audio flows through the effects chain. **You'll learn:** * Adding and removing effects dynamically * Using `effect.bypass` and `effect.mix` * Creating custom effects with native Web Audio nodes * Signal chain visualization ## Creative ### [Ambient Generator](/examples/ambient-generator) Create layered ambient soundscapes by combining oscillators and filtered white noise. Build evolving textures from simple synthesis building blocks. **You'll learn:** * Layering multiple sounds for rich textures * Using white noise with filters for atmospheric effects * ADSR envelopes for smooth, organic sounds * Real-time parameter modulation * Mixing multiple audio sources ### [Visualization](/examples/visualization) Visualize audio in real-time using the Analyzer API. See both frequency spectrum (FFT) and time-domain waveform visualization. **You'll learn:** * Using the Analyzer API for audio visualization * Frequency spectrum analysis with FFT * Time-domain waveform display * Canvas rendering with requestAnimationFrame * Understanding different waveform shapes ## Running Examples Locally Clone the repository and run the development server: ```bash git clone https://github.com/sethbrasile/ez-web-audio.git cd ez-web-audio pnpm install pnpm dev ``` Then visit `http://localhost:5173/ez-web-audio/examples/` ## Browser Compatibility These examples work in all modern browsers: | Browser | Version | |---------|---------| | Chrome | 66+ | | Firefox | 60+ | | Safari | 14.1+ | | Edge | 79+ | ::: tip Mobile Support All examples work on mobile devices. Audio requires a tap gesture to initialize, just like on desktop. ::: ## Source Code Each example includes its full source code. You can browse the source files for all examples on [GitHub](https://github.com/sethbrasile/ez-web-audio/tree/main/docs/examples). --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/AlgorithmicReverbOptions.md --- [EZ Web Audio](../index.md) / AlgorithmicReverbOptions # Interface: AlgorithmicReverbOptions Defined in: [packages/core/src/effects/reverb-effect.ts:9](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L9) Options for algorithmic reverb. ## Properties ### damping? > `optional` **damping**: `number` Defined in: [packages/core/src/effects/reverb-effect.ts:15](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L15) High-frequency damping, 0-1 where 1 = very dark (default: 0.3) *** ### decay? > `optional` **decay**: `number` Defined in: [packages/core/src/effects/reverb-effect.ts:11](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L11) Reverb decay time in seconds (default: 1.5) *** ### mix? > `optional` **mix**: `number` Defined in: [packages/core/src/effects/reverb-effect.ts:17](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L17) Wet/dry mix 0-1 (default: 1) *** ### preDelay? > `optional` **preDelay**: `number` Defined in: [packages/core/src/effects/reverb-effect.ts:13](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L13) Pre-delay time in seconds, 0-0.1 (default: 0.01) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/AnalyzerOptions.md' --- [EZ Web Audio](../index.md) / AnalyzerOptions # Interface: AnalyzerOptions Defined in: [packages/core/src/analyzer.ts:6](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L6) Configuration options for creating an Analyzer. ## Properties ### fftSize? > `optional` **fftSize**: `number` Defined in: [packages/core/src/analyzer.ts:12](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L12) FFT size for frequency analysis. Must be a power of 2 between 32 and 32768. Larger values provide more frequency detail but less time precision. #### Default ```ts 2048 ``` *** ### maxDecibels? > `optional` **maxDecibels**: `number` Defined in: [packages/core/src/analyzer.ts:22](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L22) Maximum decibel value for frequency data scaling. #### Default ```ts -30 ``` *** ### minDecibels? > `optional` **minDecibels**: `number` Defined in: [packages/core/src/analyzer.ts:17](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L17) Minimum decibel value for frequency data scaling. #### Default ```ts -100 ``` *** ### smoothingTimeConstant? > `optional` **smoothingTimeConstant**: `number` Defined in: [packages/core/src/analyzer.ts:27](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/analyzer.ts#L27) Smoothing time constant (0-1). Higher values smooth data over time. #### Default ```ts 0.8 ``` --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/AudiospriteManifest.md --- [EZ Web Audio](../index.md) / AudiospriteManifest # Interface: AudiospriteManifest Defined in: [packages/core/src/sprite.ts:65](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L65) Audiosprite-compatible manifest format. Uses `spritemap` key with second-based `{start, end, loop?}` objects. ## Example ```typescript const manifest: AudiospriteManifest = { spritemap: { laser: { start: 0, end: 0.3 }, explosion: { start: 1.0, end: 2.5 } } } ``` ## Properties ### resources? > `optional` **resources**: `string`\[] Defined in: [packages/core/src/sprite.ts:67](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L67) Optional: alternative audio formats *** ### spritemap > **spritemap**: `Record`<`string`, [`SpriteDefinition`](SpriteDefinition.md)> Defined in: [packages/core/src/sprite.ts:69](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L69) Map of sprite names to their definitions --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/BaseSoundEventMap.md' --- [EZ Web Audio](../index.md) / BaseSoundEventMap # Interface: BaseSoundEventMap Defined in: [packages/core/src/events/event-types.ts:127](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L127) Event map for BaseSound and Sound instances. These are the only events emitted by Sound — pause/resume/seek are Track-only. ## Example ```typescript sound.on('play', (e: BaseSoundEventMap['play']) => { console.log(e.detail.time); }); ``` ## Extended by * [`TrackEventMap`](TrackEventMap.md) ## Properties ### dispose > **dispose**: `CustomEvent`<`DisposeEventDetail`> Defined in: [packages/core/src/events/event-types.ts:131](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L131) *** ### end > **end**: `CustomEvent`<[`EndEventDetail`](EndEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:130](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L130) *** ### play > **play**: `CustomEvent`<[`PlayEventDetail`](PlayEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:128](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L128) *** ### stop > **stop**: `CustomEvent`<[`StopEventDetail`](StopEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:129](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L129) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/BeatEventDetail.md' --- [EZ Web Audio](../index.md) / BeatEventDetail # Interface: BeatEventDetail Defined in: [packages/core/src/events/event-types.ts:181](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L181) Detail for 'beat' events, fired when a beat is scheduled in BeatTrack. Emitted at SCHEDULE time (during lookahead), not at play time. This gives UI components ~100ms advance notice for smooth animations. ## Properties ### active > **active**: `boolean` Defined in: [packages/core/src/events/event-types.ts:187](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L187) Whether this beat is active (plays sound) or a rest *** ### beatIndex > **beatIndex**: `number` Defined in: [packages/core/src/events/event-types.ts:185](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L185) The index of this beat in the beats array *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:189](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L189) The BeatTrack instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:183](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L183) The audioContext.currentTime when this beat is scheduled to play --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/BeatTrackEventMap.md' --- [EZ Web Audio](../index.md) / BeatTrackEventMap # Interface: BeatTrackEventMap Defined in: [packages/core/src/events/event-types.ts:195](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L195) Maps BeatTrack event names to their corresponding CustomEvent types. ## Properties ### beat > **beat**: `CustomEvent`<[`BeatEventDetail`](BeatEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:196](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L196) *** ### pause > **pause**: `CustomEvent`<[`PauseEventDetail`](PauseEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:197](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L197) *** ### resume > **resume**: `CustomEvent`<[`ResumeEventDetail`](ResumeEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:198](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L198) *** ### stop > **stop**: `CustomEvent`<[`StopEventDetail`](StopEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:199](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L199) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/BeatTrackOptions.md' --- [EZ Web Audio](../index.md) / BeatTrackOptions # Interface: BeatTrackOptions Defined in: [packages/core/src/beat-track.ts:12](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L12) ## Extends * [`SamplerOptions`](SamplerOptions.md) ## Properties ### duration? > `optional` **duration**: `number` Defined in: [packages/core/src/beat-track.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L14) *** ### name? > `optional` **name**: `string` Defined in: [packages/core/src/sampler.ts:7](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L7) #### Inherited from [`SamplerOptions`](SamplerOptions.md).[`name`](SamplerOptions.md#name) *** ### numBeats? > `optional` **numBeats**: `number` Defined in: [packages/core/src/beat-track.ts:13](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L13) *** ### wrapWith()? > `optional` **wrapWith**: (`beat`) => [`Beat`](../classes/Beat.md) Defined in: [packages/core/src/beat-track.ts:25](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/beat-track.ts#L25) #### Parameters ##### beat [`Beat`](../classes/Beat.md) #### Returns [`Beat`](../classes/Beat.md) #### Method wrapWith wrapWith allows you to run a function on each beat as it is created This function must accept a beat and return a beat. An example use-case appears in the docs site in the "Multisampled Drum Machine" example where this method is used to wrap each beat in an nx-js observable proxy. --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/CompressorOptions.md' --- [EZ Web Audio](../index.md) / CompressorOptions # Interface: CompressorOptions Defined in: [packages/core/src/effects/compressor-effect.ts:8](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L8) Options for creating a CompressorEffect. ## Properties ### attack? > `optional` **attack**: `number` Defined in: [packages/core/src/effects/compressor-effect.ts:16](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L16) Attack time in seconds (default: 0.003). How fast compression engages *** ### knee? > `optional` **knee**: `number` Defined in: [packages/core/src/effects/compressor-effect.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L14) Knee width in dB (default: 30). Wider knee = gentler transition *** ### mix? > `optional` **mix**: `number` Defined in: [packages/core/src/effects/compressor-effect.ts:20](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L20) Wet/dry mix 0-1 (default: 1) *** ### ratio? > `optional` **ratio**: `number` Defined in: [packages/core/src/effects/compressor-effect.ts:12](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L12) Compression ratio (default: 4). e.g., 4:1 means 4dB above threshold → 1dB output *** ### release? > `optional` **release**: `number` Defined in: [packages/core/src/effects/compressor-effect.ts:18](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L18) Release time in seconds (default: 0.25). How fast compression releases *** ### threshold? > `optional` **threshold**: `number` Defined in: [packages/core/src/effects/compressor-effect.ts:10](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/compressor-effect.ts#L10) Threshold in dB above which compression starts (default: -24) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/Connectable.md' --- [EZ Web Audio](../index.md) / Connectable # Interface: Connectable Defined in: [packages/core/src/interfaces/connectable.ts:10](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/connectable.ts#L10) Interface for audio sources with parameter control and routing. Provides gain/pan control and audio parameter management via the fluent API. The `update` method accepts [SoundControlType](../type-aliases/SoundControlType.md) ('gain', 'pan', 'detune'). Oscillator overrides this to also accept 'frequency'. ## Properties ### audioSourceNode > **audioSourceNode**: `OscillatorNode` | `AudioBufferSourceNode` Defined in: [packages/core/src/interfaces/connectable.ts:12](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/connectable.ts#L12) *** ### changeGainTo() > **changeGainTo**: (`value`) => `this` Defined in: [packages/core/src/interfaces/connectable.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/connectable.ts#L14) #### Parameters ##### value `number` #### Returns `this` *** ### changePanTo() > **changePanTo**: (`value`) => `this` Defined in: [packages/core/src/interfaces/connectable.ts:13](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/connectable.ts#L13) #### Parameters ##### value `number` #### Returns `this` *** ### percentGain > **percentGain**: `number` Defined in: [packages/core/src/interfaces/connectable.ts:11](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/connectable.ts#L11) *** ### update() > **update**: (`type`) => `object` Defined in: [packages/core/src/interfaces/connectable.ts:28](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/connectable.ts#L28) Update an audio parameter immediately: `update(type).to(value).as(method)`. Validation semantics (as of the R1#1 unification): `'gain'` throws a [ValidationError](../classes/ValidationError.md) for negative values and warns on the console for values above 1; `'pan'` warns for values outside \[-1, 1] (the Web Audio API clamps these automatically, so it is not an error). This is the same validation `changeGainTo()`/`changePanTo()` apply — implementations route both through the same underlying check (see `BaseParamController._update()`) so `update('gain').to(-1).as('ratio')` and `changeGainTo(-1)` throw identically. `'detune'` and `'frequency'` (Oscillator only) are not range-validated. #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) #### Returns `object` ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### as() > **as**: (`method`) => `void` ###### Parameters ###### method [`RatioType`](../type-aliases/RatioType.md) ###### Returns `void` --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/ConvolutionReverbOptions.md --- [EZ Web Audio](../index.md) / ConvolutionReverbOptions # Interface: ConvolutionReverbOptions Defined in: [packages/core/src/effects/reverb-effect.ts:23](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L23) Options for convolution reverb. ## Properties ### mix? > `optional` **mix**: `number` Defined in: [packages/core/src/effects/reverb-effect.ts:27](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L27) Wet/dry mix 0-1 (default: 1) *** ### normalize? > `optional` **normalize**: `boolean` Defined in: [packages/core/src/effects/reverb-effect.ts:25](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/reverb-effect.ts#L25) Whether to normalize the impulse response (default: true) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/CrossfadeOptions.md' --- [EZ Web Audio](../index.md) / CrossfadeOptions # Interface: CrossfadeOptions Defined in: [packages/core/src/utils/crossfade.ts:38](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/crossfade.ts#L38) Options for crossfade behavior. ## Properties ### afterFade? > `optional` **afterFade**: `"pause"` | `"stop"` | `"continue"` Defined in: [packages/core/src/utils/crossfade.ts:48](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/crossfade.ts#L48) What to do with the outgoing track after the fade completes. * `'continue'` — track keeps playing at gain 0 (DJ-style, seamless crossfade back) * `'pause'` — track is paused (preserves position, frees resources) * `'stop'` — track is stopped and position resets to 0 #### Default ```ts 'pause' ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/DebugMessage.md' --- [EZ Web Audio](../index.md) / DebugMessage # Interface: DebugMessage Defined in: [packages/core/src/debug/messages.ts:10](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/debug/messages.ts#L10) A debug message representing an event, connection change, or warning. ## Properties ### details? > `optional` **details**: `Record`<`string`, `unknown`> Defined in: [packages/core/src/debug/messages.ts:20](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/debug/messages.ts#L20) Optional additional details *** ### message > **message**: `string` Defined in: [packages/core/src/debug/messages.ts:16](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/debug/messages.ts#L16) Human-readable message *** ### source > **source**: `string` Defined in: [packages/core/src/debug/messages.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/debug/messages.ts#L14) Sound name or identifier *** ### timestamp > **timestamp**: `number` Defined in: [packages/core/src/debug/messages.ts:18](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/debug/messages.ts#L18) Timestamp (audioContext.currentTime or Date.now()) *** ### type > **type**: `"event"` | `"warning"` | `"connection"` Defined in: [packages/core/src/debug/messages.ts:12](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/debug/messages.ts#L12) The type of debug message --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/DelayOptions.md' --- [EZ Web Audio](../index.md) / DelayOptions # Interface: DelayOptions Defined in: [packages/core/src/effects/delay-effect.ts:8](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L8) Options for creating a DelayEffect. ## Properties ### feedback? > `optional` **feedback**: `number` Defined in: [packages/core/src/effects/delay-effect.ts:12](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L12) Feedback amount 0-0.99 (default: 0.4). Higher values = more repeats *** ### maxTime? > `optional` **maxTime**: `number` Defined in: [packages/core/src/effects/delay-effect.ts:16](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L16) Maximum delay time in seconds (default: 2.0). Set at construction, read-only after *** ### mix? > `optional` **mix**: `number` Defined in: [packages/core/src/effects/delay-effect.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L14) Wet/dry mix 0-1 (default: 1) *** ### time? > `optional` **time**: `number` Defined in: [packages/core/src/effects/delay-effect.ts:10](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/delay-effect.ts#L10) Delay time in seconds (default: 0.3) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/DistortionOptions.md' --- [EZ Web Audio](../index.md) / DistortionOptions # Interface: DistortionOptions Defined in: [packages/core/src/effects/distortion-effect.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L14) Options for creating a DistortionEffect. ## Properties ### amount? > `optional` **amount**: `number` Defined in: [packages/core/src/effects/distortion-effect.ts:18](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L18) Distortion amount 0-100 (default: 50). Higher = more distortion *** ### curve? > `optional` **curve**: `Float32Array`<`ArrayBuffer`> Defined in: [packages/core/src/effects/distortion-effect.ts:24](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L24) Custom waveshaper curve (only used when type is 'custom') *** ### mix? > `optional` **mix**: `number` Defined in: [packages/core/src/effects/distortion-effect.ts:26](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L26) Wet/dry mix 0-1 (default: 1) *** ### oversample? > `optional` **oversample**: `OverSampleType` Defined in: [packages/core/src/effects/distortion-effect.ts:22](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L22) Oversampling to prevent aliasing (default: '4x') *** ### tone? > `optional` **tone**: `number` Defined in: [packages/core/src/effects/distortion-effect.ts:20](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L20) Post-distortion tone control 0-1 (default: 0.5). 0 = dark, 1 = bright *** ### type? > `optional` **type**: [`DistortionType`](../type-aliases/DistortionType.md) Defined in: [packages/core/src/effects/distortion-effect.ts:16](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L16) Distortion curve type (default: 'soft') --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/Effect.md' --- [EZ Web Audio](../index.md) / Effect # Interface: Effect Defined in: [packages/core/src/effects/index.ts:24](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/index.ts#L24) Common interface for all audio effects. Effects can be added to any Sound, Oscillator, or LayeredSound via addEffect(). All effects support bypass (passthrough) and wet/dry mix controls. ## Example ```typescript import { createSound, createGainEffect, createFilterEffect } from 'ez-web-audio' const sound = await createSound('audio.mp3') const boost = createGainEffect(1.5) const filter = createFilterEffect('lowpass', { frequency: 800 }) sound.addEffect(boost) sound.addEffect(filter) sound.play() // Control effects boost.bypass = true // Bypass gain boost filter.mix = 0.5 // 50% wet/dry mix on filter ``` ## Properties ### bypass > **bypass**: `boolean` Defined in: [packages/core/src/effects/index.ts:30](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/index.ts#L30) When true, effect is bypassed (passthrough) *** ### dispose() > **dispose**: () => `void` Defined in: [packages/core/src/effects/index.ts:40](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/index.ts#L40) Disconnect all internal audio nodes and release resources. "You create it, you dispose it" — every class that OWNS an Effect (BaseSound.dispose(), etc.) calls this for each attached effect. Implementations MUST be idempotent (safe to call more than once). #### Returns `void` *** ### input > **input**: `AudioNode` Defined in: [packages/core/src/effects/index.ts:26](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/index.ts#L26) The input AudioNode that receives signal from the chain *** ### mix > **mix**: `number` Defined in: [packages/core/src/effects/index.ts:32](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/index.ts#L32) Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect) *** ### output > **output**: `AudioNode` Defined in: [packages/core/src/effects/index.ts:28](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/index.ts#L28) The output AudioNode that sends signal to the next in chain --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/EndEventDetail.md' --- [EZ Web Audio](../index.md) / EndEventDetail # Interface: EndEventDetail Defined in: [packages/core/src/events/event-types.ts:56](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L56) Detail for 'end' events, fired when audio playback completes naturally. ## Properties ### duration > **duration**: `number` Defined in: [packages/core/src/events/event-types.ts:62](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L62) The duration of the audio that played (in seconds) *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:60](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L60) The sound instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:58](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L58) The audioContext.currentTime when playback ended --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/EnvelopeOptions.md' --- [EZ Web Audio](../index.md) / EnvelopeOptions # Interface: EnvelopeOptions Defined in: [packages/core/src/envelope.ts:9](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L9) Options for configuring an ADSR envelope. ## Properties ### attack? > `optional` **attack**: `number` Defined in: [packages/core/src/envelope.ts:10](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L10) Duration in seconds to ramp from 0 to peak (1.0). Default: 0.01 *** ### decay? > `optional` **decay**: `number` Defined in: [packages/core/src/envelope.ts:11](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L11) Duration in seconds to ramp from peak to sustain level. Default: 0.1 *** ### release? > `optional` **release**: `number` Defined in: [packages/core/src/envelope.ts:13](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L13) Duration in seconds for release to silence. Default: 0.3 *** ### sustain? > `optional` **sustain**: `number` Defined in: [packages/core/src/envelope.ts:12](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/envelope.ts#L12) Amplitude level (0-1) held during sustain phase. Default: 0.7 --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/EQOptions.md' --- [EZ Web Audio](../index.md) / EQOptions # Interface: EQOptions Defined in: [packages/core/src/effects/eq-effect.ts:8](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L8) Options for creating an EQEffect. ## Properties ### high? > `optional` **high**: `number` Defined in: [packages/core/src/effects/eq-effect.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L14) High band gain in dB (default: 0) *** ### highFrequency? > `optional` **highFrequency**: `number` Defined in: [packages/core/src/effects/eq-effect.ts:20](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L20) High band crossover frequency in Hz (default: 3000) *** ### low? > `optional` **low**: `number` Defined in: [packages/core/src/effects/eq-effect.ts:10](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L10) Low band gain in dB (default: 0) *** ### lowFrequency? > `optional` **lowFrequency**: `number` Defined in: [packages/core/src/effects/eq-effect.ts:16](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L16) Low band crossover frequency in Hz (default: 200) *** ### mid? > `optional` **mid**: `number` Defined in: [packages/core/src/effects/eq-effect.ts:12](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L12) Mid band gain in dB (default: 0) *** ### midFrequency? > `optional` **midFrequency**: `number` Defined in: [packages/core/src/effects/eq-effect.ts:18](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L18) Mid band center frequency in Hz (default: 1000) *** ### midQ? > `optional` **midQ**: `number` Defined in: [packages/core/src/effects/eq-effect.ts:22](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L22) Mid band Q factor / bandwidth (default: 0.7) *** ### mix? > `optional` **mix**: `number` Defined in: [packages/core/src/effects/eq-effect.ts:24](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/eq-effect.ts#L24) Wet/dry mix 0-1 (default: 1) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/ExternalEffect.md' --- [EZ Web Audio](../index.md) / ExternalEffect # Interface: ExternalEffect Defined in: [packages/core/src/effects/effect-wrapper.ts:9](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L9) Minimal interface for external effects that can be wrapped. Any effect with a connect() method can be wrapped to provide bypass/mix controls. ## Properties ### connect() > **connect**: (`destination`) => `void` Defined in: [packages/core/src/effects/effect-wrapper.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/effect-wrapper.ts#L14) Connect the effect's output to a destination node. This is the minimum requirement for wrapping an external effect. #### Parameters ##### destination `AudioNode` #### Returns `void` --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/FilterEffectOptions.md --- [EZ Web Audio](../index.md) / FilterEffectOptions # Interface: FilterEffectOptions Defined in: [packages/core/src/effects/filter-effect.ts:24](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L24) Options for creating a FilterEffect. ## Properties ### detune? > `optional` **detune**: `number` Defined in: [packages/core/src/effects/filter-effect.ts:32](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L32) Filter detune in cents (default: 0) *** ### frequency? > `optional` **frequency**: `number` Defined in: [packages/core/src/effects/filter-effect.ts:26](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L26) Filter frequency in Hz (default: 350) *** ### gain? > `optional` **gain**: `number` Defined in: [packages/core/src/effects/filter-effect.ts:30](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L30) Filter gain in dB (default: 0) - only used for shelf and peaking filters *** ### q? > `optional` **q**: `number` Defined in: [packages/core/src/effects/filter-effect.ts:28](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L28) Filter Q factor (default: 1) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/GrainPlayerEventMap.md --- [EZ Web Audio](../index.md) / GrainPlayerEventMap # Interface: GrainPlayerEventMap Defined in: [packages/core/src/events/event-types.ts:357](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L357) Maps GrainPlayer event names to their corresponding CustomEvent types. GrainPlayer emits standard lifecycle events for play/stop/pause/resume. ## Properties ### dispose > **dispose**: `CustomEvent`<`DisposeEventDetail`> Defined in: [packages/core/src/events/event-types.ts:362](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L362) *** ### pause > **pause**: `CustomEvent`<[`PauseEventDetail`](PauseEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:360](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L360) *** ### play > **play**: `CustomEvent`<[`PlayEventDetail`](PlayEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:358](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L358) *** ### resume > **resume**: `CustomEvent`<[`ResumeEventDetail`](ResumeEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:361](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L361) *** ### stop > **stop**: `CustomEvent`<[`StopEventDetail`](StopEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:359](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L359) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/GrainPlayerOptions.md --- [EZ Web Audio](../index.md) / GrainPlayerOptions # Interface: GrainPlayerOptions Defined in: [packages/core/src/grain-player.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L14) Configuration options for creating a GrainPlayer. ## Properties ### gain? > `optional` **gain**: `number` Defined in: [packages/core/src/grain-player.ts:28](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L28) Initial master gain, 0-1 (default: 1). *** ### grainSize? > `optional` **grainSize**: `number` Defined in: [packages/core/src/grain-player.ts:16](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L16) Duration of each grain in seconds (default: 0.1, min: 0.01). *** ### jitter? > `optional` **jitter**: `number` Defined in: [packages/core/src/grain-player.ts:24](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L24) Random scatter around the position for organic texture, 0-1 (default: 0). *** ### loop? > `optional` **loop**: `boolean` Defined in: [packages/core/src/grain-player.ts:26](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L26) Whether to loop back to buffer start when reaching the end (default: true). *** ### overlap? > `optional` **overlap**: `number` Defined in: [packages/core/src/grain-player.ts:18](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L18) Overlap between consecutive grains in seconds (default: 0.05). *** ### pan? > `optional` **pan**: `number` Defined in: [packages/core/src/grain-player.ts:30](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L30) Initial master pan, -1 to 1 (default: 0). *** ### pitch? > `optional` **pitch**: `number` Defined in: [packages/core/src/grain-player.ts:22](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L22) Pitch shift in semitones (default: 0). Converted to playbackRate via 2^(semitones/12). *** ### position? > `optional` **position**: `number` Defined in: [packages/core/src/grain-player.ts:20](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/grain-player.ts#L20) Initial playback position in the buffer, normalized 0-1 (default: 0). --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/HowlerSpriteManifest.md --- [EZ Web Audio](../index.md) / HowlerSpriteManifest # Interface: HowlerSpriteManifest Defined in: [packages/core/src/sprite.ts:43](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L43) Howler.js-compatible sprite manifest format. Uses `sprite` key with millisecond-based tuples. ## Example ```typescript const manifest: HowlerSpriteManifest = { sprite: { laser: [0, 300], explosion: [1000, 2500], bgm: [4000, 10000, true] } } ``` ## Properties ### sprite > **sprite**: `Record`<`string`, [`HowlerSpriteTuple`](../type-aliases/HowlerSpriteTuple.md)> Defined in: [packages/core/src/sprite.ts:47](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L47) Map of sprite names to `[offset_ms, duration_ms, loop?]` tuples *** ### src? > `optional` **src**: `string`\[] Defined in: [packages/core/src/sprite.ts:45](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L45) Optional: source audio files --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/InteractionTarget.md' --- [EZ Web Audio](../index.md) / InteractionTarget # Interface: InteractionTarget Defined in: [packages/core/src/index.ts:1394](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1394) ## Properties ### play() > **play**: () => `void` | `Promise`<`void`> Defined in: [packages/core/src/index.ts:1395](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1395) #### Returns `void` | `Promise`<`void`> *** ### stop() > **stop**: () => `void` | `Promise`<`void`> Defined in: [packages/core/src/index.ts:1396](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L1396) #### Returns `void` | `Promise`<`void`> --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/LayeredSoundEventMap.md --- [EZ Web Audio](../index.md) / LayeredSoundEventMap # Interface: LayeredSoundEventMap Defined in: [packages/core/src/events/event-types.ts:217](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L217) Maps LayeredSound event names to their corresponding CustomEvent types. ## Properties ### dispose > **dispose**: `CustomEvent`<`DisposeEventDetail`> Defined in: [packages/core/src/events/event-types.ts:222](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L222) *** ### end > **end**: `CustomEvent`<[`EndEventDetail`](EndEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:220](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L220) *** ### play > **play**: `CustomEvent`<[`PlayEventDetail`](PlayEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:218](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L218) *** ### stop > **stop**: `CustomEvent`<[`StopEventDetail`](StopEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:219](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L219) *** ### warning > **warning**: `CustomEvent`<[`WarningEventDetail`](WarningEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:221](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L221) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/LayeredSoundOptions.md --- [EZ Web Audio](../index.md) / LayeredSoundOptions # Interface: LayeredSoundOptions Defined in: [packages/core/src/layered-sound.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L14) Options for creating a LayeredSound. ## Properties ### name? > `optional` **name**: `string` Defined in: [packages/core/src/layered-sound.ts:16](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L16) Optional name for identification *** ### warnLayerCount? > `optional` **warnLayerCount**: `number` Defined in: [packages/core/src/layered-sound.ts:18](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/layered-sound.ts#L18) Layer count threshold at which to warn (default: 8) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/LFOConnectOptions.md' --- [EZ Web Audio](../index.md) / LFOConnectOptions # Interface: LFOConnectOptions Defined in: [packages/core/src/lfo.ts:31](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L31) Options for connecting an LFO to a target parameter. ## Properties ### depth? > `optional` **depth**: `number` Defined in: [packages/core/src/lfo.ts:75](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L75) Per-connection depth override (overrides LFO-level depth). **Note:** For 'ratio' and 'cents' depthUnit, this value is multiplied against the target parameter's value at connection time. The resulting absolute depth is fixed for the lifetime of the connection. *** ### depthUnit? > `optional` **depthUnit**: `"ratio"` | `"cents"` | `"absolute"` Defined in: [packages/core/src/lfo.ts:67](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L67) Depth unit: 'ratio' (most params), 'cents' (frequency), or 'absolute'. **Note:** When depthUnit is 'ratio' or 'cents', depth is calculated from the parameter's current value at connection time. If the parameter value changes later (e.g., gain is adjusted), the modulation depth will NOT automatically update. Use 'absolute' for fixed depth, or call disconnect()/connect() to recalculate. **Clamping:** for 'ratio', `depth` is clamped to \[0, 1] (documented range). For 'cents', negative depth is clamped to 0 (a negative value would only flip the LFO's phase). In both cases, if the target parameter's current value is at (or near) 0 — e.g. pan centered — depth is used directly as an absolute swing instead of a ratio of zero. 'absolute' is NOT clamped — it's the fixed-depth escape hatch and has no natural range to clamp against; a too-large absolute depth can still push a non-negative param (gain, frequency) below zero at the trough. *** ### retrigger? > `optional` **retrigger**: `boolean` Defined in: [packages/core/src/lfo.ts:48](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L48) Reset LFO phase on sound play event (default: false). Same event-contract requirement as [syncLifecycle](#synclifecycle) — a target that never emits 'play' (PolySynth) logs a console.warn instead of silently doing nothing. *** ### syncLifecycle? > `optional` **syncLifecycle**: `boolean` Defined in: [packages/core/src/lfo.ts:40](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L40) Sync LFO start/stop with sound play/stop events (default: false). **Requires** the target to actually emit 'play'/'stop' (BaseSound subclasses, GrainPlayer). PolySynth does not — connecting with `syncLifecycle: true` against a PolySynth logs a console.warn and the option is a no-op; call `lfo.start()`/`lfo.stop()` manually instead. --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/LFOOptions.md' --- [EZ Web Audio](../index.md) / LFOOptions # Interface: LFOOptions Defined in: [packages/core/src/lfo.ts:19](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L19) Configuration options for creating an LFO. ## Properties ### depth? > `optional` **depth**: `number` Defined in: [packages/core/src/lfo.ts:23](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L23) Modulation depth as ratio 0-1 (default: 0.3) *** ### frequency? > `optional` **frequency**: `number` Defined in: [packages/core/src/lfo.ts:21](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L21) Oscillation frequency in Hz (default: 1) *** ### type? > `optional` **type**: [`LFOWaveform`](../type-aliases/LFOWaveform.md) | `PeriodicWave` Defined in: [packages/core/src/lfo.ts:25](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L25) Waveform type or PeriodicWave (default: 'sine') --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/OscillatorFilterOptions.md --- [EZ Web Audio](../index.md) / OscillatorFilterOptions # Interface: OscillatorFilterOptions Defined in: [packages/core/src/oscillator.ts:17](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L17) Filter configuration for oscillator frequency shaping. ## Properties ### frequency? > `optional` **frequency**: `number` Defined in: [packages/core/src/oscillator.ts:19](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L19) Filter cutoff frequency in Hz. *** ### q? > `optional` **q**: `number` Defined in: [packages/core/src/oscillator.ts:21](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L21) Filter Q factor (resonance). Higher values create more pronounced peaks. --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/OscillatorOptions.md' --- [EZ Web Audio](../index.md) / OscillatorOptions # Interface: OscillatorOptions Defined in: [packages/core/src/oscillator.ts:46](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L46) Configuration options for creating an Oscillator. ## Example ```typescript const opts: OscillatorOptions = { frequency: 440, // A4 type: 'sawtooth', // Rich harmonic content gain: 0.5, // Half volume lowpass: { // Filter out harsh highs frequency: 2000, q: 1 }, envelope: { // ADSR for note shaping attack: 0.01, decay: 0.2, sustain: 0.5, release: 0.3 } } ``` ## Extends * `BaseSoundOptions` ## Properties ### allpass? > `optional` **allpass**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/oscillator.ts:84](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L84) Allpass filter - shifts phase without changing amplitude. *** ### bandpass? > `optional` **bandpass**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/oscillator.ts:72](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L72) Bandpass filter - allows frequencies near cutoff, attenuates others. *** ### clearTimeout()? > `optional` **clearTimeout**: (`id`) => `void` Defined in: [packages/core/src/base-sound.ts:45](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L45) Custom clearTimeout implementation. Must match the setTimeout implementation. By default, the AudioContext-aware clearTimeout is used. #### Parameters ##### id `number` Timeout ID returned by setTimeout #### Returns `void` #### Inherited from `BaseSoundOptions.clearTimeout` *** ### detune? > `optional` **detune**: `number` Defined in: [packages/core/src/oscillator.ts:64](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L64) Detune in cents (100 cents = 1 semitone). *** ### envelope? > `optional` **envelope**: [`EnvelopeOptions`](EnvelopeOptions.md) Defined in: [packages/core/src/oscillator.ts:86](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L86) ADSR envelope for amplitude shaping. *** ### frequency? > `optional` **frequency**: `number` Defined in: [packages/core/src/oscillator.ts:62](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L62) Base frequency in Hz (default: 440). *** ### gain? > `optional` **gain**: `number` Defined in: [packages/core/src/oscillator.ts:66](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L66) Initial gain/volume (0-1). *** ### highpass? > `optional` **highpass**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/oscillator.ts:70](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L70) Highpass filter - removes frequencies below cutoff. *** ### highshelf? > `optional` **highshelf**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/oscillator.ts:78](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L78) Highshelf filter - boosts/cuts frequencies above cutoff. *** ### lowpass? > `optional` **lowpass**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/oscillator.ts:74](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L74) Lowpass filter - removes frequencies above cutoff. *** ### lowshelf? > `optional` **lowshelf**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/oscillator.ts:76](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L76) Lowshelf filter - boosts/cuts frequencies below cutoff. *** ### name? > `optional` **name**: `string` Defined in: [packages/core/src/base-sound.ts:23](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L23) Optional name for identifying this sound instance. Useful for debugging and when managing multiple sounds. #### Inherited from `BaseSoundOptions.name` *** ### notch? > `optional` **notch**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/oscillator.ts:82](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L82) Notch filter - attenuates frequencies at cutoff. *** ### note? > `optional` **note**: `string` Defined in: [packages/core/src/oscillator.ts:60](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L60) Note name (e.g., 'A4', 'C3', 'Eb5'). Looked up in the frequency map. Takes precedence over `frequency` if both provided. Both flat (Db, Eb, Gb, Ab, Bb) and sharp (C#, D#, F#, G#, A#) notation are supported as enharmonic equivalents. #### Example ```typescript // Play middle C const osc = await createOscillator({ note: 'C4', type: 'sine' }) ``` *** ### peaking? > `optional` **peaking**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/oscillator.ts:80](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L80) Peaking filter - boosts/cuts frequencies around cutoff. *** ### setTimeout()? > `optional` **setTimeout**: (`fn`, `delayMillis`) => `number` Defined in: [packages/core/src/base-sound.ts:35](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/base-sound.ts#L35) Custom setTimeout implementation. By default, an AudioContext-aware setTimeout is used that compensates for browser throttling. Override this if you need different timing behavior. #### Parameters ##### fn () => `void` Function to call after delay ##### delayMillis `number` Delay in milliseconds #### Returns `number` Timeout ID for cancellation #### Inherited from `BaseSoundOptions.setTimeout` *** ### startOffset? > `optional` **startOffset**: `number` Defined in: [packages/core/src/oscillator.ts:48](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L48) Starting offset in seconds (rarely used for oscillators). *** ### type? > `optional` **type**: `OscillatorType` Defined in: [packages/core/src/oscillator.ts:68](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/oscillator.ts#L68) Waveform type: 'sine', 'square', 'sawtooth', or 'triangle'. --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/PauseEventDetail.md' --- [EZ Web Audio](../index.md) / PauseEventDetail # Interface: PauseEventDetail Defined in: [packages/core/src/events/event-types.ts:77](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L77) Detail for 'pause' events, fired when a Track is paused. ## Properties ### beatIndex? > `optional` **beatIndex**: `number` Defined in: [packages/core/src/events/event-types.ts:85](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L85) For BeatTrack: the beat index where paused *** ### position? > `optional` **position**: `number` Defined in: [packages/core/src/events/event-types.ts:83](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L83) The playback position (in seconds) where the track was paused *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:81](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L81) The Track instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:79](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L79) The audioContext.currentTime when pause occurred --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/Playable.md' --- [EZ Web Audio](../index.md) / Playable # Interface: Playable Defined in: [packages/core/src/interfaces/playable.ts:12](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L12) Minimal contract for playable audio sources. This interface defines the core playback lifecycle methods shared by all audio classes. Convenience methods like `fadeIn()`, `fadeOut()`, and `dispose()` are available on BaseSound but are not part of this minimal contract, as they depend on implementation details (gain ramping, node disconnection). ## Properties ### dispose()? > `optional` **dispose**: () => `void` Defined in: [packages/core/src/interfaces/playable.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L44) Release all audio resources. Optional — available on BaseSound. #### Returns `void` *** ### duration > **duration**: [`TimeObject`](TimeObject.md) Defined in: [packages/core/src/interfaces/playable.ts:22](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L22) *** ### fadeIn()? > `optional` **fadeIn**: (`duration`) => `Promise`<`void`> Defined in: [packages/core/src/interfaces/playable.ts:40](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L40) Fade in over the given duration (seconds). Optional — available on BaseSound. #### Parameters ##### duration `number` #### Returns `Promise`<`void`> *** ### fadeOut()? > `optional` **fadeOut**: (`duration`) => `Promise`<`void`> Defined in: [packages/core/src/interfaces/playable.ts:42](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L42) Fade out over the given duration (seconds) and stop. Optional — available on BaseSound. #### Parameters ##### duration `number` #### Returns `Promise`<`void`> *** ### isPlaying > **isPlaying**: `boolean` Defined in: [packages/core/src/interfaces/playable.ts:21](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L21) *** ### onPlayRamp() > **onPlayRamp**: (`type`, `rampType?`) => `object` Defined in: [packages/core/src/interfaces/playable.ts:31](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L31) #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) ##### rampType? `RampType` #### Returns `object` ##### from() > **from**: (`startValue`) => `object` ###### Parameters ###### startValue `number` ###### Returns `object` ###### to() > **to**: (`endValue`) => `object` ###### Parameters ###### endValue `number` ###### Returns `object` ###### in() > **in**: (`endTime`) => `void` ###### Parameters ###### endTime `number` ###### Returns `void` *** ### onPlaySet() > **onPlaySet**: (`type`) => `object` Defined in: [packages/core/src/interfaces/playable.ts:24](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L24) #### Parameters ##### type [`SoundControlType`](../type-aliases/SoundControlType.md) #### Returns `object` ##### to() > **to**: (`value`) => `object` ###### Parameters ###### value `number` ###### Returns `object` ###### at() > **at**: (`time`) => `void` ###### Parameters ###### time `number` ###### Returns `void` ###### endingAt() > **endingAt**: (`time`, `rampType?`) => `void` ###### Parameters ###### time `number` ###### rampType? `RampType` ###### Returns `void` *** ### play() > **play**: () => `Promise`<`void`> Defined in: [packages/core/src/interfaces/playable.ts:13](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L13) #### Returns `Promise`<`void`> *** ### playAt() > **playAt**: (`time`) => `Promise`<`void`> Defined in: [packages/core/src/interfaces/playable.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L14) #### Parameters ##### time `number` #### Returns `Promise`<`void`> *** ### playFor() > **playFor**: (`duration`) => `void` Defined in: [packages/core/src/interfaces/playable.ts:16](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L16) #### Parameters ##### duration `number` #### Returns `void` *** ### playIn() > **playIn**: (`when`) => `void` Defined in: [packages/core/src/interfaces/playable.ts:15](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L15) #### Parameters ##### when `number` #### Returns `void` *** ### playInAndStopAfter() > **playInAndStopAfter**: (`playIn`, `stopAfter`) => `void` Defined in: [packages/core/src/interfaces/playable.ts:17](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L17) #### Parameters ##### playIn `number` ##### stopAfter `number` #### Returns `void` *** ### stop() > **stop**: () => `Promise`<`void`> Defined in: [packages/core/src/interfaces/playable.ts:18](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L18) #### Returns `Promise`<`void`> *** ### stopAt() > **stopAt**: (`time`) => `Promise`<`void`> Defined in: [packages/core/src/interfaces/playable.ts:20](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L20) #### Parameters ##### time `number` #### Returns `Promise`<`void`> *** ### stopIn() > **stopIn**: (`seconds`) => `Promise`<`void`> Defined in: [packages/core/src/interfaces/playable.ts:19](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/interfaces/playable.ts#L19) #### Parameters ##### seconds `number` #### Returns `Promise`<`void`> --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/PlayEventDetail.md' --- [EZ Web Audio](../index.md) / PlayEventDetail # Interface: PlayEventDetail Defined in: [packages/core/src/events/event-types.ts:36](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L36) Detail for 'play' events, fired when audio playback starts. ## Properties ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:40](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L40) The sound instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:38](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L38) The audioContext.currentTime when playback started --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/PlayOptions.md' --- [EZ Web Audio](../index.md) / PlayOptions # Interface: PlayOptions Defined in: [packages/core/src/poly-synth.ts:61](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L61) Options passed to PolySynth.play() for each note. ## Properties ### frequency > **frequency**: `number` Defined in: [packages/core/src/poly-synth.ts:63](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L63) Frequency of the note to play in Hz. *** ### gain? > `optional` **gain**: `number` Defined in: [packages/core/src/poly-synth.ts:65](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L65) Per-voice gain for velocity sensitivity (0-1, default: 1). --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/PolySynthEventMap.md' --- [EZ Web Audio](../index.md) / PolySynthEventMap # Interface: PolySynthEventMap Defined in: [packages/core/src/events/event-types.ts:346](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L346) Maps PolySynth event names to their corresponding CustomEvent types. ## Properties ### dispose > **dispose**: `CustomEvent`<`DisposeEventDetail`> Defined in: [packages/core/src/events/event-types.ts:348](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L348) *** ### voicestolen > **voicestolen**: `CustomEvent`<[`VoiceStolenEventDetail`](VoiceStolenEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:347](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L347) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/PolySynthOptions.md' --- [EZ Web Audio](../index.md) / PolySynthOptions # Interface: PolySynthOptions Defined in: [packages/core/src/poly-synth.ts:25](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L25) Configuration options for creating a PolySynth. ## Properties ### allpass? > `optional` **allpass**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/poly-synth.ts:53](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L53) Allpass filter for default voice factory. *** ### bandpass? > `optional` **bandpass**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/poly-synth.ts:41](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L41) Bandpass filter for default voice factory. *** ### createVoice()? > `optional` **createVoice**: (`ctx`) => [`Oscillator`](../classes/Oscillator.md) Defined in: [packages/core/src/poly-synth.ts:55](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L55) Custom voice factory. Overrides type/envelope/filter options. #### Parameters ##### ctx `AudioContext` #### Returns [`Oscillator`](../classes/Oscillator.md) *** ### envelope? > `optional` **envelope**: [`EnvelopeOptions`](EnvelopeOptions.md) Defined in: [packages/core/src/poly-synth.ts:37](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L37) ADSR envelope for default voice factory. *** ### frequency? > `optional` **frequency**: `number` Defined in: [packages/core/src/poly-synth.ts:33](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L33) Default frequency for voices — overridden by play() options (default: 440). *** ### gain? > `optional` **gain**: `number` Defined in: [packages/core/src/poly-synth.ts:35](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L35) Default gain for voices (default: 1). *** ### highpass? > `optional` **highpass**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/poly-synth.ts:39](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L39) Highpass filter for default voice factory. *** ### highshelf? > `optional` **highshelf**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/poly-synth.ts:47](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L47) Highshelf filter for default voice factory. *** ### lowpass? > `optional` **lowpass**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/poly-synth.ts:43](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L43) Lowpass filter for default voice factory. *** ### lowshelf? > `optional` **lowshelf**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/poly-synth.ts:45](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L45) Lowshelf filter for default voice factory. *** ### maxVoices? > `optional` **maxVoices**: `number` Defined in: [packages/core/src/poly-synth.ts:27](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L27) Maximum number of simultaneous voices (default: 8). Immutable after creation. *** ### notch? > `optional` **notch**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/poly-synth.ts:51](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L51) Notch filter for default voice factory. *** ### peaking? > `optional` **peaking**: [`OscillatorFilterOptions`](OscillatorFilterOptions.md) Defined in: [packages/core/src/poly-synth.ts:49](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L49) Peaking filter for default voice factory. *** ### stealStrategy? > `optional` **stealStrategy**: [`StealStrategy`](../type-aliases/StealStrategy.md) Defined in: [packages/core/src/poly-synth.ts:29](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L29) Voice stealing strategy when pool is full (default: 'lru'). *** ### type? > `optional` **type**: `OscillatorType` Defined in: [packages/core/src/poly-synth.ts:31](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L31) Oscillator waveform type for default voice factory (default: 'sine'). --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/ResumeEventDetail.md' --- [EZ Web Audio](../index.md) / ResumeEventDetail # Interface: ResumeEventDetail Defined in: [packages/core/src/events/event-types.ts:91](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L91) Detail for 'resume' events, fired when a Track resumes from pause. ## Properties ### beatIndex? > `optional` **beatIndex**: `number` Defined in: [packages/core/src/events/event-types.ts:99](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L99) For BeatTrack: the beat index where resumed *** ### position? > `optional` **position**: `number` Defined in: [packages/core/src/events/event-types.ts:97](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L97) The playback position (in seconds) where the track resumed *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:95](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L95) The Track instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:93](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L93) The audioContext.currentTime when resume occurred --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/SamplerOptions.md' --- [EZ Web Audio](../index.md) / SamplerOptions # Interface: SamplerOptions Defined in: [packages/core/src/sampler.ts:6](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L6) ## Extended by * [`BeatTrackOptions`](BeatTrackOptions.md) ## Properties ### name? > `optional` **name**: `string` Defined in: [packages/core/src/sampler.ts:7](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sampler.ts#L7) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/SeekEventDetail.md' --- [EZ Web Audio](../index.md) / SeekEventDetail # Interface: SeekEventDetail Defined in: [packages/core/src/events/event-types.ts:105](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L105) Detail for 'seek' events, fired when a Track's playback position changes. ## Properties ### position > **position**: `number` Defined in: [packages/core/src/events/event-types.ts:111](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L111) The new playback position (in seconds) *** ### previousPosition > **previousPosition**: `number` Defined in: [packages/core/src/events/event-types.ts:113](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L113) The previous playback position (in seconds) before the seek *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:109](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L109) The Track instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:107](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L107) The audioContext.currentTime when seek occurred --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/SequenceEventDetail.md --- [EZ Web Audio](../index.md) / SequenceEventDetail # Interface: SequenceEventDetail Defined in: [packages/core/src/events/event-types.ts:297](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L297) Detail for Sequence 'event' events, fired when a scheduled callback fires. ## Properties ### eventId > **eventId**: `string` Defined in: [packages/core/src/events/event-types.ts:303](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L303) The event ID returned by sequence.at() *** ### position > **position**: [`TransportPosition`](TransportPosition.md) Defined in: [packages/core/src/events/event-types.ts:301](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L301) Musical time position of the event *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:305](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L305) The Sequence instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:299](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L299) AudioContext time when the event fires --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/SequenceEventMap.md' --- [EZ Web Audio](../index.md) / SequenceEventMap # Interface: SequenceEventMap Defined in: [packages/core/src/events/event-types.ts:321](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L321) Maps Sequence event names to their corresponding CustomEvent types. ## Properties ### event > **event**: `CustomEvent`<[`SequenceEventDetail`](SequenceEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:322](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L322) *** ### loop > **loop**: `CustomEvent`<[`SequenceLoopDetail`](SequenceLoopDetail.md)> Defined in: [packages/core/src/events/event-types.ts:323](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L323) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/SequenceLoopDetail.md --- [EZ Web Audio](../index.md) / SequenceLoopDetail # Interface: SequenceLoopDetail Defined in: [packages/core/src/events/event-types.ts:311](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L311) Detail for Sequence 'loop' events, fired when the sequence wraps around. ## Properties ### iteration > **iteration**: `number` Defined in: [packages/core/src/events/event-types.ts:313](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L313) Loop iteration count (1-indexed) *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:315](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L315) The Sequence instance that emitted this event --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/SequenceOptions.md' --- [EZ Web Audio](../index.md) / SequenceOptions # Interface: SequenceOptions Defined in: [packages/core/src/sequence.ts:19](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L19) Configuration options for creating a Sequence. ## Properties ### events? > `optional` **events**: `object`\[] Defined in: [packages/core/src/sequence.ts:25](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L25) Initial events to schedule #### callback > **callback**: [`SequenceCallback`](../type-aliases/SequenceCallback.md) #### time > **time**: [`MusicalTimeNotation`](../type-aliases/MusicalTimeNotation.md) *** ### length > **length**: [`MusicalTimeNotation`](../type-aliases/MusicalTimeNotation.md) Defined in: [packages/core/src/sequence.ts:21](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L21) Length of the sequence in musical time notation or beats. Required. *** ### loop? > `optional` **loop**: `boolean` Defined in: [packages/core/src/sequence.ts:23](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L23) Whether the sequence loops. Default: true --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/SpriteDefinition.md' --- [EZ Web Audio](../index.md) / SpriteDefinition # Interface: SpriteDefinition Defined in: [packages/core/src/sprite.ts:7](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L7) Definition of a single sprite within the audio file. ## Properties ### end > **end**: `number` Defined in: [packages/core/src/sprite.ts:11](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L11) End time in seconds *** ### loop? > `optional` **loop**: `boolean` Defined in: [packages/core/src/sprite.ts:13](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L13) Whether to loop (default: false) *** ### start > **start**: `number` Defined in: [packages/core/src/sprite.ts:9](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L9) Start time in seconds --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/SpritePlayOptions.md' --- [EZ Web Audio](../index.md) / SpritePlayOptions # Interface: SpritePlayOptions Defined in: [packages/core/src/sprite.ts:127](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L127) Options for playing a specific sprite. ## Properties ### gain? > `optional` **gain**: `number` Defined in: [packages/core/src/sprite.ts:129](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L129) Gain level 0-1 (default: 1) *** ### pan? > `optional` **pan**: `number` Defined in: [packages/core/src/sprite.ts:131](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L131) Pan position -1 to 1 (default: 0) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/StopEventDetail.md' --- [EZ Web Audio](../index.md) / StopEventDetail # Interface: StopEventDetail Defined in: [packages/core/src/events/event-types.ts:46](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L46) Detail for 'stop' events, fired when audio playback is stopped. ## Properties ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:50](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L50) The sound instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:48](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L48) The audioContext.currentTime when playback stopped --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/TimeObject.md' --- [EZ Web Audio](../index.md) / TimeObject # Interface: TimeObject Defined in: [packages/core/src/utils/create-time-object.ts:29](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/create-time-object.ts#L29) An object containing a duration in three formats. The three formats are `raw`, `string`, and `pojo`. Duration of 6 minutes would be formatted as: ``` { raw: 360, // seconds string: '06:00', pojo: { minutes: 6, seconds: 0 } } ``` ## Properties ### pojo > **pojo**: `object` Defined in: [packages/core/src/utils/create-time-object.ts:32](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/create-time-object.ts#L32) The duration in a POJO format #### minutes > **minutes**: `number` #### seconds > **seconds**: `number` *** ### raw > **raw**: `number` Defined in: [packages/core/src/utils/create-time-object.ts:30](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/create-time-object.ts#L30) The duration in seconds *** ### string > **string**: `string` Defined in: [packages/core/src/utils/create-time-object.ts:31](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/create-time-object.ts#L31) The duration in a string format --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/TrackEventMap.md' --- [EZ Web Audio](../index.md) / TrackEventMap # Interface: TrackEventMap Defined in: [packages/core/src/events/event-types.ts:138](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L138) Event map for Track instances (extends BaseSoundEventMap with pause/resume/seek). Only Track emits pause, resume, and seek events. ## Extends * [`BaseSoundEventMap`](BaseSoundEventMap.md) ## Properties ### dispose > **dispose**: `CustomEvent`<`DisposeEventDetail`> Defined in: [packages/core/src/events/event-types.ts:131](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L131) #### Inherited from [`BaseSoundEventMap`](BaseSoundEventMap.md).[`dispose`](BaseSoundEventMap.md#dispose) *** ### end > **end**: `CustomEvent`<[`EndEventDetail`](EndEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:130](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L130) #### Inherited from [`BaseSoundEventMap`](BaseSoundEventMap.md).[`end`](BaseSoundEventMap.md#end) *** ### pause > **pause**: `CustomEvent`<[`PauseEventDetail`](PauseEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:139](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L139) *** ### play > **play**: `CustomEvent`<[`PlayEventDetail`](PlayEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:128](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L128) #### Inherited from [`BaseSoundEventMap`](BaseSoundEventMap.md).[`play`](BaseSoundEventMap.md#play) *** ### resume > **resume**: `CustomEvent`<[`ResumeEventDetail`](ResumeEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:140](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L140) *** ### seek > **seek**: `CustomEvent`<[`SeekEventDetail`](SeekEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:141](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L141) *** ### stop > **stop**: `CustomEvent`<[`StopEventDetail`](StopEventDetail.md)> Defined in: [packages/core/src/events/event-types.ts:129](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L129) #### Inherited from [`BaseSoundEventMap`](BaseSoundEventMap.md).[`stop`](BaseSoundEventMap.md#stop) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/TransportErrorDetail.md --- [EZ Web Audio](../index.md) / TransportErrorDetail # Interface: TransportErrorDetail Defined in: [packages/core/src/events/event-types.ts:270](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L270) Detail for Transport 'error' events, fired when the scheduler tick throws. The Transport is stopped before this event is emitted. ## Properties ### error > **error**: `unknown` Defined in: [packages/core/src/events/event-types.ts:272](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L272) The error thrown from the scheduler tick *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:276](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L276) The Transport instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:274](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L274) The audioContext.currentTime when the error occurred --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/TransportEventMap.md' --- [EZ Web Audio](../index.md) / TransportEventMap # Interface: TransportEventMap Defined in: [packages/core/src/events/event-types.ts:282](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L282) Maps Transport event names to their corresponding CustomEvent types. ## Properties ### error > **error**: `CustomEvent`<[`TransportErrorDetail`](TransportErrorDetail.md)> Defined in: [packages/core/src/events/event-types.ts:289](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L289) *** ### loop > **loop**: `CustomEvent`<[`TransportLoopDetail`](TransportLoopDetail.md)> Defined in: [packages/core/src/events/event-types.ts:288](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L288) *** ### pause > **pause**: `CustomEvent`<[`TransportLifecycleDetail`](TransportLifecycleDetail.md)> Defined in: [packages/core/src/events/event-types.ts:285](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L285) *** ### resume > **resume**: `CustomEvent`<[`TransportLifecycleDetail`](TransportLifecycleDetail.md)> Defined in: [packages/core/src/events/event-types.ts:286](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L286) *** ### start > **start**: `CustomEvent`<[`TransportLifecycleDetail`](TransportLifecycleDetail.md)> Defined in: [packages/core/src/events/event-types.ts:283](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L283) *** ### stop > **stop**: `CustomEvent`<[`TransportLifecycleDetail`](TransportLifecycleDetail.md)> Defined in: [packages/core/src/events/event-types.ts:284](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L284) *** ### tick > **tick**: `CustomEvent`<[`TransportTickDetail`](TransportTickDetail.md)> Defined in: [packages/core/src/events/event-types.ts:287](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L287) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/TransportLifecycleDetail.md --- [EZ Web Audio](../index.md) / TransportLifecycleDetail # Interface: TransportLifecycleDetail Defined in: [packages/core/src/events/event-types.ts:247](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L247) Detail for Transport lifecycle events (start, stop, pause, resume). ## Properties ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:251](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L251) The Transport instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:249](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L249) The audioContext.currentTime when the event occurred --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/TransportLoopDetail.md --- [EZ Web Audio](../index.md) / TransportLoopDetail # Interface: TransportLoopDetail Defined in: [packages/core/src/events/event-types.ts:257](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L257) Detail for Transport 'loop' events, fired each time the loop region wraps. ## Properties ### iteration > **iteration**: `number` Defined in: [packages/core/src/events/event-types.ts:259](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L259) Loop iteration count (1-indexed) *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:263](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L263) The Transport instance that emitted this event *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:261](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L261) AudioContext time of the wrap --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/TransportOptions.md' --- [EZ Web Audio](../index.md) / TransportOptions # Interface: TransportOptions Defined in: [packages/core/src/transport.ts:26](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L26) Configuration options for creating a Transport. ## Properties ### bpm > **bpm**: `number` Defined in: [packages/core/src/transport.ts:28](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L28) Tempo in beats per minute. Must be > 0. *** ### ticksPerBeat? > `optional` **ticksPerBeat**: `number` Defined in: [packages/core/src/transport.ts:32](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L32) Number of ticks per beat for position resolution. Default: 4 (16th note resolution) *** ### timeSignature? > `optional` **timeSignature**: \[`number`, `number`] Defined in: [packages/core/src/transport.ts:30](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L30) Time signature as \[beatsPerBar, beatUnit]. Default: \[4, 4] --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/interfaces/TransportPosition.md' --- [EZ Web Audio](../index.md) / TransportPosition # Interface: TransportPosition Defined in: [packages/core/src/transport.ts:38](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L38) Musical time position reported by the Transport. ## Properties ### bar > **bar**: `number` Defined in: [packages/core/src/transport.ts:40](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L40) Current bar number (1-indexed) *** ### beat > **beat**: `number` Defined in: [packages/core/src/transport.ts:42](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L42) Current beat within the bar (1-indexed) *** ### seconds > **seconds**: `number` Defined in: [packages/core/src/transport.ts:46](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L46) Elapsed time in seconds since playback started *** ### tick > **tick**: `number` Defined in: [packages/core/src/transport.ts:44](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/transport.ts#L44) Current tick within the beat (0-indexed) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/TransportTickDetail.md --- [EZ Web Audio](../index.md) / TransportTickDetail # Interface: TransportTickDetail Defined in: [packages/core/src/events/event-types.ts:231](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L231) Detail for Transport 'tick' events, fired on every beat subdivision. Contains the current position in musical time. ## Properties ### bar > **bar**: `number` Defined in: [packages/core/src/events/event-types.ts:233](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L233) Current bar number (1-indexed) *** ### beat > **beat**: `number` Defined in: [packages/core/src/events/event-types.ts:235](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L235) Current beat within bar (1-indexed) *** ### seconds > **seconds**: `number` Defined in: [packages/core/src/events/event-types.ts:239](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L239) Elapsed time in seconds since transport started *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:241](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L241) The Transport instance that emitted this event *** ### tick > **tick**: `number` Defined in: [packages/core/src/events/event-types.ts:237](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L237) Current tick within beat (0-indexed) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/VoiceStolenEventDetail.md --- [EZ Web Audio](../index.md) / VoiceStolenEventDetail # Interface: VoiceStolenEventDetail Defined in: [packages/core/src/events/event-types.ts:332](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L332) Detail for 'voicestolen' events, fired when a PolySynth voice is stolen to accommodate a new note request when the voice pool is full. ## Properties ### newFrequency > **newFrequency**: `number` Defined in: [packages/core/src/events/event-types.ts:336](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L336) Frequency of the new note that replaced it *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:340](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L340) The PolySynth instance that emitted this event *** ### stolenFrequency > **stolenFrequency**: `number` Defined in: [packages/core/src/events/event-types.ts:334](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L334) Frequency of the voice that was stolen *** ### time > **time**: `number` Defined in: [packages/core/src/events/event-types.ts:338](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L338) The audioContext.currentTime when the steal occurred --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/interfaces/WarningEventDetail.md --- [EZ Web Audio](../index.md) / WarningEventDetail # Interface: WarningEventDetail Defined in: [packages/core/src/events/event-types.ts:205](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L205) Detail for 'warning' events, fired when LayeredSound encounters issues. ## Properties ### failedLayers > **failedLayers**: `object`\[] Defined in: [packages/core/src/events/event-types.ts:209](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L209) Array of layers that failed to load #### error > **error**: `Error` #### index > **index**: `number` *** ### message > **message**: `string` Defined in: [packages/core/src/events/event-types.ts:207](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L207) Human-readable warning message *** ### source > **source**: [`AudioEventSource`](../type-aliases/AudioEventSource.md) Defined in: [packages/core/src/events/event-types.ts:211](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L211) The LayeredSound instance that emitted this event --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/drum-machine.md' description: >- Build a drum machine step sequencer with the Web Audio API. Interactive demo with kick, snare, and hi-hat patterns at configurable BPM. --- # Drum Machine Create rhythmic patterns with a step sequencer using the BeatTrack API. Step sequencer drum machine with kick, snare, and hi-hat tracks. 16-step grid with clickable cells, BPM slider, and visual playhead highlighting the current beat. ## How to Use * **Click cells** to toggle beats on/off in the 16-step grid * **Press Play** to hear your pattern loop * **Adjust BPM** with the slider (60-200 BPM) * **Visual playhead** highlights the current beat in sync with audio ## Quick Start ```typescript import { createBeatTrack } from 'ez-web-audio' const kick = await createBeatTrack(['/audio/kick1.wav'], { numBeats: 16 }) // Set a four-on-the-floor pattern kick.beats[0].active = true kick.beats[4].active = true kick.beats[8].active = true kick.beats[12].active = true kick.playBeats(120, 1 / 16) // 120 BPM, sixteenth notes ``` ## Visual Sync The playhead highlighting in the demo above works because each Beat object has properties that auto-toggle on the scheduler's timeline: | Property | When true | Use for | |---|---|---| | `beat.currentTimeIsPlaying` | This beat's time slot is active (playing or resting) | Playhead indicator on all steps | | `beat.isPlaying` | This beat is producing sound right now | Highlight only when sound plays | Both reset to `false` automatically after `duration` ms (default 100ms). No manual bookkeeping needed. In frameworks with reactive proxies (Vue, Solid, etc.), wrap beats to make these properties trigger re-renders: ```typescript const kick = await createBeatTrack(['/audio/kick1.wav'], { numBeats: 16, wrapWith: beat => reactive(beat) // Vue's reactive() }) ``` Then bind directly in your template — no event listeners, no setTimeout, no separate state: ```vue ) } ``` No `AudioContext` exists until that first click. The library lazily creates it inside `load()`/`createSound()`, which satisfies the browser's user-gesture requirement for free — there's no separate "init" step required for the common case. If you need to warm up the shared context ahead of a factory hook — for example, priming iOS's audio unlock before the user reaches the control that calls `load()` — call `useAudioContext().init()` from an event handler: ```tsx import { useAudioContext } from '@ez-web-audio/react' function UnlockButton() { const { ready, init } = useAudioContext() return ( ) } ``` `init()` is idempotent and safe to call multiple times or from multiple components — it de-dupes concurrent calls and resolves immediately once the context is ready. ## Full Examples These match [`examples/react-basic/src/App.tsx`](https://github.com/sethbrasile/ez-web-audio/blob/main/examples/react-basic/src/App.tsx) exactly — a minimal Vite + React app that exercises three hooks with no "Load" button, per the library's demo conventions (audio initializes on the user's first interaction). ### One-shot playback — `useSound` ```tsx function ClickSound() { const { instance, loading, error, load } = useSound() const cleanup = useCleanup() async function handleClick() { if (instance) { // Already loaded — just replay it. instance.play() return } const sound = await load('https://sethbrasile.github.io/ez-web-audio/audio/click.mp3') cleanup.register(sound) sound.play() } return (
{error &&

{error.message}

}
) } ``` ### Play/stop toggle — `useOscillator` ```tsx function OscillatorToggle() { const { instance, loading, error, load } = useOscillator() const cleanup = useCleanup() const [playing, setPlaying] = useState(false) async function handleClick() { let osc = instance if (!osc) { osc = await load({ frequency: 440, // A4 type: 'sawtooth', envelope: { attack: 0.01, decay: 0.2, sustain: 0.5, release: 0.3 }, }) cleanup.register(osc) } if (playing) { await osc.stop() setPlaying(false) } else { await osc.play() setPlaying(true) } } return (
{error &&

{error.message}

}
) } ``` ### Mini keyboard — `usePolySynth` and `VoiceHandle` `PolySynth` has no `noteOn`/`noteOff` pair. Instead `synth.play(...)` returns a `VoiceHandle` per note, and `handle.stop()` releases exactly that voice. A `Map` in a `useRef` — not `useState` — tracks which handle belongs to which held key, so pointer-up releases the right voice: ```tsx import type { PolySynth, VoiceHandle } from 'ez-web-audio' function MiniKeyboard() { const { instance, loading, error, load } = usePolySynth() const cleanup = useCleanup() const handles = useRef(new Map()) async function ensureSynth(): Promise { if (instance) return instance const synth = await load({ type: 'triangle', envelope: { attack: 0.01, decay: 0.2, sustain: 0.5, release: 0.3 }, }) cleanup.register(synth) return synth } async function noteOn(note: string, frequency: number) { const synth = await ensureSynth() handles.current.set(note, synth.play({ frequency })) } function noteOff(note: string) { const handle = handles.current.get(note) if (handle) { void handle.stop() handles.current.delete(note) } } return (
{KEYS.map(({ note, frequency }) => ( ))}
{error &&

{error.message}

}
) } ``` `onPointerDown`/`onPointerUp` (not `onClick`) so holding the key sustains the note, and `onPointerLeave` releases it even if the pointer drags off the button while held. ## SSR and Next.js Importing `ez-web-audio` and `@ez-web-audio/react` is safe at module scope in an SSR environment — the shared `AudioContext` is created lazily inside `getOrCreateAudioContext()`, which only runs when a factory hook's `load()` (or `useAudioContext().init()`) actually executes from an event handler. No top-level code touches `window` or constructs an `AudioContext`. Even so, in a Next.js App Router project: * Add `'use client'` to the top of any component file that calls these hooks — they use `useState`/`useEffect`/`useRef` internally and cannot run in a Server Component. * Don't call `load()` in a bare `useEffect` on mount — that reintroduces the "AudioContext created without a user gesture" problem the hooks are designed to avoid. Gate audio creation behind a real interaction (click, keypress), exactly as the examples above do. * `useAudioContext()`'s own `init()` dynamically `import()`s `ez-web-audio` rather than importing it eagerly — a defensive pattern worth mirroring if you lazy-load other browser-only modules alongside it. Combine with `next/dynamic` (`{ ssr: false }`) for a component if it does non-audio browser-only work too (canvas, `ResizeObserver`, etc.) at render time — the hooks themselves don't require it. ## BeatTrack: Where React and Vue Diverge `useBeatTrack` returns the same `{ instance, loading, error, load, reset }` shape as every other hook — `instance` is a real `BeatTrack` with a `beats` array. This is the one spot where the parity with `@ez-web-audio/vue` breaks, because the two frameworks have fundamentally different reactivity models: | | `@ez-web-audio/vue` | `@ez-web-audio/react` | |---|---|---| | `beats` array | Wrapped via `wrapWith: beat => reactive(beat)` | Plain `Beat` instances, unwrapped | | Mutating `beat.active`/`currentTimeIsPlaying` | Triggers a re-render automatically | **Invisible to React** — no proxy, no signal | | How the UI reflects playback | Template binds directly to `beat.currentTimeIsPlaying` | Poll on `requestAnimationFrame`, or listen for the `beat` event | | Setup cost | One option (`wrapWith`) | A small polling loop or event subscription | Vue's `reactive()` is a proxy that Vue's renderer already watches; React has no built-in equivalent that works on a plain class instance. `BeatTrack.beats[i].active = true` will change the object, but nothing tells React to re-render — you have to ask for the update yourself, one of two ways. ### Pattern A: `requestAnimationFrame` polling Read `beatTrack.beats` every frame and copy the fields you care about into state: ```tsx function useBeatTrackPlayhead(beatTrack: BeatTrack | null) { const [currentBeat, setCurrentBeat] = useState(null) const rafRef = useRef(0) useEffect(() => { if (!beatTrack) return function tick() { const playing = beatTrack!.beats.findIndex(b => b.currentTimeIsPlaying) setCurrentBeat(playing === -1 ? null : playing) rafRef.current = requestAnimationFrame(tick) } rafRef.current = requestAnimationFrame(tick) return () => cancelAnimationFrame(rafRef.current) }, [beatTrack]) return currentBeat } ``` This is the same rAF-over-`audioContext.currentTime` mechanism the library uses internally for timing — see [Vanilla TS Events](/examples/drum-machine-vanilla#audiocontext-aware-timing) for why it doesn't drift. ### Pattern B: the `beat` event `BeatTrack` emits a `beat` event at play time via its internal `TypedEventEmitter`, carrying `{ time, beatIndex, active, source }` in `event.detail`. Subscribe in a `useEffect` and mirror it into state: ```tsx function useBeatTrackPlayhead(beatTrack: BeatTrack | null) { const [currentBeat, setCurrentBeat] = useState(null) useEffect(() => { if (!beatTrack) return function onBeat(e: CustomEvent<{ beatIndex: number, active: boolean }>) { setCurrentBeat(e.detail.beatIndex) } beatTrack.on('beat', onBeat) return () => beatTrack.off('beat', onBeat) }, [beatTrack]) return currentBeat } ``` Either pattern works — polling is simpler when you also need continuous values (e.g. driving a CSS transform every frame); the event is cheaper when you only care about discrete beat boundaries. Both ride the same `audioContextAwareTimeout` scheduling as the Vue `reactive()` path, so timing precision is identical across all three approaches — only the plumbing that gets state into your UI differs. ## Try It: StackBlitz Live StackBlitz embed of the full `examples/react-basic` app (three sections: `useSound`, `useOscillator`, `usePolySynth`). Not renderable in this context — use the link below. Prefer opening it directly? [github.com/sethbrasile/ez-web-audio/tree/main/examples/react-basic](https://github.com/sethbrasile/ez-web-audio/tree/main/examples/react-basic) ## See Also * [Vue Reactive Pattern](/examples/drum-machine-vue) — the `@ez-web-audio/vue` composables, same hook shape, `wrapWith: reactive()` for BeatTrack * [Vanilla TS Events](/examples/drum-machine-vanilla) — the `beat` event and `audioContextAwareTimeout` explained in depth * [Core Concepts](/guide/concepts) — the library's architecture underneath every binding * [Parameter Control](/guide/parameter-control) — automate gain, frequency, and other parameters --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/sampled-drum-kit.md' description: >- Trigger realistic drum sounds from audio samples with round-robin variation. Interactive pads for kick, snare, hi-hat, and more. --- # Sampled Drum Kit Play realistic drum sounds with round-robin sample variations for more natural playback. Clickable drum pad interface triggering sampled kick, snare, hi-hat, and percussion sounds with round-robin sample variation. ## What is Round-Robin? Round-robin is a technique where multiple recordings of the same instrument are cycled through during playback. This creates a more natural, realistic sound compared to playing the same sample repeatedly. **Why it matters:** * **Prevents the "machine gun" effect** — repeatedly playing one sample sounds artificial and robotic * **Adds variation** — each sample has slight differences in tone, attack, and decay * **Sounds more human** — mimics how real drummers never hit a drum exactly the same way twice In this demo, each drum pad cycles through 3 different recordings. Watch the sample counter to see which variation is playing. ## How It Works The `createSampler()` function loads multiple audio files and automatically rotates through them on each `play()` call: ```typescript import { createSampler } from 'ez-web-audio' const kick = await createSampler([ '/audio/kick1.wav', '/audio/kick2.wav', '/audio/kick3.wav' ]) kick.play() // Plays kick1 kick.play() // Plays kick2 kick.play() // Plays kick3 kick.play() // Plays kick1 (wraps around) ``` Each call to `play()` automatically advances to the next sample in the array, creating natural variation without any manual tracking. ## Comparison with Synthesis Compare this sampled drum kit with the [Synth Drum Kit](/examples/synth-drum-kit) which creates all sounds from synthesis. Sampled drums sound more realistic but require larger audio files, while synthesized drums are more flexible and use zero bandwidth. **Sampled drums:** * ✅ Realistic, authentic instrument sound * ✅ Natural acoustic characteristics * ❌ Larger file sizes (3 samples × 3 drums = ~2.8MB) * ❌ Fixed timbre (can't change the sound much) **Synthesized drums:** * ✅ Tiny file size (code only) * ✅ Fully customizable (frequency, waveform, filter, envelope) * ❌ Harder to make sound realistic * ❌ Requires synthesis knowledge ## API Used This example demonstrates: * **`createSampler(urls)`** — Create a round-robin sampler from audio file URLs * **`sampler.play()`** — Play the next sample in rotation * **Loading multiple files** — Each sampler loads 3 WAV files (~300-500KB each) ## Next Steps * Explore [Drum Machine](/examples/drum-machine) to sequence these samples into rhythmic patterns * Try [Soundfont Piano](/examples/soundfont-piano) for another sampling-based instrument * Learn about [synthesis](/examples/synth-drum-kit) as an alternative to samples --- --- url: 'https://sethbrasile.github.io/ez-web-audio/guide/sequence.md' description: >- Schedule arbitrary callbacks at musical time positions using the Sequence class tied to a Transport clock. --- # Sequence Sequence schedules callbacks at musical time positions tied to a Transport. Events are stored as beat positions, so live BPM changes automatically affect timing without re-scheduling. ## Basic Usage ```typescript import { createSequence, createSound, createTransport } from 'ez-web-audio' const transport = await createTransport({ bpm: 120, timeSignature: [4, 4] }) const bell = await createSound('/sounds/bell.mp3') const seq = createSequence(transport, { length: '2m', // 2 measures long loop: true // Repeat }) // Schedule events at musical positions seq.at('1:1:0', () => bell.play()) // Bar 1, Beat 1 seq.at('1:3:0', () => bell.play()) // Bar 1, Beat 3 seq.at('2:1:0', () => bell.play()) // Bar 2, Beat 1 transport.start() // Events fire at correct musical positions ``` ## Musical Time Notation Sequence supports musical time notation for the `length` option: | Notation | Meaning | |----------|---------| | `'4n'` | Quarter note (1 beat) | | `'8n'` | Eighth note (0.5 beats) | | `'16n'` | Sixteenth note (0.25 beats) | | `'2n'` | Half note (2 beats) | | `'1m'` | One measure | | `'4m'` | Four measures | | `'8t'` | Eighth note triplet | ## Event Scheduling Events are scheduled using `bar:beat:tick` position strings: ```typescript seq.at('1:1:0', (time, position) => { console.log(`Firing at bar ${position.bar}, beat ${position.beat}`) bell.play() }) ``` The callback receives: * `time` -- Precise AudioContext time for scheduling audio operations * `position` -- Transport position at the moment the event fires ## Live BPM Changes Events respond to BPM changes automatically: ```typescript transport.bpm = 140 // All sequence events adjust timing ``` ## Cleanup ```typescript seq.dispose() // Removes all events, detaches from Transport ``` ## Next Steps * [Transport](/guide/transport) -- Global clock for multi-track sync * [API Reference](/api/) -- Full Sequence API docs --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/soundfont-piano.md' description: >- Play realistic piano sounds using soundfont samples loaded from base64-encoded audio. Multi-octave keyboard with velocity-sensitive playback. --- # Soundfont Piano Play a realistic piano with real instrument samples loaded from a soundfont. Multi-octave piano keyboard using base64-encoded soundfont samples. Click keys or use keyboard input for velocity-sensitive playback. ## What is a Soundfont? A soundfont is a collection of pre-recorded instrument samples mapped to different pitches. Instead of synthesizing sounds with oscillators, soundfonts play back real audio recordings of acoustic instruments. **How it works:** 1. **Recording** — Each note is recorded from a real piano at different pitches and velocities 2. **Encoding** — Audio samples are compressed and encoded (often as base64 in MIDI.js format) 3. **Decoding** — The library decodes the audio data and creates playable notes 4. **Playback** — When you call `font.play('C4')`, it plays the pre-recorded C4 sample **Advantages:** * Realistic, authentic instrument sound * Natural acoustic characteristics (resonance, harmonics, decay) * Professional quality without synthesis expertise **Trade-offs:** * Larger file size (the piano soundfont is 1.4MB) * Loading time on slower connections * **Synchronous parsing** — soundfont data is decoded on the main thread; files over 5 MB may briefly freeze the UI on mobile devices * Fixed timbre (can't drastically change the sound like synthesis) ## How It Works The `createFont()` function loads a soundfont file and creates playable notes: ```typescript import { createFont } from 'ez-web-audio' const piano = await createFont('/audio/piano.js') // Play notes by identifier (note name + octave) piano.play('C4') // Middle C piano.play('E4') // E above middle C piano.play('G4') // G major chord with C4 // Get a specific note for advanced control const note = piano.getNote('A4') if (note) { note.changeGainTo(0.5) // Adjust volume note.play() } ``` **Note identifiers** use the format `letter + accidental + octave`: * Letters: C, D, E, F, G, A, B * Accidentals: flat (b) or natural (no symbol) * Octave: 0-8 Examples: `C4` (middle C), `Db4` (C# above middle C), `A4` (concert A at 440Hz) ## Comparison with Synthesis This piano uses **real recorded samples**. Compare with the [Synth Keyboard](/examples/synth-keyboard) which generates sounds from oscillators. | Soundfont Piano | Synth Keyboard | |-----------------|----------------| | ✅ Realistic piano sound | ✅ Fully customizable waveforms | | ✅ Natural acoustic decay | ✅ ADSR envelope control | | ✅ No synthesis knowledge needed | ✅ Tiny file size (code only) | | ❌ 1.4MB download | ❌ Harder to sound realistic | | ❌ Fixed timbre | ✅ Real-time parameter changes | **When to use soundfonts:** * You need realistic instrument sounds * File size is acceptable for your use case * You don't need to heavily customize the timbre **When to use synthesis:** * You need small file sizes * You want full control over the sound * You're creating electronic or sci-fi sounds ## Component Reuse This example reuses the `PianoKeyboard` component from [Synth Keyboard](/examples/synth-keyboard). The same visual piano keyboard works for both synthesized and sampled instruments — just swap out the sound engine! ## API Used This example demonstrates: * **`createFont(url)`** — Load a soundfont from a MIDI.js format file * **`font.play(noteIdentifier)`** — Play a note by its identifier string (e.g., 'C4') * **`font.getNote(noteIdentifier)`** — Get a specific note for advanced control * **Note naming** — Flat notation (Db, Eb, Gb, Ab, Bb) matches the library's frequency map ## Next Steps * Try [Sampled Drum Kit](/examples/sampled-drum-kit) for another example of sample-based playback * Explore [Synth Keyboard](/examples/synth-keyboard) to compare with oscillator-based synthesis * Learn about [Drum Machine](/examples/drum-machine) to sequence notes into melodies --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/layered-sound.md' description: >- Play multiple sounds at exactly the same moment using playTogether() for one-shot triggers, or LayeredSound for ongoing control with master gain and pan. --- # Synchronized Multi-Sound Playback EZ Web Audio provides two ways to play multiple sounds at exactly the same moment using the Web Audio API's precise timing: * **`playTogether()`** — A one-liner for fire-and-forget synchronized playback * **`LayeredSound`** — A class with master gain/pan and per-layer control ## playTogether() The simplest way to play multiple sounds at the same time: ```typescript import { createSound, playTogether } from 'ez-web-audio' const kick = await createSound('kick.mp3') const snare = await createSound('snare.mp3') const hihat = await createSound('hihat.mp3') // All three start at the exact same AudioContext time await playTogether([kick, snare, hihat]) ``` `playTogether()` gets the current `audioContext.currentTime`, adds a tiny scheduling offset, and calls `playAt()` on every sound with the same timestamp. Works with any mix of Sounds, Tracks, and Oscillators. ### Interactive Demo Play multiple sounds simultaneously using playTogether() for perfectly synchronized one-shot triggering. ## LayeredSound When you need ongoing control over a group of synchronized sounds — master volume, panning, per-layer mixing — use `LayeredSound`: ```typescript import { createLayeredSound, createSound } from 'ez-web-audio' const bass = await createSound('bass.mp3') const melody = await createSound('melody.mp3') const synth = await createSound('synth.mp3') const layered = await createLayeredSound([bass, melody, synth]) // All three sounds start at exactly the same time await layered.play() ``` ### Interactive Demo LayeredSound demo with individual volume sliders for each layer and a master gain control for the combined output. ### Master Controls Control all layers together using master gain and pan: ```typescript // Set master volume for all layers (0–1 range) layered.changeGainTo(0.75) // Set stereo panning for all layers (-1 left, 0 center, 1 right) layered.changePanTo(-0.2) await layered.play() ``` ### Individual Layer Access Get a specific layer by index for individual control: ```typescript const layered = await createLayeredSound([bass, melody, synth]) // Access individual layers (0-based index) const bassLayer = layered.getLayer(0) const melodyLayer = layered.getLayer(1) // Set individual layer gain bassLayer?.changeGainTo(0.9) melodyLayer?.changeGainTo(0.6) // Count active layers console.log(layered.layerCount) // 3 ``` ### Timed Playback Play all layers for a fixed duration, then auto-stop: ```typescript // Play all layers for 2 seconds, then stop automatically await layered.playFor(2) ``` ### Event Handling Listen for playback lifecycle events: ```typescript layered.on('play', (event) => { console.log(`Started at audioContext time: ${event.detail.time}`) }) layered.on('stop', () => { console.log('All layers stopped') }) layered.on('end', () => { // Fires when the last layer finishes (layers may end at different times) console.log('All layers finished naturally') }) layered.on('warning', (event) => { console.warn(`LayeredSound warning: ${event.detail.message}`) }) ``` ### Stopping All Layers Stop all layers at once: ```typescript await layered.stop() ``` ::: tip Layer Count Warning LayeredSound will log a console warning if you create an instance with 8 or more layers. This is configurable via `warnLayerCount` option. High layer counts may impact performance on some devices. ::: ```typescript // Customize the warning threshold const layered = await createLayeredSound(sounds, { warnLayerCount: 16 }) ``` ## Which Should I Use? `playTogether()` is a single function call — no class, no instance, no cleanup. It fires the sounds and you're done: ```typescript // That's it. One line. await playTogether([kick, snare, hihat]) ``` `LayeredSound` is a persistent object that holds references to your sounds and gives you ongoing control — master volume, panning, per-layer mixing, events. It's more powerful but more to manage: ```typescript const layered = await createLayeredSound([bass, melody, synth]) layered.setGain(0.75) layered.setPan(-0.2) await layered.play() // ... later await layered.stop() ``` | | `playTogether()` | `LayeredSound` | |--|------------------|----------------| | **Complexity** | One function call | Class instance with lifecycle | | **Synchronized start** | Yes | Yes | | **Master gain/pan** | No | Yes | | **Per-layer control** | Manual | Built-in | | **Best for** | One-shot triggers (chords, percussion hits) | Ongoing mixing and control | ## Next Steps * [Basic Playback](/examples/basic-playback) — Playing individual sounds * [AudioSprite](/examples/audio-sprite) — Pack multiple sounds into one file * [Crossfade](/examples/crossfade) — Smooth transitions between tracks --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/synth-drum-kit.md' description: >- Generate drum sounds purely from synthesis — kick drums from sine waves, snares from noise, hi-hats from square waves. No audio files needed. --- # Synth Drum Kit Create realistic drum sounds entirely from synthesis — no audio files needed. This example demonstrates advanced synthesis techniques using oscillators, white noise, and filters to build kick, snare, and hi-hat sounds from scratch. ## Try It: Synthesized Drums Tap the pads to hear drum sounds created entirely from synthesis. Each sound is generated in real-time using oscillators and filters. Synthesized drum kit generating kick, snare, and hi-hat sounds purely from oscillators. Clickable pads with no audio files required. ## How Each Sound Works ### Kick Drum The kick drum uses a **frequency sweep** technique. A triangle oscillator starts at 150 Hz and quickly drops to near 0 Hz, creating that characteristic "punch" sound. ```typescript import { createOscillator } from 'ez-web-audio' const kick = await createOscillator({ frequency: 150, type: 'triangle' }) // Frequency sweep: 150Hz → 0.01Hz in 100ms kick.onPlayRamp('frequency').from(150).to(0.01).in(0.1) // Gain envelope: full volume → silence in 100ms kick.onPlayRamp('gain').from(1).to(0).in(0.1) kick.changeGainTo(0.8) kick.play() setTimeout(() => kick.stop(), 200) ``` **Why triangle wave?** Triangle waves have fewer harmonics than square or sawtooth, giving the kick a cleaner, more focused low-end punch. **Why the frequency sweep?** Real kick drums have a pitch that drops as the drumhead settles. This sweep mimics that natural behavior. ### Snare Drum The snare is **two layers** playing simultaneously: 1. **Tonal body** ("meat") - Sine oscillator with frequency sweep (100 → 60 Hz) 2. **Snare crack** - White noise with highpass filter (1000 Hz cutoff) Both layers are combined with `createLayeredSound()` to ensure they start at exactly the same AudioContext timestamp. ```typescript import { createFilterEffect, createLayeredSound, createOscillator, createWhiteNoise } from 'ez-web-audio' // Layer 1: Tonal body const body = await createOscillator({ frequency: 100, type: 'sine' }) body.onPlayRamp('frequency').from(100).to(60).in(0.1) body.onPlayRamp('gain').from(1).to(0.01).in(0.1) // Layer 2: Snare crack const noise = await createWhiteNoise() const highpass = createFilterEffect('highpass', { frequency: 1000, q: 1 }) noise.addEffect(highpass) noise.onPlayRamp('gain').from(1).to(0.001).in(0.1) // Combine layers for synchronized playback const snare = await createLayeredSound([body, noise]) snare.playFor(0.1) ``` **Why layer?** Real snare drums have both a tonal component (the drum shell) and a bright, crackling component (the snare wires). `createLayeredSound()` synchronizes them to the same start time for a tight, cohesive sound. **Try the breakdown buttons** above to hear each layer separately and understand how they combine. ### Hi-Hat The hi-hat uses **multiple square oscillators** at harmonic ratios with highpass and bandpass filters. These create that characteristic metallic, shimmering sound. ```typescript import { createFilterEffect, createLayeredSound, createOscillator } from 'ez-web-audio' const fundamentalFreq = 40 // Metallic ratios: 2, 3, 4.16, 5.43, 6.79, 8.21 const ratios = [2, 3, 4.16, 5.43, 6.79, 8.21] const oscillators = await Promise.all( ratios.map(async (ratio) => { const osc = await createOscillator({ frequency: fundamentalFreq * ratio, type: 'square' }) // Highpass filter removes bass frequencies const highpass = createFilterEffect('highpass', { frequency: 7000, q: 1 }) // Bandpass filter isolates the metallic shimmer around 10kHz const bandpass = createFilterEffect('bandpass', { frequency: 10000, q: 1 }) osc.addEffect(highpass) osc.addEffect(bandpass) // ADSR-style envelope: quick attack, sustain, then decay osc.onPlayRamp('gain').from(0.00001).to(1).in(0.02) osc.onPlaySet('gain').to(0.3).endingAt(0.03) osc.onPlaySet('gain').to(0.00001).endingAt(0.3) return osc }) ) // Use LayeredSound for synchronized playback const hihat = await createLayeredSound(oscillators) hihat.playFor(0.1) ``` **Why multiple oscillators?** Real cymbals vibrate at many inharmonic frequencies simultaneously. Using multiple oscillators at slightly dissonant ratios creates that complex metallic timbre. **Why highpass + bandpass filters?** Cymbals have very little low-frequency content. The highpass filter (7000 Hz) removes bass frequencies, while the bandpass filter (10000 Hz) isolates the bright, metallic shimmer that makes a hi-hat sound like a hi-hat. ### Bass Drop A long, dramatic frequency sweep often used in electronic music: ```typescript const bassDrop = await createOscillator({ frequency: 100, type: 'sine' }) // Linear frequency sweep (steady pitch drop) and exponential gain decay bassDrop.onPlayRamp('frequency', 'linear').from(100).to(0.01).in(10) bassDrop.onPlayRamp('gain').from(1).to(0.01).in(10) bassDrop.playFor(10) ``` ## Try the Snare Breakdown Use the breakdown buttons above to hear the snare components separately. Each button plays a single layer in isolation: ```typescript // Play just the tonal body const meat = await createSnareMeat() // Sine oscillator, 100→60 Hz sweep meat.playFor(0.1) // Play just the snare crack const crack = await createSnareCrack() // Filtered white noise crack.playFor(0.1) // Play both together — createLayeredSound ensures exact same start time const snare = await createLayeredSound([meat, crack]) snare.playFor(0.1) ``` This demonstrates how layering different synthesis techniques creates realistic, complex sounds. ## Synthesis vs. Samples **Advantages of synthesis:** * **Zero file size** - No audio files to download * **Infinite variation** - Change pitch, length, timbre in real-time * **Perfectly loopable** - No clicks or pops * **Educational** - Understand how sounds are made **When to use samples instead:** * **Realistic acoustic instruments** - Hard to synthesize convincingly * **Complex textures** - Easier to record than build * **Quick iteration** - Faster to find the right sample than tune synthesis For electronic music and retro games, synthesis is often the better choice. For orchestral or realistic sounds, samples work better. ## API Used * `createOscillator()` - Creates synthesizers with different waveforms * `createWhiteNoise()` - Generates white noise for percussion "crack" * `createFilterEffect()` - Shapes frequency content (highpass, bandpass, etc.) * `createLayeredSound()` - Synchronizes multiple sounds to the same start time * `onPlayRamp()` - Schedules smooth parameter transitions during playback * `onPlaySet()` - Schedules instant parameter changes at specific times * `playFor()` - Plays a sound for a specific duration then stops * `addEffect()` - Routes audio through effects ## Next Steps * [XY Pad](/examples/xy-pad) - Real-time parameter control with visual feedback * [Effects](/examples/effects) - Explore different filter types and parameters * [Synthesis](/examples/synthesis) - Learn about ADSR envelopes and waveforms --- --- url: 'https://sethbrasile.github.io/ez-web-audio/guide/transport.md' description: >- Use the Transport clock to synchronize multiple BeatTracks and schedule events at musical time positions with Sequence. --- # Transport & Sequencing The Transport provides a global clock that multiple BeatTracks can lock to, enabling perfect multi-track synchronization. Combined with Sequence, you can schedule arbitrary callbacks at musical time positions. ## Creating a Transport ```typescript import { createTransport } from 'ez-web-audio' const transport = await createTransport({ bpm: 120, timeSignature: [4, 4] }) transport.start() transport.pause() transport.stop() ``` ## Syncing BeatTracks Instead of each BeatTrack running its own timer, sync them to a shared Transport: ```typescript import { createBeatTrack, createTransport } from 'ez-web-audio' const transport = await createTransport({ bpm: 120 }) const kick = await createBeatTrack(['/sounds/kick.wav'], { numBeats: 4 }) const hihat = await createBeatTrack(['/sounds/hihat.wav'], { numBeats: 8 }) kick.setPattern([1, 0, 1, 0]) hihat.setPattern([1, 1, 1, 1, 1, 1, 1, 1]) // Sync — kick plays quarter notes, hihat plays eighth notes kick.syncTo(transport, { noteType: 1 / 4 }) hihat.syncTo(transport, { noteType: 1 / 8 }) transport.start() // Both tracks play in perfect sync ``` Synced tracks cannot be started/stopped individually -- they follow the Transport. Use `track.unsync()` to detach. ## Position Tracking Transport reports position as bar:beat:tick: ```typescript import { formatPosition } from 'ez-web-audio' transport.on('tick', (e) => { const pos = e.detail console.log(formatPosition(pos)) // "1:3:2" console.log(pos.seconds) // elapsed time }) ``` ## Changing BPM BPM can be changed at any time -- all synced tracks and sequences adjust automatically: ```typescript transport.bpm = 140 // Immediate tempo change ``` ## Swing Add a shuffle feel without hand-placing offbeat notes. `swing` (0–1, default `0`) delays every other subdivision toward the triplet position; `swingSubdivision` picks whether that grid is eighth or sixteenth notes: ```typescript transport.swing = 0.55 // 0 = straight, 1 = full triplet shuffle transport.swingSubdivision = 1 / 8 // or 1/16 (default) ``` Swing only touches synced-track beats and Sequence events that land exactly on an odd subdivision — the playhead (`tick` events) always stays on-grid, and events that don't land on the subdivision (fills, syncopated hits) are never swung. Both properties throw if set outside their valid range, and both are live-changeable, including mid-playback: writing a pattern in straight 8ths and dialing `swing` from `0.55` down to `0` flattens it back to a straight feel, because the shuffle lives in the swing amount, not in the pattern data. ## Loop Region Loop a section of the timeline in place, without calling `stop()`/`start()`: ```typescript transport.loopStart = '1m' // musical notation ('1m', '2:1:0') or a numeric beat count transport.loopEnd = '2m' transport.loop = true // default: false transport.on('loop', (e) => { console.log(`loop ${e.detail.iteration} at ${e.detail.time}`) }) ``` `loopStart`/`loopEnd` accept musical notation or a raw beat count when set, and always read back as beats. Synced BeatTracks wrap their pattern index at `loopEnd` automatically. Sequences are **not** remapped into the loop region — a `Sequence` loops at its own `length`, so give it the same length as the loop region (e.g. `loopEnd - loopStart`) to keep it in lockstep with the transport's loop. An invalid region (`loopEnd <= loopStart`) throws when `loop` is enabled and the transport starts or resumes; toggling `loop` on live with an already-invalid region is silently ignored instead of throwing. ## Velocity `BeatTrack.setPattern()` accepts numbers instead of booleans — any value `> 0` both activates the beat and sets its `velocity` (a 0–1 gain multiplier applied on play), so ghost notes and accents live in the pattern data itself: ```typescript kick.setPattern([1, 0, 0.6, 0]) // 1 = full hit, 0.6 = ghost note, 0 = rest ``` `0`/`false` still means rest and `1`/`true` still means a full-velocity hit, so existing boolean patterns keep working unchanged. `Beat.velocity` can also be set directly (`kick.beats[2].velocity = 0.6`), and `Sampler.play()`/`playIn()`/`playAt()` all take an optional `velocity` argument for the same effect outside of BeatTrack patterns. ## Mute & Solo Control which synced tracks are audible: ```typescript kick.muted = true // Silence kick (beats still fire for UI) hihat.soloed = true // Only hihat is audible ``` ## Cleanup ```typescript transport.dispose() // Stops clock, unsyncs all tracks ``` ## Next Steps * [Sequence](/guide/sequence) -- Schedule callbacks at musical time positions * [Drum Machine Example](/examples/drum-machine) -- See Transport in action * [API Reference](/api/) -- Full Transport API docs --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/transport-sequencer.md' description: >- Interactive demo of BPM-synced transport with multi-track sequencing, mute/solo per track, musical time notation, and a visual step grid playhead. --- # Transport + Sequencer Control a BPM-synced transport driving 5 tracks -- 3 drum tracks and 2 melody tracks. Switch presets to hear five book-derived grooves (Rock, Funk, Disco, Bossa, Shuffle), then click any drum cell to edit the pattern live. Interactive multi-track sequencer demo with Transport clock control. Five tracks: Kick, Snare, Hi-hat (drum BeatTracks), Synth bass (Sequence + Oscillator), Lead (Sequence + Oscillator chords). Controls include Play/Pause/Stop, BPM slider, swing knob, mute (M) and solo (S) buttons per track, and five preset buttons (Rock, Funk, Disco, Bossa, Shuffle) adapted from a public-domain drum machine pattern book. Each drum lane's 32-step grid is directly editable — clicking a cell cycles it rest → normal → accent. A moving playhead column indicates the current step; position display shows current bar and beat. ## How It Works The Transport clock is the heartbeat of the whole demo: a Worker-backed musical clock that every track locks to instead of running its own timer. It fires a `tick` event at every 16th note, which the UI uses to advance the step-grid playhead column in sync with playback, and it drives a 2-bar loop (`transport.loop = true`, `transport.loopEnd = '2m'`) so all 5 tracks restart together on every pass. ### Drum Tracks via BeatTrack Each drum track (Kick, Snare, Hi-hat) is a `BeatTrack` that loads three sample variations and uses round-robin playback for a natural feel. Calling `syncTo(transport)` locks the beat track to the transport clock at whatever resolution it's given — this demo syncs all three drum lanes at 16th notes, while the melody tracks below run on their own musical-time `Sequence`, giving the whole rig multi-resolution sync from one shared clock: ```typescript import { createBeatTrack, createTransport } from 'ez-web-audio' const transport = await createTransport({ bpm: 96, timeSignature: [4, 4], ticksPerBeat: 4 }) const kick = await createBeatTrack(['/kick1.wav', '/kick2.wav', '/kick3.wav'], { numBeats: 32 }) // Numbers set velocity (0-1) as well as active/inactive -- 1 = accent, 0.6 = ghost note kick.setPattern([1, 0, 0, 0, 0, 0, 0.6, 0, 1, 0, 0, 0]) // first 12 of the 32-step pattern kick.syncTo(transport, { noteType: 1 / 16 }) // lock to transport grid ``` ### Swing: One Knob vs. Hand-Placed Shuffle The **Shuffle** preset is the pedagogical hook of this demo. Its drum and bass patterns are written in perfectly straight 8th/16th notes -- there is no shuffle baked into the pattern data at all. The groove comes entirely from a single Transport property: ```typescript transport.swing = 0.55 // MPC-style shuffle -- 0 = straight, 1 = full triplet feel transport.swingSubdivision = 1 / 8 // shuffle the 8th-note grid (default is 1/16) ``` Turn the swing knob down to `0` while Shuffle is playing and the groove flattens back to a straight, mechanical feel instantly -- the pattern didn't change, only the delay applied to every other subdivision did. That's the difference between hand-placing offbeat notes at shuffled positions and letting `swing` do the work: one knob re-shapes the whole track's feel live, without touching a single step. ### Melody Tracks via Sequence The Bass and Lead tracks use `createSequence()` to schedule notes at precise musical time positions, rather than syncing to a fixed grid like the drum lanes. `Sequence` events are addressed by raw beat number here (`0`, `1.5`, `2.5`...) but also support bar:beat:tick notation and note names (`'4n'`, `'8t'`) -- the same API expresses a bass line or a chord stab equally well. Because each preset supplies its own `length: '2m', loop: true`, matching the Transport's own `loopEnd = '2m'`, both the drum lanes and the melody sequences wrap back to the top of the pattern together. Each note gets its own `Oscillator` instead of one shared oscillator being retriggered -- reusing a single oscillator across triggers means a new note can race the previous note's release tail and click or screech. A chord stab (several notes at once, like the Lead track) is just several Oscillators triggered by the same sequence event: ```typescript import { createOscillator, createSequence, createTransport, getAudioContext } from 'ez-web-audio' const transport = await createTransport({ bpm: 96, timeSignature: [4, 4] }) transport.loop = true transport.loopEnd = '2m' const ctx = await getAudioContext() // sustain: 0 -- each note fades out on its own after decay, so it never // needs to be stopped or retriggered. The envelope's attack peaks at the // oscillator's `gain`, so both options compose. const envelope = { attack: 0.005, decay: 0.25, sustain: 0, release: 0.05 } const e2 = await createOscillator(ctx, { note: 'E2', type: 'triangle', gain: 0.5, envelope }) const g2 = await createOscillator(ctx, { note: 'G2', type: 'triangle', gain: 0.5, envelope }) const bassSeq = createSequence(transport, { length: '2m', loop: true }) // SYNC -- no await bassSeq.at(0, t => e2.playIn(Math.max(0, t - ctx.currentTime))) // E2 bassSeq.at(1.5, t => g2.playIn(Math.max(0, t - ctx.currentTime))) // G2 transport.start() ``` ### Mute and Solo Drum tracks use `BeatTrack.muted` and `BeatTrack.solo` properties directly -- the library handles solo stacking natively. Melody tracks are guarded by a callback check: if any track is soloed, only soloed melody tracks fire their events: ```typescript function shouldPlay(name: 'bass' | 'lead'): boolean { const anySoloed = Object.values(trackState).some(t => t.soloed) if (anySoloed) return trackState[name].soloed return !trackState[name].muted } ``` ### Live Playhead The `transport.on('tick')` event drives the step-grid highlight. Each tick carries `{ bar, beat, tick }`, which maps to a 16th-note step index across the 2-bar loop: ```typescript transport.on('tick', (e) => { const { bar, beat, tick } = e.detail const step = ((bar - 1) * 16) + ((beat - 1) * 4) + tick currentStep.value = step % 32 // 32-step loop positionDisplay.value = `${bar}:${beat}` // bar : beat }) ``` ### Editable Drum Lanes Every drum-lane cell is clickable. A click cycles that step's value rest → normal → accent → rest and immediately calls `setPattern()` on the underlying `BeatTrack` -- there's no separate "commit" step, so edits are audible on the next pass through the loop: ```typescript // Cycle a step's velocity: rest -> normal -> accent -> rest. function cycleStep(v: number): number { if (v <= 0) return NORMAL // NORMAL = 0.7 if (v < ACCENT) return ACCENT // ACCENT = 1 return 0 } drumSteps[key][index] = cycleStep(drumSteps[key][index]) drumTrackInstance(key)?.setPattern(drumSteps[key]) ``` ### Preset Switching Switching presets updates BPM, swing, and all three drum patterns via `setPattern()`, then calls `seq.clear()` followed by re-registration for the bass and lead sequences. All of it is safe during live playback -- changes take effect on the next loop iteration, so a preset swap never clicks or glitches mid-bar. ## Demo Controls | Control | What It Does | |---------|-------------| | Play / Pause / Stop | Controls transport clock | | BPM slider | Changes tempo immediately during playback | | Swing knob | Sets `transport.swing` (0-1) live -- try it on the Shuffle preset | | M button | Mutes / unmutes individual track | | S button | Solos track (multiple solos stack) | | Preset buttons | Switches all 5 track patterns, BPM, and swing simultaneously | | Step grid | Click a drum cell to cycle rest → normal → accent; shows the current playhead position | ## Further Reading * [Transport Guide](/guide/transport) -- full Transport clock API, tick events, and time signature options * [Sequence Guide](/guide/sequence) -- musical time notation, bar:beat:tick addressing, and note scheduling * [Drum Machine](/examples/drum-machine) -- simpler BeatTrack-only pattern sequencer --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/type-aliases/AudioEventSource.md --- [EZ Web Audio](../index.md) / AudioEventSource # Type Alias: AudioEventSource > **AudioEventSource** = `BaseSound` | [`BeatTrack`](../classes/BeatTrack.md) | [`GrainPlayer`](../classes/GrainPlayer.md) | [`LayeredSound`](../classes/LayeredSound.md) | [`PolySynth`](../classes/PolySynth.md) | [`Sequence`](../classes/Sequence.md) | [`Transport`](../classes/Transport.md) Defined in: [packages/core/src/events/event-types.ts:31](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L31) Union of all classes that emit events in ez-web-audio. Event detail `source` fields are typed as `AudioEventSource` instead of `unknown`. Use instanceof checks to narrow to a specific class: ## Example ```typescript sound.on('play', (e) => { if (e.detail.source instanceof Sound) { console.log('played by a Sound') } }) ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/AudioInput.md' --- [EZ Web Audio](../index.md) / AudioInput # Type Alias: AudioInput > **AudioInput** = `string` | `ArrayBuffer` | `Blob` | `File` Defined in: [packages/core/src/index.ts:358](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/index.ts#L358) Union type for audio input sources accepted by factory functions. * `string`: URL to an audio file (fetched via network) * `ArrayBuffer`: Raw decoded audio data (decoded directly) * `Blob`: Binary audio data (e.g., from File API or fetch response) * `File`: File selected via `` or drag-and-drop ## Example ```typescript import type { AudioInput } from 'ez-web-audio' async function loadAudio(input: AudioInput) { return createSound(input) } ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/ControlType.md' --- [EZ Web Audio](../index.md) / ControlType # Type Alias: ControlType > **ControlType** = `ControlTypeMap`\[keyof `ControlTypeMap`] Defined in: [packages/core/src/controllers/base-param-controller.ts:17](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L17) Union of all control type names. --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/DistortionType.md' --- [EZ Web Audio](../index.md) / DistortionType # Type Alias: DistortionType > **DistortionType** = `"soft"` | `"hard"` | `"fuzz"` | `"overdrive"` | `"custom"` Defined in: [packages/core/src/effects/distortion-effect.ts:9](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/distortion-effect.ts#L9) Available distortion curve types. --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/EventDetailFor.md' --- [EZ Web Audio](../index.md) / EventDetailFor # Type Alias: EventDetailFor\ > **EventDetailFor**<`T`> = [`SoundEventMap`](SoundEventMap.md)\[`T`] *extends* `CustomEvent`\ ? `D` : `never` Defined in: [packages/core/src/events/event-types.ts:174](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L174) Helper type to extract the detail type from an event name. ## Type Parameters ### T `T` *extends* [`SoundEventType`](SoundEventType.md) ## Example ```typescript type PlayDetail = EventDetailFor<'play'> // PlayEventDetail ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/FilterType.md' --- [EZ Web Audio](../index.md) / FilterType # Type Alias: FilterType > **FilterType** = `"lowpass"` | `"highpass"` | `"bandpass"` | `"lowshelf"` | `"highshelf"` | `"peaking"` | `"notch"` | `"allpass"` Defined in: [packages/core/src/effects/filter-effect.ts:8](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/effects/filter-effect.ts#L8) All available BiquadFilter types. --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/type-aliases/HowlerSpriteTuple.md --- [EZ Web Audio](../index.md) / HowlerSpriteTuple # Type Alias: HowlerSpriteTuple > **HowlerSpriteTuple** = \[`number`, `number`] | \[`number`, `number`, `boolean`] Defined in: [packages/core/src/sprite.ts:25](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L25) A Howler-style sprite tuple: `[offset_ms, duration_ms]` or `[offset_ms, duration_ms, loop]`. ## Example ```typescript const laser: HowlerSpriteTuple = [0, 300] // 0-300ms, no loop const bgm: HowlerSpriteTuple = [4000, 500, true] // 4000-4500ms, loop ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/LFOWaveform.md' --- [EZ Web Audio](../index.md) / LFOWaveform # Type Alias: LFOWaveform > **LFOWaveform** = `"sine"` | `"square"` | `"sawtooth"` | `"triangle"` | `"sample-and-hold"` Defined in: [packages/core/src/lfo.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/lfo.ts#L14) Waveform types supported by the LFO. Standard oscillator types plus 'sample-and-hold' for stepped random modulation. --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/type-aliases/MusicalTimeNotation.md --- [EZ Web Audio](../index.md) / MusicalTimeNotation # Type Alias: MusicalTimeNotation > **MusicalTimeNotation** = `string` | `number` Defined in: [packages/core/src/utils/musical-time.ts:15](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/musical-time.ts#L15) Musical time notation type — accepts string notation or numeric beat values. String notation supports: * Note values: `'1n'` (whole), `'2n'` (half), `'4n'` (quarter), `'8n'`, `'16n'`, `'32n'` * Triplets: `'4t'`, `'8t'`, `'16t'` (2/3 of the base note value) * Dotted notes: `'4n.'`, `'8n.'` (1.5x the base note value) * Measures: `'1m'`, `'2m'`, `'4m'` (beatsPerBar \* count) * Bar:beat:tick: `'2:1:0'` (positional, 1-indexed bar/beat, 0-indexed tick) Numeric values are treated as beat counts and passed through unchanged. --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/type-aliases/OscillatorControlType.md --- [EZ Web Audio](../index.md) / OscillatorControlType # Type Alias: OscillatorControlType > **OscillatorControlType** = [`ControlType`](ControlType.md) Defined in: [packages/core/src/controllers/base-param-controller.ts:37](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L37) Control types available on Oscillator (full set including frequency). Oscillator supports all built-in control types including 'frequency' for real-time pitch control. Equivalent to [ControlType](ControlType.md). --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/RatioType.md' --- [EZ Web Audio](../index.md) / RatioType # Type Alias: RatioType > **RatioType** = `"ratio"` | `"inverseRatio"` | `"percent"` Defined in: [packages/core/src/controllers/base-param-controller.ts:38](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L38) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/SeekType.md' --- [EZ Web Audio](../index.md) / SeekType # Type Alias: SeekType > **SeekType** = [`RatioType`](RatioType.md) | `"seconds"` Defined in: [packages/core/src/controllers/base-param-controller.ts:40](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L40) --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/type-aliases/SequenceCallback.md --- [EZ Web Audio](../index.md) / SequenceCallback # Type Alias: SequenceCallback() > **SequenceCallback** = (`time`, `position`) => `void` Defined in: [packages/core/src/sequence.ts:14](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sequence.ts#L14) Callback function invoked when a scheduled event fires. ## Parameters ### time `number` Precise AudioContext time for scheduling audio operations ### position [`TransportPosition`](../interfaces/TransportPosition.md) Transport position at the moment the event fires ## Returns `void` --- --- url: >- https://sethbrasile.github.io/ez-web-audio/api/type-aliases/SoundControlType.md --- [EZ Web Audio](../index.md) / SoundControlType # Type Alias: SoundControlType > **SoundControlType** = `Exclude`<[`ControlType`](ControlType.md), `"frequency"`> Defined in: [packages/core/src/controllers/base-param-controller.ts:29](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/controllers/base-param-controller.ts#L29) Control types available on Sound and Track. Derived from ControlTypeMap (excluding 'frequency', since Sound/Track instances play pre-recorded audio buffers which do not have a frequency AudioParam) rather than hardcoded, so that module augmentation of `ControlTypeMap` (see the "Extending ControlType" docs) actually extends this type too — not just [ControlType](ControlType.md) / [OscillatorControlType](OscillatorControlType.md). Use [OscillatorControlType](OscillatorControlType.md) for oscillator-specific parameters. --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/SoundEventType.md' --- [EZ Web Audio](../index.md) / SoundEventType # Type Alias: SoundEventType > **SoundEventType** = keyof [`SoundEventMap`](SoundEventMap.md) Defined in: [packages/core/src/events/event-types.ts:164](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/events/event-types.ts#L164) Union of all valid event names for sound instances. Use this for type-safe event name parameters: ## Example ```typescript function on(event: SoundEventType, handler: Function) { ... } ``` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/SpriteManifest.md' --- [EZ Web Audio](../index.md) / SpriteManifest # Type Alias: SpriteManifest > **SpriteManifest** = [`AudiospriteManifest`](../interfaces/AudiospriteManifest.md) | [`HowlerSpriteManifest`](../interfaces/HowlerSpriteManifest.md) Defined in: [packages/core/src/sprite.ts:79](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/sprite.ts#L79) Union type accepting either Howler.js or audiosprite manifest formats. Format detection is automatic based on top-level key presence: * `sprite` key → Howler format (ms-based tuples) * `spritemap` key → audiosprite format (seconds-based objects) --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/type-aliases/StealStrategy.md' --- [EZ Web Audio](../index.md) / StealStrategy # Type Alias: StealStrategy > **StealStrategy** = `"lru"` | `"oldest-active"` | `"quietest"` Defined in: [packages/core/src/poly-synth.ts:20](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/poly-synth.ts#L20) Voice stealing strategy when the voice pool is full. * `'lru'`: Steal oldest-released voice first, then oldest-active if no released voices (default) * `'oldest-active'`: Always steal the voice that started playing earliest * `'quietest'`: Steal the voice with the lowest current gain --- --- url: 'https://sethbrasile.github.io/ez-web-audio/guide/utilities.md' description: >- Use EZ Web Audio utility functions for batch sound loading, synchronized playback, equal-power crossfade, preloading, cache management, debug logging, and interaction helpers. --- # Utility Functions EZ Web Audio ships with a set of utility functions for common audio programming tasks — loading multiple sounds, synchronized playback, crossfading, preloading, debug logging, and binding UI interactions. ## Collection Control Control multiple sounds at once with a single call: ```typescript import { pauseAll, playAll, stopAll } from 'ez-web-audio' const sounds = [sound1, sound2, sound3] playAll(sounds) // Play all sounds pauseAll(sounds) // Pause all tracks (no effect on non-track sounds) stopAll(sounds) // Stop all sounds ``` ## Global Volume / Mute Set an app-wide volume or mute switch without touching every sound individually. Both are sugar over `setMasterDestination()`: the first call lazily creates a managed `GainNode` and installs it as the master destination, so instances created afterward route through it automatically: ```typescript import { createSound, muteAll, setGlobalVolume } from 'ez-web-audio' setGlobalVolume(0.5) // app-wide volume knob, set once at startup const music = await createSound('theme.mp3') music.play() // plays at half the master volume // Mute button let isMuted = false document.getElementById('mute-btn')!.addEventListener('click', () => { isMuted = !isMuted muteAll(isMuted) // unmuting restores the last setGlobalVolume() value }) ``` Same caveat as `setMasterDestination()`: only instances created **after** the first `setGlobalVolume()`/`muteAll()` call pick up the managed bus. Call it early (app startup) if you want it to cover everything, or move an existing instance with `instance.setDestination(...)`. `setGlobalVolume()` throws a `ValidationError` for negative values and warns on the console above 1 — the same rule as `sound.changeGainTo()`. ## Synchronized Playback Play multiple sounds at the exact same AudioContext timestamp. Unlike calling `play()` on each sound sequentially (which introduces tiny timing gaps), `playTogether` schedules all sources to a shared start time slightly in the future: ```typescript import { createOscillator, createSound, playTogether } from 'ez-web-audio' const bass = await createSound('/audio/bass.mp3') const melody = await createSound('/audio/melody.mp3') const chord = await createOscillator({ frequency: 440, type: 'triangle' }) // All three start at precisely the same AudioContext time await playTogether([bass, melody, chord]) ``` Use cases: building chords from oscillators, layering SFX components, and synchronizing stems in a multi-track arrangement. Works with any mix of `Sound`, `Track`, and `Oscillator` instances. ## Batch Loading Load multiple sounds at once with optional progress tracking: ```typescript import { createSounds } from 'ez-web-audio' const sounds = await createSounds( ['click.mp3', 'whoosh.mp3', 'ding.mp3'], (loaded, total) => console.log(`${loaded}/${total}`) ) ``` For tracks (music with pause/resume/seek), use `createTracks()`: ```typescript import { createTracks } from 'ez-web-audio' const tracks = await createTracks( ['intro.mp3', 'verse.mp3', 'chorus.mp3'], (loaded, total, url) => console.log(`${loaded}/${total}: ${url}`) ) ``` Both callbacks fire after each item finishes loading, making it easy to drive a loading progress bar. ## Crossfade Smoothly transition between two tracks using an equal-power curve. Equal-power crossfading keeps the total perceived loudness constant throughout the transition — there is no volume dip at the midpoint that a simple linear cross-fade would produce. ```typescript import { createTrack, crossfade } from 'ez-web-audio' const intro = await createTrack('/music/intro.mp3') const main = await createTrack('/music/main.mp3') intro.play() // Crossfade from intro to main over 3 seconds // intro fades out; main fades in — overlap uses equal-power curve await crossfade(intro, main, 3) // intro is now stopped, main is playing at full volume ``` `crossfade` returns a `Promise` that resolves when the transition is complete and the source track has been stopped. If the destination track is already playing, the fade starts from its current position; otherwise it starts playing at gain 0 and fades in. Typical use cases: DJ transitions, ambient scene changes, and background music swaps. ## Preloading Audio Cache audio files before they are needed so playback starts instantly: ```typescript import { createSound, isPreloaded, preload } from 'ez-web-audio' // Preload during a loading screen await preload(['/audio/level1.mp3', '/audio/level2.mp3', '/audio/boss.mp3']) // Subsequent createSound/createTrack calls hit the cache — no additional fetch const level1 = await createSound('/audio/level1.mp3') // Check if a URL is already cached console.log(isPreloaded('/audio/level1.mp3')) // true ``` ## Cache Management Clear the internal preload cache when you no longer need cached audio — useful in long-running apps after level transitions: ```typescript import { clearPreloadCache, preload } from 'ez-web-audio' await preload(['/audio/level1.mp3', '/audio/level2.mp3']) // Level transition: free memory from level 1 assets clearPreloadCache('/audio/level1.mp3') // Clear a single URL // Or clear everything at once clearPreloadCache() ``` `clearPreloadCache()` without arguments clears the entire cache. With a URL argument, it removes only that entry. After clearing, the next `createSound()` or `preload()` call for that URL fetches it fresh. ## Noise Generation Generate procedural noise for ambience, testing, or synthesis: ```typescript import { createNoise } from 'ez-web-audio' const white = await createNoise('white') // Equal energy — hiss/static const pink = await createNoise('pink') // 1/f spectrum — natural ambience const brown = await createNoise('brown') // Random walk — deep rumble ``` White noise has a flat spectrum (equal energy at all frequencies). Pink noise rolls off 3 dB/octave, sounding more balanced to human ears. Brown noise rolls off 6 dB/octave for a deep, rumbling character. All return a 1-second `Sound` instance — set `.loop = true` for continuous playback, and add effects and control gain like any other sound. ## Debug Mode Enable debug logging to trace audio events and connections during development: ```typescript import { setDebugHandler, setDebugMode } from 'ez-web-audio' // Enable debug mode — logs all events to the console setDebugMode(true) // Example console output: // [ez-audio:event] [0.000] kick: play // [ez-audio:connection] [0.021] kick: Effect added at position 0 // [ez-audio:warning] [1.420] bgMusic: AudioContext suspended ``` Each message is a `DebugMessage` object with: | Field | Type | Description | |-------|------|-------------| | `type` | `'event' \| 'connection' \| 'warning'` | Category of message | | `source` | string | Sound name or identifier | | `message` | string | Human-readable description | | `timestamp` | number | `audioContext.currentTime` | Use `setDebugHandler` to capture messages in your own logging system: ```typescript import { setDebugHandler, setDebugMode } from 'ez-web-audio' // Capture warning messages only setDebugHandler((msg) => { if (msg.type === 'warning') { myLogger.warn(`[${msg.source}] ${msg.message}`) } }) // Restore default console.log handler setDebugHandler(null) ``` ## Interaction Helpers Bind touch and mouse events to a sound for piano-style interactive controls. ::: tip Plain DOM conveniences, not framework hooks `useInteractionMethods` and `preventEventDefaults` live in the root package namespace and use the `use*` prefix, which can read like a React/Vue hook. They're not — both are framework-agnostic `addEventListener`/`removeEventListener` wrappers around plain DOM elements, safe to call from vanilla JS, React, Vue, or anywhere else. They stay in the root namespace for now (a future major version may move them under a `/dom` subpath for clarity). ::: `useInteractionMethods(element, player)` attaches `touchstart`/`mousedown` → `play()` and `touchend`/`mouseup`/`mouseleave` → `stop()`. It returns a cleanup function to remove all listeners: ```typescript import { createOscillator, useInteractionMethods } from 'ez-web-audio' const synth = await createOscillator({ frequency: 440 }) const key = document.getElementById('piano-key')! const cleanup = await useInteractionMethods(key, synth) // Touching or clicking the element now plays/stops the synth // Later — clean up on component unmount cleanup() ``` `preventEventDefaults(element)` prevents text selection, context menus, and drag-and-drop on interactive audio elements. It also returns a cleanup function: ```typescript import { createOscillator, preventEventDefaults, useInteractionMethods } from 'ez-web-audio' const synth = await createOscillator({ frequency: 261.63 }) // C4 const key = document.getElementById('key-c4')! // Prevent browser defaults (selection, context menu, drag) before binding audio const removePrevention = preventEventDefaults(key) const cleanup = await useInteractionMethods(key, synth) // Clean up both when done removePrevention() cleanup() ``` Both helpers work with any object that has `play()` and `stop()` methods — not just oscillators. ## Resource Cleanup When you're done with a sound, call `dispose()` to disconnect all audio nodes and free resources: ```typescript sound.dispose() // sound.play() will now throw — the instance is no longer usable ``` `dispose()` is idempotent — calling it multiple times has no additional effect. This is especially important in single-page applications where audio instances are created and destroyed as users navigate between views. ### Context-Free Analyzer `createAnalyzer()` works without passing an AudioContext — it resolves the shared context automatically: ```typescript const analyzer = await createAnalyzer({ fftSize: 2048 }) ``` This matches the pattern used by `createFilterEffect()` and `createGainEffect()`, keeping your code consistent without needing to manage context references directly. ## Next Steps * [Core Concepts](/guide/concepts) - Sound types, AudioContext lifecycle, audio routing * [Parameter Control](/guide/parameter-control) - Automate gain, frequency, and pan over time * [Interactive Examples](/examples/) - See utilities in action * [API Reference](/api/) - Full method documentation --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/drum-machine-vanilla.md' description: >- Build a drum machine with vanilla TypeScript and DOM events. Demonstrates event-based UI sync pattern for framework-free Web Audio applications. --- # Drum Machine: Vanilla TS Event Pattern This page demonstrates the **event-based approach** to drum machine UI synchronization. BeatTrack emits `beat` events at play time using AudioContext-aware timing, and we update the DOM directly through event listeners. No reactive framework needed for the playhead. Vanilla TypeScript drum machine using event-based DOM updates. Step sequencer grid with kick/snare/hi-hat, BPM slider, and visual playhead sync via beat events. ## Key Code The event listener that drives the playhead: ```typescript const kick = await createBeatTrack([...urls], { numBeats: 16 }) // No wrapWith needed — events handle sync kick.on('beat', (e) => { const { beatIndex, active } = e.detail // Clear previous playhead document.querySelectorAll('.beat-cell.current').forEach( el => el.classList.remove('current') ) // Highlight current step document.querySelectorAll(`.beat-cell[data-beat="${beatIndex}"]`).forEach( el => el.classList.add('current') ) }) ``` Key aspects: * **No reactive wrapper** — beats are plain objects * **Direct DOM manipulation** — querySelector + classList * **Event-driven timing** — visual updates triggered by audio events * **Scoped to component** — use a ref to scope queries and avoid global DOM pollution ## How It Works Under the Hood The event-based pattern works in three coordinated phases: 1. **Lookahead Scheduling (100ms ahead):** BeatTrack's internal scheduler runs every 25ms, checking which beats fall within the next 100ms window. For each upcoming beat, it schedules the audio playback on the Web Audio API thread using `audioContext.currentTime`. 2. **Event Emission (at play time):** When a beat is scheduled, BeatTrack also schedules a beat event to fire at the exact moment the audio plays. This event fires using `audioContextAwareTimeout`, which polls `audioContext.currentTime` via `requestAnimationFrame` for frame-accurate timing. 3. **DOM Updates (same frame):** The event handler receives the beat index and updates DOM classes directly. Since the event fires on the same RAF frame as the timing check, the visual update appears synchronized with the audio. This architecture separates concerns: Web Audio API handles precise audio timing, RAF handles frame-accurate visual timing, and events bridge the two. ## AudioContext-Aware Timing Why doesn't this drift over time? **The Problem with Standard Timers:** * `setTimeout(fn, 1000)` uses the system clock (wall time) * System clocks can drift, skip, or jump (sleep/wake, NTP adjustments) * After 2 minutes of playback, audio and visuals can be 100ms+ out of sync **The AudioContext Solution:** * `audioContext.currentTime` is hardware-driven and monotonic * It never drifts, skips, or goes backward * It's the same clock driving audio playback **How audioContextAwareTimeout Works:** ```typescript // Simplified implementation function audioContextAwareTimeout(audioContext) { let tasks = [] function scheduler() { const now = audioContext.currentTime * 1000 // Execute due tasks tasks.forEach((task) => { if (task.due <= now) task.fn() }) // Remove completed tasks tasks = tasks.filter(task => task.due > now) // Continue if tasks pending if (tasks.length > 0) { requestAnimationFrame(scheduler) } } return { setTimeout(fn, delayMillis) { tasks.push({ due: now() + delayMillis, fn }) if (tasks.length === 1) { requestAnimationFrame(scheduler) } } } } ``` The key insight: by checking `audioContext.currentTime` on every animation frame, visual updates are synchronized to the same clock that drives audio playback. The result: audio and visuals stay perfectly locked even over extended playback. ## Mute & Solo Mute and solo controls work by toggling beat `active` states: ```typescript function toggleMute(track) { if (track.muted) { // Save current pattern track.savedStates = track.beats.map(b => b.active) // Deactivate all beats track.beats.forEach(b => b.active = false) } else { // Restore saved pattern track.savedStates.forEach((active, i) => { track.beats[i].active = active }) } } ``` Solo works similarly: when any track is soloed, all non-solo tracks are muted. When no tracks are soloed, all tracks restore their saved states. ## Cleanup Event listeners must be cleaned up manually to prevent memory leaks: ```typescript // Store reference for cleanup function beatHandler(e) { const { beatIndex } = e.detail // Update DOM... } kick.on('beat', beatHandler) // On teardown (component unmount, page navigation, etc.): kick.off('beat', beatHandler) kick.stop() ``` This is the tradeoff of the event-based approach: you manage the lifecycle explicitly. Reactive frameworks handle this automatically through their reactivity systems. ## When to Use This Pattern **Best for:** * **React** — combine with refs or state + useEffect for visual updates * **Vanilla JavaScript / TypeScript** — no framework overhead * **Svelte, Angular, or any framework** — events are universal * **Explicit control** — you want precise control over timing and DOM updates * **No reactive proxies** — when reactive wrappers aren't available or add unwanted overhead **Use reactive pattern instead when:** * You're using Vue 3 with Composition API * You're using Solid.js or another fine-grained reactive framework * You want automatic cleanup and less boilerplate ## Comparison with Reactive Pattern | Aspect | Reactive (Vue) | Event-Based (Vanilla) | |--------|----------------|----------------------| | Visual sync mechanism | `beat.currentTimeIsPlaying` auto-toggles | `track.on('beat', ...)` fires at play time | | DOM update | Vue template re-render | Direct class manipulation | | Setup | `wrapWith: reactive` | Event listener | | Cleanup | Automatic (Vue reactivity) | Manual `.off()` required | | Timing precision | Same (both use audioContextAwareTimeout) | Same (both use audioContextAwareTimeout) | | Boilerplate | Less (framework handles it) | More (manual event management) | | Best for | Vue, Solid.js | React, vanilla JS, any framework | Both patterns use the same underlying timing mechanism (`audioContextAwareTimeout` + `audioContext.currentTime`), so they have identical timing precision. The choice is about API style and framework compatibility. ## See Also * [Drum Machine: Vue Reactive Pattern](/examples/drum-machine-vue) — for Vue, Solid.js, or frameworks with reactive proxies * [Drum Machine Overview](/examples/drum-machine) — API reference and basic usage --- --- url: 'https://sethbrasile.github.io/ez-web-audio/api/variables/frequencyMap.md' --- [EZ Web Audio](../index.md) / frequencyMap # Variable: frequencyMap > **frequencyMap**: `object` Defined in: [packages/core/src/utils/frequency-map.ts:6](https://github.com/sethbrasile/ez-web-audio/blob/71b53000b9c0a3721ffd8d8aae172c45a956085f/packages/core/src/utils/frequency-map.ts#L6) ## Type Declaration ### A#0 > **A#0**: `number` = `29.14` ### A#1 > **A#1**: `number` = `58.27` ### A#2 > **A#2**: `number` = `116.54` ### A#3 > **A#3**: `number` = `233.08` ### A#4 > **A#4**: `number` = `466.16` ### A#5 > **A#5**: `number` = `932.33` ### A#6 > **A#6**: `number` = `1864.66` ### A#7 > **A#7**: `number` = `3729.31` ### A0 > **A0**: `number` = `27.5` ### A1 > **A1**: `number` = `55` ### A2 > **A2**: `number` = `110` ### A3 > **A3**: `number` = `220` ### A4 > **A4**: `number` = `440` ### A5 > **A5**: `number` = `880` ### A6 > **A6**: `number` = `1760` ### A7 > **A7**: `number` = `3520` ### Ab0 > **Ab0**: `number` = `25.96` ### Ab1 > **Ab1**: `number` = `51.91` ### Ab2 > **Ab2**: `number` = `103.83` ### Ab3 > **Ab3**: `number` = `207.65` ### Ab4 > **Ab4**: `number` = `415.3` ### Ab5 > **Ab5**: `number` = `830.61` ### Ab6 > **Ab6**: `number` = `1661.22` ### Ab7 > **Ab7**: `number` = `3322.44` ### B0 > **B0**: `number` = `30.87` ### B1 > **B1**: `number` = `61.74` ### B2 > **B2**: `number` = `123.47` ### B3 > **B3**: `number` = `246.94` ### B4 > **B4**: `number` = `493.88` ### B5 > **B5**: `number` = `987.77` ### B6 > **B6**: `number` = `1975.53` ### B7 > **B7**: `number` = `3951.07` ### Bb0 > **Bb0**: `number` = `29.14` ### Bb1 > **Bb1**: `number` = `58.27` ### Bb2 > **Bb2**: `number` = `116.54` ### Bb3 > **Bb3**: `number` = `233.08` ### Bb4 > **Bb4**: `number` = `466.16` ### Bb5 > **Bb5**: `number` = `932.33` ### Bb6 > **Bb6**: `number` = `1864.66` ### Bb7 > **Bb7**: `number` = `3729.31` ### C#0 > **C#0**: `number` = `17.32` ### C#1 > **C#1**: `number` = `34.65` ### C#2 > **C#2**: `number` = `69.3` ### C#3 > **C#3**: `number` = `138.59` ### C#4 > **C#4**: `number` = `277.18` ### C#5 > **C#5**: `number` = `554.37` ### C#6 > **C#6**: `number` = `1108.73` ### C#7 > **C#7**: `number` = `2217.46` ### C#8 > **C#8**: `number` = `4434.92` ### C0 > **C0**: `number` = `16.35` ### C1 > **C1**: `number` = `32.7` ### C2 > **C2**: `number` = `65.41` ### C3 > **C3**: `number` = `130.81` ### C4 > **C4**: `number` = `261.63` ### C5 > **C5**: `number` = `523.25` ### C6 > **C6**: `number` = `1046.5` ### C7 > **C7**: `number` = `2093` ### C8 > **C8**: `number` = `4186.01` ### D#0 > **D#0**: `number` = `19.45` ### D#1 > **D#1**: `number` = `38.89` ### D#2 > **D#2**: `number` = `77.78` ### D#3 > **D#3**: `number` = `155.56` ### D#4 > **D#4**: `number` = `311.13` ### D#5 > **D#5**: `number` = `622.25` ### D#6 > **D#6**: `number` = `1244.51` ### D#7 > **D#7**: `number` = `2489.02` ### D#8 > **D#8**: `number` = `4978.03` ### D0 > **D0**: `number` = `18.35` ### D1 > **D1**: `number` = `36.71` ### D2 > **D2**: `number` = `73.42` ### D3 > **D3**: `number` = `146.83` ### D4 > **D4**: `number` = `293.66` ### D5 > **D5**: `number` = `587.33` ### D6 > **D6**: `number` = `1174.66` ### D7 > **D7**: `number` = `2349.32` ### D8 > **D8**: `number` = `4698.64` ### Db0 > **Db0**: `number` = `17.32` ### Db1 > **Db1**: `number` = `34.65` ### Db2 > **Db2**: `number` = `69.3` ### Db3 > **Db3**: `number` = `138.59` ### Db4 > **Db4**: `number` = `277.18` ### Db5 > **Db5**: `number` = `554.37` ### Db6 > **Db6**: `number` = `1108.73` ### Db7 > **Db7**: `number` = `2217.46` ### Db8 > **Db8**: `number` = `4434.92` ### E0 > **E0**: `number` = `20.6` ### E1 > **E1**: `number` = `41.2` ### E2 > **E2**: `number` = `82.41` ### E3 > **E3**: `number` = `164.81` ### E4 > **E4**: `number` = `329.63` ### E5 > **E5**: `number` = `659.26` ### E6 > **E6**: `number` = `1318.51` ### E7 > **E7**: `number` = `2637.02` ### Eb0 > **Eb0**: `number` = `19.45` ### Eb1 > **Eb1**: `number` = `38.89` ### Eb2 > **Eb2**: `number` = `77.78` ### Eb3 > **Eb3**: `number` = `155.56` ### Eb4 > **Eb4**: `number` = `311.13` ### Eb5 > **Eb5**: `number` = `622.25` ### Eb6 > **Eb6**: `number` = `1244.51` ### Eb7 > **Eb7**: `number` = `2489.02` ### Eb8 > **Eb8**: `number` = `4978.03` ### F#0 > **F#0**: `number` = `23.12` ### F#1 > **F#1**: `number` = `46.25` ### F#2 > **F#2**: `number` = `92.5` ### F#3 > **F#3**: `number` = `185` ### F#4 > **F#4**: `number` = `369.99` ### F#5 > **F#5**: `number` = `739.99` ### F#6 > **F#6**: `number` = `1479.98` ### F#7 > **F#7**: `number` = `2959.96` ### F0 > **F0**: `number` = `21.83` ### F1 > **F1**: `number` = `43.65` ### F2 > **F2**: `number` = `87.31` ### F3 > **F3**: `number` = `174.61` ### F4 > **F4**: `number` = `349.23` ### F5 > **F5**: `number` = `698.46` ### F6 > **F6**: `number` = `1396.91` ### F7 > **F7**: `number` = `2793.83` ### G#0 > **G#0**: `number` = `25.96` ### G#1 > **G#1**: `number` = `51.91` ### G#2 > **G#2**: `number` = `103.83` ### G#3 > **G#3**: `number` = `207.65` ### G#4 > **G#4**: `number` = `415.3` ### G#5 > **G#5**: `number` = `830.61` ### G#6 > **G#6**: `number` = `1661.22` ### G#7 > **G#7**: `number` = `3322.44` ### G0 > **G0**: `number` = `24.5` ### G1 > **G1**: `number` = `49` ### G2 > **G2**: `number` = `98` ### G3 > **G3**: `number` = `196` ### G4 > **G4**: `number` = `392` ### G5 > **G5**: `number` = `783.99` ### G6 > **G6**: `number` = `1567.98` ### G7 > **G7**: `number` = `3135.96` ### Gb0 > **Gb0**: `number` = `23.12` ### Gb1 > **Gb1**: `number` = `46.25` ### Gb2 > **Gb2**: `number` = `92.5` ### Gb3 > **Gb3**: `number` = `185` ### Gb4 > **Gb4**: `number` = `369.99` ### Gb5 > **Gb5**: `number` = `739.99` ### Gb6 > **Gb6**: `number` = `1479.98` ### Gb7 > **Gb7**: `number` = `2959.96` --- --- url: 'https://sethbrasile.github.io/ez-web-audio/examples/drum-machine-vue.md' description: >- Build a reactive drum machine using Vue.js and EZ Web Audio. Demonstrates automatic UI sync with reactive beat properties — no manual event listeners needed. --- # Drum Machine: Vue Reactive Pattern This page demonstrates using Vue's `reactive()` with BeatTrack's `wrapWith` option. Beat properties auto-toggle and trigger re-renders — **no event listeners needed for visual sync**. Vue reactive drum machine demonstrating automatic UI sync via reactive beat properties. Includes mute/solo controls and BPM adjustment. ## How to Use * **Click cells** to toggle beats on/off * **Press Play** to start the pattern loop * **Mute (M)** silences a track by deactivating all its beats ([code below](#mute--solo-implementation)) * **Solo (S)** mutes all other tracks ([code below](#mute--solo-implementation)) * **Adjust BPM** to change tempo in real-time * **Step counter** shows current playhead position ## How It Works The reactive property pattern eliminates the need for event listeners: 1. `wrapWith: (beat) => reactive(beat)` wraps each Beat in a Vue reactive proxy 2. `beat.currentTimeIsPlaying` auto-toggles true/false on the scheduler's timeline 3. Vue detects the property change and re-renders the bound CSS class 4. **No `.on('beat', ...)` event listener needed** — the Beat IS the state ## Key Code ### Setup with wrapWith ```typescript import { createBeatTrack } from 'ez-web-audio' import { reactive } from 'vue' const kick = await createBeatTrack([ '/audio/kick1.wav', '/audio/kick2.wav', '/audio/kick3.wav' ], { numBeats: 16, wrapWith: beat => reactive(beat) // ← Makes beat properties reactive }) // Set default pattern ;[0, 4, 8, 12].forEach(i => kick.beats[i].active = true) ``` ### Template Binding ```vue