No description
  • Rust 95.5%
  • WGSL 3.3%
  • Just 0.8%
  • HTML 0.2%
  • Shell 0.2%
Find a file
2026-06-30 21:33:13 +00:00
.cargo feat(wasm): browser (WebAssembly/WebGPU) build target + re-add Exit button 2026-06-20 09:34:55 +02:00
.forgejo/workflows ci: warm the dynamic build via a persistent CARGO_TARGET_DIR (drop rust-cache) 2026-06-30 23:28:46 +02:00
assets Release v0.3.0 (#10) 2026-06-27 22:23:45 +00:00
examples Release v0.3.0-rc1 (#6) 2026-06-27 20:45:47 +00:00
scripts Release v0.3.0-rc1 (#6) 2026-06-27 20:45:47 +00:00
src fix: vsync frame cap follows the active monitor's refresh rate 2026-06-29 21:30:08 +02:00
tests wip commit 2026-06-24 00:16:44 +02:00
.actrc chore: WIP — pre-existing untracked files and tooling tweaks 2026-06-05 19:02:08 +02:00
.env.example fix(input): suppress shortcuts only while a text field is focused + CI mirror swap 2026-06-24 01:07:28 +02:00
.gitignore gitignore 2026-06-26 01:15:47 +02:00
.gitlab-ci.yml fix(ci): publish Pages without pipeline variables (avoids permission 400) 2026-06-20 20:14:58 +02:00
build.rs Restructure to Bevy-only architecture with build optimizations 2025-10-09 23:22:30 +02:00
Cargo.lock chore: release v0.3.2 2026-06-29 22:12:04 +00:00
Cargo.toml chore: release v0.3.2 2026-06-29 22:12:04 +00:00
CHANGELOG.md chore: release v0.3.2 2026-06-29 22:12:04 +00:00
CLAUDE.md ci: warm the dynamic build via a persistent CARGO_TARGET_DIR (drop rust-cache) 2026-06-30 23:28:46 +02:00
cliff.toml fix(ci): drive the Release PR with git-cliff (release-plz never opened one) 2026-06-29 23:59:44 +02:00
CONTRIBUTING.md Release v0.3.0-rc1 (#6) 2026-06-27 20:45:47 +00:00
Cross.toml Release v0.3.0-rc1 (#6) 2026-06-27 20:45:47 +00:00
index.html fix(wasm): disable wasm-opt — Trunk's binaryen rejects rustc bulk-memory ops 2026-06-20 14:43:14 +02:00
justfile fix(ci): drive the Release PR with git-cliff (release-plz never opened one) 2026-06-29 23:59:44 +02:00
LICENSE Implement Mesh2d rendering for spectrum and circle modes with opacity control 2025-10-09 20:27:32 +02:00
README.md fix(ci): forgejo-first release + headless render builds (gitlab can't block it) 2026-06-29 21:02:51 +02:00
rust-toolchain.toml ci: warm the dynamic build via a persistent CARGO_TARGET_DIR (drop rust-cache) 2026-06-30 23:28:46 +02:00
TODO.md feat(headless): vendor libopus as pure Rust (drop the system libopus dep) 2026-06-28 14:12:35 +02:00
Trunk.toml feat(wasm): browser file playback + dynamic canvas scaling 2026-06-20 10:00:02 +02:00

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 effects
  • assets/presets/orbit/eye.toml - Hypnotic center-focused design
  • assets/presets/orbit/wizzy.toml - High-energy chaotic motion
  • assets/presets/orbit/hazy.toml - Smooth, dreamy aesthetic
  • assets/presets/orbit/cracked.toml - Aggressive, glitchy style
  • assets/presets/orbit/washy.toml - Flowing, organic movement
  • assets/presets/orbit/blue.toml - Cool, calming color palette
  • assets/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 showcase
  • assets/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):

  1. 📋 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
  2. 🎯 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 effects
  • eye.toml - Hypnotic center-focused design
  • wizzy.toml - High-energy chaotic motion
  • hazy.toml - Smooth, dreamy aesthetic
  • cracked.toml - Aggressive, glitchy style
  • washy.toml - Flowing, organic movement
  • blue.toml - Cool, calming color palette
  • trippy.toml - Psychedelic visual journey

Background Mode (2 presets):

  • energy.toml - High-energy multi-pattern showcase
  • trippy.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:

  1. sets default values for any subset of settings (applied when the theme is imported), and
  2. 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 .toml theme 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 renderersoundy-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 30s45s

# --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 051, 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 with mesa-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:

  1. Open about:config and accept the warning.
  2. Set dom.webgpu.enabled to true.
  3. 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.enabled is true (above) and that about:support lists 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-vulkan if shown) and relaunch. Open chrome://gpu and confirm WebGPU: Hardware accelerated and Vulkan: Enabled. If needed, launch with --enable-unsafe-webgpu --enable-features=Vulkan, and ensure Vulkan drivers are installed (vulkaninfo succeeds). 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:

  1. [system] — Window, music, playlist, and UI state (never included in presets)
  2. Per-mode sections[spectrum], [orbit], [waveform], [cymatics], [background], each holding that mode's complete visual settings
  3. 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

  1. Start the application:

    cargo run --release
    
  2. 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
  3. Explore visualization modes:

    • Press M to cycle through modes
    • Watch how each mode responds differently to your music
  4. 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
  5. 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
  6. 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.toml and set msaa_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 checklist
  • CLAUDE.md - Developer documentation, architecture, full settings checklist
  • CHANGELOG.md - Notable changes per release
  • TODO.md - Planned features and known issues

📝 License

MIT License - See LICENSE file for details.


🙏 Acknowledgments

Built with:

  • Bevy — game engine, ECS, and the wgpu renderer
  • 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:


🎶 Transform your music into art. Start visualizing today!