fix : sound overlap issue (#38)
This commit is contained in:
@@ -1,37 +1,40 @@
|
|||||||
import { Move } from "chess.js";
|
import { Move } from "chess.js";
|
||||||
|
|
||||||
let audioContext: AudioContext | null = null;
|
let ctx: AudioContext | null = null;
|
||||||
let audio: HTMLAudioElement | null = null;
|
const bufferCache = new Map<string, AudioBuffer>();
|
||||||
|
|
||||||
const playSound = async (url: string) => {
|
const urls = {
|
||||||
if (!audio) {
|
move: "/sounds/move.mp3",
|
||||||
audioContext = new AudioContext();
|
capture: "/sounds/capture.mp3",
|
||||||
audio = new Audio();
|
illegal: "/sounds/illegal-move.mp3"
|
||||||
const source = audioContext.createMediaElementSource(audio);
|
} as const;
|
||||||
const volume = audioContext.createGain();
|
type Sound = keyof typeof urls;
|
||||||
volume.gain.value = 0.3;
|
|
||||||
source.connect(volume);
|
|
||||||
volume.connect(audioContext.destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
audio.src = url;
|
async function play(sound: Sound) {
|
||||||
try {
|
try {
|
||||||
await audio.play();
|
ctx ??= new (window.AudioContext || (window as any).webkitAudioContext)();
|
||||||
|
if (ctx.state === "suspended") await ctx.resume();
|
||||||
|
let buf = bufferCache.get(urls[sound]);
|
||||||
|
if (!buf) {
|
||||||
|
const res = await fetch(urls[sound]);
|
||||||
|
buf = await ctx.decodeAudioData(await res.arrayBuffer());
|
||||||
|
bufferCache.set(urls[sound], buf);
|
||||||
|
}
|
||||||
|
const src = ctx.createBufferSource();
|
||||||
|
src.buffer = buf;
|
||||||
|
src.connect(ctx.destination);
|
||||||
|
src.start();
|
||||||
} catch {
|
} catch {
|
||||||
console.warn("Audio play failed");
|
if ("vibrate" in navigator) navigator.vibrate(50);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export const playCaptureSound = () => playSound("/sounds/capture.mp3");
|
export const playCaptureSound = () => play("capture");
|
||||||
export const playIllegalMoveSound = () => playSound("/sounds/error.mp3");
|
export const playIllegalMoveSound = () => play("illegal");
|
||||||
export const playMoveSound = () => playSound("/sounds/move.mp3");
|
export const playMoveSound = () => play("move");
|
||||||
|
|
||||||
export const playSoundFromMove = async (move: Move | null) => {
|
export async function playSoundFromMove(move: Move | null) {
|
||||||
if (!move) {
|
if (!move) return playIllegalMoveSound();
|
||||||
playIllegalMoveSound();
|
if (move.captured) return playCaptureSound();
|
||||||
} else if (move.captured) {
|
return playMoveSound();
|
||||||
playCaptureSound();
|
}
|
||||||
} else {
|
|
||||||
playMoveSound();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user