From 4d598116bb8d5713e8276fa9dc1113e6be67da70 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Mon, 1 Jun 2026 10:53:13 +0300 Subject: [PATCH 1/3] Fix BASOP issue 1765 by improving improving accuracy in FD CNG noise estimation. --- lib_com/basop_util.c | 14 ++++++++++++-- lib_com/options.h | 1 + lib_dec/fd_cng_dec_fx.c | 8 ++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib_com/basop_util.c b/lib_com/basop_util.c index 335f61c1e..c1ee858f4 100644 --- a/lib_com/basop_util.c +++ b/lib_com/basop_util.c @@ -2726,19 +2726,29 @@ Word32 dotWord32_16_Mant32Exp( const Word32 *bufX32, /* i: 32-bit buffer with un Word16 shift, shift1, i; - shift = getScaleFactor32( bufX32, len ); /* current available headroom */ + shift = getScaleFactor32( bufX32, len ); /* current available headroom */ +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + shift = sub( shift, sub( 15, norm_s( len ) ) ); /* reduced required headroom */ +#else shift = sub( shift, sub( 14, norm_s( len ) ) ); /* reduced required headroom */ - L_sum = 0; /* Clear accu */ +#endif + L_sum = 0; /* Clear accu */ move32(); FOR( i = 0; i < len; i++ ) { +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + L_sum = L_add( L_sum, Mpy_32_16_1( L_shl( bufX32[i], shift ), bufY16[i] ) ); +#else L_sum = L_mac0( L_sum, round_fx( L_shl( bufX32[i], shift ) ), bufY16[i] ); +#endif } shift1 = norm_l( L_sum ); L_sum = L_shl( L_sum, shift1 ); /* return value */ shift = sub( add( bufX32_exp, bufY16_exp ), add( shift, shift1 ) ); +#ifndef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH shift = add( shift, 1 ); /* compensate for factor of 2 introduced by L_mac0 */ +#endif /* In case of NULL result, we want to have a 0 exponent too */ if ( L_sum == 0 ) shift = 0; diff --git a/lib_com/options.h b/lib_com/options.h index a1b758cfc..174089845 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -106,6 +106,7 @@ #define FIX_BASOP_2599_TCA_OVERFLOW /* VA: issue 2599, Fix TCA overflow */ #define FIX_2588_MISSING_CONDITIONS /* VA: Proposed fix to 2588, addition of a condition in lsf_dec */ #define FIX_BASOP_2442_MASA2TC_TO_MONO_AND_AMBI /* Nokia: BASOP issue 2442: Increase accuracy of computations and add additional gain clamp for low energy decorrelated signal rendering. */ +#define FIX_BASOP_1765_MASA1TC_CNG_MISMATCH /* Nokia: BASOP issue 1765: Improve accuracy of FD CNG noise estimation */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index dc24fc6f9..a00ba59d3 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -1481,7 +1481,11 @@ void perform_noise_estimation_dec_ivas_fx( FOR( p = 0; p < npart; p++ ) { temp = L_shl( msPeriodog[p], q_shift ); +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + msNoiseEst[p] = Madd_32_16( Mpy_32_16_r( msNoiseEst[p], add( sub( MAX_16, alpha ), 1 ) ), temp, alpha ); /*Q31 - hFdCngDec->msNoiseEst_exp*/ /* add one to alpha comp to get ONE_IN_Q15 - alpha */ +#else msNoiseEst[p] = Madd_32_16( Mpy_32_16_r( msNoiseEst[p], sub( MAX_16, alpha ) ), temp, alpha ); /*Q31 - hFdCngDec->msNoiseEst_exp*/ +#endif move32(); } } @@ -1681,7 +1685,11 @@ void perform_noise_estimation_dec_ivas_fx( move16(); } } +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + *ptr_per = Madd_32_16( ( *ptr_per ), enr, add( sub( MAX_16, alpha ), 1 ) ); /*Q31 - enr_e*/ /* add one to alpha comp to get ONE_IN_Q15 - alpha */ +#else *ptr_per = Madd_32_16( ( *ptr_per ), enr, sub( MAX_16, alpha ) ); /*Q31 - enr_e*/ +#endif move32(); ptr_per++; } -- GitLab From 04ff9d8ba3e490f3b61e62a509064ed846b6dea1 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Tue, 2 Jun 2026 11:19:19 +0300 Subject: [PATCH 2/3] Add changes to maintain EVS BE. --- lib_com/basop_util.c | 32 ++++++++++++++++++++++---- lib_com/basop_util.h | 7 +++++- lib_com/prot_fx.h | 5 ++++ lib_dec/acelp_core_dec_fx.c | 4 ++++ lib_dec/amr_wb_dec_fx.c | 4 ++++ lib_dec/evs_dec_fx.c | 4 ++++ lib_dec/fd_cng_dec_fx.c | 9 ++++++++ lib_dec/ivas_stereo_mdct_core_dec_fx.c | 4 ++++ lib_dec/ivas_tcx_core_dec_fx.c | 4 ++++ 9 files changed, 68 insertions(+), 5 deletions(-) diff --git a/lib_com/basop_util.c b/lib_com/basop_util.c index c1ee858f4..3b1a0cf21 100644 --- a/lib_com/basop_util.c +++ b/lib_com/basop_util.c @@ -2720,7 +2720,12 @@ Word32 dotWord32_16_Mant32Exp( const Word32 *bufX32, /* i: 32-bit buffer with un const Word16 *bufY16, /* i: 16-bit buffer quite right-aligned */ Word16 bufY16_exp, /* i: exponent of buffer bufY16 */ Word16 len, /* i: buffer len to process */ - Word16 *exp ) /* o: result exponent */ +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + Word16 *exp, /* o: result exponent */ + const Word16 is_ivas ) /* i: flag indicating IVAS to maintain EVS BE */ +#else + Word16 *exp ) /* o: result exponent */ +#endif { Word32 L_sum; Word16 shift, shift1, i; @@ -2728,7 +2733,14 @@ Word32 dotWord32_16_Mant32Exp( const Word32 *bufX32, /* i: 32-bit buffer with un shift = getScaleFactor32( bufX32, len ); /* current available headroom */ #ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH - shift = sub( shift, sub( 15, norm_s( len ) ) ); /* reduced required headroom */ + IF( EQ_16( is_ivas, 1 ) ) + { + shift = sub( shift, sub( 15, norm_s( len ) ) ); /* reduced required headroom */ + } + ELSE + { + shift = sub( shift, sub( 14, norm_s( len ) ) ); /* reduced required headroom */ + } #else shift = sub( shift, sub( 14, norm_s( len ) ) ); /* reduced required headroom */ #endif @@ -2737,7 +2749,14 @@ Word32 dotWord32_16_Mant32Exp( const Word32 *bufX32, /* i: 32-bit buffer with un FOR( i = 0; i < len; i++ ) { #ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH - L_sum = L_add( L_sum, Mpy_32_16_1( L_shl( bufX32[i], shift ), bufY16[i] ) ); + IF( EQ_16( is_ivas, 1 ) ) + { + L_sum = L_add( L_sum, Mpy_32_16_1( L_shl( bufX32[i], shift ), bufY16[i] ) ); + } + ELSE + { + L_sum = L_mac0( L_sum, round_fx( L_shl( bufX32[i], shift ) ), bufY16[i] ); + } #else L_sum = L_mac0( L_sum, round_fx( L_shl( bufX32[i], shift ) ), bufY16[i] ); #endif @@ -2746,7 +2765,12 @@ Word32 dotWord32_16_Mant32Exp( const Word32 *bufX32, /* i: 32-bit buffer with un L_sum = L_shl( L_sum, shift1 ); /* return value */ shift = sub( add( bufX32_exp, bufY16_exp ), add( shift, shift1 ) ); -#ifndef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + IF( EQ_16( is_ivas, 0 ) ) + { + shift = add( shift, 1 ); /* compensate for factor of 2 introduced by L_mac0 */ + } +#else shift = add( shift, 1 ); /* compensate for factor of 2 introduced by L_mac0 */ #endif /* In case of NULL result, we want to have a 0 exponent too */ diff --git a/lib_com/basop_util.h b/lib_com/basop_util.h index d52830430..19b0bb4aa 100644 --- a/lib_com/basop_util.h +++ b/lib_com/basop_util.h @@ -864,7 +864,12 @@ Word32 dotWord32_16_Mant32Exp( const Word32 *bufX32, /* i: 32-bit buffer with un const Word16 *bufY16, /* i: 16-bit buffer quite right-aligned */ Word16 bufY16_exp, /* i: exponent of buffer bufY16 */ Word16 len, /* i: buffer len to process */ - Word16 *exp ); /* o: result exponent */ +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + Word16 *exp, /* o: result exponent */ + const Word16 is_ivas ); /* i: flag indicating IVAS to maintain EVS BE */ +#else + Word16 *exp ); /* o: result exponent */ +#endif /*!********************************************************************** \brief Converts linear factor or energy to Decibel diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 6458662e7..f4d4c2c3b 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -6448,7 +6448,12 @@ void noisy_speech_detection_fx( HANDLE_FD_CNG_DEC hFdCngDec, /* i/o: FD_CNG structure */ const Word16 vad, /* i : VAD flag */ const Word16 *syn, /* i : i time-domain frame */ +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + const Word16 Q, + const Word16 is_ivas ); +#else const Word16 Q ); +#endif void generate_comfort_noise_dec_fx( Word32 **bufferReal, /* o : matrix to real part of i bands */ diff --git a/lib_dec/acelp_core_dec_fx.c b/lib_dec/acelp_core_dec_fx.c index f0d79382c..46ab4a810 100644 --- a/lib_dec/acelp_core_dec_fx.c +++ b/lib_dec/acelp_core_dec_fx.c @@ -1549,7 +1549,11 @@ ivas_error acelp_core_dec_fx( IF( st->idchan == 0 && ( st->flag_cna || ( EQ_16( st->cng_type, FD_CNG ) && LE_32( st->total_brate, ACELP_32k ) ) || ( st->cng_type == LP_CNG && LE_32( st->core_brate, SID_2k40 ) ) ) ) { /*Noisy speech detector*/ +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + noisy_speech_detection_fx( st->hFdCngDec, st->VAD, psyn_fx, st->Q_syn, 1 ); +#else noisy_speech_detection_fx( st->hFdCngDec, st->VAD, psyn_fx, st->Q_syn ); +#endif st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = mult_r( st->hFdCngDec->hFdCngCom->likelihood_noisy_speech, 32440 /*0.99 Q15*/ ); move16(); diff --git a/lib_dec/amr_wb_dec_fx.c b/lib_dec/amr_wb_dec_fx.c index 1fdfe44a4..fbe877f58 100644 --- a/lib_dec/amr_wb_dec_fx.c +++ b/lib_dec/amr_wb_dec_fx.c @@ -798,7 +798,11 @@ ivas_error amr_wb_dec_fx( move16(); /*Noisy speech detector*/ +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + noisy_speech_detection_fx( st_fx->hFdCngDec, st_fx->VAD, syn_fx, st_fx->Q_syn, 0 ); +#else noisy_speech_detection_fx( st_fx->hFdCngDec, st_fx->VAD, syn_fx, st_fx->Q_syn ); +#endif st_fx->hFdCngDec->hFdCngCom->likelihood_noisy_speech = mult_r( st_fx->hFdCngDec->hFdCngCom->likelihood_noisy_speech, 32440 /*0.99 Q15*/ ); IF( st_fx->hFdCngDec->hFdCngCom->flag_noisy_speech != 0 ) diff --git a/lib_dec/evs_dec_fx.c b/lib_dec/evs_dec_fx.c index add3a07c3..85fde0949 100644 --- a/lib_dec/evs_dec_fx.c +++ b/lib_dec/evs_dec_fx.c @@ -940,7 +940,11 @@ ivas_error evs_dec_fx( * -------------------------------------------------------------- */ HANDLE_FD_CNG_DEC hFdCngDec = st_fx->hFdCngDec; +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + noisy_speech_detection_fx( st_fx->hFdCngDec, st_fx->VAD && EQ_16( st_fx->m_frame_type, ACTIVE_FRAME ), output_sp, 0, 0 ); +#else noisy_speech_detection_fx( st_fx->hFdCngDec, st_fx->VAD && EQ_16( st_fx->m_frame_type, ACTIVE_FRAME ), output_sp, 0 ); +#endif hFdCngDec->hFdCngCom->likelihood_noisy_speech = mult_r( hFdCngDec->hFdCngCom->likelihood_noisy_speech, 32440 /*0.99 Q15*/ ); /*Q15*/ if ( hFdCngDec->hFdCngCom->flag_noisy_speech != 0 ) diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index a00ba59d3..6e44864a9 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -2101,7 +2101,12 @@ void noisy_speech_detection_fx( HANDLE_FD_CNG_DEC hFdCngDec, /* i/o: FD_CNG structure */ const Word16 vad, /*Q0*/ const Word16 *syn, /* i : input time-domain frame Q*/ +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + const Word16 Q, + const Word16 is_ivas ) +#else const Word16 Q ) +#endif { Word16 i; Word32 tmp; @@ -2117,7 +2122,11 @@ void noisy_speech_detection_fx( IF( vad == 0 ) { +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + totalNoise = dotWord32_16_Mant32Exp( hFdCngDec->msNoiseEst, hFdCngDec->msNoiseEst_exp, hFdCngDec->psize_shaping_norm, hFdCngDec->psize_shaping_norm_exp, hFdCngDec->nFFTpart_shaping, &totalNoise_exp, is_ivas ); /*Q31 - totalNoise_exp*/ +#else totalNoise = dotWord32_16_Mant32Exp( hFdCngDec->msNoiseEst, hFdCngDec->msNoiseEst_exp, hFdCngDec->psize_shaping_norm, hFdCngDec->psize_shaping_norm_exp, hFdCngDec->nFFTpart_shaping, &totalNoise_exp ); /*Q31 - totalNoise_exp*/ +#endif /* - logTotalNoise is scaled by LD_DATA_SCALE+2 diff --git a/lib_dec/ivas_stereo_mdct_core_dec_fx.c b/lib_dec/ivas_stereo_mdct_core_dec_fx.c index c64baefe6..d04d30a06 100644 --- a/lib_dec/ivas_stereo_mdct_core_dec_fx.c +++ b/lib_dec/ivas_stereo_mdct_core_dec_fx.c @@ -1023,7 +1023,11 @@ static void run_min_stats_fx( Copy_Scale_sig32_16( x[ch][0], x_fx_16, L_FRAME16k, 0 ); /* exp(x_e) */ test(); +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + noisy_speech_detection_fx( st->hFdCngDec, save_VAD[ch] && EQ_16( st->m_frame_type, ACTIVE_FRAME ), x_fx_16, sub( Q15, x_e[ch][0] ), 1 ); +#else noisy_speech_detection_fx( st->hFdCngDec, save_VAD[ch] && EQ_16( st->m_frame_type, ACTIVE_FRAME ), x_fx_16, sub( Q15, x_e[ch][0] ) ); +#endif st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = add( mult_r( 32440 /* 0.99 in Q15 */, st->hFdCngDec->hFdCngCom->likelihood_noisy_speech ), mult_r( st->hFdCngDec->hFdCngCom->flag_noisy_speech, 328 /* 0.01 in Q15 */ ) ); /* Q15 */ move16(); st->lp_noise = st->hFdCngDec->lp_noise; /* Q9.23 */ diff --git a/lib_dec/ivas_tcx_core_dec_fx.c b/lib_dec/ivas_tcx_core_dec_fx.c index 599329953..cd03669c3 100644 --- a/lib_dec/ivas_tcx_core_dec_fx.c +++ b/lib_dec/ivas_tcx_core_dec_fx.c @@ -837,7 +837,11 @@ void stereo_tcx_core_dec_fx( test(); IF( st->hFdCngDec != NULL && ( EQ_32( st->sr_core, INT_FS_12k8 ) || EQ_32( st->sr_core, INT_FS_16k ) ) && LE_32( st->total_brate, MAX_ACELP_BRATE ) ) { +#ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH + noisy_speech_detection_fx( st->hFdCngDec, st->VAD && EQ_16( st->m_frame_type, ACTIVE_FRAME ), signal_out_fx, 0, 1 ); +#else noisy_speech_detection_fx( st->hFdCngDec, st->VAD && EQ_16( st->m_frame_type, ACTIVE_FRAME ), signal_out_fx, 0 ); +#endif st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = add( mult_r( 32440 /* 0.99f in Q15 */, st->hFdCngDec->hFdCngCom->likelihood_noisy_speech ), mult_r( st->hFdCngDec->hFdCngCom->flag_noisy_speech, 328 /* 0.01f in Q15 */ ) ); /* Q15 */ st->lp_noise = st->hFdCngDec->lp_noise; /* Q9.23 */ move16(); -- GitLab From a7049067ef4c66ddc86df97a241231c1e165ee57 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Tue, 2 Jun 2026 11:58:03 +0300 Subject: [PATCH 3/3] One more change to maintain EVS BE. --- lib_dec/acelp_core_dec_fx.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib_dec/acelp_core_dec_fx.c b/lib_dec/acelp_core_dec_fx.c index 46ab4a810..cdb551e70 100644 --- a/lib_dec/acelp_core_dec_fx.c +++ b/lib_dec/acelp_core_dec_fx.c @@ -1550,7 +1550,14 @@ ivas_error acelp_core_dec_fx( { /*Noisy speech detector*/ #ifdef FIX_BASOP_1765_MASA1TC_CNG_MISMATCH - noisy_speech_detection_fx( st->hFdCngDec, st->VAD, psyn_fx, st->Q_syn, 1 ); + IF( NE_16( st->element_mode, EVS_MONO ) ) + { + noisy_speech_detection_fx( st->hFdCngDec, st->VAD, psyn_fx, st->Q_syn, 1 ); + } + ELSE + { + noisy_speech_detection_fx( st->hFdCngDec, st->VAD, psyn_fx, st->Q_syn, 0 ); + } #else noisy_speech_detection_fx( st->hFdCngDec, st->VAD, psyn_fx, st->Q_syn ); #endif -- GitLab