From fa3f2e2445cc8b3e0099924fecc95da572095835 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Fri, 8 Nov 2024 17:30:33 +0530 Subject: [PATCH] Fix for 3GPP issue 981: Stereo decoding with JBM: energy difference in right channel despite similar TSM link: #981 --- lib_com/prot_fx.h | 8 ++++++- lib_dec/core_dec_init_fx.c | 4 ++++ lib_dec/hq_core_dec_fx.c | 14 +++++++++++++ lib_dec/ivas_core_dec.c | 8 ++++++- lib_dec/ivas_mdct_core_dec.c | 4 +--- lib_dec/ivas_tcx_core_dec.c | 9 +++++++- lib_dec/stat_dec.h | 2 ++ lib_dec/tonalMDCTconcealment_fx.c | 35 ++++++++++++++++++++++++++++--- 8 files changed, 75 insertions(+), 9 deletions(-) diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index ea3dd0530..66e80a6b3 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -6407,7 +6407,13 @@ void TonalMDCTConceal_SaveTimeSignal( TonalMDCTConcealPtr hTonalMDCTConc, Word16 *timeSignal, Word16 nNewSamples ); - +#ifdef IVAS_FLOAT_FIXED +void TonalMDCTConceal_SaveTimeSignal_ivas_fx( + TonalMDCTConcealPtr hTonalMDCTConc, + Word16 *timeSignal, + Word16 q_timeSignal, + Word16 nNewSamples ); +#endif // decision_matrix_dec_fx.c void decision_matrix_dec_fx( diff --git a/lib_dec/core_dec_init_fx.c b/lib_dec/core_dec_init_fx.c index a3c76e23c..537b586f3 100644 --- a/lib_dec/core_dec_init_fx.c +++ b/lib_dec/core_dec_init_fx.c @@ -1050,6 +1050,8 @@ void open_decoder_LPD_fx( move16(); st->tonalMDCTconceal.lastPcmOut = 0x0; move16(); + st->tonalMDCTconceal.q_lastPcmOut = Q15; + move16(); st->tonalMDCTconceal.lastBlockData.tonalConcealmentActive = 0; move16(); st->tonalMDCTconceal.lastBlockData.nSamples = 0; @@ -2121,6 +2123,8 @@ void open_decoder_LPD_ivas_fx( move16(); st->hTonalMDCTConc->lastPcmOut = 0x0; move16(); + st->hTonalMDCTConc->q_lastPcmOut = Q15; + move16(); st->hTonalMDCTConc->lastBlockData.tonalConcealmentActive = 0; move16(); st->hTonalMDCTConc->lastBlockData.nSamples = 0; diff --git a/lib_dec/hq_core_dec_fx.c b/lib_dec/hq_core_dec_fx.c index c31727f29..cc047f9d0 100644 --- a/lib_dec/hq_core_dec_fx.c +++ b/lib_dec/hq_core_dec_fx.c @@ -507,6 +507,13 @@ void hq_core_dec_fx( st_fx->plcInfo.recovery_gain = shl( st_fx->plcInfo.recovery_gain, *Q_synth ); move16(); #endif + IF( st_fx->tonalMDCTconceal.q_lastPcmOut != 0 ) + { + Scale_sig( st_fx->tonalMDCTconceal.secondLastPcmOut, shr( st_fx->plcInfo.FrameSize, 1 ), negate( st_fx->tonalMDCTconceal.q_lastPcmOut ) ); + Scale_sig( st_fx->tonalMDCTconceal.lastPcmOut, st_fx->plcInfo.FrameSize, negate( st_fx->tonalMDCTconceal.q_lastPcmOut ) ); + st_fx->tonalMDCTconceal.q_lastPcmOut = 0; + move16(); + } waveform_adj2_fix( st_fx->tonalMDCTconceal.secondLastPcmOut, synth, st_fx->plcInfo.data_noise, @@ -1136,6 +1143,13 @@ void ivas_hq_core_dec_fx( st_fx->plcInfo.recovery_gain = shl( st_fx->plcInfo.recovery_gain, *Q_synth ); #endif move16(); + IF( st_fx->tonalMDCTconceal.q_lastPcmOut != 0 ) + { + Scale_sig( st_fx->tonalMDCTconceal.secondLastPcmOut, shr( st_fx->plcInfo.FrameSize, 1 ), negate( st_fx->tonalMDCTconceal.q_lastPcmOut ) ); + Scale_sig( st_fx->tonalMDCTconceal.lastPcmOut, st_fx->plcInfo.FrameSize, negate( st_fx->tonalMDCTconceal.q_lastPcmOut ) ); + st_fx->tonalMDCTconceal.q_lastPcmOut = 0; + move16(); + } waveform_adj2_fix( st_fx->tonalMDCTconceal.secondLastPcmOut, synth, st_fx->plcInfo.data_noise, diff --git a/lib_dec/ivas_core_dec.c b/lib_dec/ivas_core_dec.c index 8d44af509..d8f9a8b90 100644 --- a/lib_dec/ivas_core_dec.c +++ b/lib_dec/ivas_core_dec.c @@ -1295,7 +1295,13 @@ ivas_error ivas_core_dec_fx( IF( EQ_16( st->core, ACELP_CORE ) && !st->bfi && st->prev_bfi && GE_32( st->last_total_brate, HQ_48k ) && EQ_16( st->last_codec_mode, MODE2 ) && ( EQ_16( st->last_core_bfi, TCX_20_CORE ) || EQ_16( st->last_core_bfi, TCX_10_CORE ) ) && EQ_16( st->hPlcInfo->concealment_method, TCX_NONTONAL ) && LT_16( st->hPlcInfo->nbLostCmpt, 4 ) ) { tmps = NS2SA_FX2( output_Fs, DELAY_CLDFB_NS ); - + IF( st->tonalMDCTconceal.q_lastPcmOut != 0 ) + { + Scale_sig( st->tonalMDCTconceal.secondLastPcmOut, shr( st->plcInfo.FrameSize, 1 ), negate( st->tonalMDCTconceal.q_lastPcmOut ) ); + Scale_sig( st->tonalMDCTconceal.lastPcmOut, st->plcInfo.FrameSize, negate( st->tonalMDCTconceal.q_lastPcmOut ) ); + st->tonalMDCTconceal.q_lastPcmOut = 0; + move16(); + } waveform_adj2_fix( st->hTonalMDCTConc->secondLastPcmOut, synth_16_fx[n] + tmps, st->plcInfo.data_noise, &st->plcInfo.outx_new_n1_fx, &st->plcInfo.nsapp_gain_fx, &st->plcInfo.nsapp_gain_n_fx, &st->plcInfo.recovery_gain, st->plcInfo.step_concealgain_fx, st->plcInfo.Pitch_fx, st->plcInfo.FrameSize, tmps, add( st->hPlcInfo->nbLostCmpt, 1 ), st->bfi ); diff --git a/lib_dec/ivas_mdct_core_dec.c b/lib_dec/ivas_mdct_core_dec.c index 0550189ac..57d08a708 100644 --- a/lib_dec/ivas_mdct_core_dec.c +++ b/lib_dec/ivas_mdct_core_dec.c @@ -2117,9 +2117,7 @@ void ivas_mdct_core_reconstruct_fx( test(); IF( ( bfi == 0 ) && st->hTonalMDCTConc != NULL ) { - Word16 synth_tmp[L_FRAME48k]; - Copy_Scale_sig( synthFB_fx, synth_tmp, st->hTonalMDCTConc->nSamples, 2 ); - TonalMDCTConceal_SaveTimeSignal( st->hTonalMDCTConc, synth_tmp, L_frameTCX[ch] ); + TonalMDCTConceal_SaveTimeSignal_ivas_fx( st->hTonalMDCTConc, synthFB_fx, q_win, L_frameTCX[ch] ); } decoder_tcx_post_ivas_fx( st, synth_fx, synthFB_fx, q_win, NULL, bfi, MCT_flag ); diff --git a/lib_dec/ivas_tcx_core_dec.c b/lib_dec/ivas_tcx_core_dec.c index 407f6d68d..4ac2bc814 100644 --- a/lib_dec/ivas_tcx_core_dec.c +++ b/lib_dec/ivas_tcx_core_dec.c @@ -710,6 +710,13 @@ void stereo_tcx_core_dec_fx( ( GE_32( st->last_total_brate, HQ_48k ) && /* recovery */ EQ_16( st->last_codec_mode, MODE2 ) ) ) { + IF( st->hTonalMDCTConc->q_lastPcmOut != 0 ) + { + Scale_sig( st->hTonalMDCTConc->secondLastPcmOut, shr( hTcxDec->L_frameTCX, 1 ), negate( st->hTonalMDCTConc->q_lastPcmOut ) ); + Scale_sig( st->hTonalMDCTConc->lastPcmOut, hTcxDec->L_frameTCX, negate( st->hTonalMDCTConc->q_lastPcmOut ) ); + st->hTonalMDCTConc->q_lastPcmOut = 0; + move16(); + } /* waveform adjustment */ concealment_signal_tuning_fx( bfi, st->core, synthFB_fx, &st->plcInfo, st->nbLostCmpt, st->prev_bfi, st->hTonalMDCTConc->secondLastPcmOut, st->last_core_bfi, st->hTonalMDCTConc->lastPcmOut, st ); @@ -730,7 +737,7 @@ void stereo_tcx_core_dec_fx( IF( !bfi && st->hTonalMDCTConc != NULL ) { - TonalMDCTConceal_SaveTimeSignal( st->hTonalMDCTConc, synthFB_fx, hTcxDec->L_frameTCX ); + TonalMDCTConceal_SaveTimeSignal_ivas_fx( st->hTonalMDCTConc, synthFB_fx, 0, hTcxDec->L_frameTCX ); } decoder_tcx_post_ivas_fx( st, synth_fx, synthFB_fx, 0, Aq_fx, bfi, 0 ); diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index cc6f7c5be..509051c18 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -403,6 +403,8 @@ typedef struct tonalmdctconceal Word16 *secondLastPcmOut; + Word16 q_lastPcmOut; + Word16 *secondLastPowerSpectrum; Word16 secondLastPowerSpectrum_exp; diff --git a/lib_dec/tonalMDCTconcealment_fx.c b/lib_dec/tonalMDCTconcealment_fx.c index c4fb3259e..0170aa985 100644 --- a/lib_dec/tonalMDCTconcealment_fx.c +++ b/lib_dec/tonalMDCTconcealment_fx.c @@ -773,7 +773,7 @@ static void ivas_CalcPowerSpecAndDetectTonalComponents_fx( move16(); /* It is taken into account that the MDCT is not normalized. */ - floorPowerSpectrum /*Q0*/ = extract_l( Mpy_32_16_1( L_mult0( hTonalMDCTConc->nSamples, hTonalMDCTConc->nSamples ), 82 ) ); /*1/400 = 82 Q15*/ + floorPowerSpectrum /*Q0*/ = extract_l( Mpy_32_32( L_mult0( hTonalMDCTConc->nSamples, hTonalMDCTConc->nSamples ), 5368709 ) ); /*1/400 = 5368709 Q31*/ powerSpectrum_exp = 0; move16(); @@ -1247,9 +1247,9 @@ void TonalMDCTConceal_Detect_ivas_fx( nSamples = hTonalMDCTConc->nSamples; move16(); - secondLastMDST_exp = 16; /*time signal Q-1*/ + secondLastMDST_exp = sub( 16, hTonalMDCTConc->q_lastPcmOut ); /*time signal Q-1 - hTonalMDCTConc->q_lastPcmOut*/ move16(); - secondLastMDCT_exp = 16; /*time signal Q-1*/ + secondLastMDCT_exp = sub( 16, hTonalMDCTConc->q_lastPcmOut ); /*time signal Q-1 - hTonalMDCTConc->q_lastPcmOut*/ move16(); test(); test(); @@ -3163,6 +3163,35 @@ void TonalMDCTConceal_SaveTimeSignal( return; } +#ifdef IVAS_FLOAT_FIXED +void TonalMDCTConceal_SaveTimeSignal_ivas_fx( + TonalMDCTConcealPtr hTonalMDCTConc, + Word16 *timeSignal, // q_timeSignal + Word16 q_timeSignal, + Word16 nNewSamples ) +{ + IF( EQ_16( nNewSamples, hTonalMDCTConc->nSamples ) ) + { + assert( nNewSamples <= L_FRAME_MAX ); + IF( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive ) + { + Word16 exp, len; + len = shr( hTonalMDCTConc->nSamples, 1 ); + Copy( hTonalMDCTConc->lastPcmOut + len, hTonalMDCTConc->secondLastPcmOut, len ); + exp = sub( q_timeSignal, hTonalMDCTConc->q_lastPcmOut ); + IF( exp != 0 ) + { + Scale_sig( hTonalMDCTConc->secondLastPcmOut, len, exp ); // q_timeSignal + } + } + Copy( timeSignal, hTonalMDCTConc->lastPcmOut, hTonalMDCTConc->nSamples ); + hTonalMDCTConc->q_lastPcmOut = q_timeSignal; + move16(); + } + + return; +} +#endif static void CalcPowerSpec( const Word32 *mdctSpec, /* i: MDCT spectrum Q31-mdctSpec_exp */ const Word16 mdctSpec_exp, /* i: exponent of MDCT spectrum */ -- GitLab