Repository navigation
feat(modes): Stereo Trails, each band rises from its place in the stereo image - #732
Conversation
…reo image Refs CaYatur#638 A new visualizer in Particles & Events. It is a fountain: every frequency band launches its own particles. The launch angle comes from where the band sits between the left and right channel, the scatter from how diffuse it is, and the count and height from the band's level. A centred kick draws an upright column, a guitar panned left bends its arcs to the left, a wide reverb opens like a fan. Mono input stands straight up, which is correct. The stereo measurement is new: src/shared/stereo-bands.js runs a band-pass biquad per band over timeL/timeR and keeps sum(L^2), sum(R^2), sum(LR): - pan = (R^2 - L^2) / (R^2 + L^2), exact at hard left, centre, hard right (sin(p*pi/2) under constant-power panning); - spread = 1 - correlation: a single panned source is 0 wherever it sits, decorrelated or anti-phase sound is 1. analysis.js's width gives a hard-panned mono guitar and a wide reverb the same value (1), so it is deliberately not reused here. Silence and 8-bit quantisation noise read as centred. 0.07 ms per frame for 8 bands in Node; no allocation per frame. Levels come from audio.getBars, so every control the catalog flags reveal works: bar count (band count), frequency range, the whole Spectrum Measurement group, line width, amplitude and the secondary colour. The stereo bands use the spectrum's own edges (SVSpectrum.bandEdges), so with a mel or bark scale the level and the pan come from the same band. Drawn with source-over and butt caps: additive blending washed out on the default light background, and round caps cost frames on integrated graphics (Iris Xe, 1080p, uncapped: 118/92 fps with round, 124/118 butt). Checks: - npm test: 2941 pass (16 new); doc counts updated. - tests/stereo-bands.test.js runs the real mode file in a vm with a recording canvas: left/right/mono lean, diffuse sound fans out, each band in its own place, levels from getBars, deterministic output, and every page loads the helper. 10 of 10 mutations caught. - npm run smoke (isolated --user-data-dir): PASS, 60 visualizer modes drawn. - npm run bench, vsync on, 1080p on Iris Xe: 58.2 / 60.0 / 58.4 fps, p95 16.9 ms in three runs (Goniometer 59.4 / 60.0, Bouncing Balls 60.0). - The mode sheet in docs/screenshots is not regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
CaYaDraft — pull request Summary Files Free, open-source music visualizer and VJ software for every screen you ownTurn whatever your computer is playing — Spotify, YouTube, a DAW, a DJ set, a game — into README.tr.md (modified, +8/-7) Sahip olduğunuz her ekran için ücretsiz, açık kaynak müzik görselleştirici ve VJ yazılımıBilgisayarınızda ne çalıyorsa — Spotify, YouTube, bir DAW, bir DJ seti, bir oyun — bir ekranda ya ROADMAP.md (modified, +1/-1) |
The fountain sat at 94% of the canvas, so a full screen left a dead band under the launch line. The floor is now the bottom edge. trailHeight scales those same arcs. 1 keeps today's peak. Up to 3 lets them leave the top of the frame and fall back. The slider sits on the layer and on the classic visualizer card, and the MIDI/OSC target uses the same range.
The sheet is drawn from the catalogue and now holds 60 modes, including Stereo Trails. That mode waits with the other trail builders so its tile is not an empty first frame.
Uncapped, the full-screen trail and glow were submitted hundreds of times a second, faster than the GPU finished them. That backlog was charged to the following scene. Painting is now capped at 120 Hz. Physics still steps every frame, and 60 Hz and 75 Hz displays still paint every frame. On this machine, uncapped 1080p Bars read 663 fps before Stereo Trails and 380 fps after. After the cap it reads 663 fps before and 665 fps after. With vsync, Stereo Trails and the next scene both hold 75 fps.
|
Ready to merge. Checked
The description still says 2941 tests. The tree and the README badges say 2942, after the height test. That is not a code blocker. |
Refs #638
What
A new visualizer, Stereo Trails (
stereotrails, Stereo İzler), in Particles & Events. It is a fountain: every frequency band launches its own particles.A centred kick draws an upright column. A guitar panned left bends its arcs to the left. A wide reverb opens like a fan. Mono input stands straight up, which is the correct reading.
Why
#638 asks for more original modes. Since #566 every frame carries real left and right channels, but only the Goniometer and the Level Meter read them, and both are meters. This turns the stereo image into a visual mode.
How
src/shared/stereo-bands.js(new, pure arithmetic, Node-tested) runs one band-pass biquad per band overtimeL/timeRand keeps ΣL², ΣR² and ΣLR:analysis.js's width is deliberately not reused: it gives a hard-panned mono guitar and a wide reverb the same value (1).The mode (in
generative2.js, where the #638 batches live):audio.getBars, so every control the catalog flags reveal does something: bar count (band count), frequency range, the whole Spectrum Measurement group, line width, amplitude and the secondary colour.SVSpectrum.bandEdges, so with a mel or bark scale the level and the pan come from the same band.lighter, because additive blending washed out on the default light background. Butt caps, not round: Iris Xe, 1080p, uncapped bench gave 118 and 92 fps with round caps against 124 and 118 with butt.visualizer.trailHeight) keeps today's peak at 100% and can carry the arcs off the top of the frame, up to 300%.Wiring:
stereo-bands.jsloaded on all four pages that draw modes (visualizer, overlay, exporter, admin);docs/screenshots/modes-visualizer.jpg, regenerated from the catalogue (60 modes, including Stereo Trails).Performance of the follow-up fix
Uncapped, the full-screen trail and glow were submitted hundreds of times a second, faster than the GPU finished them. That backlog was charged to the next scene. Painting is now capped at 120 Hz. The cap is only inside
StereoTrails.draw.Same machine (RTX 5070 Laptop, 1080p,
npm run bench, 1 s warm-up, 3 s measured). The pair in each row is Bars immediately before Stereo Trails, then Bars immediately after it.With vsync on, after the cap, Stereo Trails and the following Flow Field both hold 75.0 fps, p95 13.4 ms. The Iris Xe vsync figures below are from the original commit and still describe the mode while it is on screen.
Checks
npm test: 2942 pass, 17 of them new (the original 16, plus the height-slider test).tests/stereo-bands.test.js, the measurement: checked against known-answer signals (panned tones, mono, constant-power pan law, anti-phase, decorrelated tones, silence, byte vs float input, mel edges).tests/stereo-bands.test.js, the mode: the real mode file runs in avmwith a recording canvas. The tests check that left, right and mono sound lean the right way, that diffuse sound fans out, that each band sits in its own place, that subtle stereo visibly leans, that levels come fromgetBars, that height 1 matches the unset default and 2.5 lifts the peak by more than one screen, that output is deterministic, and that every page loads the helper.Math.random, missing script tag).npm run smoke: PASS on 2026-10-11, exit 0, isolated--user-data-dir. 60 visualizer modes drawn (includingstereotrails), 41 backgrounds, 40/40 effects, 18/18 transitions. The real profile was not used.npm run bench, vsync on, 1080p, Iris Xe (original commit): 58.2 / 60.0 / 58.4 fps with p95 16.9 ms over three runs. In the same runs the Goniometer read 59.4 / 60.0 and Bouncing Balls 60.0.For the reviewer
docs/screenshots/modes-visualizer.jpgshows 60 modes.tests/copyright-headers.test.jsrequires.🤖 Generated with Claude Code