Example #1
0
/* 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 ) );
    }
}
SKP_INLINE opus_int silk_setup_LBRR(
    silk_encoder_state          *psEncC,            /* I/O                      */
    const opus_int32                 TargetRate_bps      /* I                        */
)
{
    opus_int   ret = SILK_NO_ERROR;
    opus_int32 LBRR_rate_thres_bps;

    psEncC->LBRR_enabled = 0;
    if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
        if( psEncC->fs_kHz == 8 ) {
            LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS;
        } else if( psEncC->fs_kHz == 12 ) {
            LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS;
        } else {
            LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS;
        }
        LBRR_rate_thres_bps = SKP_SMULWB( SKP_MUL( LBRR_rate_thres_bps, 125 - SKP_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );

        if( TargetRate_bps > LBRR_rate_thres_bps ) {
            /* Set gain increase for coding LBRR excitation */
            psEncC->LBRR_enabled = 1;
            psEncC->LBRR_GainIncreases = SKP_max_int( 7 - SKP_SMULWB( psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
        }
    }

    return ret;
}
Example #3
0
/* Encodes signs of excitation */
void silk_encode_signs(
    ec_enc                      *psRangeEnc,                        /* I/O  Compressor data structure                   */
    const SKP_int8              pulses[],                           /* I    pulse signal                                */
    SKP_int                     length,                             /* I    length of input                             */
    const SKP_int               signalType,                         /* I    Signal type                                 */
    const SKP_int               quantOffsetType,                    /* I    Quantization offset type                    */
    const SKP_int               sum_pulses[ MAX_NB_SHELL_BLOCKS ]   /* I    Sum of absolute pulses per block            */
)
{
    SKP_int         i, j, p;
    SKP_uint8       icdf[ 2 ];
    const SKP_int8  *q_ptr;
    const SKP_uint8 *icdf_ptr;

    icdf[ 1 ] = 0;
    q_ptr = pulses;
    i = SKP_SMULBB( 6, SKP_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
    icdf_ptr = &silk_sign_iCDF[ i ];
    length = SKP_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
    for( i = 0; i < length; i++ ) {
        p = sum_pulses[ i ];
        if( p > 0 ) {
            icdf[ 0 ] = icdf_ptr[ SKP_min( p - 1, 5 ) ];
            for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
                if( q_ptr[ j ] != 0 ) {
                    ec_enc_icdf( psRangeEnc, SKP_enc_map( q_ptr[ j ]), icdf, 8 );
                }
            }
        }
        q_ptr += SHELL_CODEC_FRAME_LENGTH;
    }
}
/* Resample with a 2x downsampler (optional), a 2nd order AR filter followed by FIR interpolation */
void silk_resampler_private_down_FIR(
	void	                        *SS,		    /* I/O: Resampler state 						*/
	opus_int16						out[],		    /* O:	Output signal 							*/
	const opus_int16					in[],		    /* I:	Input signal							*/
	opus_int32					    inLen		    /* I:	Number of input samples					*/
)
{
    silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
	opus_int32 nSamplesIn;
	opus_int32 max_index_Q16, index_increment_Q16;
	opus_int16 buf1[ RESAMPLER_MAX_BATCH_SIZE_IN / 2 ];
	opus_int32 buf2[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_DOWN_ORDER_FIR ];
	const opus_int16 *FIR_Coefs;

	/* Copy buffered samples to start of buffer */	
	SKP_memcpy( buf2, S->sFIR, RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) );

    FIR_Coefs = &S->Coefs[ 2 ];

	/* Iterate over blocks of frameSizeIn input samples */
    index_increment_Q16 = S->invRatio_Q16;
	while( 1 ) {
		nSamplesIn = SKP_min( inLen, S->batchSize );

        if( S->input2x == 1 ) {
            /* Downsample 2x */
            silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn );

            nSamplesIn = SKP_RSHIFT32( nSamplesIn, 1 );

		    /* Second-order AR filter (output in Q8) */
		    silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], buf1, S->Coefs, nSamplesIn );
        } else {
		    /* Second-order AR filter (output in Q8) */
		    silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], in, S->Coefs, nSamplesIn );
        }

        max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 );

		/* Interpolate filtered signal */
        if( S->FIR_Fracs == 1 ) {
    		out = silk_resampler_private_down_FIR_INTERPOL0(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16);
        } else {
    		out = silk_resampler_private_down_FIR_INTERPOL1(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16, S->FIR_Fracs);
        }
        
		in += nSamplesIn << S->input2x;
		inLen -= nSamplesIn << S->input2x;

		if( inLen > S->input2x ) {
			/* More iterations to do; copy last part of filtered signal to beginning of buffer */
			SKP_memcpy( buf2, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) );
		} else {
			break;
		}
	}

	/* Copy last part of filtered signal to the state for the next call */
	SKP_memcpy( S->sFIR, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) );
}
/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */
void SKP_Silk_resampler_private_IIR_FIR(
	void	                        *SS,		    /* I/O: Resampler state 						*/
	SKP_int16						out[],		    /* O:	Output signal 							*/
	const SKP_int16					in[],		    /* I:	Input signal							*/
	SKP_int32					    inLen		    /* I:	Number of input samples					*/
)
{
    SKP_Silk_resampler_state_struct *S = (SKP_Silk_resampler_state_struct *)SS;
	SKP_int32 nSamplesIn, table_index;
	SKP_int32 max_index_Q16, index_Q16, index_increment_Q16, res_Q15;
	SKP_int16 buf[ 2 * RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_ORDER_FIR_144 ];
    SKP_int16 *buf_ptr;

	/* Copy buffered samples to start of buffer */	
	SKP_memcpy( buf, S->sFIR, RESAMPLER_ORDER_FIR_144 * sizeof( SKP_int32 ) );

	/* Iterate over blocks of frameSizeIn input samples */
    index_increment_Q16 = S->invRatio_Q16;
	while( 1 ) {
		nSamplesIn = SKP_min( inLen, S->batchSize );

        if( S->input2x == 1 ) {
		    /* Upsample 2x */
            S->up2_function( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, nSamplesIn );
        } else {
		    /* Fourth-order ARMA filter */
            SKP_Silk_resampler_private_ARMA4( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, S->Coefs, nSamplesIn );
        }

        max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 + S->input2x );         /* +1 if 2x upsampling */

		/* Interpolate upsampled signal and store in output array */
	    for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
            table_index = SKP_SMULWB( index_Q16 & 0xFFFF, 144 );
            buf_ptr = &buf[ index_Q16 >> 16 ];
            res_Q15 = SKP_SMULBB(          buf_ptr[ 0 ], SKP_Silk_resampler_frac_FIR_144[       table_index ][ 0 ] );
            res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 1 ], SKP_Silk_resampler_frac_FIR_144[       table_index ][ 1 ] );
            res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 2 ], SKP_Silk_resampler_frac_FIR_144[       table_index ][ 2 ] );
            res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 3 ], SKP_Silk_resampler_frac_FIR_144[ 143 - table_index ][ 2 ] );
            res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 4 ], SKP_Silk_resampler_frac_FIR_144[ 143 - table_index ][ 1 ] );
            res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 5 ], SKP_Silk_resampler_frac_FIR_144[ 143 - table_index ][ 0 ] );
			*out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q15, 15 ) );
	    }
		in += nSamplesIn;
		inLen -= nSamplesIn;

		if( inLen > 0 ) {
			/* More iterations to do; copy last part of filtered signal to beginning of buffer */
			SKP_memcpy( buf, &buf[ nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( SKP_int32 ) );
		} else {
			break;
		}
	}

	/* Copy last part of filtered signal to the state for the next call */
	SKP_memcpy( S->sFIR, &buf[nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( SKP_int32 ) );
}
Example #6
0
/* Glues concealed frames with new good recieved frames             */
void SKP_Silk_PLC_glue_frames(
    SKP_Silk_decoder_state      *psDec,             /* I/O decoder state    */
    SKP_Silk_decoder_control    *psDecCtrl,         /* I/O Decoder control  */
    SKP_int16                   signal[],           /* I/O signal           */
    SKP_int                     length              /* I length of residual */
)
{
    SKP_int   i, energy_shift;
    SKP_int32 energy;
    SKP_Silk_PLC_struct *psPLC;
    psPLC = &psDec->sPLC;

    if( psDec->lossCnt ) {
        /* Calculate energy in concealed residual */
        SKP_Silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, signal, length );
        
        psPLC->last_frame_lost = 1;
    } else {
        if( psDec->sPLC.last_frame_lost ) {
            /* Calculate residual in decoded signal if last frame was lost */
            SKP_Silk_sum_sqr_shift( &energy, &energy_shift, signal, length );

            /* Normalize energies */
            if( energy_shift > psPLC->conc_energy_shift ) {
                psPLC->conc_energy = SKP_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
            } else if( energy_shift < psPLC->conc_energy_shift ) {
                energy = SKP_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
            }

            /* Fade in the energy difference */
            if( energy > psPLC->conc_energy ) {
                SKP_int32 frac_Q24, LZ;
                SKP_int32 gain_Q12, slope_Q12;

                LZ = SKP_Silk_CLZ32( psPLC->conc_energy );
                LZ = LZ - 1;
                psPLC->conc_energy = SKP_LSHIFT( psPLC->conc_energy, LZ );
                energy = SKP_RSHIFT( energy, SKP_max_32( 24 - LZ, 0 ) );
                
                frac_Q24 = SKP_DIV32( psPLC->conc_energy, SKP_max( energy, 1 ) );
                
                gain_Q12 = SKP_Silk_SQRT_APPROX( frac_Q24 );
                slope_Q12 = SKP_DIV32_16( ( 1 << 12 ) - gain_Q12, length );

                for( i = 0; i < length; i++ ) {
                    signal[ i ] = SKP_RSHIFT( SKP_MUL( gain_Q12, signal[ i ] ), 12 );
                    gain_Q12 += slope_Q12;
                    gain_Q12 = SKP_min( gain_Q12, ( 1 << 12 ) );
                }
            }
        }
        psPLC->last_frame_lost = 0;

    }
}
/* Downsample by a factor 3, low quality */
void SKP_Silk_resampler_down3(
    SKP_int32                           *S,         /* I/O: State vector [ 8 ]                  */
    SKP_int16                           *out,       /* O:   Output signal [ floor(inLen/3) ]    */
    const SKP_int16                     *in,        /* I:   Input signal [ inLen ]              */
    SKP_int32                           inLen       /* I:   Number of input samples             */
)
{
	SKP_int32 nSamplesIn, counter, res_Q6;
	SKP_int32 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR ];
	SKP_int32 *buf_ptr;

	/* Copy buffered samples to start of buffer */
	SKP_memcpy( buf, S, ORDER_FIR * sizeof( SKP_int32 ) );

	/* Iterate over blocks of frameSizeIn input samples */
	while( 1 ) {
		nSamplesIn = SKP_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN );

	    /* Second-order AR filter (output in Q8) */
	    SKP_Silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in,
            SKP_Silk_Resampler_1_3_COEFS_LQ, nSamplesIn );

		/* Interpolate filtered signal */
        buf_ptr = buf;
        counter = nSamplesIn;
        while( counter > 2 ) {
            /* Inner product */
            res_Q6 = SKP_SMULWB(         SKP_ADD32( buf_ptr[ 0 ], buf_ptr[ 5 ] ), SKP_Silk_Resampler_1_3_COEFS_LQ[ 2 ] );
            res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 1 ], buf_ptr[ 4 ] ), SKP_Silk_Resampler_1_3_COEFS_LQ[ 3 ] );
            res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 2 ], buf_ptr[ 3 ] ), SKP_Silk_Resampler_1_3_COEFS_LQ[ 4 ] );

            /* Scale down, saturate and store in output array */
            *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) );

            buf_ptr += 3;
            counter -= 3;
        }

		in += nSamplesIn;
		inLen -= nSamplesIn;

		if( inLen > 0 ) {
			/* More iterations to do; copy last part of filtered signal to beginning of buffer */
			SKP_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( SKP_int32 ) );
		} else {
			break;
		}
	}

	/* Copy last part of filtered signal to the state for the next call */
	SKP_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( SKP_int32 ) );
}
/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */
void SKP_Silk_resampler_private_IIR_FIR(
	void	                        *SS,		    /* I/O: Resampler state 						*/
	SKP_int16						out[],		    /* O:	Output signal 							*/
	const SKP_int16					in[],		    /* I:	Input signal							*/
	SKP_int32					    inLen		    /* I:	Number of input samples					*/
)
{
    SKP_Silk_resampler_state_struct *S = (SKP_Silk_resampler_state_struct *)SS;
	SKP_int32 nSamplesIn;
	SKP_int32 max_index_Q16, index_increment_Q16;
	SKP_int16 buf[ 2 * RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_ORDER_FIR_144 ];
    

	/* Copy buffered samples to start of buffer */	
	SKP_memcpy( buf, S->sFIR, RESAMPLER_ORDER_FIR_144 * sizeof( SKP_int32 ) );

	/* Iterate over blocks of frameSizeIn input samples */
    index_increment_Q16 = S->invRatio_Q16;
	while( 1 ) {
		nSamplesIn = SKP_min( inLen, S->batchSize );

        if( S->input2x == 1 ) {
		    /* Upsample 2x */
            S->up2_function( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, nSamplesIn );
        } else {
		    /* Fourth-order ARMA filter */
            SKP_Silk_resampler_private_ARMA4( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, S->Coefs, nSamplesIn );
        }

        max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 + S->input2x );         /* +1 if 2x upsampling */
		out = SKP_Silk_resampler_private_IIR_FIR_INTERPOL(out, buf, max_index_Q16, index_increment_Q16);    
		in += nSamplesIn;
		inLen -= nSamplesIn;

		if( inLen > 0 ) {
			/* More iterations to do; copy last part of filtered signal to beginning of buffer */
			SKP_memcpy( buf, &buf[ nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( SKP_int32 ) );
		} else {
			break;
		}
	}

	/* Copy last part of filtered signal to the state for the next call */
	SKP_memcpy( S->sFIR, &buf[nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( SKP_int32 ) );
}
Example #9
0
/* Decodes signs of excitation */
void silk_decode_signs(
    ec_dec                      *psRangeDec,                        /* I/O  Compressor data structure                   */
    SKP_int                     pulses[],                           /* I/O  pulse signal                                */
    SKP_int                     length,                             /* I    length of input                             */
    const SKP_int               signalType,                         /* I    Signal type                                 */
    const SKP_int               quantOffsetType,                    /* I    Quantization offset type                    */
    const SKP_int               sum_pulses[ MAX_NB_SHELL_BLOCKS ]   /* I    Sum of absolute pulses per block            */
)
{
    SKP_int         i, j, p;
    SKP_uint8       icdf[ 2 ];
    SKP_int         *q_ptr;
    const SKP_uint8 *icdf_ptr;

    icdf[ 1 ] = 0;
    q_ptr = pulses;
    i = SKP_SMULBB( 6, SKP_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
    icdf_ptr = &silk_sign_iCDF[ i ];
    length = SKP_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
    for( i = 0; i < length; i++ ) {
        p = sum_pulses[ i ];
        if( p > 0 ) {
            icdf[ 0 ] = icdf_ptr[ SKP_min( p - 1, 5 ) ];
            for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
                if( q_ptr[ j ] > 0 ) {
                    /* attach sign */
#if 0
                    /* conditional implementation */
                    if( ec_dec_icdf( psRangeDec, icdf, 8 ) == 0 ) {
                        q_ptr[ j ] = -q_ptr[ j ];
                    }
#else
                    /* implementation with shift, subtraction, multiplication */
                    q_ptr[ j ] *= SKP_dec_map( ec_dec_icdf( psRangeDec, icdf, 8 ) );
#endif
                }
            }
        }
        q_ptr += SHELL_CODEC_FRAME_LENGTH;
    }
}
void SKP_Silk_find_pred_coefs_FIX(SKP_Silk_encoder_state_FIX * psEnc,	/* I/O  encoder state                               */
				  SKP_Silk_encoder_control_FIX * psEncCtrl,	/* I/O  encoder control                             */
				  const int16_t res_pitch[]	/* I    Residual from pitch analysis                */
    )
{
	int i;
	int32_t WLTP[NB_SUBFR * LTP_ORDER * LTP_ORDER];
	int32_t invGains_Q16[NB_SUBFR], local_gains_Qx[NB_SUBFR],
	    Wght_Q15[NB_SUBFR];
	int NLSF_Q15[MAX_LPC_ORDER];
	const int16_t *x_ptr;
	int16_t *x_pre_ptr,
	    LPC_in_pre[NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH];

	int32_t tmp, min_gain_Q16;
#if !VARQ
	int LZ;
#endif
	int LTP_corrs_rshift[NB_SUBFR];

	/* weighting for weighted least squares */
	min_gain_Q16 = int32_t_MAX >> 6;
	for (i = 0; i < NB_SUBFR; i++) {
		min_gain_Q16 = SKP_min(min_gain_Q16, psEncCtrl->Gains_Q16[i]);
	}
#if !VARQ
	LZ = SKP_Silk_CLZ32(min_gain_Q16) - 1;
	LZ = SKP_LIMIT(LZ, 0, 16);
	min_gain_Q16 = SKP_RSHIFT(min_gain_Q16, 2);	/* Ensure that maximum invGains_Q16 is within range of a 16 bit int */
#endif
	for (i = 0; i < NB_SUBFR; i++) {
		/* Divide to Q16 */
		assert(psEncCtrl->Gains_Q16[i] > 0);
#if VARQ
		/* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */
		invGains_Q16[i] =
		    SKP_DIV32_varQ(min_gain_Q16, psEncCtrl->Gains_Q16[i],
				   16 - 2);
#else
		invGains_Q16[i] =
		    SKP_DIV32(SKP_LSHIFT(min_gain_Q16, LZ),
			      SKP_RSHIFT(psEncCtrl->Gains_Q16[i], 16 - LZ));
#endif

		/* Ensure Wght_Q15 a minimum value 1 */
		invGains_Q16[i] = SKP_max(invGains_Q16[i], 363);

		/* Square the inverted gains */
		assert(invGains_Q16[i] == SKP_SAT16(invGains_Q16[i]));
		tmp = SKP_SMULWB(invGains_Q16[i], invGains_Q16[i]);
		Wght_Q15[i] = SKP_RSHIFT(tmp, 1);

		/* Invert the inverted and normalized gains */
		local_gains_Qx[i] =
		    SKP_DIV32((1 << (16 + Qx)), invGains_Q16[i]);
	}

	if (psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED) {
	/**********/
		/* VOICED */
	/**********/
		assert(psEnc->sCmn.frame_length -
			   psEnc->sCmn.predictLPCOrder >=
			   psEncCtrl->sCmn.pitchL[0] + LTP_ORDER / 2);

		/* LTP analysis */
		SKP_Silk_find_LTP_FIX(psEncCtrl->LTPCoef_Q14, WLTP,
				      &psEncCtrl->LTPredCodGain_Q7, res_pitch,
				      res_pitch +
				      SKP_RSHIFT(psEnc->sCmn.frame_length, 1),
				      psEncCtrl->sCmn.pitchL, Wght_Q15,
				      psEnc->sCmn.subfr_length,
				      psEnc->sCmn.frame_length,
				      LTP_corrs_rshift);

		/* Quantize LTP gain parameters */
		SKP_Silk_quant_LTP_gains_FIX(psEncCtrl->LTPCoef_Q14,
					     psEncCtrl->sCmn.LTPIndex,
					     &psEncCtrl->sCmn.PERIndex, WLTP,
					     psEnc->mu_LTP_Q8,
					     psEnc->sCmn.LTPQuantLowComplexity);

		/* Control LTP scaling */
		SKP_Silk_LTP_scale_ctrl_FIX(psEnc, psEncCtrl);

		/* Create LTP residual */
		SKP_Silk_LTP_analysis_filter_FIX(LPC_in_pre,
						 psEnc->x_buf +
						 psEnc->sCmn.frame_length -
						 psEnc->sCmn.predictLPCOrder,
						 psEncCtrl->LTPCoef_Q14,
						 psEncCtrl->sCmn.pitchL,
						 invGains_Q16, 16,
						 psEnc->sCmn.subfr_length,
						 psEnc->sCmn.predictLPCOrder);

	} else {
	/************/
		/* UNVOICED */
	/************/
		/* Create signal with prepended subframes, scaled by inverse gains */
		x_ptr =
		    psEnc->x_buf + psEnc->sCmn.frame_length -
		    psEnc->sCmn.predictLPCOrder;
		x_pre_ptr = LPC_in_pre;
		for (i = 0; i < NB_SUBFR; i++) {
			SKP_Silk_scale_copy_vector16(x_pre_ptr, x_ptr,
						     invGains_Q16[i],
						     psEnc->sCmn.subfr_length +
						     psEnc->sCmn.
						     predictLPCOrder);
			x_pre_ptr +=
			    psEnc->sCmn.subfr_length +
			    psEnc->sCmn.predictLPCOrder;
			x_ptr += psEnc->sCmn.subfr_length;
		}

		SKP_memset(psEncCtrl->LTPCoef_Q14, 0,
			   NB_SUBFR * LTP_ORDER * sizeof(int16_t));
		psEncCtrl->LTPredCodGain_Q7 = 0;
	}

	/* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */
	TIC(FIND_LPC)
	    SKP_Silk_find_LPC_FIX(NLSF_Q15, &psEncCtrl->sCmn.NLSFInterpCoef_Q2,
				  psEnc->sPred.prev_NLSFq_Q15,
				  psEnc->sCmn.useInterpolatedNLSFs * (1 -
								      psEnc->
								      sCmn.
								      first_frame_after_reset),
				  psEnc->sCmn.predictLPCOrder, LPC_in_pre,
				  psEnc->sCmn.subfr_length +
				  psEnc->sCmn.predictLPCOrder);
	TOC(FIND_LPC)

	    /* Quantize LSFs */
	    TIC(PROCESS_LSFS)
	    SKP_Silk_process_NLSFs_FIX(psEnc, psEncCtrl, NLSF_Q15);
	TOC(PROCESS_LSFS)

	    /* Calculate residual energy using quantized LPC coefficients */
	    SKP_Silk_residual_energy_FIX(psEncCtrl->ResNrg, psEncCtrl->ResNrgQ,
					 LPC_in_pre, (const int16_t(*)[])psEncCtrl->PredCoef_Q12,
					 local_gains_Qx, Qx,
					 psEnc->sCmn.subfr_length,
					 psEnc->sCmn.predictLPCOrder);

	/* Copy to prediction struct for use in next frame for fluctuation reduction */
	SKP_memcpy(psEnc->sPred.prev_NLSFq_Q15, NLSF_Q15,
		   psEnc->sCmn.predictLPCOrder * sizeof(int));

}
void SKP_Silk_find_pred_coefs_FIX(
    SKP_Silk_encoder_state_FIX      *psEnc,         /* I/O  encoder state                               */
    SKP_Silk_encoder_control_FIX    *psEncCtrl,     /* I/O  encoder control                             */
    const SKP_int16                 res_pitch[],    /* I    Residual from pitch analysis                */
    const SKP_int16                 x[]             /* I    Speech signal                               */
)
{
    SKP_int         i;
    SKP_int32       WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
    SKP_int32       invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ];
    SKP_int16       NLSF_Q15[ MAX_LPC_ORDER ];
    const SKP_int16 *x_ptr;
    SKP_int16       *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ];
    SKP_int32       tmp, min_gain_Q16;
    SKP_int         LTP_corrs_rshift[ MAX_NB_SUBFR ];

    /* weighting for weighted least squares */
    min_gain_Q16 = SKP_int32_MAX >> 6;
    for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
        min_gain_Q16 = SKP_min( min_gain_Q16, psEncCtrl->Gains_Q16[ i ] );
    }
    for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
        /* Divide to Q16 */
        SKP_assert( psEncCtrl->Gains_Q16[ i ] > 0 );
        /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */
        invGains_Q16[ i ] = SKP_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 );

        /* Ensure Wght_Q15 a minimum value 1 */
        invGains_Q16[ i ] = SKP_max( invGains_Q16[ i ], 363 ); 
        
        /* Square the inverted gains */
        SKP_assert( invGains_Q16[ i ] == SKP_SAT16( invGains_Q16[ i ] ) );
        tmp = SKP_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] );
        Wght_Q15[ i ] = SKP_RSHIFT( tmp, 1 );

        /* Invert the inverted and normalized gains */
        local_gains[ i ] = SKP_DIV32( ( 1 << 16 ), invGains_Q16[ i ] );
    }

    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
        /**********/
        /* VOICED */
        /**********/
        SKP_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );

        /* LTP analysis */
        SKP_Silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7, 
            res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length, 
            psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift );

        /* Quantize LTP gain parameters */
        SKP_Silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, 
            WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr);

        /* Control LTP scaling */
        SKP_Silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl );

        /* Create LTP residual */
        SKP_Silk_LTP_analysis_filter_FIX( LPC_in_pre, psEnc->x_buf + psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder, 
            psEncCtrl->LTPCoef_Q14, psEncCtrl->pitchL, invGains_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );

    } else {
        /************/
        /* UNVOICED */
        /************/
        /* Create signal with prepended subframes, scaled by inverse gains */
        x_ptr     = x - psEnc->sCmn.predictLPCOrder;
        x_pre_ptr = LPC_in_pre;
        for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
            SKP_Silk_scale_copy_vector16( x_pre_ptr, x_ptr, invGains_Q16[ i ], 
                psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder );
            x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder;
            x_ptr     += psEnc->sCmn.subfr_length;
        }

        SKP_memset( psEncCtrl->LTPCoef_Q14, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( SKP_int16 ) );
        psEncCtrl->LTPredCodGain_Q7 = 0;
    }

    /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */
    TIC(FIND_LPC)
    SKP_Silk_find_LPC_FIX( NLSF_Q15, &psEnc->sCmn.indices.NLSFInterpCoef_Q2, psEnc->sCmn.prev_NLSFq_Q15, 
        psEnc->sCmn.useInterpolatedNLSFs, psEnc->sCmn.first_frame_after_reset, psEnc->sCmn.predictLPCOrder, 
        LPC_in_pre, psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder, psEnc->sCmn.nb_subfr );
    TOC(FIND_LPC)

    /* Quantize LSFs */
    TIC(PROCESS_LSFS)
    SKP_Silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 );
    TOC(PROCESS_LSFS)

    /* Calculate residual energy using quantized LPC coefficients */
    SKP_Silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains,
        psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );

    /* Copy to prediction struct for use in next frame for fluctuation reduction */
    SKP_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
}
/* Control encoder SNR */
SKP_int SKP_Silk_control_encoder_FIX( 
    SKP_Silk_encoder_state_FIX  *psEnc,             /* I/O  Pointer to Silk encoder state                   */
    const SKP_int               API_fs_kHz,         /* I    External (API) sampling rate (kHz)              */
    const SKP_int               PacketSize_ms,      /* I    Packet length (ms)                              */
    SKP_int32                   TargetRate_bps,     /* I    Target max bitrate (bps) (used if SNR_dB == 0)  */
    const SKP_int               PacketLoss_perc,    /* I    Packet loss rate (in percent)                   */
    const SKP_int               INBandFec_enabled,  /* I    Enable (1) / disable (0) inband FEC             */
    const SKP_int               DTX_enabled,        /* I    Enable / disable DTX                            */
    const SKP_int               InputFramesize_ms,  /* I    Inputframe in ms                                */
    const SKP_int               Complexity          /* I    Complexity (0->low; 1->medium; 2->high)         */
)
{
    SKP_int32 LBRRRate_thres_bps;
    SKP_int   k, fs_kHz, ret = 0;
    SKP_int32 frac_Q6;
    const SKP_int32 *rateTable;

    /* State machine for the SWB/WB switching */
    fs_kHz = psEnc->sCmn.fs_kHz;
    
    /* Only switch during low speech activity, when no frames are sitting in the payload buffer */
    if( API_fs_kHz == 8 || fs_kHz == 0 || API_fs_kHz < fs_kHz ) {
        // Switching is not possible, encoder just initialized, or internal mode higher than external
        fs_kHz = API_fs_kHz;
    } else {

        /* Resample all valid data in x_buf. Resampling the last part gets rid of a click, 5ms after switching  */
        /* this is because the same state is used when downsampling in API.c and is then up to date             */
        /* the click immidiatly after switching is most of the time still there                                 */

        if( psEnc->sCmn.fs_kHz == 24 ) {
            /* Accumulate the difference between the target rate and limit */
            if( psEnc->sCmn.fs_kHz_changed == 0 ) {
                psEnc->sCmn.bitrateDiff += SKP_MUL( InputFramesize_ms, TargetRate_bps - SWB2WB_BITRATE_BPS_INITIAL );
            } else {
                psEnc->sCmn.bitrateDiff += SKP_MUL( InputFramesize_ms, TargetRate_bps - SWB2WB_BITRATE_BPS );
            }
            psEnc->sCmn.bitrateDiff = SKP_min( psEnc->sCmn.bitrateDiff, 0 );

            /* Check if we should switch from 24 to 16 kHz */
#if SWITCH_TRANSITION_FILTERING
            if( ( psEnc->sCmn.sLP.transition_frame_no == 0 ) && /* Transition phase not active */
                ( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD || psEnc->sCmn.sSWBdetect.WB_detected == 1 ) &&
                ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) {
                psEnc->sCmn.sLP.transition_frame_no = 1; /* Begin transition phase */
                psEnc->sCmn.sLP.mode = 0; /* Switch down */
            }

            if( ( psEnc->sCmn.sLP.transition_frame_no >= TRANSITION_FRAMES_DOWN ) && ( psEnc->sCmn.sLP.mode == 0 ) && /* Transition phase complete, ready to switch */
#else
            if( ( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD || psEnc->sCmn.sSWBdetect.WB_detected == 1 ) &&
#endif
                ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) {

                    SKP_int16 x_buf[    2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; 
                    SKP_int16 x_bufout[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];
                    
                    psEnc->sCmn.bitrateDiff = 0;
                    fs_kHz = 16;

                    SKP_memcpy( x_buf, psEnc->x_buf, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) );

                    SKP_memset( psEnc->sCmn.resample24To16state, 0, sizeof( psEnc->sCmn.resample24To16state ) );
                    
#if LOW_COMPLEXITY_ONLY
                    {
                        SKP_int16 scratch[ ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) + SigProc_Resample_2_3_coarse_NUM_FIR_COEFS - 1 ];
                        SKP_Silk_resample_2_3_coarse( &x_bufout[ 0 ], psEnc->sCmn.resample24To16state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape, (SKP_int16*)scratch );
                    }
#else
                    SKP_Silk_resample_2_3( &x_bufout[ 0 ], psEnc->sCmn.resample24To16state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape );
#endif

                    /* set the first frame to zero, no performance difference was noticed though */
                    SKP_memset( x_bufout, 0, 320 * sizeof( SKP_int16 ) );
                    SKP_memcpy( psEnc->x_buf, x_bufout, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) );

#if SWITCH_TRANSITION_FILTERING
                    psEnc->sCmn.sLP.transition_frame_no = 0; /* Transition phase complete */
#endif
            }
        } else if( psEnc->sCmn.fs_kHz == 16 ) {

            /* Check if we should switch from 16 to 24 kHz */
#if SWITCH_TRANSITION_FILTERING
            if( ( psEnc->sCmn.sLP.transition_frame_no == 0 ) && /* No transition phase running, ready to switch */
#else
            if(
#endif
                ( API_fs_kHz > psEnc->sCmn.fs_kHz && TargetRate_bps >= WB2SWB_BITRATE_BPS && psEnc->sCmn.sSWBdetect.WB_detected == 0 ) && 
                ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) {

                SKP_int16 x_buf[          2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; 
                SKP_int16 x_bufout[ 3 * ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) / 2 ]; 
                SKP_int32 resample16To24state[ 11 ];

                psEnc->sCmn.bitrateDiff = 0;
                fs_kHz = 24;
                
                SKP_memcpy( x_buf, psEnc->x_buf, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) );

                SKP_memset( resample16To24state, 0, sizeof(resample16To24state) );
                
                SKP_Silk_resample_3_2( &x_bufout[ 0 ], resample16To24state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape );

                /* set the first frame to zero, no performance difference was noticed though */
                SKP_memset( x_bufout, 0, 480 * sizeof( SKP_int16 ) );
                SKP_memcpy( psEnc->x_buf, x_bufout, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) );
#if SWITCH_TRANSITION_FILTERING
                psEnc->sCmn.sLP.mode = 1; /* Switch up */
#endif
            } else { 
                /* accumulate the difference between the target rate and limit */
                psEnc->sCmn.bitrateDiff += SKP_MUL( InputFramesize_ms, TargetRate_bps - WB2MB_BITRATE_BPS );
                psEnc->sCmn.bitrateDiff = SKP_min( psEnc->sCmn.bitrateDiff, 0 );

                /* Check if we should switch from 16 to 12 kHz */
#if SWITCH_TRANSITION_FILTERING
                if( ( psEnc->sCmn.sLP.transition_frame_no == 0 ) && /* Transition phase not active */
                    ( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD ) &&
                    ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) {
                    psEnc->sCmn.sLP.transition_frame_no = 1; /* Begin transition phase */
                    psEnc->sCmn.sLP.mode = 0; /* Switch down */
                }

                if( ( psEnc->sCmn.sLP.transition_frame_no >= TRANSITION_FRAMES_DOWN ) && ( psEnc->sCmn.sLP.mode == 0 ) && /* Transition phase complete, ready to switch */
#else
                if( ( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD ) &&
#endif
                    ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) {

                    SKP_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; 

                    SKP_memcpy( x_buf, psEnc->x_buf, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) );
    
                    psEnc->sCmn.bitrateDiff = 0;
                    fs_kHz = 12;
                    
                    if( API_fs_kHz == 24 ) {

                        /* Intermediate upsampling of x_bufFIX from 16 to 24 kHz */
                        SKP_int16 x_buf24[ 3 * ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) / 2 ]; 
                        SKP_int32 scratch[    3 * ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) ];
                        SKP_int32 resample16To24state[ 11 ];

                        SKP_memset( resample16To24state, 0, sizeof( resample16To24state ) );
                        SKP_Silk_resample_3_2( &x_buf24[ 0 ], resample16To24state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape );

                        /* Update the state of the resampler used in API.c, from 24 to 12 kHz */
                        SKP_memset( psEnc->sCmn.resample24To12state, 0, sizeof( psEnc->sCmn.resample24To12state ) );
                        SKP_Silk_resample_1_2_coarse( &x_buf24[ 0 ], psEnc->sCmn.resample24To12state, &x_buf[ 0 ], scratch, SKP_RSHIFT( SKP_SMULBB( 3, SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape ), 2 ) );

                        /* set the first frame to zero, no performance difference was noticed though */
                        SKP_memset( x_buf, 0, 240 * sizeof( SKP_int16 ) );
                        SKP_memcpy( psEnc->x_buf, x_buf, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) );

                    } else if( API_fs_kHz == 16 ) {
                        SKP_int16 x_bufout[ 3 * ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) / 4 ]; 
                        SKP_memset( psEnc->sCmn.resample16To12state, 0, sizeof( psEnc->sCmn.resample16To12state ) );
                        
                        SKP_Silk_resample_3_4( &x_bufout[ 0 ], psEnc->sCmn.resample16To12state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape );
                    
                        /* set the first frame to zero, no performance difference was noticed though */
                        SKP_memset( x_bufout, 0, 240 * sizeof( SKP_int16 ) );
                        SKP_memcpy( psEnc->x_buf, x_bufout, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) );
                    }
#if SWITCH_TRANSITION_FILTERING
                    psEnc->sCmn.sLP.transition_frame_no = 0; /* Transition phase complete */
#endif
                }
            }
        } else if( psEnc->sCmn.fs_kHz == 12 ) {
Example #13
0
SKP_int SKP_Silk_SDK_Encode( 
    void                                *encState,      /* I/O: State                                           */
    SKP_Silk_EncodeControlStruct        *encControl,    /* I:   Control structure                               */
    const SKP_int16                     *samplesIn,     /* I:   Speech sample input vector                      */
    SKP_int                             nSamplesIn,     /* I:   Number of samples in input vector               */
    ec_enc                              *psRangeEnc,    /* I/O  Compressor data structure                       */
    SKP_int32                           *nBytesOut,     /* I/O: Number of bytes in payload (input: Max bytes)   */
    const SKP_int                       prefillFlag     /* I:   Flag to indicate prefilling buffers no coding   */
)
{
    SKP_int   tmp_payloadSize_ms, tmp_complexity, ret = 0;
    SKP_int   nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0;
    SKP_Silk_encoder_state_Fxx *psEnc = ( SKP_Silk_encoder_state_Fxx* )encState;

    ret = process_enc_control_struct( psEnc, encControl );

    nBlocksOf10ms = SKP_DIV32( 100 * nSamplesIn, psEnc->sCmn.API_fs_Hz );
    if( prefillFlag ) {
        /* Only accept input length of 10 ms */
        if( nBlocksOf10ms != 1 ) {
            ret = SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
            SKP_assert( 0 );
            return( ret );
        }
        /* Reset Encoder */
        if( ret = SKP_Silk_init_encoder_Fxx( psEnc ) ) {
            SKP_assert( 0 );
        }
        tmp_payloadSize_ms = encControl->payloadSize_ms;
        encControl->payloadSize_ms = 10;
        tmp_complexity = encControl->complexity;
        encControl->complexity = 0;
        ret = process_enc_control_struct( psEnc, encControl );
        psEnc->sCmn.prefillFlag = 1;
    } else {
        /* Only accept input lengths that are a multiple of 10 ms */
        if( nBlocksOf10ms * psEnc->sCmn.API_fs_Hz != 100 * nSamplesIn || nSamplesIn < 0 ) {
            ret = SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
            SKP_assert( 0 );
            return( ret );
        }
        /* Make sure no more than one packet can be produced */
        if( 1000 * (SKP_int32)nSamplesIn > psEnc->sCmn.PacketSize_ms * psEnc->sCmn.API_fs_Hz ) {
            ret = SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
            SKP_assert( 0 );
            return( ret );
        }
    }

    /* Input buffering/resampling and encoding */
    while( 1 ) {
        nSamplesToBuffer = psEnc->sCmn.frame_length - psEnc->sCmn.inputBufIx;
        if( psEnc->sCmn.API_fs_Hz == SKP_SMULBB( 1000, psEnc->sCmn.fs_kHz ) ) { 
            nSamplesToBuffer  = SKP_min_int( nSamplesToBuffer, nSamplesIn );
            nSamplesFromInput = nSamplesToBuffer;
            /* Copy to buffer */
            SKP_memcpy( &psEnc->sCmn.inputBuf[ psEnc->sCmn.inputBufIx ], samplesIn, nSamplesFromInput * sizeof( SKP_int16 ) );
        } else {  
            nSamplesToBuffer  = SKP_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->sCmn.fs_kHz );
            nSamplesFromInput = SKP_DIV32_16( nSamplesToBuffer * psEnc->sCmn.API_fs_Hz, psEnc->sCmn.fs_kHz * 1000 );
            /* Resample and write to buffer */
            ret += SKP_Silk_resampler( &psEnc->sCmn.resampler_state, &psEnc->sCmn.inputBuf[ psEnc->sCmn.inputBufIx ], samplesIn, nSamplesFromInput );
        } 
        samplesIn              += nSamplesFromInput;
        nSamplesIn             -= nSamplesFromInput;
        psEnc->sCmn.inputBufIx += nSamplesToBuffer;

        /* Silk encoder */
        if( psEnc->sCmn.inputBufIx >= psEnc->sCmn.frame_length ) {
            SKP_assert( psEnc->sCmn.inputBufIx == psEnc->sCmn.frame_length );

            /* Enough data in input buffer, so encode */
            if( ( ret = SKP_Silk_encode_frame_Fxx( psEnc, nBytesOut, psRangeEnc ) ) != 0 ) {
                SKP_assert( 0 );
            }
            psEnc->sCmn.inputBufIx = 0;
            psEnc->sCmn.controlled_since_last_payload = 0;

            if( nSamplesIn == 0 ) {
                break;
            }
        } else {
            break;
        }
    }

    if( prefillFlag ) {
        encControl->payloadSize_ms = tmp_payloadSize_ms;
        encControl->complexity = tmp_complexity;
        ret = process_enc_control_struct( psEnc, encControl );
        psEnc->sCmn.prefillFlag = 0;
    }

    return ret;
}
/* Control internal sampling rate */
SKP_int SKP_Silk_control_audio_bandwidth(
    SKP_Silk_encoder_state      *psEncC,            /* I/O  Pointer to Silk encoder state               */
    const SKP_int32             TargetRate_bps      /* I    Target max bitrate (bps)                    */
)
{
    SKP_int fs_kHz;

    fs_kHz = psEncC->fs_kHz;
    if( fs_kHz == 0 ) {
        /* Encoder has just been initialized */
        if( TargetRate_bps >= SWB2WB_BITRATE_BPS ) {
            fs_kHz = 24;
        } else if( TargetRate_bps >= WB2MB_BITRATE_BPS ) {
            fs_kHz = 16;
        } else if( TargetRate_bps >= MB2NB_BITRATE_BPS ) {
            fs_kHz = 12;
        } else {
            fs_kHz = 8;
        }
        /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */
        fs_kHz = SKP_min( fs_kHz, SKP_DIV32_16( psEncC->API_fs_Hz, 1000 ) );
        fs_kHz = SKP_min( fs_kHz, psEncC->maxInternal_fs_kHz );
    } else if( SKP_SMULBB( fs_kHz, 1000 ) > psEncC->API_fs_Hz || fs_kHz > psEncC->maxInternal_fs_kHz ) {
        /* Make sure internal rate is not higher than external rate or maximum allowed */
        fs_kHz = SKP_DIV32_16( psEncC->API_fs_Hz, 1000 );
        fs_kHz = SKP_min( fs_kHz, psEncC->maxInternal_fs_kHz );
    } else {
        /* State machine for the internal sampling rate switching */
        if( psEncC->API_fs_Hz > 8000 ) {
            /* Accumulate the difference between the target rate and limit for switching down */
            psEncC->bitrateDiff += SKP_MUL( psEncC->PacketSize_ms, psEncC->TargetRate_bps - psEncC->bitrate_threshold_down );
            psEncC->bitrateDiff  = SKP_min( psEncC->bitrateDiff, 0 );

            if( psEncC->vadFlag == NO_VOICE_ACTIVITY ) { /* Low speech activity */
                /* Check if we should switch down */
#if SWITCH_TRANSITION_FILTERING 
                if( ( psEncC->sLP.transition_frame_no == 0 ) &&                         /* Transition phase not active */
                    ( psEncC->bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD ||              /* Bitrate threshold is met */
                    ( psEncC->sSWBdetect.WB_detected * psEncC->fs_kHz == 24 ) ) ) {     /* Forced down-switching due to WB input */
                        psEncC->sLP.transition_frame_no = 1;                            /* Begin transition phase */
                        psEncC->sLP.mode                = 0;                            /* Switch down */
                } else if( 
                    ( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES_DOWN ) &&    /* Transition phase complete */
                    ( psEncC->sLP.mode == 0 ) ) {                                       /* Ready to switch down */
                        psEncC->sLP.transition_frame_no = 0;                            /* Ready for new transition phase */
#else
                if( psEncC->bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD ) {               /* Bitrate threshold is met */ 
#endif            
                    psEncC->bitrateDiff = 0;

                    /* Switch to a lower sample frequency */
                    if( psEncC->fs_kHz == 24 ) {
                        fs_kHz = 16;
                    } else if( psEncC->fs_kHz == 16 ) {
                        fs_kHz = 12;
                    } else {
                        SKP_assert( psEncC->fs_kHz == 12 );
                        fs_kHz = 8;
                    }
                }

                /* Check if we should switch up */
                if( ( ( psEncC->fs_kHz * 1000 < psEncC->API_fs_Hz ) &&
                    ( psEncC->TargetRate_bps >= psEncC->bitrate_threshold_up ) && 
                    ( psEncC->sSWBdetect.WB_detected * psEncC->fs_kHz < 16 ) ) && 
                    ( ( ( psEncC->fs_kHz == 16 ) && ( psEncC->maxInternal_fs_kHz >= 24 ) ) || 
                    (   ( psEncC->fs_kHz == 12 ) && ( psEncC->maxInternal_fs_kHz >= 16 ) ) ||
                    (   ( psEncC->fs_kHz ==  8 ) && ( psEncC->maxInternal_fs_kHz >= 12 ) ) ) 
#if SWITCH_TRANSITION_FILTERING
                    && ( psEncC->sLP.transition_frame_no == 0 ) ) { /* No transition phase running, ready to switch */
                        psEncC->sLP.mode = 1; /* Switch up */
#else
                    ) {
#endif
                    psEncC->bitrateDiff = 0;

                    /* Switch to a higher sample frequency */
                    if( psEncC->fs_kHz == 8 ) {
                        fs_kHz = 12;
                    } else if( psEncC->fs_kHz == 12 ) {
                        fs_kHz = 16;
                    } else {
                        SKP_assert( psEncC->fs_kHz == 16 );
                        fs_kHz = 24;
                    }
                }
            }
        }
/* Control encoder SNR */
SKP_int SKP_Silk_control_encoder_FIX( 
    SKP_Silk_encoder_state_FIX  *psEnc,             /* I/O  Pointer to Silk encoder state                   */
    const SKP_int32             API_fs_Hz,          /* I    External (API) sampling rate (Hz)               */
    const SKP_int               max_internal_fs_kHz,/* I    Maximum internal sampling rate (kHz)            */
    const SKP_int               PacketSize_ms,      /* I    Packet length (ms)                              */
    SKP_int32                   TargetRate_bps,     /* I    Target max bitrate (bps) (used if SNR_dB == 0)  */
    const SKP_int               PacketLoss_perc,    /* I    Packet loss rate (in percent)                   */
    const SKP_int               INBandFEC_enabled,  /* I    Enable (1) / disable (0) inband FEC             */
    const SKP_int               DTX_enabled,        /* I    Enable / disable DTX                            */
    const SKP_int               InputFramesize_ms,  /* I    Inputframe in ms                                */
    const SKP_int               Complexity          /* I    Complexity (0->low; 1->medium; 2->high)         */
)
{
    SKP_int32 LBRRRate_thres_bps;
    SKP_int   k, fs_kHz, ret = 0;
    SKP_int32 frac_Q6;
    const SKP_int32 *rateTable;

    /* State machine for the SWB/WB switching */
    fs_kHz = psEnc->sCmn.fs_kHz;
    
    /* Only switch during low speech activity, when no frames are sitting in the payload buffer */
    if( API_fs_Hz == 8000 || fs_kHz == 0 || API_fs_Hz < SKP_SMULBB( fs_kHz, 1000 ) || fs_kHz > max_internal_fs_kHz ) {
        /* Switching is not possible, encoder just initialized, internal mode higher than external, */
        /* or internal mode higher than maximum allowed internal mode                               */
        fs_kHz = SKP_min( SKP_DIV32_16( API_fs_Hz, 1000 ), max_internal_fs_kHz );
    } else {
        /* Accumulate the difference between the target rate and limit for switching down */
        psEnc->sCmn.bitrateDiff += SKP_MUL( InputFramesize_ms, TargetRate_bps - psEnc->sCmn.bitrate_threshold_down );
        psEnc->sCmn.bitrateDiff  = SKP_min( psEnc->sCmn.bitrateDiff, 0 );

        if( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) { /* Low speech activity and payload buffer empty */
            /* Check if we should switch down */
#if SWITCH_TRANSITION_FILTERING 
            if( ( psEnc->sCmn.sLP.transition_frame_no == 0 ) &&                         /* Transition phase not active */
                ( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD ||              /* Bitrate threshold is met */
                ( psEnc->sCmn.sSWBdetect.WB_detected * psEnc->sCmn.fs_kHz == 24 ) ) ) { /* Forced down-switching due to WB input */
                psEnc->sCmn.sLP.transition_frame_no = 1;                                /* Begin transition phase */
                psEnc->sCmn.sLP.mode                = 0;                                /* Switch down */
            } else if( 
                ( psEnc->sCmn.sLP.transition_frame_no >= TRANSITION_FRAMES_DOWN ) &&    /* Transition phase complete */
                ( psEnc->sCmn.sLP.mode == 0 ) ) {                                       /* Ready to switch down */
                psEnc->sCmn.sLP.transition_frame_no = 0;                                /* Ready for new transition phase */
#else
            if( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD ) {               /* Bitrate threshold is met */ 
#endif            
                psEnc->sCmn.bitrateDiff = 0;

                /* Switch to a lower sample frequency */
                if( psEnc->sCmn.fs_kHz == 24 ) {
                    fs_kHz = 16;
                } else if( psEnc->sCmn.fs_kHz == 16 ) {
                    fs_kHz = 12;
                } else {
                    SKP_assert( psEnc->sCmn.fs_kHz == 12 );
                    fs_kHz = 8;
                }
            }

            /* Check if we should switch up */
            if( ( ( SKP_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) < API_fs_Hz ) &&
                ( TargetRate_bps >= psEnc->sCmn.bitrate_threshold_up ) && 
                ( psEnc->sCmn.sSWBdetect.WB_detected * psEnc->sCmn.fs_kHz != 16 ) ) && 
                ( ( psEnc->sCmn.fs_kHz == 16 ) && ( max_internal_fs_kHz >= 24 ) || 
                  ( psEnc->sCmn.fs_kHz == 12 ) && ( max_internal_fs_kHz >= 16 ) ||
                  ( psEnc->sCmn.fs_kHz ==  8 ) && ( max_internal_fs_kHz >= 12 ) ) 
#if SWITCH_TRANSITION_FILTERING
                  && ( psEnc->sCmn.sLP.transition_frame_no == 0 ) ) { /* No transition phase running, ready to switch */
                    psEnc->sCmn.sLP.mode = 1; /* Switch up */
#else
                ) {
#endif
                psEnc->sCmn.bitrateDiff = 0;

                /* Switch to a higher sample frequency */
                if( psEnc->sCmn.fs_kHz == 8 ) {
                    fs_kHz = 12;
                } else if( psEnc->sCmn.fs_kHz == 12 ) {
                    fs_kHz = 16;
                } else {
                    SKP_assert( psEnc->sCmn.fs_kHz == 16 );
                    fs_kHz = 24;
                } 
            }
        }
    }
/* Compute reflection coefficients from input signal */
void SKP_Silk_burg_modified(
    SKP_int32       *res_nrg,           /* O    residual energy                                                 */
    SKP_int         *res_nrg_Q,         /* O    residual energy Q value                                         */
    SKP_int32       A_Q16[],            /* O    prediction coefficients (length order)                          */
    const SKP_int16 x[],                /* I    input signal, length: nb_subfr * ( D + subfr_length )           */
    const SKP_int   subfr_length,       /* I    input signal subframe length (including D preceeding samples)   */
    const SKP_int   nb_subfr,           /* I    number of subframes stacked in x                                */
    const SKP_int32 WhiteNoiseFrac_Q32, /* I    fraction added to zero-lag autocorrelation                      */
    const SKP_int   D                   /* I    order                                                           */
)
{
    SKP_int         k, n, s, lz, rshifts, rshifts_extra;
    SKP_int32       C0, num, nrg, rc_Q31, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2;
    const SKP_int16 *x_ptr;

    SKP_int32       C_first_row[ SKP_Silk_MAX_ORDER_LPC ];
    SKP_int32       C_last_row[  SKP_Silk_MAX_ORDER_LPC ];
    SKP_int32       Af_QA[       SKP_Silk_MAX_ORDER_LPC ];

    SKP_int32       CAf[ SKP_Silk_MAX_ORDER_LPC + 1 ];
    SKP_int32       CAb[ SKP_Silk_MAX_ORDER_LPC + 1 ];

    SKP_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
    SKP_assert( nb_subfr <= MAX_NB_SUBFR );


    /* Compute autocorrelations, added over subframes */
    SKP_Silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length );
    if( rshifts > MAX_RSHIFTS ) {
        C0 = SKP_LSHIFT32( C0, rshifts - MAX_RSHIFTS );
        SKP_assert( C0 > 0 );
        rshifts = MAX_RSHIFTS;
    } else {
        lz = SKP_Silk_CLZ32( C0 ) - 1;
        rshifts_extra = N_BITS_HEAD_ROOM - lz;
        if( rshifts_extra > 0 ) {
            rshifts_extra = SKP_min( rshifts_extra, MAX_RSHIFTS - rshifts );
            C0 = SKP_RSHIFT32( C0, rshifts_extra );
        } else {
            rshifts_extra = SKP_max( rshifts_extra, MIN_RSHIFTS - rshifts );
            C0 = SKP_LSHIFT32( C0, -rshifts_extra );
        }
        rshifts += rshifts_extra;
    }
    SKP_memset( C_first_row, 0, SKP_Silk_MAX_ORDER_LPC * sizeof( SKP_int32 ) );
    if( rshifts > 0 ) {
        for( s = 0; s < nb_subfr; s++ ) {
            x_ptr = x + s * subfr_length;
            for( n = 1; n < D + 1; n++ ) {
                C_first_row[ n - 1 ] += (SKP_int32)SKP_RSHIFT64( 
                    SKP_Silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n ), rshifts );
            }
        }
    } else {
        for( s = 0; s < nb_subfr; s++ ) {
            x_ptr = x + s * subfr_length;
            for( n = 1; n < D + 1; n++ ) {
                C_first_row[ n - 1 ] += SKP_LSHIFT32( 
                    SKP_Silk_inner_prod_aligned( x_ptr, x_ptr + n, subfr_length - n ), -rshifts );
            }
        }
    }
    SKP_memcpy( C_last_row, C_first_row, SKP_Silk_MAX_ORDER_LPC * sizeof( SKP_int32 ) );
    
    /* Initialize */
    CAb[ 0 ] = CAf[ 0 ] = C0 + SKP_SMMUL( WhiteNoiseFrac_Q32, C0 ) + 1;         // Q(-rshifts)

    for( n = 0; n < D; n++ ) {
        /* Update first row of correlation matrix (without first element) */
        /* Update last row of correlation matrix (without last element, stored in reversed order) */
        /* Update C * Af */
        /* Update C * flipud(Af) (stored in reversed order) */
        if( rshifts > -2 ) {
            for( s = 0; s < nb_subfr; s++ ) {
                x_ptr = x + s * subfr_length;
                x1  = -SKP_LSHIFT32( (SKP_int32)x_ptr[ n ],                    16 - rshifts );      // Q(16-rshifts)
                x2  = -SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts );      // Q(16-rshifts)
                tmp1 = SKP_LSHIFT32( (SKP_int32)x_ptr[ n ],                    QA - 16 );           // Q(QA-16)
                tmp2 = SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 );           // Q(QA-16)
                for( k = 0; k < n; k++ ) {
                    C_first_row[ k ] = SKP_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ]            ); // Q( -rshifts )
                    C_last_row[ k ]  = SKP_SMLAWB( C_last_row[ k ],  x2, x_ptr[ subfr_length - n + k ] ); // Q( -rshifts )
                    Atmp_QA = Af_QA[ k ];
                    tmp1 = SKP_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ]            );              // Q(QA-16)
                    tmp2 = SKP_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] );              // Q(QA-16)
                }
                tmp1 = SKP_LSHIFT32( -tmp1, 32 - QA - rshifts );                                    // Q(16-rshifts)
                tmp2 = SKP_LSHIFT32( -tmp2, 32 - QA - rshifts );                                    // Q(16-rshifts)
                for( k = 0; k <= n; k++ ) {
                    CAf[ k ] = SKP_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ]                    );     // Q( -rshift )
                    CAb[ k ] = SKP_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] );     // Q( -rshift )
                }
            }
        } else {
            for( s = 0; s < nb_subfr; s++ ) {
                x_ptr = x + s * subfr_length;
                x1  = -SKP_LSHIFT32( (SKP_int32)x_ptr[ n ],                    -rshifts );          // Q( -rshifts )
                x2  = -SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n - 1 ], -rshifts );          // Q( -rshifts )
                tmp1 = SKP_LSHIFT32( (SKP_int32)x_ptr[ n ],                    17 );                // Q17
                tmp2 = SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n - 1 ], 17 );                // Q17
                for( k = 0; k < n; k++ ) {
                    C_first_row[ k ] = SKP_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ]            ); // Q( -rshifts )
                    C_last_row[ k ]  = SKP_MLA( C_last_row[ k ],  x2, x_ptr[ subfr_length - n + k ] ); // Q( -rshifts )
                    Atmp1 = SKP_RSHIFT_ROUND( Af_QA[ k ], QA - 17 );                                // Q17
                    tmp1 = SKP_MLA( tmp1, x_ptr[ n - k - 1 ],            Atmp1 );                   // Q17
                    tmp2 = SKP_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 );                   // Q17
                }
                tmp1 = -tmp1;                                                                       // Q17
                tmp2 = -tmp2;                                                                       // Q17
                for( k = 0; k <= n; k++ ) {
                    CAf[ k ] = SKP_SMLAWW( CAf[ k ], tmp1, 
                        SKP_LSHIFT32( (SKP_int32)x_ptr[ n - k ], -rshifts - 1 ) );                  // Q( -rshift )
                    CAb[ k ] = SKP_SMLAWW( CAb[ k ], tmp2, 
                        SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) );// Q( -rshift )
                }
            }
        }

        /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */
        tmp1 = C_first_row[ n ];                                                            // Q( -rshifts )
        tmp2 = C_last_row[ n ];                                                             // Q( -rshifts )
        num  = 0;                                                                           // Q( -rshifts )
        nrg  = SKP_ADD32( CAb[ 0 ], CAf[ 0 ] );                                             // Q( 1-rshifts )
        for( k = 0; k < n; k++ ) {
            Atmp_QA = Af_QA[ k ];
            lz = SKP_Silk_CLZ32( SKP_abs( Atmp_QA ) ) - 1;
            lz = SKP_min( 32 - QA, lz );
            Atmp1 = SKP_LSHIFT32( Atmp_QA, lz );                                            // Q( QA + lz )

            tmp1 = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( C_last_row[  n - k - 1 ], Atmp1 ), 32 - QA - lz );    // Q( -rshifts )
            tmp2 = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz );    // Q( -rshifts )
            num  = SKP_ADD_LSHIFT32( num,  SKP_SMMUL( CAb[ n - k ],             Atmp1 ), 32 - QA - lz );    // Q( -rshifts )
            nrg  = SKP_ADD_LSHIFT32( nrg,  SKP_SMMUL( SKP_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), 
                                                                                Atmp1 ), 32 - QA - lz );    // Q( 1-rshifts )
        }
        CAf[ n + 1 ] = tmp1;                                                                // Q( -rshifts )
        CAb[ n + 1 ] = tmp2;                                                                // Q( -rshifts )
        num = SKP_ADD32( num, tmp2 );                                                       // Q( -rshifts )
        num = SKP_LSHIFT32( -num, 1 );                                                      // Q( 1-rshifts )

        /* Calculate the next order reflection (parcor) coefficient */
        if( SKP_abs( num ) < nrg ) {
            rc_Q31 = SKP_DIV32_varQ( num, nrg, 31 );
        } else {
            /* Negative energy or ratio too high; set remaining coefficients to zero and exit loop */
            SKP_memset( &Af_QA[ n ], 0, ( D - n ) * sizeof( SKP_int32 ) );
            SKP_assert( 0 );
            break;
        }

        /* Update the AR coefficients */
        for( k = 0; k < (n + 1) >> 1; k++ ) {
            tmp1 = Af_QA[ k ];                                                              // QA
            tmp2 = Af_QA[ n - k - 1 ];                                                      // QA
            Af_QA[ k ]         = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( tmp2, rc_Q31 ), 1 );    // QA
            Af_QA[ n - k - 1 ] = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( tmp1, rc_Q31 ), 1 );    // QA
        }
        Af_QA[ n ] = SKP_RSHIFT32( rc_Q31, 31 - QA );                                       // QA

        /* Update C * Af and C * Ab */
        for( k = 0; k <= n + 1; k++ ) {
            tmp1 = CAf[ k ];                                                                // Q( -rshifts )
            tmp2 = CAb[ n - k + 1 ];                                                        // Q( -rshifts )
            CAf[ k ]         = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( tmp2, rc_Q31 ), 1 );      // Q( -rshifts )
            CAb[ n - k + 1 ] = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( tmp1, rc_Q31 ), 1 );      // Q( -rshifts )
        }
    }

    /* Return residual energy */
    nrg  = CAf[ 0 ];                                                                        // Q( -rshifts )
    tmp1 = 1 << 16;                                                                         // Q16
    for( k = 0; k < D; k++ ) {
        Atmp1 = SKP_RSHIFT_ROUND( Af_QA[ k ], QA - 16 );                                    // Q16
        nrg  = SKP_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 );                                      // Q( -rshifts )
        tmp1 = SKP_SMLAWW( tmp1, Atmp1, Atmp1 );                                            // Q16
        A_Q16[ k ] = -Atmp1;
    }
    *res_nrg = SKP_SMLAWW( nrg, SKP_SMMUL( WhiteNoiseFrac_Q32, C0 ), -tmp1 );               // Q( -rshifts )
    *res_nrg_Q = -rshifts;
}
/* Resample with a 2x downsampler (optional), a 2nd order AR filter followed by FIR interpolation */
void SKP_Silk_resampler_private_down_FIR(
	void	                        *SS,		    /* I/O: Resampler state 						*/
	SKP_int16						out[],		    /* O:	Output signal 							*/
	const SKP_int16					in[],		    /* I:	Input signal							*/
	SKP_int32					    inLen		    /* I:	Number of input samples					*/
)
{
    SKP_Silk_resampler_state_struct *S = (SKP_Silk_resampler_state_struct *)SS;
	SKP_int32 nSamplesIn, interpol_ind;
	SKP_int32 max_index_Q16, index_Q16, index_increment_Q16, res_Q6;
	SKP_int16 buf1[ RESAMPLER_MAX_BATCH_SIZE_IN / 2 ];
	SKP_int32 buf2[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_DOWN_ORDER_FIR ];
	SKP_int32 *buf_ptr;
	const SKP_int16 *interpol_ptr, *FIR_Coefs;

	/* Copy buffered samples to start of buffer */	
	SKP_memcpy( buf2, S->sFIR, RESAMPLER_DOWN_ORDER_FIR * sizeof( SKP_int32 ) );

    FIR_Coefs = &S->Coefs[ 2 ];

	/* Iterate over blocks of frameSizeIn input samples */
    index_increment_Q16 = S->invRatio_Q16;
	while( 1 ) {
		nSamplesIn = SKP_min( inLen, S->batchSize );

        if( S->input2x == 1 ) {
            /* Downsample 2x */
            SKP_Silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn );

            nSamplesIn = SKP_RSHIFT32( nSamplesIn, 1 );

		    /* Second-order AR filter (output in Q8) */
		    SKP_Silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], buf1, S->Coefs, nSamplesIn );
        } else {
		    /* Second-order AR filter (output in Q8) */
		    SKP_Silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], in, S->Coefs, nSamplesIn );
        }

        max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 );

		/* Interpolate filtered signal */
        if( S->FIR_Fracs == 1 ) {
    		for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
			    /* Integer part gives pointer to buffered input */
			    buf_ptr = buf2 + SKP_RSHIFT( index_Q16, 16 );

			    /* Inner product */
			    res_Q6 = SKP_SMULWB(         SKP_ADD32( buf_ptr[ 0 ], buf_ptr[ 11 ] ), FIR_Coefs[ 0 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 1 ], buf_ptr[ 10 ] ), FIR_Coefs[ 1 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 2 ], buf_ptr[  9 ] ), FIR_Coefs[ 2 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 3 ], buf_ptr[  8 ] ), FIR_Coefs[ 3 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 4 ], buf_ptr[  7 ] ), FIR_Coefs[ 4 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 5 ], buf_ptr[  6 ] ), FIR_Coefs[ 5 ] );

			    /* Scale down, saturate and store in output array */
			    *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) );
		    }
        } else {
    		for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
			    /* Integer part gives pointer to buffered input */
			    buf_ptr = buf2 + SKP_RSHIFT( index_Q16, 16 );

			    /* Fractional part gives interpolation coefficients */
			    interpol_ind = SKP_SMULWB( index_Q16 & 0xFFFF, S->FIR_Fracs );

			    /* Inner product */
			    interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * interpol_ind ];
			    res_Q6 = SKP_SMULWB(         buf_ptr[ 0 ], interpol_ptr[ 0 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] );
			    interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * ( S->FIR_Fracs - 1 - interpol_ind ) ];
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 0 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 1 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[  9 ], interpol_ptr[ 2 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[  8 ], interpol_ptr[ 3 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[  7 ], interpol_ptr[ 4 ] );
			    res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[  6 ], interpol_ptr[ 5 ] );

			    /* Scale down, saturate and store in output array */
			    *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) );
		    }
        }

		in += nSamplesIn << S->input2x;
		inLen -= nSamplesIn << S->input2x;

		if( inLen > S->input2x ) {
			/* More iterations to do; copy last part of filtered signal to beginning of buffer */
			SKP_memcpy( buf2, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( SKP_int32 ) );
		} else {
			break;
		}
	}

	/* Copy last part of filtered signal to the state for the next call */
	SKP_memcpy( S->sFIR, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( SKP_int32 ) );
}
void SKP_Silk_quant_LTP_gains_FIX(
    SKP_int16               B_Q14[],                /* I/O  (un)quantized LTP gains     */
    SKP_int                 cbk_index[],            /* O    Codebook Index              */
    SKP_int                 *periodicity_index,     /* O    Periodicity Index           */
    const SKP_int32         W_Q18[],                /* I    Error Weights in Q18        */
    SKP_int                 mu_Q8,                  /* I    Mu value (R/D tradeoff)     */
    SKP_int                 lowComplexity           /* I    Flag for low complexity     */
)
{
    SKP_int             j, k, temp_idx[ NB_SUBFR ], cbk_size;
    const SKP_uint16    *cdf_ptr;
    const SKP_int16     *cl_ptr;
    const SKP_int16     *cbk_ptr_Q14;
    const SKP_int16     *b_Q14_ptr;
    const SKP_int32     *W_Q18_ptr;
    SKP_int32           rate_dist_subfr, rate_dist, min_rate_dist;



    /***************************************************/
    /* iterate over different codebooks with different */
    /* rates/distortions, and choose best */
    /***************************************************/
    min_rate_dist = SKP_int32_MAX;
    for( k = 0; k < 3; k++ ) {
        cdf_ptr     = SKP_Silk_LTP_gain_CDF_ptrs[     k ];
        cl_ptr      = SKP_Silk_LTP_gain_BITS_Q6_ptrs[ k ];
        cbk_ptr_Q14 = SKP_Silk_LTP_vq_ptrs_Q14[       k ];
        cbk_size    = SKP_Silk_LTP_vq_sizes[          k ];

        /* Setup pointer to first subframe */
        W_Q18_ptr = W_Q18;
        b_Q14_ptr = B_Q14;

        rate_dist = 0;
        for( j = 0; j < NB_SUBFR; j++ ) {

            SKP_Silk_VQ_WMat_EC_FIX(
                &temp_idx[ j ],         /* O    index of best codebook vector                           */
                &rate_dist_subfr,       /* O    best weighted quantization error + mu * rate            */
                b_Q14_ptr,              /* I    input vector to be quantized                            */
                W_Q18_ptr,              /* I    weighting matrix                                        */
                cbk_ptr_Q14,            /* I    codebook                                                */
                cl_ptr,                 /* I    code length for each codebook vector                    */
                mu_Q8,                  /* I    tradeoff between weighted error and rate                */
                cbk_size                /* I    number of vectors in codebook                           */
            );

            rate_dist = SKP_ADD_POS_SAT32( rate_dist, rate_dist_subfr );

            b_Q14_ptr += LTP_ORDER;
            W_Q18_ptr += LTP_ORDER * LTP_ORDER;
        }

        /* Avoid never finding a codebook */
        rate_dist = SKP_min( SKP_int32_MAX - 1, rate_dist );

        if( rate_dist < min_rate_dist ) {
            min_rate_dist = rate_dist;
            SKP_memcpy( cbk_index, temp_idx, NB_SUBFR * sizeof( SKP_int ) );
            *periodicity_index = k;
        }

        /* Break early in low-complexity mode if rate distortion is below threshold */
        if( lowComplexity && ( rate_dist < SKP_Silk_LTP_gain_middle_avg_RD_Q14 ) ) {
            break;
        }
    }

    cbk_ptr_Q14 = SKP_Silk_LTP_vq_ptrs_Q14[ *periodicity_index ];
    for( j = 0; j < NB_SUBFR; j++ ) {
        for( k = 0; k < LTP_ORDER; k++ ) { 
            B_Q14[ j * LTP_ORDER + k ] = cbk_ptr_Q14[ SKP_MLA( k, cbk_index[ j ], LTP_ORDER ) ];
        }
    }
}
/* Control internal sampling rate */
SKP_int SKP_Silk_control_audio_bandwidth(
    SKP_Silk_encoder_state      *psEncC,            /* I/O  Pointer to Silk encoder state               */
    SKP_int32                   TargetRate_bps      /* I    Target max bitrate (bps)                    */
)
{
    SKP_int fs_kHz;

    fs_kHz = psEncC->fs_kHz;

    /* Reduce bitrate for 10 ms modes in these calculations */
    if( psEncC->nb_subfr == 2 ) {
        TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS;
    }

    if( fs_kHz == 0 ) {
        /* Encoder has just been initialized */
        if( TargetRate_bps >= WB2MB_BITRATE_BPS ) {
            fs_kHz = 16;
        } else if( TargetRate_bps >= MB2NB_BITRATE_BPS ) {
            fs_kHz = 12;
        } else {
            fs_kHz = 8;
        }
        /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */
        fs_kHz = SKP_min( fs_kHz, SKP_DIV32_16( psEncC->API_fs_Hz, 1000 ) );
        fs_kHz = SKP_min( fs_kHz, psEncC->maxInternal_fs_kHz );
        fs_kHz = SKP_max( fs_kHz, psEncC->minInternal_fs_kHz );
    } else if( SKP_SMULBB( fs_kHz, 1000 ) > psEncC->API_fs_Hz || fs_kHz > psEncC->maxInternal_fs_kHz || fs_kHz < psEncC->minInternal_fs_kHz ) {
        /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */
        fs_kHz = SKP_DIV32_16( psEncC->API_fs_Hz, 1000 );
        fs_kHz = SKP_min( fs_kHz, psEncC->maxInternal_fs_kHz );
        fs_kHz = SKP_max( fs_kHz, psEncC->minInternal_fs_kHz );
    } else {
        /* State machine for the internal sampling rate switching */
        if( psEncC->API_fs_Hz > 8000 && psEncC->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) { /* Low speech activity */
            /* Check if we should switch down */
            if( ( psEncC->fs_kHz == 12 && TargetRate_bps < MB2NB_BITRATE_BPS && psEncC->minInternal_fs_kHz <=  8 ) ||
                ( psEncC->fs_kHz == 16 && TargetRate_bps < WB2MB_BITRATE_BPS && psEncC->minInternal_fs_kHz <= 12 ) ) 
            {
                /* Switch down */
                if( SWITCH_TRANSITION_FILTERING && psEncC->sLP.mode == 0 ) {
                    /* New transition */
                    psEncC->sLP.transition_frame_no = TRANSITION_FRAMES;

                    /* Reset transition filter state */
                    SKP_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) );
                } 
                if( psEncC->sLP.transition_frame_no <= 0 ) {
                    /* Stop transition phase */
                    psEncC->sLP.mode = 0;

                    /* Switch to a lower sample frequency */
                    fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8;
                } else {
                    /* Direction: down (at double speed) */
                    psEncC->sLP.mode = -2;
                } 
            } 
            else
            if( ( psEncC->fs_kHz ==  8 && TargetRate_bps > NB2MB_BITRATE_BPS && psEncC->maxInternal_fs_kHz >= 12 && psEncC->API_fs_Hz >= 12000 ) ||
                ( psEncC->fs_kHz == 12 && TargetRate_bps > MB2WB_BITRATE_BPS && psEncC->maxInternal_fs_kHz >= 16 && psEncC->API_fs_Hz >= 16000 ) ) 
            {
                /* Switch up */
                if( SWITCH_TRANSITION_FILTERING && psEncC->sLP.mode == 0 ) {
                    /* Switch to a higher sample frequency */
                    fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16;

                    /* New transition */
                    psEncC->sLP.transition_frame_no = 0;
                } 
                if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) {
                    /* Stop transition phase */
                    psEncC->sLP.mode = 0;
                } else {
                    /* Direction: up */
                    psEncC->sLP.mode = 1;
                }
            }
        }
    }

#ifdef FORCE_INTERNAL_FS_KHZ
    fs_kHz = FORCE_INTERNAL_FS_KHZ;
#endif

    return fs_kHz;
}
/* Control internal sampling rate */
SKP_int silk_control_audio_bandwidth(
    silk_encoder_state      *psEncC             /* I/O  Pointer to Silk encoder state               */
)
{
    SKP_int   fs_kHz;
    SKP_int32 fs_Hz;
    
    fs_kHz = psEncC->fs_kHz;
    fs_Hz = SKP_SMULBB( fs_kHz, 1000 );
    if( fs_Hz == 0 ) {
        /* Encoder has just been initialized */
        fs_Hz  = SKP_min( psEncC->desiredInternal_fs_Hz, psEncC->API_fs_Hz );
        fs_kHz = SKP_DIV32_16( fs_Hz, 1000 );
    } else if( fs_Hz > psEncC->API_fs_Hz || fs_Hz > psEncC->maxInternal_fs_Hz || fs_Hz < psEncC->minInternal_fs_Hz ) {
        /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */
        fs_Hz  = psEncC->API_fs_Hz;
        fs_Hz  = SKP_min( fs_Hz, psEncC->maxInternal_fs_Hz );
        fs_Hz  = SKP_max( fs_Hz, psEncC->minInternal_fs_Hz );
        fs_kHz = SKP_DIV32_16( fs_Hz, 1000 );
    } else {
        /* State machine for the internal sampling rate switching */
        if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) {
            /* Stop transition phase */
            psEncC->sLP.mode = 0;
        }
        if( psEncC->allow_bandwidth_switch ) {
            /* Check if we should switch down */
            if( SKP_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz ) 
            {
                /* Switch down */
                if( psEncC->sLP.mode == 0 ) {
                    /* New transition */
                    psEncC->sLP.transition_frame_no = TRANSITION_FRAMES;

                    /* Reset transition filter state */
                    SKP_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) );
                } 
                if( psEncC->sLP.transition_frame_no <= 0 ) {
                    /* Stop transition phase */
                    psEncC->sLP.mode = 0;

                    /* Switch to a lower sample frequency */
                    fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8;
                } else {
                    /* Direction: down (at double speed) */
                    psEncC->sLP.mode = -2;
                } 
            } 
            else
            /* Check if we should switch up */
            if( SKP_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz ) 
            {
                /* Switch up */
                if( psEncC->sLP.mode == 0 ) {
                    /* Switch to a higher sample frequency */
                    fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16;

                    /* New transition */
                    psEncC->sLP.transition_frame_no = 0;

                    /* Reset transition filter state */
                    SKP_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) );
                } 
                /* Direction: up */
                psEncC->sLP.mode = 1;
            }
        }
    }

#ifdef FORCE_INTERNAL_FS_KHZ
    fs_kHz = FORCE_INTERNAL_FS_KHZ;
#endif

    return fs_kHz;
}