From 1d5c86fb61ce7bfc50c7fdc65a510458c884e930 Mon Sep 17 00:00:00 2001 From: jim kolpack Date: Thu, 8 Oct 2026 17:17:49 -0400 Subject: [PATCH] Vary glitch band positions across loop cycles; soften corner ticks GLITCH_STATES was a fixed list of 4 band configs that every repeat cycle played identically, so the jitter looked the same each time it looped. Expanded to an 8-entry GLITCH_STATE_POOL and rotate through a different 4-state window each cycle (wrapping back to the start via modular indexing, since Starlark list slicing doesn't wrap) -- verified via an isolated two-cycle test that cycle 2's band positions genuinely differ from cycle 1's, not just coincidentally similar-looking. Also added alpha transparency to the corner tick color (#33ff9980) so they read as a subtle HUD accent rather than a solid opaque overlay. --- subwave_nowplaying.star | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/subwave_nowplaying.star b/subwave_nowplaying.star index 5f53660..d9c802f 100644 --- a/subwave_nowplaying.star +++ b/subwave_nowplaying.star @@ -357,12 +357,25 @@ def _zoomed_art(art_bytes, zoom_scale, zoom_position, subsonic_id): # middle band, each about 30% of the frame's height. GLITCH_HOLD_TICKS = 5 # ~250ms per jitter state at the default 50ms/tick GLITCH_PAUSE_TICKS = 15 # ~750ms of clean art between bursts -GLITCH_STATES = [ - # (top1, height1, shift1, hue1, top2, height2, shift2, hue2) +GLITCH_STATES_PER_CYCLE = 4 + +# A larger pool than any one burst needs, so repeated cycles (see +# GLITCH_REPEATS below) draw a different rotating window of states each +# time instead of showing the identical 4 band positions every loop. +# (top1, height1, shift1, hue1, top2, height2, shift2, hue2); proportions +# loosely modeled on the one SUB/WAVE keyframe that was visible (roughly +# the top third and an overlapping middle band, each ~30% of the frame's +# height) -- see the note above GLITCH_HOLD_TICKS for why that's the only +# part grounded in anything observed rather than invented. +GLITCH_STATE_POOL = [ (3, 9, -2, 150.0, 19, 8, 2, -60.0), (2, 8, 2, 150.0, 20, 9, -3, -60.0), (5, 7, -3, 150.0, 17, 10, 1, -60.0), (1, 10, 1, 150.0, 21, 7, -2, -60.0), + (6, 6, 1, 150.0, 14, 9, 3, -60.0), + (0, 8, 3, 150.0, 24, 6, -1, -60.0), + (4, 7, -1, 150.0, 12, 10, 2, -60.0), + (2, 9, -3, 150.0, 22, 7, 1, -60.0), ] # render.Sequence doesn't loop on its own (see _glitch_scanlines below), so @@ -371,10 +384,18 @@ GLITCH_STATES = [ # 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. -_GLITCH_CYCLE_TICKS = len(GLITCH_STATES) * GLITCH_HOLD_TICKS + GLITCH_PAUSE_TICKS +_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 +def _glitch_states_for_cycle(cycle_index): + # Rotate through GLITCH_STATE_POOL instead of slicing (which doesn't + # wrap around in Starlark), so each cycle's window of states can + # straddle the end of the pool and loop back to the start. + pool_size = len(GLITCH_STATE_POOL) + start = (cycle_index * GLITCH_STATES_PER_CYCLE) % pool_size + return [GLITCH_STATE_POOL[(start + i) % pool_size] for i in range(GLITCH_STATES_PER_CYCLE)] + def _glitch_band(zoomed_art, top, height, shift_x, hue_change): tinted = filter.Hue(child = zoomed_art, change = hue_change) band = render.Padding( @@ -410,8 +431,8 @@ def _glitch_jitter(zoomed_art): pause = _glitch_hold(render.Box(width = ART_SLOT, height = ART_SLOT), GLITCH_PAUSE_TICKS) sequence = [] - for _ in range(GLITCH_REPEATS): - for top1, h1, shift1, hue1, top2, h2, shift2, hue2 in GLITCH_STATES: + for cycle_index in range(GLITCH_REPEATS): + for top1, h1, shift1, hue1, top2, h2, shift2, hue2 in _glitch_states_for_cycle(cycle_index): state = render.Stack(children = [ _glitch_band(zoomed_art, top1, h1, shift1, hue1), _glitch_band(zoomed_art, top2, h2, shift2, hue2), @@ -486,7 +507,7 @@ def _glitch_effect(zoomed_art): child = render.Stack(children = [ _glitch_jitter(zoomed_art), _glitch_scanlines(), - _glitch_corner_ticks("#33ff99"), + _glitch_corner_ticks("#33ff9980"), ]), )