// Tiny WebAudio synth — no asset files. All sounds built from oscillators/noise. let ctx: AudioContext | null = null; let muted = localStorage.getItem("gigaslop-muted") === "1"; function ac(): AudioContext | null { if (muted) return null; if (!ctx) ctx = new AudioContext(); if (ctx.state === "suspended") ctx.resume(); return ctx; } export function setMuted(m: boolean) { muted = m; localStorage.setItem("gigaslop-muted", m ? "1" : "0"); } export function isMuted() { return muted; } function tone(freq: number, dur: number, type: OscillatorType, vol: number, when = 0, glideTo?: number) { const c = ac(); if (!c) return; const t0 = c.currentTime + when; const o = c.createOscillator(); const g = c.createGain(); o.type = type; o.frequency.setValueAtTime(freq, t0); if (glideTo) o.frequency.exponentialRampToValueAtTime(glideTo, t0 + dur); g.gain.setValueAtTime(vol, t0); g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur); o.connect(g).connect(c.destination); o.start(t0); o.stop(t0 + dur + 0.02); } function noise(dur: number, vol: number, lowpass = 800) { const c = ac(); if (!c) return; const buf = c.createBuffer(1, c.sampleRate * dur, c.sampleRate); const d = buf.getChannelData(0); for (let i = 0; i < d.length; i++) d[i] = (Math.random() * 2 - 1) * (1 - i / d.length); const src = c.createBufferSource(); src.buffer = buf; const f = c.createBiquadFilter(); f.type = "lowpass"; f.frequency.value = lowpass; const g = c.createGain(); g.gain.value = vol; src.connect(f).connect(g).connect(c.destination); src.start(); } export const sfx = { click: () => tone(880, 0.05, "square", 0.04), place: () => { noise(0.12, 0.25, 500); tone(140, 0.1, "sine", 0.15); }, sell: () => tone(520, 0.12, "triangle", 0.08, 0, 260), wire: () => { tone(660, 0.06, "square", 0.05); tone(990, 0.06, "square", 0.05, 0.07); }, publish: () => { tone(523, 0.08, "sine", 0.07); tone(784, 0.12, "sine", 0.07, 0.08); }, viral: () => [523, 659, 784, 1047, 1319].forEach((f, i) => tone(f, 0.18, "triangle", 0.09, i * 0.07)), tierUp: () => [392, 523, 659, 784].forEach((f, i) => tone(f, 0.3, "sawtooth", 0.05, i * 0.12)), breaker: () => { noise(0.4, 0.5, 250); tone(80, 0.5, "sawtooth", 0.2, 0, 35); }, error: () => tone(180, 0.15, "square", 0.06), };