// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // DONAU2SPACE // DEV ENTITY — Audio Synth // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ let ctx = null; function getCtx() { if (!ctx) { try { ctx = new (window.AudioContext || window.webkitAudioContext)(); } catch { return null; } } if (ctx.state === 'suspended') ctx.resume().catch(() => {}); return ctx; } export function beep(freq = 880, ms = 70, vol = 0.04, type = 'square') { const ac = getCtx(); if (!ac) return; const osc = ac.createOscillator(); const gain = ac.createGain(); osc.type = type; osc.frequency.value = freq; gain.gain.setValueAtTime(vol, ac.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, ac.currentTime + ms / 1000); osc.connect(gain); gain.connect(ac.destination); osc.start(); osc.stop(ac.currentTime + ms / 1000 + 0.05); } export function keyClick() { beep(800 + Math.random() * 400, 15, 0.008, 'sine'); } export function errorBeep() { beep(220, 90, 0.05, 'square'); setTimeout(() => beep(180, 120, 0.04, 'square'), 100); } export function successChime() { beep(523, 60, 0.03, 'sine'); setTimeout(() => beep(659, 60, 0.03, 'sine'), 70); setTimeout(() => beep(784, 80, 0.03, 'sine'), 140); } export function warningTone() { beep(440, 150, 0.04, 'sawtooth'); setTimeout(() => beep(440, 150, 0.04, 'sawtooth'), 200); } export function sirenBurst(duration = 800) { const ac = getCtx(); if (!ac) return; const osc = ac.createOscillator(); const gain = ac.createGain(); osc.type = 'sawtooth'; osc.frequency.setValueAtTime(200, ac.currentTime); osc.frequency.linearRampToValueAtTime(600, ac.currentTime + duration / 2000); osc.frequency.linearRampToValueAtTime(200, ac.currentTime + duration / 1000); gain.gain.setValueAtTime(0.03, ac.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, ac.currentTime + duration / 1000); osc.connect(gain); gain.connect(ac.destination); osc.start(); osc.stop(ac.currentTime + duration / 1000 + 0.05); } export function transmitSound() { const ac = getCtx(); if (!ac) return; for (let i = 0; i < 8; i++) { setTimeout(() => { beep(1200 + Math.random() * 800, 30, 0.015, 'sine'); }, i * 40); } } export function droneStart() { const ac = getCtx(); if (!ac) return null; const osc = ac.createOscillator(); const gain = ac.createGain(); osc.type = 'sine'; osc.frequency.value = 55; gain.gain.value = 0; gain.gain.linearRampToValueAtTime(0.015, ac.currentTime + 2); osc.connect(gain); gain.connect(ac.destination); osc.start(); return { osc, gain, stop: () => { gain.gain.linearRampToValueAtTime(0.001, ac.currentTime + 1); setTimeout(() => { try { osc.stop(); } catch {} }, 1200); }}; } export function bootSound() { beep(130, 200, 0.02, 'sine'); setTimeout(() => beep(165, 200, 0.02, 'sine'), 200); setTimeout(() => beep(196, 300, 0.025, 'sine'), 400); }