Commit 7f3542ab authored by Sandesh Venkatesh's avatar Sandesh Venkatesh
Browse files

Fix for 3GPP issue 1042: Clicks in MC5.1 output at 160kbps with FER

link #1042
parent 6362e224
Loading
Loading
Loading
Loading
Loading
+60 −48
Original line number Diff line number Diff line
@@ -51,10 +51,8 @@


#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_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,21 +850,31 @@ 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;
    }

    hLsSetUpConversion->te_prev_exp[0] = te_max_e; /* te_prev_exp = 40 - 2*q_output */
    move16();
        hLsSetUpConversion->dmx_prev_exp = 31;
    hLsSetUpConversion->dmx_prev_exp[0] = dmx_max_e; /* dmx_prev_exp = 40 - 2*q_output */
    move16();
    }

    FOR( i = 0; i < inChannels; ++i )
    {
@@ -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,23 +1484,32 @@ 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;
                }

                hLsSetUpConversion->te_prev_exp[chOutIdx] = te_max_e; /* te_prev_exp = 50 - 2*q_output */
                move16();
                    hLsSetUpConversion->dmx_prev_exp = 31;
                hLsSetUpConversion->dmx_prev_exp[chOutIdx] = dmx_max_e; /* dmx_prev_exp = 50 - 2*q_output */
                move16();
            }
        }
        }

        FOR( i = 0; i < outChannels; ++i )
        {
@@ -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 );
+2 −2
Original line number Diff line number Diff line
@@ -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;