/* Encodes signs of excitation */
void SKP_Silk_encode_signs(
    SKP_Silk_range_coder_state      *sRC,               /* I/O  Range coder state                       */
    const SKP_int8                  q[],                /* I    Pulse signal                            */
    const SKP_int                   length,             /* I    Length of input                         */
    const SKP_int                   sigtype,            /* I    Signal type                             */
    const SKP_int                   QuantOffsetType,    /* I    Quantization offset type                */
    const SKP_int                   RateLevelIndex      /* I    Rate level index                        */
)
{
    SKP_int i;
    SKP_int inData;
    SKP_uint16 cdf[ 3 ];

    i = SKP_SMULBB( N_RATE_LEVELS - 1, SKP_LSHIFT( sigtype, 1 ) + QuantOffsetType ) + RateLevelIndex;
    cdf[ 0 ] = 0;
    cdf[ 1 ] = SKP_Silk_sign_CDF[ i ];
    cdf[ 2 ] = 65535;
    
    for( i = 0; i < length; i++ ) {
        if( q[ i ] != 0 ) {
            inData = SKP_enc_map( q[ i ] ); /* - = 0, + = 1 */
            SKP_Silk_range_encoder( sRC, inData, cdf );
        }
    }
}
/* Range encoder for multiple symbols */
void SKP_Silk_range_encoder_multi(
    SKP_Silk_range_coder_state      *psRC,              /* I/O  compressor data structure                   */
    const SKP_int                   data[],             /* I    uncompressed data    [nSymbols]             */
    const SKP_uint16 * const        prob[],             /* I    cumulative density functions                */
    const SKP_int                   nSymbols            /* I    number of data symbols                      */
)
{
    SKP_int k;
    for( k = 0; k < nSymbols; k++ ) {
        SKP_Silk_range_encoder( psRC, data[ k ], prob[ k ] );
    }
}
static inline void encode_split(SKP_Silk_range_coder_state * sRC,	/* I/O: compressor data structure                   */
			     const int p_child1,	/* I:   pulse amplitude of first child subframe     */
			     const int p,	/* I:   pulse amplitude of current subframe         */
			     const uint16_t * shell_table	/* I:   table of shell cdfs                         */
    )
{
	const uint16_t *cdf;

	if (p > 0) {
		cdf = &shell_table[SKP_Silk_shell_code_table_offsets[p]];
		SKP_Silk_range_encoder(sRC, p_child1, cdf);
	}
}
SKP_int SKP_Silk_encode_frame_FLP( 
    SKP_Silk_encoder_state_FLP      *psEnc,             /* I/O  Encoder state FLP                       */
          SKP_uint8                 *pCode,             /* O    Payload                                 */
          SKP_int16                 *pnBytesOut,        /* I/O  Number of payload bytes;                */
                                                        /*      input: max length; output: used         */
    const SKP_int16                 *pIn                /* I    Input speech frame                      */
)
{
    SKP_Silk_encoder_control_FLP sEncCtrl;
    SKP_int     k, nBytes, ret = 0;
    SKP_float   *x_frame, *res_pitch_frame;
    SKP_int16   pIn_HP[    MAX_FRAME_LENGTH ];
    SKP_int16   pIn_HP_LP[ MAX_FRAME_LENGTH ];
    SKP_float   xfw[       MAX_FRAME_LENGTH ];
    SKP_float   res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
    SKP_int     LBRR_idx, frame_terminator;

    /* Low bitrate redundancy parameters */
    SKP_uint8   LBRRpayload[ MAX_ARITHM_BYTES ];
    SKP_int16   nBytesLBRR;

    const SKP_uint16 *FrameTermination_CDF;


    sEncCtrl.sCmn.Seed = psEnc->sCmn.frameCounter++ & 3;
    /**************************************************************/
    /* Setup Input Pointers, and insert frame in input buffer    */
    /*************************************************************/
    /* pointers aligned with start of frame to encode */
    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 */
    /****************************/
    SKP_Silk_VAD_FLP( psEnc, &sEncCtrl, pIn );

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

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

    /*******************************************/
    /* Copy new frame to front of input buffer */
    /*******************************************/
    SKP_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, pIn_HP_LP, psEnc->sCmn.frame_length );

    /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */
    for( k = 0; k < 8; k++ ) {
        x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + k * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( k & 2 ) ) * 1e-6f;
    }

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

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

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

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

    /****************************************/
    /* Process gains                        */
    /****************************************/
    SKP_Silk_process_gains_FLP( psEnc, &sEncCtrl );
    
    /****************************************/
    /* Low Bitrate Redundant Encoding       */
    /****************************************/
    nBytesLBRR = MAX_ARITHM_BYTES;
    SKP_Silk_LBRR_encode_FLP( psEnc, &sEncCtrl, LBRRpayload, &nBytesLBRR, xfw );

    /*****************************************/
    /* Noise shaping quantization            */
    /*****************************************/
    SKP_Silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, xfw, psEnc->sCmn.q, 0 );

    /**************************************************/
    /* Convert speech activity into VAD and DTX flags */
    /**************************************************/
    if( psEnc->speech_activity < SPEECH_ACTIVITY_DTX_THRES ) {
        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 + NO_SPEECH_FRAMES_BEFORE_DTX ) {
            psEnc->sCmn.noSpeechCounter = NO_SPEECH_FRAMES_BEFORE_DTX;
            psEnc->sCmn.inDTX           = 0;
        }
    } else {
        psEnc->sCmn.noSpeechCounter = 0;
        psEnc->sCmn.inDTX           = 0;
        psEnc->sCmn.vadFlag         = VOICE_ACTIVITY;
    }

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

    /****************************************/
    /* Encode Parameters                    */
    /****************************************/
    SKP_Silk_encode_parameters( &psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC, psEnc->sCmn.q );
    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 + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( SKP_float ) );
    
    /* 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 );

        /* 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( SKP_uint8 ) );

            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( SKP_uint8 ) );
                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( SKP_uint8 ) );
            psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].nBytes = nBytesLBRR;
            /* The line below 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 );

        } else {
            /* Not enough space: Payload will be discarded */
            *pnBytesOut = 0;
            nBytes      = 0;
            ret = SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT;
        }

        /* Reset the number of frames in payload buffer */         
        psEnc->sCmn.nFramesInPayloadBuf = 0;
    } else {
        /* No payload 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 );
    }

    /* 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 */
    psEnc->BufferedInChannel_ms   += ( 8.0f * 1000.0f * ( nBytes - psEnc->sCmn.nBytesInPayloadBuf ) ) / psEnc->sCmn.TargetRate_bps;
    psEnc->BufferedInChannel_ms   -= FRAME_LENGTH_MS;
    psEnc->BufferedInChannel_ms    = SKP_LIMIT_float( psEnc->BufferedInChannel_ms, 0.0f, 100.0f );
    psEnc->sCmn.nBytesInPayloadBuf = nBytes;

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

    return( ret );
}
/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate           */
void SKP_Silk_LBRR_encode_FLP(
    SKP_Silk_encoder_state_FLP      *psEnc,             /* I/O  Encoder state FLP                       */
    SKP_Silk_encoder_control_FLP    *psEncCtrl,         /* I/O  Encoder control FLP                     */
          SKP_uint8                 *pCode,             /* O    Payload                                 */
          SKP_int16                 *pnBytesOut,        /* I/O  Payload bytes; in: max; out: used       */
    const SKP_float                 xfw[]               /* I    Input signal                            */
)
{
    SKP_int32   Gains_Q16[ NB_SUBFR ];
    SKP_int     k, TempGainsIndices[ NB_SUBFR ], frame_terminator;
    SKP_int     nBytes, nFramesInPayloadBuf;
    SKP_float   TempGains[ NB_SUBFR ];
    SKP_int     typeOffset, LTP_scaleIndex, Rate_only_parameters = 0;

    /* Control use of inband LBRR */
    SKP_Silk_LBRR_ctrl_FLP( psEnc, &psEncCtrl->sCmn );

    if( psEnc->sCmn.LBRR_enabled ) {
        /* Save original gains */
        SKP_memcpy( TempGainsIndices, psEncCtrl->sCmn.GainsIndices, NB_SUBFR * sizeof( SKP_int   ) );
        SKP_memcpy( TempGains,        psEncCtrl->Gains,             NB_SUBFR * sizeof( SKP_float ) );

        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 {
            SKP_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->sCmn.sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( SKP_Silk_nsq_state ) );
                psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;
                /* Increase Gains to get target LBRR rate */
                psEncCtrl->sCmn.GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases;
                psEncCtrl->sCmn.GainsIndices[ 0 ]  = SKP_LIMIT_int( psEncCtrl->sCmn.GainsIndices[ 0 ], 0, N_LEVELS_QGAIN - 1 );
            }
            /* Decode to get gains in sync with decoder */
            SKP_Silk_gains_dequant( Gains_Q16, psEncCtrl->sCmn.GainsIndices, 
                &psEnc->sCmn.LBRRprevLastGainIndex, psEnc->sCmn.nFramesInPayloadBuf );

            /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
            for( k = 0; k < NB_SUBFR; k++ ) {
                psEncCtrl->Gains[ k ] = Gains_Q16[ k ] / 65536.0f;
            }

            /*****************************************/
            /* Noise shaping quantization            */
            /*****************************************/
            SKP_Silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, xfw, psEnc->sCmn.q_LBRR, 1 );
        } else {
            SKP_memset( psEnc->sCmn.q_LBRR, 0, psEnc->sCmn.frame_length * sizeof( SKP_int8 ) );
            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                    */
        /****************************************/
        SKP_Silk_encode_parameters( &psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sCmn.sRC_LBRR, psEnc->sCmn.q_LBRR );

        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( 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 );

            /* 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( SKP_uint8 ) );
                
                *pnBytesOut = nBytes;               
            } else {
                /* Not enough space: Payload will be discarded */
                *pnBytesOut = 0;
                SKP_assert( 0 );
            }
        } else {
            /* No payload 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( SKP_int   ) );
        SKP_memcpy( psEncCtrl->Gains,             TempGains,        NB_SUBFR * sizeof( SKP_float ) );
    
        /* Restore LTP scale index and typeoffset */
        psEncCtrl->sCmn.LTP_scaleIndex = LTP_scaleIndex;
        psEnc->sCmn.typeOffsetPrev     = typeOffset;
    }
}
/* 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;
	}
}
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);
}
void SKP_Silk_encode_parameters_v4(
    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             */
)
{
    SKP_int   i, k, typeOffset;
    SKP_int   encode_absolute_lagIndex, delta_lagIndex;
    const SKP_Silk_NLSF_CB_struct *psNLSF_CB;


    /************************/
    /* Encode sampling rate */
    /************************/
    /* only done for first frame in packet */
    if( psEncC->nFramesInPayloadBuf == 0 ) {

        /* Initialize arithmetic coder */
        SKP_Silk_range_enc_init( &psEncC->sRC );
        psEncC->nBytesInPayloadBuf = 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 VAD flag                           */
    /*********************************************/
    SKP_Silk_range_encoder( psRC, psEncC->vadFlag, SKP_Silk_vadflag_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 */
        encode_absolute_lagIndex = 1;
        if( psEncC->nFramesInPayloadBuf > 0 && psEncC->prev_sigtype == SIG_TYPE_VOICED ) {
            /* Delta Encoding */
            delta_lagIndex = psEncCtrlC->lagIndex - psEncC->prev_lagIndex;
            if( delta_lagIndex > MAX_DELTA_LAG ) {
                delta_lagIndex = ( MAX_DELTA_LAG << 1 ) + 1;
            } else if ( delta_lagIndex < -MAX_DELTA_LAG ) {
                delta_lagIndex = ( MAX_DELTA_LAG << 1 ) + 1;
            } else {
                delta_lagIndex = delta_lagIndex + MAX_DELTA_LAG;
                encode_absolute_lagIndex = 0; /* Only use delta */
            }
            SKP_Silk_range_encoder( psRC, delta_lagIndex, SKP_Silk_pitch_delta_CDF );
        }
        if( encode_absolute_lagIndex ) {
            /* Absolute encoding */
            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 );
            }
        }
        psEncC->prev_lagIndex = psEncCtrlC->lagIndex;


        /* 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 */
void SKP_Silk_encode_pulses(
    SKP_Silk_range_coder_state      *psRC,          /* I/O  Range coder state               */
    const SKP_int                   sigtype,        /* I    Sigtype                         */
    const SKP_int                   QuantOffsetType,/* I    QuantOffsetType                 */
    const SKP_int8                  q[],            /* I    quantization indices            */
    const SKP_int                   frame_length    /* I    Frame length                    */
)
{
    SKP_int   i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0;
    SKP_int32 abs_q, minSumBits_Q6, sumBits_Q6;
    SKP_int   abs_pulses[ MAX_FRAME_LENGTH ];
    SKP_int   sum_pulses[ MAX_NB_SHELL_BLOCKS ];
    SKP_int   nRshifts[   MAX_NB_SHELL_BLOCKS ];
    SKP_int   pulses_comb[ 8 ];
    SKP_int   *abs_pulses_ptr;
    const SKP_int8 *pulses_ptr;
    const SKP_uint16 *cdf_ptr;
    const SKP_int16 *nBits_ptr;

    SKP_memset( pulses_comb, 0, 8 * sizeof( SKP_int ) ); // Fixing Valgrind reported problem

    /****************************/
    /* Prepare for shell coding */
    /****************************/
    /* Calculate number of shell blocks */
    iter = frame_length / SHELL_CODEC_FRAME_LENGTH;
    
    /* Take the absolute value of the pulses */
    for( i = 0; i < frame_length; i+=4 ) {
        abs_pulses[i+0] = ( SKP_int )SKP_abs( q[ i + 0 ] );
        abs_pulses[i+1] = ( SKP_int )SKP_abs( q[ i + 1 ] );
        abs_pulses[i+2] = ( SKP_int )SKP_abs( q[ i + 2 ] );
        abs_pulses[i+3] = ( SKP_int )SKP_abs( q[ i + 3 ] );
    }

    /* Calc sum pulses per shell code frame */
    abs_pulses_ptr = abs_pulses;
    for( i = 0; i < iter; i++ ) {
        nRshifts[ i ] = 0;

        while( 1 ) {
            /* 1+1 -> 2 */
            scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, SKP_Silk_max_pulses_table[ 0 ], 8 );

            /* 2+2 -> 4 */
            scale_down += combine_and_check( pulses_comb, pulses_comb, SKP_Silk_max_pulses_table[ 1 ], 4 );

            /* 4+4 -> 8 */
            scale_down += combine_and_check( pulses_comb, pulses_comb, SKP_Silk_max_pulses_table[ 2 ], 2 );

            /* 8+8 -> 16 */
            sum_pulses[ i ] = pulses_comb[ 0 ] + pulses_comb[ 1 ];
            if( sum_pulses[ i ] > SKP_Silk_max_pulses_table[ 3 ] ) {
                scale_down++;
            }

            if( scale_down ) {
                /* We need to down scale the quantization signal */
                nRshifts[ i ]++;                
                for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
                    abs_pulses_ptr[ k ] = SKP_RSHIFT( abs_pulses_ptr[ k ], 1 );
                }
            } else {
                /* Jump out of while(1) loop and go to next shell coding frame */
                break;
            }
        }
        abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH;
    }

    /**************/
    /* Rate level */
    /**************/
    /* find rate level that leads to fewest bits for coding of pulses per block info */
    minSumBits_Q6 = SKP_int32_MAX;
    for( k = 0; k < N_RATE_LEVELS - 1; k++ ) {
        nBits_ptr  = SKP_Silk_pulses_per_block_BITS_Q6[ k ];
        sumBits_Q6 = SKP_Silk_rate_levels_BITS_Q6[sigtype][ k ];
        for( i = 0; i < iter; i++ ) {
            if( nRshifts[ i ] > 0 ) {
                sumBits_Q6 += nBits_ptr[ MAX_PULSES + 1 ];
            } else {
                sumBits_Q6 += nBits_ptr[ sum_pulses[ i ] ];
            }
        }
        if( sumBits_Q6 < minSumBits_Q6 ) {
            minSumBits_Q6 = sumBits_Q6;
            RateLevelIndex = k;
        }
    }
    SKP_Silk_range_encoder( psRC, RateLevelIndex, SKP_Silk_rate_levels_CDF[ sigtype ] );

    /***************************************************/
    /* Sum-Weighted-Pulses Encoding                    */
    /***************************************************/
    cdf_ptr = SKP_Silk_pulses_per_block_CDF[ RateLevelIndex ];
    for( i = 0; i < iter; i++ ) {
        if( nRshifts[ i ] == 0 ) {
            SKP_Silk_range_encoder( psRC, sum_pulses[ i ], cdf_ptr );
        } else {
            SKP_Silk_range_encoder( psRC, MAX_PULSES + 1, cdf_ptr );
            for( k = 0; k < nRshifts[ i ] - 1; k++ ) {
                SKP_Silk_range_encoder( psRC, MAX_PULSES + 1, SKP_Silk_pulses_per_block_CDF[ N_RATE_LEVELS - 1 ] );
            }
            SKP_Silk_range_encoder( psRC, sum_pulses[ i ], SKP_Silk_pulses_per_block_CDF[ N_RATE_LEVELS - 1 ] );
        }
    }

    /******************/
    /* Shell Encoding */
    /******************/
    for( i = 0; i < iter; i++ ) {
        if( sum_pulses[ i ] > 0 ) {
            SKP_Silk_shell_encoder( psRC, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] );
        }
    }

    /****************/
    /* LSB Encoding */
    /****************/
    for( i = 0; i < iter; i++ ) {
        if( nRshifts[ i ] > 0 ) {
            pulses_ptr = &q[ i * SHELL_CODEC_FRAME_LENGTH ];
            nLS = nRshifts[ i ] - 1;
            for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
                abs_q = (SKP_int8)SKP_abs( pulses_ptr[ k ] );
                for( j = nLS; j > 0; j-- ) {
                    bit = SKP_RSHIFT( abs_q, j ) & 1;
                    SKP_Silk_range_encoder( psRC, bit, SKP_Silk_lsb_CDF );
                }
                bit = abs_q & 1;
                SKP_Silk_range_encoder( psRC, bit, SKP_Silk_lsb_CDF );
            }
        }
    }

    /****************/
    /* Encode signs */
    /****************/
    SKP_Silk_encode_signs( psRC, q, frame_length, sigtype, QuantOffsetType, RateLevelIndex );
}