import type { AudioChannel, Vec2 } from '../core/types';
import { EventBus } from '../core/EventBus';
export interface SoundOptions {
    volume?: number;
    loop?: boolean;
    channel?: AudioChannel;
    pitch?: number;
    pan?: number;
    position?: Vec2;
    maxDistance?: number;
}
export interface MusicOptions {
    volume?: number;
    loop?: boolean;
    fadeIn?: number;
}
export declare class AudioManager {
    readonly events: EventBus;
    private ctx;
    private masterGain;
    private channelGains;
    private bufferCache;
    private activeMusic;
    private activeSounds;
    private pool;
    private _listenerPos;
    private _muted;
    private volumes;
    /** Initialize audio context (must be called after user gesture). */
    init(): void;
    /** Ensure context is running (after autoplay policy). */
    resume(): Promise<void>;
    dispose(): void;
    /** Load an audio file and cache its buffer. */
    load(id: string, url: string): Promise<void>;
    /** Check if a sound is loaded. */
    isLoaded(id: string): boolean;
    /** Play a sound effect. Returns an ID to control it. */
    play(id: string, options?: SoundOptions): number;
    /** Stop a specific playing sound. */
    stopSound(soundId: number): void;
    /** Play background music with optional crossfade. */
    playMusic(id: string, options?: MusicOptions): void;
    /** Stop music with fade out. */
    stopMusic(fadeOut?: number): void;
    private fadeOutMusic;
    setVolume(channel: AudioChannel, volume: number): void;
    getVolume(channel: AudioChannel): number;
    get muted(): boolean;
    set muted(value: boolean);
    setListenerPosition(pos: Vec2): void;
    /** Stop all sounds and music, properly disconnecting audio nodes. */
    stopAll(): void;
    get activeSoundCount(): number;
}
