2026-06-11·Sanchez

Zero Sound Files — Synthesizing SFX with Web Audio

I kept external assets to a minimum throughout the rebuild.
Only the background music (BGM) uses mp3s; the sound effects (SFX) use no files at all — every effect (collect, jump, hit, combo) is synthesized on the spot with the Web Audio API.

There are only two basic tools: an oscillator (which generates a waveform) and gain (volume).
Add a starting frequency, a duration, a waveform type, and an envelope that decays the volume toward zero over time, and you've got one short sound effect.
I reuse this single function for everything.

function blip(freq, dur, type, gain = 0.15, slide = 0) {
  const c = ac(); // lazily-created AudioContext (browser/SSR guard)
  const o = c.createOscillator();
  const g = c.createGain();
  o.type = type;
  o.frequency.setValueAtTime(freq, c.currentTime);
  if (slide !== 0) // glide the pitch over the duration
    o.frequency.exponentialRampToValueAtTime(freq + slide, c.currentTime + dur);
  g.gain.setValueAtTime(gain, c.currentTime);
  g.gain.exponentialRampToValueAtTime(0.0001, c.currentTime + dur); // envelope
  o.connect(g).connect(c.destination);
  o.start();
  o.stop(c.currentTime + dur);
}

I split the timbres: a low sine wave for jumps, a gritty sawtooth for taking a hit.
My favorite detail is the collect sound — the pitch rises as your combo climbs.

export const playCollect = (combo: number) =>
  blip(520 + Math.min(combo, 24) * 40, 0.18, "triangle", 0.18, 120);

520 + min(combo,24)*40Hz.
Grab one and it's 520Hz; as the combo builds it steps up a notch at a time and caps out at the ceiling.
When you collect a streak in a row, the pitch trickles upward — and that rising feel was more thrilling than the combo itself.
There's no way I'd have gotten that satisfaction from replaying the same canned sound.

I also covered the browser environment check.
If window or AudioContext is missing, every function quietly falls back to a no-op.
That keeps things from blowing up under SSR or unsupported environments.

That wraps up the rebuild dev log.
The takeaway is simple — even with zero sound-effect files, code alone was enough to make sounds that feel cute and satisfying to play.

Try it yourself →