From 5fae14d68d3b96dd033f1920ab0239cc0680b4af Mon Sep 17 00:00:00 2001 From: vicrodh Date: Thu, 5 Mar 2026 11:16:05 -0600 Subject: [PATCH] fix(audio): stop updating live gain during refinement passes Only write to gain atomic on initial measurement. Refinements now update the cache only, preventing audible volume changes within a single track. Inter-track normalization still works via cached values. --- crates/qbz-audio/src/loudness_analyzer.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/qbz-audio/src/loudness_analyzer.rs b/crates/qbz-audio/src/loudness_analyzer.rs index bde4df507..3b43ffea1 100644 --- a/crates/qbz-audio/src/loudness_analyzer.rs +++ b/crates/qbz-audio/src/loudness_analyzer.rs @@ -211,15 +211,19 @@ impl AnalyzerState { self.track_id, phase, measured_lufs, self.target_lufs, adjustment_db, gain ); - // Update shared atomic - if let Some(ref atomic) = self.gain_atomic { - atomic.store(gain.to_bits(), Ordering::Relaxed); + // Only update the live gain on the FIRST measurement. + // Refinements update the cache only — applying gain changes mid-song + // causes audible volume fluctuations within a single track. + if !self.initial_done { + if let Some(ref atomic) = self.gain_atomic { + atomic.store(gain.to_bits(), Ordering::Relaxed); + } } self.samples_at_last_measure = self.samples_fed; self.initial_done = true; - // Cache the result (store the adjustment in dB, not the linear gain) + // Always cache the latest measurement for next playback cache.set(self.track_id, adjustment_db, 0.0, "ebur128"); } }