From 348500c8df3d2a5affc9d59ed0863158021bf707 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 22 Apr 2026 11:17:16 +0200 Subject: [PATCH 01/17] Add switch NONBE_FIX_ISSUE_2518 to increase Q_new to mitigate the regression from issue #2518. --- lib_com/options.h | 1 + lib_enc/ivas_core_pre_proc_front_fx.c | 2 ++ lib_enc/ivas_core_pre_proc_fx.c | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/lib_com/options.h b/lib_com/options.h index 33519e38f..e4c95bf52 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -92,6 +92,7 @@ #define NONBE_FIX_ISSUE_2206_AVOID_OVERFLOW_MSVQ_Interpol_Tran_fx /* FhG: Fix saturation crash in MSVQ_Interpol_Tran_fx() */ #define NONBE_FIX_ISSUE_2206_SWB_EXPERIMENT_FIX_2527 /* Fix crash from issue #2527 */ #define NONBE_FIX_2507 /* Fix porting error in SQ_gain_estimate_fx() */ +#define NONBE_FIX_ISSUE_2518 /* FhG: Fix issue 2518, noise during ACELP switching from 16KHz to 12k8Hz */ #define FIX_FLOAT_1539_G192_FORMAT_SWITCH /* VA/Nokia: reintroduce format switching for g192 bitstreams */ #define HARMONIZE_2499_CONFIGUREFDCNGDEC /* FhG: basop issue 2499: harmonoize configureFdCngDec */ #define FIX_BASOP_2530_IVAS_DECISION_MAT /* VA: Fix ambiguous usage of extract_l() */ diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index 80116aa5b..81125e048 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -776,7 +776,9 @@ void pre_proc_front_ivas_fx( /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ *Q_new = s_min( *Q_new, st->q_inp ); #endif +#ifndef NONBE_FIX_ISSUE_2518 *Q_new = add( *Q_new, Q_inp_const ); +#endif move16(); Copy_Scale_sig32_16( sig_out, preemp_start_idx, preemp_len, sub( add( *Q_new, 1 ), st->q_inp ) ); /* Q_new */ Scale_sig( old_inp_12k8_fx, (Word16) ( preemp_start_idx - old_inp_12k8_fx ), sub( *Q_new, st->q_inp ) ); /* Q_new */ diff --git a/lib_enc/ivas_core_pre_proc_fx.c b/lib_enc/ivas_core_pre_proc_fx.c index 8f1a7b60b..3cf42e3d9 100644 --- a/lib_enc/ivas_core_pre_proc_fx.c +++ b/lib_enc/ivas_core_pre_proc_fx.c @@ -607,6 +607,11 @@ void pre_proc_ivas_fx( ivas_compute_core_buffers_fx( st, &inp_16k_fx, old_inp_16k_fx, new_inp_resamp16k_fx, input_frame, last_element_mode, sr_core_tmp, ener_fx, A_fx, Aw_fx, epsP_fx, lsp_new_fx, lsp_mid_fx, Q_old_inp_16k, Q_r, &Q_inp_16k ); +#ifdef NONBE_FIX_ISSUE_2518 + Q_inp_12k8 = add( Q_inp_12k8, norm_arr( old_inp_12k8_fx, L_INP_12k8 ) ); + scale_sig( old_inp_12k8_fx, L_INP_12k8, sub( Q_inp_12k8, *Q_new ) ); +#endif + IF( GT_16( Q_inp_16k, Q_inp_12k8 ) ) { #ifdef NONBE_FIX_ISSUE_2206 -- GitLab From c10d62a671e0a79fa97c9a6a862b8324ee4caa7b Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 22 Apr 2026 16:40:50 +0200 Subject: [PATCH 02/17] Add st->hLPDmem->q_lpd_old_exc into account of Q_new calculation to avoid saturation issue of EXC buffers. --- lib_com/options.h | 2 +- lib_enc/ivas_core_pre_proc_front_fx.c | 7 ++++++- lib_enc/ivas_core_pre_proc_fx.c | 6 ++++++ lib_enc/updt_enc_fx.c | 17 +++++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index e4c95bf52..7f703dd20 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -92,7 +92,7 @@ #define NONBE_FIX_ISSUE_2206_AVOID_OVERFLOW_MSVQ_Interpol_Tran_fx /* FhG: Fix saturation crash in MSVQ_Interpol_Tran_fx() */ #define NONBE_FIX_ISSUE_2206_SWB_EXPERIMENT_FIX_2527 /* Fix crash from issue #2527 */ #define NONBE_FIX_2507 /* Fix porting error in SQ_gain_estimate_fx() */ -#define NONBE_FIX_ISSUE_2518 /* FhG: Fix issue 2518, noise during ACELP switching from 16KHz to 12k8Hz */ +#define NONBE_FIX_ISSUE_2518 /* FhG: Fix issue 2518, noise during ACELP switching from 16KHz to 12k8Hz by improving Q_new calculation. */ #define FIX_FLOAT_1539_G192_FORMAT_SWITCH /* VA/Nokia: reintroduce format switching for g192 bitstreams */ #define HARMONIZE_2499_CONFIGUREFDCNGDEC /* FhG: basop issue 2499: harmonoize configureFdCngDec */ #define FIX_BASOP_2530_IVAS_DECISION_MAT /* VA: Fix ambiguous usage of extract_l() */ diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index 81125e048..25445d201 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -776,7 +776,12 @@ void pre_proc_front_ivas_fx( /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ *Q_new = s_min( *Q_new, st->q_inp ); #endif -#ifndef NONBE_FIX_ISSUE_2518 +#ifdef NONBE_FIX_ISSUE_2518 + if ( st->hLPDmem != NULL ) + { + *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_old_exc, 1 ) ); + } +#else *Q_new = add( *Q_new, Q_inp_const ); #endif move16(); diff --git a/lib_enc/ivas_core_pre_proc_fx.c b/lib_enc/ivas_core_pre_proc_fx.c index 3cf42e3d9..019c1e058 100644 --- a/lib_enc/ivas_core_pre_proc_fx.c +++ b/lib_enc/ivas_core_pre_proc_fx.c @@ -1305,6 +1305,12 @@ void ivas_compute_core_buffers_fx( shift = sub( norm_s( inp_max ), 1 /* headroom */ ); #endif #ifdef NONBE_FIX_ISSUE_2206 +#ifdef NONBE_FIX_ISSUE_2518 + if ( st->hLPDmem != NULL ) + { + *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_old_exc, 1 ) ); + } +#endif *Q_new = s_min( shift, Q_MAX ); move16(); #else diff --git a/lib_enc/updt_enc_fx.c b/lib_enc/updt_enc_fx.c index 65f997c63..5c8b4ddd8 100644 --- a/lib_enc/updt_enc_fx.c +++ b/lib_enc/updt_enc_fx.c @@ -34,8 +34,25 @@ void updt_enc_fx( GSC_ENC_HANDLE hGSCEnc = st->hGSCEnc; TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; +#ifdef NONBE_FIX_2507 + /* update old excitation buffer */ + IF( st->element_mode > EVS_MONO ) + { + Word16 tmp; + + tmp = norm_arr( &old_exc[st->L_frame], L_EXC_MEM ); + Copy_Scale_sig_nosat( &old_exc[st->L_frame], hLPDmem->old_exc, L_EXC_MEM, tmp ); + hLPDmem->q_lpd_old_exc = add( hLPDmem->q_lpd_old_exc, tmp ); + move16(); + } + ELSE + { + Copy( &old_exc[st->L_frame], hLPDmem->old_exc, L_EXC_MEM ); + } +#else /* update old excitation buffer */ Copy( &old_exc[st->L_frame], hLPDmem->old_exc, L_EXC_MEM ); +#endif test(); test(); IF( !st->Opt_AMR_WB && st->hBWE_TD != NULL ) -- GitLab From 4b5a6c87385bf96f8438b2266b04081cb3b644c1 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 22 Apr 2026 16:44:58 +0200 Subject: [PATCH 03/17] Fix msvc warning. --- lib_enc/updt_enc_fx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib_enc/updt_enc_fx.c b/lib_enc/updt_enc_fx.c index 5c8b4ddd8..5979a83d3 100644 --- a/lib_enc/updt_enc_fx.c +++ b/lib_enc/updt_enc_fx.c @@ -38,8 +38,6 @@ void updt_enc_fx( /* update old excitation buffer */ IF( st->element_mode > EVS_MONO ) { - Word16 tmp; - tmp = norm_arr( &old_exc[st->L_frame], L_EXC_MEM ); Copy_Scale_sig_nosat( &old_exc[st->L_frame], hLPDmem->old_exc, L_EXC_MEM, tmp ); hLPDmem->q_lpd_old_exc = add( hLPDmem->q_lpd_old_exc, tmp ); -- GitLab From fdc9c1a77c291e77e3f6cb045febbdbc865f8122 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 22 Apr 2026 17:32:14 +0200 Subject: [PATCH 04/17] Undo normalization of old_inp_12k8_fx after ivas_compute_core_buffers_fx(). Fixes regression. --- lib_enc/ivas_core_pre_proc_fx.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib_enc/ivas_core_pre_proc_fx.c b/lib_enc/ivas_core_pre_proc_fx.c index 019c1e058..a7fc62354 100644 --- a/lib_enc/ivas_core_pre_proc_fx.c +++ b/lib_enc/ivas_core_pre_proc_fx.c @@ -607,11 +607,6 @@ void pre_proc_ivas_fx( ivas_compute_core_buffers_fx( st, &inp_16k_fx, old_inp_16k_fx, new_inp_resamp16k_fx, input_frame, last_element_mode, sr_core_tmp, ener_fx, A_fx, Aw_fx, epsP_fx, lsp_new_fx, lsp_mid_fx, Q_old_inp_16k, Q_r, &Q_inp_16k ); -#ifdef NONBE_FIX_ISSUE_2518 - Q_inp_12k8 = add( Q_inp_12k8, norm_arr( old_inp_12k8_fx, L_INP_12k8 ) ); - scale_sig( old_inp_12k8_fx, L_INP_12k8, sub( Q_inp_12k8, *Q_new ) ); -#endif - IF( GT_16( Q_inp_16k, Q_inp_12k8 ) ) { #ifdef NONBE_FIX_ISSUE_2206 -- GitLab From 3a09c97f99f6e16b43f6fd50536f9e343a98216c Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 22 Apr 2026 22:47:59 +0200 Subject: [PATCH 05/17] Fine tune Q_new calculation, improve initial condition of q_lpd_old_exc via prev_Q_new. --- lib_enc/core_enc_switch_fx.c | 4 +++ lib_enc/init_enc_fx.c | 7 ++++ lib_enc/ivas_core_pre_proc_front_fx.c | 46 +++++++++++++++++++++++---- lib_enc/ivas_core_pre_proc_fx.c | 18 +++++++++-- 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/lib_enc/core_enc_switch_fx.c b/lib_enc/core_enc_switch_fx.c index 2fe851f62..43704fd1c 100644 --- a/lib_enc/core_enc_switch_fx.c +++ b/lib_enc/core_enc_switch_fx.c @@ -386,6 +386,7 @@ void core_coder_mode_switch_ivas_fx( move32(); st->currEnergyHF_e_fx = 0; move16(); +#ifndef NONBE_FIX_ISSUE_2518 Word16 shift = getScaleFactor16( st->old_inp_16k_fx, L_INP_MEM ); Scale_sig( st->old_inp_16k_fx, L_INP_MEM, shift ); st->exp_old_inp_16k = sub( st->exp_old_inp_16k, shift ); @@ -394,12 +395,15 @@ void core_coder_mode_switch_ivas_fx( Scale_sig( st->old_inp_12k8_fx, L_INP_MEM, shift ); st->exp_old_inp_12k8 = sub( st->exp_old_inp_12k8, shift ); move16(); +#endif init_coder_ace_plus_ivas_fx( st, last_total_brate, st->total_brate, MCT_flag ); +#ifndef NONBE_FIX_ISSUE_2518 if ( st->hLPDmem != NULL ) { st->hLPDmem->q_lpd_old_exc = st->prev_Q_new; move16(); } +#endif } test(); diff --git a/lib_enc/init_enc_fx.c b/lib_enc/init_enc_fx.c index e47b7621f..f55066687 100644 --- a/lib_enc/init_enc_fx.c +++ b/lib_enc/init_enc_fx.c @@ -249,6 +249,13 @@ ivas_error init_encoder_fx( st->prev_Q_new = 0; move16(); +#ifdef NONBE_FIX_ISSUE_2518 + if ( st->element_mode > EVS_MONO ) + { + st->prev_Q_new = Q15; + move16(); + } +#endif IF( EQ_32( st->input_Fs, 8000 ) ) { diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index 25445d201..bdd31912e 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -211,9 +211,15 @@ void pre_proc_front_ivas_fx( Word16 sf_energySum[CLDFB_NO_CHANNELS_MAX]; Word16 Q_inp_const = -1; move16(); +#ifdef NONBE_FIX_ISSUE_2518 + Word16 preemp_len; + Word16 *preemp_start_idx = NULL; + Word32 sig_out[STEREO_DFT_OVL_16k + L_FRAME16k /* = max( L_FRAME16k + STEREO_DFT_OVL_16k, L_FRAME16k + L_FILT16k + lMemRecalc_16k ) */]; +#else Word16 headroom, preemp_len, inp_max; Word16 *preemp_start_idx = NULL; Word32 sig_out[STEREO_DFT_OVL_16k + L_FRAME16k /* = max( L_FRAME16k + STEREO_DFT_OVL_16k, L_FRAME16k + L_FILT16k + lMemRecalc_16k ) */], max_32; +#endif push_wmops( "pre_proc_front" ); /*------------------------------------------------------------------* @@ -572,9 +578,15 @@ void pre_proc_front_ivas_fx( #endif } #ifdef NONBE_FIX_ISSUE_2206 +#ifdef NONBE_FIX_ISSUE_2518 + st->q_mem_decim_fx = add( st->q_inp, norm_arr( st->mem_decim_fx_q_inp, 2 * L_FILT_MAX ) ); + move16(); + Copy_Scale_sig_nosat( st->mem_decim_fx_q_inp, st->mem_decim_fx, 2 * L_FILT_MAX, sub( st->q_mem_decim_fx, st->q_inp ) ); +#else Copy( st->mem_decim_fx_q_inp, st->mem_decim_fx, 2 * L_FILT_MAX ); st->q_mem_decim_fx = st->q_inp; move16(); +#endif Word16 q_buf_speech_enc; @@ -627,6 +639,7 @@ void pre_proc_front_ivas_fx( * Perform fixed preemphasis (12.8 kHz signal) through 1 - g*z^-1 *-----------------------------------------------------------------*/ +#ifndef NONBE_FIX_ISSUE_2518 #ifdef NONBE_FIX_ISSUE_2206 headroom = 0; move16(); @@ -638,6 +651,7 @@ void pre_proc_front_ivas_fx( #else headroom = 2; move16(); +#endif #endif preemp_len = 0; move16(); @@ -734,6 +748,17 @@ void pre_proc_front_ivas_fx( move16(); st->mem_preemph_q = st->q_inp; move16(); +#ifdef NONBE_FIX_ISSUE_2518 + Word16 shift = L_norm_arr( sig_out, preemp_len ); + shift = s_min( shift, norm_arr( old_inp_16k_fx, (Word16) ( preemp_start_idx - old_inp_16k_fx ) ) ); + shift = add( shift, st->q_inp ); + if ( NE_32( input_Fs, st->sr_core ) ) + { + shift = s_min( shift, add( st->q_mem_decim_fx, 1 ) ); + } + *Q_new = s_min( shift, Q_MAX ); + move16(); +#else maximum_abs_32_fx( sig_out, preemp_len, &max_32 ); inp_max = s_max( extract_h( max_32 ), 1 ); @@ -769,19 +794,28 @@ void pre_proc_front_ivas_fx( st->Q_max[i] = shift; move16(); #endif +#endif +#ifdef NONBE_FIX_ISSUE_2518 + if ( flag_16k_smc ) + { + /* Avoid saturation of resampling decimation buffer inside ivas_compute_core_buffers_fx(). */ + *Q_new = s_min( *Q_new, add( st->q_mem_decim16k_fx, 1 ) ); + } + /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ + *Q_new = s_min( *Q_new, st->q_inp ); + IF( st->hLPDmem != NULL ) + { + *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_old_exc, 2 ) ); + *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_syn, 1 ) ); + } +#else #ifdef NONBE_FIX_ISSUE_2206 /* Avoid saturation of resampling decimation buffer inside ivas_compute_core_buffers_fx(). */ *Q_new = s_min( *Q_new, st->q_mem_decim16k_fx ); /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ *Q_new = s_min( *Q_new, st->q_inp ); #endif -#ifdef NONBE_FIX_ISSUE_2518 - if ( st->hLPDmem != NULL ) - { - *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_old_exc, 1 ) ); - } -#else *Q_new = add( *Q_new, Q_inp_const ); #endif move16(); diff --git a/lib_enc/ivas_core_pre_proc_fx.c b/lib_enc/ivas_core_pre_proc_fx.c index a7fc62354..5b5dd48af 100644 --- a/lib_enc/ivas_core_pre_proc_fx.c +++ b/lib_enc/ivas_core_pre_proc_fx.c @@ -806,9 +806,15 @@ void ivas_compute_core_buffers_fx( #else Word16 i, shift, Q_min; #endif +#ifdef NONBE_FIX_ISSUE_2518 + Word16 preemp_len; + Word16 *preemp_start_idx = NULL; + Word32 sig_out[STEREO_DFT_OVL_16k + L_FRAME16k + L_FILT16k]; +#else Word16 preemp_len, inp_max; Word16 *preemp_start_idx = NULL; Word32 sig_out[STEREO_DFT_OVL_16k + L_FRAME16k + L_FILT16k], max_32; +#endif #ifdef NONBE_FIX_ISSUE_2206 assert( Q_old_inp_16k == ( *Q_new - 1 ) ); @@ -1290,6 +1296,11 @@ void ivas_compute_core_buffers_fx( preemp_len = L_FRAME16k + L_FILT16k; move16(); } +#ifdef NONBE_FIX_ISSUE_2518 + shift = L_norm_arr( sig_out, preemp_len ); + shift = s_min( shift, norm_arr( old_inp_16k_fx, (Word16) ( preemp_start_idx - old_inp_16k_fx ) ) ); + shift = add( shift, Q_old_inp_16k ); +#else maximum_abs_32_fx( sig_out, preemp_len, &max_32 ); inp_max = s_max( extract_h( max_32 ), 1 ); @@ -1299,11 +1310,14 @@ void ivas_compute_core_buffers_fx( #else shift = sub( norm_s( inp_max ), 1 /* headroom */ ); #endif +#endif + #ifdef NONBE_FIX_ISSUE_2206 #ifdef NONBE_FIX_ISSUE_2518 - if ( st->hLPDmem != NULL ) + IF( st->hLPDmem != NULL ) { - *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_old_exc, 1 ) ); + *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_old_exc, 2 ) ); + *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_syn, 1 ) ); } #endif *Q_new = s_min( shift, Q_MAX ); -- GitLab From a7cd2c4f26f4404020b381dd02d5261849da3c31 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 22 Apr 2026 23:10:30 +0200 Subject: [PATCH 06/17] Correct copy paste error leading to UBSAN error. --- lib_enc/ivas_core_pre_proc_front_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index bdd31912e..3d1d2a2e6 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -750,7 +750,7 @@ void pre_proc_front_ivas_fx( move16(); #ifdef NONBE_FIX_ISSUE_2518 Word16 shift = L_norm_arr( sig_out, preemp_len ); - shift = s_min( shift, norm_arr( old_inp_16k_fx, (Word16) ( preemp_start_idx - old_inp_16k_fx ) ) ); + shift = s_min( shift, norm_arr( old_inp_12k8_fx, (Word16) ( preemp_start_idx - old_inp_12k8_fx ) ) ); shift = add( shift, st->q_inp ); if ( NE_32( input_Fs, st->sr_core ) ) { -- GitLab From 12e8620ef3e591561a0efbe658a5bf081ca3bc76 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Thu, 23 Apr 2026 10:11:39 +0200 Subject: [PATCH 07/17] Cleanup. --- lib_enc/ivas_core_pre_proc_front_fx.c | 32 ++++++++++++++------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index 3d1d2a2e6..46a8a4f13 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -756,6 +756,21 @@ void pre_proc_front_ivas_fx( { shift = s_min( shift, add( st->q_mem_decim_fx, 1 ) ); } + + /* Avoid saturation of resampling decimation buffer inside ivas_compute_core_buffers_fx(). */ + shift = s_min( shift, add( st->q_mem_decim16k_fx, 2 ) ); + + /* Add one bit headroom for filter overshoot in modify_Fs_fx() */ + shift = add( shift, 1 ); + + /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ + shift = s_min( shift, st->q_inp ); + IF( st->hLPDmem != NULL ) + { + shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 2 ) ); + shift = s_min( shift, add( st->hLPDmem->q_lpd_syn, 1 ) ); + } + *Q_new = s_min( shift, Q_MAX ); move16(); #else @@ -796,20 +811,7 @@ void pre_proc_front_ivas_fx( #endif #endif -#ifdef NONBE_FIX_ISSUE_2518 - if ( flag_16k_smc ) - { - /* Avoid saturation of resampling decimation buffer inside ivas_compute_core_buffers_fx(). */ - *Q_new = s_min( *Q_new, add( st->q_mem_decim16k_fx, 1 ) ); - } - /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ - *Q_new = s_min( *Q_new, st->q_inp ); - IF( st->hLPDmem != NULL ) - { - *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_old_exc, 2 ) ); - *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_syn, 1 ) ); - } -#else +#ifndef NONBE_FIX_ISSUE_2518 #ifdef NONBE_FIX_ISSUE_2206 /* Avoid saturation of resampling decimation buffer inside ivas_compute_core_buffers_fx(). */ *Q_new = s_min( *Q_new, st->q_mem_decim16k_fx ); @@ -817,8 +819,8 @@ void pre_proc_front_ivas_fx( *Q_new = s_min( *Q_new, st->q_inp ); #endif *Q_new = add( *Q_new, Q_inp_const ); -#endif move16(); +#endif Copy_Scale_sig32_16( sig_out, preemp_start_idx, preemp_len, sub( add( *Q_new, 1 ), st->q_inp ) ); /* Q_new */ Scale_sig( old_inp_12k8_fx, (Word16) ( preemp_start_idx - old_inp_12k8_fx ), sub( *Q_new, st->q_inp ) ); /* Q_new */ #ifdef NONBE_FIX_ISSUE_2206 -- GitLab From 4c2c01bb3dd7c9d5256fcdefd72dfb0a095ac238 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Thu, 23 Apr 2026 13:36:23 +0200 Subject: [PATCH 08/17] Undo some changes that worsened Q_new, and tidy up changes under NONBE_FIX_ISSUE_2518. --- lib_enc/init_enc_fx.c | 2 ++ lib_enc/ivas_core_pre_proc_front_fx.c | 14 +++----------- lib_enc/ivas_core_pre_proc_fx.c | 19 +++++++++++-------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/lib_enc/init_enc_fx.c b/lib_enc/init_enc_fx.c index f55066687..60760e2fb 100644 --- a/lib_enc/init_enc_fx.c +++ b/lib_enc/init_enc_fx.c @@ -1151,11 +1151,13 @@ ivas_error init_encoder_fx( init_coder_ace_plus_ivas_fx( st, st->last_total_brate, igf_brate, 0 ); } +#ifndef NONBE_FIX_ISSUE_2518 IF( st->hLPDmem != NULL ) { st->hLPDmem->q_lpd_old_exc = st->prev_Q_new; move16(); } +#endif /*-----------------------------------------------------------------* * FD-CNG encoder diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index 46a8a4f13..4cd83e48b 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -752,23 +752,15 @@ void pre_proc_front_ivas_fx( Word16 shift = L_norm_arr( sig_out, preemp_len ); shift = s_min( shift, norm_arr( old_inp_12k8_fx, (Word16) ( preemp_start_idx - old_inp_12k8_fx ) ) ); shift = add( shift, st->q_inp ); - if ( NE_32( input_Fs, st->sr_core ) ) - { - shift = s_min( shift, add( st->q_mem_decim_fx, 1 ) ); - } - - /* Avoid saturation of resampling decimation buffer inside ivas_compute_core_buffers_fx(). */ - shift = s_min( shift, add( st->q_mem_decim16k_fx, 2 ) ); - /* Add one bit headroom for filter overshoot in modify_Fs_fx() */ - shift = add( shift, 1 ); + /* Avoid saturation of resampling/delay decimation buffer. */ + shift = s_min( shift, add( st->q_mem_decim16k_fx, 1 ) ); /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ shift = s_min( shift, st->q_inp ); IF( st->hLPDmem != NULL ) { - shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 2 ) ); - shift = s_min( shift, add( st->hLPDmem->q_lpd_syn, 1 ) ); + shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 1 ) ); } *Q_new = s_min( shift, Q_MAX ); diff --git a/lib_enc/ivas_core_pre_proc_fx.c b/lib_enc/ivas_core_pre_proc_fx.c index 5b5dd48af..31687f3b7 100644 --- a/lib_enc/ivas_core_pre_proc_fx.c +++ b/lib_enc/ivas_core_pre_proc_fx.c @@ -1300,6 +1300,16 @@ void ivas_compute_core_buffers_fx( shift = L_norm_arr( sig_out, preemp_len ); shift = s_min( shift, norm_arr( old_inp_16k_fx, (Word16) ( preemp_start_idx - old_inp_16k_fx ) ) ); shift = add( shift, Q_old_inp_16k ); + + /* Avoid saturation of resampling/delay decimation buffer. */ + shift = s_min( shift, add( st->q_mem_decim16k_fx, 1 ) ); + + IF( st->hLPDmem != NULL ) + { + shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 1 ) ); + } + *Q_new = s_min( shift, Q_MAX ); + move16(); #else maximum_abs_32_fx( sig_out, preemp_len, &max_32 ); inp_max = s_max( extract_h( max_32 ), 1 ); @@ -1310,16 +1320,8 @@ void ivas_compute_core_buffers_fx( #else shift = sub( norm_s( inp_max ), 1 /* headroom */ ); #endif -#endif #ifdef NONBE_FIX_ISSUE_2206 -#ifdef NONBE_FIX_ISSUE_2518 - IF( st->hLPDmem != NULL ) - { - *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_old_exc, 2 ) ); - *Q_new = s_min( *Q_new, add( st->hLPDmem->q_lpd_syn, 1 ) ); - } -#endif *Q_new = s_min( shift, Q_MAX ); move16(); #else @@ -1349,6 +1351,7 @@ void ivas_compute_core_buffers_fx( st->Q_max_16k[i] = shift; move16(); #endif +#endif #ifndef NONBE_FIX_ISSUE_2206 Copy_Scale_sig32_16( sig_out, preemp_start_idx, preemp_len, add( *Q_new, 1 ) ); -- GitLab From 3db8695fab46626e9b26c2613e20820c8c6f0808 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Thu, 23 Apr 2026 13:43:01 +0200 Subject: [PATCH 09/17] Correct macro name --- lib_enc/updt_enc_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_enc/updt_enc_fx.c b/lib_enc/updt_enc_fx.c index 5979a83d3..c26ddc8c8 100644 --- a/lib_enc/updt_enc_fx.c +++ b/lib_enc/updt_enc_fx.c @@ -34,7 +34,7 @@ void updt_enc_fx( GSC_ENC_HANDLE hGSCEnc = st->hGSCEnc; TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; -#ifdef NONBE_FIX_2507 +#ifdef NONBE_FIX_ISSUE_2518 /* update old excitation buffer */ IF( st->element_mode > EVS_MONO ) { -- GitLab From abfc200a9f44aff87ac9b441ad31e6d88857b0c6 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Mon, 27 Apr 2026 23:29:56 +0200 Subject: [PATCH 10/17] Correct scale of hLPDmem->mem_w0 when copied from st->wspeech_enc[-1]. Add all hLPDmem members into Q_new calculation to avoid ACELP saturations. --- lib_enc/acelp_core_enc_fx.c | 2 ++ lib_enc/core_enc_init_fx.c | 17 ++++++++++++++++- lib_enc/core_enc_updt_fx.c | 1 + lib_enc/ivas_core_enc_fx.c | 4 ++++ lib_enc/ivas_core_pre_proc_front_fx.c | 12 ++++++++---- lib_enc/ivas_core_pre_proc_fx.c | 4 +++- lib_enc/stat_enc.h | 3 ++- lib_enc/updt_enc_fx.c | 24 ++++++++++++++++++++++++ 8 files changed, 60 insertions(+), 7 deletions(-) diff --git a/lib_enc/acelp_core_enc_fx.c b/lib_enc/acelp_core_enc_fx.c index 964f90f78..f3ed3a1b7 100644 --- a/lib_enc/acelp_core_enc_fx.c +++ b/lib_enc/acelp_core_enc_fx.c @@ -953,6 +953,7 @@ ivas_error acelp_core_enc_fx( * Updates *-----------------------------------------------------------------*/ +#ifndef NONBE_FIX_ISSUE_2518 IF( st->element_mode > EVS_MONO ) { if ( st->hBWE_TD != NULL ) @@ -963,6 +964,7 @@ ivas_error acelp_core_enc_fx( hLPDmem->q_lpd_old_exc = Q_new; move16(); } +#endif updt_enc_fx( st, old_exc_fx, pitch_buf, Es_pred_fx, Aq, lsf_new_fx, lsp_new, old_bwe_exc_fx ); diff --git a/lib_enc/core_enc_init_fx.c b/lib_enc/core_enc_init_fx.c index c74d46084..4ba2f41d0 100644 --- a/lib_enc/core_enc_init_fx.c +++ b/lib_enc/core_enc_init_fx.c @@ -28,7 +28,11 @@ static void init_tcx_ivas_fx( Encoder_State *st, const Word16 L_frame_old, const static void init_core_sig_ana_ivas_fx( Encoder_State *st ); static void init_modes_ivas_fx( Encoder_State *st, const Word32 last_total_brate ); static void init_sig_buffers_ivas_fx( Encoder_State *st, const Word16 L_frame_old, const Word16 L_subfr, const Word32 last_total_brate ); +#ifdef NONBE_FIX_ISSUE_2518 +static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, const Word32 last_total_brate ); +#else static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 shift, const Word32 last_total_brate ); +#endif /*-----------------------------------------------------------------------* * init_coder_ace_plus_fx() @@ -1084,8 +1088,11 @@ void init_coder_ace_plus_ivas_fx( init_sig_buffers_ivas_fx( st, L_frame_old, L_subfr, last_total_brate ); /* Initialize ACELP */ - +#ifdef NONBE_FIX_ISSUE_2518 + init_acelp_ivas_fx( st, L_frame_old, last_total_brate ); +#else init_acelp_ivas_fx( st, L_frame_old, 0, last_total_brate ); +#endif if ( st->ini_frame == 0 ) { @@ -1538,7 +1545,11 @@ static void init_core_sig_ana_ivas_fx( Encoder_State *st ) * * *-----------------------------------------------------------------------*/ +#ifdef NONBE_FIX_ISSUE_2518 +static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, const Word32 last_total_brate ) +#else static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 shift, const Word32 last_total_brate ) +#endif { Word16 mem_syn_r_size_old; Word16 mem_syn_r_size_new; @@ -1722,7 +1733,11 @@ static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 sh Copy( hLPDmem->mem_syn2, tmp_buf + 1, M ); deemph_fx( tmp_buf + 1, st->preemph_fac, M, &tmp ); Residu3_fx( Ap, tmp_buf + M, &tmp, 1, 1 ); +#ifdef NONBE_FIX_ISSUE_2518 + hLPDmem->mem_w0 = sub_sat( shl_sat( st->wspeech_enc[-1], sub( hLPDmem->q_mem_syn, sub( Q15, st->exp_buf_wspeech_enc ) ) ), tmp ); +#else hLPDmem->mem_w0 = sub_sat( shr_sat( st->wspeech_enc[-1], shift ), tmp ); +#endif move16(); } } diff --git a/lib_enc/core_enc_updt_fx.c b/lib_enc/core_enc_updt_fx.c index f6aba6f61..3272830e8 100644 --- a/lib_enc/core_enc_updt_fx.c +++ b/lib_enc/core_enc_updt_fx.c @@ -102,6 +102,7 @@ void core_encode_update_cng_fx( p_A += ( M + 1 ); } + assert( st->element_mode == EVS_MONO ); tmp = sub( st->wspeech_enc[-1], shl( hLPDmem->mem_w0, shift ) ); E_UTIL_deemph2( negate( shift ), wsyn, st->preemph_fac, st->L_frame, &tmp ); hLPDmem->mem_w0 = sub_sat( st->wspeech_enc[st->L_frame - 1], tmp ); diff --git a/lib_enc/ivas_core_enc_fx.c b/lib_enc/ivas_core_enc_fx.c index 919ef5df2..53ca86b01 100644 --- a/lib_enc/ivas_core_enc_fx.c +++ b/lib_enc/ivas_core_enc_fx.c @@ -436,11 +436,13 @@ ivas_error ivas_core_enc_fx( #ifndef NONBE_FIX_ISSUE_2206 Scale_sig( old_inp_16k_fx[n], L_INP, sub( Q1, Q_new[n] ) ); // Q0 #endif +#ifndef NONBE_FIX_ISSUE_2518 IF( NE_16( st->element_mode, IVAS_CPE_DFT ) && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) { st->hTcxEnc->exp_buf_speech_ltp = st->exp_buf_speech_enc; move16(); } +#endif } Word16 Q_spec_old[2], L_spec; Q_spec_old[0] = hCPE->hCoreCoder[0]->hTcxEnc->spectrum_long_e; @@ -523,12 +525,14 @@ ivas_error ivas_core_enc_fx( st = sts[i]; Scale_sig( old_inp_16k_fx[i], L_INP, sub( Q1, Q_new[i] ) ); // Q0 +#ifndef NONBE_FIX_ISSUE_2518 test(); IF( NE_16( st->element_mode, IVAS_CPE_DFT ) && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) { st->hTcxEnc->exp_buf_speech_ltp = st->exp_buf_speech_enc; move16(); } +#endif shift = norm_arr( st->input_fx, input_frame ); #ifdef NONBE_FIX_ISSUE_2206 Q_min = add( st->q_inp, shift ); diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index 4cd83e48b..69f57ca92 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -753,14 +753,18 @@ void pre_proc_front_ivas_fx( shift = s_min( shift, norm_arr( old_inp_12k8_fx, (Word16) ( preemp_start_idx - old_inp_12k8_fx ) ) ); shift = add( shift, st->q_inp ); - /* Avoid saturation of resampling/delay decimation buffer. */ - shift = s_min( shift, add( st->q_mem_decim16k_fx, 1 ) ); - + IF( flag_16k_smc ) + { + /* Avoid saturation of resampling/delay decimation buffer. */ + shift = s_min( shift, add( st->q_mem_decim16k_fx, 1 ) ); + } /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ shift = s_min( shift, st->q_inp ); IF( st->hLPDmem != NULL ) { - shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 1 ) ); + shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 0 ) ); + shift = s_min( shift, add( st->hLPDmem->q_lpd_syn, 0 ) ); + shift = s_min( shift, add( st->hLPDmem->q_mem_syn, 1 ) ); } *Q_new = s_min( shift, Q_MAX ); diff --git a/lib_enc/ivas_core_pre_proc_fx.c b/lib_enc/ivas_core_pre_proc_fx.c index 31687f3b7..52475d0ee 100644 --- a/lib_enc/ivas_core_pre_proc_fx.c +++ b/lib_enc/ivas_core_pre_proc_fx.c @@ -1306,7 +1306,9 @@ void ivas_compute_core_buffers_fx( IF( st->hLPDmem != NULL ) { - shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 1 ) ); + shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 0 ) ); + shift = s_min( shift, add( st->hLPDmem->q_lpd_syn, 0 ) ); + shift = s_min( shift, add( st->hLPDmem->q_mem_syn, 1 ) ); } *Q_new = s_min( shift, Q_MAX ); move16(); diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index f84b51824..12f78670e 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -1789,8 +1789,9 @@ typedef struct enc_core_structure /*----------------------------------------------------------------------------------* * Fixed point only variables *----------------------------------------------------------------------------------*/ - +#ifndef NONBE_FIX_ISSUE_2518 Word16 Q_exc; +#endif Word16 Q_stat_noise_ge; Word16 Q_stat_noise; Word16 Q_syn2; diff --git a/lib_enc/updt_enc_fx.c b/lib_enc/updt_enc_fx.c index c26ddc8c8..9224b1081 100644 --- a/lib_enc/updt_enc_fx.c +++ b/lib_enc/updt_enc_fx.c @@ -39,9 +39,33 @@ void updt_enc_fx( IF( st->element_mode > EVS_MONO ) { tmp = norm_arr( &old_exc[st->L_frame], L_EXC_MEM ); + tmp = s_min( tmp, sub( 15, hLPDmem->q_lpd_old_exc ) ); Copy_Scale_sig_nosat( &old_exc[st->L_frame], hLPDmem->old_exc, L_EXC_MEM, tmp ); hLPDmem->q_lpd_old_exc = add( hLPDmem->q_lpd_old_exc, tmp ); move16(); + + tmp = norm_arr( st->hLPDmem->syn, M + 1 ); + tmp = s_min( tmp, sub( 15, hLPDmem->q_lpd_syn ) ); + scale_sig( st->hLPDmem->syn, M, tmp ); + st->hLPDmem->q_lpd_syn = add( st->hLPDmem->q_lpd_syn, tmp ); + move16(); + + tmp = norm_arr( hLPDmem->mem_syn, M ); + tmp = s_min( tmp, norm_arr( hLPDmem->mem_syn1_fx, M ) ); + tmp = s_min( tmp, norm_arr( hLPDmem->mem_syn2, M ) ); + tmp = s_min( tmp, norm_arr( hLPDmem->mem_syn3, M ) ); + tmp = s_min( tmp, norm_arr( hLPDmem->mem_syn_r, L_SYN_MEM ) ); + tmp = s_min( tmp, norm_s( hLPDmem->mem_w0 ) ); + tmp = s_min( tmp, sub( 15, hLPDmem->q_mem_syn ) ); + // tmp = sub( tmp, 1 ); + scale_sig( hLPDmem->mem_syn, M, tmp ); + scale_sig( hLPDmem->mem_syn1_fx, M, tmp ); + scale_sig( hLPDmem->mem_syn2, M, tmp ); + scale_sig( hLPDmem->mem_syn3, M, tmp ); + scale_sig( hLPDmem->mem_syn_r, L_SYN_MEM, tmp ); + hLPDmem->mem_w0 = shl( hLPDmem->mem_w0, tmp ); + move16(); + st->hLPDmem->q_mem_syn = add( st->hLPDmem->q_mem_syn, tmp ); } ELSE { -- GitLab From ebd34cb248775aaccb49283c16d3056ae3f1e443 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 29 Apr 2026 17:13:49 +0200 Subject: [PATCH 11/17] Add missing scale adaption of ACELP high rate memories mem_deemp_preQ_fx and mem_preemp_preQ_fx. Correct another scaling issue of hLPDmem->mem_w0. --- lib_enc/acelp_core_enc_fx.c | 4 ++++ lib_enc/core_enc_init_fx.c | 3 ++- lib_enc/ivas_core_pre_proc_front_fx.c | 12 +++++------- lib_enc/ivas_core_pre_proc_fx.c | 5 ++--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/lib_enc/acelp_core_enc_fx.c b/lib_enc/acelp_core_enc_fx.c index f3ed3a1b7..338456596 100644 --- a/lib_enc/acelp_core_enc_fx.c +++ b/lib_enc/acelp_core_enc_fx.c @@ -117,6 +117,10 @@ ivas_error acelp_core_enc_fx( move16(); hLPDmem->q_mem_syn = sub( Q_new, 1 ); move16(); +#ifdef NONBE_FIX_ISSUE_2518 + st->mem_deemp_preQ_fx = shl_sat( st->mem_deemp_preQ_fx, sub( Q_new, st->prev_Q_new ) ); + st->mem_preemp_preQ_fx = shl_sat( st->mem_preemp_preQ_fx, sub( Q_new, st->prev_Q_new ) ); +#endif } Scale_sig32( st->Bin_E_old_fx, L_FFT / 2, sub( add( Q_new, Q_SCALE - 2 ), st->q_Bin_E_old ) ); // Q_new + Q_scale - 2 diff --git a/lib_enc/core_enc_init_fx.c b/lib_enc/core_enc_init_fx.c index 4ba2f41d0..2f1673ab8 100644 --- a/lib_enc/core_enc_init_fx.c +++ b/lib_enc/core_enc_init_fx.c @@ -1732,10 +1732,11 @@ static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 sh move16(); Copy( hLPDmem->mem_syn2, tmp_buf + 1, M ); deemph_fx( tmp_buf + 1, st->preemph_fac, M, &tmp ); - Residu3_fx( Ap, tmp_buf + M, &tmp, 1, 1 ); #ifdef NONBE_FIX_ISSUE_2518 + Residu3_fx( Ap, tmp_buf + M, &tmp, 1, 0 ); hLPDmem->mem_w0 = sub_sat( shl_sat( st->wspeech_enc[-1], sub( hLPDmem->q_mem_syn, sub( Q15, st->exp_buf_wspeech_enc ) ) ), tmp ); #else + Residu3_fx( Ap, tmp_buf + M, &tmp, 1, 1 ); hLPDmem->mem_w0 = sub_sat( shr_sat( st->wspeech_enc[-1], shift ), tmp ); #endif move16(); diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index 69f57ca92..1ad149b0a 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -753,17 +753,15 @@ void pre_proc_front_ivas_fx( shift = s_min( shift, norm_arr( old_inp_12k8_fx, (Word16) ( preemp_start_idx - old_inp_12k8_fx ) ) ); shift = add( shift, st->q_inp ); - IF( flag_16k_smc ) - { - /* Avoid saturation of resampling/delay decimation buffer. */ - shift = s_min( shift, add( st->q_mem_decim16k_fx, 1 ) ); - } + /* Avoid saturation of resampling/delay decimation buffer. */ + shift = s_min( shift, add( st->q_mem_decim16k_fx, 1 ) ); + /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ shift = s_min( shift, st->q_inp ); IF( st->hLPDmem != NULL ) { - shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 0 ) ); - shift = s_min( shift, add( st->hLPDmem->q_lpd_syn, 0 ) ); + shift = s_min( shift, st->hLPDmem->q_lpd_old_exc ); + shift = s_min( shift, st->hLPDmem->q_lpd_syn ); shift = s_min( shift, add( st->hLPDmem->q_mem_syn, 1 ) ); } diff --git a/lib_enc/ivas_core_pre_proc_fx.c b/lib_enc/ivas_core_pre_proc_fx.c index 52475d0ee..4f6a95943 100644 --- a/lib_enc/ivas_core_pre_proc_fx.c +++ b/lib_enc/ivas_core_pre_proc_fx.c @@ -943,7 +943,6 @@ void ivas_compute_core_buffers_fx( #ifdef NONBE_FIX_ISSUE_2206 scale_sig( new_inp_16k_fx + NS2SA_FX2( sr_core, FRAME_SIZE_NS ), size_modified, negate( Q_tmp ) ); /* scaling back to Q_old_inp_16k */ - // Scale_sig( st->mem_decim16k_fx, 2 * L_FILT_MAX, sub( -1, Q_old_inp_16k ) ); /* Q(-1) */ Q_tmp = norm_arr( st->mem_decim16k_fx, mem_decim16k_size ); scale_sig( st->mem_decim16k_fx, mem_decim16k_size, Q_tmp ); st->q_mem_decim16k_fx = add( Q_tmp, Q_old_inp_16k ); @@ -1306,8 +1305,8 @@ void ivas_compute_core_buffers_fx( IF( st->hLPDmem != NULL ) { - shift = s_min( shift, add( st->hLPDmem->q_lpd_old_exc, 0 ) ); - shift = s_min( shift, add( st->hLPDmem->q_lpd_syn, 0 ) ); + shift = s_min( shift, st->hLPDmem->q_lpd_old_exc ); + shift = s_min( shift, st->hLPDmem->q_lpd_syn ); shift = s_min( shift, add( st->hLPDmem->q_mem_syn, 1 ) ); } *Q_new = s_min( shift, Q_MAX ); -- GitLab From 8af4aa5e08baed055b9e5bb1376ce54d96da8e63 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 29 Apr 2026 21:10:48 +0200 Subject: [PATCH 12/17] Undo rescale of mem_preemp_preQ_fx (wrong). --- lib_enc/acelp_core_enc_fx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib_enc/acelp_core_enc_fx.c b/lib_enc/acelp_core_enc_fx.c index 68cb01e67..5f38e5bd3 100644 --- a/lib_enc/acelp_core_enc_fx.c +++ b/lib_enc/acelp_core_enc_fx.c @@ -119,7 +119,6 @@ ivas_error acelp_core_enc_fx( move16(); #ifdef NONBE_FIX_ISSUE_2518 st->mem_deemp_preQ_fx = shl_sat( st->mem_deemp_preQ_fx, sub( Q_new, st->prev_Q_new ) ); - st->mem_preemp_preQ_fx = shl_sat( st->mem_preemp_preQ_fx, sub( Q_new, st->prev_Q_new ) ); #endif } -- GitLab From 437d10e8568ff91192e0989e87dd225ff27a5dbd Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 29 Apr 2026 21:12:21 +0200 Subject: [PATCH 13/17] Add NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX to fix saturation inside transf_cdbk_enc_fx(). --- lib_com/options.h | 3 ++- lib_enc/enc_higher_acelp_fx.c | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib_com/options.h b/lib_com/options.h index ac9629dba..050fc5528 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -92,7 +92,6 @@ #define NONBE_FIX_ISSUE_2206_AVOID_OVERFLOW_MSVQ_Interpol_Tran_fx /* FhG: Fix saturation crash in MSVQ_Interpol_Tran_fx() */ #define NONBE_FIX_ISSUE_2206_SWB_EXPERIMENT_FIX_2527 /* Fix crash from issue #2527 */ #define NONBE_FIX_2507 /* Fix porting error in SQ_gain_estimate_fx() */ -#define NONBE_FIX_ISSUE_2518 /* FhG: Fix issue 2518, noise during ACELP switching from 16KHz to 12k8Hz by improving Q_new calculation. */ #define FIX_FLOAT_1539_G192_FORMAT_SWITCH /* VA/Nokia: reintroduce format switching for g192 bitstreams */ #define HARMONIZE_2499_CONFIGUREFDCNGDEC /* FhG: basop issue 2499: harmonoize configureFdCngDec */ #define FIX_BASOP_2530_IVAS_DECISION_MAT /* VA: Fix ambiguous usage of extract_l() */ @@ -147,6 +146,8 @@ #define FIX_FMSW_DEC_2 /* float issue 1575: fix crash for format switching when bitsream starts with EVS */ #define FIX_BASOP_2561_STEREO_DFT_ENC_COMPUTE_ITD /* BASOP issue 2561: fix diffs in stereo_dft_enc_compute_itd() between float and BASOP */ #define FIX_BASOP_2517_CLICK_IN_OMASA_LTV /* FhG: BASOP #2517: preserve precision by removing one-bit headroom from Q_min and allowing saturation during buffer scaling */ +#define NONBE_FIX_ISSUE_2518 /* FhG: Fix issue 2518, noise during ACELP switching from 16KHz to 12k8Hz by improving Q_new calculation. */ +#define NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX /* FhG: Fix issue 2518, fix wrong amplitude because of saturation of x_tran in transf_cdbk_enc_fx() for transient signals. */ #define FIX_BASOP_2559_Q_SYNTH_HISTORY_RESET /* FhG: BASOP issue 2559: reset hTcxDec->q_synth_history_fx in allocate_CoreCoder_TCX_fx() */ #define FIX_FLOAT_1578_OMASA_REND_SPIKES /* Nokia: Float issue 1578: Fix spikes and collapsed perception in OMASA/MASA rendering to FOA/HOA */ diff --git a/lib_enc/enc_higher_acelp_fx.c b/lib_enc/enc_higher_acelp_fx.c index 24bf48838..5b6476d92 100644 --- a/lib_enc/enc_higher_acelp_fx.c +++ b/lib_enc/enc_higher_acelp_fx.c @@ -301,11 +301,17 @@ void transf_cdbk_enc_fx( * DCT transform *--------------------------------------------------------------*/ +#ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX + Word16 q_x_tran; + q_x_tran = s_min( Q_AVQ_OUT_DEC, norm_arr( x_norm, Nsv * WIDTH_BAND ) ); + Copy_Scale_sig_nosat( x_norm, x_tran, Nsv * WIDTH_BAND, q_x_tran ); +#else FOR( i = 0; i < Nsv * WIDTH_BAND; i++ ) { x_tran[i] = shl_sat( x_norm[i], Q_AVQ_OUT_DEC ); move16(); } +#endif test(); test(); @@ -321,8 +327,13 @@ void transf_cdbk_enc_fx( edct2_fx( L_SUBFR, 1, x_tran, out32, &Qdct, ip_edct2_64, w_edct2_64_fx ); /*qdct = sub(Q_AVQ_OUT_DEC,qdct+Q_AVQ_OUT_DEC);*/ Qdct = negate( Qdct ); +#ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX + Copy_Scale_sig_32_16( out32, code_preQ, L_SUBFR, Qdct ); /* Output in q_x_tran */ + /*qdct = q_x_tran;*/ +#else Copy_Scale_sig_32_16( out32, code_preQ, L_SUBFR, Qdct ); /* Output in Q_AVQ_OUT_DEC */ /*qdct = Q_AVQ_OUT_DEC;*/ +#endif } /*--------------------------------------------------------------* @@ -348,22 +359,41 @@ void transf_cdbk_enc_fx( test(); IF( GT_16( st_fx->element_mode, EVS_MONO ) && NE_16( st_fx->coder_type, INACTIVE ) && GE_32( st_fx->core_brate, MIN_BRATE_AVQ_EXC ) && LE_32( st_fx->core_brate, MAX_BRATE_AVQ_EXC_TD ) && !harm_flag_acelp && code_preQ[0] != 0 ) { +#ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX + IF( GT_16( abs_s( st_fx->last_code_preq ), shl_sat( abs_s( code_preQ[0] ), sub( Q_AVQ_OUT_DEC + 4, q_x_tran ) ) ) ) +#else IF( GT_16( abs_s( st_fx->last_code_preq ), shl_sat( abs_s( code_preQ[0] ), 4 ) ) ) +#endif { st_fx->mem_preemp_preQ_fx = shr( st_fx->mem_preemp_preQ_fx, 4 ); move16(); } +#ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX + ELSE IF( GT_16( abs_s( st_fx->last_code_preq ), shl_sat( abs_s( code_preQ[0] ), sub( Q_AVQ_OUT_DEC + 3, q_x_tran ) ) ) ) +#else ELSE IF( GT_16( abs_s( st_fx->last_code_preq ), shl_sat( abs_s( code_preQ[0] ), 3 ) ) ) +#endif { st_fx->mem_preemp_preQ_fx = shr( st_fx->mem_preemp_preQ_fx, 3 ); move16(); } } +#ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX + st_fx->last_code_preq = shl_sat( code_preQ[L_SUBFR - 1], sub( 1, q_x_tran ) ); // Q0 ? Q1 + move16(); + + st_fx->mem_preemp_preQ_fx = shl_sat( st_fx->mem_preemp_preQ_fx, sub( q_x_tran, Q_AVQ_OUT_DEC ) ); + move16(); + preemph_fx( code_preQ, FAC_PRE_AVQ_FX, L_SUBFR, &( st_fx->mem_preemp_preQ_fx ) ); + st_fx->mem_preemp_preQ_fx = shl_sat( st_fx->mem_preemp_preQ_fx, sub( Q_AVQ_OUT_DEC, q_x_tran ) ); + move16(); +#else st_fx->last_code_preq = shr( code_preQ[L_SUBFR - 1], 9 ); // Q0 move16(); preemph_fx( code_preQ, FAC_PRE_AVQ_FX, L_SUBFR, &( st_fx->mem_preemp_preQ_fx ) ); +#endif /*--------------------------------------------------------------* * For inactive segments @@ -376,22 +406,36 @@ void transf_cdbk_enc_fx( IF( EQ_16( st_fx->coder_type, INACTIVE ) ) { /*ftemp = fcode_preQ[0] *fh1[L_SUBFR-1];*/ +#ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX + Ltmp = L_mult( code_preQ[0], h1[L_SUBFR - 1] ); /*1+14+shift + q_x_tran */ +#else Ltmp = L_mult( code_preQ[0], h1[L_SUBFR - 1] ); /*1+14+shift + Q_AVQ_OUT */ +#endif FOR( i = 1; i < L_SUBFR; i++ ) { /*ftemp += fcode_preQ[i] * fh1[L_SUBFR-1-i];*/ Ltmp = L_mac( Ltmp, code_preQ[i], h1[L_SUBFR - 1 - i] ); } /*fxn[L_SUBFR-1] -= *fgain_preQ * ftemp;*/ +#ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX + Ltmp = L_shr( Mult_32_16( Ltmp, *gain_preQ ), sub( add( q_x_tran, 2 ), Q_new ) ); /* (2 + 1 + 14 +shift+Q_AVQ_OUT)-(Q_AVQ_OUT+2-Q_new) = 15 + Q_new + shift */ +#else Ltmp = L_shr( Mult_32_16( Ltmp, *gain_preQ ), sub( add( Q_AVQ_OUT_DEC, 2 ), Q_new ) ); /* (2 + 1 + 14 +shift+Q_AVQ_OUT)-(Q_AVQ_OUT+2-Q_new) = 15 + Q_new + shift */ +#endif xn[L_SUBFR - 1] = round_fx( L_sub( L_mult( xn[L_SUBFR - 1], 32767 ), Ltmp ) ); /* -> Q_new + shift -1 */ } ELSE { conv_fx( code_preQ, h1, x_tran, L_SUBFR ); +#ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX + updt_tar_HR_fx( cn, cn, code_preQ, *gain_preQ, sub( Q_new, add( -15 + 2, q_x_tran ) ), L_SUBFR ); + + updt_tar_HR_fx( xn, xn, x_tran, *gain_preQ, sub( Q_new, add( -15 + 2, q_x_tran ) ), L_SUBFR ); +#else updt_tar_HR_fx( cn, cn, code_preQ, *gain_preQ, sub( Q_new, add( -15 + 2, Q_AVQ_OUT_DEC ) ), L_SUBFR ); updt_tar_HR_fx( xn, xn, x_tran, *gain_preQ, sub( Q_new, add( -15 + 2, Q_AVQ_OUT_DEC ) ), L_SUBFR ); +#endif *gain_pit = corr_xy1_fx( xn, y1, g_corr, L_SUBFR, 0, &Overflow ); /* Q14 */ move16(); /* clip gain if necessary to avoid problems at decoder */ -- GitLab From 72b2203134df2366dbdbba50aa64e35dbf6ade0d Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 29 Apr 2026 21:14:34 +0200 Subject: [PATCH 14/17] clang format --- lib_enc/enc_higher_acelp_fx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib_enc/enc_higher_acelp_fx.c b/lib_enc/enc_higher_acelp_fx.c index 5b6476d92..d2091073b 100644 --- a/lib_enc/enc_higher_acelp_fx.c +++ b/lib_enc/enc_higher_acelp_fx.c @@ -329,10 +329,10 @@ void transf_cdbk_enc_fx( Qdct = negate( Qdct ); #ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX Copy_Scale_sig_32_16( out32, code_preQ, L_SUBFR, Qdct ); /* Output in q_x_tran */ - /*qdct = q_x_tran;*/ + /*qdct = q_x_tran;*/ #else Copy_Scale_sig_32_16( out32, code_preQ, L_SUBFR, Qdct ); /* Output in Q_AVQ_OUT_DEC */ - /*qdct = Q_AVQ_OUT_DEC;*/ + /*qdct = Q_AVQ_OUT_DEC;*/ #endif } @@ -360,7 +360,7 @@ void transf_cdbk_enc_fx( IF( GT_16( st_fx->element_mode, EVS_MONO ) && NE_16( st_fx->coder_type, INACTIVE ) && GE_32( st_fx->core_brate, MIN_BRATE_AVQ_EXC ) && LE_32( st_fx->core_brate, MAX_BRATE_AVQ_EXC_TD ) && !harm_flag_acelp && code_preQ[0] != 0 ) { #ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX - IF( GT_16( abs_s( st_fx->last_code_preq ), shl_sat( abs_s( code_preQ[0] ), sub( Q_AVQ_OUT_DEC + 4, q_x_tran ) ) ) ) + IF( GT_16( abs_s( st_fx->last_code_preq ), shl_sat( abs_s( code_preQ[0] ), sub( Q_AVQ_OUT_DEC + 4, q_x_tran ) ) ) ) #else IF( GT_16( abs_s( st_fx->last_code_preq ), shl_sat( abs_s( code_preQ[0] ), 4 ) ) ) #endif @@ -386,7 +386,7 @@ void transf_cdbk_enc_fx( st_fx->mem_preemp_preQ_fx = shl_sat( st_fx->mem_preemp_preQ_fx, sub( q_x_tran, Q_AVQ_OUT_DEC ) ); move16(); preemph_fx( code_preQ, FAC_PRE_AVQ_FX, L_SUBFR, &( st_fx->mem_preemp_preQ_fx ) ); - st_fx->mem_preemp_preQ_fx = shl_sat( st_fx->mem_preemp_preQ_fx, sub( Q_AVQ_OUT_DEC, q_x_tran ) ); + st_fx->mem_preemp_preQ_fx = shl_sat( st_fx->mem_preemp_preQ_fx, sub( Q_AVQ_OUT_DEC, q_x_tran ) ); move16(); #else st_fx->last_code_preq = shr( code_preQ[L_SUBFR - 1], 9 ); // Q0 @@ -422,7 +422,7 @@ void transf_cdbk_enc_fx( #else Ltmp = L_shr( Mult_32_16( Ltmp, *gain_preQ ), sub( add( Q_AVQ_OUT_DEC, 2 ), Q_new ) ); /* (2 + 1 + 14 +shift+Q_AVQ_OUT)-(Q_AVQ_OUT+2-Q_new) = 15 + Q_new + shift */ #endif - xn[L_SUBFR - 1] = round_fx( L_sub( L_mult( xn[L_SUBFR - 1], 32767 ), Ltmp ) ); /* -> Q_new + shift -1 */ + xn[L_SUBFR - 1] = round_fx( L_sub( L_mult( xn[L_SUBFR - 1], 32767 ), Ltmp ) ); /* -> Q_new + shift -1 */ } ELSE { -- GitLab From 525045c2a9fe65386333046b6e0988d9d9cab1a2 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Wed, 29 Apr 2026 21:39:28 +0200 Subject: [PATCH 15/17] Fix EVS BE regression --- lib_enc/enc_higher_acelp_fx.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib_enc/enc_higher_acelp_fx.c b/lib_enc/enc_higher_acelp_fx.c index d2091073b..9d74cedc9 100644 --- a/lib_enc/enc_higher_acelp_fx.c +++ b/lib_enc/enc_higher_acelp_fx.c @@ -303,8 +303,17 @@ void transf_cdbk_enc_fx( #ifdef NONBE_FIX_ISSUE_2518_TRANSENC_SAT_FIX Word16 q_x_tran; - q_x_tran = s_min( Q_AVQ_OUT_DEC, norm_arr( x_norm, Nsv * WIDTH_BAND ) ); - Copy_Scale_sig_nosat( x_norm, x_tran, Nsv * WIDTH_BAND, q_x_tran ); + IF( EQ_16( st_fx->element_mode, EVS_MONO ) ) + { + q_x_tran = Q_AVQ_OUT_DEC; + move16(); + Copy_Scale_sig( x_norm, x_tran, Nsv * WIDTH_BAND, q_x_tran ); + } + ELSE + { + q_x_tran = s_min( Q_AVQ_OUT_DEC, norm_arr( x_norm, Nsv * WIDTH_BAND ) ); + Copy_Scale_sig_nosat( x_norm, x_tran, Nsv * WIDTH_BAND, q_x_tran ); + } #else FOR( i = 0; i < Nsv * WIDTH_BAND; i++ ) { -- GitLab From 5c752786b0c2584e0556f70b880e8d19a9cdd7b8 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Thu, 30 Apr 2026 08:21:09 +0200 Subject: [PATCH 16/17] Undo unnecessary difference to main --- lib_enc/core_enc_init_fx.c | 1 + lib_enc/stat_enc.h | 1 + 2 files changed, 2 insertions(+) diff --git a/lib_enc/core_enc_init_fx.c b/lib_enc/core_enc_init_fx.c index fd5c05fe0..7efe8a9ff 100644 --- a/lib_enc/core_enc_init_fx.c +++ b/lib_enc/core_enc_init_fx.c @@ -1088,6 +1088,7 @@ void init_coder_ace_plus_ivas_fx( init_sig_buffers_ivas_fx( st, L_frame_old, L_subfr, last_total_brate ); /* Initialize ACELP */ + #ifdef NONBE_FIX_ISSUE_2518 init_acelp_ivas_fx( st, L_frame_old, last_total_brate ); #else diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 12f78670e..862292de8 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -1789,6 +1789,7 @@ typedef struct enc_core_structure /*----------------------------------------------------------------------------------* * Fixed point only variables *----------------------------------------------------------------------------------*/ + #ifndef NONBE_FIX_ISSUE_2518 Word16 Q_exc; #endif -- GitLab From a1331dc085ad9336670037bdee7b9616061e2662 Mon Sep 17 00:00:00 2001 From: Manuel Jander Date: Thu, 30 Apr 2026 09:16:24 +0200 Subject: [PATCH 17/17] Fix ivas_pytest_on_merge crash (saturation of mem_decim16k_fx) --- lib_enc/ivas_core_pre_proc_front_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index cc7a06671..77be7fe6d 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -754,7 +754,7 @@ void pre_proc_front_ivas_fx( shift = add( shift, st->q_inp ); /* Avoid saturation of resampling/delay decimation buffer. */ - shift = s_min( shift, add( st->q_mem_decim16k_fx, 1 ) ); + shift = s_min( shift, st->q_mem_decim16k_fx ); /* Limit Q_new here to st->q_inp because inside ivas_compute_core_buffers_fx() st->input is rescaled to Q_new */ shift = s_min( shift, st->q_inp ); -- GitLab