feat: add radial FFT visualizer - #35
Merged
Merged
Conversation
Adds a full-screen visualizer panel (Waves icon in toolbar, Escape to close) with 64-band FFT-driven radial bars around the album art. - Rust: new `AnalysisSource` wraps the audio pipeline with RMS EMA and a 2048-sample Hann-windowed FFT (rustfft), writing log-spaced band magnitudes with attack/decay smoothing to a shared ArcSwap. Engine tick lowered to 50ms; a new `visualizer-data` event fires at 20Hz only while the panel is open (enable/disable commands gate it). - Frontend: canvas rAF loop interpolates toward incoming FFT bands for smooth motion between frames; radial wedge bars drawn with a glow gradient from the accent colour. Album art fades to 28% opacity and morphs to a circle while playing, returning on pause. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…gnette - Replace clearRect with an annulus-clipped decay fill so bars ghost out with a brief motion trail; the clip confines the fill to the bar ring so the center (behind the art) and canvas exterior stay transparent - Parse the active theme's --accent hex into HSL and shift hue ±25° across band index for each bar, keeping saturation and lightness from the theme so every palette stays recognizable - Switch the full-panel scrim from a uniform overlay to a horizontal gradient (darker at edges, lighter in center) so the blurred album art background glows through in the middle - Fix event-listener leak: store and call the unlisten fn from onVisualizerData in onDestroy Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ering - Add an "Outline" style that draws a smooth closed curve through the tip positions of the 64 bars using midpoint quadratic Bezier segments, giving a C1-continuous polar waveform with per-segment frequency-mapped hue - Outline uses only bands 6–57 (~40Hz–10kHz) spread evenly around the full circle, skipping the sub-bass and ultra-high bands that are typically silent and caused a visible flat gap where the curve closed at 12 o'clock - Outline decays at alpha 0.05 vs bars' 0.15 so ghost shapes accumulate into visible artifacts before clearing - Add a Dropdown in the top-left corner to switch between Bars and Outline; Escape inside the dropdown closes the list without closing the visualizer - Persist the selected style to localStorage (key: spudbox.visualizerStyle) so it survives closing and reopening the visualizer Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AnalysisSourcewrapper (replacingRmsSource) that computes a 2048-sample Hann-windowed FFT viarustffton every decoded frame, maps output into 64 log-spaced frequency bands with attack/decay smoothing, and writes both RMS and band magnitudes to lock-free shared atomicsvisualizer-dataevent fires at ~20Hz only while the panel is open, gated byplayback_enable_visualizer/playback_disable_visualizercommands to avoid overhead when closedrequestAnimationFrameloop interpolates toward incoming FFT bands between events for smooth motion; bars are drawn as radial wedge arcs with a glow gradient in the current theme's accent colourTest plan
cargo test --libpasses (117 tests including new FFT/RMS analysis tests)npm run checkandnpm run testpassScreencast.from.2026-07-11.22-01-19.mp4
Screencast.from.2026-07-12.09-08-05.mp4
closes #8
🤖 Generated with Claude Code