Пример #1
0
void SKP_Silk_LBRR_embed(
    SKP_Silk_encoder_state      *psEncC,            /* I/O  Encoder state                               */
    ec_enc                      *psRangeEnc         /* I/O  Compressor data structure                   */
)
{
    SKP_int   i;
    SKP_int32 LBRR_symbol;

    /* Encode LBRR flags */
    LBRR_symbol = 0;
    for( i = 0; i < psEncC->nFramesPerPacket; i++ ) {
        LBRR_symbol |= SKP_LSHIFT( psEncC->LBRR_flags[ i ], i );
    }
    psEncC->LBRR_flag = LBRR_symbol > 0 ? 1 : 0;
    if( LBRR_symbol && psEncC->nFramesPerPacket > 1 ) {
        ec_enc_icdf( psRangeEnc, LBRR_symbol - 1, SKP_Silk_LBRR_flags_iCDF_ptr[ psEncC->nFramesPerPacket - 2 ], 8 );
    }

    /* Code indices and excitation signals */
    for( i = 0; i < psEncC->nFramesPerPacket; i++ ) {
        if( psEncC->LBRR_flags[ i ] ) {
            SKP_Silk_encode_indices( psEncC, psRangeEnc, i, 1 );
            SKP_Silk_encode_pulses( psRangeEnc, psEncC->indices_LBRR[i].signalType, 
                psEncC->indices_LBRR[i].quantOffsetType, psEncC->pulses_LBRR[ i ], psEncC->frame_length );
        }
    }
}
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);
}
/* Low BitRate Redundancy encoding functionality. Reuse all parameters but encode residual with lower bitrate */
void SKP_Silk_LBRR_encode_FIX(SKP_Silk_encoder_state_FIX * psEnc,	/* I/O  Pointer to Silk encoder state           */
			      SKP_Silk_encoder_control_FIX * psEncCtrl,	/* I/O  Pointer to Silk encoder control struct  */
			      uint8_t * pCode,	/* O    Pointer to payload                      */
			      int16_t * pnBytesOut,	/* I/O  Pointer to number of payload bytes      */
			      int16_t xfw[]	/* I    Input signal                            */
    )
{
	int i, TempGainsIndices[NB_SUBFR], frame_terminator;
	int nBytes, nFramesInPayloadBuf;
	int32_t TempGains_Q16[NB_SUBFR];
	int typeOffset, LTP_scaleIndex, Rate_only_parameters = 0;
    /*******************************************/
	/* Control use of inband LBRR              */
    /*******************************************/
	SKP_Silk_LBRR_ctrl_FIX(psEnc, psEncCtrl);

	if (psEnc->sCmn.LBRR_enabled) {
		/* Save original Gains */
		SKP_memcpy(TempGainsIndices, psEncCtrl->sCmn.GainsIndices,
			   NB_SUBFR * sizeof(int));
		SKP_memcpy(TempGains_Q16, psEncCtrl->Gains_Q16,
			   NB_SUBFR * sizeof(int32_t));

		typeOffset = psEnc->sCmn.typeOffsetPrev;	// Temp save as cannot be overwritten
		LTP_scaleIndex = psEncCtrl->sCmn.LTP_scaleIndex;

		/* Set max rate where quant signal is encoded */
		if (psEnc->sCmn.fs_kHz == 8) {
			Rate_only_parameters = 13500;
		} else if (psEnc->sCmn.fs_kHz == 12) {
			Rate_only_parameters = 15500;
		} else if (psEnc->sCmn.fs_kHz == 16) {
			Rate_only_parameters = 17500;
		} else if (psEnc->sCmn.fs_kHz == 24) {
			Rate_only_parameters = 19500;
		} else {
			assert(0);
		}

		if (psEnc->sCmn.Complexity > 0
		    && psEnc->sCmn.TargetRate_bps > Rate_only_parameters) {
			if (psEnc->sCmn.nFramesInPayloadBuf == 0) {
				/* First frame in packet copy Everything */
				SKP_memcpy(&psEnc->sNSQ_LBRR, &psEnc->sNSQ,
					   sizeof(SKP_Silk_nsq_state));

				psEnc->sCmn.LBRRprevLastGainIndex =
				    psEnc->sShape.LastGainIndex;
				/* Increase Gains to get target LBRR rate */
				psEncCtrl->sCmn.GainsIndices[0] =
				    psEncCtrl->sCmn.GainsIndices[0] +
				    psEnc->sCmn.LBRR_GainIncreases;
				psEncCtrl->sCmn.GainsIndices[0] =
				    SKP_LIMIT(psEncCtrl->sCmn.GainsIndices[0],
					      0, N_LEVELS_QGAIN - 1);
			}
			/* Decode to get Gains in sync with decoder         */
			/* Overwrite unquantized gains with quantized gains */
			SKP_Silk_gains_dequant(psEncCtrl->Gains_Q16,
					       psEncCtrl->sCmn.GainsIndices,
					       &psEnc->sCmn.
					       LBRRprevLastGainIndex,
					       psEnc->sCmn.nFramesInPayloadBuf);
	    /*****************************************/
			/* Noise shaping quantization            */
	    /*****************************************/
			psEnc->NoiseShapingQuantizer(&psEnc->sCmn,
						     &psEncCtrl->sCmn,
						     &psEnc->sNSQ_LBRR, xfw,
						     &psEnc->sCmn.q_LBRR[psEnc->
									 sCmn.
									 nFramesInPayloadBuf
									 *
									 psEnc->
									 sCmn.
									 frame_length],
						     psEncCtrl->sCmn.
						     NLSFInterpCoef_Q2,
						     psEncCtrl->PredCoef_Q12[0],
						     psEncCtrl->LTPCoef_Q14,
						     psEncCtrl->AR2_Q13,
						     psEncCtrl->
						     HarmShapeGain_Q14,
						     psEncCtrl->Tilt_Q14,
						     psEncCtrl->LF_shp_Q14,
						     psEncCtrl->Gains_Q16,
						     psEncCtrl->Lambda_Q10,
						     psEncCtrl->LTP_scale_Q14);
		} else {
			SKP_memset(&psEnc->sCmn.
				   q_LBRR[psEnc->sCmn.nFramesInPayloadBuf *
					  psEnc->sCmn.frame_length], 0,
				   psEnc->sCmn.frame_length * sizeof(int));
			psEncCtrl->sCmn.LTP_scaleIndex = 0;
		}
	/****************************************/
		/* Initialize arithmetic coder          */
	/****************************************/
		if (psEnc->sCmn.nFramesInPayloadBuf == 0) {
			SKP_Silk_range_enc_init(&psEnc->sCmn.sRC_LBRR);
			psEnc->sCmn.nBytesInPayloadBuf = 0;
		}

	/****************************************/
		/* Encode Parameters                    */
	/****************************************/
		if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) {
			SKP_Silk_encode_parameters_v4(&psEnc->sCmn,
						      &psEncCtrl->sCmn,
						      &psEnc->sCmn.sRC_LBRR);
		} else {
			SKP_Silk_encode_parameters(&psEnc->sCmn,
						   &psEncCtrl->sCmn,
						   &psEnc->sCmn.sRC_LBRR,
						   &psEnc->sCmn.q_LBRR[psEnc->
								       sCmn.
								       nFramesInPayloadBuf
								       *
								       psEnc->
								       sCmn.
								       frame_length]);
		}

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

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

			/* Check if FEC information should be added */
			frame_terminator = SKP_SILK_LAST_FRAME;

			/* Add the frame termination info to stream */
			SKP_Silk_range_encoder(&psEnc->sCmn.sRC_LBRR,
					       frame_terminator,
					       SKP_Silk_FrameTermination_CDF);

			if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) {
		/*********************************************/
				/* Encode quantization indices of excitation */
		/*********************************************/
				for (i = 0; i < nFramesInPayloadBuf; i++) {
					SKP_Silk_encode_pulses(&psEnc->sCmn.
							       sRC_LBRR,
							       psEnc->sCmn.
							       sigtype[i],
							       psEnc->sCmn.
							       QuantOffsetType
							       [i],
							       &psEnc->sCmn.
							       q_LBRR[i *
								      psEnc->
								      sCmn.
								      frame_length],
							       psEnc->sCmn.
							       frame_length);
				}
			}
			/* payload length so far */
			SKP_Silk_range_coder_get_length(&psEnc->sCmn.sRC_LBRR,
							&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_LBRR);
				SKP_memcpy(pCode, psEnc->sCmn.sRC_LBRR.buffer,
					   nBytes * sizeof(uint8_t));

				*pnBytesOut = nBytes;
			} else {
				/* not enough space: payload will be discarded */
				*pnBytesOut = 0;
				assert(0);
			}
		} 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_LBRR,
					       frame_terminator,
					       SKP_Silk_FrameTermination_CDF);
		}

		/* Restore original Gains */
		SKP_memcpy(psEncCtrl->sCmn.GainsIndices, TempGainsIndices,
			   NB_SUBFR * sizeof(int));
		SKP_memcpy(psEncCtrl->Gains_Q16, TempGains_Q16,
			   NB_SUBFR * sizeof(int32_t));

		/* Restore LTP scale index and typeoffset */
		psEncCtrl->sCmn.LTP_scaleIndex = LTP_scaleIndex;
		psEnc->sCmn.typeOffsetPrev = typeOffset;
	}
}
void SKP_Silk_encode_parameters(
    SKP_Silk_encoder_state          *psEncC,        /* I/O  Encoder state                   */
    SKP_Silk_encoder_control        *psEncCtrlC,    /* I/O  Encoder control                 */
    SKP_Silk_range_coder_state      *psRC,          /* I/O  Range encoder state             */
    const SKP_int8                  *q              /* I    Quantization indices            */
)
{
    SKP_int   i, k, typeOffset;
    const SKP_Silk_NLSF_CB_struct *psNLSF_CB;


    /************************/
    /* Encode sampling rate */
    /************************/
    /* only done for first frame in packet */
    if( psEncC->nFramesInPayloadBuf == 0 ) {
        /* get sampling rate index */
        for( i = 0; i < 3; i++ ) {
            if( SKP_Silk_SamplingRates_table[ i ] == psEncC->fs_kHz ) {
                break;
            }
        }
        SKP_Silk_range_encoder( psRC, i, SKP_Silk_SamplingRates_CDF );
    }

    /*******************************************/
    /* Encode signal type and quantizer offset */
    /*******************************************/
    typeOffset = 2 * psEncCtrlC->sigtype + psEncCtrlC->QuantOffsetType;
    if( psEncC->nFramesInPayloadBuf == 0 ) {
        /* first frame in packet: independent coding */
        SKP_Silk_range_encoder( psRC, typeOffset, SKP_Silk_type_offset_CDF );
    } else {
        /* condidtional coding */
        SKP_Silk_range_encoder( psRC, typeOffset, SKP_Silk_type_offset_joint_CDF[ psEncC->typeOffsetPrev ] );
    }
    psEncC->typeOffsetPrev = typeOffset;

    /****************/
    /* Encode gains */
    /****************/
    /* first subframe */
    if( psEncC->nFramesInPayloadBuf == 0 ) {
        /* first frame in packet: independent coding */
        SKP_Silk_range_encoder( psRC, psEncCtrlC->GainsIndices[ 0 ], SKP_Silk_gain_CDF[ psEncCtrlC->sigtype ] );
    } else {
        /* condidtional coding */
        SKP_Silk_range_encoder( psRC, psEncCtrlC->GainsIndices[ 0 ], SKP_Silk_delta_gain_CDF );
    }

    /* remaining subframes */
    for( i = 1; i < NB_SUBFR; i++ ) {
        SKP_Silk_range_encoder( psRC, psEncCtrlC->GainsIndices[ i ], SKP_Silk_delta_gain_CDF );
    }


    /****************/
    /* Encode NLSFs */
    /****************/
    /* Range encoding of the NLSF path */
    psNLSF_CB = psEncC->psNLSF_CB[ psEncCtrlC->sigtype ];
    SKP_Silk_range_encoder_multi( psRC, psEncCtrlC->NLSFIndices, psNLSF_CB->StartPtr, psNLSF_CB->nStages );

    /* Encode NLSF interpolation factor */
    SKP_assert( psEncC->useInterpolatedNLSFs == 1 || psEncCtrlC->NLSFInterpCoef_Q2 == ( 1 << 2 ) );
    SKP_Silk_range_encoder( psRC, psEncCtrlC->NLSFInterpCoef_Q2, SKP_Silk_NLSF_interpolation_factor_CDF );


    if( psEncCtrlC->sigtype == SIG_TYPE_VOICED ) {
        /*********************/
        /* Encode pitch lags */
        /*********************/


        /* lag index */
        if( psEncC->fs_kHz == 8 ) {
            SKP_Silk_range_encoder( psRC, psEncCtrlC->lagIndex, SKP_Silk_pitch_lag_NB_CDF );
        } else if( psEncC->fs_kHz == 12 ) {
            SKP_Silk_range_encoder( psRC, psEncCtrlC->lagIndex, SKP_Silk_pitch_lag_MB_CDF );
        } else if( psEncC->fs_kHz == 16 ) {
            SKP_Silk_range_encoder( psRC, psEncCtrlC->lagIndex, SKP_Silk_pitch_lag_WB_CDF );
        } else {
            SKP_Silk_range_encoder( psRC, psEncCtrlC->lagIndex, SKP_Silk_pitch_lag_SWB_CDF );
        }


        /* countour index */
        if( psEncC->fs_kHz == 8 ) {
            /* Less codevectors used in 8 khz mode */
            SKP_Silk_range_encoder( psRC, psEncCtrlC->contourIndex, SKP_Silk_pitch_contour_NB_CDF );
        } else {
            /* Joint for 12, 16, 24 khz */
            SKP_Silk_range_encoder( psRC, psEncCtrlC->contourIndex, SKP_Silk_pitch_contour_CDF );
        }

        /********************/
        /* Encode LTP gains */
        /********************/

        /* PERIndex value */
        SKP_Silk_range_encoder( psRC, psEncCtrlC->PERIndex, SKP_Silk_LTP_per_index_CDF );

        /* Codebook Indices */
        for( k = 0; k < NB_SUBFR; k++ ) {
            SKP_Silk_range_encoder( psRC, psEncCtrlC->LTPIndex[ k ], SKP_Silk_LTP_gain_CDF_ptrs[ psEncCtrlC->PERIndex ] );
        }

        /**********************/
        /* Encode LTP scaling */
        /**********************/
        SKP_Silk_range_encoder( psRC, psEncCtrlC->LTP_scaleIndex, SKP_Silk_LTPscale_CDF );
    }


    /***************/
    /* Encode seed */
    /***************/
    SKP_Silk_range_encoder( psRC, psEncCtrlC->Seed, SKP_Silk_Seed_CDF );

    /*********************************************/
    /* Encode quantization indices of excitation */
    /*********************************************/
    SKP_Silk_encode_pulses( psRC, psEncCtrlC->sigtype, psEncCtrlC->QuantOffsetType, q, psEncC->frame_length );


    /*********************************************/
    /* Encode VAD flag                           */
    /*********************************************/
    SKP_Silk_range_encoder( psRC, psEncC->vadFlag, SKP_Silk_vadflag_CDF );
}