/* Laroia low complexity NLSF weights */ void SKP_Silk_NLSF_VQ_weights_laroia_FLP( SKP_float *pXW, /* 0: Pointer to input vector weights [D x 1] */ const SKP_float *pX, /* I: Pointer to input vector [D x 1] */ const SKP_int D /* I: Input vector dimension */ ) { SKP_int k; SKP_float tmp1, tmp2; /* Safety checks */ SKP_assert( D > 0 ); SKP_assert( ( D & 1 ) == 0 ); /* First value */ tmp1 = 1.0f / SKP_max_float( pX[ 0 ], MIN_NDELTA ); tmp2 = 1.0f / SKP_max_float( pX[ 1 ] - pX[ 0 ], MIN_NDELTA ); pXW[ 0 ] = tmp1 + tmp2; /* Main loop */ for( k = 1; k < D - 1; k += 2 ) { tmp1 = 1.0f / SKP_max_float( pX[ k + 1 ] - pX[ k ], MIN_NDELTA ); pXW[ k ] = tmp1 + tmp2; tmp2 = 1.0f / SKP_max_float( pX[ k + 2 ] - pX[ k + 1 ], MIN_NDELTA ); pXW[ k + 1 ] = tmp1 + tmp2; } /* Last value */ tmp1 = 1.0f / SKP_max_float( 1.0f - pX[ D - 1 ], MIN_NDELTA ); pXW[ D - 1 ] = tmp1 + tmp2; }
/* Generates excitation for CNG LPC synthesis */ SKP_INLINE void SKP_Silk_CNG_exc( SKP_int16 residual[], /* O CNG residual signal Q0 */ SKP_int32 exc_buf_Q10[], /* I Random samples buffer Q10 */ SKP_int32 Gain_Q16, /* I Gain to apply */ SKP_int length, /* I Length */ SKP_int32 *rand_seed /* I/O Seed to random index generator */ ) { SKP_int32 seed; SKP_int i, idx, exc_mask; exc_mask = CNG_BUF_MASK_MAX; while( exc_mask > length ) { exc_mask = SKP_RSHIFT( exc_mask, 1 ); } seed = *rand_seed; for( i = 0; i < length; i++ ) { seed = SKP_RAND( seed ); idx = ( SKP_int )( SKP_RSHIFT( seed, 24 ) & exc_mask ); SKP_assert( idx >= 0 ); SKP_assert( idx <= CNG_BUF_MASK_MAX ); residual[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( exc_buf_Q10[ idx ], Gain_Q16 ), 10 ) ); } *rand_seed = seed; }
void SKP_Silk_VAD_GetNoiseLevels( const SKP_int32 pX[ VAD_N_BANDS ], /* I subband energies */ SKP_Silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ ) { SKP_int k; SKP_int32 nl, nrg, inv_nrg; SKP_int coef, min_coef; /* Initially faster smoothing */ if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */ min_coef = SKP_DIV32_16( SKP_int16_MAX, SKP_RSHIFT( psSilk_VAD->counter, 4 ) + 1 ); } else { min_coef = 0; } for( k = 0; k < VAD_N_BANDS; k++ ) { /* Get old noise level estimate for current band */ nl = psSilk_VAD->NL[ k ]; SKP_assert( nl >= 0 ); /* Add bias */ nrg = SKP_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] ); SKP_assert( nrg > 0 ); /* Invert energies */ inv_nrg = SKP_DIV32( SKP_int32_MAX, nrg ); SKP_assert( inv_nrg >= 0 ); /* Less update when subband energy is high */ if( nrg > SKP_LSHIFT( nl, 3 ) ) { coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3; } else if( nrg < nl ) {
/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */ void silk_NLSF_VQ( SKP_int32 err_Q26[], /* O Quantization errors [K] */ const SKP_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */ const SKP_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */ const SKP_int K, /* I Number of codebook vectors */ const SKP_int LPC_order /* I Number of LPCs */ ) { SKP_int i, m; SKP_int32 diff_Q15, sum_error_Q30, sum_error_Q26; SKP_assert( LPC_order <= 16 ); SKP_assert( ( LPC_order & 1 ) == 0 ); /* Loop over codebook */ for( i = 0; i < K; i++ ) { sum_error_Q26 = 0; for( m = 0; m < LPC_order; m += 2 ) { /* Compute weighted squared quantization error for index m */ diff_Q15 = SKP_SUB_LSHIFT32( in_Q15[ m ], ( SKP_int32 )*pCB_Q8++, 7 ); // range: [ -32767 : 32767 ] sum_error_Q30 = SKP_SMULBB( diff_Q15, diff_Q15 ); /* Compute weighted squared quantization error for index m + 1 */ diff_Q15 = SKP_SUB_LSHIFT32( in_Q15[m + 1], ( SKP_int32 )*pCB_Q8++, 7 ); // range: [ -32767 : 32767 ] sum_error_Q30 = SKP_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 ); sum_error_Q26 = SKP_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 ); SKP_assert( sum_error_Q26 >= 0 ); SKP_assert( sum_error_Q30 >= 0 ); } err_Q26[ i ] = sum_error_Q26; } }
void SKP_Silk_shell_insertion_sort_increasing( SKP_int32 *a, /* I/O: Unsorted / Sorted vector */ SKP_int *index, /* O: Index vector for the sorted elements */ const SKP_int L, /* I: Vector length */ const SKP_int K /* I: Number of correctly sorted positions */ ) { SKP_int32 value, inc_Q16_tmp; SKP_int i, j, inc, idx; /* Safety checks */ SKP_assert( K > 0 ); SKP_assert( L > 0 ); SKP_assert( L >= K ); /* Calculate initial step size */ inc_Q16_tmp = SKP_LSHIFT( (SKP_int32)L, 15 ); inc = SKP_RSHIFT( inc_Q16_tmp, 16 ); /* Write start indices in index vector */ for( i = 0; i < K; i++ ) { index[ i ] = i; } /* Shell sort first values */ while( inc > 0 ) { for( i = inc; i < K; i++ ) { value = a[ i ]; idx = index[ i ]; for( j = i - inc; ( j >= 0 ) && ( value < a[ j ] ); j -= inc ) { a[ j + inc ] = a[ j ]; /* Shift value */ index[ j + inc ] = index[ j ]; /* Shift index */ } a[ j + inc ] = value; /* Write value */ index[ j + inc ] = idx; /* Write index */ } inc_Q16_tmp = SKP_SMULWB( inc_Q16_tmp, 29789 ); // 29789_Q16 = 2.2^(-1)_Q0 inc = SKP_RSHIFT_ROUND( inc_Q16_tmp, 16 ); } /* If less than L values are asked for, check the remaining values, */ /* but only spend CPU to ensure that the K first values are correct */ /* Insertion sort remaining values */ for( i = K; i < L; i++ ) { value = a[ i ]; if( value < a[ K - 1 ] ) { for( j = K - 2; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { a[ j + 1 ] = a[ j ]; /* Shift value */ index[ j + 1 ] = index[ j ]; /* Shift index */ } a[ j + 1 ] = value; /* Write value */ index[ j + 1 ] = i; /* Write index */ } } }
/* every other sample of window is linearly interpolated, for speed */ void SKP_Silk_apply_sine_window( SKP_int16 px_win[], /* O Pointer to windowed signal */ const SKP_int16 px[], /* I Pointer to input signal */ const SKP_int win_type, /* I Selects a window type */ const SKP_int length /* I Window length, multiple of 4 */ ) { SKP_int k; SKP_int32 f_Q16, c_Q20, S0_Q16, S1_Q16; /* Length must be multiple of 4 */ SKP_assert( ( length & 3 ) == 0 ); /* Input pointer must be 4-byte aligned */ SKP_assert( ( (SKP_int64)px & 3 ) == 0 ); if( win_type == 0 ) { f_Q16 = SKP_DIV32_16( 411775, length + 1 ); // 411775 = 2 * 65536 * pi } else { f_Q16 = SKP_DIV32_16( 205887, length + 1 ); // 205887 = 65536 * pi } /* factor used for cosine approximation */ c_Q20 = -SKP_RSHIFT( SKP_MUL( f_Q16, f_Q16 ), 12 ); /* c_Q20 becomes too large if length is too small */ SKP_assert( c_Q20 >= -32768 ); /* initialize state */ if( win_type < 2 ) { /* start from 0 */ S0_Q16 = 0; /* approximation of sin(f) */ S1_Q16 = f_Q16; } else { /* start from 1 */ S0_Q16 = ( 1 << 16 ); /* approximation of cos(f) */ S1_Q16 = ( 1 << 16 ) + SKP_RSHIFT( c_Q20, 5 ); } /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ /* 4 samples at a time */ for( k = 0; k < length; k += 4 ) { px_win[ k ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] ); px_win[ k + 1 ] = (SKP_int16)SKP_SMULWB( S1_Q16, px[ k + 1] ); S0_Q16 = SKP_RSHIFT( SKP_MUL( c_Q20, S1_Q16 ), 20 ) + SKP_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1; S0_Q16 = SKP_min( S0_Q16, ( 1 << 16 ) ); px_win[ k + 2 ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] ); px_win[ k + 3 ] = (SKP_int16)SKP_SMULWB( S0_Q16, px[ k + 3 ] ); S1_Q16 = SKP_RSHIFT( SKP_MUL( c_Q20, S0_Q16 ), 20 ) + SKP_LSHIFT( S0_Q16, 1 ) - S1_Q16; S1_Q16 = SKP_min( S1_Q16, ( 1 << 16 ) ); } }
/* Autocorrelations for a warped frequency axis */ void silk_warped_autocorrelation_FIX( opus_int32 *corr, /* O Result [order + 1] */ opus_int *scale, /* O Scaling of the correlation vector */ const opus_int16 *input, /* I Input data to correlate */ const opus_int warping_Q16, /* I Warping coefficient */ const opus_int length, /* I Length of input */ const opus_int order /* I Correlation order (even) */ ) { opus_int n, i, lsh; opus_int32 tmp1_QS, tmp2_QS; opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* Order must be even */ SKP_assert( ( order & 1 ) == 0 ); SKP_assert( 2 * QS - QC >= 0 ); /* Loop over samples */ for( n = 0; n < length; n++ ) { tmp1_QS = SKP_LSHIFT32( ( opus_int32 )input[ n ], QS ); /* Loop over allpass sections */ for( i = 0; i < order; i += 2 ) { /* Output of allpass section */ tmp2_QS = SKP_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); state_QS[ i ] = tmp1_QS; corr_QC[ i ] += SKP_RSHIFT64( SKP_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); /* Output of allpass section */ tmp1_QS = SKP_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); state_QS[ i + 1 ] = tmp2_QS; corr_QC[ i + 1 ] += SKP_RSHIFT64( SKP_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); } state_QS[ order ] = tmp1_QS; corr_QC[ order ] += SKP_RSHIFT64( SKP_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); } lsh = silk_CLZ64( corr_QC[ 0 ] ) - 35; lsh = SKP_LIMIT( lsh, -12 - QC, 30 - QC ); *scale = -( QC + lsh ); SKP_assert( *scale >= -30 && *scale <= 12 ); if( lsh >= 0 ) { for( i = 0; i < order + 1; i++ ) { corr[ i ] = ( opus_int32 )SKP_CHECK_FIT32( SKP_LSHIFT64( corr_QC[ i ], lsh ) ); } } else { for( i = 0; i < order + 1; i++ ) { corr[ i ] = ( opus_int32 )SKP_CHECK_FIT32( SKP_RSHIFT64( corr_QC[ i ], -lsh ) ); } } SKP_assert( corr_QC[ 0 ] >= 0 ); // If breaking, decrease QC }
void SKP_Silk_LDL_FLP( SKP_float *A, /* (I/O) Pointer to Symetric Square Matrix */ SKP_int M, /* (I) Size of Matrix */ SKP_float *L, /* (I/O) Pointer to Square Upper triangular Matrix */ SKP_float *Dinv /* (I/O) Pointer to vector holding the inverse diagonal elements of D */ ) { SKP_int i, j, k, loop_count, err = 1; SKP_float *ptr1, *ptr2; double temp, diag_min_value; SKP_float v[ MAX_MATRIX_SIZE ], D[ MAX_MATRIX_SIZE ]; // temp arrays SKP_assert( M <= MAX_MATRIX_SIZE ); diag_min_value = FIND_LTP_COND_FAC * 0.5f * ( A[ 0 ] + A[ M * M - 1 ] ); for( loop_count = 0; loop_count < M && err == 1; loop_count++ ) { err = 0; for( j = 0; j < M; j++ ) { ptr1 = matrix_adr( L, j, 0, M ); temp = matrix_ptr( A, j, j, M ); // element in row j column j for( i = 0; i < j; i++ ) { v[ i ] = ptr1[ i ] * D[ i ]; temp -= ptr1[ i ] * v[ i ]; } if( temp < diag_min_value ) { /* Badly conditioned matrix: add white noise and run again */ temp = ( loop_count + 1 ) * diag_min_value - temp; for( i = 0; i < M; i++ ) { matrix_ptr( A, i, i, M ) += ( SKP_float )temp; } err = 1; break; } D[ j ] = ( SKP_float )temp; Dinv[ j ] = ( SKP_float )( 1.0f / temp ); matrix_ptr( L, j, j, M ) = 1.0f; ptr1 = matrix_adr( A, j, 0, M ); ptr2 = matrix_adr( L, j + 1, 0, M); for( i = j + 1; i < M; i++ ) { temp = 0.0; for( k = 0; k < j; k++ ) { temp += ptr2[ k ] * v[ k ]; } matrix_ptr( L, i, j, M ) = ( SKP_float )( ( ptr1[ i ] - temp ) * Dinv[ j ] ); ptr2 += M; // go to next column } } } SKP_assert( err == 0 ); }
/* Compute weighted quantization errors for an LPC_order element input vector, over one codebook stage */ void SKP_Silk_NLSF_VQ_sum_error_FIX( SKP_int32 *err_Q20, /* O Weighted quantization errors [N*K] */ const SKP_int *in_Q15, /* I Input vectors to be quantized [N*LPC_order] */ const SKP_int *w_Q6, /* I Weighting vectors [N*LPC_order] */ const SKP_int16 *pCB_Q15, /* I Codebook vectors [K*LPC_order] */ const SKP_int N, /* I Number of input vectors */ const SKP_int K, /* I Number of codebook vectors */ const SKP_int LPC_order /* I Number of LPCs */ ) { SKP_int i, n, m; SKP_int32 diff_Q15, sum_error, Wtmp_Q6; SKP_int32 Wcpy_Q6[ MAX_LPC_ORDER / 2 ]; const SKP_int16 *cb_vec_Q15; SKP_assert( LPC_order <= 16 ); SKP_assert( ( LPC_order & 1 ) == 0 ); /* Copy to local stack and pack two weights per int32 */ for( m = 0; m < SKP_RSHIFT( LPC_order, 1 ); m++ ) { Wcpy_Q6[ m ] = w_Q6[ 2 * m ] | SKP_LSHIFT( ( SKP_int32 )w_Q6[ 2 * m + 1 ], 16 ); } /* Loop over input vectors */ for( n = 0; n < N; n++ ) { /* Loop over codebook */ cb_vec_Q15 = pCB_Q15; for( i = 0; i < K; i++ ) { sum_error = 0; for( m = 0; m < LPC_order; m += 2 ) { /* Get two weights packed in an int32 */ Wtmp_Q6 = Wcpy_Q6[ SKP_RSHIFT( m, 1 ) ]; /* Compute weighted squared quantization error for index m */ diff_Q15 = in_Q15[ m ] - *cb_vec_Q15++; // range: [ -32767 : 32767 ] sum_error = SKP_SMLAWB( sum_error, SKP_SMULBB( diff_Q15, diff_Q15 ), Wtmp_Q6 ); /* Compute weighted squared quantization error for index m + 1 */ diff_Q15 = in_Q15[m + 1] - *cb_vec_Q15++; // range: [ -32767 : 32767 ] sum_error = SKP_SMLAWT( sum_error, SKP_SMULBB( diff_Q15, diff_Q15 ), Wtmp_Q6 ); } SKP_assert( sum_error >= 0 ); err_Q20[ i ] = sum_error; } err_Q20 += K; in_Q15 += LPC_order; } }
/* Convert NLSF parameters to stable AR prediction filter coefficients */ void SKP_Silk_NLSF2A_stable( SKP_int16 pAR_Q12[ MAX_LPC_ORDER ], /* O Stabilized AR coefs [LPC_order] */ const SKP_int pNLSF[ MAX_LPC_ORDER ], /* I NLSF vector [LPC_order] */ const SKP_int LPC_order /* I LPC/LSF order */ ) { SKP_int i; SKP_int32 invGain_Q30; SKP_Silk_NLSF2A( pAR_Q12, pNLSF, LPC_order ); /* Ensure stable LPCs */ for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { if( SKP_Silk_LPC_inverse_pred_gain( &invGain_Q30, pAR_Q12, LPC_order ) == 1 ) { SKP_Silk_bwexpander( pAR_Q12, LPC_order, 65536 - SKP_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015 */ } else { break; } } /* Reached the last iteration */ if( i == MAX_LPC_STABILIZE_ITERATIONS ) { SKP_assert( 0 ); for( i = 0; i < LPC_order; i++ ) { pAR_Q12[ i ] = 0; } } }
/* sum of squares of a SKP_float array, with result as double */ double SKP_Silk_energy_FLP( const SKP_float *data, SKP_int dataSize ) { SKP_int i, dataSize4; double result; /* 4x unrolled loop */ result = 0.0f; dataSize4 = dataSize & 0xFFFC; for( i = 0; i < dataSize4; i += 4 ) { result += data[ i + 0 ] * data[ i + 0 ] + data[ i + 1 ] * data[ i + 1 ] + data[ i + 2 ] * data[ i + 2 ] + data[ i + 3 ] * data[ i + 3 ]; } /* add any remaining products */ for( ; i < dataSize; i++ ) { result += data[ i ] * data[ i ]; } SKP_assert( result >= 0.0 ); return result; }
/* Shell decoder, operates on one shell code frame of 16 pulses */ void SKP_Silk_shell_decoder( SKP_int *pulses0, /* O data: nonnegative pulse amplitudes */ ec_dec *psRangeDec, /* I/O Compressor data structure */ const SKP_int pulses4 /* I number of pulses per pulse-subframe */ ) { SKP_int pulses3[ 2 ], pulses2[ 4 ], pulses1[ 8 ]; /* this function operates on one shell code frame of 16 pulses */ SKP_assert( SHELL_CODEC_FRAME_LENGTH == 16 ); decode_split( &pulses3[ 0 ], &pulses3[ 1 ], psRangeDec, pulses4, SKP_Silk_shell_code_table3 ); decode_split( &pulses2[ 0 ], &pulses2[ 1 ], psRangeDec, pulses3[ 0 ], SKP_Silk_shell_code_table2 ); decode_split( &pulses1[ 0 ], &pulses1[ 1 ], psRangeDec, pulses2[ 0 ], SKP_Silk_shell_code_table1 ); decode_split( &pulses0[ 0 ], &pulses0[ 1 ], psRangeDec, pulses1[ 0 ], SKP_Silk_shell_code_table0 ); decode_split( &pulses0[ 2 ], &pulses0[ 3 ], psRangeDec, pulses1[ 1 ], SKP_Silk_shell_code_table0 ); decode_split( &pulses1[ 2 ], &pulses1[ 3 ], psRangeDec, pulses2[ 1 ], SKP_Silk_shell_code_table1 ); decode_split( &pulses0[ 4 ], &pulses0[ 5 ], psRangeDec, pulses1[ 2 ], SKP_Silk_shell_code_table0 ); decode_split( &pulses0[ 6 ], &pulses0[ 7 ], psRangeDec, pulses1[ 3 ], SKP_Silk_shell_code_table0 ); decode_split( &pulses2[ 2 ], &pulses2[ 3 ], psRangeDec, pulses3[ 1 ], SKP_Silk_shell_code_table2 ); decode_split( &pulses1[ 4 ], &pulses1[ 5 ], psRangeDec, pulses2[ 2 ], SKP_Silk_shell_code_table1 ); decode_split( &pulses0[ 8 ], &pulses0[ 9 ], psRangeDec, pulses1[ 4 ], SKP_Silk_shell_code_table0 ); decode_split( &pulses0[ 10 ], &pulses0[ 11 ], psRangeDec, pulses1[ 5 ], SKP_Silk_shell_code_table0 ); decode_split( &pulses1[ 6 ], &pulses1[ 7 ], psRangeDec, pulses2[ 3 ], SKP_Silk_shell_code_table1 ); decode_split( &pulses0[ 12 ], &pulses0[ 13 ], psRangeDec, pulses1[ 6 ], SKP_Silk_shell_code_table0 ); decode_split( &pulses0[ 14 ], &pulses0[ 15 ], psRangeDec, pulses1[ 7 ], SKP_Silk_shell_code_table0 ); }
/* Calculates correlation vector X'*t */ void SKP_Silk_corrVector_FIX( const SKP_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ const SKP_int16 *t, /* I target vector [L] */ const SKP_int L, /* I Length of vectors */ const SKP_int order, /* I Max lag for correlation */ SKP_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */ const SKP_int rshifts /* I Right shifts of correlations */ ) { SKP_int lag, i; const SKP_int16 *ptr1, *ptr2; SKP_int32 inner_prod; ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */ ptr2 = t; /* Calculate X'*t */ if( rshifts > 0 ) { /* Right shifting used */ for( lag = 0; lag < order; lag++ ) { inner_prod = 0; for( i = 0; i < L; i++ ) { inner_prod += SKP_RSHIFT32( SKP_SMULBB( ptr1[ i ], ptr2[i] ), rshifts ); } Xt[ lag ] = inner_prod; /* X[:,lag]'*t */ ptr1--; /* Go to next column of X */ } } else { SKP_assert( rshifts == 0 ); for( lag = 0; lag < order; lag++ ) { Xt[ lag ] = SKP_Silk_inner_prod_aligned( ptr1, ptr2, L ); /* X[:,lag]'*t */ ptr1--; /* Go to next column of X */ } } }
/* Variable order MA prediction error filter. Inverse filter of SKP_Silk_LPC_synthesis_filter. The inlined assembly makes it over 30% faster than the generic C. */ void SKP_Silk_LPC_analysis_filter( const SKP_int16 *in, /* I: Input signal */ const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ SKP_int16 *S, /* I/O: State vector [order] */ SKP_int16 *out, /* O: Output signal */ const SKP_int32 len, /* I: Signal length */ const SKP_int32 Order /* I: Filter order */ ) { SKP_int k; SKP_int32 out32_Q12, out32; /* Order must be even */ SKP_assert( 2 * Order_half == Order ); /* S[] values are in Q0 */ for( k = 0; k < len; k++ ) { LPC_ANALYSYS(out32_Q12, S, B, Order); /* Subtract prediction */ out32_Q12 = SKP_SUB_SAT32( SKP_LSHIFT( (SKP_int32)in[ k ], 12 ), out32_Q12 ); /* Scale to Q0 */ out32 = SKP_RSHIFT_ROUND( out32_Q12, 12 ); out[ k ] = (SKP_int16)SKP_SAT16( out32 ); /* Move input line */ S[ 0 ] = in[ k ]; } }
void SKP_Silk_insertion_sort_decreasing_FLP( SKP_float *a, /* I/O: Unsorted / Sorted vector */ SKP_int *index, /* O: Index vector for the sorted elements */ const SKP_int L, /* I: Vector length */ const SKP_int K /* I: Number of correctly sorted positions */ ) { SKP_float value; SKP_int i, j; /* Safety checks */ SKP_assert( K > 0 ); SKP_assert( L > 0 ); SKP_assert( L >= K ); /* Write start indices in index vector */ for( i = 0; i < K; i++ ) { index[ i ] = i; } /* Sort vector elements by value, decreasing order */ for( i = 1; i < K; i++ ) { value = a[ i ]; for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { a[ j + 1 ] = a[ j ]; /* Shift value */ index[ j + 1 ] = index[ j ]; /* Shift index */ } a[ j + 1 ] = value; /* Write value */ index[ j + 1 ] = i; /* Write index */ } /* If less than L values are asked check the remaining values, */ /* but only spend CPU to ensure that the K first values are correct */ for( i = K; i < L; i++ ) { value = a[ i ]; if( value > a[ K - 1 ] ) { for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { a[ j + 1 ] = a[ j ]; /* Shift value */ index[ j + 1 ] = index[ j ]; /* Shift index */ } a[ j + 1 ] = value; /* Write value */ index[ j + 1 ] = i; /* Write index */ } } }
/* Inverse filter of SKP_Silk_LPC_synthesis_filter */ void SKP_Silk_LPC_analysis_filter( const SKP_int16 *in, /* I: Input signal */ const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ SKP_int16 *S, /* I/O: State vector [order] */ SKP_int16 *out, /* O: Output signal */ const SKP_int32 len, /* I: Signal length */ const SKP_int32 Order /* I: Filter order */ ) { SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 ); SKP_int32 Btmp, B_align_Q12[ SigProc_MAX_ORDER_LPC >> 1 ], out32_Q12, out32; SKP_int16 SA, SB; /* Order must be even */ SKP_assert( 2 * Order_half == Order ); /* Combine two A_Q12 values and ensure 32-bit alignment */ for( k = 0; k < Order_half; k++ ) { idx = SKP_SMULBB( 2, k ); B_align_Q12[ k ] = ( ( (SKP_int32)B[ idx ] ) & 0x0000ffff ) | SKP_LSHIFT( (SKP_int32)B[ idx + 1 ], 16 ); } /* S[] values are in Q0 */ for( k = 0; k < len; k++ ) { SA = S[ 0 ]; out32_Q12 = 0; for( j = 0; j < ( Order_half - 1 ); j++ ) { idx = SKP_SMULBB( 2, j ) + 1; /* Multiply-add two prediction coefficients for each loop */ Btmp = B_align_Q12[ j ]; SB = S[ idx ]; S[ idx ] = SA; out32_Q12 = SKP_SMLABB( out32_Q12, SA, Btmp ); out32_Q12 = SKP_SMLABT( out32_Q12, SB, Btmp ); SA = S[ idx + 1 ]; S[ idx + 1 ] = SB; } /* Unrolled loop: epilog */ Btmp = B_align_Q12[ Order_half - 1 ]; SB = S[ Order - 1 ]; S[ Order - 1 ] = SA; out32_Q12 = SKP_SMLABB( out32_Q12, SA, Btmp ); out32_Q12 = SKP_SMLABT( out32_Q12, SB, Btmp ); /* Subtract prediction */ out32_Q12 = SKP_SUB_SAT32( SKP_LSHIFT( (SKP_int32)in[ k ], 12 ), out32_Q12 ); /* Scale to Q0 */ out32 = SKP_RSHIFT_ROUND( out32_Q12, 12 ); /* Saturate output */ out[ k ] = (SKP_int16)SKP_SAT16( out32 ); /* Move input line */ S[ 0 ] = in[ k ]; } }
/* 2 -> sine window from pi/2 to pi */ void SKP_Silk_apply_sine_window_FLP( SKP_float px_win[], /* O Pointer to windowed signal */ const SKP_float px[], /* I Pointer to input signal */ const SKP_int win_type, /* I Selects a window type */ const SKP_int length /* I Window length, multiple of 4 */ ) { SKP_int k; SKP_float freq, c, S0, S1; SKP_assert( win_type == 1 || win_type == 2 ); /* Length must be multiple of 4 */ SKP_assert( ( length & 3 ) == 0 ); freq = PI / ( length + 1 ); /* Approximation of 2 * cos(f) */ c = 2.0f - freq * freq; /* Initialize state */ if( win_type < 2 ) { /* Start from 0 */ S0 = 0.0f; /* Approximation of sin(f) */ S1 = freq; } else { /* Start from 1 */ S0 = 1.0f; /* Approximation of cos(f) */ S1 = 0.5f * c; } /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ /* 4 samples at a time */ for( k = 0; k < length; k += 4 ) { px_win[ k + 0 ] = px[ k + 0 ] * 0.5f * ( S0 + S1 ); px_win[ k + 1 ] = px[ k + 1 ] * S1; S0 = c * S1 - S0; px_win[ k + 2 ] = px[ k + 2 ] * 0.5f * ( S1 + S0 ); px_win[ k + 3 ] = px[ k + 3 ] * S0; S1 = c * S0 - S1; } }
void silk_LPC_analysis_filter_FLP( SKP_float r_LPC[], /* O LPC residual signal */ const SKP_float PredCoef[], /* I LPC coefficients */ const SKP_float s[], /* I Input signal */ const opus_int length, /* I Length of input signal */ const opus_int Order /* I LPC order */ ) { SKP_assert( Order <= length ); switch( Order ) { case 6: silk_LPC_analysis_filter6_FLP( r_LPC, PredCoef, s, length ); break; case 8: silk_LPC_analysis_filter8_FLP( r_LPC, PredCoef, s, length ); break; case 10: silk_LPC_analysis_filter10_FLP( r_LPC, PredCoef, s, length ); break; case 12: silk_LPC_analysis_filter12_FLP( r_LPC, PredCoef, s, length ); break; case 14: silk_LPC_analysis_filter14_FLP( r_LPC, PredCoef, s, length ); break; case 16: silk_LPC_analysis_filter16_FLP( r_LPC, PredCoef, s, length ); break; default: SKP_assert( 0 ); break; } /* Set first Order output samples to zero */ SKP_memset( r_LPC, 0, Order * sizeof( SKP_float ) ); }
/* Upsample by a factor 4, Note: very low quality, only use with output sampling rates above 96 kHz. */ void SKP_Silk_resampler_private_up4( SKP_int32 *S, /* I/O: State vector [ 2 ] */ SKP_int16 *out, /* O: Output signal [ 4 * len ] */ const SKP_int16 *in, /* I: Input signal [ len ] */ SKP_int32 len /* I: Number of INPUT samples */ ) { SKP_int32 k; SKP_int32 in32, out32, Y, X; SKP_int16 out16; SKP_assert( SKP_Silk_resampler_up2_lq_0 > 0 ); SKP_assert( SKP_Silk_resampler_up2_lq_1 < 0 ); /* Internal variables and state are in Q10 format */ for( k = 0; k < len; k++ ) { /* Convert to Q10 */ in32 = SKP_LSHIFT( (SKP_int32)in[ k ], 10 ); /* All-pass section for even output sample */ Y = SKP_SUB32( in32, S[ 0 ] ); X = SKP_SMULWB( Y, SKP_Silk_resampler_up2_lq_0 ); out32 = SKP_ADD32( S[ 0 ], X ); S[ 0 ] = SKP_ADD32( in32, X ); /* Convert back to int16 and store to output */ out16 = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); out[ 4 * k ] = out16; out[ 4 * k + 1 ] = out16; /* All-pass section for odd output sample */ Y = SKP_SUB32( in32, S[ 1 ] ); X = SKP_SMLAWB( Y, Y, SKP_Silk_resampler_up2_lq_1 ); out32 = SKP_ADD32( S[ 1 ], X ); S[ 1 ] = SKP_ADD32( in32, X ); /* Convert back to int16 and store to output */ out16 = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); out[ 4 * k + 2 ] = out16; out[ 4 * k + 3 ] = out16; } }
/* Helper function, interpolates the filter taps */ SKP_INLINE void silk_LP_interpolate_filter_taps( SKP_int32 B_Q28[ TRANSITION_NB ], SKP_int32 A_Q28[ TRANSITION_NA ], const SKP_int ind, const SKP_int32 fac_Q16 ) { SKP_int nb, na; if( ind < TRANSITION_INT_NUM - 1 ) { if( fac_Q16 > 0 ) { if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */ /* Piece-wise linear interpolation of B and A */ for( nb = 0; nb < TRANSITION_NB; nb++ ) { B_Q28[ nb ] = SKP_SMLAWB( silk_Transition_LP_B_Q28[ ind ][ nb ], silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - silk_Transition_LP_B_Q28[ ind ][ nb ], fac_Q16 ); } for( na = 0; na < TRANSITION_NA; na++ ) { A_Q28[ na ] = SKP_SMLAWB( silk_Transition_LP_A_Q28[ ind ][ na ], silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - silk_Transition_LP_A_Q28[ ind ][ na ], fac_Q16 ); } } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */ SKP_assert( fac_Q16 - ( 1 << 16 ) == SKP_SAT16( fac_Q16 - ( 1 << 16 ) ) ); /* Piece-wise linear interpolation of B and A */ for( nb = 0; nb < TRANSITION_NB; nb++ ) { B_Q28[ nb ] = SKP_SMLAWB( silk_Transition_LP_B_Q28[ ind + 1 ][ nb ], silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - silk_Transition_LP_B_Q28[ ind ][ nb ], fac_Q16 - ( 1 << 16 ) ); } for( na = 0; na < TRANSITION_NA; na++ ) { A_Q28[ na ] = SKP_SMLAWB( silk_Transition_LP_A_Q28[ ind + 1 ][ na ], silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - silk_Transition_LP_A_Q28[ ind ][ na ], fac_Q16 - ( 1 << 16 ) ); } } } else { SKP_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( SKP_int32 ) ); SKP_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( SKP_int32 ) ); } } else { SKP_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( SKP_int32 ) ); SKP_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( SKP_int32 ) ); } }
/* Entropy code the mid/side quantization indices */ void silk_stereo_encode_pred( ec_enc *psRangeEnc, /* I/O Compressor data structure */ opus_int8 ix[ 2 ][ 4 ] /* I Quantization indices */ ) { opus_int n; /* Entropy coding */ n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ]; SKP_assert( n < 25 ); ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 ); for( n = 0; n < 2; n++ ) { SKP_assert( ix[ n ][ 0 ] < 3 ); SKP_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS ); ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 ); ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 ); } /* Encode flag that only mid channel is coded */ ec_enc_icdf( psRangeEnc, ix[ 0 ][ 3 ], silk_stereo_only_code_mid_iCDF, 8 ); }
/* * Prefilter for finding Quantizer input signal */ SKP_INLINE void silk_prefilt_FLP( silk_prefilter_state_FLP *P,/* I/O state */ SKP_float st_res[], /* I */ SKP_float xw[], /* O */ SKP_float *HarmShapeFIR, /* I */ SKP_float Tilt, /* I */ SKP_float LF_MA_shp, /* I */ SKP_float LF_AR_shp, /* I */ opus_int lag, /* I */ opus_int length /* I */ ) { opus_int i; opus_int idx, LTP_shp_buf_idx; SKP_float n_Tilt, n_LF, n_LTP; SKP_float sLF_AR_shp, sLF_MA_shp; SKP_float *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 = P->sLF_AR_shp; sLF_MA_shp = P->sLF_MA_shp; for( i = 0; i < length; i++ ) { if( lag > 0 ) { SKP_assert( HARM_SHAPE_FIR_TAPS == 3 ); idx = lag + LTP_shp_buf_idx; n_LTP = LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ] * HarmShapeFIR[ 0 ]; n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ] * HarmShapeFIR[ 1 ]; n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ] * HarmShapeFIR[ 2 ]; } else { n_LTP = 0; } n_Tilt = sLF_AR_shp * Tilt; n_LF = sLF_AR_shp * LF_AR_shp + sLF_MA_shp * LF_MA_shp; sLF_AR_shp = st_res[ i ] - n_Tilt; sLF_MA_shp = sLF_AR_shp - n_LF; LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; LTP_shp_buf[ LTP_shp_buf_idx ] = sLF_MA_shp; xw[ i ] = sLF_MA_shp - n_LTP; } /* Copy temp variable back to state */ P->sLF_AR_shp = sLF_AR_shp; P->sLF_MA_shp = sLF_MA_shp; P->sLTP_shp_buf_idx = LTP_shp_buf_idx; }
/* 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; }
/* Downsample by a factor 2, mediocre quality */ void SKP_Silk_resampler_down2( SKP_int32 *S, /* I/O: State vector [ 2 ] */ SKP_int16 *out, /* O: Output signal [ len ] */ const SKP_int16 *in, /* I: Input signal [ floor(len/2) ] */ SKP_int32 inLen /* I: Number of input samples */ ) { SKP_int32 k, len2 = SKP_RSHIFT32( inLen, 1 ); SKP_int32 in32, out32, Y, X; SKP_assert( SKP_Silk_resampler_down2_0 > 0 ); SKP_assert( SKP_Silk_resampler_down2_1 < 0 ); /* Internal variables and state are in Q10 format */ for( k = 0; k < len2; k++ ) { /* Convert to Q10 */ in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k ], 10 ); /* All-pass section for even input sample */ Y = SKP_SUB32( in32, S[ 0 ] ); X = SKP_SMLAWB( Y, Y, SKP_Silk_resampler_down2_1 ); out32 = SKP_ADD32( S[ 0 ], X ); S[ 0 ] = SKP_ADD32( in32, X ); /* Convert to Q10 */ in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k + 1 ], 10 ); /* All-pass section for odd input sample, and add to output of previous section */ Y = SKP_SUB32( in32, S[ 1 ] ); X = SKP_SMULWB( Y, SKP_Silk_resampler_down2_0 ); out32 = SKP_ADD32( out32, S[ 1 ] ); out32 = SKP_ADD32( out32, X ); S[ 1 ] = SKP_ADD32( in32, X ); /* Add, convert back to int16 and store to output */ out[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 11 ) ); } }
SKP_int SKP_Silk_SDK_InitEncoder( void *encState, /* I/O: State */ SKP_Silk_EncodeControlStruct *encStatus /* O: Control structure */ ) { SKP_Silk_encoder_state_Fxx *psEnc; SKP_int ret = SKP_SILK_NO_ERROR; psEnc = ( SKP_Silk_encoder_state_Fxx* )encState; /* Reset Encoder */ if( ret += SKP_Silk_init_encoder_Fxx( psEnc ) ) { SKP_assert( 0 ); } /* Read control structure */ if( ret += SKP_Silk_SDK_QueryEncoder( encState, encStatus ) ) { SKP_assert( 0 ); } return ret; }
/* Deactivate by setting psEncC->mode = 0; */ void silk_LP_variable_cutoff( silk_LP_state *psLP, /* I/O LP filter state */ SKP_int16 *signal, /* I/O Low-pass filtered output signal */ const SKP_int frame_length /* I Frame length */ ) { SKP_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0; SKP_int ind = 0; SKP_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES ); /* Run filter if needed */ if( psLP->mode != 0 ) { /* Calculate index and interpolation factor for interpolation */ #if( TRANSITION_INT_STEPS == 64 ) fac_Q16 = SKP_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 ); #else fac_Q16 = SKP_DIV32_16( SKP_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES ); #endif ind = SKP_RSHIFT( fac_Q16, 16 ); fac_Q16 -= SKP_LSHIFT( ind, 16 ); SKP_assert( ind >= 0 ); SKP_assert( ind < TRANSITION_INT_NUM ); /* Interpolate filter coefficients */ silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 ); /* Update transition frame number for next frame */ psLP->transition_frame_no = SKP_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES ); /* ARMA low-pass filtering */ SKP_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 ); silk_biquad_alt( signal, B_Q28, A_Q28, psLP->In_LP_State, signal, frame_length ); } }
/* even order AR filter */ void SKP_Silk_LPC_synthesis_filter( const SKP_int16 *in, /* I: excitation signal */ const SKP_int16 *A_Q12, /* I: AR coefficients [Order], between -8_Q0 and 8_Q0 */ const SKP_int32 Gain_Q26, /* I: gain */ SKP_int32 *S, /* I/O: state vector [Order] */ SKP_int16 *out, /* O: output signal */ const SKP_int32 len, /* I: signal length */ const SKP_int Order /* I: filter order, must be even */ ) { SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 ); SKP_int32 SA, SB, out32_Q10, out32; /* Order must be even */ SKP_assert( 2 * Order_half == Order ); /* S[] values are in Q14 */ for( k = 0; k < len; k++ ) { SA = S[ Order - 1 ]; out32_Q10 = 0; for( j = 0; j < ( Order_half - 1 ); j++ ) { idx = SKP_SMULBB( 2, j ) + 1; SB = S[ Order - 1 - idx ]; S[ Order - 1 - idx ] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ ( j << 1 ) ] ); out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ ( j << 1 ) + 1 ] ); SA = S[ Order - 2 - idx ]; S[ Order - 2 - idx ] = SB; } /* unrolled loop: epilog */ SB = S[ 0 ]; S[ 0 ] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ Order - 2 ] ); out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ Order - 1 ] ); /* apply gain to excitation signal and add to prediction */ out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[ k ] ) ); /* scale to Q0 */ out32 = SKP_RSHIFT_ROUND( out32_Q10, 10 ); /* saturate output */ out[ k ] = ( SKP_int16 )SKP_SAT16( out32 ); /* move result into delay line */ S[ Order - 1 ] = SKP_LSHIFT_SAT32( out32_Q10, 4 ); } }
/* Processing of gains */ void silk_process_gains_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state_FIX */ silk_encoder_control_FIX *psEncCtrl /* I/O Encoder control_FIX */ ) { silk_shape_state_FIX *psShapeSt = &psEnc->sShape; opus_int k; opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; /* Gain reduction when LTP coding gain is high */ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { /*s = -0.5f * SKP_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ s_Q16 = -silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { psEncCtrl->Gains_Q16[ k ] = SKP_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); } } /* Limit the quantized signal */ /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ InvMaxSqrVal_Q16 = SKP_DIV32_16( silk_log2lin( SKP_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { /* Soft limit on ratio residual energy and squared gains */ ResNrg = psEncCtrl->ResNrg[ k ]; ResNrgPart = SKP_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); if( psEncCtrl->ResNrgQ[ k ] > 0 ) { ResNrgPart = SKP_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); } else { if( ResNrgPart >= SKP_RSHIFT( SKP_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { ResNrgPart = SKP_int32_MAX; } else { ResNrgPart = SKP_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); } } gain = psEncCtrl->Gains_Q16[ k ]; gain_squared = SKP_ADD_SAT32( ResNrgPart, SKP_SMMUL( gain, gain ) ); if( gain_squared < SKP_int16_MAX ) { /* recalculate with higher precision */ gain_squared = SKP_SMLAWW( SKP_LSHIFT( ResNrgPart, 16 ), gain, gain ); SKP_assert( gain_squared > 0 ); gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ gain = SKP_min( gain, SKP_int32_MAX >> 8 ); psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( gain, 8 ); /* Q16 */ } else {
void silk_insertion_sort_increasing_all_values_int16( SKP_int16 *a, /* I/O: Unsorted / Sorted vector */ const SKP_int L /* I: Vector length */ ) { SKP_int value; SKP_int i, j; /* Safety checks */ SKP_assert( L > 0 ); /* Sort vector elements by value, increasing order */ for( i = 1; i < L; i++ ) { value = a[ i ]; for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { a[ j + 1 ] = a[ j ]; /* Shift value */ } a[ j + 1 ] = value; /* Write value */ } }
void silk_warped_LPC_analysis_filter_FLP( SKP_float state[], /* I/O State [order + 1] */ SKP_float res[], /* O Residual signal [length] */ const SKP_float coef[], /* I Coefficients [order] */ const SKP_float input[], /* I Input signal [length] */ const SKP_float lambda, /* I Warping factor */ const opus_int length, /* I Length of input signal */ const opus_int order /* I Filter order (even) */ ) { opus_int n, i; SKP_float acc, tmp1, tmp2; /* Order must be even */ SKP_assert( ( order & 1 ) == 0 ); for( n = 0; n < length; n++ ) { /* Output of lowpass section */ tmp2 = state[ 0 ] + lambda * state[ 1 ]; state[ 0 ] = input[ n ]; /* Output of allpass section */ tmp1 = state[ 1 ] + lambda * ( state[ 2 ] - tmp2 ); state[ 1 ] = tmp2; acc = coef[ 0 ] * tmp2; /* Loop over allpass sections */ for( i = 2; i < order; i += 2 ) { /* Output of allpass section */ tmp2 = state[ i ] + lambda * ( state[ i + 1 ] - tmp1 ); state[ i ] = tmp1; acc += coef[ i - 1 ] * tmp1; /* Output of allpass section */ tmp1 = state[ i + 1 ] + lambda * ( state[ i + 2 ] - tmp2 ); state[ i + 1 ] = tmp2; acc += coef[ i ] * tmp2; } state[ order ] = tmp1; acc += coef[ order - 1 ] * tmp1; res[ n ] = input[ n ] - acc; } }