/* Upsample by a factor 2, coarser */ void SKP_Silk_resample_2_1_coarse( const SKP_int16 *in, /* I: 8 kHz signal [len] */ SKP_int32 *S, /* I/O: State vector [4] */ SKP_int16 *out, /* O: 16 kHz signal [2*len] */ SKP_int32 *scratch, /* I: Scratch memory [3*len] */ const SKP_int32 len /* I: Number of INPUT samples */ ) { SKP_int32 k, idx; /* Coefficients for coarser 2-fold resampling */ const SKP_int16 A20c[ 2 ] = { 2119, 16663 }; const SKP_int16 A21c[ 2 ] = { 8050, 26861 }; /* Convert Q15 -> Q25 */ for( k = 0; k < len; k++ ) { scratch[ k ] = SKP_LSHIFT( (SKP_int32)in[ k ], 10 ); } idx = SKP_LSHIFT( len, 1 ); /* Allpass filters */ SKP_Silk_allpass_int( scratch, S, A20c[ 0 ], scratch + idx, len ); SKP_Silk_allpass_int( scratch + idx, S + 1, A20c[ 1 ], scratch + len, len ); SKP_Silk_allpass_int( scratch, S + 2, A21c[ 0 ], scratch + idx, len ); SKP_Silk_allpass_int( scratch + idx, S + 3, A21c[ 1 ], scratch, len ); /* Interleave two allpass outputs */ for( k = 0; k < len; k++ ) { idx = SKP_LSHIFT( k, 1 ); out[ idx ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( scratch[ k + len ], 10 ) ); out[ idx + 1 ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( scratch[ k ], 10 ) ); } }
/* Downsample by a factor 2, coarsest */ void SKP_Silk_resample_1_2_coarsest( const SKP_int16 *in, /* I: 16 kHz signal [2*len] */ SKP_int32 *S, /* I/O: State vector [2] */ SKP_int16 *out, /* O: 8 kHz signal [len] */ SKP_int32 *scratch, /* I: Scratch memory [3*len] */ const SKP_int32 len /* I: Number of OUTPUT samples*/ ) { SKP_int32 k, idx; /* De-interleave allpass inputs, and convert Q15 -> Q25 */ for( k = 0; k < len; k++ ) { idx = SKP_LSHIFT( k, 1 ); scratch[ k ] = SKP_LSHIFT( (SKP_int32)in[ idx ], 10 ); scratch[ k + len ] = SKP_LSHIFT( (SKP_int32)in[ idx + 1 ], 10 ); } idx = SKP_LSHIFT( len, 1 ); /* Allpass filters */ SKP_Silk_allpass_int( scratch, S, A21cst[ 0 ], scratch + idx, len ); SKP_Silk_allpass_int( scratch + len, S + 1, A20cst[ 0 ], scratch, len ); /* Add two allpass outputs */ for( k = 0; k < len; k++ ) { out[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( scratch[ k ] + scratch[ k + idx ], 11 ) ); } }
/* Split signal into two decimated bands using first-order allpass filters */ void SKP_Silk_ana_filt_bank_1(const int16_t * in, /* I: Input signal [N] */ int32_t * S, /* I/O: State vector [2] */ int16_t * outL, /* O: Low band [N/2] */ int16_t * outH, /* O: High band [N/2] */ int32_t * scratch, /* I: Scratch memory [3*N/2] */ const int32_t N /* I: Number of input samples */ ) { int k, N2 = SKP_RSHIFT(N, 1); int32_t out_tmp; /* De-interleave three allpass inputs, and convert Q15 -> Q25 */ for (k = 0; k < N2; k++) { scratch[k + N] = SKP_LSHIFT((int32_t) in[2 * k], 10); scratch[k + N2] = SKP_LSHIFT((int32_t) in[2 * k + 1], 10); } /* Allpass filters */ SKP_Silk_allpass_int(scratch + N2, S + 0, A_fb1_20[0], scratch, N2); SKP_Silk_allpass_int(scratch + N, S + 1, A_fb1_21[0], scratch + N2, N2); /* Add and subtract two allpass outputs to create bands */ for (k = 0; k < N2; k++) { out_tmp = scratch[k] + scratch[k + N2]; outL[k] = (int16_t) SKP_SAT16(SKP_RSHIFT_ROUND(out_tmp, 11)); out_tmp = scratch[k] - scratch[k + N2]; outH[k] = (int16_t) SKP_SAT16(SKP_RSHIFT_ROUND(out_tmp, 11)); } }
/* Resamples by a factor 3/1 */ void SKP_Silk_resample_3_1( SKP_int16 *out, /* O: Fs_high signal [inLen*3] */ SKP_int32 *S, /* I/O: State vector [7] */ const SKP_int16 *in, /* I: Fs_low signal [inLen] */ const SKP_int32 inLen /* I: Input length */ ) { SKP_int k, LSubFrameIn, LSubFrameOut; SKP_int32 out_tmp, idx, inLenTmp = inLen; SKP_int32 scratch00[ IN_SUBFR_LEN_RESAMPLE_3_1 ]; SKP_int32 scratch0[ 3 * IN_SUBFR_LEN_RESAMPLE_3_1 ]; SKP_int32 scratch1[ 3 * IN_SUBFR_LEN_RESAMPLE_3_1 ]; /* Coefficients for 3-fold resampling */ const SKP_int16 A30[ 2 ] = { 1773, 17818 }; const SKP_int16 A31[ 2 ] = { 4942, 25677 }; const SKP_int16 A32[ 2 ] = { 11786, 29304 }; while( inLenTmp > 0 ) { LSubFrameIn = SKP_min_int( IN_SUBFR_LEN_RESAMPLE_3_1, inLenTmp ); LSubFrameOut = SKP_SMULBB( 3, LSubFrameIn ); /* Convert Q15 -> Q25 */ for( k = 0; k < LSubFrameIn; k++ ) { scratch00[k] = SKP_LSHIFT( (SKP_int32)in[ k ], 10 ); } /* Allpass filtering */ /* Scratch size: 2 * 3* LSubFrame * sizeof(SKP_int32) */ SKP_Silk_allpass_int( scratch00, S + 1, A30[ 0 ], scratch1, LSubFrameIn ); SKP_Silk_allpass_int( scratch1, S + 2, A30[ 1 ], scratch0, LSubFrameIn ); SKP_Silk_allpass_int( scratch00, S + 3, A31[ 0 ], scratch1, LSubFrameIn ); SKP_Silk_allpass_int( scratch1, S + 4, A31[ 1 ], scratch0 + IN_SUBFR_LEN_RESAMPLE_3_1, LSubFrameIn ); SKP_Silk_allpass_int( scratch00, S + 5, A32[ 0 ], scratch1, LSubFrameIn ); SKP_Silk_allpass_int( scratch1, S + 6, A32[ 1 ], scratch0 + 2 * IN_SUBFR_LEN_RESAMPLE_3_1, LSubFrameIn ); /* Interleave three allpass outputs */ for( k = 0; k < LSubFrameIn; k++ ) { idx = SKP_SMULBB( 3, k ); scratch1[ idx ] = scratch0[ k ]; scratch1[ idx + 1 ] = scratch0[ k + IN_SUBFR_LEN_RESAMPLE_3_1 ]; scratch1[ idx + 2 ] = scratch0[ k + 2 * IN_SUBFR_LEN_RESAMPLE_3_1 ]; } /* Low-pass filtering */ SKP_Silk_lowpass_int( scratch1, S, scratch0, LSubFrameOut ); /* Saturate and convert to SKP_int16 */ for( k = 0; k < LSubFrameOut; k++ ) { out_tmp = scratch0[ k ]; out[ k ] = (SKP_int16) SKP_SAT16( SKP_RSHIFT_ROUND( out_tmp, 10 ) ); } in += LSubFrameIn; inLenTmp -= LSubFrameIn; out += LSubFrameOut; } }
/* Downsamples by a factor 3 */ void SKP_Silk_resample_1_3( SKP_int16 *out, /* O: Fs_low signal [inLen/3] */ SKP_int32 *S, /* I/O: State vector [7] */ const SKP_int16 *in, /* I: Fs_high signal [inLen] */ const SKP_int32 inLen /* I: Input length, must be a multiple of 3 */ ) { SKP_int k, outLen, LSubFrameIn, LSubFrameOut; SKP_int32 out_tmp, limit = 102258000; // (102258000 + 1560) * 21 * 2^(-16) = 32767.5 SKP_int32 scratch0[ 3 * OUT_SUBFR_LEN ]; SKP_int32 scratch10[ OUT_SUBFR_LEN ], scratch11[ OUT_SUBFR_LEN ], scratch12[ OUT_SUBFR_LEN ]; /* coefficients for 3-fold resampling */ const SKP_int16 A30[ 2 ] = { 1773, 17818 }; const SKP_int16 A31[ 2 ] = { 4942, 25677 }; const SKP_int16 A32[ 2 ] = { 11786, 29304 }; /* Check that input is multiple of 3 */ SKP_assert( inLen % 3 == 0 ); outLen = SKP_DIV32_16( inLen, 3 ); while( outLen > 0 ) { LSubFrameOut = SKP_min_int( OUT_SUBFR_LEN, outLen ); LSubFrameIn = SKP_SMULBB( 3, LSubFrameOut ); /* Low-pass filter, Q15 -> Q25 */ SKP_Silk_lowpass_short( in, S, scratch0, LSubFrameIn ); /* De-interleave three allpass inputs */ for( k = 0; k < LSubFrameOut; k++ ) { scratch10[ k ] = scratch0[ 3 * k ]; scratch11[ k ] = scratch0[ 3 * k + 1 ]; scratch12[ k ] = scratch0[ 3 * k + 2 ]; } /* Allpass filters */ SKP_Silk_allpass_int( scratch10, S + 1, A32[ 0 ], scratch0, LSubFrameOut ); SKP_Silk_allpass_int( scratch0, S + 2, A32[ 1 ], scratch10, LSubFrameOut ); SKP_Silk_allpass_int( scratch11, S + 3, A31[ 0 ], scratch0, LSubFrameOut ); SKP_Silk_allpass_int( scratch0, S + 4, A31[ 1 ], scratch11, LSubFrameOut ); SKP_Silk_allpass_int( scratch12, S + 5, A30[ 0 ], scratch0, LSubFrameOut ); SKP_Silk_allpass_int( scratch0, S + 6, A30[ 1 ], scratch12, LSubFrameOut ); /* Add three allpass outputs */ for( k = 0; k < LSubFrameOut; k++ ) { out_tmp = scratch10[ k ] + scratch11[ k ] + scratch12[ k ]; if( out_tmp - limit > 0 ) { out[ k ] = SKP_int16_MAX; } else if( out_tmp + limit < 0 ) { out[ k ] = SKP_int16_MIN; } else { out[ k ] = (SKP_int16) SKP_SMULWB( out_tmp + 1560, 21 ); } } in += LSubFrameIn; out += LSubFrameOut; outLen -= LSubFrameOut; } }