Commit f60c669ce3 for ffmpeg
commit f60c669ce37ff80904cb3fc4040d964570ffe720
Author: Patrick Domack <patrickdk@patrickdk.com>
Date: Sun Nov 1 04:56:42 2026 -0500
avcodec/g723_1dec: round the reflection coefficient like the reference
The formant postfilter's tilt follows the first reflection coefficient
k of each subframe (DS2-Anywhere SPEC.md section 4.8.1, step 5). The
reference halves the autocorrelation R1 with a floor, divides its
magnitude by twice the top 16 bits of R0, caps it at 32767 and puts
the sign back. FFmpeg floors R1 / 4 and divides with truncation. For
some negative R1 the two differ by 1, and the smoothed tilt carries
the difference into the next subframes. This has been so since the
decoder was added in 2011.
Compute k as the reference does.
Over the 371 test streams, the last frame that differed from the
reference with the postfilter on now matches. All 371 streams decode
exactly as the reference does, with the postfilter on and off.
Frame 20 of saturation.tco comes from a stream where, in subframe 2,
the reference's k is -2389 and FFmpeg's -2390. With the postfilter on
and every G.723.1 fix but this one, the frame parts from the reference
at sample 183 by up to 3.
fate-g723_1-dec-11 decodes saturation.tco with the postfilter on. Its
ref matches the DS2-Anywhere G.723.1 decoder frame for frame. It fails
with any one of this fix, the formant postfilter fix, the synthesis
filter fix and the Annex A fix left out. fate-g723_1-dec-1 to -8 pass
unchanged.
Signed-off-by: Patrick Domack <patrickdk@patrickdk.com>
diff --git a/libavcodec/g723_1dec.c b/libavcodec/g723_1dec.c
index 5414bf8712..a4c5bdd1d4 100644
--- a/libavcodec/g723_1dec.c
+++ b/libavcodec/g723_1dec.c
@@ -690,7 +690,11 @@ static void formant_postfilter(G723_1_ChannelContext *p, int16_t *lpc,
/* Compute reflection coefficient */
temp = auto_corr[1] >> 16;
if (temp) {
- temp = (auto_corr[0] >> 2) / temp;
+ int r1 = auto_corr[0] >> 1;
+
+ temp = FFMIN(FFABS(r1) / (2 * temp), INT16_MAX);
+ if (r1 < 0)
+ temp = -temp;
}
p->reflection_coef = (3 * p->reflection_coef + temp + 2) >> 2;
temp = -p->reflection_coef >> 1 & ~3;
diff --git a/tests/fate/voice.mak b/tests/fate/voice.mak
index e71e95690c..fa35584ddb 100644
--- a/tests/fate/voice.mak
+++ b/tests/fate/voice.mak
@@ -53,6 +53,9 @@ fate-g723_1-dec-9: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/cng-
FATE_G723_1 += fate-g723_1-dec-10
fate-g723_1-dec-10: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/cng-erasures.tco -af aresample
+FATE_G723_1 += fate-g723_1-dec-11
+fate-g723_1-dec-11: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/saturation.tco -af aresample
+
FATE_G723_1 += fate-g723_1-dec-12
fate-g723_1-dec-12: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/saturation.tco -af aresample
diff --git a/tests/ref/fate/g723_1-dec-11 b/tests/ref/fate/g723_1-dec-11
new file mode 100644
index 0000000000..d76eec2979
--- /dev/null
+++ b/tests/ref/fate/g723_1-dec-11
@@ -0,0 +1,53 @@
+#tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout_name 0: mono
+0, 0, 0, 240, 480, 0x8c91e30f
+0, 240, 240, 240, 480, 0x8dc1f1f4
+0, 480, 480, 240, 480, 0x666fef0e
+0, 720, 720, 240, 480, 0xdcaf07db
+0, 960, 960, 240, 480, 0xdcecf37f
+0, 1200, 1200, 240, 480, 0xc4aaf297
+0, 1440, 1440, 240, 480, 0xdda2f146
+0, 1680, 1680, 240, 480, 0xdffae723
+0, 1920, 1920, 240, 480, 0xf91eebe2
+0, 2160, 2160, 240, 480, 0x5950f145
+0, 2400, 2400, 240, 480, 0x56d9ec81
+0, 2640, 2640, 240, 480, 0x10f5dbf2
+0, 2880, 2880, 240, 480, 0xd107e9d3
+0, 3120, 3120, 240, 480, 0xd609e69c
+0, 3360, 3360, 240, 480, 0xf7f4ecfe
+0, 3600, 3600, 240, 480, 0xf6a5ef56
+0, 3840, 3840, 240, 480, 0x09b7e4b6
+0, 4080, 4080, 240, 480, 0x567af88b
+0, 4320, 4320, 240, 480, 0x1cfefb42
+0, 4560, 4560, 240, 480, 0x17ceec74
+0, 4800, 4800, 240, 480, 0xdefff5e9
+0, 5040, 5040, 240, 480, 0x0447f824
+0, 5280, 5280, 240, 480, 0x252af234
+0, 5520, 5520, 240, 480, 0x7693f2c9
+0, 5760, 5760, 240, 480, 0x0c13f98b
+0, 6000, 6000, 240, 480, 0x03feeecc
+0, 6240, 6240, 240, 480, 0x1b5bf18d
+0, 6480, 6480, 240, 480, 0x3bd0f781
+0, 6720, 6720, 240, 480, 0xe76bf794
+0, 6960, 6960, 240, 480, 0x3d14f718
+0, 7200, 7200, 240, 480, 0xb07a0267
+0, 7440, 7440, 240, 480, 0xcb1eea36
+0, 7680, 7680, 240, 480, 0x3767e516
+0, 7920, 7920, 240, 480, 0xb8cd1660
+0, 8160, 8160, 240, 480, 0xbf330dd7
+0, 8400, 8400, 240, 480, 0x764be98e
+0, 8640, 8640, 240, 480, 0x2993e407
+0, 8880, 8880, 240, 480, 0xf1a6db54
+0, 9120, 9120, 240, 480, 0x0797e462
+0, 9360, 9360, 240, 480, 0x9b9bf011
+0, 9600, 9600, 240, 480, 0x67ceeb77
+0, 9840, 9840, 240, 480, 0xede5dd4a
+0, 10080, 10080, 240, 480, 0x7787f6e2
+0, 10320, 10320, 240, 480, 0x98ebfc01
+0, 10560, 10560, 240, 480, 0x1129e64c
+0, 10800, 10800, 240, 480, 0xd631e94f
+0, 11040, 11040, 240, 480, 0x3120f0d7
+0, 11280, 11280, 240, 480, 0xc07cf758