Commit 6a68c167 authored by Sandesh Venkatesh's avatar Sandesh Venkatesh
Browse files

Merge branch '3gpp_issue_1308_fix' into 'main'

Fix for 3GPP issue 1308: Large differences between BASOP and float for critical item in MDCT-stereo @96kbps [allow regression]

See merge request !1183
parents 30ec319b 643d82a6
Loading
Loading
Loading
Loading
+85 −0
Original line number Diff line number Diff line
@@ -1210,6 +1210,91 @@ Word16 E_LPC_lsp_unweight(
    return 0;
}

/*
 * E_LPC_schur_ivas
 *
 * Parameters:
 *    R         I:   Rh[M+1] Vector of autocorrelations (msb)
 *    reflCoeff O:   rc[M]   Reflection coefficients.          Q15
 *    epsP      O:   error vector
 *
 * Function:
 *    Schur algorithm to compute
 *    the LPC parameters from the autocorrelations of speech.
 *
 * Returns:
 *    void
 */
Word32 E_LPC_schur_ivas( Word32 r[] /*Qr*/, Word16 reflCoeff[] /*Q15*/, const Word16 m )
{
    Word16 i, j, temp16, mMi, s;
    Word32 g0[M], *g1, tmp32;
    const Word32 min_epsP = 1; /* > 0.01f*2^27/2^30 */
    Word32 tmp_epsP;

    s = getScaleFactor32( r, add( m, 1 ) );
    IF( s != 0 )
    {
        scale_sig32( r, add( m, 1 ), s ); /* scale in-place */
    }

    g1 = r;
    Copy32( r + 1, g0, m );

    /* compute g0[0]/g1[0], where g0[0] < g1[0] */
    temp16 = negate( divide3232( g0[0], g1[0] ) );
    reflCoeff[0] = temp16;
    move16();
    //  epsP[0] = r[0];
    move32();


    FOR( i = 0; i < m; i++ )
    {
        /* g1[0] = g0[0]*temp16 + g1[0]; */
        tmp32 = Mpy_32_16_1( g0[0], temp16 );
        g1[0] = L_add( g1[0], tmp32 );
        move32();

        mMi = sub( m, i );
        FOR( j = 1; j < mMi; j++ )
        {
            /* g0[j-1] = g0[j]        + g1[j]*temp16;
            g1[j]   = g0[j]*temp16 + g1[j];       */
            g0[j - 1] = L_add( g0[j], Mpy_32_16_1( g1[j], temp16 ) );
            move32();
            g1[j] = L_add( g1[j], Mpy_32_16_1( g0[j], temp16 ) );
            move32();
        }
        temp16 = negate( divide3232( g0[0], g1[0] ) );
        reflCoeff[i + 1] = temp16;
        move16();

        /* Prediction errors */
        tmp_epsP = L_shr( g1[0], s );
        if ( tmp_epsP <= 0 )
        {
            tmp_epsP = min_epsP;
            move32();
        }
        // epsP[i + 1] = tmp_epsP;
        move32();
    }

    /* epsP[i+1] = g0[0]*temp16 + g1[0]; */
    tmp_epsP = L_add( g1[0], Mpy_32_16_1( g0[0], temp16 ) );
    tmp_epsP = L_shr( tmp_epsP, s );
    if ( tmp_epsP <= 0 )
    {
        tmp_epsP = min_epsP;
        move32();
    }

    /* prediction gain = divide3232(L_shr(epsP[0], PRED_GAIN_E), g1[0]); */


    return g1[0];
}

/*
 * E_LPC_schur
+1 −0
Original line number Diff line number Diff line
@@ -1198,6 +1198,7 @@ Word16 E_LPC_lsp_unweight(
);
Word32 E_LPC_schur( Word32 r[] /*Qr*/, Word16 reflCoeff[] /*Q15*/, Word32 epsP[] /*Qr*/, const Word16 m );
Word32 E_LPC_schur_ivas( Word32 r[] /*Qr*/, Word16 reflCoeff[] /*Q15*/, const Word16 m );
void E_LPC_a_lsf_isf_conversion( Word16 *lpcCoeffs /*Qx*/, Word16 *lsf /*15Q16*/, const Word16 *old_lsf /*15Q16*/, Word16 lpcOrder, Word8 lpcRep /*Q0*/ );
+1 −0
Original line number Diff line number Diff line
@@ -197,6 +197,7 @@ typedef struct TNS_filter_structure
    Word16 order;                           /* Filter order. */
    Word16 coefIndex[TNS_MAX_FILTER_ORDER]; /* Quantized filter coefficients. */
    Word16 predictionGain;                  /* Prediction gain. The ratio of a signal and TNS residual energy. E(PRED_GAIN_E), Q7 */
    Word32 predictionGain32;                /* Prediction gain. The ratio of a signal and TNS residual energy. E(PRED_GAIN_E), Q23 */
    Word16 avgSqrCoef;                      /* Average squared filter coefficient. E(0), Q15 */
} STnsFilter;

+2 −0
Original line number Diff line number Diff line
@@ -1202,6 +1202,8 @@ void ResetTnsData( STnsData *pTnsData )
        move16();
        pTnsFilter->predictionGain = ONE_IN_Q7; /*Q7*/
        move16();
        pTnsFilter->predictionGain32 = ONE_IN_Q23; /*Q23*/
        move32();
        pTnsFilter->avgSqrCoef = 0;
        move16();
        pTnsFilter->filterType = TNS_FILTER_OFF; /*Q0*/
+21 −20
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@

#define SIMILAR_TNS_THRESHOLD_FX_IN_Q15        ( 1311 )
#define TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q7  ( 384 )
#define TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q23 ( 25165824 )
void TNSAnalysisStereo_fx(
    Encoder_State **sts,                            /* i  : encoder state handle                    */
    Word32 *mdst_spectrum_fx[CPE_CHANNELS][NB_DIV], /* o  : MDST spectrum                       Qx*/
@@ -72,7 +73,7 @@ void TNSAnalysisStereo_fx(
    Encoder_State *st = NULL;
    TCX_ENC_HANDLE hTcxEnc = NULL;
    Word16 individual_decision[NB_DIV];
    Word16 maxPredictionGain_fx = 0, meanPredictionGain_fx;
    Word32 maxPredictionGain_fx = 0, meanPredictionGain_fx;
    move16();

    individual_decision[0] = 0;
@@ -144,7 +145,7 @@ void TNSAnalysisStereo_fx(
                    BREAK;
                }

                CalculateTnsFilt_fx( st->hTcxCfg->pCurrentTnsConfig, spectrum_fx, hTcxEnc->spectrum_e[k], &hTcxEnc->tnsData[k], NULL );
                CalculateTnsFilt_fx( st->hTcxCfg->pCurrentTnsConfig, spectrum_fx, hTcxEnc->spectrum_e[k], &hTcxEnc->tnsData[k] );
            }
        }
    }
@@ -209,7 +210,7 @@ void TNSAnalysisStereo_fx(
                test();
                IF( sts[0]->hTcxCfg->fIsTNSAllowed && NE_16( individual_decision[k], 1 ) && ( !bWhitenedDomain || sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) )
                {
                    Word16 maxPredGain_fx = -ONE_IN_Q7;
                    Word32 maxPredGain_fx = -ONE_IN_Q23;
                    move16();
                    sts[0]->hTcxCfg->pCurrentTnsConfig = &sts[0]->hTcxCfg->tnsConfig[sts[0]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[0]->last_core == ACELP_CORE )];
                    sts[1]->hTcxCfg->pCurrentTnsConfig = &sts[1]->hTcxCfg->tnsConfig[sts[1]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[1]->last_core == ACELP_CORE )];
@@ -227,30 +228,30 @@ void TNSAnalysisStereo_fx(
                         * both filters for the decision
                         */

                        meanPredictionGain_fx = mac_r( L_mult( pFilter[0]->predictionGain, 16384 /*0.5f Q15*/ ), pFilter[1]->predictionGain, 16384 /*0.5f Q15*/ ); // Q7
                        maxPredictionGain_fx = s_max( maxPredictionGain_fx, meanPredictionGain_fx );                                                               // Q7
                        meanPredictionGain_fx = L_add( Mpy_32_16_1( pFilter[0]->predictionGain32, 16384 /*0.5f Q15*/ ), Mpy_32_16_1( pFilter[1]->predictionGain32, 16384 /*0.5f Q15*/ ) ); // Q23
                        maxPredictionGain_fx = L_max( maxPredictionGain_fx, meanPredictionGain_fx );                                                                                       // Q23

                        test();
                        test();
                        test();
                        IF( GT_16( pFilter[0]->predictionGain, pTnsParameters[0]->minPredictionGain ) && LT_32( sts[0]->element_brate, IVAS_80k ) &&
                            GT_16( pFilter[1]->predictionGain, pTnsParameters[1]->minPredictionGain ) && EQ_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) )
                        IF( GT_32( pFilter[0]->predictionGain32, L_shl( pTnsParameters[0]->minPredictionGain, 16 ) ) && LT_32( sts[0]->element_brate, IVAS_80k ) &&
                            GT_32( pFilter[1]->predictionGain32, L_shl( pTnsParameters[1]->minPredictionGain, 16 ) ) && EQ_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) )
                        {
                            pFilter[0]->predictionGain = pFilter[1]->predictionGain = meanPredictionGain_fx; /* more TNS filter sync at 48kbps */
                            pFilter[0]->predictionGain32 = pFilter[1]->predictionGain32 = meanPredictionGain_fx; /* more TNS filter sync at 48kbps */
                            move16();
                            move16();
                        }
                        test();
                        IF( LT_16( abs_s( sub( pFilter[0]->predictionGain, pFilter[1]->predictionGain ) ), mult( SIMILAR_TNS_THRESHOLD_FX_IN_Q15, meanPredictionGain_fx ) ) &&
                        IF( LT_32( L_abs( L_sub( pFilter[0]->predictionGain32, pFilter[1]->predictionGain32 ) ), Mpy_32_16_1( meanPredictionGain_fx, SIMILAR_TNS_THRESHOLD_FX_IN_Q15 ) ) &&
                            ( EQ_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) ) )
                        {

                            Word16 maxAvgSqrCoef_fx = s_max( pFilter[0]->avgSqrCoef, pFilter[1]->avgSqrCoef ); // Q15
                            Word16 meanLtpGain_fx = add( shr( sts[0]->hTcxEnc->tcxltp_gain, 1 ), shr( sts[1]->hTcxEnc->tcxltp_gain, 1 ) );
                            maxPredGain_fx = s_max( maxPredGain_fx, meanPredictionGain_fx );
                            maxPredGain_fx = L_max( maxPredGain_fx, meanPredictionGain_fx );
                            test();
                            test();
                            IF( GT_16( meanPredictionGain_fx, pTnsParameters[0]->minPredictionGain ) || GT_16( maxAvgSqrCoef_fx, pTnsParameters[0]->minAvgSqrCoef ) )
                            IF( GT_32( meanPredictionGain_fx, L_shl( pTnsParameters[0]->minPredictionGain, 16 ) ) || GT_16( maxAvgSqrCoef_fx, pTnsParameters[0]->minAvgSqrCoef ) )
                            {
                                test();
                                test();
@@ -456,7 +457,7 @@ void TNSAnalysisStereo_fx(
                    test();
                    test();
                    test();
                    IF( !bWhitenedDomain && individual_decision[k] == 0 && LT_16( maxPredGain_fx, TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q7 ) && NE_16( sts[0]->hTcxEnc->transform_type[k], TCX_5 ) )
                    IF( !bWhitenedDomain && individual_decision[k] == 0 && LT_32( maxPredGain_fx, TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q23 ) && NE_16( sts[0]->hTcxEnc->transform_type[k], TCX_5 ) )
                    {
                        sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1;
                        move16();
@@ -476,7 +477,7 @@ void TNSAnalysisStereo_fx(
                            ClearTnsFilterCoefficients( sts[1]->hTcxEnc->tnsData[k].filter + iFilter );
                        }
                    }
                    maxPredictionGain_fx = s_max( maxPredictionGain_fx, maxPredGain_fx );
                    maxPredictionGain_fx = L_max( maxPredictionGain_fx, maxPredGain_fx );
                }
            }
        }
@@ -514,7 +515,7 @@ void TNSAnalysisStereo_fx(
            IF( sts[ch]->hTcxCfg->fIsTNSAllowed && ( individual_decision[k] || mct_on ) &&
                ( !bWhitenedDomain || sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) )
            {
                Word16 maxPredGain_fx = -ONE_IN_Q7; // Q7
                Word32 maxPredGain_fx = -ONE_IN_Q23; // Q23
                move16();
                sts[ch]->hTcxCfg->pCurrentTnsConfig = &sts[ch]->hTcxCfg->tnsConfig[sts[ch]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[ch]->last_core == ACELP_CORE )];

@@ -525,9 +526,9 @@ void TNSAnalysisStereo_fx(
                    pFilter = sts[ch]->hTcxEnc->tnsData[k].filter + iFilter;
                    pTnsParameters = sts[ch]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter;

                    maxPredGain_fx = s_max( maxPredGain_fx, pFilter->predictionGain );
                    maxPredGain_fx = L_max( maxPredGain_fx, pFilter->predictionGain32 );
                    test();
                    IF( GT_16( pFilter->predictionGain, pTnsParameters->minPredictionGain ) || GT_16( pFilter->avgSqrCoef, pTnsParameters->minAvgSqrCoef ) )
                    IF( GT_32( pFilter->predictionGain32, L_shl( pTnsParameters->minPredictionGain, 16 ) ) || GT_16( pFilter->avgSqrCoef, pTnsParameters->minAvgSqrCoef ) )
                    {
                        test();
                        test();
@@ -601,7 +602,7 @@ void TNSAnalysisStereo_fx(
                move16();
                test();
                test();
                IF( !bWhitenedDomain && LT_16( maxPredGain_fx, TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q7 ) && NE_16( sts[ch]->hTcxEnc->transform_type[k], TCX_5 ) )
                IF( !bWhitenedDomain && LT_32( maxPredGain_fx, TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q23 ) && NE_16( sts[ch]->hTcxEnc->transform_type[k], TCX_5 ) )
                {
                    sts[ch]->hTcxEnc->fUseTns[k] = 0;
                    move16();
@@ -616,7 +617,7 @@ void TNSAnalysisStereo_fx(
                        move16();
                    }
                }
                maxPredictionGain_fx = s_max( maxPredictionGain_fx, maxPredGain_fx );
                maxPredictionGain_fx = L_max( maxPredictionGain_fx, maxPredGain_fx );
            }
        }
    }
Loading