From 7f3542ab52a458ca094606bc0b7c16e94dd7cead Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 11 Dec 2024 08:12:12 +0530 Subject: [PATCH] Fix for 3GPP issue 1042: Clicks in MC5.1 output at 160kbps with FER link #1042 --- lib_dec/ivas_out_setup_conversion.c | 108 +++++++++++++++------------- lib_rend/ivas_stat_rend.h | 4 +- 2 files changed, 62 insertions(+), 50 deletions(-) diff --git a/lib_dec/ivas_out_setup_conversion.c b/lib_dec/ivas_out_setup_conversion.c index fbbe2a6fe..6a955ddaf 100644 --- a/lib_dec/ivas_out_setup_conversion.c +++ b/lib_dec/ivas_out_setup_conversion.c @@ -50,11 +50,9 @@ *----------------------------------------------------------------------------------*/ -#define LS_OUT_CONV_SMOOTHING_FACTOR_Q31 93415539 -#define LS_OUT_CONV_CLIP_FACTOR_MAX_Q29 1073741824 -#define LS_OUT_CONV_CLIP_FACTOR_MAX_SQ_Q28 1073741824 -#define LS_OUT_CONV_CLIP_FACTOR_MIN_Q29 161061274 -#define LS_OUT_CONV_CLIP_FACTOR_MIN_SQ_Q28 24159191 +#define LS_OUT_CONV_SMOOTHING_FACTOR_Q31 93415539 +#define LS_OUT_CONV_CLIP_FACTOR_MAX_Q30 2147483647 +#define LS_OUT_CONV_CLIP_FACTOR_MIN_Q30 322122547 /*----------------------------------------------------------------------------------* @@ -62,24 +60,12 @@ *----------------------------------------------------------------------------------*/ static void ivas_lssetupconversion_computeEQFactor_fx( - Word32 *outputEnergy, // Q0 - Word32 *inputEnergy, // Q0 + Word32 *outputEnergy, + Word16 output_exp, + Word32 *inputEnergy, + Word16 input_exp, Word32 *EQ ) { - - IF( GE_32( L_shr( *outputEnergy, 3 ), Mpy_32_32( LS_OUT_CONV_CLIP_FACTOR_MAX_SQ_Q28, *inputEnergy ) ) ) - { - *EQ = L_shl_sat( LS_OUT_CONV_CLIP_FACTOR_MAX_Q29, 1 ); // Q30 - move32(); - return; - } - IF( LE_32( L_shr( *outputEnergy, 3 ), Mpy_32_32( LS_OUT_CONV_CLIP_FACTOR_MIN_SQ_Q28, *inputEnergy ) ) ) - { - *EQ = L_shl_sat( LS_OUT_CONV_CLIP_FACTOR_MIN_Q29, 1 ); // Q30 - move32(); - return; - } - test(); IF( ( *outputEnergy == 0 ) && ( *inputEnergy == 0 ) ) { @@ -90,9 +76,16 @@ static void ivas_lssetupconversion_computeEQFactor_fx( /* Compute the Equalization Gain */ Word16 tmp_e; Word16 tmp = BASOP_Util_Divide3232_Scale( *outputEnergy, L_add( EPSILON_FX, *inputEnergy ), &tmp_e ); - Word32 tmp_32 = L_shl( (Word32) tmp, 16 ); + tmp_e = add( tmp_e, sub( output_exp, input_exp ) ); + Word32 tmp_32 = L_deposit_h( tmp ); tmp_32 = Sqrt32( tmp_32, &tmp_e ); - *EQ = L_shr( tmp_32, 1 - tmp_e ); + *EQ = L_shr_sat( tmp_32, sub( 1, tmp_e ) ); // range of EQ in float 0.3 - 2.0 + move32(); + + *EQ = L_min( *EQ, LS_OUT_CONV_CLIP_FACTOR_MAX_Q30 ); + *EQ = L_max( *EQ, LS_OUT_CONV_CLIP_FACTOR_MIN_Q30 ); + move32(); + move32(); return; } @@ -437,10 +430,10 @@ ivas_error ivas_ls_setup_conversion_open_fx( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) ); } set32_fx( hLsSetUpConversion->targetEnergyPrev_fx[chIdx], 0, hLsSetUpConversion->sfbCnt ); - hLsSetUpConversion->te_prev_exp = 0; + hLsSetUpConversion->te_prev_exp[chIdx] = 0; move16(); set32_fx( hLsSetUpConversion->dmxEnergyPrev_fx[chIdx], 0, hLsSetUpConversion->sfbCnt ); - hLsSetUpConversion->dmx_prev_exp = 0; + hLsSetUpConversion->dmx_prev_exp[chIdx] = 0; move16(); } FOR( ; chIdx < MAX_CICP_CHANNELS; chIdx++ ) @@ -857,22 +850,32 @@ void ivas_ls_setup_conversion_process_mdct_fx( } /* end of out channel loop */ /* Step 3: Peform energy smoothing */ + + Word16 te_scale = getScaleFactor32( hLsSetUpConversion->targetEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt ); + scale_sig32( hLsSetUpConversion->targetEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, te_scale ); + Word16 dmx_sacle = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt ); + scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, dmx_sacle ); + + Word16 te_max_e = s_max( sub( 40, shl( q_output, 1 ) ), sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) ); + Word16 dmx_max_e = s_max( sub( 40, shl( q_output, 1 ) ), sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_sacle ) ); + FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ ) { - targetEnergy[bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, targetEnergy[bandIdx] ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] ) ); + targetEnergy[bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( targetEnergy[bandIdx], sub( te_max_e, sub( 40, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], sub( te_max_e, sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) ) ) ) ); move32(); - dmxEnergy[bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, dmxEnergy[bandIdx] ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] ) ); + dmxEnergy[bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( dmxEnergy[bandIdx], sub( dmx_max_e, sub( 40, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], sub( dmx_max_e, sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_sacle ) ) ) ) ); move32(); - hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy[bandIdx]; // exp( hLsSetUpConversion->te_prev_exp) (Q0 here) + hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy[bandIdx]; /* te_prev_exp = 40 - 2*q_output */ move32(); - hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy[bandIdx]; // exp( hLsSetUpConversion->dmx_prev_exp) (Q0) + hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy[bandIdx]; /* dmx_prev_exp = 40 - 2*q_output */ move32(); - hLsSetUpConversion->te_prev_exp = 31; - move16(); - hLsSetUpConversion->dmx_prev_exp = 31; - move16(); } + hLsSetUpConversion->te_prev_exp[0] = te_max_e; /* te_prev_exp = 40 - 2*q_output */ + move16(); + hLsSetUpConversion->dmx_prev_exp[0] = dmx_max_e; /* dmx_prev_exp = 40 - 2*q_output */ + move16(); + FOR( i = 0; i < inChannels; ++i ) { FOR( j = 0; j < L_FRAME48k; ++j ) @@ -901,7 +904,7 @@ void ivas_ls_setup_conversion_process_mdct_fx( move16(); /* Compute Eq gains */ - ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain ); // Q(eqGain) = 30 + ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain ); // Q(eqGain) = 30 FOR( binIdx = start; binIdx < stop; binIdx++ ) { x[chInIdx][0][binIdx] = Mpy_32_32( L_shl( x[chInIdx][0][binIdx], 1 ), eqGain ); // Q - 1 @@ -921,7 +924,7 @@ void ivas_ls_setup_conversion_process_mdct_fx( move16(); /* Compute Eq gains */ - ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain ); + ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain ); FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ ) { @@ -1261,18 +1264,18 @@ void ivas_ls_setup_conversion_process_mdct_param_mc_fx( /* Step 3: Peform energy smoothing */ FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ ) { - targetEnergy_fx[bandIdx] = L_add( Mult_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, targetEnergy_fx[bandIdx] ), Mult_32_32( L_sub( MAX_32, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], add( output_exp, sub( 2, hLsSetUpConversion->te_prev_exp ) ) ) ) ); /*output_exp + 2*/ + targetEnergy_fx[bandIdx] = L_add( Mult_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, targetEnergy_fx[bandIdx] ), Mult_32_32( L_sub( MAX_32, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], add( output_exp, sub( 2, hLsSetUpConversion->te_prev_exp[0] ) ) ) ) ); /*output_exp + 2*/ move32(); - dmxEnergy_fx[bandIdx] = L_add( Mult_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, dmxEnergy_fx[bandIdx] ), Mult_32_32( L_sub( MAX_32, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], sub( shl( add( max_e, 2 ), 1 ), hLsSetUpConversion->dmx_prev_exp ) ) ) ); /*2 * (max_e + 2)*/ + dmxEnergy_fx[bandIdx] = L_add( Mult_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, dmxEnergy_fx[bandIdx] ), Mult_32_32( L_sub( MAX_32, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], sub( shl( add( max_e, 2 ), 1 ), hLsSetUpConversion->dmx_prev_exp[0] ) ) ) ); /*2 * (max_e + 2)*/ move32(); hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy_fx[bandIdx]; move32(); hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy_fx[bandIdx]; move32(); } - hLsSetUpConversion->te_prev_exp = add( output_exp, 2 ); + hLsSetUpConversion->te_prev_exp[0] = add( output_exp, 2 ); move16(); - hLsSetUpConversion->dmx_prev_exp = shl( add( max_e, 2 ), 1 ); + hLsSetUpConversion->dmx_prev_exp[0] = shl( add( max_e, 2 ), 1 ); move16(); /* Step 4: Perform equalization */ FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ ) @@ -1290,7 +1293,7 @@ void ivas_ls_setup_conversion_process_mdct_param_mc_fx( move16(); /*Compute Eq gains */ - ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], &dmxEnergy_fx[bandIdx], &eqGain_fx ); + ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy_fx[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain_fx ); FOR( binIdx = start; binIdx < stop; binIdx++ ) { @@ -1308,7 +1311,7 @@ void ivas_ls_setup_conversion_process_mdct_param_mc_fx( stop = shr( hLsSetUpConversion->sfbOffset[bandIdx + 1], 1 ); /*Compute Eq gains */ - ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], &dmxEnergy_fx[bandIdx], &eqGain_fx ); + ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy_fx[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain_fx ); FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ ) @@ -1481,21 +1484,30 @@ void ivas_lssetupconversion_process_param_mc_fx( { IF( channel_active[chOutIdx] ) { + Word16 te_scale = getScaleFactor32( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt ); + scale_sig32( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt, te_scale ); + Word16 dmx_sacle = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt ); + scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt, dmx_sacle ); + + Word16 te_max_e = s_max( sub( 50, shl( q_output, 1 ) ), sub( hLsSetUpConversion->te_prev_exp[chOutIdx], te_scale ) ); + Word16 dmx_max_e = s_max( sub( 50, shl( q_output, 1 ) ), sub( hLsSetUpConversion->dmx_prev_exp[chOutIdx], dmx_sacle ) ); + FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ ) { - targetEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, targetEnergy[chOutIdx][bandIdx] ), Mpy_32_32( L_sub( ONE_IN_Q31, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx][bandIdx] ) ); + targetEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( targetEnergy[chOutIdx][bandIdx], sub( te_max_e, sub( 50, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( L_sub( ONE_IN_Q31, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx][bandIdx], sub( te_max_e, sub( hLsSetUpConversion->te_prev_exp[chOutIdx], te_scale ) ) ) ) ); move32(); - dmxEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, dmxEnergy[chOutIdx][bandIdx] ), Mpy_32_32( L_sub( ONE_IN_Q31, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx][bandIdx] ) ); + dmxEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( dmxEnergy[chOutIdx][bandIdx], sub( dmx_max_e, sub( 50, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( L_sub( ONE_IN_Q31, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx][bandIdx], sub( dmx_max_e, sub( hLsSetUpConversion->dmx_prev_exp[chOutIdx], dmx_sacle ) ) ) ) ); move32(); hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx][bandIdx] = targetEnergy[chOutIdx][bandIdx]; // Q0 move32(); hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx][bandIdx] = dmxEnergy[chOutIdx][bandIdx]; // Q0 move32(); - hLsSetUpConversion->te_prev_exp = 31; - move16(); - hLsSetUpConversion->dmx_prev_exp = 31; - move16(); } + + hLsSetUpConversion->te_prev_exp[chOutIdx] = te_max_e; /* te_prev_exp = 50 - 2*q_output */ + move16(); + hLsSetUpConversion->dmx_prev_exp[chOutIdx] = dmx_max_e; /* dmx_prev_exp = 50 - 2*q_output */ + move16(); } } @@ -1517,7 +1529,7 @@ void ivas_lssetupconversion_process_param_mc_fx( { FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ ) { - ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[chOutIdx][bandIdx], &dmxEnergy[chOutIdx][bandIdx], &EQ ); // Q(EQ) = Q30 + ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[chOutIdx][bandIdx], hLsSetUpConversion->te_prev_exp[chOutIdx], &dmxEnergy[chOutIdx][bandIdx], hLsSetUpConversion->dmx_prev_exp[chOutIdx], &EQ ); // Q(EQ) = Q30 Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] = Mpy_32_32( L_shl( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx], 1 ), EQ ); move32(); Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] = Mpy_32_32( L_shl( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx], 1 ), EQ ); diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index a911631a4..38b2fe524 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1421,8 +1421,8 @@ typedef struct ivas_LS_setupconversion_struct Word32 *dmxEnergyPrev_fx[MAX_OUTPUT_CHANNELS]; Word16 sfbOffset[MAX_SFB + 2]; Word16 sfbCnt; - Word16 te_prev_exp; - Word16 dmx_prev_exp; + Word16 te_prev_exp[MAX_OUTPUT_CHANNELS]; + Word16 dmx_prev_exp[MAX_OUTPUT_CHANNELS]; } LSSETUP_CONVERSION_STRUCT, *LSSETUP_CONVERSION_HANDLE; -- GitLab