// AUDIO_HAXOR — WALKTHROUGH

Tutorial index Docs hub
Progress
15 / 19

15.Real-time visualizer — F4

Six live tiles driven by either the audio-engine subprocess or a Web Audio AnalyserNode fallback. Drag to reorder, double-click to go fullscreen, pause the FFT to freeze a snapshot, and trust the idle backoff to stay invisible when you're not looking.

Visualizer tab with six live tiles — FFT, oscilloscope, spectrogram, stereo, levels, bands
assets/visualizers.png · Visualizer tab

Open the tab

Press F4 or click Visualizer. The tab uses a grid layout with two display modes held in _vizMode (frontend/js/visualizer.js):

  • Grid mode'all'. All six tiles visible at once at 20 FPS.
  • Single mode — one tile fills the full viewport at 30 FPS.

Double-click any tile to toggle single-mode / grid-mode. Drag tiles by their handle to reorder — drops emit a toast.reordered_viz_tiles toast (frontend/js/visualizer.js:1597) and the order persists via the shared drag-reorder utility.

The six tiles

  1. FFT — frequency spectrum bars. Parameters: fftSmoothing = 0.8 (exponential moving average between frames), fftLogScale = true (log frequency axis). Pause the animation with the dedicated button (toggleFftAnimationPaused(), ~line 1393) to freeze a snapshot in _vizFftFrozenCopy for close inspection.
  2. Oscilloscope — real-time waveform trace. Two modes controlled by oscilloscopeTriggeredSweep: free-run or triggered sweep (aligns the trace to a zero-crossing like a scope). _vizOscLastTrigger carries the previous trigger index across frames so the trace stays stable even when a buffer contains no new crossing.
  3. Spectrogram — scrolling waterfall plot of the spectrum over time, driven by a ring buffer (_vizSpectrogramData) with write index _vizSpectrogramIdx. Scroll speed is spectrogramSpeed = 1.
  4. Stereo — per-channel L/R amplitude meters with peak hold.
  5. Levels — overall RMS + peak. Peak hold is a decay timer (_vizPeakHold / _vizPeakTimer) controlled by levelsHold = true.
  6. Bands — 10 equal-loudness bands with peak indicators per band (bandsCount = 10).

Data sources — engine vs Web Audio

The visualizer prefers the AudioEngine subprocess's playback_status.spectrum bins and falls back to the Web Audio AnalyserNode.

  • Engine spectrum (preferred)window._engineSpectrumU8, a Uint8Array populated from the engine's playback_status response (see frontend/js/audio-engine.js). Sample rate in window._engineSpectrumSrHz. Optional overall peak in window._enginePlaybackPeak. FFT order is configurable (8–15 = 256–32 768 bins) via the Audio Engine tab; off skips the spectrum altogether for minimum CPU.
  • Shim_vizEngineShim wraps the engine array in an AnalyserNode-compatible façade with matching frequencyBinCount, fftSize, getByteFrequencyData(arr), and a synthesized getFloatTimeDomainData(arr) for the oscilloscope tile.
  • Fallback_analyser from audio.js, set in ensureAudioGraph(). 2048-point FFT = 1024 frequency bins.

Net result: any audio going through the app — Web Audio preview, engine playback, video audio route (engine mode), input-stream monitoring — lights up every tile with the same visuals.

Frame scheduling

The animation loop (_vizRAF) runs as requestAnimationFrame and is throttled to a target FPS based on mode:

  • _VIZ_FPS_SINGLE = 30
  • _VIZ_FPS_ALL = 20

Last frame time is tracked in _vizLastFrame; if not enough time has passed, the frame is skipped instead of forcing a redraw.

Idle backoff

When the app goes into heavy-CPU idle mode (minimized, hidden, unfocused), ui-idle.js emits ui-idle-heavy-cpu. The visualizer sets _vizBackoffTimer and defers its animation loop so GPU/CPU drops to zero while the tab isn't visible. It resumes instantly when you bring the window back.

Customization

  • Frame rate cap — Settings → Visualizer FPS cap, 10–60 Hz.
  • Smoothing_vizParams.fftSmoothing, default 0.8. No UI exposed; changeable at runtime through the DevTools console.
  • Colors — every tile uses CSS variables (--cyan, --magenta, --accent, etc.) so color-scheme switches (step 17) flow through immediately.
  • Right-click a tile for its context menu — close, fullscreen, reset, export snapshot.
TipThe FFT pause button is the underrated one — freeze a spectrum snapshot of a tricky sample, then sort your library for similar frequency content with smart playlists. Works especially well for finding kicks with matching harmonic profiles.