Audio & Game Dev

8-BIT RETRO SFX GENERATOR

Synthesize classic arcade and 8-bit game sound effects (Coin, Laser, Explosion, Jump, Power-Up) powered by Web Audio API synthesis.

Instant Sound Presets
Start Frequency 440 Hz
End Frequency (Sweep) 880 Hz
Decay Duration 0.25s

        
Developer Reference

Core Algorithm & Standalone Script

Standalone, zero-dependency JavaScript implementation powering this tool. Free to inspect, copy, and build upon.

let audioCtx = null;
    const canvas = document.getElementById('waveform-canvas');
    const ctx = canvas.getContext('2d');
    const toast = document.getElementById('toast');

    const elWave = document.getElementById('select-wave');
    const elFStart = document.getElementById('input-fstart');
    const elFEnd = document.getElementById('input-fend');
    const elDecay = document.getElementById('input-decay');
    const jsOut = document.getElementById('js-code-out');

    function showToast(msg) {
      toast.textContent = msg;
      toast.classList.add('show');
      setTimeout(() => toast.classList.remove('show'), 2000);
    }

    function initAudio() {
      if (!audioCtx) {
        audioCtx = new (window.AudioContext || window.webkitAudioContext)();
      }
    }

    function playSound() {
      initAudio();
      const wave = elWave.value;
      const fStart = parseFloat(elFStart.value);
      const fEnd = parseFloat(elFEnd.value);
      const decay = parseFloat(elDecay.value);

      const now = audioCtx.currentTime;

      if (wave === 'noise') {
        const bufferSize = audioCtx.sampleRate * decay;
        const buffer = audioCtx.createBuffer(1, bufferSize, audioCtx.sampleRate);
        const data = buffer.getChannelData(0);
        for (let i = 0; i < bufferSize; i++) {
          data[i] = Math.random() * 2 - 1;
        }
        const noise = audioCtx.createBufferSource();
        noise.buffer = buffer;
        const gain = audioCtx.createGain();
        gain.gain.setValueAtTime(1, now);
        gain.gain.exponentialRampToValueAtTime(0.01, now + decay);
        noise.connect(gain);
        gain.connect(audioCtx.destination);
        noise.start(now);
      } else {
        const osc = audioCtx.createOscillator();
        const gain = audioCtx.createGain();

        osc.type = wave;
        osc.frequency.setValueAtTime(fStart, now);
        osc.frequency.exponentialRampToValueAtTime(Math.max(20, fEnd), now + decay);

        gain.gain.setValueAtTime(1, now);
        gain.gain.exponentialRampToValueAtTime(0.01, now + decay);

        osc.connect(gain);
        gain.connect(audioCtx.destination);

        osc.start(now);
        osc.stop(now + decay);
      }

      drawWaveVisual(fStart, fEnd, decay);
      updateCodeSnippet();
    }

    function drawWaveVisual(fStart, fEnd, decay) {
      canvas.width = canvas.clientWidth;
      canvas.height = canvas.clientHeight;
      const w = canvas.width;
      const h = canvas.height;

      ctx.fillStyle = '#000';
      ctx.fillRect(0, 0, w, h);

      ctx.beginPath();
      ctx.lineWidth = 2;
      ctx.strokeStyle = '#00ff66';

      for (let i = 0; i < w; i++) {
        const progress = i / w;
        const freq = fStart + (fEnd - fStart) * progress;
        const y = (h / 2) + Math.sin(progress * freq * 0.05) * ((1 - progress) * (h * 0.4));
        if (i === 0) ctx.moveTo(i, y);
        else ctx.lineTo(i, y);
      }
      ctx.stroke();
    }

    function updateCodeSnippet() {
      const code = `const ctx = new AudioContext();
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.type = '${elWave.value}';
osc.frequency.setValueAtTime(${elFStart.value}, ctx.currentTime);
osc.frequency.exponentialRampToValueAtTime(${elFEnd.value}, ctx.currentTime + ${elDecay.value});
gain.gain.setValueAtTime(1, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + ${elDecay.value});
osc.connect(gain); gain.connect(ctx.destination);
osc.start(); osc.stop(ctx.currentTime + ${elDecay.value});`;

      jsOut.textContent = code;
    }

    document.querySelectorAll('.btn-preset').forEach(btn => {
      btn.addEventListener('click', () => {
        const sfx = btn.dataset.sfx;
        if (sfx === 'coin') {
          elWave.value = 'square'; elFStart.value = 987; elFEnd.value = 1318; elDecay.value = 0.2;
        } else if (sfx === 'laser') {
          elWave.value = 'sawtooth'; elFStart.value = 1400; elFEnd.value = 120; elDecay.value = 0.15;
        } else if (sfx === 'explosion') {
          elWave.value = 'noise'; elFStart.value = 200; elFEnd.value = 50; elDecay.value = 0.6;
        } else if (sfx === 'jump') {
          elWave.value = 'square'; elFStart.value = 150; elFEnd.value = 600; elDecay.value = 0.25;
        } else if (sfx === 'powerup') {
          elWave.value = 'triangle'; elFStart.value = 330; elFEnd.value = 1100; elDecay.value = 0.4;
        } else if (sfx === 'random') {
          const waves = ['square', 'sawtooth', 'triangle', 'noise'];
          elWave.value = waves[Math.floor(Math.random() * waves.length)];
          elFStart.value = Math.floor(Math.random() * 1800 + 100);
          elFEnd.value = Math.floor(Math.random() * 1800 + 100);
          elDecay.value = (Math.random() * 0.5 + 0.1).toFixed(2);
        }

        document.getElementById('val-fstart').textContent = elFStart.value + ' Hz';
        document.getElementById('val-fend').textContent = elFEnd.value + ' Hz';
        document.getElementById('val-decay').textContent = elDecay.value + 's';

        playSound();
      });
    });

    [elFStart, elFEnd, elDecay].forEach(el => {
      el.addEventListener('input', () => {
        document.getElementById('val-fstart').textContent = elFStart.value + ' Hz';
        document.getElementById('val-fend').textContent = elFEnd.value + ' Hz';
        document.getElementById('val-decay').textContent = elDecay.value + 's';
        updateCodeSnippet();
      });
    });

    document.getElementById('btn-play').addEventListener('click', playSound);
    document.getElementById('btn-copy-js').addEventListener('click', () => {
      navigator.clipboard.writeText(jsOut.textContent);
      showToast('Web Audio Code copied!');
    });

    // Init canvas
    drawWaveVisual(440, 880, 0.25);
    updateCodeSnippet();
Copied to clipboard!