/* 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 ) ); }