all repos — emchess @ main

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);
  },
};