Files
battle-caster-v1/src/model/SoundPlayer.ts
2024-10-13 16:09:21 +00:00

61 lines
1.8 KiB
TypeScript

export class SoundPlayer {
public sounds = ['sword slash', 'knock - wood'];
private ctx = new AudioContext();
private cache = new Map<string, AudioBuffer>();
private cacheOptions = new Map<string, string[]>();
constructor() {
}
async play(sound: string) {
if (this.sounds.includes(sound)) {
const options = await this.fetchSoundOptions(sound);
const randomOption = options[Math.floor(Math.random() * options.length)];
const soundBuffer = await this.fetchSound(sound, randomOption);
this.playBuffer(soundBuffer);
console.log(`Playing sound: ${sound}`);
} else {
console.log(`Sound not found: ${sound}`);
}
}
async fetchSoundOptions(sound: string) {
const url = `/soundfx/${sound}/`;
const dir = fetch(url)
.then((res) => res.json())
.then((dir) => {
this.cacheOptions.set(url, dir.map(({name}: any) => name) as string[]);
});
if (!this.cacheOptions.has(url)) {
await dir;
}
return this.cacheOptions.get(url)!;
}
async fetchSound(sound: string, options: string) {
const url = `/soundfx/${sound}/${options}`;
if (this.cache.has(url)) {
return this.cache.get(url)!;
}
console.log(`Fetching sound: ${sound}/${options}`);
const arrayBuffer = await (await fetch(url)).arrayBuffer();
const audioBuffer = await this.ctx.decodeAudioData(arrayBuffer);
this.cache.set(url, audioBuffer);
return audioBuffer;
}
async playBuffer(buffer: AudioBuffer) {
const source = this.ctx.createBufferSource();
const panner = this.ctx.createStereoPanner();
// panner.pan.value = Math.random() > 0.5 ? 1 : -1;
source.buffer = buffer;
source.connect(panner);
panner.connect(this.ctx.destination);
source.start();
}
}