A real-time audio visualizer that runs in the terminal. Built with Rust using cpal for audio capture and ratatui for rendering. A companion Swift binary handles system audio capture via ScreenCaptureKit, so you can visualize whatever’s playing on your Mac — Apple Music, Spotify, YouTube, anything.

Four visualization modes: spectrum bars with logarithmic frequency binning, a waveform plot, a zero-crossing-triggered oscilloscope, and a stereo mode that mirrors left and right channels above and below a center line. Press m to cycle through them.

The spectrum uses a dual-resolution FFT — 4096-point for bass below 200Hz (~11.7Hz bin spacing), 2048 samples zero-padded to 4096 for mids and highs (better time resolution). Logarithmic frequency binning gives more resolution in the bass, less in the treble. An equalizer curve compensates for natural 1/f roll-off so highs don’t disappear. Bars have gravity-based fall-off — they snap up instantly but fall with acceleration, giving a natural decay feel. An auto-sensitivity system with fast attack and slow multiplicative recovery normalizes the display so it uses the full height regardless of volume.

Features

  • Spectrum — frequency bars with 1/8th-cell precision via Unicode block characters, color gradient interpolation, and gravity
  • Waveform — amplitude plot drawn as line segments on a canvas
  • Oscilloscope — zero-crossing triggered waveform for stable display
  • Stereo — dual-channel bars growing up (left) and down (right) from center, with half-cell precision
spectrum modewaveform mode
oscilloscope modestereo mode
  • 7 themes — classic, fire, ocean, purple, matrix, synthwave, mono
  • Settings menu — smoothing, monstercat envelope, noise gate, gradient mode, sensitivity — all persisted to ~/.config/termwave/config.toml
  • Sensitivity control — adjustable sensitivity percentage displayed in the title bar, useful for fine-tuning the display for different volume levels
  • Device switching — swap between mic input and system audio at runtime
  • Monstercat smoothing — connects bar tops in a smooth curve with exponential falloff
  • Now playing — shows the currently playing Apple Music track in the status bar, polled every 3 seconds via AppleScript
  • Bar customization — adjustable bar width (1–8 columns) and spacing (0–4 columns) via settings menu or CLI flags

Architecture

Two-process design. The Rust binary handles everything visual: CLI parsing, FFT analysis, smoothing, and terminal rendering at 60fps. The Swift binary (termwave-tap) only captures system audio — it uses ScreenCaptureKit to grab the system audio stream, mixes to mono, and writes raw f32 samples to stdout. The Rust side spawns it as a subprocess and reads from its stdout.

Audio data flows through shared ring buffers (Arc<Mutex<Vec<f32>>>) — one mono buffer for spectrum/wave/scope modes, plus a stereo pair for the stereo visualization. The render thread reads these each frame, runs the FFT, bins and smooths the results, and draws.

Key bindings

KeyAction
mCycle mode
dSelect audio device
tSelect color theme
sSettings menu
Up / DownIncrease / decrease sensitivity
Right / LeftWider / narrower bars
?Help
q / EscQuit

Code