Commit 0d47aa8e authored by Sandesh Venkatesh's avatar Sandesh Venkatesh
Browse files

Fix for 3GPP issue 1192: areas of reduced energy observed

Link #1192
parent a3ddf608
Loading
Loading
Loading
Loading
Loading
+62 −131
Original line number Diff line number Diff line
@@ -2399,6 +2399,7 @@ void tcx_noise_factor_fx(
    *fac_ns = extract_l( L_mult0( *quantized_fac_ns, shr( 24576 /*0.75f Q15*/, NBITS_NOISE_FILL_LEVEL ) ) );
}


void tcx_noise_factor_ivas_fx(
    Word32 *x_orig,           /* i: unquantized mdct coefficients                    */
    Word16 x_orig_e,          /* i: exponent                                         */
@@ -2415,8 +2416,9 @@ void tcx_noise_factor_ivas_fx(
    Word16 element_mode       /* i: element mode                                     */
)
{
    Word16 i, k = 0, maxK, segmentOffset;
    Word16 i, k, win, segmentOffset;
    Word32 sqErrorNrg, n;
    Word64 sqErrorNrg64;
    Word16 inv_gain2, inv_gain2_e, tilt_factor, nTransWidth_1;
    Word32 accu1, accu2, tmp32;
    Word16 tmp1, tmp2, s;
@@ -2427,7 +2429,6 @@ void tcx_noise_factor_ivas_fx(
    Flag Overflow = 0;
    move32();
#endif
    move16();

    assert( nTransWidth <= 16 );

@@ -2436,8 +2437,10 @@ void tcx_noise_factor_ivas_fx(
    nTransWidth_1 = sub( nTransWidth, 1 );

    /*Adjust noise filling level*/
    sqErrorNrg = L_deposit_l( 0 );
    n = L_deposit_l( 0 );
    sqErrorNrg64 = 0;
    move64();
    n = 0;
    move32();

    /* get inverse frame length */
    tmp1 = getInvFrameLen( L_frame );
@@ -2463,15 +2466,13 @@ void tcx_noise_factor_ivas_fx(
    IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */
    {
        segmentOffset = i;
        maxK = 1;
        move16();
        move16();
    }
    ELSE
    {
        /* find last nonzero line below iFirstLine, use it as start offset */
        tmp1 = shr( iFirstLine, 1 );
        FOR( i = iFirstLine; i > tmp1; i-- )
        FOR( ; i > tmp1; i-- )
        {
            IF( sqQ[i] != 0 )
            {
@@ -2484,16 +2485,6 @@ void tcx_noise_factor_ivas_fx(
            inv_gain2 = shl( mult( inv_gain2, tilt_factor ), 1 );
        }

        /* initialize left (k) and right (maxK) non-zero neighbor pointers */
        k = 0;
        move16();
        FOR( maxK = 1; maxK < nTransWidth; maxK++ )
        {
            IF( sqQ[i + maxK] != 0 )
            {
                BREAK;
            }
        }
        i = add( i, 1 );
        segmentOffset = i;
        move16();
@@ -2501,17 +2492,20 @@ void tcx_noise_factor_ivas_fx(

    IF( LE_16( nTransWidth, 3 ) )
    {
        accu1 = L_deposit_l( 0 );
        accu2 = L_deposit_l( 0 );
        xMax = L_deposit_l( 0 );
        accu1 = 0;
        move32();
        accu2 = 0;
        move32();
        xMax = 0;
        move32();

        FOR( k = s_and( i, (Word16) 0xFFFE ); k < lowpassLine; k++ )
        FOR( k = i & 0xFFFE; k < lowpassLine; k++ )
        {
            xMax = L_max( xMax, L_abs( x_orig[k] ) );
        }
        s = sub( norm_l( xMax ), 4 );

        FOR( k = s_and( i, (Word16) 0xFFFE ); k < lowpassLine; k += 2 )
        FOR( k = i & 0xFFFE; k < lowpassLine; k += 2 )
        {
            /* even-index bins, left sub-win */
            tmp1 = round_fx( L_shl( x_orig[k], s ) );
@@ -2524,13 +2518,15 @@ void tcx_noise_factor_ivas_fx(
        k = 0;
        move16();

        IF( accu1 == 0 )
        if ( accu1 == 0 )
        {
            accu1 = L_deposit_l( 1 );
            accu1 = 1;
            move32();
        }
        IF( accu2 == 0 )
        if ( accu2 == 0 )
        {
            accu2 = L_deposit_l( 1 );
            accu2 = 1;
            move32();
        }

        att = BASOP_Util_Divide3232_Scale( L_shl( L_min( accu1, accu2 ), 1 ), L_add( accu1, accu2 ), &s );
@@ -2545,19 +2541,19 @@ void tcx_noise_factor_ivas_fx(
        move16();
    }

    accu1 = L_deposit_l( 0 );
    win = 0;
    move16();

    tmp1 = sub( lowpassLine, nTransWidth );
    FOR( ; i <= tmp1; i++ )
    FOR( ; i < lowpassLine; i++ )
    {
        inv_gain2 = shl( mult( inv_gain2, tilt_factor ), 1 );

        IF( EQ_16( maxK, 1 ) ) /* current line is not zero, so reset pointers */
        IF( sqQ[i] != 0 ) /* current line is not zero, so reset pointers */
        {
            IF( win > 0 )
            {
                k = sub( i, segmentOffset );

            IF( k > 0 ) /* add segment sum to sum of segment magnitudes */
            {
                IF( LE_16( nTransWidth, 3 ) )
                {
                    tmp2 = sub( k, c1 );
@@ -2590,58 +2586,35 @@ void tcx_noise_factor_ivas_fx(
                        n = L_mac( n, int_sqr[k], 1152 /*0.03515625f Q15*/ );
                    }
                }
                sqErrorNrg = L_add( sqErrorNrg, accu1 );
                accu1 = L_deposit_l( 0 ); /* segment ended here, so reset segment sum */
                k = 0;
                move16();
            }

            FOR( ; maxK < nTransWidth; maxK++ )
                FOR( k = segmentOffset; k < i - win; k++ )
                {
                IF( sqQ[i + maxK] != 0 )
                    sqErrorNrg64 = W_add( sqErrorNrg64, W_mult_32_16( sqQ[k], nTransWidth ) );
                    sqQ[k] = 0;
                    move32();
                }
                FOR( ; win > 0; win-- )
                {
                    BREAK;
                    sqErrorNrg64 = W_add( sqErrorNrg64, W_mult_32_16( sqQ[k], win ) );
                    sqQ[k++] = 0;
                    move32();
                }
            }
            segmentOffset = add( i, 1 ); /* new segment might start at next line */
        }
        ELSE /* current line is zero, so update pointers & segment sum */
        {
            IF( LT_16( k, nTransWidth ) )
            IF( LT_16( win, nTransWidth ) )
            {
                k = add( k, 1 );
                win = add( win, 1 );
            }

            tmp2 = sub( maxK, nTransWidth );
            test();
            IF( tmp2 < 0 && NE_16( element_mode, IVAS_CPE_MDCT ) )
            {
                maxK = sub( maxK, 1 );
            }

            test();
            IF( ( tmp2 >= 0 ) && ( sqQ[i + sub( nTransWidth, 1 )] != 0 ) )
            {
                maxK = sub( nTransWidth, 1 );
            }

            /* update segment sum: magnitudes scaled by smoothing function */
            /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/
            tmp2 = mult( inv_gain2, shl( imult1616( k, maxK ), 8 ) );
            accu1 = L_add( accu1, L_abs( Mpy_32_16_1( x_orig[i], tmp2 ) ) );
            sqQ[i] = L_shl( Mpy_32_16_1( imult3216( L_abs( x_orig[i] ), win ), inv_gain2 ), inv_gain2_e );
            move32();
        }
    }

    FOR( ; i < lowpassLine; i++ )
    {
        inv_gain2 = shl( mult( inv_gain2, tilt_factor ), 1 );

        IF( EQ_16( maxK, 1 ) ) /* current line is not zero, so reset pointers */
    IF( win > 0 ) /* add last segment sum to sum of segment magnitudes */
    {
        k = sub( i, segmentOffset );

            IF( k > 0 ) /* add segment sum to sum of segment magnitudes */
            {
        IF( LE_16( nTransWidth, 3 ) )
        {
            tmp2 = sub( k, c1 );
@@ -2674,71 +2647,27 @@ void tcx_noise_factor_ivas_fx(
                n = L_mac( n, int_sqr[k], 1152 /*0.03515625f Q15*/ );
            }
        }
                sqErrorNrg = L_add( sqErrorNrg, accu1 );
            }
            segmentOffset = add( i, 1 ); /* no new segments since maxK remains 1 */
        }
        ELSE /* current line is zero, so update pointers & energy sum */
        {
            IF( LT_16( k, nTransWidth ) )
        FOR( k = segmentOffset; k < i - win; k++ )
        {
                k = add( k, 1 );
            }
            IF( LT_16( maxK, nTransWidth ) )
            {
                maxK = sub( maxK, 1 );
            }

            /* update segment sum: magnitudes scaled by smoothing function */
            /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/
            tmp2 = mult( inv_gain2, shl( imult1616( k, maxK ), 8 ) );
            accu1 = L_add( accu1, L_abs( Mpy_32_16_1( x_orig[i], tmp2 ) ) );
        }
    }

    k = sub( i, segmentOffset );
    IF( k > 0 ) /* add last segment sum to sum of segment magnitudes */
    {
        IF( LE_16( nTransWidth, 3 ) )
        {
            tmp2 = sub( k, c1 );
            IF( tmp2 > 0 )
            {
                n = L_msu( n, k, (Word16) 0x8000 );
            }
            IF( tmp2 > 0 )
            {
                n = L_mac( n, nTransWidth_1, (Word16) 0x8000 );
            }
            IF( tmp2 <= 0 )
            {
                n = L_mac( n, int_sqr[k], c2 );
            }
        }
        ELSE
        {
            tmp2 = sub( k, 12 );
            IF( tmp2 > 0 )
            {
                n = L_msu( n, k, (Word16) 0x8000 );
            sqErrorNrg64 = W_add( sqErrorNrg64, W_mult_32_16( sqQ[k], nTransWidth ) );
            sqQ[k] = 0;
            move32();
        }
            IF( tmp2 > 0 )
        FOR( ; win > 0; win-- )
        {
                n = L_sub( n, 0x70000 );
            }
            IF( tmp2 <= 0 )
            {
                n = L_mac( n, int_sqr[k], 1152 /*0.03515625f Q15*/ );
            }
            sqErrorNrg64 = W_add( sqErrorNrg64, W_mult_32_16( sqQ[k], win ) );
            sqQ[k++] = 0;
            move32();
        }
        sqErrorNrg = L_add( sqErrorNrg, accu1 );
    }

    /* noise level factor: average of segment magnitudes of noise bins */
    IF( n > 0 )
    {
        tmp2 = W_norm( sqErrorNrg64 );
        sqErrorNrg = W_extract_l( W_shr( sqErrorNrg64, sub( 32, tmp2 ) ) ); // 31 - (x_orig_e - 1) - 32 + tmp2
        tmp1 = BASOP_Util_Divide3232_Scale( Mpy_32_16_1( sqErrorNrg, att ), n, &s );
        s = add( add( add( s, x_orig_e ), inv_gain2_e ), 7 - 15 );
        s = add( add( add( x_orig_e, sub( 31, tmp2 ) ), -15 ), s );
        BASOP_SATURATE_WARNING_OFF_EVS;
        tmp1 = shl_o( tmp1, s, &Overflow );
        BASOP_SATURATE_WARNING_ON_EVS;
@@ -2762,8 +2691,10 @@ void tcx_noise_factor_ivas_fx(
    move16();

    *fac_ns = extract_l( L_mult0( *quantized_fac_ns, shr( 24576 /*0.75f Q15*/, NBITS_NOISE_FILL_LEVEL ) ) );
    move16();
}


void tcx_encoder_memory_update_fx(
    Word16 *wsig,        /* i : target weighted signal */
    Word16 *xn_buf,      /* i/o: mdct output buffer/time domain weigthed synthesis        */