Commit 3b1d0fe8 authored by Sandesh Venkatesh's avatar Sandesh Venkatesh
Browse files

Fix for 3GPP issue 1058: BASOP asserts in Stereo fx encoder for +10dB selection test inputs - 2

link #1058
parent 6362e224
Loading
Loading
Loading
Loading
Loading
+350 −0
Original line number Diff line number Diff line
@@ -375,3 +375,353 @@ Word16 multi_harm_fx( /* o : frame multi-harmonicity
    }
    return harm;
}

Word16 multi_harm_ivas_fx(                           /* o  : frame multi-harmonicity (1-harmonic, 0-not)   		*/
                      const Word16 Bin_E[],     /* i  : log-energy spectrum of the current frame      Q7	*/
                      Word16 old_S[],           /* i/o: prev. log-energy spectrum w. subtracted floor Q7	*/
                      Word16 cor_map_LT[],      /* i/o: LT correlation map                            Q15	*/
                      Word16 *multi_harm_limit, /* i/o: multi harminic threshold                      Q9	*/
                      const Word32 total_brate, /* i  : total bitrate             					  Q0	*/
                      const Word16 bwidth,      /* i  : input signal bandwidth                        Q0    */
                      Word16 *cor_strong_limit, /* i/o: HF correlation indicator  					  Q0	*/
                      Word16 *st_mean_avr_dyn,  /* i/o: long term average dynamic 					  Q7	*/
                      Word16 *st_last_sw_dyn,   /* i/o: last dynamic              					  Q7	*/
                      Word16 *cor_map_sum,      /* i  : sum of correlation map                        Q8	*/
                      Word16 *sp_floor,         /* o: noise floor estimate                            Q7    */
                      Word16 S_map[]            /* o  : short-term correlation map                    Q7    */
)
{
    Word16 i, j, k, L, stemp, N_mins, ind_mins[L_FFT / 4], *pt_mins, harm;
    Word16 S[L_FFT / 2], flor, step, tmp16, tmp2, Expx2, Expy2;
    Word16 corx2, cory2, corxy, cor, cor_map[L_FFT / 2], *pt1, *pt2, cor_strong;
    Word32 L_acc;
    Word32 Lcorx2, Lcory2, Lcorxy, Lcor_map_LT_sum;
    Word16 mean_dyn;
#ifdef BASOP_NOGLOB_DECLARE_LOCAL
    Flag Overflow = 0;
    move32();
#endif

    /*------------------------------------------------------------------*
     * initialization
     *------------------------------------------------------------------*/

    /* length of the useful part of the spectrum (up to 6.4kHz) */
    L = L_FFT / 2;
    move16();
    if ( EQ_16( bwidth, NB ) )
    {
        /* length of the useful part of the spectrum (up to 3.6kHz) */
        L = 76;
        move16();
    }

    Copy( Bin_E, S, L );

    /*------------------------------------------------------------------*
     * searching of spectral maxima and minima
     *------------------------------------------------------------------*/

    pt_mins = ind_mins;

    /* index of the first minimum */
    if ( LT_16( Bin_E[0], Bin_E[1] ) )
    {
        *pt_mins++ = 0;
        move16();
    }

    FOR( i = 1; i < L - 1; i++ )
    {
        /* minimum found */
        test();
        if ( LT_16( Bin_E[i], Bin_E[i - 1] ) && LT_16( Bin_E[i], Bin_E[i + 1] ) )
        {
            *pt_mins++ = i;
            move16();
        }
    }

    /* index of the last minimum */
    IF( LT_16( Bin_E[L - 1], Bin_E[L - 2] ) )
    {
        *pt_mins++ = sub( L, 1 );
        move16();
    }

    /* total number of minimas found */
    N_mins = (Word16) ( pt_mins - ind_mins - 1 );
    move16();

    /*------------------------------------------------------------------*
     * calculation of the spectral floor
     * subtraction of the spectral floor
     *------------------------------------------------------------------*/

    set16_fx( S, 0, L );

    IF( N_mins > 0 )
    {
        L_acc = L_deposit_l( 0 );
        FOR( i = 0; i < N_mins; ++i )
        {
            L_acc = L_mac0( L_acc, Bin_E[ind_mins[i]], 1 );
        }
        *sp_floor = extract_l( Mult_32_16( L_acc, div_s( 1, N_mins ) ) );
        move16();

        set16_fx( S, 0, ind_mins[0] );
        set16_fx( &S[ind_mins[N_mins]], 0, sub( shr( L_FFT, 1 ), ind_mins[N_mins] ) );

        pt_mins = ind_mins;
        flor = 0;
        move16();
        step = 0;
        move16();

        FOR( i = ind_mins[0]; i < ind_mins[N_mins]; i++ )
        {
            /* we are at the end of the next minimum */
            IF( EQ_16( i, *pt_mins ) )
            {
                pt_mins++;
                flor = Bin_E[i];
                move16(); /*Q7*/

                /* calculate the new step */
                /*step = (Bin_E[*pt_mins] - Bin_E[i]) / (*pt_mins-i);*/

                tmp16 = div_s( 1, sub( *pt_mins, i ) );                            // Q15
                step = msu_r( L_mult( Bin_E[*pt_mins], tmp16 ), Bin_E[i], tmp16 ); // Q7 (15+7+1-16)
            }

            /* subtract the floor */
            S[i] = s_max( sub_sat( Bin_E[i], flor ), 0 );
            move16();

            /* update the floor */
            flor = add( flor, step ); /*Q7*/
        }
    }

    /* Calculate the maximum dynamic per band */
    /* since we are processing 40 bins we will use 1/40 in Q15 to find the mean */
    /* mean_dyn = mean(&S[L-40], 40);*/
    L_acc = L_deposit_l( 0 );
    FOR( i = L - 40; i < L; i++ )
    {
        L_acc = L_mac( L_acc, S[i], 819 /* 1 / 40 in Q15 */ );
    }
    mean_dyn = round_fx( L_acc ); /*Q7*/

    /*mean_dyn = 0.6f * *st_mean_avr_dyn + 0.4f * mean_dyn;*/
    L_acc = L_mult( 13107 /*0.4f*/, mean_dyn );               /*Q23*/
    L_acc = L_mac( L_acc, 19661 /*0.6f*/, *st_mean_avr_dyn ); /*Q23*/
    mean_dyn = round_fx( L_acc );                             /*Q7*/

    test();
    IF( LT_16( mean_dyn, 1229 ) /*9.6f*/ && *cor_strong_limit != 0 )
    {
        *cor_strong_limit = 0;
        move16();
        *st_last_sw_dyn = mean_dyn;
        move16();
    }
    ELSE IF( GT_16( sub( mean_dyn, *st_last_sw_dyn ), 576 ) /*4.5f*/ )
    {
        *cor_strong_limit = 1;
        move16();
    }
    test();
    if ( LT_32( total_brate, ACELP_9k60 ) || GT_32( total_brate, ACELP_16k40 ) )
    {
        *cor_strong_limit = 1;
        move16();
    }

    *st_mean_avr_dyn = mean_dyn;
    move16();

    /*------------------------------------------------------------------*
     * calculation of the correlation map
     *------------------------------------------------------------------*/

    set16_fx( cor_map, 0, L );
    IF( N_mins > 0 )
    {
        Lcorx2 = L_deposit_l( 0 );
        Lcorxy = L_deposit_l( 0 );
        stemp = ind_mins[0];
        move16();
        Lcory2 = L_mult( old_S[stemp], old_S[stemp] );
        k = 1;
        move16();

        FOR( i = add( stemp, 1 ); i <= ind_mins[N_mins]; i++ )
        {
            IF( EQ_16( i, ind_mins[k] ) )
            {
                /* include the last peak point (new minimum) to the corr. sum */
#ifdef BASOP_NOGLOB
                Lcory2 = L_mac_o( Lcory2, old_S[i], old_S[i], &Overflow );
#else  /* BASOP_NOGLOB */
                Lcory2 = L_mac( Lcory2, old_S[i], old_S[i] );
#endif /* BASOP_NOGLOB */

                /* calculation of the norm. peak correlation */
                test();
                IF( Lcorx2 != 0 && Lcory2 != 0 )
                {
                    /* corxy * corxy*/
                    tmp16 = sub( norm_l( Lcorxy ), 1 );
                    corxy = extract_h( L_shl( Lcorxy, tmp16 ) );
                    corxy = mult_r( corxy, corxy );
                    /* (corx2 * cory2) */
                    Expx2 = norm_l( Lcorx2 );
                    Expy2 = norm_l( Lcory2 );
                    corx2 = extract_h( L_shl( Lcorx2, Expx2 ) );
                    cory2 = extract_h( L_shl( Lcory2, Expy2 ) );
                    corx2 = mult_r( corx2, cory2 );
                    Expx2 = add( Expy2, Expx2 );
                    /* Validate num < den */
                    cor = sub( corx2, corxy );
                    cor = shr( cor, 15 );
                    /* Add 1 to tmp16 & shr by 2 if corxy > corx2 */
                    tmp16 = sub( tmp16, cor );
                    corxy = shl( corxy, cor );
                    corxy = shl( corxy, cor );
                    /* cor = corxy * corxy / (corx2 * cory2) */
                    corxy = div_s( corxy, corx2 );
#ifdef BASOP_NOGLOB
                    cor = shr_o( corxy, sub( shl( tmp16, 1 ), Expx2 ), &Overflow ); /* Q15 */
#else                                                                               /* BASOP_NOGLOB */
                    cor = shr( corxy, sub( shl( tmp16, 1 ), Expx2 ) ); /* Q15 */
#endif                                                                              /* BASOP_NOGLOB */
                }
                ELSE
                {
                    cor = 0;
                    move16();
                }

                /* save the norm. peak correlation in the correlation map */
                FOR( j = ind_mins[k - 1]; j < ind_mins[k]; j++ )
                {
                    old_S[j] = S[j];
                    move16();
                    S[j] = shr( cor, 8 );
                    move16();
                    cor_map[j] = cor;
                    move16();
                }

                Lcorx2 = L_deposit_l( 0 );
                Lcory2 = L_deposit_l( 0 );
                Lcorxy = L_deposit_l( 0 );

                k++;
            }
#ifdef BASOP_NOGLOB
            Lcorx2 = L_mac_o( Lcorx2, S[i], S[i], &Overflow );
            Lcory2 = L_mac_o( Lcory2, old_S[i], old_S[i], &Overflow );
            Lcorxy = L_mac_o( Lcorxy, S[i], old_S[i], &Overflow );
#else /* BASOP_NOGLOB */
            Lcorx2 = L_mac( Lcorx2, S[i], S[i] );
            Lcory2 = L_mac( Lcory2, old_S[i], old_S[i] );
            Lcorxy = L_mac( Lcorxy, S[i], old_S[i] );
#endif
        }

        Copy( S, old_S, ind_mins[0] );
        Copy( &S[ind_mins[N_mins]], &old_S[ind_mins[N_mins]], sub( L, ind_mins[N_mins] ) );
    }
    ELSE
    {
        *sp_floor = Bin_E[0];
        move16();
    }
    *sp_floor = mult( *sp_floor, 14231 /* 1.0f / logf( 10.0f ) in Q15 */ );
    move16(); /* Convert to log10() */

    /*------------------------------------------------------------------*
     * updating of the long-term correlation map
     * summation of the long-term correlation map
     *------------------------------------------------------------------*/

    Lcor_map_LT_sum = L_deposit_l( 0 );
    tmp2 = 0;
    move16();

    cor_strong = 0;
    move16();
    pt1 = cor_map_LT;
    move16();
    pt2 = cor_map;
    move16();
    FOR( i = 0; i < L; i++ )
    {
        /* tmp2 += S[i]; */
        tmp2 = add( tmp2, shl( S[i], 1 ) ); /* tmp2 in Q8; max value is 128) */

        /* *pt1 = M_ALPHA_FX * *pt1 + (1-M_ALPHA_FX) * *pt2++ */
        *pt1 = mac_r( L_mult( ONE_MINUS_M_ALPHA, *pt2 ), M_ALPHA_FX, *pt1 );
        move16();

        /* cor_map_LT_sum += *pt1 */
        Lcor_map_LT_sum = L_add( Lcor_map_LT_sum, *pt1 ); /* cor_map_LT_sum in Q15; max value is 128) */

        if ( GT_16( *pt1, 31130 ) /*0.95f*/ )
        {
            cor_strong = 1;
            move16();
        }

        pt1++;
        pt2++;
    }

    IF( EQ_16( bwidth, NB ) )
    {
        /* cor_map_LT_sum *= 1.53f; */
        /* tmp2 *= 1.53f; */
        Lcor_map_LT_sum = L_shl( Mult_32_16( Lcor_map_LT_sum, 25068 /* 1.53f in Q14 */ ), 1 );
        tmp2 = round_fx( L_mac( L_mult( tmp2, 32767 ), tmp2, 17367 /* 0.53 in Q15 */ ) );
    }
    *cor_map_sum = tmp2;
    move16();

    /* final decision about multi-harmonicity */
    harm = 0;
    move16();
    test();
    if ( ( L_msu0( Lcor_map_LT_sum, *multi_harm_limit, 64 ) > 0 ) || ( cor_strong != 0 ) )
    {
        harm = 1;
        move16();
    }

    /*------------------------------------------------------------------*
     * updating of the decision threshold
     *------------------------------------------------------------------*/

    stemp = add( *multi_harm_limit, THR_CORR_STEP_FX );
    if ( GT_32( Lcor_map_LT_sum, THR_CORR_FX ) ) /* Q15 */
    {
        /* *multi_harm_limit -= THR_CORR_STEP_FX */
        stemp = sub( *multi_harm_limit, THR_CORR_STEP_FX );
    }

    stemp = s_min( stemp, THR_CORR_MAX_FX );
    *multi_harm_limit = s_max( stemp, THR_CORR_MIN_FX );
    move16();

    IF( N_mins <= 0 )
    {
        set16_fx( old_S, 0, L );
    }
    IF( S_map != NULL )
    {
        Copy( S, S_map, L );
    }
    return harm;
}
+2 −2
Original line number Diff line number Diff line
@@ -2353,7 +2353,7 @@ void noise_est_ivas_fx(
        {
            i = 0;
            move16();
            *loc_harm = multi_harm_fx( EspecdB, hNoiseEst->old_S_fx, hNoiseEst->cor_map_fx, &hNoiseEst->multi_harm_limit_fx, st_fx->total_brate,
            *loc_harm = multi_harm_ivas_fx( EspecdB, hNoiseEst->old_S_fx, hNoiseEst->cor_map_fx, &hNoiseEst->multi_harm_limit_fx, st_fx->total_brate,
                                            st_fx->bwidth, ( st_fx->hGSCEnc != NULL ) ? &hGSCEnc->cor_strong_limit : &i, &hSpMusClas->mean_avr_dyn_fx, &hSpMusClas->last_sw_dyn_fx, cor_map_sum, sp_floor, S_map );
            move16();
        }
+15 −0
Original line number Diff line number Diff line
@@ -4449,6 +4449,21 @@ Word16 multi_harm_fx( /* o : frame multi-harmonicity
                      Word16 S_map[]            /* o  : short-term correlation map                    Q7    */
);

Word16 multi_harm_ivas_fx(                           /* o  : frame multi-harmonicity (1-harmonic, 0-not)   		*/
                           const Word16 Bin_E[],     /* i  : log-energy spectrum of the current frame      Q7	*/
                           Word16 old_S[],           /* i/o: prev. log-energy spectrum w. subtracted floor Q7	*/
                           Word16 cor_map_LT[],      /* i/o: LT correlation map                            Q15	*/
                           Word16 *multi_harm_limit, /* i/o: multi harminic threshold                      Q9	*/
                           const Word32 total_brate, /* i  : total bitrate             					  Q0	*/
                           const Word16 bwidth,      /* i  : i   signal bandwidth                        Q0    */
                           Word16 *cor_strong_limit, /* i/o: HF correlation indicator  					  Q0	*/
                           Word16 *st_mean_avr_dyn,  /* i/o: long term average dynamic 					  Q7	*/
                           Word16 *st_last_sw_dyn,   /* i/o: last dynamic              					  Q7	*/
                           Word16 *cor_map_sum,      /* i  : sum of correlation map                        Q8	*/
                           Word16 *sp_floor,         /* o: noise floor estimate                            Q7    */
                           Word16 S_map[]            /* o  : short-term correlation map                    Q7    */
);

void pvq_encode_frame_fx(
    BSTR_ENC_HANDLE hBstr,    /* i/o: encoder bitstream handle            */
    const Word16 *coefs_norm, /* i  : normalized coefficients to encode */