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