SKP_int SKP_Silk_VAD_FLP(
    SKP_Silk_encoder_state_FLP      *psEnc,             /* I/O  Encoder state FLP                       */
    SKP_Silk_encoder_control_FLP    *psEncCtrl,         /* I/O  Encoder control FLP                     */
    const SKP_int16                 *pIn                /* I    Input signal                            */
)
{
    SKP_int i, ret, SA_Q8, SNR_dB_Q7, Tilt_Q15;
    SKP_int Quality_Bands_Q15[ VAD_N_BANDS ];

    ret = SKP_Silk_VAD_GetSA_Q8( &psEnc->sCmn.sVAD, &SA_Q8, &SNR_dB_Q7, Quality_Bands_Q15, &Tilt_Q15,
        pIn, psEnc->sCmn.frame_length );

    psEnc->speech_activity = ( SKP_float )SA_Q8 / 256.0f;
    for( i = 0; i < VAD_N_BANDS; i++ ) {
        psEncCtrl->input_quality_bands[ i ] = ( SKP_float )Quality_Bands_Q15[ i ] / 32768.0f;
    }
    psEncCtrl->input_tilt = ( SKP_float )Tilt_Q15 / 32768.0f;

    return ret;
}
int SKP_Silk_encode_frame_FIX(SKP_Silk_encoder_state_FIX * psEnc,	/* I/O  Pointer to Silk FIX encoder state           */
			      uint8_t * pCode,	/* O    Pointer to payload                          */
			      int16_t * pnBytesOut,	/* I/O  Pointer to number of payload bytes          */
			      /*      input: max length; output: used             */
			      const int16_t * pIn	/* I    Pointer to input speech frame               */
    ) {
	SKP_Silk_encoder_control_FIX sEncCtrl;
	int i, nBytes, ret = 0;
	int16_t *x_frame, *res_pitch_frame;
	int16_t xfw[MAX_FRAME_LENGTH];
	int16_t pIn_HP[MAX_FRAME_LENGTH];
	int16_t res_pitch[2 * MAX_FRAME_LENGTH + LA_PITCH_MAX];
	int LBRR_idx, frame_terminator, SNR_dB_Q7;
	const uint16_t *FrameTermination_CDF;

	/* Low bitrate redundancy parameters */
	uint8_t LBRRpayload[MAX_ARITHM_BYTES];
	int16_t nBytesLBRR;

	//int32_t   Seed[ MAX_LAYERS ];
	sEncCtrl.sCmn.Seed = psEnc->sCmn.frameCounter++ & 3;

    /**************************************************************/
	/* Setup Input Pointers, and insert frame in input buffer    */
    /*************************************************************/
	x_frame = psEnc->x_buf + psEnc->sCmn.frame_length;	/* start of frame to encode */
	res_pitch_frame = res_pitch + psEnc->sCmn.frame_length;	/* start of pitch LPC residual frame */

    /****************************/
	/* Voice Activity Detection */
    /****************************/
	ret =
	    SKP_Silk_VAD_GetSA_Q8(&psEnc->sCmn.sVAD, &psEnc->speech_activity_Q8,
				  &SNR_dB_Q7, sEncCtrl.input_quality_bands_Q15,
				  &sEncCtrl.input_tilt_Q15, pIn,
				  psEnc->sCmn.frame_length);

    /*******************************************/
	/* High-pass filtering of the input signal */
    /*******************************************/
#if HIGH_PASS_INPUT
	/* Variable high-pass filter */
	SKP_Silk_HP_variable_cutoff_FIX(psEnc, &sEncCtrl, pIn_HP, pIn);
#else
	SKP_memcpy(pIn_HP, pIn, psEnc->sCmn.frame_length * sizeof(int16_t));
#endif

#if SWITCH_TRANSITION_FILTERING
	/* Ensure smooth bandwidth transitions */
	SKP_Silk_LP_variable_cutoff(&psEnc->sCmn.sLP,
				    x_frame + psEnc->sCmn.la_shape, pIn_HP,
				    psEnc->sCmn.frame_length);
#else
	SKP_memcpy(x_frame + psEnc->sCmn.la_shape, pIn_HP,
		   psEnc->sCmn.frame_length * sizeof(int16_t));
#endif

    /*****************************************/
	/* Find pitch lags, initial LPC analysis */
    /*****************************************/
	SKP_Silk_find_pitch_lags_FIX(psEnc, &sEncCtrl, res_pitch, x_frame);

    /************************/
	/* Noise shape analysis */
    /************************/
	SKP_Silk_noise_shape_analysis_FIX(psEnc, &sEncCtrl, res_pitch_frame,
					  x_frame);

    /*****************************************/
	/* Prefiltering for noise shaper         */
    /*****************************************/
	SKP_Silk_prefilter_FIX(psEnc, &sEncCtrl, xfw, x_frame);

    /***************************************************/
	/* Find linear prediction coefficients (LPC + LTP) */
    /***************************************************/
	SKP_Silk_find_pred_coefs_FIX(psEnc, &sEncCtrl, res_pitch);

    /****************************************/
	/* Process gains                        */
    /****************************************/
	SKP_Silk_process_gains_FIX(psEnc, &sEncCtrl);

	psEnc->sCmn.sigtype[psEnc->sCmn.nFramesInPayloadBuf] =
	    sEncCtrl.sCmn.sigtype;
	psEnc->sCmn.QuantOffsetType[psEnc->sCmn.nFramesInPayloadBuf] =
	    sEncCtrl.sCmn.QuantOffsetType;

    /****************************************/
	/* Low Bitrate Redundant Encoding       */
    /****************************************/
	nBytesLBRR = MAX_ARITHM_BYTES;
	SKP_Silk_LBRR_encode_FIX(psEnc, &sEncCtrl, LBRRpayload, &nBytesLBRR,
				 xfw);

    /*****************************************/
	/* Noise shaping quantization            */
    /*****************************************/
	psEnc->NoiseShapingQuantizer(&psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sNSQ,
				     xfw,
				     &psEnc->sCmn.q[psEnc->sCmn.
						    nFramesInPayloadBuf *
						    psEnc->sCmn.frame_length],
				     sEncCtrl.sCmn.NLSFInterpCoef_Q2,
				     sEncCtrl.PredCoef_Q12[0],
				     sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13,
				     sEncCtrl.HarmShapeGain_Q14,
				     sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14,
				     sEncCtrl.Gains_Q16, sEncCtrl.Lambda_Q10,
				     sEncCtrl.LTP_scale_Q14);

    /**************************************************/
	/* Convert speech activity into VAD and DTX flags */
    /**************************************************/
	if (psEnc->speech_activity_Q8 < SPEECH_ACTIVITY_DTX_THRES_Q8) {
		psEnc->sCmn.vadFlag = NO_VOICE_ACTIVITY;
		psEnc->sCmn.noSpeechCounter++;
		if (psEnc->sCmn.noSpeechCounter > NO_SPEECH_FRAMES_BEFORE_DTX) {
			psEnc->sCmn.inDTX = 1;
		}
		if (psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX) {
			psEnc->sCmn.noSpeechCounter = 0;
			psEnc->sCmn.inDTX = 0;
		}
	} else {
		psEnc->sCmn.noSpeechCounter = 0;
		psEnc->sCmn.inDTX = 0;
		psEnc->sCmn.vadFlag = VOICE_ACTIVITY;
	}

    /****************************************/
	/* Initialize arithmetic coder          */
    /****************************************/
	if (psEnc->sCmn.nFramesInPayloadBuf == 0) {
		SKP_Silk_range_enc_init(&psEnc->sCmn.sRC);
		psEnc->sCmn.nBytesInPayloadBuf = 0;
	}

    /****************************************/
	/* Encode Parameters                    */
    /****************************************/
	if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) {
		SKP_Silk_encode_parameters_v4(&psEnc->sCmn, &sEncCtrl.sCmn,
					      &psEnc->sCmn.sRC);
		FrameTermination_CDF = SKP_Silk_FrameTermination_v4_CDF;
	} else {
		SKP_Silk_encode_parameters(&psEnc->sCmn, &sEncCtrl.sCmn,
					   &psEnc->sCmn.sRC,
					   &psEnc->sCmn.q[psEnc->sCmn.
							  nFramesInPayloadBuf *
							  psEnc->sCmn.
							  frame_length]);
		FrameTermination_CDF = SKP_Silk_FrameTermination_CDF;
	}

    /****************************************/
	/* Update Buffers and State             */
    /****************************************/
	/* Update Input buffer */
	SKP_memmove(psEnc->x_buf, &psEnc->x_buf[psEnc->sCmn.frame_length],
		    (psEnc->sCmn.frame_length +
		     psEnc->sCmn.la_shape) * sizeof(int16_t));

	/* parameters needed for next frame */
	psEnc->sCmn.prev_sigtype = sEncCtrl.sCmn.sigtype;
	psEnc->sCmn.prevLag = sEncCtrl.sCmn.pitchL[NB_SUBFR - 1];
	psEnc->sCmn.first_frame_after_reset = 0;

	if (psEnc->sCmn.sRC.error) {
		/* encoder returned error: clear payload buffer */
		psEnc->sCmn.nFramesInPayloadBuf = 0;
	} else {
		psEnc->sCmn.nFramesInPayloadBuf++;
	}

    /****************************************/
	/* finalize payload and copy to output  */
    /****************************************/
	if (psEnc->sCmn.nFramesInPayloadBuf * FRAME_LENGTH_MS >=
	    psEnc->sCmn.PacketSize_ms) {

		LBRR_idx = (psEnc->sCmn.oldest_LBRR_idx + 1) & LBRR_IDX_MASK;

		/* Check if FEC information should be added */
		frame_terminator = SKP_SILK_LAST_FRAME;
		if (psEnc->sCmn.LBRR_buffer[LBRR_idx].usage ==
		    SKP_SILK_ADD_LBRR_TO_PLUS1) {
			frame_terminator = SKP_SILK_LBRR_VER1;
		}
		if (psEnc->sCmn.LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx].
		    usage == SKP_SILK_ADD_LBRR_TO_PLUS2) {
			frame_terminator = SKP_SILK_LBRR_VER2;
			LBRR_idx = psEnc->sCmn.oldest_LBRR_idx;
		}
		/* Add the frame termination info to stream */
		SKP_Silk_range_encoder(&psEnc->sCmn.sRC, frame_terminator,
				       FrameTermination_CDF);

		if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) {
			/* Code excitation signal */
			for (i = 0; i < psEnc->sCmn.nFramesInPayloadBuf; i++) {
				SKP_Silk_encode_pulses(&psEnc->sCmn.sRC,
						       psEnc->sCmn.sigtype[i],
						       psEnc->sCmn.
						       QuantOffsetType[i],
						       &psEnc->sCmn.q[i *
								      psEnc->
								      sCmn.
								      frame_length],
						       psEnc->sCmn.
						       frame_length);
			}
		}
		/* payload length so far */
		SKP_Silk_range_coder_get_length(&psEnc->sCmn.sRC, &nBytes);

		/* check that there is enough space in external output buffer, and move data */
		if (*pnBytesOut >= nBytes) {
			SKP_Silk_range_enc_wrap_up(&psEnc->sCmn.sRC);
			SKP_memcpy(pCode, psEnc->sCmn.sRC.buffer,
				   nBytes * sizeof(uint8_t));

			if (frame_terminator > SKP_SILK_MORE_FRAMES &&
			    *pnBytesOut >=
			    nBytes + psEnc->sCmn.LBRR_buffer[LBRR_idx].nBytes) {
				/* Get old packet and add to payload. */
				SKP_memcpy(&pCode[nBytes],
					   psEnc->sCmn.LBRR_buffer[LBRR_idx].
					   payload,
					   psEnc->sCmn.LBRR_buffer[LBRR_idx].
					   nBytes * sizeof(uint8_t));
				nBytes +=
				    psEnc->sCmn.LBRR_buffer[LBRR_idx].nBytes;
			}

			*pnBytesOut = nBytes;

			/* Update FEC buffer */
			SKP_memcpy(psEnc->sCmn.
				   LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx].
				   payload, LBRRpayload,
				   nBytesLBRR * sizeof(uint8_t));
			psEnc->sCmn.LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx].
			    nBytes = nBytesLBRR;
			/* This line tells describes how FEC should be used */
			psEnc->sCmn.LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx].
			    usage = sEncCtrl.sCmn.LBRR_usage;
			psEnc->sCmn.oldest_LBRR_idx =
			    (psEnc->sCmn.oldest_LBRR_idx + 1) & LBRR_IDX_MASK;

			/* Reset number of frames in payload buffer */
			psEnc->sCmn.nFramesInPayloadBuf = 0;
		} else {
			/* Not enough space: Payload will be discarded */
			*pnBytesOut = 0;
			nBytes = 0;
			psEnc->sCmn.nFramesInPayloadBuf = 0;
			ret = SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT;
		}
	} else {
		/* no payload for you this time */
		*pnBytesOut = 0;

		/* Encode that more frames follows */
		frame_terminator = SKP_SILK_MORE_FRAMES;
		SKP_Silk_range_encoder(&psEnc->sCmn.sRC, frame_terminator,
				       FrameTermination_CDF);

		/* payload length so far */
		SKP_Silk_range_coder_get_length(&psEnc->sCmn.sRC, &nBytes);

		if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) {
			/* Take into account the q signal that isnt in the bitstream yet */
			nBytes += SKP_Silk_pulses_to_bytes(&psEnc->sCmn,
							   &psEnc->sCmn.
							   q[(psEnc->sCmn.
							      nFramesInPayloadBuf
							      -
							      1) *
							     psEnc->sCmn.
							     frame_length]);
		}
	}

	/* Check for arithmetic coder errors */
	if (psEnc->sCmn.sRC.error) {
		ret = SKP_SILK_ENC_INTERNAL_ERROR;
	}

	/* simulate number of ms buffered in channel because of exceeding TargetRate */
	assert((8 * 1000 *
		    ((int64_t) nBytes -
		     (int64_t) psEnc->sCmn.nBytesInPayloadBuf)) ==
		   SKP_SAT32(8 * 1000 *
			     ((int64_t) nBytes -
			      (int64_t) psEnc->sCmn.nBytesInPayloadBuf)));
	assert(psEnc->sCmn.TargetRate_bps > 0);
	psEnc->BufferedInChannel_ms +=
	    SKP_DIV32(8 * 1000 * (nBytes - psEnc->sCmn.nBytesInPayloadBuf),
		      psEnc->sCmn.TargetRate_bps);
	psEnc->BufferedInChannel_ms -= FRAME_LENGTH_MS;
	psEnc->BufferedInChannel_ms =
	    SKP_LIMIT(psEnc->BufferedInChannel_ms, 0, 100);
	psEnc->sCmn.nBytesInPayloadBuf = nBytes;

	if (psEnc->speech_activity_Q8 > WB_DETECT_ACTIVE_SPEECH_LEVEL_THRES_Q8) {
		psEnc->sCmn.sSWBdetect.ActiveSpeech_ms =
		    SKP_ADD_POS_SAT32(psEnc->sCmn.sSWBdetect.ActiveSpeech_ms,
				      FRAME_LENGTH_MS);
	}

	return (ret);
}