asciitorium
Version:
an ASCII CLUI framework
75 lines (74 loc) • 2.57 kB
JavaScript
import { isWebEnvironment } from './environment.js';
export class SoundManager {
static setEnabled(enabled) {
this.enabled = enabled;
}
static isEnabled() {
return this.enabled;
}
static async playSound(soundPath, loop = false) {
// Only play sounds in web environment
if (!isWebEnvironment()) {
return;
}
if (!this.enabled) {
return;
}
try {
// Check cache first
let audio = this.audioCache.get(soundPath);
if (!audio) {
// Create new audio element
audio = new Audio(`art/sounds/${soundPath}`);
this.audioCache.set(soundPath, audio);
}
// Clone the audio element to allow overlapping sounds
const audioClone = audio.cloneNode();
audioClone.loop = loop;
// Track playing audio for fade operations
if (loop) {
this.playingAudio.set(soundPath, audioClone);
// Clean up when audio ends (if it's stopped manually)
audioClone.addEventListener('ended', () => {
this.playingAudio.delete(soundPath);
});
}
await audioClone.play();
}
catch (error) {
console.warn(`Failed to play sound "${soundPath}":`, error);
}
}
static fadeToStop(soundPath, durationMs = 1000) {
// Only works in web environment
if (!isWebEnvironment()) {
return;
}
const audio = this.playingAudio.get(soundPath);
if (!audio) {
return;
}
// Store initial volume
const initialVolume = audio.volume;
const startTime = Date.now();
const fadeInterval = setInterval(() => {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / durationMs, 1);
// Calculate new volume (linear fade from initial to 0)
audio.volume = initialVolume * (1 - progress);
// When fade is complete, stop audio and clean up
if (progress >= 1) {
clearInterval(fadeInterval);
audio.pause();
audio.currentTime = 0;
this.playingAudio.delete(soundPath);
}
}, 16); // ~60fps
}
static clearCache() {
this.audioCache.clear();
}
}
SoundManager.audioCache = new Map();
SoundManager.playingAudio = new Map();
SoundManager.enabled = true;