fledgling/src/sound.ts

54 lines
1.4 KiB
TypeScript

class SoundShared {
readonly context: AudioContext;
bgmSource: AudioBufferSourceNode | null;
bgmGain: GainNode | null;
constructor() {
this.context = new AudioContext();
this.bgmSource = null;
this.bgmGain = null;
}
}
const shared = new SoundShared();
export class Sound {
#link: string;
#audioBufferPromise: Promise<AudioBuffer>;
constructor(link: string) {
this.#link = link;
this.#audioBufferPromise = this.#unsafeGetAudioBuffer();
}
async #unsafeGetAudioBuffer(): Promise<AudioBuffer> {
let resp = await fetch(this.#link);
let buf = await resp.arrayBuffer();
return await shared.context.decodeAudioData(buf);
}
async #getAudioBuffer(): Promise<AudioBuffer> {
return await this.#audioBufferPromise;
}
play(options?: { volume?: number; bgm?: boolean }) {
this.#getAudioBuffer().then((adata) => {
let source = shared.context.createBufferSource();
source.buffer = adata;
let gain = shared.context.createGain();
gain.gain.value = options?.volume ?? 1.0;
source.connect(gain);
gain.connect(shared.context.destination);
source.start();
if (options?.bgm) {
shared.bgmSource?.stop(shared.context.currentTime + 1);
shared.bgmGain?.gain?.linearRampToValueAtTime(
0.0,
shared.context.currentTime + 1,
);
shared.bgmSource = source;
shared.bgmGain = gain;
}
});
}
}