[PR] avcodec/amrwbdec: implement SID/comfort noise support (PR #24003)

ssenthilnathan3 via ffmpeg-devel <[email protected]> Tue, 04 Aug 2026 11:30:43 -0000
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178584304456.59.3901172017361706203@29965ddac10e>
PR #24003 opened by ssenthilnathan3
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24003
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24003.patch

Add DTX comfort noise generation for AMR-WB SID frames.
Supports SID_FIRST, SID_UPDATE, and continues comfort noise
during NO_DATA frames in DTX mode.

Replaces the 'patchwelcome' stub with a full implementation
based on 3GPP TS 26.190, 26.192, and 26.201.


>From aa312d0e75e710806cd39ff2b7df0348efaee10d Mon Sep 17 00:00:00 2001
From: Senthilnathan <[email protected]>
Date: Tue, 4 Aug 2026 16:56:09 +0530
Subject: [PATCH] avcodec/amrwbdec: implement SID/comfort noise support

Add DTX comfort noise generation for AMR-WB SID frames.
Supports SID_FIRST, SID_UPDATE, and continues comfort noise
during NO_DATA frames in DTX mode.

Replaces the 'patchwelcome' stub with a full implementation
based on 3GPP TS 26.190, 26.192, and 26.201.
---
 libavcodec/amrwbdata.h | 132 +++++++++++++++++++++-
 libavcodec/amrwbdec.c  | 246 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 366 insertions(+), 12 deletions(-)

diff --git a/libavcodec/amrwbdata.h b/libavcodec/amrwbdata.h
index 95c0aaa37b..21d2535fda 100644
--- a/libavcodec/amrwbdata.h
+++ b/libavcodec/amrwbdata.h
@@ -669,6 +669,19 @@ static const uint16_t order_MODE_23k85[] = {
                               402, 437, 459,
      7,   AMR_OF(3, vq_gain),   1,  16,  42,  24,  36,  46,  28,
      4,   AMR_OF(3, hb_gain),  83,  82,  81,  80,
+      0
+};
+
+static const uint16_t order_MODE_SID[] = {
+     6,   AMR_BIT(isp_id[0]),   0,   1,   2,   3,   4,   5,
+     6,   AMR_BIT(isp_id[1]),   6,   7,   8,   9,  10,  11,
+     6,   AMR_BIT(isp_id[2]),  12,  13,  14,  15,  16,  17,
+     5,   AMR_BIT(isp_id[3]),  18,  19,  20,  21,  22,
+     5,   AMR_BIT(isp_id[4]),  23,  24,  25,  26,  27,
+     6,   AMR_BIT(isp_id[5]),  28,  29,  30,  31,  32,  33,
+     1,   AMR_BIT(isp_id[6]),  34,
+     1,   AMR_BIT(vad),        35,
+     4,   AMR_OF(0, adap),     36,  37,  38,  39,
      0
 };
 
@@ -682,7 +695,8 @@ static const uint16_t * const amr_bit_orderings_by_mode[] = {
     order_MODE_18k25,
     order_MODE_19k85,
     order_MODE_23k05,
-    order_MODE_23k85
+    order_MODE_23k85,
+    order_MODE_SID
 };
 
 // Extracted from 3GPP TS 26.173 V9.0.0 (qpisf_2s.tab)
@@ -1887,4 +1901,120 @@ static const uint16_t cf_sizes_wb[] = {
     40, 0, 0, 0, 0, 0, 0
 };
 
+// SID (comfort noise) ISF codebook tables from 3GPP TS 26.192 / reference code
+// All values in Q15
+
+static const int16_t dicoSID_isf_0[64 * 2] = {
+    -269, -673,  -222, -537,  -233, -430,  -138, -451,
+    -212, -331,  -192, -241,   -87, -231,  -191, -128,
+     -70, -106,  -164,   -6,    74, -179,    27,  -33,
+    -102,   74,  -162,  115,   -94,  172,    -6,  130,
+    -143,  234,    14,  218,   -65,  270,    88,  182,
+    -124,  341,   -44,  381,    38,  335,   117,  274,
+    -112,  454,    74,  431,    -5,  488,   175,  384,
+     -83,  561,   122,  529,    21,  601,   229,  481,
+     231,  303,   226,  608,   300,  372,   210,  187,
+     306,  265,   328,  473,   382,  331,   371,  132,
+     139,   58,   365,   21,   250,  -82,   443,  218,
+     483,  110,   426,  415,   579,  222,   518,  333,
+     573,  448,   455,  529,   685,  329,   332,  580,
+     595,  593,   468,  645,   762,  517,   326,  709,
+     485,  793,   130,  684,   671,  737,   354,  876,
+      88,  806,   -65,  706,   -35, 1016,   266, 1123
+};
+
+static const int16_t dicoSID_isf_1[64 * 3] = {
+    -824, -884, -949,  -805, -456, -418,  -442, -438, -541,
+    -217, -578, -793,  -168, -444, -582,  -287, -492, -274,
+    -552, -297, -300,  -163, -333, -358,  -370, -232, -232,
+    -175, -358, -159,  -381,  -21, -357,  -184, -159, -162,
+     -53, -191, -280,    18, -267, -215,  -138,   61, -283,
+      71,  -95, -294,    13, -156, -546,     0,  -83,  -79,
+      44,   97, -316,   178,  -52, -213,   222, -261, -422,
+     237, -118,  -44,   141,  145, -132,   363,   81, -287,
+     213,   65,   34,  -107,   94,   -5,    91,  -29,  126,
+    -355,   51,  -41,  -219,  -76,  145,   -63,  100,  244,
+    -719,   44,   27,  -572, -124,  155,  -423,  133,  315,
+    -917,   71,  224,  -268,  318,  131,   -93, -190,  420,
+     -97,  122,  491,   -79,  317,  355,   130,  100,  325,
+      86, -293,  210,   133,  258,  161,   176,  -73,  465,
+     195,  300,  384,   348,   22,  221,   376,  183,  409,
+     377,  286,  202,   242,  213,  659,   257,  565,  248,
+     344,  408,  -76,   405,  440,  509,   612,  385,  379,
+     536,  607,  216,   -56,  582,  192,   100,  517,  567,
+    -365,  448,  445,   728,  347,   10,   505,  357,  759,
+     636,  582,  658,   335,  517,  852,   378,  809,  572,
+    -195,  878,  829,   529,  707,  987,   918,  726,  392,
+    1250,  997, 1063
+};
+
+static const int16_t dicoSID_isf_2[64 * 3] = {
+    -805, -838, -774,  -522, -627, -828,  -477, -486, -603,
+    -295, -481, -634,  -366, -384, -393,  -186, -414, -396,
+    -237, -394, -106,  -252, -202, -275,   -61, -177, -442,
+     -84, -198, -199,  -179, -125,  -31,   -72,  -47, -163,
+    -298, -220,  215,   -64, -168,  251,  -133,  156,  -59,
+     -30,   -2,  127,    54,   66,  -61,  -233,   21,  251,
+     209,  -50,   32,    33,  194,  136,  -117,  -18,  475,
+     202,   46,  309,   256,  185,   53,    35,  200,  390,
+     200,  263,  242,  -216,  302,  294,   128,  358,    0,
+      19,  431,  287,   224,  447,  280,   367,  165,  213,
+     397,  314,  319,   383,  379,   75,   277,  325,  462,
+     394,  505,  334,   251,   98, -213,   450,  153,  448,
+     565,  226,   76,   470,  383,  502,   635,  390,  278,
+     237,  135,  620,   342,  401,  649,   331,  551,  518,
+     130,  418,  592,   531,  306,  737,   729,  389,  580,
+     497,  557,  699,   296,  383,  874,   283,  624,  759,
+     126,  622,  476,   559,  595,  472,   382,  770,  616,
+     719,  613,  745,   540,  639,  928,   517,  826,  801,
+     684,  811,  604,   752,  786,  857,   933,  661,  350,
+     694,  450, 1061,   562,  911, 1051,   824,  813, 1104,
+     758, 1047,  882,  1140,  917,  889,  1039, 1246, 1426,
+    1483, 1666, 1876
+};
+
+static const int16_t dicoSID_isf_3[32 * 4] = {
+    -776, -854, -891, -920,  -552, -610, -663, -741,
+    -321, -370, -476, -565,   274, -160, -456,  201,
+     265,   67, -160, -306,    -8, -210,   79,  272,
+     163,  236,  307,  308,   578,  317,   64,  298,
+      -9,  197,  342,  620,   343,  232,  314,  622,
+     173,  149,  548,  527,   356,  370,  481,  376,
+     135,  444,  488,  556,   391,  471,  487,  653,
+     228,  424,  576,  835,   422,  372,  722,  682,
+     295,  673,  693,  635,   539,  596,  590,  449,
+     475,  618,  659,  818,   735,  517,  491,  673,
+     602,  346,  257,  877,   625,  635,  849,  720,
+     727,  818,  698,  595,   653,  481,  690, 1139,
+     814,  762,  704,  908,   507,  747,  898,  936,
+     848,  855,  924,  785,   646, 1037,  882,  795,
+     772,  845, 1024, 1151,  1133,  983,  818,  921,
+     940, 1068, 1252, 1302,  1588, 1767, 1718, 1513
+};
+
+static const int16_t dicoSID_isf_4[32 * 4] = {
+    -810, -879, -945, -254,   248,  184,  671,  128,
+     288,  703,  918,   99,   658,  558,  662,  219,
+     552,  585,  910,  208,   559,  804,  759,  119,
+     606,  774,  921, -139,   782,  761,  748,  208,
+     756,  708,  983,   56,   544,  864, 1010,  152,
+     737,  698,  987,  299,   771,  924,  879,  103,
+     536,  785,  961,  405,   667,  916,  801,  328,
+     738,  705,  773,  439,   823,  871,  992,  355,
+     640, 1004, 1052,  369,   724,  822,  949,  597,
+     415,  655,  729,  482,  1009,  896,  793,  363,
+     908,  803,  687,  -25,  1016,  838, 1011,  189,
+     947, 1112,  942,  222,   914, 1049,  981,  527,
+     956,  987, 1011, -120,   781, 1049, 1121,   92,
+    1178, 1053,  884,   47,  1123, 1059, 1182,  118,
+     933,  972, 1277,  357,  1109,  918, 1101,  503,
+    1039, 1286, 1220,  317,  1351, 1207, 1010,  326
+};
+
+/** Mean ISF vector for comfort noise in Q15 */
+static const int16_t isf_noise_mean[LP_ORDER] = {
+    478, 1100, 2213, 3267, 4219, 5222, 6198, 7240,
+    8229, 9153, 10098, 11108, 12144, 13184, 14165, 3803
+};
+
 #endif /* AVCODEC_AMRWBDATA_H */
diff --git a/libavcodec/amrwbdec.c b/libavcodec/amrwbdec.c
index 3557b4709d..3fbecfa368 100644
--- a/libavcodec/amrwbdec.c
+++ b/libavcodec/amrwbdec.c
@@ -96,6 +96,15 @@ typedef struct AMRWBContext {
     CELPFContext                       celpf_ctx; ///< context for filters for CELP-based codecs
     CELPMContext                       celpm_ctx; ///< context for fixed point math operations
 
+    float               sid_isf[LP_ORDER];      ///< decoded SID ISF for comfort noise
+    float               sid_isf_prev[LP_ORDER]; ///< previous SID ISF
+    float               sid_log_en;             ///< SID log energy (log2)
+    float               sid_log_en_prev;        ///< previous SID log energy
+    int                 sid_valid_data;         ///< whether valid SID parameters exist
+    int                 sid_dith_flag;          ///< CN dithering flag
+    int                 dtx_since_last_sid;     ///< frames since last SID update
+    int                 dtx_state;              ///< 0=SPEECH, 1=DTX active
+
 } AMRWBContext;
 
 typedef struct AMRWBChannelsContext {
@@ -138,6 +147,14 @@ static av_cold int amrwb_decode_init(AVCodecContext *avctx)
         ff_acelp_vectors_init(&ctx->acelpv_ctx);
         ff_celp_filter_init(&ctx->celpf_ctx);
         ff_celp_math_init(&ctx->celpm_ctx);
+
+        for (i = 0; i < LP_ORDER; i++)
+            ctx->sid_isf[i] = ctx->sid_isf_prev[i] = isf_init[i] * (1.0f / (1 << 15));
+        ctx->sid_log_en = ctx->sid_log_en_prev = -14.0f;
+        ctx->sid_valid_data = 0;
+        ctx->sid_dith_flag = 0;
+        ctx->dtx_since_last_sid = 0;
+        ctx->dtx_state = 0;
     }
 
     return 0;
@@ -1109,6 +1126,35 @@ static void update_sub_state(AMRWBContext *ctx)
             LP_ORDER_16k * sizeof(float));
 }
 
+/**
+ * Decode ISF parameters from SID comfort noise codebook.
+ *
+ * @param[in]  indices           Array of 5 codebook indices
+ * @param[out] isf_q              Decoded ISF vector (Q15, not normalized)
+ */
+static void decode_sid_isf(const uint16_t *indices, float *isf_q)
+{
+    int i;
+
+    for (i = 0; i < 2; i++)
+        isf_q[i] = dicoSID_isf_0[indices[0] * 2 + i] * (1.0f / (1 << 15));
+
+    for (i = 0; i < 3; i++)
+        isf_q[i + 2] = dicoSID_isf_1[indices[1] * 3 + i] * (1.0f / (1 << 15));
+
+    for (i = 0; i < 3; i++)
+        isf_q[i + 5] = dicoSID_isf_2[indices[2] * 3 + i] * (1.0f / (1 << 15));
+
+    for (i = 0; i < 4; i++)
+        isf_q[i + 8] = dicoSID_isf_3[indices[3] * 4 + i] * (1.0f / (1 << 15));
+
+    for (i = 0; i < 4; i++)
+        isf_q[i + 12] = dicoSID_isf_4[indices[4] * 4 + i] * (1.0f / (1 << 15));
+
+    for (i = 0; i < LP_ORDER; i++)
+        isf_q[i] += isf_noise_mean[i] * (1.0f / (1 << 15));
+}
+
 static int amrwb_decode_frame(AVCodecContext *avctx, AVFrame *frame,
                               int *got_frame_ptr, AVPacket *avpkt)
 {
@@ -1143,14 +1189,6 @@ static int amrwb_decode_frame(AVCodecContext *avctx, AVFrame *frame,
         if (!ctx->fr_quality)
             av_log(avctx, AV_LOG_ERROR, "Encountered a bad or corrupted frame\n");
 
-        if (ctx->fr_cur_mode == NO_DATA || !ctx->fr_quality) {
-            /* The specification suggests a "random signal" and
-               "a muting technique" to "gradually decrease the output level". */
-            av_samples_set_silence(&frame->extended_data[ch], 0, frame->nb_samples, 1, AV_SAMPLE_FMT_FLT);
-            buf += expected_fr_size;
-            buf_size -= expected_fr_size;
-            continue;
-        }
         if (ctx->fr_cur_mode > MODE_SID) {
             av_log(avctx, AV_LOG_ERROR,
                    "Invalid mode %d\n", ctx->fr_cur_mode);
@@ -1164,9 +1202,195 @@ static int amrwb_decode_frame(AVCodecContext *avctx, AVFrame *frame,
             return AVERROR_INVALIDDATA;
         }
 
-        if (ctx->fr_cur_mode == MODE_SID) { /* Comfort noise frame */
-            avpriv_request_sample(avctx, "SID mode");
-            return AVERROR_PATCHWELCOME;
+        if (ctx->fr_cur_mode == NO_DATA || !ctx->fr_quality) {
+            if (ctx->sid_valid_data) {
+                /* In DTX mode: continue comfort noise from last SID params */
+                ctx->dtx_state = 1;
+                ctx->dtx_since_last_sid++;
+            } else {
+                av_samples_set_silence(&frame->extended_data[ch], 0,
+                                       frame->nb_samples, 1, AV_SAMPLE_FMT_FLT);
+            }
+            if (ctx->sid_valid_data) {
+                float *sub_buf;
+                float sid_lpc[LP_ORDER];
+                double sid_isp[LP_ORDER];
+                float sid_isf[LP_ORDER];
+                int fi;
+
+                memcpy(sid_isf, ctx->sid_isf, LP_ORDER * sizeof(float));
+                sid_isf[LP_ORDER - 1] *= 2.0;
+                ff_acelp_lsf2lspd(sid_isp, sid_isf, LP_ORDER);
+                ff_amrwb_lsp2lpc(sid_isp, sid_lpc, LP_ORDER);
+
+                for (fi = 0; fi < 4; fi++) {
+                    float noise_exc[AMRWB_SFR_SIZE];
+                    float synth_exc[AMRWB_SFR_SIZE];
+                    float *samples_az_ptr = &ctx->samples_az[LP_ORDER];
+                    float hb_exc[AMRWB_SFR_SIZE_16k];
+                    float hb_samples_buf[AMRWB_SFR_SIZE_16k];
+                    float hb_gain;
+                    float cn_gain;
+                    float exc_scale;
+
+                    for (i = 0; i < AMRWB_SFR_SIZE; i++)
+                        noise_exc[i] = 32768.0 - (uint16_t) av_lfg_get(&ctx->prng);
+
+                    exc_scale = powf(2.0, ctx->sid_log_en - 2.0);
+                    cn_gain = sqrtf(exc_scale / (AMRWB_SFR_SIZE));
+                    for (i = 0; i < AMRWB_SFR_SIZE; i++)
+                        noise_exc[i] *= cn_gain;
+
+                    ctx->celpf_ctx.celp_lp_synthesis_filterf(
+                        samples_az_ptr, sid_lpc, noise_exc, AMRWB_SFR_SIZE, LP_ORDER);
+
+                    de_emphasis(&ctx->samples_up[UPS_MEM_SIZE],
+                                samples_az_ptr, PREEMPH_FAC, ctx->demph_mem);
+
+                    ctx->acelpf_ctx.acelp_apply_order_2_transfer_function(
+                        &ctx->samples_up[UPS_MEM_SIZE],
+                        &ctx->samples_up[UPS_MEM_SIZE],
+                        hpf_zeros, hpf_31_poles, hpf_31_gain,
+                        ctx->hpf_31_mem, AMRWB_SFR_SIZE);
+
+                    sub_buf = buf_out + fi * AMRWB_SFR_SIZE_16k;
+                    upsample_5_4(sub_buf, &ctx->samples_up[UPS_FIR_SIZE],
+                                 AMRWB_SFR_SIZE_16k, &ctx->celpm_ctx);
+
+                    memcpy(synth_exc, noise_exc, AMRWB_SFR_SIZE * sizeof(float));
+
+                    ctx->acelpf_ctx.acelp_apply_order_2_transfer_function(
+                        hb_samples_buf, &ctx->samples_up[UPS_MEM_SIZE],
+                        hpf_zeros, hpf_400_poles, hpf_400_gain,
+                        ctx->hpf_400_mem, AMRWB_SFR_SIZE);
+
+                    hb_gain = find_hb_gain(ctx, hb_samples_buf, 0, 1);
+
+                    scaled_hb_excitation(ctx, hb_exc, synth_exc, hb_gain);
+
+                    memcpy(ctx->lp_coef[fi], sid_lpc, LP_ORDER * sizeof(float));
+
+                    hb_synthesis(ctx, fi, &ctx->samples_hb[LP_ORDER_16k],
+                                 hb_exc, ctx->isf_cur, ctx->isf_past_final);
+
+                    hb_fir_filter(hb_samples_buf, bpf_6_7_coef,
+                                  ctx->bpf_6_7_mem,
+                                  &ctx->samples_hb[LP_ORDER_16k]);
+
+                    /* Add the low and high frequency bands */
+                    for (i = 0; i < AMRWB_SFR_SIZE_16k; i++)
+                        sub_buf[i] = (sub_buf[i] + hb_samples_buf[i]) * (1.0f / (1 << 15));
+
+                    update_sub_state(ctx);
+                }
+            }
+            buf += expected_fr_size;
+            buf_size -= expected_fr_size;
+            continue;
+        }
+
+        if (ctx->fr_cur_mode == MODE_SID) {
+            AMRWBFrame *cf = &ctx->frame;
+            float sid_isf_dec[LP_ORDER];
+            double sid_isp[LP_ORDER];
+            int is_sid_update;
+            int fi;
+            float *sub_buf;
+
+            ff_amr_bit_reorder((uint16_t *) cf, sizeof(AMRWBFrame),
+                               buf + header_size, amr_bit_orderings_by_mode[ctx->fr_cur_mode]);
+
+            decode_sid_isf(cf->isp_id, sid_isf_dec);
+            ff_set_min_dist_lsf(sid_isf_dec, MIN_ISF_SPACING, LP_ORDER - 1);
+
+            is_sid_update = cf->vad != 0;
+
+            if (is_sid_update) {
+                ctx->sid_log_en = ((int)cf->isp_id[5]) * (1.0f / 2.625f) *
+                                  (1 << (15 - 6)) / (1 << 15);
+                ctx->sid_dith_flag = cf->isp_id[6];
+                ctx->sid_valid_data = 1;
+                ctx->dtx_since_last_sid = 0;
+
+                memcpy(ctx->sid_isf, sid_isf_dec, LP_ORDER * sizeof(float));
+            } else {
+                memcpy(ctx->sid_isf, sid_isf_dec, LP_ORDER * sizeof(float));
+                ctx->sid_valid_data = 1;
+                ctx->dtx_since_last_sid = 0;
+            }
+
+            ctx->dtx_state = 1;
+
+            memcpy(ctx->isf_cur, ctx->sid_isf, LP_ORDER * sizeof(float));
+
+            sid_isf_dec[LP_ORDER - 1] *= 2.0;
+            ff_acelp_lsf2lspd(sid_isp, sid_isf_dec, LP_ORDER);
+
+            for (fi = 0; fi < 4; fi++)
+                ff_amrwb_lsp2lpc(sid_isp, ctx->lp_coef[fi], LP_ORDER);
+
+            for (fi = 0; fi < 4; fi++) {
+                float noise_exc[AMRWB_SFR_SIZE];
+                float synth_exc[AMRWB_SFR_SIZE];
+                float *samples_az_ptr = &ctx->samples_az[LP_ORDER];
+                float hb_exc[AMRWB_SFR_SIZE_16k];
+                float hb_samples_buf[AMRWB_SFR_SIZE_16k];
+                float hb_gain;
+                float exc_scale, cn_gain;
+
+                for (i = 0; i < AMRWB_SFR_SIZE; i++)
+                    noise_exc[i] = 32768.0 - (uint16_t) av_lfg_get(&ctx->prng);
+
+                exc_scale = powf(2.0, ctx->sid_log_en - 2.0);
+                cn_gain = sqrtf(exc_scale / AMRWB_SFR_SIZE);
+                for (i = 0; i < AMRWB_SFR_SIZE; i++)
+                    noise_exc[i] *= cn_gain;
+
+                ctx->celpf_ctx.celp_lp_synthesis_filterf(
+                    samples_az_ptr, ctx->lp_coef[fi], noise_exc,
+                    AMRWB_SFR_SIZE, LP_ORDER);
+
+                de_emphasis(&ctx->samples_up[UPS_MEM_SIZE],
+                            samples_az_ptr, PREEMPH_FAC, ctx->demph_mem);
+
+                ctx->acelpf_ctx.acelp_apply_order_2_transfer_function(
+                    &ctx->samples_up[UPS_MEM_SIZE],
+                    &ctx->samples_up[UPS_MEM_SIZE],
+                    hpf_zeros, hpf_31_poles, hpf_31_gain,
+                    ctx->hpf_31_mem, AMRWB_SFR_SIZE);
+
+                sub_buf = buf_out + fi * AMRWB_SFR_SIZE_16k;
+                upsample_5_4(sub_buf, &ctx->samples_up[UPS_FIR_SIZE],
+                             AMRWB_SFR_SIZE_16k, &ctx->celpm_ctx);
+
+                memcpy(synth_exc, noise_exc, AMRWB_SFR_SIZE * sizeof(float));
+
+                ctx->acelpf_ctx.acelp_apply_order_2_transfer_function(
+                    hb_samples_buf, &ctx->samples_up[UPS_MEM_SIZE],
+                    hpf_zeros, hpf_400_poles, hpf_400_gain,
+                    ctx->hpf_400_mem, AMRWB_SFR_SIZE);
+
+                hb_gain = find_hb_gain(ctx, hb_samples_buf, 0, 1);
+
+                scaled_hb_excitation(ctx, hb_exc, synth_exc, hb_gain);
+
+                hb_synthesis(ctx, fi, &ctx->samples_hb[LP_ORDER_16k],
+                             hb_exc, ctx->isf_cur, ctx->isf_past_final);
+
+                hb_fir_filter(hb_samples_buf, bpf_6_7_coef,
+                              ctx->bpf_6_7_mem,
+                              &ctx->samples_hb[LP_ORDER_16k]);
+
+                /* Add the low and high frequency bands */
+                for (i = 0; i < AMRWB_SFR_SIZE_16k; i++)
+                    sub_buf[i] = (sub_buf[i] + hb_samples_buf[i]) * (1.0f / (1 << 15));
+
+                update_sub_state(ctx);
+            }
+
+            buf += expected_fr_size;
+            buf_size -= expected_fr_size;
+            continue;
         }
 
         ff_amr_bit_reorder((uint16_t *) &ctx->frame, sizeof(AMRWBFrame),
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]