/* SKP_Silk_prefilter. Prefilter for finding Quantizer input signal */ SKP_INLINE void SKP_Silk_prefilt_FIX( SKP_Silk_prefilter_state_FIX *P, /* I/O state */ SKP_int32 st_res_Q12[], /* I short term residual signal */ SKP_int16 xw[], /* O prefiltered signal */ SKP_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ SKP_int Tilt_Q14, /* I Tilt shaping coeficient */ SKP_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients*/ SKP_int lag, /* I Lag for harmonic shaping */ SKP_int length /* I Length of signals */ ) { SKP_int i, idx, LTP_shp_buf_idx; SKP_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; SKP_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; SKP_int16 *LTP_shp_buf; /* To speed up use temp variables instead of using the struct */ LTP_shp_buf = P->sLTP_shp; LTP_shp_buf_idx = P->sLTP_shp_buf_idx; sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; for( i = 0; i < length; i++ ) { if( lag > 0 ) { /* unrolled loop */ SKP_assert( HARM_SHAPE_FIR_TAPS == 3 ); idx = lag + LTP_shp_buf_idx; n_LTP_Q12 = SKP_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); n_LTP_Q12 = SKP_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); n_LTP_Q12 = SKP_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); } else { n_LTP_Q12 = 0; } n_Tilt_Q10 = SKP_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); n_LF_Q10 = SKP_SMLAWB( SKP_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); sLF_AR_shp_Q12 = SKP_SUB32( st_res_Q12[ i ], SKP_LSHIFT( n_Tilt_Q10, 2 ) ); sLF_MA_shp_Q12 = SKP_SUB32( sLF_AR_shp_Q12, SKP_LSHIFT( n_LF_Q10, 2 ) ); LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; LTP_shp_buf[ LTP_shp_buf_idx ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); xw[i] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 12 ) ); } /* Copy temp variable back to state */ P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; P->sLTP_shp_buf_idx = LTP_shp_buf_idx; }
/* Entropy constrained MATRIX-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */ void SKP_Silk_VQ_WMat_EC_FIX(int *ind, /* O index of best codebook vector */ int32_t * rate_dist_Q14, /* O best weighted quantization error + mu * rate */ const int16_t * in_Q14, /* I input vector to be quantized */ const int32_t * W_Q18, /* I weighting matrix */ const int16_t * cb_Q14, /* I codebook */ const int16_t * cl_Q6, /* I code length for each codebook vector */ const int mu_Q8, /* I tradeoff between weighted error and rate */ int L /* I number of vectors in codebook */ ) { int k; const int16_t *cb_row_Q14; int32_t sum1_Q14, sum2_Q16, diff_Q14_01, diff_Q14_23, diff_Q14_4; /* Loop over codebook */ *rate_dist_Q14 = int32_t_MAX; cb_row_Q14 = cb_Q14; for (k = 0; k < L; k++) { /* Pack pairs of int16 values per int32 */ diff_Q14_01 = (uint16_t) (in_Q14[0] - cb_row_Q14[0]) | SKP_LSHIFT((int32_t) in_Q14[1] - cb_row_Q14[1], 16); diff_Q14_23 = (uint16_t) (in_Q14[2] - cb_row_Q14[2]) | SKP_LSHIFT((int32_t) in_Q14[3] - cb_row_Q14[3], 16); diff_Q14_4 = in_Q14[4] - cb_row_Q14[4]; /* Weighted rate */ sum1_Q14 = SKP_SMULBB(mu_Q8, cl_Q6[k]); assert(sum1_Q14 >= 0); /* Add weighted quantization error, assuming W_Q18 is symmetric */ /* NOTE: the code below loads two int16 values as one int32, and multiplies each using the */ /* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */ /* loaded in reverse order and the code will give the wrong result. In that case swapping */ /* the SMLAWB and SMLAWT instructions should solve the problem. */ /* first row of W_Q18 */ sum2_Q16 = SKP_SMULWT(W_Q18[1], diff_Q14_01); sum2_Q16 = SKP_SMLAWB(sum2_Q16, W_Q18[2], diff_Q14_23); sum2_Q16 = SKP_SMLAWT(sum2_Q16, W_Q18[3], diff_Q14_23); sum2_Q16 = SKP_SMLAWB(sum2_Q16, W_Q18[4], diff_Q14_4); sum2_Q16 = SKP_LSHIFT(sum2_Q16, 1); sum2_Q16 = SKP_SMLAWB(sum2_Q16, W_Q18[0], diff_Q14_01); sum1_Q14 = SKP_SMLAWB(sum1_Q14, sum2_Q16, diff_Q14_01); /* second row of W_Q18 */ sum2_Q16 = SKP_SMULWB(W_Q18[7], diff_Q14_23); sum2_Q16 = SKP_SMLAWT(sum2_Q16, W_Q18[8], diff_Q14_23); sum2_Q16 = SKP_SMLAWB(sum2_Q16, W_Q18[9], diff_Q14_4); sum2_Q16 = SKP_LSHIFT(sum2_Q16, 1); sum2_Q16 = SKP_SMLAWT(sum2_Q16, W_Q18[6], diff_Q14_01); sum1_Q14 = SKP_SMLAWT(sum1_Q14, sum2_Q16, diff_Q14_01); /* third row of W_Q18 */ sum2_Q16 = SKP_SMULWT(W_Q18[13], diff_Q14_23); sum2_Q16 = SKP_SMLAWB(sum2_Q16, W_Q18[14], diff_Q14_4); sum2_Q16 = SKP_LSHIFT(sum2_Q16, 1); sum2_Q16 = SKP_SMLAWB(sum2_Q16, W_Q18[12], diff_Q14_23); sum1_Q14 = SKP_SMLAWB(sum1_Q14, sum2_Q16, diff_Q14_23); /* fourth row of W_Q18 */ sum2_Q16 = SKP_SMULWB(W_Q18[19], diff_Q14_4); sum2_Q16 = SKP_LSHIFT(sum2_Q16, 1); sum2_Q16 = SKP_SMLAWT(sum2_Q16, W_Q18[18], diff_Q14_23); sum1_Q14 = SKP_SMLAWT(sum1_Q14, sum2_Q16, diff_Q14_23); /* last row of W_Q18 */ sum2_Q16 = SKP_SMULWB(W_Q18[24], diff_Q14_4); sum1_Q14 = SKP_SMLAWB(sum1_Q14, sum2_Q16, diff_Q14_4); assert(sum1_Q14 >= 0); /* find best */ if (sum1_Q14 < *rate_dist_Q14) { *rate_dist_Q14 = sum1_Q14; *ind = k; } /* Go to next cbk vector */ cb_row_Q14 += LTP_ORDER; } }