예제 #1
0
opus_int silk_encode_frame_FLP(
    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
    opus_int32                      *pnBytesOut,                        /* O    Number of payload bytes;                    */
    ec_enc                          *psRangeEnc,                        /* I/O  compressor data structure                   */
    opus_int                        condCoding,                         /* I    The type of conditional coding to use       */
    opus_int                        maxBits,                            /* I    If > 0: maximum number of output bits       */
    opus_int                        useCBR                              /* I    Flag to force constant-bitrate operation    */
)
{
    silk_encoder_control_FLP sEncCtrl;
    opus_int     i, iter, maxIter, found_upper, found_lower, ret = 0;
    silk_float   *x_frame, *res_pitch_frame;
    silk_float   xfw[ MAX_FRAME_LENGTH ];
    silk_float   res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
    ec_enc       sRangeEnc_copy, sRangeEnc_copy2;
    silk_nsq_state sNSQ_copy, sNSQ_copy2;
    opus_int32   seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
    opus_int32   gainsID, gainsID_lower, gainsID_upper;
    opus_int16   gainMult_Q8;
    opus_int16   ec_prevLagIndex_copy;
    opus_int     ec_prevSignalType_copy;
    opus_int8    LastGainIndex_copy2;
    opus_int32   pGains_Q16[ MAX_NB_SUBFR ];
    opus_uint8   ec_buf_copy[ 1275 ];

    /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
    LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;

    psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;

    /**************************************************************/
    /* Set up Input Pointers, and insert frame in input buffer    */
    /**************************************************************/
    /* pointers aligned with start of frame to encode */
    x_frame         = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;    /* start of frame to encode */
    res_pitch_frame = res_pitch    + psEnc->sCmn.ltp_mem_length;    /* start of pitch LPC residual frame */

    /***************************************/
    /* Ensure smooth bandwidth transitions */
    /***************************************/
    silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );

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

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

    if( !psEnc->sCmn.prefillFlag ) {
        /*****************************************/
        /* Find pitch lags, initial LPC analysis */
        /*****************************************/
        silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame );

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

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

        /****************************************/
        /* Process gains                        */
        /****************************************/
        silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding );

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

        /****************************************/
        /* Low Bitrate Redundant Encoding       */
        /****************************************/
        silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding );

        /* Loop over quantizer and entroy coding to control bitrate */
        maxIter = 6;
        gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
        found_lower = 0;
        found_upper = 0;
        gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
        gainsID_lower = -1;
        gainsID_upper = -1;
        /* Copy part of the input state */
        silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
        silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
        seed_copy = psEnc->sCmn.indices.Seed;
        ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
        ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
        for( iter = 0; ; iter++ ) {
            if( gainsID == gainsID_lower ) {
                nBits = nBits_lower;
            } else if( gainsID == gainsID_upper ) {
                nBits = nBits_upper;
            } else {
                /* Restore part of the input state */
                if( iter > 0 ) {
                    silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
                    silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) );
                    psEnc->sCmn.indices.Seed = seed_copy;
                    psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
                    psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
                }

                /*****************************************/
                /* Noise shaping quantization            */
                /*****************************************/
                silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );

                /****************************************/
                /* Encode Parameters                    */
                /****************************************/
                silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );

                /****************************************/
                /* Encode Excitation Signal             */
                /****************************************/
                silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
                      psEnc->sCmn.pulses, psEnc->sCmn.frame_length );

                nBits = ec_tell( psRangeEnc );

                if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
                    break;
                }
            }

            if( iter == maxIter ) {
                if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
                    /* Restore output state from earlier iteration that did meet the bitrate budget */
                    silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
                    silk_assert( sRangeEnc_copy2.offs <= 1275 );
                    silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
                    silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
                    psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
                }
                break;
            }

            if( nBits > maxBits ) {
                if( found_lower == 0 && iter >= 2 ) {
                    /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
                    sEncCtrl.Lambda *= 1.5f;
                    found_upper = 0;
                    gainsID_upper = -1;
                } else {
                    found_upper = 1;
                    nBits_upper = nBits;
                    gainMult_upper = gainMult_Q8;
                    gainsID_upper = gainsID;
                }
            } else if( nBits < maxBits - 5 ) {
                found_lower = 1;
                nBits_lower = nBits;
                gainMult_lower = gainMult_Q8;
                if( gainsID != gainsID_lower ) {
                    gainsID_lower = gainsID;
                    /* Copy part of the output state */
                    silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
                    silk_assert( psRangeEnc->offs <= 1275 );
                    silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
                    silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
                    LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
                }
            } else {
                /* Within 5 bits of budget: close enough */
                break;
            }

            if( ( found_lower & found_upper ) == 0 ) {
                /* Adjust gain according to high-rate rate/distortion curve */
                opus_int32 gain_factor_Q16;
                gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
                gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
                if( nBits > maxBits ) {
                    gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
                }
                gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
            } else {
                /* Adjust gain by interpolating */
                gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );
                /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
                if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
                    gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
                } else
                if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
                    gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
                }
            }

            for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
                pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
            }

            /* Quantize gains */
            psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
            silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
                  &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );

            /* Unique identifier of gains vector */
            gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );

            /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
            for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
                sEncCtrl.Gains[ i ] = pGains_Q16[ i ] / 65536.0f;
            }
        }
    }

    /* Update input buffer */
    silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
        ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( silk_float ) );

    /* Parameters needed for next frame */
    psEnc->sCmn.prevLag        = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ];
    psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType;

    /* Exit without entropy coding */
    if( psEnc->sCmn.prefillFlag ) {
        /* No payload */
        *pnBytesOut = 0;
        return ret;
    }

    /****************************************/
    /* Finalize payload                     */
    /****************************************/
    psEnc->sCmn.first_frame_after_reset = 0;
    /* Payload size */
    *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );

    return ret;
}
예제 #2
0
int silk_encode_frame_FIX(silk_encoder_state_FIX * psEnc,	/* I/O  Pointer to Silk FIX encoder state                                           */
			       int32_t * pnBytesOut,	/* O    Pointer to number of payload bytes;                                         */
			       ec_enc * psRangeEnc,	/* I/O  compressor data structure                                                   */
			       int condCoding,	/* I    The type of conditional coding to use                                       */
			       int maxBits,	/* I    If > 0: maximum number of output bits                                       */
			       int useCBR	/* I    Flag to force constant-bitrate operation                                    */
    ) {
	silk_encoder_control_FIX sEncCtrl;
	int i, iter, maxIter, found_upper, found_lower, ret = 0;
	int16_t *x_frame;
	ec_enc sRangeEnc_copy, sRangeEnc_copy2;
	silk_nsq_state sNSQ_copy, sNSQ_copy2;
	int32_t seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower,
	    gainMult_upper;
	int32_t gainsID, gainsID_lower, gainsID_upper;
	int16_t gainMult_Q8;
	int16_t ec_prevLagIndex_copy;
	int ec_prevSignalType_copy;
	int8_t LastGainIndex_copy2;

	/* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
	LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower =
	    gainMult_upper = 0;

	psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;

    /**************************************************************/
	/* Set up Input Pointers, and insert frame in input buffer   */
    /*************************************************************/
	/* start of frame to encode */
	x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;

    /***************************************/
	/* Ensure smooth bandwidth transitions */
    /***************************************/
	silk_LP_variable_cutoff(&psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1,
				psEnc->sCmn.frame_length);

    /*******************************************/
	/* Copy new frame to front of input buffer */
    /*******************************************/
	memcpy(x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz,
		    psEnc->sCmn.inputBuf + 1,
		    psEnc->sCmn.frame_length * sizeof(int16_t));

	if (!psEnc->sCmn.prefillFlag) {

		int16_t *res_pitch_frame;

		int16_t res_pitch[psEnc->sCmn.la_pitch +
				     psEnc->sCmn.frame_length +
				     psEnc->sCmn.ltp_mem_length];
		/* start of pitch LPC residual frame */
		res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length;

	/*****************************************/
		/* Find pitch lags, initial LPC analysis */
	/*****************************************/
		silk_find_pitch_lags_FIX(psEnc, &sEncCtrl, res_pitch, x_frame,
					 psEnc->sCmn.arch);

	/************************/
		/* Noise shape analysis */
	/************************/
		silk_noise_shape_analysis_FIX(psEnc, &sEncCtrl, res_pitch_frame,
					      x_frame, psEnc->sCmn.arch);

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

	/****************************************/
		/* Process gains                        */
	/****************************************/
		silk_process_gains_FIX(psEnc, &sEncCtrl, condCoding);

	/*****************************************/
		/* Prefiltering for noise shaper         */
	/*****************************************/
		int32_t xfw_Q3[psEnc->sCmn.frame_length];
		silk_prefilter_FIX(psEnc, &sEncCtrl, xfw_Q3, x_frame);

	/****************************************/
		/* Low Bitrate Redundant Encoding       */
	/****************************************/
		silk_LBRR_encode_FIX(psEnc, &sEncCtrl, xfw_Q3, condCoding);

		/* Loop over quantizer and entropy coding to control bitrate */
		maxIter = 6;
		gainMult_Q8 = SILK_FIX_CONST(1, 8);
		found_lower = 0;
		found_upper = 0;
		gainsID =
		    silk_gains_ID(psEnc->sCmn.indices.GainsIndices,
				  psEnc->sCmn.nb_subfr);
		gainsID_lower = -1;
		gainsID_upper = -1;
		/* Copy part of the input state */
		memcpy(&sRangeEnc_copy, psRangeEnc, sizeof(ec_enc));
		memcpy(&sNSQ_copy, &psEnc->sCmn.sNSQ,
			    sizeof(silk_nsq_state));
		seed_copy = psEnc->sCmn.indices.Seed;
		ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
		ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
		uint8_t ec_buf_copy[1275];
		for (iter = 0;; iter++) {
			if (gainsID == gainsID_lower) {
				nBits = nBits_lower;
			} else if (gainsID == gainsID_upper) {
				nBits = nBits_upper;
			} else {
				/* Restore part of the input state */
				if (iter > 0) {
					memcpy(psRangeEnc, &sRangeEnc_copy,
						    sizeof(ec_enc));
					memcpy(&psEnc->sCmn.sNSQ,
						    &sNSQ_copy,
						    sizeof(silk_nsq_state));
					psEnc->sCmn.indices.Seed = seed_copy;
					psEnc->sCmn.ec_prevLagIndex =
					    ec_prevLagIndex_copy;
					psEnc->sCmn.ec_prevSignalType =
					    ec_prevSignalType_copy;
				}

		/*****************************************/
				/* Noise shaping quantization            */
		/*****************************************/
				if (psEnc->sCmn.nStatesDelayedDecision > 1
				    || psEnc->sCmn.warping_Q16 > 0) {
					silk_NSQ_del_dec(&psEnc->sCmn,
							 &psEnc->sCmn.sNSQ,
							 &psEnc->sCmn.indices,
							 xfw_Q3,
							 psEnc->sCmn.pulses,
							 sEncCtrl.
							 PredCoef_Q12[0],
							 sEncCtrl.LTPCoef_Q14,
							 sEncCtrl.AR2_Q13,
							 sEncCtrl.
							 HarmShapeGain_Q14,
							 sEncCtrl.Tilt_Q14,
							 sEncCtrl.LF_shp_Q14,
							 sEncCtrl.Gains_Q16,
							 sEncCtrl.pitchL,
							 sEncCtrl.Lambda_Q10,
							 sEncCtrl.
							 LTP_scale_Q14);
				} else {
					silk_NSQ(&psEnc->sCmn,
						 &psEnc->sCmn.sNSQ,
						 &psEnc->sCmn.indices, xfw_Q3,
						 psEnc->sCmn.pulses,
						 sEncCtrl.PredCoef_Q12[0],
						 sEncCtrl.LTPCoef_Q14,
						 sEncCtrl.AR2_Q13,
						 sEncCtrl.HarmShapeGain_Q14,
						 sEncCtrl.Tilt_Q14,
						 sEncCtrl.LF_shp_Q14,
						 sEncCtrl.Gains_Q16,
						 sEncCtrl.pitchL,
						 sEncCtrl.Lambda_Q10,
						 sEncCtrl.LTP_scale_Q14);
				}

		/****************************************/
				/* Encode Parameters                    */
		/****************************************/
				silk_encode_indices(&psEnc->sCmn, psRangeEnc,
						    psEnc->sCmn.nFramesEncoded,
						    0, condCoding);

		/****************************************/
				/* Encode Excitation Signal             */
		/****************************************/
				silk_encode_pulses(psRangeEnc,
						   psEnc->sCmn.indices.
						   signalType,
						   psEnc->sCmn.indices.
						   quantOffsetType,
						   psEnc->sCmn.pulses,
						   psEnc->sCmn.frame_length);

				nBits = ec_tell(psRangeEnc);

				if (useCBR == 0 && iter == 0
				    && nBits <= maxBits) {
					break;
				}
			}

			if (iter == maxIter) {
				if (found_lower
				    && (gainsID == gainsID_lower
					|| nBits > maxBits)) {
					/* Restore output state from earlier iteration that did meet the bitrate budget */
					memcpy(psRangeEnc,
						    &sRangeEnc_copy2,
						    sizeof(ec_enc));
					assert(sRangeEnc_copy2.offs <=
						    1275);
					memcpy(psRangeEnc->buf,
						    ec_buf_copy,
						    sRangeEnc_copy2.offs);
					memcpy(&psEnc->sCmn.sNSQ,
						    &sNSQ_copy2,
						    sizeof(silk_nsq_state));
					psEnc->sShape.LastGainIndex =
					    LastGainIndex_copy2;
				}
				break;
			}

			if (nBits > maxBits) {
				if (found_lower == 0 && iter >= 2) {
					/* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
					sEncCtrl.Lambda_Q10 =
					    silk_ADD_RSHIFT32(sEncCtrl.
							      Lambda_Q10,
							      sEncCtrl.
							      Lambda_Q10, 1);
					found_upper = 0;
					gainsID_upper = -1;
				} else {
					found_upper = 1;
					nBits_upper = nBits;
					gainMult_upper = gainMult_Q8;
					gainsID_upper = gainsID;
				}
			} else if (nBits < maxBits - 5) {
				found_lower = 1;
				nBits_lower = nBits;
				gainMult_lower = gainMult_Q8;
				if (gainsID != gainsID_lower) {
					gainsID_lower = gainsID;
					/* Copy part of the output state */
					memcpy(&sRangeEnc_copy2,
						    psRangeEnc, sizeof(ec_enc));
					assert(psRangeEnc->offs <= 1275);
					memcpy(ec_buf_copy,
						    psRangeEnc->buf,
						    psRangeEnc->offs);
					memcpy(&sNSQ_copy2,
						    &psEnc->sCmn.sNSQ,
						    sizeof(silk_nsq_state));
					LastGainIndex_copy2 =
					    psEnc->sShape.LastGainIndex;
				}
			} else {
				/* Within 5 bits of budget: close enough */
				break;
			}

			if ((found_lower & found_upper) == 0) {
				/* Adjust gain according to high-rate rate/distortion curve */
				int32_t gain_factor_Q16;
				gain_factor_Q16 =
				    silk_log2lin(silk_LSHIFT(nBits - maxBits, 7)
						 / psEnc->sCmn.frame_length +
						 SILK_FIX_CONST(16, 7));
				gain_factor_Q16 =
				    silk_min_32(gain_factor_Q16,
						SILK_FIX_CONST(2, 16));
				if (nBits > maxBits) {
					gain_factor_Q16 =
					    silk_max_32(gain_factor_Q16,
							SILK_FIX_CONST(1.3,
								       16));
				}
				gainMult_Q8 =
				    silk_SMULWB(gain_factor_Q16, gainMult_Q8);
			} else {
				/* Adjust gain by interpolating */
				assert(nBits_upper != nBits_lower);
				gainMult_Q8 =
				    gainMult_lower +
				    silk_DIV32_16(silk_MUL
						  (gainMult_upper -
						   gainMult_lower,
						   maxBits - nBits_lower),
						  nBits_upper - nBits_lower);
				/* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
				if (gainMult_Q8 >
				    silk_ADD_RSHIFT32(gainMult_lower,
						      gainMult_upper -
						      gainMult_lower, 2)) {
					gainMult_Q8 =
					    silk_ADD_RSHIFT32(gainMult_lower,
							      gainMult_upper -
							      gainMult_lower,
							      2);
				} else if (gainMult_Q8 <
					   silk_SUB_RSHIFT32(gainMult_upper,
							     gainMult_upper -
							     gainMult_lower,
							     2)) {
					gainMult_Q8 =
					    silk_SUB_RSHIFT32(gainMult_upper,
							      gainMult_upper -
							      gainMult_lower,
							      2);
				}
			}

			for (i = 0; i < psEnc->sCmn.nb_subfr; i++) {
				sEncCtrl.Gains_Q16[i] =
				    silk_LSHIFT_SAT32(silk_SMULWB
						      (sEncCtrl.GainsUnq_Q16[i],
						       gainMult_Q8), 8);
			}

			/* Quantize gains */
			psEnc->sShape.LastGainIndex =
			    sEncCtrl.lastGainIndexPrev;
			silk_gains_quant(psEnc->sCmn.indices.GainsIndices,
					 sEncCtrl.Gains_Q16,
					 &psEnc->sShape.LastGainIndex,
					 condCoding == CODE_CONDITIONALLY,
					 psEnc->sCmn.nb_subfr);

			/* Unique identifier of gains vector */
			gainsID =
			    silk_gains_ID(psEnc->sCmn.indices.GainsIndices,
					  psEnc->sCmn.nb_subfr);
		}
	}

	/* Update input buffer */
	memmove(psEnc->x_buf, &psEnc->x_buf[psEnc->sCmn.frame_length],
		(psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz) * sizeof(int16_t));

	/* Exit without entropy coding */
	if (psEnc->sCmn.prefillFlag) {
		/* No payload */
		*pnBytesOut = 0;

		return ret;
	}

	/* Parameters needed for next frame */
	psEnc->sCmn.prevLag = sEncCtrl.pitchL[psEnc->sCmn.nb_subfr - 1];
	psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType;

    /****************************************/
	/* Finalize payload                     */
    /****************************************/
	psEnc->sCmn.first_frame_after_reset = 0;
	/* Payload size */
	*pnBytesOut = silk_RSHIFT(ec_tell(psRangeEnc) + 7, 3);

	return ret;
}