src/util/sound.ts (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
// Short synthesized blips, so there are no audio files to ship. Silent until the
// first move, since browsers only allow audio after a user gesture.
let ctx: AudioContext | null = null;
function tone(freq: number, ms: number, gain: number) {
if (!ctx) ctx = new (window.AudioContext || (window as any).webkitAudioContext)();
const osc = ctx.createOscillator();
const vol = ctx.createGain();
osc.type = "triangle";
osc.frequency.value = freq;
vol.gain.value = gain;
osc.connect(vol).connect(ctx.destination);
const t = ctx.currentTime;
vol.gain.setValueAtTime(gain, t);
vol.gain.exponentialRampToValueAtTime(0.0001, t + ms / 1000);
osc.start(t);
osc.stop(t + ms / 1000);
}
export const sound = {
move: () => tone(220, 70, 0.05),
capture: () => tone(150, 110, 0.07),
check: () => tone(440, 130, 0.06),
castle: () => {
tone(196, 70, 0.05);
setTimeout(() => tone(294, 90, 0.05), 70);
},
promote: () => {
tone(523, 80, 0.06);
setTimeout(() => tone(659, 80, 0.06), 80);
setTimeout(() => tone(784, 150, 0.06), 160);
},
start: () => {
tone(330, 80, 0.06);
setTimeout(() => tone(440, 80, 0.06), 90);
setTimeout(() => tone(554, 140, 0.06), 180);
},
tick: () => tone(880, 30, 0.03),
end: () => {
tone(330, 160, 0.06);
setTimeout(() => tone(247, 220, 0.06), 120);
},
};
|