// Native ES module served with the production JavaScript MIME type. export class AudioDirector { constructor(records, getSettings) { this.getSettings = getSettings; this.records = records; this.sounds = new Map(); this.music = null; this.ambience = null; this.unlocked = false; records.forEach((record) => { this.sounds.set(record.id, new window.Howl({ src: record.urls || [record.url], loop: record.type !== "sfx", preload: record.type === "sfx", volume: 0 })); }); document.addEventListener("visibilitychange", () => { if (document.hidden) window.Howler?.mute(true); else if (this.getSettings().sound) window.Howler?.mute(false); }); } unlock() { this.unlocked = true; window.Howler?.ctx?.resume?.(); this.sync(); } sync() { const settings = this.getSettings(); window.Howler.volume(settings.masterVolume); window.Howler.mute(!settings.sound); if (this.music) this.sounds.get(this.music)?.volume(settings.musicVolume); if (this.ambience) this.sounds.get(this.ambience)?.volume(settings.ambienceVolume * 0.35); } playLocation(music, ambience) { if (!this.unlocked) return; this.crossfade("music", music); this.crossfade("ambience", ambience); } crossfade(channel, nextId) { const currentId = this[channel]; if (currentId === nextId) return; const settings = this.getSettings(); const target = channel === "music" ? settings.musicVolume : settings.ambienceVolume * 0.35; if (currentId && this.sounds.has(currentId)) { const old = this.sounds.get(currentId); old.fade(old.volume(), 0, 500); window.setTimeout(() => old.stop(), 520); } this[channel] = nextId; const next = this.sounds.get(nextId); if (next) { next.volume(0); if (!next.playing()) next.play(); next.fade(0, target, 700); } } sfx(id) { if (!this.unlocked || !this.getSettings().sound) return; const sound = this.sounds.get(id); if (sound) { sound.volume(this.getSettings().sfxVolume); sound.play(); } } duck(active) { if (!this.music) return; const sound = this.sounds.get(this.music); const volume = this.getSettings().musicVolume * (active ? 0.45 : 1); sound?.fade(sound.volume(), volume, 250); } }