- Rust 95.5%
- WGSL 3.3%
- Just 0.8%
- HTML 0.2%
- Shell 0.2%
|
All checks were successful
release-pr / release-pr (push) Successful in 3s
Reviewed-on: #21 |
||
|---|---|---|
| .cargo | ||
| .forgejo/workflows | ||
| assets | ||
| examples | ||
| scripts | ||
| src | ||
| tests | ||
| .actrc | ||
| .env.example | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| build.rs | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| cliff.toml | ||
| CONTRIBUTING.md | ||
| Cross.toml | ||
| index.html | ||
| justfile | ||
| LICENSE | ||
| README.md | ||
| rust-toolchain.toml | ||
| TODO.md | ||
| Trunk.toml | ||
Soundy Bits
A real-time audio visualization application built with Rust and Bevy 0.19. Transform your music into stunning visuals with GPU-accelerated effects, multiple visualization modes, a fully customizable preset system, and shareable curator themes — and render any preset to a video file headlessly, with GPU-accelerated H.264 encoding.
▶ Live demo (browser, WebGPU): https://soundy-bits-dc14e6.gitlab.io/ · https://public.pages.ssy.dk/soundy-bits/
Features:
- 🎨 Five distinct visualization modes (Spectrum, Orbit, Waveform, Cymatics, Background)
- 🌫️ Vector SDF background layer — resolution-independent procedural patterns + a film-grade filter stack (duotone, bloom, posterize, halftone, scanlines, grain, chromatic…)
- 🎲 Curator themes / "seeds" — shareable styles that set defaults and shape the randomizer; importable as a TOML file or a compact paste-able seed code, with an in-app theme editor
- 🎵 Support for audio files (MP3, OGG, WAV, FLAC), live microphone, and system-audio loopback
- 🎭 GPU-accelerated post-processing effects (blur, glow, streak, chromatic aberration, edge spectrum)
- 🎬 Headless render-to-video — render any preset to an H.264 + Opus MP4 with no window or display (ideal for a server), using hardware NVENC on NVIDIA (~7× real-time at 1080p60) or a multi-threaded software encoder as the fallback
- 💾 TOML-based preset system with per-mode settings
- 🎛️ Real-time parameter adjustment with immediate visual feedback
- 🔊 Stereo visualization with independent L/R channel rendering
- 📋 Full playlist support with drag-and-drop reordering
- ⚡ Optimized rendering - single draw call per visualization mode
- 🎨 Developer-curated presets included in
assets/presets/
🎬 Visualization Modes
Press M to cycle through five unique visualization modes:
1. 🌈 Spectrum Mode
A classic frequency spectrum analyzer with modern optimizations.
Features:
- 64 frequency bars rendered in a single draw call (Mesh2d)
- Rainbow gradient coloring across the frequency spectrum
- Vertical mirroring option - bars grow from center outward
- Adjustable opacity (0.0-1.0) for layering effects
- Configurable frequency boost (0.5-10.0x) to emphasize mids/highs
- Stereo mode: Dual side-by-side spectrums with harmonic color separation
Best for: Clean, traditional visualization with customizable intensity
2. 🔮 Orbit Mode
An audio-reactive orbital system with dynamic elements.
Features:
- Center hub that pulses with bass energy
- 6-24 orbital triangular elements rotating around the hub
- Orbit radius expands with bass (adjustable sensitivity 0.0-2.0)
- Rotation speed driven by mid frequencies (adjustable sensitivity 0.0-2.0)
- Element sizes react to high frequencies
- Optional waveform ring display around the orbit
- Stereo mode: Dual side-by-side orbit systems
- Corner visualizations: Beat Pulse, Frequency Rings, Lissajous (stereo)
Best for: Complex, mesmerizing animations with multiple reactive elements
⭐ Try the curated presets:
assets/presets/orbit/the-biz-stereo.toml- Stereo showcase with intense visual effectsassets/presets/orbit/eye.toml- Hypnotic center-focused designassets/presets/orbit/wizzy.toml- High-energy chaotic motionassets/presets/orbit/hazy.toml- Smooth, dreamy aestheticassets/presets/orbit/cracked.toml- Aggressive, glitchy styleassets/presets/orbit/washy.toml- Flowing, organic movementassets/presets/orbit/blue.toml- Cool, calming color paletteassets/presets/orbit/trippy.toml- Psychedelic visual journey
3. 〰️ Waveform Mode
Oscilloscope-style time-domain visualization showing raw audio waveform.
Features:
- Linear mode: Horizontal waveform across the screen (1024 samples)
- Radial mode (W key): Circular "shooting star" pattern (512 samples)
- Adjustable scale (0.5-2.0x) for amplitude/radius control
- Stereo mode: Top/bottom split for L/R channels in linear, dual radial patterns
- Corner visualizations: Beat Pulse, Frequency Rings, Lissajous (stereo)
Best for: Seeing the raw audio signal, perfect for analyzing transients and dynamics
4. 🌀 Cymatics Mode
A Chladni-plate simulation — standing-wave nodal patterns driven by the audio's frequency bands.
Features:
- HeatGrid, Particles, or Both render styles
- Square / Circular / Hexagonal symmetry
- Configurable grid size, mode count, damping, and per-band (bass/mid/high) mode weights
- Heat palettes (Mono, Gradient, Inverse) with gamma/contrast controls
- Particle field with drift, jitter, size, and trail-fade
Best for: Organic, physics-driven patterns that breathe with the music
5. 🌌 Background Mode
Spiral and galaxy sprite patterns that dance to your music.
Features:
Spiral Patterns:
- 10-100 sprites arranged in customizable spiral formations
- 1-7 spiral patterns distributed in a circle
- Configurable speed (0.1-10.0), tightness (0.1-2.0), and size (5-100)
- Bass and mid frequency influence (0.0-2.0 sensitivity each)
Galaxy Sprites:
- 5-100 rotating galaxies with 2-6 spiral arms each
- Deterministic placement: Same audio file = same galaxy positions every time
- File playback: Seeded from audio buffer for consistent visuals
- Microphone input: Random placement (no buffer, no seed)
- Configurable rotation speed (0.1-10.0) and size (10-200)
- Audio-reactive arm intensity and rotation
Color Modes (both patterns):
- 🌈 Rainbow: Full spectrum gradient
- 🔥 Energy Bands: Bass (red) → Mid (green) → High (blue)
- ⚪ Monochrome: Single color controlled by hue slider
⭐ Try the curated presets:
assets/presets/background/energy.toml- High-energy multi-pattern showcaseassets/presets/background/trippy.toml- Psychedelic spiral madness
Best for: Ambient, atmospheric visuals with complex layered patterns
🎨 Background Effects (Available in All Modes)
Tilemap - Scrolling Spectrogram
A frequency waterfall that can be layered behind any visualization mode.
Features:
- Real-time scrolling spectrogram (bass at bottom, highs at top)
- GPU shader-based rendering for ultra-efficient performance
- 7 essential controls:
- Opacity (0.0-1.0)
- Bass/Mid/High sensitivity (0.0-2.0 each)
- Beat flash intensity (0.0-2.0)
- Color mode (Rainbow, Heat, Energy Bands)
- Scroll speed (0.5-5.0)
- Hardcoded optimal defaults for logarithmic frequency mapping and vibrant colors
Enable it in the Tilemap controls of the background settings panel.
Vector SDF Layer — procedural patterns + film grade
A resolution-independent, per-pixel signed-distance-field pattern that scales crisply at any resolution and can layer over any mode, with a "the29nov-style" filter stack applied as a final pass.
Pattern types: Rings, Sunburst, Hex Grid, Nested Polygons, Moiré, Kaleidoscope — audio-reactive (scale/spokes/rotation driven by bass/mid/high), with adjustable scale, speed, domain-warp, and an in-shader echo/trail.
Filter stack: threshold/duotone (two-color), posterize, halftone (ordered dither), beat-gated invert, bloom/glow (the luminous highlights), chromatic split, scanlines, film grain, vignette, and flicker. Layer opacity crossfades the whole treatment over the scene.
Enable it in the Vector controls of the background section. Tune by hand, or — better — drive it from a curator theme (below).
✨ Visual Effects
All effects are GPU-accelerated and can be adjusted in real-time:
Post-Processing Effects
- Blur - Spatial blur shader (radius 1.0-20.0)
- Glow - Radial bloom effect (radius 0.1-10.0, intensity 1.0-4.0)
- Streak - Vertical energy beam trails (length 10.0-200.0, fade 0.5-0.95, toggle with S key)
- Chromatic Aberration - RGB color separation (intensity 0.0-0.5)
Edge Spectrum
GPU-accelerated frequency spectrum along all window edges (toggle with E key).
Features:
- Smooth interpolated bars with corner blending
- Configurable width (50-300 pixels)
- Three color modes: Rainbow, Energy Bands, Monochrome
Energy Color System
Dynamic hue shifts driven by frequency energy.
How it works:
- Bass energy → Shift toward red (+120° hue)
- High energy → Shift toward blue (-120° hue)
- Adjustable intensity (0.0-2.0)
- Applies to all rainbow/gradient-based visualizations
Stereo Visualization
When stereo audio is available, all modes support dual L/R channel rendering:
- Spectrum: Side-by-side frequency spectrums
- Orbit: Dual orbital systems
- Waveform: Split top/bottom (linear) or dual patterns (radial)
- Harmonic color separation with adjustable hue offset (0-60°)
Toggle with T key when stereo audio is loaded.
🎵 Audio Sources
File Playback
Load audio files in MP3, OGG, WAV, or FLAC formats.
Playlist System:
- Load multiple files to create a playlist (O key)
- Drag tracks to reorder within the playlist
- Drag tracks outside the playlist window to remove them
- Click any track to jump to it
- Visual indicator (▶ in green) shows currently playing track
- Auto-scroll: Playlist automatically centers the active track
- Position memory: Window position persisted across sessions
Playback Controls:
- Repeat Modes: Repeat single track, Repeat playlist, or play once
- Shuffle Modes:
- Off: Sequential playback
- Fair: Plays all tracks once before repeating (like Spotify)
- Random: True random - any track can play at any time
- Auto-Advance: Automatically plays next track when current ends
- Auto-Load: Optionally restore your last session on startup
Microphone Input
Real-time visualization from your default microphone (I key).
- Cross-platform audio capture via CPAL (Linux, macOS)
- Low-latency audio capture via CPAL
- Automatically switches to random galaxy placement (no seeded visuals)
💾 Preset System
Save and load complete visual configurations as shareable TOML files.
Quick Access
- L key - Load preset (opens file dialog)
- P key - Save preset (opens file dialog)
- 📁 Load and 💾 Save buttons in sidebar and ESC menu
Preset Load Modes
Choose how presets are applied in the ESC menu (Playback & Presets section):
-
📋 Load All Modes (default)
- Loads settings for all visualization modes (Spectrum, Orbit, Waveform, Cymatics, Background)
- Switches to the mode specified in the preset
- Best for complete visual style changes
-
🎯 Load Current Only
- Only loads settings for the currently active mode
- Keeps you in your current mode
- Best for fine-tuning one mode without affecting others
What's Included in Presets?
✅ Visual Settings (included):
- Current visualization mode
- Mode-specific settings (freq_boost, orbit_speed, etc.)
- All visual effects (blur, glow, streak, edge spectrum)
- Stereo settings, energy color, corner visualizations
- Background effects (tilemap, spiral, galaxy)
❌ System Settings (excluded):
- Window settings (VSync, fullscreen, resolution, MSAA)
- Music/Playlist (auto-load, playlist files, shuffle mode)
- UI state (debug info, hidden UI, window positions)
Why? Presets are portable and shareable. System settings stay on your machine.
Developer-Curated Presets
Explore professionally crafted visual styles in assets/presets/:
Orbit Mode (8 presets):
the-biz-stereo.toml- Stereo showcase with intense effectseye.toml- Hypnotic center-focused designwizzy.toml- High-energy chaotic motionhazy.toml- Smooth, dreamy aestheticcracked.toml- Aggressive, glitchy stylewashy.toml- Flowing, organic movementblue.toml- Cool, calming color palettetrippy.toml- Psychedelic visual journey
Background Mode (2 presets):
energy.toml- High-energy multi-pattern showcasetrippy.toml- Psychedelic spiral madness
Preset Tips
- Store presets anywhere on your system
- Share presets with others - they're just TOML files!
- Edit presets manually for fine control (they're human-readable)
- Create preset collections organized by mood, genre, or style
- Each mode can have its own unique visual settings
🎲 Curator Themes (Seeds)
A theme is a portable, partial style that does two things:
- sets default values for any subset of settings (applied when the theme is imported), and
- constrains the randomizer — locks a toggle on/off, narrows a value to a range, or restricts a picker to an allowed set — so pressing R stays within a coherent style instead of producing noise.
Unlike a preset (a full snapshot), a theme only touches what it lists; everything else is left as-is.
Use it from the control panel or the ESC menu:
- Pick a built-in (Mono / the29nov, Neon, VHS, Cosmic) — the active theme's name shows next to the Randomize button.
- Import a
.tomltheme file, or paste a seed code and hit Apply. - Copy current → seed to snapshot your current look as a shareable code.
- Open the Theme Editor to author one: every option, grouped per mode, with a default value and a randomize range/constraint you can tune; changes live-preview.
The active theme persists across restarts and keeps governing Randomize until you Clear it. Seed codes are a compact, versioned, CRC-checked string — paste-and-share friendly.
⌨️ Keyboard Shortcuts
Global Controls
| Key | Action |
|---|---|
| M | Cycle visualization modes (Spectrum → Orbit → Waveform → Cymatics → Background) |
| O | Load audio file(s) (opens file dialog) |
| I | Toggle microphone input |
| Y | Toggle system-audio loopback capture (native only) |
| Space | Play/Pause audio |
| L | Load preset (opens file dialog) |
| P | Save preset (opens file dialog) |
| H | Hide/Show UI |
| Ctrl+H | Open/Close keybind reference overlay |
| D | Toggle debug info (FPS, resolution, buffer size) |
| F | Cycle window mode: windowed → borderless → exclusive fullscreen (native; cursor auto-hides after 2s in fullscreen) |
| ESC | Open/Close settings menu |
| Alt+F4 / Super+Q / Super+W | Quit the application (native only) |
Playback Controls
| Key | Action |
|---|---|
| ← / Media Previous | Previous track on tap; hold to seek backward (respects shuffle mode) |
| → / Media Next | Next track on tap; hold to seek forward (respects shuffle mode) |
| ↑ / ↓ | Volume up/down while playing — or navigate tracks when hovering the playlist |
| Enter | Play selected track (playlist) |
| Del | Remove selected track (playlist) |
| X | Cycle shuffle mode (Off → Fair → Random → Off) |
Mode-Specific Toggles
| Key | Action | Available In |
|---|---|---|
| S | Toggle streak effect | All modes |
| E | Toggle edge spectrum | All modes |
| B | Toggle background sprites (spiral/galaxy master) | All modes |
| W | Toggle radial waveform | Waveform only |
| C | Cycle corner visualizations | All modes |
| T | Toggle stereo mode | All modes (when stereo audio loaded) |
UI Shortcuts
| Key | Action |
|---|---|
| Ctrl+R | Reset current mode to default settings |
| R | Randomize all settings (mode-specific + effects) |
🖱️ Mouse Controls
UI Interaction
- Click buttons to toggle modes, load files, and activate features
- Drag sliders to adjust parameters in real-time with immediate visual feedback
- Hover tooltips provide helpful descriptions for all controls
Playlist
- Drag tracks vertically to reorder within the playlist
- Drag tracks outside the playlist window to remove them
- Click tracks to immediately jump to that song
- "Add Files" button to expand your playlist without clearing it
⬇️ Download & Live Demo
Try it in your browser (no install): the WebGPU build runs live at two hosts — https://soundy-bits-dc14e6.gitlab.io/ (GitLab Pages) and https://public.pages.ssy.dk/soundy-bits/ (Forgejo Pages). A WebGPU-capable browser is required — see Browser (WebAssembly) for Firefox setup.
Prebuilt binaries are attached to every tagged release on Forgejo and the GitLab mirror:
| Artifact | Platform |
|---|---|
soundy-bits-<version>-x86_64-linux.tar.gz |
Linux x86-64 |
soundy-bits-<version>-x86_64-linux-nvenc.tar.gz |
Linux x86-64 + NVIDIA NVENC — hardware H.264 for the headless renderer (NVIDIA hosts; software fallback elsewhere) |
soundy-bits-<version>-aarch64-linux.tar.gz |
Linux ARM64 |
soundy-bits-<version>-x86_64-linux-headless.tar.gz |
Linux x86-64, render-only — no GUI/live-audio deps, needs only a Vulkan driver |
soundy-bits-<version>-aarch64-linux-headless.tar.gz |
Linux ARM64, render-only (same) |
soundy-bits-<version>-wasm.zip |
Browser build (self-host the WebGPU demo) |
soundy-bits-<version>-SHA256SUMS.txt |
Checksums for the archives above |
Each archive bundles the binary, the assets/ directory, the README, and the LICENSE. Verify a
download with sha256sum -c soundy-bits-<version>-SHA256SUMS.txt.
Every binary is also a headless video renderer — soundy-bits render … turns a preset + audio
into an MP4 with no window or display (see Render to Video (Headless)).
The -nvenc build additionally encodes H.264 on NVIDIA hardware. The dedicated -headless builds
drop the GUI + live-audio deps entirely for render servers/containers — they need only a Vulkan driver
(libvulkan1 mesa-vulkan-drivers on Debian/glibc, vulkan-loader mesa-vulkan-swrast on Alpine/musl);
each archive's HEADLESS.md repeats this.
Prebuilt binaries are Linux only (x86-64 + ARM64). macOS and Windows are build-from-source (see below); Windows is currently untested.
🔧 Installation
Prerequisites
1. Install Rust
Download and install from https://rustup.rs/
Verify installation:
rustc --version
cargo --version
2. Platform-Specific Requirements
Windows is not supported right now — Windows builds have been pulled from the release matrix and there are no prebuilt Windows binaries. Building from source on Windows is currently untested.
These are the system libraries the desktop (GUI) build links: the audio stack (ALSA + PulseAudio),
the windowing/input stack (Wayland, X11/xcb, xkbcommon, udev), a Vulkan driver, and a C toolchain. (A
headless render-only build — cargo build --no-default-features --features diagnostics — needs none
of the audio or windowing libs; only a Vulkan driver + C compiler.)
Debian / Ubuntu (24.04+):
sudo apt update
sudo apt install build-essential pkg-config \
libasound2-dev libudev-dev libwayland-dev \
libxkbcommon-dev libpulse-dev \
libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
# Vulkan driver to actually render (pick for your GPU):
sudo apt install mesa-vulkan-drivers # Intel / AMD / software (lavapipe)
# NVIDIA: install the proprietary driver (e.g. the `nvidia-driver-###` package) instead.
Arch:
sudo pacman -S --needed base-devel pkgconf \
alsa-lib libpulse \
wayland libxkbcommon libxcb systemd-libs
# Vulkan loader + an ICD for your GPU:
sudo pacman -S --needed vulkan-icd-loader vulkan-radeon # AMD
# Intel: vulkan-intel · NVIDIA: nvidia-utils · software/lavapipe: vulkan-swrast
No libopus-dev / opus package needed — the render's Opus encoder is vendored pure Rust
(unsafe-libopus), and OpenH264's C builds via the base toolchain (build-essential / base-devel).
The app renders through Vulkan, so a Vulkan ICD for your GPU is required at runtime.
A running PulseAudio or PipeWire-Pulse server is required for system-audio loopback capture. Ubuntu 24.04 ships PipeWire by default:
# Verify a PulseAudio-compatible server is running
pactl info
# If missing, install one (pick one):
sudo apt install pipewire-pulse # modern, recommended on 24.04+
# or
sudo apt install pulseaudio
# Also install the ALSA→PipeWire bridge so cpal (which uses ALSA on Linux)
# can see PipeWire monitor sources for loopback capture:
sudo apt install pipewire-alsa
If loopback startup logs No PulseAudio monitor sources found even though
pactl info reports a running server, the ALSA→PipeWire bridge is missing.
pipewire-alsa fixes this. If you also see
ALSA lib pcm_oss.c ... Cannot open device /dev/dsp, no audio server is
running for your session — start it and retry.
Linux (Arch/Manjaro):
sudo pacman -S base-devel alsa-lib systemd-libs wayland
macOS:
- Xcode Command Line Tools (installs automatically when running cargo)
- Note: MSAA samples are limited to [1, 2, 4] on macOS. Default is 4.
🚀 Usage
Quick Start
# Clone the repository (Forgejo primary; GitLab mirror at gitlab.com/soundy-stuff/soundy-bits)
git clone https://git.ssy.dk/public/soundy-bits.git
cd soundy-bits
# Build and run (optimized)
cargo run --release
# Development build (faster compilation, slower runtime)
cargo run
Build Profiles
# Development - Fast compilation, debug symbols
cargo build
# Release - Optimized for speed, parallel compilation
cargo build --release
# Distribution - Maximum optimization, smallest binary
cargo build --profile dist --no-default-features
Using Just (Optional Task Runner)
Install Just from GitHub releases, then:
just # Build and run release
just run # Build and run dev (with dynamic linking)
just build # Build release
just build-dist # Build for distribution (max optimization)
just build-debug # Build debug
just clean # Clean build artifacts
Render to Video (Headless)
The same binary can render a clip straight to a video file with no window or display — handy on a headless server, or to capture a deterministic, reproducible clip of a preset:
soundy-bits render \
--input song.flac \
--preset my-preset.toml \
--out clip.mp4 \
--width 1920 --height 1080 --fps 60 \
--from 30 --to 45 # optional: render only 30s–45s
# --out ending in .mp4 -> H.264 video + Opus audio (in sync).
# --out as any other path -> a directory of PNG frames (no encoder needed).
# --gain <G> scales how reactive the visualization is (audio plays at normal volume).
# --encoder auto (default; hardware NVENC if present, else software) | hw | sw.
# --bitrate <M> NVENC target bitrate in Mbps (default: resolution-scaled, ~0.15 bits/pixel).
# --quality <QP> software encoder constant-quality 0–51, lower = better/bigger (default 22).
# --speed trade a little quality for faster software encoding.
# --software render on the CPU (Mesa lavapipe) instead of the GPU — for headless servers.
# --codec h264 (default) | av1 (planned).
Hardware encoding (NVIDIA): build with --features nvenc to encode H.264 on the GPU's NVENC
instead of the CPU. It needs only an NVIDIA driver at runtime (no CUDA toolkit to build), and is
auto-selected when present. Tune size/quality with --bitrate. A full song renders at ~7× real
time at 1080p60 on a recent NVIDIA GPU (≈420 fps; well above for smaller outputs). Without the
feature (or on non-NVIDIA GPUs) it uses the multi-threaded software encoder, which uses every CPU
core (multi-threaded H.264 + parallel colour conversion) and still renders faster than real time.
Its Opus audio encoder is vendored (pure-Rust unsafe-libopus), so the build needs no libopus-dev. Native-only —
the browser build doesn't include it. The render uses the GPU by default; on a headless server with
no GPU, install Mesa's software Vulkan (sudo apt install mesa-vulkan-drivers) — it's auto-selected
when it's the only adapter, or force it anywhere with --software (much slower).
Deploying headless on a server / container
The headless build is lean — cargo build --release --no-default-features --features diagnostics
drops the GUI + live-audio system libs entirely. At runtime it needs only a Vulkan driver (the
GPU's, or Mesa's software lavapipe with --software):
| Target | Provide at runtime |
|---|---|
| Debian/Ubuntu server (x86-64 or arm64) | libvulkan1 mesa-vulkan-drivers (software lavapipe), or your GPU's Vulkan driver |
| Alpine container (fully-static musl binary) | vulkan-loader mesa-vulkan-swrast — the static binary needs nothing else |
NVIDIA host (--features nvenc) |
the NVIDIA driver (libnvidia-encode.so.1 + libcuda) — the only extra dep |
Minimal Alpine image (software render, static binary):
FROM alpine:3.20
RUN apk add --no-cache vulkan-loader mesa-vulkan-swrast
COPY soundy-bits-headless /usr/local/bin/soundy-bits
ENTRYPOINT ["soundy-bits", "render"]
A static musl binary can only load musl Vulkan drivers (hence Alpine's
mesa-vulkan-swrast); on a glibc server use the glibc headless build withmesa-vulkan-drivers.
🌐 Browser (WebAssembly)
Soundy Bits also builds to WebAssembly and runs directly in the browser — same visualizers, same GPU effects, rendered on WebGPU. Hosted builds are live at https://soundy-bits-dc14e6.gitlab.io/ and https://public.pages.ssy.dk/soundy-bits/ if you'd rather not build it yourself.
Requirements
- A WebGPU-capable browser (see below — there is no WebGL2 fallback; the post-processing pipeline needs WebGPU).
- The wasm target and Trunk:
rustup target add wasm32-unknown-unknown
cargo install trunk
Build & serve
trunk serve # dev server at http://localhost:8080
trunk build --release # static bundle in dist/ for hosting
Serve over http://localhost (or HTTPS) — microphone capture requires a secure
context, which localhost satisfies. No special COOP/COEP headers are needed.
Enabling WebGPU
Firefox (recommended): WebGPU ships in Firefox 141+, but on Linux it is not yet on by default. Enable it once:
- Open
about:configand accept the warning. - Set
dom.webgpu.enabledtotrue. - Reload the page.
You can confirm it's live at about:support (search for "WebGPU") or by checking the
browser console for surface-creation errors.
Chromium-based browsers enable WebGPU by default and will "just work" — at the usual cost of running a Chromium-based browser. Your machine, your call.
Troubleshooting — "Unable to find a GPU"
If the page shows a "WebGPU isn't available" message (or the console panics with "Unable to find a GPU"), the browser has WebGPU but couldn't get a GPU adapter:
- Firefox: make sure
dom.webgpu.enabledistrue(above) and thatabout:supportlists a working graphics adapter. - Chromium-based browsers (Linux): WebGPU runs on Vulkan, which is often
blocklisted or disabled. Enable
chrome://flags/#enable-unsafe-webgpu(and#enable-vulkanif shown) and relaunch. Openchrome://gpuand confirm WebGPU: Hardware accelerated and Vulkan: Enabled. If needed, launch with--enable-unsafe-webgpu --enable-features=Vulkan, and ensure Vulkan drivers are installed (vulkaninfosucceeds). Headless/VM sessions without GPU passthrough won't work.
What works in the browser
- ✅ Microphone input — press
I, grant the permission prompt, and the visualizers react to live audio. - ✅ All visualization modes, post-processing, themes, and UI.
- ✅ Settings persist via the browser's
localStorage. - ⛔ System-audio loopback is not available — no browser exposes an API for it. (Use the native build for loopback.)
The frame rate is capped to your display's refresh (typically 60 FPS) by the
browser's requestAnimationFrame — this is the browser doing vsync, not a
performance limit, and there is no way to exceed it from WebAssembly.
⚙️ Configuration
Config File Location
The application auto-generates a TOML configuration file:
- Linux:
~/.config/soundy-bits/config.toml - Windows:
%APPDATA%\soundy-bits\config\config.toml - macOS:
~/Library/Application Support/soundy-bits/config.toml
Auto-Save Behavior
Settings are automatically saved:
- Every 2 seconds during runtime
- On application exit (Ctrl+C, ESC key, or window close)
Config Structure
The config file is organized into:
[system]— Window, music, playlist, and UI state (never included in presets)- Per-mode sections —
[spectrum],[orbit],[waveform],[cymatics],[background], each holding that mode's complete visual settings - Background sub-sections —
[background.spiral],[background.galaxy],[background.tilemap],[background.vector]
Per-Mode Settings
Each visualization mode can have completely different visual settings:
- Example: Heavy blur in Spectrum, intense glow in Orbit, clean Waveform
- Enable "Auto-Save Mode Overrides" in the UI to activate per-mode settings
- Settings save to the currently active mode's config section
For complete configuration documentation, see CONFIG.md.
🎯 Getting Started
First Launch
-
Start the application:
cargo run --release -
Load some music:
- Press O to open a file dialog
- Select one or more audio files (MP3, OGG, WAV, FLAC)
- Or press I to use your microphone
-
Explore visualization modes:
- Press M to cycle through modes
- Watch how each mode responds differently to your music
-
Try a curated preset:
- Press L to load a preset
- Navigate to
assets/presets/orbit/the-biz-stereo.toml - Enable stereo mode (T key) for full effect
-
Customize your experience:
- Press ESC to open the settings menu (or Ctrl+H for the keybind reference)
- Adjust sliders in real-time
- Press S to enable streak effect
- Press E to enable edge spectrum
- Press B to enable background sprites
-
Save your creation:
- Press P to save your current settings as a preset
- Choose a location and filename
- Load it anytime with L key
🐛 Troubleshooting
macOS MSAA Crash
If the app crashes on startup with "Sample count 8 is not supported":
- Edit
config.tomland setmsaa_samples = 4 - macOS/WebGPU only supports [1, 2, 4] samples
Audio Not Playing
- Check default audio device in system settings
- Verify audio file format is supported (MP3, OGG, WAV, FLAC)
- For microphone: Check system microphone permissions
Performance Issues
- Reduce blur radius (major performance impact)
- Reduce glow radius/intensity
- Disable streak effect (S key)
- Disable edge spectrum (E key)
- Lower MSAA samples in settings menu
Config Issues
- Delete config file to regenerate with defaults
- Check file permissions in config directory
- Validate TOML syntax if manually edited
📚 Additional Documentation
CONTRIBUTING.md- Contributor quick-start: dev workflow + the settings-integration checklistCLAUDE.md- Developer documentation, architecture, full settings checklistCHANGELOG.md- Notable changes per releaseTODO.md- Planned features and known issues
📝 License
MIT License - See LICENSE file for details.
🙏 Acknowledgments
Built with:
- Bevy — game engine, ECS, and the
wgpurenderer - Rodio — audio decode + playback
- CPAL — cross-platform audio I/O
- rustfft — FFT spectrum analysis
- bevy_egui — immediate-mode UI
- rfd — async file dialogs
Headless render-to-video:
- openh264 — H.264 software encoder (vendored C, built via
cc) - muxide — pure-Rust MP4 muxer
- unsafe-libopus via the opus-rs fork — Opus encoder from libopus transpiled to pure Rust (c2rust), so there's no system
libopusdependency - nvidia-video-codec-sdk + cudarc — optional NVENC hardware H.264
🎶 Transform your music into art. Start visualizing today!