* [FFmpeg-devel] [PR] avfilter/af_loudnorm: fix slow gain ramp after initial silence (PR #21449)
@ 2026-01-13 15:27 realies via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: realies via ffmpeg-devel @ 2026-01-13 15:27 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: realies
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 <ffmpeg@reali.es>
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 -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-01-13 15:27 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-13 15:27 [FFmpeg-devel] [PR] avfilter/af_loudnorm: fix slow gain ramp after initial silence (PR #21449) realies via ffmpeg-devel
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git