Files
Wackelpeter/web/src/SoundManager.ts
T

62 lines
1.7 KiB
TypeScript

const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)();
const sounds: Record<string, AudioBuffer> = {};
async function loadSound(name: string): Promise<AudioBuffer> {
const response = await fetch(`./sounds/${name}.ogg`);
const arrayBuffer = await response.arrayBuffer();
return audioCtx.decodeAudioData(arrayBuffer);
}
export async function initSounds() {
const names = ['fireball', 'explosion', 'sword_hit1', 'teleport', 'damage', 'spiderwalking', 'spawn', 'gameover'];
for (const name of names) {
try {
sounds[name] = await loadSound(name);
} catch {
console.warn(`Sound ${name} not found`);
}
}
}
export function resumeContext() {
if (audioCtx.state === 'suspended') {
audioCtx.resume();
}
}
export function playSound(name: string, volume = 1) {
const buffer = sounds[name];
if (!buffer) return;
if (audioCtx.state === 'suspended') return;
const source = audioCtx.createBufferSource();
source.buffer = buffer;
const gain = audioCtx.createGain();
gain.gain.value = volume;
source.connect(gain);
gain.connect(audioCtx.destination);
source.start(0);
}
export function playLoopingSound(name: string, volume = 1): (() => void) | null {
const buffer = sounds[name];
if (!buffer) return null;
if (audioCtx.state === 'suspended') return null;
const source = audioCtx.createBufferSource();
source.buffer = buffer;
source.loop = true;
const gain = audioCtx.createGain();
gain.gain.value = volume;
source.connect(gain);
gain.connect(audioCtx.destination);
source.start(0);
return () => {
try {
source.stop();
} catch {
// already stopped
}
source.disconnect();
};
}