From 9692a5a2fb59d32a54929e0a8042d09f417a0aae Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Tue, 26 May 2026 14:24:03 +0200 Subject: [PATCH 1/3] add code and macros for HARMONIZE_2604_decoder_tcx_post --- lib_com/options.h | 1 + lib_com/prot_fx.h | 27 ++- lib_dec/dec_LPD_fx.c | 4 + lib_dec/dec_tcx_fx.c | 301 ++++++++++++++++++++++++-------- lib_dec/ivas_mdct_core_dec_fx.c | 4 + lib_dec/ivas_tcx_core_dec_fx.c | 4 + 6 files changed, 257 insertions(+), 84 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 1d498d32d..ef06a4299 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -94,6 +94,7 @@ #define FIX_FLOAT_1539_G192_FORMAT_SWITCH /* VA/Nokia: reintroduce format switching for g192 bitstreams */ #define HARMONIZE_2595_reconfig_decoder_LPD /* FhG: Harmonize reconfig_decoder_LPD with its ivas derivate */ #define HARMONIZE_2596_SetModeIndex /* FhG: Harmonize SetModeIndex with its ivas derivate */ +#define HARMONIZE_2604_decoder_tcx_post /* FhG: Harmonize decoder_tcx_post with its ivas derivate */ /* #################### End BE switches ################################## */ diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 056cba33b..ea57b9a53 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -7996,12 +7996,14 @@ void decoder_tcx_ivas_fx( const Word16 frame_cnt, const Word16 sba_dirac_stereo_flag ); +#ifndef HARMONIZE_2604_decoder_tcx_post void decoder_tcx_post_fx( Decoder_State *st_fx, Word16 *synth, Word16 *synthFB, Word16 *A, Word16 bfi ); +#endif void tcx_arith_decode_envelope_fx( Word32 q_spectrum[], /* o: quantised MDCT coefficients Q31-e */ @@ -8425,14 +8427,23 @@ UWord32 mvl2s_r( const Word16 n /* i : vector size */ ); -void decoder_tcx_post_ivas_fx( - Decoder_State *st_fx, - Word16 *synth, - Word16 *synthFB, - Word16 Q_syn, - Word16 *A, - Word16 bfi, - Word16 MCT_flag ); +#ifdef HARMONIZE_2604_decoder_tcx_post +void decoder_tcx_post_fx( Decoder_State *st_fx, + Word16 *synth, // Q_syn + Word16 *synthFB, // Q_syn + Word16 Q_syn, + Word16 *A, // Q: 14 - norm_s(A[0]) + Word16 bfi, + Word16 MCT_flag ); +#else +void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, + Word16 *synth, // Q_syn + Word16 *synthFB, // Q_syn + Word16 Q_syn, + Word16 *A, // Q: 14 - norm_s(A[0]) + Word16 bfi, + Word16 MCT_flag ); +#endif void con_tcx_fx( Decoder_State *st, /* i/o: coder memory state */ diff --git a/lib_dec/dec_LPD_fx.c b/lib_dec/dec_LPD_fx.c index 671d20d5c..9fee8f8a4 100644 --- a/lib_dec/dec_LPD_fx.c +++ b/lib_dec/dec_LPD_fx.c @@ -770,7 +770,11 @@ void decoder_LPD_fx( { TonalMDCTConceal_SaveTimeSignal_fx( st->element_mode, st->hTonalMDCTConc, synthFB, 0, L_frameTCX ); } +#ifdef HARMONIZE_2604_decoder_tcx_post + decoder_tcx_post_fx( st, synth, synthFB, 0, Aq, bfi, 0 ); +#else decoder_tcx_post_fx( st, synth, synthFB, Aq, bfi ); +#endif IF( EQ_16( st->core, TCX_20_CORE ) ) { /* LPC Interpolation for BWE/post-processing */ diff --git a/lib_dec/dec_tcx_fx.c b/lib_dec/dec_tcx_fx.c index db29982a5..882799e72 100644 --- a/lib_dec/dec_tcx_fx.c +++ b/lib_dec/dec_tcx_fx.c @@ -1256,7 +1256,7 @@ void decoder_tcx_fx( Copy( xn_bufFB + sub( shr( overlapFB, 1 ), tcx_offsetFB ), synthFB, L_frameTCX_glob ); } - +#ifndef HARMONIZE_2604_decoder_tcx_post void decoder_tcx_post_fx( Decoder_State *st_fx, Word16 *synth, Word16 *synthFB, @@ -1517,7 +1517,17 @@ void decoder_tcx_post_fx( Decoder_State *st_fx, move16(); } } +#endif /*HARMONIZE_2604_decoder_tcx_post*/ +#ifdef HARMONIZE_2604_decoder_tcx_post +void decoder_tcx_post_fx( Decoder_State *st_fx, + Word16 *synth, // Q_syn + Word16 *synthFB, // Q_syn + Word16 Q_syn, + Word16 *A, // Q: 14 - norm_s(A[0]) + Word16 bfi, + Word16 MCT_flag ) /*EVS: 0*/ +#else void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, Word16 *synth, // Q_syn Word16 *synthFB, // Q_syn @@ -1525,6 +1535,7 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, Word16 *A, // Q: 14 - norm_s(A[0]) Word16 bfi, Word16 MCT_flag ) +#endif { Word16 i; Word16 level_syn; @@ -1568,6 +1579,8 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, test(); test(); /* run lpc gain compensation not for waveform adjustment */ + test(); + test(); IF( 0 == st_fx->enablePlcWaveadjust || ( st_fx->hPlcInfo != NULL && EQ_16( st_fx->hPlcInfo->concealment_method, TCX_TONAL ) ) ) { UWord32 dmy; @@ -1635,12 +1648,42 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, test(); test(); test(); +#ifdef HARMONIZE_2604_decoder_tcx_post + IF( bfi == 0 && st_fx->tcxonly != 0 && ( ( GT_16( st_fx->element_mode, EVS_MONO ) && ( NE_16( st_fx->element_mode, IVAS_CPE_MDCT ) || MCT_flag ) ) || EQ_16( st_fx->element_mode, EVS_MONO ) ) && EQ_16( st_fx->clas_dec, UNVOICED_CLAS ) ) +#else IF( bfi == 0 && st_fx->tcxonly != 0 && ( NE_16( st_fx->element_mode, IVAS_CPE_MDCT ) || MCT_flag ) && EQ_16( st_fx->clas_dec, UNVOICED_CLAS ) ) +#endif { Word16 Qnew_levelBackgroundTrace; Qnew_levelBackgroundTrace = 0; move16(); +#ifdef HARMONIZE_2604_decoder_tcx_post + Word16 *NoiseLevelIndex_tmp, *CurrLevelIndex_tmp; + IF( EQ_16( st_fx->element_mode, EVS_MONO ) ) + { + NoiseLevelIndex_tmp = &hTcxDec->conNoiseLevelIndex; + CurrLevelIndex_tmp = &hTcxDec->conCurrLevelIndex; + } + ELSE + { + NoiseLevelIndex_tmp = &hTcxDec->NoiseLevelIndex_bfi; + CurrLevelIndex_tmp = &hTcxDec->CurrLevelIndex_bfi; + } + + minimumStatistics_fx( hTcxDec->conNoiseLevelMemory, /*Q15*/ + NoiseLevelIndex_tmp, /*Q0 */ + CurrLevelIndex_tmp, /*Q0 */ + &hTcxDec->conCngLevelBackgroundTrace, /*Q15*/ + &hTcxDec->conLastFrameLevel, /*Q15*/ + level_syn, /*Q15*/ + hTcxDec->conNoiseLevelMemory_e, + hTcxDec->conCngLevelBackgroundTrace_e, + &Qnew_levelBackgroundTrace, + &hTcxDec->conLastFrameLevel_e, + level_syn_e /*scaling of level_syn*/ + ); +#else minimumStatistics_fx( hTcxDec->conNoiseLevelMemory, /*Q15*/ &hTcxDec->NoiseLevelIndex_bfi, /*Q0 */ &hTcxDec->CurrLevelIndex_bfi, /*Q0 */ @@ -1653,6 +1696,7 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, &hTcxDec->conLastFrameLevel_e, level_syn_e /*scaling of level_syn*/ ); +#endif /*note: All parameters being different from Q0 have to have the same Q-format*/ @@ -1664,6 +1708,9 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, * PLC: fade-out in time domain */ IF( bfi != 0 ) { +#ifdef HARMONIZE_2604_decoder_tcx_post + Word32 conceal_eof_gain32; +#endif Word32 conceal_eof_gainFB; Word16 conceal_eof_gainFB_e; move16(); @@ -1673,17 +1720,24 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, IF( st_fx->tcxonly != 0 ) { /*gainCNG = st_fx->conCngLevelBackgroundTrace/(tracingLevel+0.01f);*/ - IF( level_syn ) +#ifdef HARMONIZE_2604_decoder_tcx_post + IF( GT_16( st_fx->element_mode, EVS_MONO ) ) { - level_syn_e = BASOP_Util_Add_MantExp( level_syn, level_syn_e, 20992, -6, &level_syn ); /* 0.01 in Q21*/ - } - ELSE - { - level_syn = 328; /* (1 / 0.01) in Q15 */ - level_syn_e = 0; - move16(); - move16(); +#endif + IF( level_syn ) + { + level_syn_e = BASOP_Util_Add_MantExp( level_syn, level_syn_e, 20992, -6, &level_syn ); /* 0.01 in Q21*/ + } + ELSE + { + level_syn = 328; /* (1 / 0.01) in Q15 */ + level_syn_e = 0; + move16(); + move16(); + } +#ifdef HARMONIZE_2604_decoder_tcx_post } +#endif IF( level_syn != 0 ) { @@ -1695,36 +1749,50 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, &gainCNG, &gainCNG_e ); } - test(); - IF( EQ_16( st_fx->element_mode, IVAS_CPE_MDCT ) && !MCT_flag ) +#ifdef HARMONIZE_2604_decoder_tcx_post + IF( GT_16( st_fx->element_mode, EVS_MONO ) ) { - IF( GT_16( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME + MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN ) ) - { - gainCNG = 0; - move16(); - } - ELSE IF( GT_16( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) ) +#endif + test(); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_MDCT ) && !MCT_flag ) { - // gainCNG *= 1.f - (float) sub( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN; - tmp32 = L_sub( ONE_IN_Q31, imult3216( 107374182 /* 1 / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN in Q31*/, sub( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) ) ); /* Q31 */ - gainCNG = extract_l( Mpy_32_32( gainCNG, tmp32 ) ); + IF( GT_16( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME + MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN ) ) + { + gainCNG = 0; + move16(); + } + ELSE IF( GT_16( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) ) + { + // gainCNG *= 1.f - (float) sub( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN; + tmp32 = L_sub( ONE_IN_Q31, imult3216( 107374182 /* 1 / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN in Q31*/, sub( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) ) ); /* Q31 */ + gainCNG = extract_l( Mpy_32_32( gainCNG, tmp32 ) ); + } } +#ifdef HARMONIZE_2604_decoder_tcx_post } +#endif } ELSE { /*gainCNG = st_fx->cngTDLevel/(tracingLevel+0.01f);*/ - IF( level_syn ) +#ifdef HARMONIZE_2604_decoder_tcx_post + IF( GT_16( st_fx->element_mode, EVS_MONO ) ) { - level_syn_e = BASOP_Util_Add_MantExp( level_syn, level_syn_e, 20992, -6, &level_syn ); /* 0.01 in Q21*/ - } - ELSE - { - level_syn = 328; /* (1 / 0.01) in Q15 */ - level_syn_e = 0; - move16(); - move16(); +#endif + IF( level_syn ) + { + level_syn_e = BASOP_Util_Add_MantExp( level_syn, level_syn_e, 20992, -6, &level_syn ); /* 0.01 in Q21*/ + } + ELSE + { + level_syn = 328; /* (1 / 0.01) in Q15 */ + level_syn_e = 0; + move16(); + move16(); + } +#ifdef HARMONIZE_2604_decoder_tcx_post } +#endif IF( level_syn != 0 ) { @@ -1738,61 +1806,57 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, } } - IF( ( EQ_16( st_fx->nbLostCmpt, 1 ) ) ) - { - hTcxDec->conceal_eof_gain32 = ONE_IN_Q30 /*1.0f Q30*/; - move32(); - hTcxDec->conceal_eof_gain_e = 1; - move16(); - } - - /* step = (st_fx->conceal_eof_gain - ( st_fx->conceal_eof_gain * st_fx->damping + gainCNG * (1 - st_fx->damping) )) / st_fx->L_frame; */ - Word32 L_tmp = BASOP_Util_Add_Mant32Exp( - Mpy_32_16_1( hTcxDec->conceal_eof_gain32, - hTcxDec->damping /*Q14*/ ), - add( 1, hTcxDec->conceal_eof_gain_e ) /*->Q15*/, - L_mult( gainCNG /*Q15*/, sub( 0x4000, hTcxDec->damping /*Q14*/ ) ) /*Q14*/, - add( gainCNG_e, 15 - 14 ) /*->Q15*/, - &tmp2 ); - L_tmp = BASOP_Util_Add_Mant32Exp( hTcxDec->conceal_eof_gain32, hTcxDec->conceal_eof_gain_e, L_negate( L_tmp ), tmp2, &tmp2 ); - step = Mpy_32_16_1( L_tmp, getInvFrameLen( st_fx->L_frame ) ); - step_e = sub( tmp2, 6 ); +#ifdef HARMONIZE_2604_decoder_tcx_post + IF( EQ_16( st_fx->element_mode, EVS_MONO ) ) { - Word32 stepFB; - Word16 stepFB_e; - UWord32 dmy; - Word16 tmp_shift; - conceal_eof_gainFB = hTcxDec->conceal_eof_gain32; - conceal_eof_gainFB_e = hTcxDec->conceal_eof_gain_e; - move32(); - move16(); - Mpy_32_32_ss( step, L_shl( L_mult0( st_fx->L_frame, getInvFrameLen( hTcxDec->L_frameTCX ) ), 8 ), &stepFB, &dmy ); - stepFB_e = add( step_e, 2 ); + IF( ( EQ_16( st_fx->nbLostCmpt, 1 ) ) ) + { + hTcxDec->conceal_eof_gain = 16384 /*1.0f Q14*/; /*Q14*/ + move16(); + } - FOR( i = 0; i < hTcxDec->L_frameTCX; i++ ) + /* step = (st_fx->conceal_eof_gain - ( st_fx->conceal_eof_gain * st_fx->damping + gainCNG * (1 - st_fx->damping) )) / st_fx->L_frame; */ + tmp2 = BASOP_Util_Add_MantExp( + mult_r( hTcxDec->conceal_eof_gain /*Q14*/, + hTcxDec->damping /*Q14*/ ), + 15 - 13 /*->Q15*/, + mult_r( gainCNG /*Q15*/, sub( 0x4000, hTcxDec->damping /*Q14*/ ) ) /*Q14*/, + add( gainCNG_e, 15 - 14 ) /*->Q15*/, + &tmp1 ); + tmp2 = BASOP_Util_Add_MantExp( hTcxDec->conceal_eof_gain, 15 - 14, negate( tmp1 ), tmp2, &tmp1 ); + + step = L_shl_sat( L_mult( tmp1, getInvFrameLen( st_fx->L_frame ) ), sub( tmp2, 6 /*scaling from table lookup*/ + 1 /*go to Q30*/ ) ); /*Q30*/ + { + Word32 stepFB; + UWord32 dmy; + conceal_eof_gainFB = L_deposit_h( hTcxDec->conceal_eof_gain ); /*Q30*/ + Mpy_32_32_ss( step, L_shl( L_mult0( st_fx->L_frame, getInvFrameLen( hTcxDec->L_frameTCX ) ), 8 ), &stepFB, &dmy ); + stepFB = L_shl_sat( stepFB, 3 - 1 ); /*Q30*/ + FOR( i = 0; i < hTcxDec->L_frameTCX; i++ ) + { + synthFB[i] = round_fx_sat( L_shl_sat( Mpy_32_16_1( conceal_eof_gainFB, synthFB[i] ), 1 ) ); + move16(); + conceal_eof_gainFB = L_sub_sat( conceal_eof_gainFB, stepFB ); + } + } + conceal_eof_gain32 = L_deposit_h( hTcxDec->conceal_eof_gain ); /*Q30*/ + FOR( i = 0; i < st_fx->L_frame; i++ ) { - tmp_shift = conceal_eof_gainFB_e; - synthFB[i] = round_fx_sat( L_shl_sat( Mpy_32_16_1( conceal_eof_gainFB, synthFB[i] ), tmp_shift ) ); // Q_syn + xn_buf[i] = round_fx_sat( L_shl_sat( Mpy_32_16_1( conceal_eof_gain32 /*Q30*/, xn_buf[i] ), 1 ) ); move16(); - conceal_eof_gainFB = BASOP_Util_Add_Mant32Exp( conceal_eof_gainFB, conceal_eof_gainFB_e, L_negate( stepFB ), stepFB_e, &conceal_eof_gainFB_e ); // Q: 31 - conceal_eof_gainFB_e + conceal_eof_gain32 = L_sub_sat( conceal_eof_gain32, step ); } - } - FOR( i = 0; i < st_fx->L_frame; i++ ) - { - xn_buf[i] = round_fx_sat( L_shl_sat( Mpy_32_16_1( hTcxDec->conceal_eof_gain32, xn_buf[i] ), hTcxDec->conceal_eof_gain_e ) ); // Qx + hTcxDec->conceal_eof_gain = round_fx_sat( conceal_eof_gain32 ); /*Q14*/ move16(); - hTcxDec->conceal_eof_gain32 = BASOP_Util_Add_Mant32Exp( hTcxDec->conceal_eof_gain32, hTcxDec->conceal_eof_gain_e, L_negate( step ), step_e, &hTcxDec->conceal_eof_gain_e ); - move32(); - } - - /* run lpc gain compensation not for waveform adjustment */ - IF( st_fx->hPlcInfo != NULL ) - { + /* run lpc gain compensation not for waveform adjustment */ test(); IF( 0 == st_fx->enablePlcWaveadjust || EQ_16( st_fx->hPlcInfo->concealment_method, TCX_TONAL ) ) { - st_fx->hPlcInfo->recovery_gain = extract_h( L_shl_sat( Mpy_32_16_1( conceal_eof_gainFB, st_fx->last_concealed_gain_syn_deemph ), st_fx->last_concealed_gain_syn_deemph_e ) ); /*Q30->Q14*/ + st_fx->hPlcInfo->recovery_gain = extract_h( L_shl_sat( Mpy_32_16_1( conceal_eof_gainFB, + st_fx->last_concealed_gain_syn_deemph ), + st_fx->last_concealed_gain_syn_deemph_e ) ); + /*Q30->Q14*/ move16(); } ELSE @@ -1800,9 +1864,82 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, st_fx->hPlcInfo->recovery_gain = extract_h( conceal_eof_gainFB ); /*Q14*/ move16(); } - st_fx->hPlcInfo->step_concealgain_fx = round_fx_sat( L_shl_sat( L_mult0( round_fx_sat( L_shr_sat( step, sub( 1, step_e ) ) ), round_fx_sat( L_shl_sat( L_mult0( st_fx->L_frame, getInvFrameLen( hTcxDec->L_frameTCX ) ), 8 ) ) ), 4 ) ); /*Q15*/ + st_fx->hPlcInfo->step_concealgain_fx = round_fx_sat( L_shl_sat( L_mult0( round_fx_sat( step ), round_fx_sat( L_shl_sat( L_mult0( st_fx->L_frame, getInvFrameLen( hTcxDec->L_frameTCX ) ), 8 ) ) ), 3 ) ); /*Q15*/ move16(); } + ELSE + { +#endif + + + IF( ( EQ_16( st_fx->nbLostCmpt, 1 ) ) ) + { + hTcxDec->conceal_eof_gain32 = ONE_IN_Q30 /*1.0f Q30*/; + move32(); + hTcxDec->conceal_eof_gain_e = 1; + move16(); + } + + /* step = (st_fx->conceal_eof_gain - ( st_fx->conceal_eof_gain * st_fx->damping + gainCNG * (1 - st_fx->damping) )) / st_fx->L_frame; */ + Word32 L_tmp = BASOP_Util_Add_Mant32Exp( + Mpy_32_16_1( hTcxDec->conceal_eof_gain32, + hTcxDec->damping /*Q14*/ ), + add( 1, hTcxDec->conceal_eof_gain_e ) /*->Q15*/, + L_mult( gainCNG /*Q15*/, sub( 0x4000, hTcxDec->damping /*Q14*/ ) ) /*Q14*/, + add( gainCNG_e, 15 - 14 ) /*->Q15*/, + &tmp2 ); + + L_tmp = BASOP_Util_Add_Mant32Exp( hTcxDec->conceal_eof_gain32, hTcxDec->conceal_eof_gain_e, L_negate( L_tmp ), tmp2, &tmp2 ); + step = Mpy_32_16_1( L_tmp, getInvFrameLen( st_fx->L_frame ) ); + step_e = sub( tmp2, 6 ); + { + Word32 stepFB; + Word16 stepFB_e; + UWord32 dmy; + Word16 tmp_shift; + conceal_eof_gainFB = hTcxDec->conceal_eof_gain32; + conceal_eof_gainFB_e = hTcxDec->conceal_eof_gain_e; + move32(); + move16(); + Mpy_32_32_ss( step, L_shl( L_mult0( st_fx->L_frame, getInvFrameLen( hTcxDec->L_frameTCX ) ), 8 ), &stepFB, &dmy ); + stepFB_e = add( step_e, 2 ); + + FOR( i = 0; i < hTcxDec->L_frameTCX; i++ ) + { + tmp_shift = conceal_eof_gainFB_e; + synthFB[i] = round_fx_sat( L_shl_sat( Mpy_32_16_1( conceal_eof_gainFB, synthFB[i] ), tmp_shift ) ); // Q_syn + move16(); + conceal_eof_gainFB = BASOP_Util_Add_Mant32Exp( conceal_eof_gainFB, conceal_eof_gainFB_e, L_negate( stepFB ), stepFB_e, &conceal_eof_gainFB_e ); // Q: 31 - conceal_eof_gainFB_e + } + } + FOR( i = 0; i < st_fx->L_frame; i++ ) + { + xn_buf[i] = round_fx_sat( L_shl_sat( Mpy_32_16_1( hTcxDec->conceal_eof_gain32, xn_buf[i] ), hTcxDec->conceal_eof_gain_e ) ); // Qx + move16(); + hTcxDec->conceal_eof_gain32 = BASOP_Util_Add_Mant32Exp( hTcxDec->conceal_eof_gain32, hTcxDec->conceal_eof_gain_e, L_negate( step ), step_e, &hTcxDec->conceal_eof_gain_e ); + move32(); + } + + /* run lpc gain compensation not for waveform adjustment */ + IF( st_fx->hPlcInfo != NULL ) + { + test(); + IF( 0 == st_fx->enablePlcWaveadjust || EQ_16( st_fx->hPlcInfo->concealment_method, TCX_TONAL ) ) + { + st_fx->hPlcInfo->recovery_gain = extract_h( L_shl_sat( Mpy_32_16_1( conceal_eof_gainFB, st_fx->last_concealed_gain_syn_deemph ), st_fx->last_concealed_gain_syn_deemph_e ) ); /*Q30->Q14*/ + move16(); + } + ELSE + { + st_fx->hPlcInfo->recovery_gain = extract_h( conceal_eof_gainFB ); /*Q14*/ + move16(); + } + st_fx->hPlcInfo->step_concealgain_fx = round_fx_sat( L_shl_sat( L_mult0( round_fx_sat( L_shr_sat( step, sub( 1, step_e ) ) ), round_fx_sat( L_shl_sat( L_mult0( st_fx->L_frame, getInvFrameLen( hTcxDec->L_frameTCX ) ), 8 ) ) ), 4 ) ); /*Q15*/ + move16(); + } +#ifdef HARMONIZE_2604_decoder_tcx_post + } +#endif } /*-----------------------------------------------------------* @@ -1834,11 +1971,23 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, st_fx->mem_pitch_gain[st_fx->nb_subfr * 2] = st_fx->mem_pitch_gain[st_fx->nb_subfr]; // Q14 move16(); +#ifdef HARMONIZE_2604_decoder_tcx_post + Word16 tcxltp_last_gain_unmodified_tmp = hTcxDec->tcxltp_last_gain_unmodified; + if ( GT_16( st_fx->element_mode, EVS_MONO ) ) + { + tcxltp_last_gain_unmodified_tmp = shr( tcxltp_last_gain_unmodified_tmp, 1 ); + } +#endif + FOR( i = 0; i < st_fx->nb_subfr; i++ ) { st_fx->mem_pitch_gain[( st_fx->nb_subfr * 2 - 1 ) - i] = st_fx->mem_pitch_gain[st_fx->nb_subfr - 1 - i]; // Q14 move16(); +#ifdef HARMONIZE_2604_decoder_tcx_post + st_fx->mem_pitch_gain[st_fx->nb_subfr - 1 - i] = tcxltp_last_gain_unmodified_tmp; /* Q14 */ +#else st_fx->mem_pitch_gain[st_fx->nb_subfr - 1 - i] = shr( hTcxDec->tcxltp_last_gain_unmodified, 1 ); /* Q14 */ +#endif move16(); } } diff --git a/lib_dec/ivas_mdct_core_dec_fx.c b/lib_dec/ivas_mdct_core_dec_fx.c index 2b25c2984..ee96a43e8 100755 --- a/lib_dec/ivas_mdct_core_dec_fx.c +++ b/lib_dec/ivas_mdct_core_dec_fx.c @@ -1259,7 +1259,11 @@ void ivas_mdct_core_reconstruct_fx( { TonalMDCTConceal_SaveTimeSignal_fx( st->element_mode, st->hTonalMDCTConc, synthFB_fx, q_winFB, L_frameTCX[ch] ); } +#ifdef HARMONIZE_2604_decoder_tcx_post + decoder_tcx_post_fx( st, synth_fx, synthFB_fx, q_winFB, NULL, bfi, MCT_flag ); +#else decoder_tcx_post_ivas_fx( st, synth_fx, synthFB_fx, q_winFB, NULL, bfi, MCT_flag ); +#endif // norm(synth_buf) >= q_syn - q_win // norm(synth_buf) + q_win >= q_syn diff --git a/lib_dec/ivas_tcx_core_dec_fx.c b/lib_dec/ivas_tcx_core_dec_fx.c index 3e848fcd8..599329953 100644 --- a/lib_dec/ivas_tcx_core_dec_fx.c +++ b/lib_dec/ivas_tcx_core_dec_fx.c @@ -634,7 +634,11 @@ void stereo_tcx_core_dec_fx( TonalMDCTConceal_SaveTimeSignal_fx( st->element_mode, st->hTonalMDCTConc, synthFB_fx, st->Q_syn, hTcxDec->L_frameTCX ); } +#ifdef HARMONIZE_2604_decoder_tcx_post + decoder_tcx_post_fx( st, synth_fx, synthFB_fx, st->Q_syn, Aq_fx, bfi, 0 ); +#else decoder_tcx_post_ivas_fx( st, synth_fx, synthFB_fx, st->Q_syn, Aq_fx, bfi, 0 ); +#endif IF( EQ_16( st->core, TCX_20_CORE ) ) { -- GitLab From 5fcab10290c59ceb1d1dc054c50060f9315f85ea Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Wed, 27 May 2026 17:33:57 +0200 Subject: [PATCH 2/3] few simplifications --- lib_dec/dec_tcx_fx.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/lib_dec/dec_tcx_fx.c b/lib_dec/dec_tcx_fx.c index 882799e72..612969201 100644 --- a/lib_dec/dec_tcx_fx.c +++ b/lib_dec/dec_tcx_fx.c @@ -1547,6 +1547,9 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, Word16 tmp1, tmp2, s; Word32 tmp32; Word32 tmp32_1, tmp32_2; +#ifdef HARMONIZE_2604_decoder_tcx_post + Word16 tcxltp_last_gain_unmodified_tmp; +#endif TCX_DEC_HANDLE hTcxDec; hTcxDec = st_fx->hTcxDec; @@ -1648,11 +1651,7 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, test(); test(); test(); -#ifdef HARMONIZE_2604_decoder_tcx_post - IF( bfi == 0 && st_fx->tcxonly != 0 && ( ( GT_16( st_fx->element_mode, EVS_MONO ) && ( NE_16( st_fx->element_mode, IVAS_CPE_MDCT ) || MCT_flag ) ) || EQ_16( st_fx->element_mode, EVS_MONO ) ) && EQ_16( st_fx->clas_dec, UNVOICED_CLAS ) ) -#else IF( bfi == 0 && st_fx->tcxonly != 0 && ( NE_16( st_fx->element_mode, IVAS_CPE_MDCT ) || MCT_flag ) && EQ_16( st_fx->clas_dec, UNVOICED_CLAS ) ) -#endif { Word16 Qnew_levelBackgroundTrace; @@ -1749,28 +1748,21 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, &gainCNG, &gainCNG_e ); } -#ifdef HARMONIZE_2604_decoder_tcx_post - IF( GT_16( st_fx->element_mode, EVS_MONO ) ) + test(); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_MDCT ) && !MCT_flag ) { -#endif - test(); - IF( EQ_16( st_fx->element_mode, IVAS_CPE_MDCT ) && !MCT_flag ) + IF( GT_16( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME + MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN ) ) { - IF( GT_16( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME + MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN ) ) - { - gainCNG = 0; - move16(); - } - ELSE IF( GT_16( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) ) - { - // gainCNG *= 1.f - (float) sub( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN; - tmp32 = L_sub( ONE_IN_Q31, imult3216( 107374182 /* 1 / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN in Q31*/, sub( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) ) ); /* Q31 */ - gainCNG = extract_l( Mpy_32_32( gainCNG, tmp32 ) ); - } + gainCNG = 0; + move16(); + } + ELSE IF( GT_16( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) ) + { + // gainCNG *= 1.f - (float) sub( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN; + tmp32 = L_sub( ONE_IN_Q31, imult3216( 107374182 /* 1 / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN in Q31*/, sub( st_fx->nbLostCmpt, MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) ) ); /* Q31 */ + gainCNG = extract_l( Mpy_32_32( gainCNG, tmp32 ) ); } -#ifdef HARMONIZE_2604_decoder_tcx_post } -#endif } ELSE { @@ -1870,8 +1862,6 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, ELSE { #endif - - IF( ( EQ_16( st_fx->nbLostCmpt, 1 ) ) ) { hTcxDec->conceal_eof_gain32 = ONE_IN_Q30 /*1.0f Q30*/; @@ -1972,7 +1962,7 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, move16(); #ifdef HARMONIZE_2604_decoder_tcx_post - Word16 tcxltp_last_gain_unmodified_tmp = hTcxDec->tcxltp_last_gain_unmodified; + tcxltp_last_gain_unmodified_tmp = hTcxDec->tcxltp_last_gain_unmodified; if ( GT_16( st_fx->element_mode, EVS_MONO ) ) { tcxltp_last_gain_unmodified_tmp = shr( tcxltp_last_gain_unmodified_tmp, 1 ); -- GitLab From 4043a3c11b4d737e4a13436edae59ed753625faf Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Wed, 27 May 2026 17:36:40 +0200 Subject: [PATCH 3/3] remove test()-operators, which were added --- lib_dec/dec_tcx_fx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib_dec/dec_tcx_fx.c b/lib_dec/dec_tcx_fx.c index 612969201..0d91397fb 100644 --- a/lib_dec/dec_tcx_fx.c +++ b/lib_dec/dec_tcx_fx.c @@ -1582,8 +1582,6 @@ void decoder_tcx_post_ivas_fx( Decoder_State *st_fx, test(); test(); /* run lpc gain compensation not for waveform adjustment */ - test(); - test(); IF( 0 == st_fx->enablePlcWaveadjust || ( st_fx->hPlcInfo != NULL && EQ_16( st_fx->hPlcInfo->concealment_method, TCX_TONAL ) ) ) { UWord32 dmy; -- GitLab