Skip to content

feat(mixer): live multi-color LUFS meters per deck - #88

Merged
robmorgan merged 1 commit into
mainfrom
feat/lufs-deck-meters
Aug 2, 2026
Merged

feat(mixer): live multi-color LUFS meters per deck#88
robmorgan merged 1 commit into
mainfrom
feat/lufs-deck-meters

Conversation

@robmorgan

Copy link
Copy Markdown
Owner

Summary

Replaces the flat green 6 px peak bars between the channel strips with 12 px segmented LED meters on a −40..0 LUFS scale, driven by the new MomentaryLoudness streaming BS.1770-4 meter from timestretch-rs 0.10.0 (robmorgan/timestretch-rs#26, merged).

  • Audio callback (audio.rs): one MomentaryLoudness per deck (all 3, audition included) fed the post-trim pre-fader stereo pair per frame — the same tap as the peak meter. Published per block into a new DeckShared::meter_lufs atomic; no extra ballistics (the 400 ms window is its own integration). Meters reset on processor adoption and warm-start seeks so transitions don't ghost. The meter's push/read paths are allocation- and lock-free (verified against the ebur128 source), keeping the callback rules intact.
  • Widget (app.rs): 3 px LED segments lit bottom-up, each colored by its own position — green below −14 LUFS, amber (ACCENT) to −9, red above — reusing the master/CPU meter palette. A light marker sits at the track's integrated LUFS (gain-match decks by aligning bars to markers), a red top strip flags peaks at the ceiling, and hover shows the numeric momentary/integrated values. Mixer panel widens 130 → 144 px.
  • Worker (worker.rs): analysis now runs measure_loudness on the original interleaved signal (BS.1770 sums per-channel energies; the mono downmix reads ~3 dB low) and stores it in the artifact. Old rows deserialize with loudness: None — previously analyzed tracks just show no marker until re-analyzed.
  • The marker reads pending_artifact before deck.pre_analysis, since a fresh analysis waits for a non-playing moment to reach the engine but the marker is display-only.

Testing

  • 5 new unit tests in timestretch-rs, including an oracle test that streaming frame-by-frame matches a one-shot Mode::M measurement within 0.01 LU.
  • cargo test --workspace (117 passed), cargo check --workspace --all-targets, cargo +nightly fmt --all.
  • Manual: launched with a real track — ladder rises green→amber during loud sections, integrated marker rendered at the analyzed −9.7 LUFS, deck B (empty) shows a dark bar with no marker, no underruns in the log, layout intact at 144 px.

🤖 Generated with Claude Code

Replace the flat green peak bars in the mixer cluster with segmented
LED meters on a -40..0 LUFS scale, driven by timestretch's new
MomentaryLoudness streaming BS.1770-4 meter (400 ms window) fed the
post-trim pre-fader signal in the audio callback. Zones: green below
-14 LUFS, amber to -9, red above; a red strip at the top flags peaks
at the ceiling.

The analysis worker now measures integrated loudness on the original
interleaved signal (the mono downmix reads ~3 dB low) and stores it in
the artifact; the meter draws it as a reference marker so two decks can
be gain-matched by aligning bars to markers. The marker prefers a
completed analysis still pending engine adoption, since it is
display-only. Tracks analyzed before this change show no marker until
re-analyzed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@robmorgan
robmorgan merged commit 2cf7bf6 into main Aug 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant