ez-web-audio
Version:
Making the Web Audio API super EZ since 2024.
154 lines • 6.13 kB
TypeScript
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