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