Esempio n. 1
0
/* of int16s to make it fit in an int32                                 */
void silk_sum_sqr_shift(int32_t * energy,	/* O   Energy of x, after shifting to the right                     */
			int * shift,	/* O   Number of bits right shift applied to energy                 */
			const int16_t * x,	/* I   Input vector                                                 */
			int len	/* I   Length of input vector                                       */
    )
{
	int i, shft;
	int32_t nrg_tmp, nrg;

	nrg = 0;
	shft = 0;
	len--;
	for (i = 0; i < len; i += 2) {
		nrg = silk_SMLABB_ovflw(nrg, x[i], x[i]);
		nrg = silk_SMLABB_ovflw(nrg, x[i + 1], x[i + 1]);
		if (nrg < 0) {
			/* Scale down */
			nrg =
			    (int32_t) silk_RSHIFT_uint((uint32_t) nrg, 2);
			shft = 2;
			break;
		}
	}
	for (; i < len; i += 2) {
		nrg_tmp = silk_SMULBB(x[i], x[i]);
		nrg_tmp = silk_SMLABB_ovflw(nrg_tmp, x[i + 1], x[i + 1]);
		nrg =
		    (int32_t) silk_ADD_RSHIFT_uint(nrg,
						      (uint32_t) nrg_tmp,
						      shft);
		if (nrg < 0) {
			/* Scale down */
			nrg =
			    (int32_t) silk_RSHIFT_uint((uint32_t) nrg, 2);
			shft += 2;
		}
	}
	if (i == len) {
		/* One sample left to process */
		nrg_tmp = silk_SMULBB(x[i], x[i]);
		nrg = (int32_t) silk_ADD_RSHIFT_uint(nrg, nrg_tmp, shft);
	}

	/* Make sure to have at least one extra leading zero (two leading zeros in total) */
	if (nrg & 0xC0000000) {
		nrg = silk_RSHIFT_uint((uint32_t) nrg, 2);
		shft += 2;
	}

	/* Output arguments */
	*shift = shft;
	*energy = nrg;
}
void silk_LPC_analysis_filter(
    opus_int16                  *out,               /* O    Output signal                                               */
    const opus_int16            *in,                /* I    Input signal                                                */
    const opus_int16            *B,                 /* I    MA prediction coefficients, Q12 [order]                     */
    const opus_int32            len,                /* I    Signal length                                               */
    const opus_int32            d                   /* I    Filter order                                                */
)
{
    opus_int         ix, j;
    opus_int32       out32_Q12, out32;
    const opus_int16 *in_ptr;

    silk_assert( d >= 6 );
    silk_assert( (d & 1) == 0 );
    silk_assert( d <= len );

    for( ix = d; ix < len; ix++ ) {
        in_ptr = &in[ ix - 1 ];

        out32_Q12 = silk_SMULBB( in_ptr[  0 ], B[ 0 ] );
        /* Allowing wrap around so that two wraps can cancel each other. The rare
           cases where the result wraps around can only be triggered by invalid streams*/
        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -1 ], B[ 1 ] );
        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -2 ], B[ 2 ] );
        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -3 ], B[ 3 ] );
        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -4 ], B[ 4 ] );
        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -5 ], B[ 5 ] );
        for( j = 6; j < d; j += 2 ) {
            out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j     ], B[ j     ] );
            out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] );
        }

        /* Subtract prediction */
        out32_Q12 = silk_SUB32_ovflw( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 );

        /* Scale to Q0 */
        out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );

        /* Saturate output */
        out[ ix ] = (opus_int16)silk_SAT16( out32 );
    }

    /* Set first d output samples to zero */
    silk_memset( out, 0, d * sizeof( opus_int16 ) );
}