From 0dbe5fd22964b6eb72b8561e203c407bb7eaff1d Mon Sep 17 00:00:00 2001 From: you Date: Sun, 22 Mar 2026 17:25:42 +0000 Subject: [PATCH] =?UTF-8?q?Audio:=20fix=20inconsistent=20init=20=E2=80=94?= =?UTF-8?q?=20lazy=20AudioContext,=20no=20premature=20creation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit restore() was creating AudioContext without user gesture (on page load when volume was saved), causing browser to permanently suspend it. Now restore() only sets flags; AudioContext created lazily on first sonifyPacket() call or setEnabled() click. Pending volume applied when context is finally created. --- public/audio.js | 18 +++++++++++------- public/index.html | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/public/audio.js b/public/audio.js index 2f70a466..c5ee8344 100644 --- a/public/audio.js +++ b/public/audio.js @@ -12,7 +12,8 @@ let bpm = 120; let activeVoices = 0; const MAX_VOICES = 12; - let currentVoice = null; // active voice module + let currentVoice = null; + let _pendingVolume = 0.3; // active voice module // === Shared Helpers (available to voice modules) === @@ -79,14 +80,18 @@ } audioCtx = new (window.AudioContext || window.webkitAudioContext)(); masterGain = audioCtx.createGain(); - masterGain.gain.value = 0.3; + masterGain.gain.value = _pendingVolume; masterGain.connect(audioCtx.destination); } // === Engine: Sonify === function sonifyPacket(pkt) { - if (!audioEnabled || !audioCtx || !currentVoice) return; + if (!audioEnabled || !currentVoice) return; + // Lazy-init AudioContext on first actual packet (may not have user gesture, + // but browser will auto-resume when it gets one) + if (!audioCtx) initAudio(); + if (!audioCtx) return; if (audioCtx.state === 'suspended') audioCtx.resume(); if (activeVoices >= MAX_VOICES) return; @@ -166,10 +171,9 @@ const savedBpm = localStorage.getItem('live-audio-bpm'); if (savedBpm) bpm = parseInt(savedBpm, 10) || 120; const savedVol = localStorage.getItem('live-audio-volume'); - if (savedVol) { - initAudio(); - if (masterGain) masterGain.gain.value = parseFloat(savedVol) || 0.3; - } + // Don't create AudioContext here — no user gesture yet, browser will suspend it. + // Just store the desired volume; initAudio() will apply it when user interacts. + if (savedVol) _pendingVolume = parseFloat(savedVol) || 0.3; const savedVoice = localStorage.getItem('live-audio-voice'); if (savedVoice) setVoice(savedVoice); } diff --git a/public/index.html b/public/index.html index bfd6c02b..d675e5e7 100644 --- a/public/index.html +++ b/public/index.html @@ -90,7 +90,7 @@ - +