Commit d4273b84 authored by Sandesh Venkatesh's avatar Sandesh Venkatesh
Browse files

Merge branch '3gpp_issue_1165_fix' into 'main'

Fix for 3GPP issue 1165: Assertion in lpc2lsp_fx for OMASA LTV input

See merge request !987
parents 78cb4903 8f777411
Loading
Loading
Loading
Loading
Loading
+147 −0
Original line number Diff line number Diff line
@@ -631,6 +631,153 @@ Word16 lpc2lsp_fx(
    return ( 1 );
}

#ifdef FIX_ISSUE_1165
/*===================================================================*/
/* FUNCTION : lpc2lsp_ivas_fx () */
/*-------------------------------------------------------------------*/
/* PURPOSE : Convert LPC coefficients to LSP coefficients */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* */
/* _ (Word32 []) a : LPC coefficients, Q27 */
/* _ (Word16 []) old_freq: Previous frame LSP coefficients, Q15 */
/* _ (Word16 []) order: LPC order */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16 []) freq: LSP coefficients, Q15 */
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ None */
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ (Word16) flag: 1 means all 10 LSPs are found, 0 otherwise */
/*===================================================================*/

/*NOTE: This function was created to avoid a crash that happens in the*/
/*      first for loop of this function while performing L_shl on a in*/
/*      lpc2lsp_fx, this computation assigns value to Lacc, which is  */
/*      kept in Q26 here to avoid L_shl when a has saturated value.   */
Word16 lpc2lsp_ivas_fx(
    Word32 *a,
    Word16 *freq,
    Word16 *old_freq,
    Word16 order )
{
    Word16 i;
    Word16 rt, low, high, prev_rt, rc;
    Word32 p[11], q[11]; /*  Q26 */
    Word32 Ltemp, v_low;
    Word32 Lacc;
    Word16 tfreq[21];

    /* First construct the P,Q polynomial */
    /* p[0] = q[0] = 1 */
    /* p[i] = -lpcCoeff[i] - lpcCoeff[11-i] - p[i-1] ( 1<=i<=5)*/
    /* q[i] = -lpcCoeff[i] + lpcCoeff[11-i] + q[i-1] ( 1<=i<=5)*/
    Ltemp = L_deposit_h( 0x400 ); /*  Ltemp is 1.0 in Q26 */

    p[0] = Ltemp;
    move32();
    q[0] = Ltemp;
    move32();

    FOR( i = 1; i < ( order / 2 ) + 1; i++ )
    {
        Lacc = L_shr( a[order - i], 1 );
        move32();                                   /* Q26 */
        Lacc = L_sub( Lacc, L_shr( a[i - 1], 1 ) ); /*  Lacc=-lpcCoeff[i-1] + lpcCoeff[order-i]//Q26 */
        q[i] = L_add( ( Lacc ), q[i - 1] );
        move32(); /* Q26 */

        Lacc = L_add( Lacc, a[i - 1] ); /*  Lacc=lpcCoeff[i-1] + lpcCoeff[order-i]//Q26 */

        p[i] = L_sub( L_negate( Lacc ), p[i - 1] );
        move32(); /* Q26 */
    }

    /* Search roots of the P and Q polynomials */

    v_low = polynomial_eval_fx( 0, p, order ); /* Q25 */
    move16();
    move16();
    move16();
    move16();
    low = 0;
    high = 8;
    prev_rt = 0;
    rc = 0; /*  root counter */
    FOR( i = 0; i < 32; i++ )
    {
        rt = root_search_fx( low, high, &v_low, p, order );
        low = high;
        move16();
        high = add( high, 8 );

        IF( GE_16( rt, prev_rt ) )
        {
            tfreq[rc] = rt;
            move16();
            rc = add( rc, 2 );
        }
        prev_rt = add( rt, 6 );
    } /*  End for P roots */

    tfreq[rc] = 0x3f80;
    move16(); /*  Set a high enough value as fake root for Q search */

    IF( LT_16( rc, order ) )
    {
        /*  lost P root */
        /* copy from previous LSP and return */
        FOR( i = 0; i < order; i++ )
        {
            move16();
            freq[i] = old_freq[i];
        }
        return ( 0 );
    }
    ELSE
    {
        /*  Search for Q roots between P roots */
        v_low = L_deposit_h( 0x800 ); /* Init a positive value for v_low */
        rc = 1;
        move16();
        FOR( i = 0; i < order / 2; i++ )
        {
            low = shr( tfreq[rc - 1], 6 );
            high = add( shr( tfreq[rc + 1], 6 ), 1 );
            rt = root_search_fx( low, high, &v_low, q, order );

            IF( rt < 0 )
            {
                /* No Q root in this interval */
                /* copy from previous LSP and return */
                FOR( i = 0; i < order; i++ )
                {
                    move16();
                    freq[i] = old_freq[i];
                }
                return ( 0 );
            }
            ELSE
            {
                move16();
                tfreq[rc] = rt;
                rc = add( rc, 2 );
            } /*  end else, find Q root */
        }     /*  end for */
    }         /* end else */

    FOR( i = 0; i < order; i++ )
    {
        freq[i] = tfreq[i];
        move16();
    }

    return ( 1 );
}
#endif

/*===================================================================*/
/* FUNCTION      :  lsp2lpc_fx ()                                    */
/*-------------------------------------------------------------------*/
+1 −0
Original line number Diff line number Diff line
@@ -122,4 +122,5 @@
#define FIX_1113_OPT_DIRAC_BIN_REND             /* FhG: Various optimizations to ivas_dirac_dec_binaual_functions.c */
#define FIX_ISSUE_1187                          /* Ittiam: Fix for issue 1187: Assertion error observed in evs_enc_fx (with option stereo_dmx_evs) from bass_pf_enc_fx function*/
#define FIX_ISSUE_1186                          /* Ittiam: Fix for Issue 1186: Energy/scaling issue for ISM-1 at all bitrates */
#define FIX_ISSUE_1165                          /* Ittiam: Fix for issue 1165: Assertion in lpc2lsp_fx for OMASA LTV input */
#endif
+8 −0
Original line number Diff line number Diff line
@@ -808,6 +808,14 @@ Word16 lpc2lsp_fx(
    Word16 *old_freq,
    Word16 order );
#ifdef FIX_ISSUE_1165
Word16 lpc2lsp_ivas_fx(
    Word32 *a,
    Word16 *freq,
    Word16 *old_freq,
    Word16 order );
#endif
void lsp2lpc_fx(
    Word16 *a,
    Word16 *freq,
+347 −0
Original line number Diff line number Diff line
@@ -1495,6 +1495,349 @@ void E_ACELP_4tsearch_fx( Word16 dn[] /*Qdn*/, const Word16 cn[] /*Q_xn*/, const
    return;
}

#ifdef FIX_ISSUE_1165
void E_ACELP_4tsearch_ivas_fx( Word16 dn[] /*Qdn*/, const Word16 cn[] /*Q_xn*/, const Word16 H[] /*Q12*/, Word16 code[] /*Q9*/, const PulseConfig *config, Word16 ind[] /*Q0*/, Word16 y[] /*Qy*/ )
{
    Word16 sign[L_SUBFR], vec[L_SUBFR];
    Word16 cor_x[16], cor_y[16], h_buf[4 * L_SUBFR];
    Word16 rrixix[4][16];
    Word16 rrixiy[4][256];
    Word16 dn2[L_SUBFR];
    Word16 psk, ps, alpk, alp = 0;
    Word16 codvec[NB_PULSE_MAX];
    Word16 pos_max[4];
    Word16 dn2_pos[8 * 4];
    UWord8 ipos[NB_PULSE_MAX];
    Word16 *p0, *p1, *p2, *p3;
    Word16 *h, *h_inv;
    Word16 i, j, k, l, st, pos;
    Word16 val, tmp, scale;
    Word32 s, L_tmp;
    Word16 nb_pulse, nb_pulse_m2;
    Word16 check = 0; /* debug code not instrumented */
#ifdef BASOP_NOGLOB_DECLARE_LOCAL
    Flag Overflow = 0;
    move32();
#endif


    alp = config->alp; /* Q13 */ /* initial value for energy of all fixed pulses */
    move16();
    nb_pulse = config->nb_pulse;
    move16();
    nb_pulse_m2 = sub( nb_pulse, 2 );

    set16_fx( codvec, 0, nb_pulse );

    /*
     * Find sign for each pulse position.
     */

    E_ACELP_pulsesign( cn, dn, dn2, sign, vec, alp, 0x7fff, L_SUBFR );

    /*
     * Select the most important 8 position per track according to dn2[].
     */
    E_ACELP_findcandidates( dn2, dn2_pos, pos_max );

    /*
     * Compute h_inv[i].
     */
    set16_fx( h_buf, 0, L_SUBFR );

    set16_fx( h_buf + ( 2 * L_SUBFR ), 0, L_SUBFR );

    h = h_buf + L_SUBFR;
    h_inv = h_buf + ( 3 * L_SUBFR );

    /*Check the energy if it is too high then scale to prevent an overflow*/
    scale = 0;
    move16();
    L_tmp = L_deposit_l( 0 );
    BASOP_SATURATE_WARNING_OFF_EVS
    FOR( i = 0; i < L_SUBFR; i++ )
    {
#ifdef BASOP_NOGLOB
        L_tmp = L_mac_o( L_tmp, H[i], H[i], &Overflow ); /*Q25*/
#else
        L_tmp = L_mac( L_tmp, H[i], H[i] );
#endif
    }
    val = extract_h( L_tmp ); /*Q9*/
    BASOP_SATURATE_WARNING_ON_EVS

    if ( GT_16( val, 0x2000 ) )
    {
        scale = -1;
        move16();
    }
    if ( GT_16( val, 0x7000 ) )
    {
        scale = -2;
        move16();
    }
    if ( EQ_16( val, 32767 ) )
    {
        scale = -3;
        move16();
    }

    Copy_Scale_sig( H, h, L_SUBFR, scale ); /*Q12+scale*/

    E_ACELP_vec_neg_fx( h, h_inv, L_SUBFR );


    /*
     * Compute correlation matrices needed for the codebook search.
     */
    E_ACELP_corrmatrix_fx( h, sign, vec, rrixix, rrixiy );


    /*
     * Deep first search:
     * ------------------
     * 20 bits (4p):  4 iter x ((4x16)+(8x16))              = 768 tests
     * 36 bits (8p):  4 iter x ((1x1)+(4x16)+(8x16)+(8x16)) = 1280 tests
     * 52 bits (12p): 3 iter x ((1x1)+(1x1)+(4x16)+(6x16)
     *                                      +(8x16)+(8x16)) = 1248 tests
     * 64 bits (16p): 2 iter x ((1x1)+(1x1)+(4x16)+(6x16)
     *                        +(6x16)+(8x16)+(8x16)+(8x16)) = 1280 tests
     */
    psk = -1;
    move16();
    alpk = 1;
    move16();

    /*Number of iterations*/
    FOR( k = 0; k < config->nbiter; k++ )
    {
        E_ACELP_setup_pulse_search_pos( config, k, ipos );

        /* format of alp changes to Q(15-ALP2_E) */

        pos = config->fixedpulses;
        move16();

        IF( config->fixedpulses == 0 ) /* 1100, 11, 1110, 1111, 2211 */
        {
            ps = 0;
            move16();
            alp = 0;
            move16();
            set16_fx( vec, 0, L_SUBFR );
        }
        ELSE IF( EQ_16( config->fixedpulses, 2 ) ) /* 2222 and 3322 */
        {
            /* first stage: fix 2 pulses */
            ind[0] = pos_max[ipos[0]];
            move16();
            ind[1] = pos_max[ipos[1]];
            move16();
            ps = add( dn[ind[0]], dn[ind[1]] );

            /*alp = rrixix[ipos[0]][ind[0] >> 2] + rrixix[ipos[1]][ind[1] >> 2] +
                    rrixiy[ipos[0]][((ind[0] >> 2) << 4) + (ind[1] >> 2)];*/

            i = shr( ind[0], 2 );
            j = shr( ind[1], 2 );
            l = add( shl( i, 4 ), j );
            s = L_mult( rrixix[ipos[0]][i], _1_ );     /* Q9+Q12+1 */
            s = L_mac( s, rrixix[ipos[1]][j], _1_ );   /* Q9+Q12+1 */
            alp = mac_r( s, rrixiy[ipos[0]][l], _1_ ); /* Q9+Q12+1-16 */

            p0 = h - ind[0]; /*Q12+scale*/
            IF( sign[ind[0]] < 0 )
            {
                p0 = h_inv - ind[0]; /*Q12+scale*/
            }

            p1 = h - ind[1]; /*Q12+scale*/
            IF( sign[ind[1]] < 0 )
            {
                p1 = h_inv - ind[1]; /*Q12+scale*/
            }

            FOR( i = 0; i < L_SUBFR; i++ )
            {
                vec[i] = add( *p0++, *p1++ ); /*Q12+scale*/
                move16();
            }
        }
        ELSE /* 3333 and above */
        {
            /* first stage: fix 4 pulses */

            ind[0] = pos_max[ipos[0]]; /*Q0*/
            move16();
            ind[1] = pos_max[ipos[1]]; /*Q0*/
            move16();
            ind[2] = pos_max[ipos[2]]; /*Q0*/
            move16();
            ind[3] = pos_max[ipos[3]]; /*Q0*/
            move16();

            /*ps = dn[ind[0]] + dn[ind[1]] + dn[ind[2]] + dn[ind[3]];*/
            ps = add( add( add( dn[ind[0]], dn[ind[1]] ), dn[ind[2]] ), dn[ind[3]] );

            p0 = h - ind[0]; /*Q12+scale*/
            IF( sign[ind[0]] < 0 )
            {
                p0 = h_inv - ind[0]; /*Q12+scale*/
            }

            p1 = h - ind[1]; /*Q12+scale*/
            IF( sign[ind[1]] < 0 )
            {
                p1 = h_inv - ind[1]; /*Q12+scale*/
            }

            p2 = h - ind[2]; /*Q12+scale*/
            IF( sign[ind[2]] < 0 )
            {
                p2 = h_inv - ind[2]; /*Q12+scale*/
            }

            p3 = h - ind[3]; /*Q12+scale*/
            IF( sign[ind[3]] < 0 )
            {
                p3 = h_inv - ind[3]; /*Q12+scale*/
            }

            FOR( i = 0; i < L_SUBFR; i++ )
            {
                vec[i] = add( add( add( *p0++, *p1++ ), *p2++ ), *p3++ ); /*Q12+scale*/
                move16();
            }

            L_tmp = L_mult( vec[0], vec[0] ); /*Q25+2*scale*/
            FOR( i = 1; i < L_SUBFR; i++ )
#ifdef BASOP_NOGLOB
            L_tmp = L_mac_o( L_tmp, vec[i], vec[i], &Overflow ); /*Q25+2*scale*/
#else
            L_tmp = L_mac( L_tmp, vec[i], vec[i] );
#endif

            alp = round_fx( L_shr( L_tmp, 3 ) ); /*Q6+2*scale*/

            /*alp *= 0.5F;      */
        }

        /* other stages of 2 pulses */
        st = 0;
        move16();
        FOR( j = pos; j < nb_pulse; j += 2 )
        {
            IF( GE_16( nb_pulse_m2, j ) ) /* pair-wise search */
            {
                /*
                 * Calculate correlation of all possible positions
                 * of the next 2 pulses with previous fixed pulses.
                 * Each pulse can have 16 possible positions.
                 */
                E_ACELP_h_vec_corr1_fx( h, vec, ipos[j], sign, rrixix, cor_x, dn2_pos, config->nbpos[st] );

                E_ACELP_h_vec_corr2_fx( h, vec, ipos[j + 1], sign, rrixix, cor_y );

                /*
                 * Find best positions of 2 pulses.
                 */
                E_ACELP_2pulse_search( config->nbpos[st], ipos[j], ipos[j + 1], &ps, &alp,
                                       &ind[j], &ind[j + 1], dn, dn2_pos, cor_x, cor_y, rrixiy );
            }
            ELSE /* single pulse search */
            {
                E_ACELP_h_vec_corr2_fx( h, vec, ipos[j], sign, rrixix, cor_x );

                E_ACELP_h_vec_corr2_fx( h, vec, ipos[j + 1], sign, rrixix, cor_y );

                E_ACELP_1pulse_search( &ipos[j], &ps, &alp,
                                       &ind[j], dn, cor_x, cor_y );
            }

            IF( GT_16( nb_pulse_m2, j ) )
            {
                p0 = h - ind[j]; /*Q12+scale*/
                IF( sign[ind[j]] < 0 )
                {
                    p0 = h_inv - ind[j]; /*Q12+scale*/
                }

                p1 = h - ind[j + 1]; /*Q12+scale*/
                IF( sign[ind[j + 1]] < 0 )
                {
                    p1 = h_inv - ind[j + 1]; /*Q12+scale*/
                }


                FOR( i = 0; i < L_SUBFR; i++ )
                {
                    tmp = add( *p0++, *p1++ );
#ifdef BASOP_NOGLOB
                    vec[i] = add_o( vec[i], tmp, &Overflow ); /* can saturate here. */
                    move16();
#else
                    vec[i] = add( vec[i], tmp ); /* can saturate here. */
                    move16();
#endif
                }
            }
            st = add( st, 1 );
        }

        /* memorise the best codevector */

        /*ps = ps * ps;                                            MULT(1);*/
        ps = mult( ps, ps );
        /*s = (alpk * ps) - (psk * alp);                            MULT(2);ADD(1);*/
        s = L_msu( L_mult( alpk, ps ), psk, alp ); /*Q9+Q6+1=Q16*/

        if ( psk < 0 )
        {
            s = 1;
            move32();
        }
        IF( s > 0 )
        {
            psk = ps;
            move16();
            alpk = alp;
            move16();
            Copy( ind, codvec, nb_pulse ); /*Q0*/
            check = 1;                     /* debug code not instrumented */
        }
    }

    assert( check ); /* debug code not instrumented */

    /*
     * Build the codeword, the filtered codeword and index of codevector, as well as store weighted correlations.
     */

    E_ACELP_build_code( nb_pulse, codvec, sign, code, ind );

    set16_fx( y, 0, L_SUBFR );
    FOR( k = 0; k < nb_pulse; ++k )
    {
        i = codvec[k]; /*Q0*/
        move16();
        p0 = h_inv - i; /*Q12+scale*/
        IF( sign[i] > 0 )
        {
            p0 -= 2 * L_SUBFR;
        }
        FOR( i = 0; i < L_SUBFR; i++ )
        {
#ifdef BASOP_NOGLOB
            y[i] = add_o( y[i], *p0++, &Overflow ); /*Q12+scale*/
#else
            y[i] = add( y[i], *p0++ );
#endif
            move16();
        }
    }
    return;
}
#endif

/*
 * E_ACELP_4t_fx
@@ -1651,7 +1994,11 @@ void E_ACELP_4t_ivas_fx(
    }
    ELSE
    {
#ifdef FIX_ISSUE_1165
        E_ACELP_4tsearch_ivas_fx( dn, cn, H, code, &config, ind, y );
#else
        E_ACELP_4tsearch_fx( dn, cn, H, code, &config, ind, y );
#endif
    }
    E_ACELP_indexing_fx( code, &config, NB_TRACK_FCB_4T, _index );
    return;
+4 −0
Original line number Diff line number Diff line
@@ -1559,6 +1559,10 @@ void Mode2_pit_encode_fx(
    Word16 pit_res_max );
void E_ACELP_4tsearch_fx( Word16 dn[] /*Qdn*/, const Word16 cn[] /*Q_xn*/, const Word16 H[] /*Q12*/, Word16 code[] /*Q9*/, const PulseConfig *config, Word16 ind[] /*Q0*/, Word16 y[] /*Qy*/ );

#ifdef FIX_ISSUE_1165
void E_ACELP_4tsearch_ivas_fx( Word16 dn[] /*Qdn*/, const Word16 cn[] /*Q_xn*/, const Word16 H[] /*Q12*/, Word16 code[] /*Q9*/, const PulseConfig *config, Word16 ind[] /*Q0*/, Word16 y[] /*Qy*/ );
#endif

void E_ACELP_4t_fx(
    Word16 dn[], /* Qdn */
    Word16 cn[] /* Q_xn */,
Loading