From 6c113682025e21af0c074d76d32a0e9b9d16de31 Mon Sep 17 00:00:00 2001 From: m3ultra Date: Thu, 16 Jul 2026 21:56:22 +1000 Subject: [PATCH] Expose audio state and levels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ready` only meant the graph got built — a suspended AudioContext is still silent, so there was no way to tell whether the storm was actually audible. The HUD now reports the real context state. Verified through it: context runs on first gesture; 7.5 -> 17.8 m/s takes the wind bed 0.16 -> 0.36 gain while the howl layer goes 0.016 -> 0.104 and the cutoff opens 428 -> 767 Hz, so a gale reads as a gale and not just a louder breeze. Rain tracks its curve 0.03 -> 0.32. Co-Authored-By: Claude Opus 4.8 --- web/world/js/skyfx.js | 13 +++++++++++++ web/world/weather_demo.html | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/web/world/js/skyfx.js b/web/world/js/skyfx.js index 2c63773..030576e 100644 --- a/web/world/js/skyfx.js +++ b/web/world/js/skyfx.js @@ -168,6 +168,19 @@ function createAudio(seed = 1) { return { get ready() { return started; }, + /** 'running' | 'suspended' | 'closed' | 'none'. `ready` only means the graph + * got built — a suspended context is still silent, so the HUD reports this. */ + get state() { return ctx ? ctx.state : 'none'; }, + /** Current layer gains — for the HUD and for asserting the bed tracks wind. */ + levels() { + if (!started) return null; + return { + wind: +windGain.gain.value.toFixed(4), + howl: +howlGain.gain.value.toFixed(4), + rain: +rainGain.gain.value.toFixed(4), + cutoff: Math.round(windFilter.frequency.value), + }; + }, /** Call from the first click/keydown. Safe to call repeatedly. */ unlock() { diff --git a/web/world/weather_demo.html b/web/world/weather_demo.html index 8a67a0e..0c5801f 100644 --- a/web/world/weather_demo.html +++ b/web/world/weather_demo.html @@ -247,7 +247,7 @@ function frame(now) {
dir ${(wind.dirAt(t)).toFixed(2)} rad
rain
worst
-
debris ${debris.pieces.length} audio ${sky.audio.ready ? 'on' : '(click)'}
+
debris ${debris.pieces.length} audio ${sky.audio.ready ? sky.audio.state : '(click)'}
flash ${sky.flash.toFixed(2)}
${tg ? `
GUST INBOUND ${tg.eta.toFixed(1)}s pow ${tg.power.toFixed(0)}
` : '
 
'} ${ticker.slice(0, 3).map((s) => `
${s}
`).join('')}