gibribbon
gibribbon · sourcesGIBRIBBON (video) — an AUDIO-DRIVEN rhythm line-runner in the spirit of Vib-Ribbon, cast with DOOM shareware sprites as fair-use artistic parody (owner-ruled rewrite 2026-08-28; audio-in redirect 2026-08-29). Like the original game — which analyses the music (any CD the player inserts) and builds its course from interesting frequency changes — the course derives from whatever is patched into AUDIO IN: the module's own analyser folds the signal into four musical bands (bass 20-200 / low-mid 200-1k / high-mid 1k-4k / treble 4k-16k Hz), and an ADAPTIVE extractor spawns events on relative peaks against each band's own rolling baseline, biased toward spectral-flux onsets — any source at any level plays, silence and stuck-flat signals spawn nothing, and there is no gain calibration anywhere in the path. THE BAND IS THE EVENT: bass=LOOP road dips (A), low-mid=JUMP humps (B), high-mid=IMP (X), treble=ZOMBIE (Y) — the low end shapes the road, the highs send the monsters (real TROO*/POSS* sprites when DOOM1.WAD is present, line-art otherwise; the marine is PLAY*). THE DAMAGE MODEL IS VIB-RIBBON'S: an uncleared event HITS the marine and degrades him one VISIBLE form down a DOOM ladder (the status-bar face mugshot grades from grin to bloodied; the line-art figure loses limbs), like Vibri degrading rabbit-to-frog-to-insect; hits at the floor are GAME OVER (evt_gameover pulses; the restart gate / R key / RESET revives); streaks heal and a long streak reaches gold SUPER. One clock: the internal TEMPO transport paces the ribbon while the audio decides what spawns; judgement is phase-anchored to it. An idle unpatched module self-plays in labelled ATTRACT (its bot deliberately fumbles so the ladder shows); any input — buttons, keyboard, or MOVING audio — starts a real run. Outputs: out (video), evt_hit/miss/fire/kill/gameover (10 ms gates), health_cv. Pure deterministic engine (gibribbon-engine.ts) + pure spectral fold (gibribbon-spectral.ts); VRT-baselined via the __gibribbonVrtSeed/__gibribbonVrtTicks pins. DOOM shareware terms apply (same file as the DOOM module, read-only).
the faceplate
inputs
| id | cable | what it does |
|---|---|---|
audio_in | audio | THE SOURCE. Patch any audio here — the whole course derives from it, like Vib-Ribbon generating stages from a music CD. The module's own AnalyserNode folds the signal into four musical bands (bass/low-mid/high-mid/treble) and spawns events on relative peaks against each band's own rolling baseline, biased toward spectral-flux onsets. Tap-only and inaudible: route the signal to AUDIO OUT separately to hear it. Moving audio also counts as player presence — it wakes the module out of ATTRACT into a live run. audio signal |
x | modsignal | Aim X (bipolar -1..1): re-centres the judgement point by up to one hit-window (stick left = clear events slightly early, right = slightly late). Shifts the window, never widens it. Modulates the X control. modulation (CV / gate / audio); modulates axis_x (additive offset — ±1 CV sweeps the full range, centered on the knob) |
y | modsignal | Aim Y (bipolar -1..1): raises the marine off the ribbon (up) or crouches it (down) — a visible aim aid consumed by the renderer. Modulates the Y control. modulation (CV / gate / audio); modulates axis_y (additive offset — ±1 CV sweeps the full range, centered on the knob) |
a | gate | The A play button (rising edge): judges the nearest in-window LOOP event at the tick-anchored phase of the press. Spare presses with no matching event are ignored (no penalty). Modulates the A control. gate / trigger; modulates btn_a (summed directly (the destination DSP scales it)); trigger — fires once per rising edge |
b | gate | The B play button (rising edge): judges the nearest in-window JUMP event. Modulates the B control. gate / trigger; modulates btn_b (summed directly (the destination DSP scales it)); trigger — fires once per rising edge |
x_btn | gate | The X play button (rising edge): judges the nearest in-window IMP event. Named x_btn to disambiguate from the x AXIS port. Modulates the X (btn) control. gate / trigger; modulates btn_x (summed directly (the destination DSP scales it)); trigger — fires once per rising edge |
y_btn | gate | The Y play button (rising edge): judges the nearest in-window ZOMBIE event. Named y_btn to disambiguate from the y AXIS port. Modulates the Y (btn) control. gate / trigger; modulates btn_y (summed directly (the destination DSP scales it)); trigger — fires once per rising edge |
restart | gate | Restart gate (rising edge): starts a fresh run — from GAME OVER or as a hard reset mid-run — so a rack can loop the game (wire evt_gameover back here through a delay for an endless arcade). Same path as the R key and the RESET action. Modulates the RESTART control. gate / trigger; modulates restart_btn (summed directly (the destination DSP scales it)); trigger — fires once per rising edge |
outputs
| id | cable | what it does |
|---|---|---|
out | video | The rendered game frame (video): the 16:9 ribbon scene — course, sprites, the DOOM status-bar face showing the marine's current form, and the in-canvas HUD (score, combo, ATTRACT label, count-in, GAME OVER banner) — letterboxed into the engine's 4:3 output. RGB video stream |
evt_hit | gate | A ~10 ms gate pulse on every successful clear (any in-window button match). In ATTRACT mode the self-player keeps firing these — the sequencer half of the module stays alive while idle. gate / trigger; trigger — fires once per rising edge |
evt_miss | gate | A ~10 ms gate pulse every time an uncleared event HITS the marine (it reached him without the right press), as he degrades a visible form down the ladder. gate / trigger; trigger — fires once per rising edge |
evt_fire | gate | A ~10 ms gate pulse when the marine FIRES — emitted on a successful enemy (imp/zombie) clear. gate / trigger; trigger — fires once per rising edge |
evt_kill | gate | A ~10 ms gate pulse when an enemy DIES (its death animation), emitted alongside evt_fire on an enemy clear. gate / trigger; trigger — fires once per rising edge |
evt_gameover | gate | A ~10 ms gate pulse fired once when the marine's form degrades past the floor — GAME OVER (Vibri hit once too often as an insect). gate / trigger; trigger — fires once per rising edge |
health_cv | cv | The marine's vitality as a 0..1 CV (super=1, healthy=0.75, wounded=0.5, critical=0.25, dead=0), ramped smoothly on each form change. control voltage (CV) |
params
| id | label | range | default | curve |
|---|---|---|---|---|
axis_x | X | -1..1 | 0 | linear |
axis_y | Y | -1..1 | 0 | linear |
btn_a | A | 0..1 | 0 | linear |
btn_b | B | 0..1 | 0 | linear |
btn_x | X (btn) | 0..1 | 0 | linear |
btn_y | Y (btn) | 0..1 | 0 | linear |
restart_btn | RESTART | 0..1 | 0 | linear |
autoplay | Attract | 0..1 | 1 | discrete |
difficulty | Difficulty | 0..1 | 0.5 | linear |
tempo | Tempo | 60..180 | — | log |
controls
| control | what it does |
|---|---|
| Attract | ATTRACT toggle (0/1, default 1 = ON). The id says autoplay for historical continuity; the behaviour is ATTRACT MODE: when ON, an IDLE and unpatched module self-plays a labelled attract run through the real extractor and judge (its demo bot deliberately fumbles some events so the damage ladder shows), and any real input — a button, the keyboard, or moving audio at AUDIO IN — starts a fresh live run. Set 0 and the module never self-plays; an idle ribbon stays honestly empty. |
| X | The aim-X value (-1..1, default 0) re-centring the judgement window; written by the X axis jack. |
| Y | The aim-Y value (-1..1, default 0) raising/crouching the marine; written by the Y axis jack. |
| A | The A-button level (0..1); a rising edge judges the nearest in-window loop event. Written by the A jack (or keyboard F / left-arrow). |
| B | The B-button level (0..1); a rising edge judges the nearest in-window jump event. Written by the B jack (or keyboard D / down-arrow). |
| X (btn) | The X-button level (0..1); a rising edge judges the nearest in-window imp event. Written by the x_btn jack (or keyboard J / right-arrow). |
| Y (btn) | The Y-button level (0..1); a rising edge judges the nearest in-window zombie event. Written by the y_btn jack (or keyboard K / up-arrow). |
| Difficulty | The one game knob (0..1, default 0.5): scales course density (extraction bar + spawn-rate cap) and the course rate together. Low = sparse and readable; high = dense and fast. |
| RESTART | The restart level (0..1); a rising edge starts a fresh run (from game over, or hard reset mid-run). Written by the restart jack (or keyboard R / the RESET action). |
| Tempo | The ribbon's course rate (60..180 BPM-equivalent, default ~143 = the classic 0.42 s beat). The audio decides WHAT spawns; TEMPO decides how fast the course approaches. One clock: judgement is anchored to this transport's tick phase. |
source
gibribbon.ts on GitHub.