PR #24533 opened by AYOUB NABIL BOUBAGRAT (ayoubnabil) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24533 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24533.patch
short silent inputs produce NaNs because the linear path computes an infinite gain. use unity gain when the peak is zero and keep the behavior unchanged for nonzero input. added a FATE test that fails before the fix and passes after. >From ec1fa9c9025736ee888de71fbfb6b1fccbc85610 Mon Sep 17 00:00:00 2001 From: Ayoub Nabil Boubagrat <[email protected]> Date: Wed, 16 Sep 2026 11:37:59 +0200 Subject: [PATCH] avfilter/af_loudnorm: preserve silence in the short-input linear path Signed-off-by: Ayoub Nabil Boubagrat <[email protected]> --- libavfilter/af_loudnorm.c | 19 ++++++++++++++++--- tests/fate/filter-audio.mak | 5 +++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/libavfilter/af_loudnorm.c b/libavfilter/af_loudnorm.c index 7ca3f2e6f2..386e3fb7b6 100644 --- a/libavfilter/af_loudnorm.c +++ b/libavfilter/af_loudnorm.c @@ -458,9 +458,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) true_peak = tmp; } - offset = pow(10., (s->target_i - global) / 20.); - offset_tp = true_peak * offset; - s->offset = offset_tp < s->target_tp ? offset : s->target_tp / true_peak; + /* Digital silence has no true peak. global is -inf, so offset is + * +inf and true_peak * offset is 0 * inf, a NaN; the comparison below + * is false for a NaN, so s->offset takes target_tp / 0 == +inf and + * every output sample comes out 0 * inf, again NaN. + * + * Only a zero peak is a problem. A signal quieter than the -70 LUFS + * absolute gate also reports global == -inf, but it has a peak, so + * the branch below still yields target_tp / true_peak and scales it + * up to the true peak ceiling as intended. */ + if (true_peak <= 0.) { + s->offset = 1.; + } else { + offset = pow(10., (s->target_i - global) / 20.); + offset_tp = true_peak * offset; + s->offset = offset_tp < s->target_tp ? offset : s->target_tp / true_peak; + } s->frame_type = LINEAR_MODE; } diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index b5c27daf1c..d490264c3f 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -205,6 +205,11 @@ fate-filter-pan-channel-id-limit: REF = Input channel id 768 FATE_AFILTER-$(call ALLYES, LAVFI_INDEV AEVALSRC_FILTER SILENCEREMOVE_FILTER ARESAMPLE_FILTER) += fate-filter-silenceremove fate-filter-silenceremove: CMD = framecrc -auto_conversion_filters -f lavfi -i "aevalsrc=between(t\,1\,2)+between(t\,4\,5)+between(t\,7\,9):d=10:n=8192,silenceremove=start_periods=0:start_duration=0:start_threshold=0:stop_periods=-1:stop_duration=0:stop_threshold=-90dB:window=0:detection=avg" +FATE_AFILTER-$(call ALLYES, LAVFI_INDEV PCM_F64LE_DECODER AEVALSRC_FILTER LOUDNORM_FILTER ASTATS_FILTER NULL_MUXER) += fate-filter-loudnorm-silence +fate-filter-loudnorm-silence: CMD = run $(FFMPEG) -nostdin -hide_banner -f lavfi -i "aevalsrc=0:c=stereo:d=2:n=4096" -af "loudnorm,astats" -f null - +fate-filter-loudnorm-silence: CMP = grep +fate-filter-loudnorm-silence: REF = Number of NaNs: 0 + FATE_FILTER_STEREOTOOLS-$(call FRAMECRC) += fate-filter-stereotools FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, STEREOTOOLS ARESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_FILTER_STEREOTOOLS-yes) fate-filter-stereotools: SRC = $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
