From c82503c73f9fc3385e9a954dd19aa157b9ca5fe3 Mon Sep 17 00:00:00 2001 From: jim kolpack Date: Thu, 8 Oct 2026 18:51:35 -0400 Subject: [PATCH] Widen the ending glitch window; decouple jitter duration from it User reported the progress bar consistently stalling a few segments short of full -- SUB/WAVE's reported track duration appears to run a bit longer than the station actually plays before crossfading/cutting to the next track, so "remaining" rarely if ever dropped below the old 5s end-window before the subsonic_id changed out from under it. Split the single STATIC_OVERLAY_SECONDS into separate start (5s, unchanged) and end (22s) windows to compensate. Widening the end window naively (scaling GLITCH_REPEATS to cover all 22s of it) pushed a real render to 481KB, over the 460KB device limit -- each repeat adds several more uniquely-tinted/shifted frames for WebP to encode, and 22s of continuous jitter is a lot of those. Added GLITCH_ACTIVE_SECONDS (6s) to cap how much of the window actually gets jitter bursts, independent of how long show_static itself stays true -- scanlines and corner ticks are cheap, constant per-pixel layers that still cover the full window on their own. Verified: payload stays well under budget (max 234KB) across every zoom level/position combination after the fix. --- subwave_nowplaying.star | 44 ++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/subwave_nowplaying.star b/subwave_nowplaying.star index 7abdbe1..651c1a2 100644 --- a/subwave_nowplaying.star +++ b/subwave_nowplaying.star @@ -91,11 +91,21 @@ COLOR_SCHEMES = { } DEFAULT_COLOR_SCHEME = "cyberpunk" # matches the station's own site theme -# How many seconds into a track's start, or before its end, the "static" -# overlay shows over the album art (a bundled animated GIF of sparse noise -# specks over a transparent background -- images/static.gif). Only used -# when the "Static overlay" schema field is enabled. -STATIC_OVERLAY_SECONDS = 5 +# How many seconds into a track's start, or before its reported end, the +# glitch overlay shows over the album art. Only used when the "Static +# overlay" schema field is enabled. +# +# These aren't symmetric on purpose: SUB/WAVE's reported `duration` is a +# track's full metadata length, but in practice the station appears to +# cut/crossfade to the next track a bit before that duration actually +# elapses (observed via the progress bar consistently stalling a few +# segments short of full, never reaching the end) -- so `remaining` was +# rarely if ever dropping below a short end-window before the subsonic_id +# changed out from under it. Widening the end window compensates for that +# observed early cutoff; the start window doesn't have the same problem +# (elapsed genuinely starts at 0) so it stays short. +STATIC_OVERLAY_START_SECONDS = 5 +STATIC_OVERLAY_END_SECONDS = 22 DEFAULT_STATIC_OVERLAY = "on" # How far in the album art zoom goes, relative to its fully-zoomed-out rest @@ -180,7 +190,7 @@ def main(config): show_static = ( static_overlay_enabled and progress != None and - (progress["elapsed"] < STATIC_OVERLAY_SECONDS or progress["remaining"] < STATIC_OVERLAY_SECONDS) + (progress["elapsed"] < STATIC_OVERLAY_START_SECONDS or progress["remaining"] < STATIC_OVERLAY_END_SECONDS) ) # The show/host and time/temp rows always render, even when empty, so @@ -384,14 +394,24 @@ GLITCH_STATE_POOL = [ ] # render.Sequence doesn't loop on its own (see _glitch_scanlines below), so -# to repeat the burst-then-pause pattern for the whole show_static window, -# the repeats have to be spelled out as one long children list up front -# rather than relying on any runtime looping. Rounds up so the window is -# always fully covered, even if that runs a little past -# STATIC_OVERLAY_SECONDS -- better than the jitter cutting out early. +# to repeat the burst-then-pause pattern, the repeats have to be spelled +# out as one long children list up front rather than relying on any +# runtime looping. +# +# Deliberately *not* sized against the full show_static window (which can +# now be up to STATIC_OVERLAY_END_SECONDS = 22s): each repeat adds several +# more uniquely-tinted/shifted frames for WebP to encode, and scaling that +# up to cover 22s of jitter pushed a real render past the 460KB device +# limit (measured 481KB). Scanlines and corner ticks (see _glitch_effect) +# are cheap, constant per-pixel layers that can cover the full window for +# free, but the hue-shifted bands don't need to keep jittering the whole +# time to read as "something's happening" -- GLITCH_ACTIVE_SECONDS caps +# how much of the window actually gets jitter, independent of how long +# the window itself is. +GLITCH_ACTIVE_SECONDS = 6 _GLITCH_CYCLE_TICKS = GLITCH_STATES_PER_CYCLE * GLITCH_HOLD_TICKS + GLITCH_PAUSE_TICKS _GLITCH_TICKS_PER_SECOND = 20 # 1000ms / 50ms-per-tick -GLITCH_REPEATS = int(STATIC_OVERLAY_SECONDS * _GLITCH_TICKS_PER_SECOND / _GLITCH_CYCLE_TICKS) + 1 +GLITCH_REPEATS = int(GLITCH_ACTIVE_SECONDS * _GLITCH_TICKS_PER_SECOND / _GLITCH_CYCLE_TICKS) + 1 def _glitch_states_for_cycle(cycle_index): # Rotate through GLITCH_STATE_POOL instead of slicing (which doesn't