PR #21449 opened by realies URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21449 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21449.patch
## Summary - Fixes fade-in artifact when audio begins with silence (3+ seconds) - When first 3s of audio is below `measured_thresh`, the filter set `above_threshold=0` - This caused gain to ramp at only 0.5 dB/second instead of applying correct gain immediately - Audio took 20+ seconds to reach steady state after silence ended ## Root Cause In INNER_FRAME processing with `above_threshold=0`: - Gain was increased via `prev_delta *= 1.0058` (~0.05 dB per 100ms) - `above_threshold` only changed to 1 when OUTPUT reached target - Created a catch-22: output couldn't reach target because gain was too low ## Fix When input short-term loudness exceeds `measured_thresh`, immediately transition to normal gain mode by: 1. Setting `above_threshold = 1` 2. Reinitializing all `delta[]` values with the correct gain This ensures proper gain is applied immediately when audio starts after silence. ## Test plan - [x] Tested with 11 different silence durations (0s to 10s) followed by constant tone - [x] All tests pass with fix (previously 5 failed with silence >= 3s) - [x] LUFS compliance tests pass - [x] True peak compliance tests pass - [x] Limiter and gating tests pass Fixes: https://github.com/slhck/ffmpeg-normalize/issues/146 >From 5f0547f2e61cd472fc12715d301b2d608d11a945 Mon Sep 17 00:00:00 2001 From: realies <[email protected]> Date: Tue, 13 Jan 2026 16:48:14 +0200 Subject: [PATCH] avfilter/af_loudnorm: fix slow gain ramp after initial silence When audio begins with silence (below measured_thresh), the filter would set above_threshold=0 and then slowly ramp up gain at only 0.5 dB/second when audio content started. This caused audible fade-in artifacts taking 20+ seconds to reach steady state. The bug was in the INNER_FRAME processing: when above_threshold=0, gain was increased via prev_delta *= 1.0058 (~0.05 dB per 100ms), and above_threshold only changed to 1 when OUTPUT reached target. This created a catch-22: output couldn't reach target because gain was too low. Fix: When input short-term loudness exceeds measured_thresh, immediately transition to normal gain mode by: 1. Setting above_threshold = 1 2. Reinitializing all delta[] values with the correct gain This ensures proper gain is applied immediately when audio starts after silence, rather than slowly ramping via Gaussian smoothing of stale values. Fixes fade-in artifacts reported in: - https://github.com/slhck/ffmpeg-normalize/issues/146 --- libavfilter/af_loudnorm.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libavfilter/af_loudnorm.c b/libavfilter/af_loudnorm.c index 432b9710a5..5c047cb57d 100644 --- a/libavfilter/af_loudnorm.c +++ b/libavfilter/af_loudnorm.c @@ -543,14 +543,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) ff_ebur128_relative_threshold(s->r128_in, &relative_threshold); if (s->above_threshold == 0) { - double shortterm_out; - - if (shortterm > s->measured_thresh) - s->prev_delta *= 1.0058; - - ff_ebur128_loudness_shortterm(s->r128_out, &shortterm_out); - if (shortterm_out >= s->target_i) + if (shortterm > s->measured_thresh) { + /* Input has exceeded threshold, transition to normal gain mode. + * Reinitialize all delta values with the correct gain to ensure + * immediate proper gain application when audio starts after + * silence, rather than slowly ramping up via Gaussian smoothing + * of stale values. */ + double env_st = s->target_i - shortterm; + double new_delta = pow(10., env_st / 20.); + for (int i = 0; i < 30; i++) + s->delta[i] = new_delta; + s->prev_delta = new_delta; s->above_threshold = 1; + } } if (shortterm < relative_threshold || shortterm <= -70. || s->above_threshold == 0) { -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
