UNPKG

ez-web-audio

Version:

Making the Web Audio API super EZ since 2024.

154 lines 6.13 kB
import { Sound } from './sound'; import { Oscillator } from './oscillator'; import { LayeredSoundEventMap } from './events/event-types'; /** * Options for creating a LayeredSound. */ export interface LayeredSoundOptions { /** Optional name for identification */ name?: string; /** Layer count threshold at which to warn (default: 8) */ warnLayerCount?: number; } /** * 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. * * @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.setGain(0.5) // Affects all layers * layered.getLayer(2)?.changeGainTo(0.8) // Control individual layer * ``` */ export declare class LayeredSound extends EventTarget { private audioContext; private layers; private failedLayers; name: string; constructor(audioContext: AudioContext, layers: (Sound | Oscillator | null | undefined)[], opts?: LayeredSoundOptions); /** * Get a layer by index for individual control. * * @param index - The layer index (0-based) * @returns The Sound or Oscillator at that index, or undefined if out of bounds */ getLayer(index: number): Sound | Oscillator | undefined; /** * Get the number of valid layers in this LayeredSound. */ get layerCount(): number; /** * Play all layers simultaneously at exactly the same audioContext.currentTime. * This ensures perfect synchronization across all layers. */ play(): Promise<void>; /** * Stop all layers. */ stop(): Promise<void>; /** * Set the gain for all layers. * * @param value - The gain value (0-1 range typical) */ setGain(value: number): void; /** * Set the pan for all layers. * * @param value - The pan value (-1 to 1, where -1 is full left, 1 is full right) */ setPan(value: number): void; /** * Set up tracking for when each layer ends. Emits 'end' event when * the last layer finishes (layers end independently). * * Creates a fresh Set per play() call to support multiple playbacks. */ private setupLayerEndTracking; /** * Add a typed event listener for LayeredSound lifecycle events. * Overloaded to provide type safety for known event types while remaining * compatible with EventTarget. * * @param type - The event type ('play', 'stop', 'end', 'warning') * @param listener - The event handler function * @param options - Standard addEventListener options */ addEventListener<K extends keyof LayeredSoundEventMap>(type: K, listener: (event: LayeredSoundEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void; /** * Remove a typed event listener for LayeredSound lifecycle events. * Overloaded to provide type safety for known event types while remaining * compatible with EventTarget. * * @param type - The event type ('play', 'stop', 'end', 'warning') * @param listener - The event handler function to remove * @param options - Standard removeEventListener options */ removeEventListener<K extends keyof LayeredSoundEventMap>(type: K, listener: (event: LayeredSoundEventMap[K]) => void, options?: boolean | EventListenerOptions): void; removeEventListener(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | EventListenerOptions): void; /** * Emit a typed event with the given detail. * @protected * @param type - The event type to emit * @param detail - The event detail object */ protected emit<K extends keyof LayeredSoundEventMap>(type: K, detail: LayeredSoundEventMap[K]['detail']): void; /** * Subscribe to one or more events. Supports chaining. * * @example * ```typescript * layered.on('play', handlePlay).on('stop', handleStop); * layered.on(['play', 'stop'], handleBoth); * ``` * * @param type - The event type(s) to subscribe to * @param listener - The event handler function * @returns this for chaining */ on<K extends keyof LayeredSoundEventMap>(type: K | K[], listener: (event: LayeredSoundEventMap[K]) => void): this; /** * Subscribe to an event once. Handler is removed after first invocation. * * @example * ```typescript * layered.once('end', () => console.log('All layers finished')); * ``` * * @param type - The event type to subscribe to * @param listener - The event handler function * @returns this for chaining */ once<K extends keyof LayeredSoundEventMap>(type: K, listener: (event: LayeredSoundEventMap[K]) => void): this; /** * Unsubscribe from an event. * * Note: Due to native EventTarget limitations, you must provide the same * listener function reference that was used when subscribing. To remove * listeners, store the function reference when adding it. * * @example * ```typescript * const handler = (e) => console.log(e.detail); * layered.on('play', handler); * // later... * layered.off('play', handler); * ``` * * @param type - The event type to unsubscribe from * @param listener - The event handler function to remove * @returns this for chaining */ off<K extends keyof LayeredSoundEventMap>(type: K, listener: (event: LayeredSoundEventMap[K]) => void): this; } //# sourceMappingURL=layered-sound.d.ts.map