All notable non-shader feature changes to this project will be documented in this file.
- Wavelet (DWT) audio analysis (
?wavelet=true) — Opt-in multiresolution analysis running alongside the FFT pipeline. A Daubechies-4 wavelet transform gives octave bands at their own time resolution (smooth bass, sharp treble) for better deep-bass-drop detection and frequency-motion features. Bands are first-class features with the full 11 stat variations (waveletBand0ZScore, etc.), plus derived axes (waveletCentroid/waveletSpread/waveletTilt), a sharpwavelet_bassHitdrop trigger, and FFT×wavelet combinations (wavelet_punch,wavelet_confirmedDrop). Uses a 128-sample sliding window for ~3ms-latency updates. (#123)
- Headless wavelet feature harnesses —
scripts/wavelet-harness2.mjsandscripts/wavelet-fft-cross.mjsscore audio features for animation quality and cross-domain independence from ffmpeg-decoded PCM, running the exactcreateWaveletAnalyzerthat runs live. (#123)
- MIDI mapping page (
/midi.html) — Dedicated visual UI for managing controller mappings: device list, live CC→knob table with inline knob-index editing, and a knob grid you click to learn-bind the next incoming CC. Replaces the per-knob learn flow buried in the editor. (#121)
/vibejskill (renamed from/vj) — The live auto-VJ loop is now invoked as/vibej. The legacy/vjalias still works identically — same arguments, same.claude/vj-state.json, same per-shader journal. Disambiguates "vj" (often "video jockey" generally) from this specific shader auto-mutation loop./jam,/fork,/recordskills — Streamlined live-jam workflow./jamopens jam page + Spotify + tab audio sharing in one shot./forksnapshots the current shader + knob state as a new numbered iteration./recordcaptures a video of the current visualization with auto-stop. (#115)/vibej(/vj) skill + live VJ session infrastructure — Claude runs as the VJ: every minute, reads audio features + Spotify track name from the jam page, makes one focused edit to the shader (validated pre-save against a real GL compile), HMR hot-swaps. Per-shader journal accumulates "cool moments", todos, removals, and forks so future sessions resume with full context. Subtle vs dramatic move styles, auto-wires knobs the user is twisting. (#116)- Tab audio capture title in snapshots — Snapshots now record the shared tab title (via
MediaStreamTrack.label), so the queue knows which Spotify/SoundCloud track was playing when each preset was captured. - Controller hot-reload — Edits to
controllers/*.jsnow hot-reload on the jam/edit pages without losing the audio stream or knob state.
scripts/dev-port— Branch-derived dev server port (main = 6969, other branches hash to 1024–65534). All skills and tooling read from this script; never hardcode the port. Means multiple worktrees can runnpm run devsimultaneously without colliding.- Pre-save GL validation in
/vibej— Each shader edit is compiled in a tiny offscreen WebGL2 context on the jam tab BEFORE writing to disk, catching errors the static linter misses (forward refs, type errors).
- Jam page (
/jam.html) — Lean visualization page for live sessions: fullscreen shader + knob drawer, no editor. Spacebar snapshots the current knob + audio state to a queue for batch processing. Backspace undoes the last snapshot. (#114) - Preset snapshot queue — Snapshots capture structured audio features (normalized, zScore, slope, rSquared for 14 features) alongside knob values. Process the queue offline with
/preset process— no live browser needed. (#114) ?audio=noneparam — Explicitly disable audio input. Cleaner than?noaudio=true. (#107)- MIDI on index page — Opt-in MIDI controller support on the viewer page with
?midi=true. (#113)
- No more black flashes on tab switch — Eliminated black frames when hiding/showing the browser tab or switching desktops. (#101)
- Wake lock on user gesture — Screen stays on during live sessions without needing manual settings. (#112)
- Editor save no longer reloads — Ctrl+S in the editor saves to disk without triggering a full page reload. (#109)
- Audio warm-up ramp — Prevents visual spikes when audio first connects. (#110)
- Hot-swap shader updates on jam page —
.fragfile changes apply without page reload, preserving tab audio sharing permissions.
- Compact list page layout — Desktop list page uses space more efficiently. (#108)
- Multiplayer editor with live cursors — Edit the same shader with multiple people simultaneously, with colored cursors and real-time sync over WebSocket. (#98)
- Tab audio capture (
?audio=tab) — Visualize Spotify, YouTube, or any browser tab's audio without installing a loopback driver. Just append?audio=taband pick a tab. Chrome/Edge only. (#97) - Editor-filesystem sync — Ctrl+S in the editor writes to disk; external file changes push back into the browser via HMR. Works alongside multiplayer without stomping edits. (#103)
- Shader presets — Define presets (pre-configured knob values) per shader that appear on the list page for one-tap access. (#71)
- List page param forwarding — All current URL params carry through when navigating from the list page, so knob overrides and settings stick. Current params take precedence over preset values.
- Quality-of-life navigation — Smoother navigation between edit, list, and remote views. (#96)
- WebGL context restore without reload — GPU resources re-initialize in-place on context loss instead of reloading the page. Also fixed cascading reloads on tab focus and drawing buffer loss when switching desktops. (#87, #88, #89)
- Build fix for Cloudflare Pages — Removed
optimize-images.shwhich required tools unavailable in the Pages build environment, silently aborting the entire build. - List page no longer forces fullscreen on tap — Tapping a shader/preset navigates without forcing fullscreen mode. (#91)
- Deterministic audio file playback — New
?audio_file=<url>param plays a specific audio file through the analyzer for reproducible e2e tests and screenshots. (#94) - MIDI controller profiles — Plug in any MIDI controller and knobs auto-map. Profiles persist per device in localStorage with a learn mode for manual assignment.
- Knob remap script —
scripts/remap-knobs.jsutility for remapping knob assignments across shader files.