/// <summary> /// Encode side-information parameters to payload /// </summary> /// <param name="psEncC">I/O Encoder state</param> /// <param name="psRangeEnc">I/O Compressor data structure</param> /// <param name="FrameIndex">I Frame number</param> /// <param name="encode_LBRR">I Flag indicating LBRR data is being encoded</param> /// <param name="condCoding">I The type of conditional coding to use</param> internal static void silk_encode_indices( SilkChannelEncoder psEncC, EntropyCoder psRangeEnc, int FrameIndex, int encode_LBRR, int condCoding) { int i, k, typeOffset; int encode_absolute_lagIndex, delta_lagIndex; short[] ec_ix = new short[SilkConstants.MAX_LPC_ORDER]; byte[] pred_Q8 = new byte[SilkConstants.MAX_LPC_ORDER]; SideInfoIndices psIndices; if (encode_LBRR != 0) { psIndices = psEncC.indices_LBRR[FrameIndex]; } else { psIndices = psEncC.indices; } /*******************************************/ /* Encode signal type and quantizer offset */ /*******************************************/ typeOffset = 2 * psIndices.signalType + psIndices.quantOffsetType; Inlines.OpusAssert(typeOffset >= 0 && typeOffset < 6); Inlines.OpusAssert(encode_LBRR == 0 || typeOffset >= 2); if (encode_LBRR != 0 || typeOffset >= 2) { psRangeEnc.enc_icdf(typeOffset - 2, Tables.silk_type_offset_VAD_iCDF, 8); } else { psRangeEnc.enc_icdf(typeOffset, Tables.silk_type_offset_no_VAD_iCDF, 8); } /****************/ /* Encode gains */ /****************/ /* first subframe */ if (condCoding == SilkConstants.CODE_CONDITIONALLY) { /* conditional coding */ Inlines.OpusAssert(psIndices.GainsIndices[0] >= 0 && psIndices.GainsIndices[0] < SilkConstants.MAX_DELTA_GAIN_QUANT - SilkConstants.MIN_DELTA_GAIN_QUANT + 1); psRangeEnc.enc_icdf(psIndices.GainsIndices[0], Tables.silk_delta_gain_iCDF, 8); } else { /* independent coding, in two stages: MSB bits followed by 3 LSBs */ Inlines.OpusAssert(psIndices.GainsIndices[0] >= 0 && psIndices.GainsIndices[0] < SilkConstants.N_LEVELS_QGAIN); psRangeEnc.enc_icdf(Inlines.silk_RSHIFT(psIndices.GainsIndices[0], 3), Tables.silk_gain_iCDF[psIndices.signalType], 8); psRangeEnc.enc_icdf(psIndices.GainsIndices[0] & 7, Tables.silk_uniform8_iCDF, 8); } /* remaining subframes */ for (i = 1; i < psEncC.nb_subfr; i++) { Inlines.OpusAssert(psIndices.GainsIndices[i] >= 0 && psIndices.GainsIndices[i] < SilkConstants.MAX_DELTA_GAIN_QUANT - SilkConstants.MIN_DELTA_GAIN_QUANT + 1); psRangeEnc.enc_icdf(psIndices.GainsIndices[i], Tables.silk_delta_gain_iCDF, 8); } /****************/ /* Encode NLSFs */ /****************/ psRangeEnc.enc_icdf(psIndices.NLSFIndices[0], psEncC.psNLSF_CB.CB1_iCDF, ((psIndices.signalType >> 1) * psEncC.psNLSF_CB.nVectors), 8); NLSF.silk_NLSF_unpack(ec_ix, pred_Q8, psEncC.psNLSF_CB, psIndices.NLSFIndices[0]); Inlines.OpusAssert(psEncC.psNLSF_CB.order == psEncC.predictLPCOrder); for (i = 0; i < psEncC.psNLSF_CB.order; i++) { if (psIndices.NLSFIndices[i + 1] >= SilkConstants.NLSF_QUANT_MAX_AMPLITUDE) { psRangeEnc.enc_icdf(2 * SilkConstants.NLSF_QUANT_MAX_AMPLITUDE, psEncC.psNLSF_CB.ec_iCDF, (ec_ix[i]), 8); psRangeEnc.enc_icdf(psIndices.NLSFIndices[i + 1] - SilkConstants.NLSF_QUANT_MAX_AMPLITUDE, Tables.silk_NLSF_EXT_iCDF, 8); } else if (psIndices.NLSFIndices[i + 1] <= 0 - SilkConstants.NLSF_QUANT_MAX_AMPLITUDE) { psRangeEnc.enc_icdf(0, psEncC.psNLSF_CB.ec_iCDF, ec_ix[i], 8); psRangeEnc.enc_icdf(-psIndices.NLSFIndices[i + 1] - SilkConstants.NLSF_QUANT_MAX_AMPLITUDE, Tables.silk_NLSF_EXT_iCDF, 8); } else { psRangeEnc.enc_icdf(psIndices.NLSFIndices[i + 1] + SilkConstants.NLSF_QUANT_MAX_AMPLITUDE, psEncC.psNLSF_CB.ec_iCDF, ec_ix[i], 8); } } /* Encode NLSF interpolation factor */ if (psEncC.nb_subfr == SilkConstants.MAX_NB_SUBFR) { Inlines.OpusAssert(psIndices.NLSFInterpCoef_Q2 >= 0 && psIndices.NLSFInterpCoef_Q2 < 5); psRangeEnc.enc_icdf(psIndices.NLSFInterpCoef_Q2, Tables.silk_NLSF_interpolation_factor_iCDF, 8); } if (psIndices.signalType == SilkConstants.TYPE_VOICED) { /*********************/ /* Encode pitch lags */ /*********************/ /* lag index */ encode_absolute_lagIndex = 1; if (condCoding == SilkConstants.CODE_CONDITIONALLY && psEncC.ec_prevSignalType == SilkConstants.TYPE_VOICED) { /* Delta Encoding */ delta_lagIndex = psIndices.lagIndex - psEncC.ec_prevLagIndex; if (delta_lagIndex < -8 || delta_lagIndex > 11) { delta_lagIndex = 0; } else { delta_lagIndex = delta_lagIndex + 9; encode_absolute_lagIndex = 0; /* Only use delta */ } Inlines.OpusAssert(delta_lagIndex >= 0 && delta_lagIndex < 21); psRangeEnc.enc_icdf(delta_lagIndex, Tables.silk_pitch_delta_iCDF, 8); } if (encode_absolute_lagIndex != 0) { /* Absolute encoding */ int pitch_high_bits, pitch_low_bits; pitch_high_bits = Inlines.silk_DIV32_16(psIndices.lagIndex, Inlines.silk_RSHIFT(psEncC.fs_kHz, 1)); pitch_low_bits = psIndices.lagIndex - Inlines.silk_SMULBB(pitch_high_bits, Inlines.silk_RSHIFT(psEncC.fs_kHz, 1)); Inlines.OpusAssert(pitch_low_bits < psEncC.fs_kHz / 2); Inlines.OpusAssert(pitch_high_bits < 32); psRangeEnc.enc_icdf(pitch_high_bits, Tables.silk_pitch_lag_iCDF, 8); psRangeEnc.enc_icdf(pitch_low_bits, psEncC.pitch_lag_low_bits_iCDF, 8); } psEncC.ec_prevLagIndex = psIndices.lagIndex; /* Countour index */ Inlines.OpusAssert(psIndices.contourIndex >= 0); Inlines.OpusAssert((psIndices.contourIndex < 34 && psEncC.fs_kHz > 8 && psEncC.nb_subfr == 4) || (psIndices.contourIndex < 11 && psEncC.fs_kHz == 8 && psEncC.nb_subfr == 4) || (psIndices.contourIndex < 12 && psEncC.fs_kHz > 8 && psEncC.nb_subfr == 2) || (psIndices.contourIndex < 3 && psEncC.fs_kHz == 8 && psEncC.nb_subfr == 2)); psRangeEnc.enc_icdf(psIndices.contourIndex, psEncC.pitch_contour_iCDF, 8); /********************/ /* Encode LTP gains */ /********************/ /* PERIndex value */ Inlines.OpusAssert(psIndices.PERIndex >= 0 && psIndices.PERIndex < 3); psRangeEnc.enc_icdf(psIndices.PERIndex, Tables.silk_LTP_per_index_iCDF, 8); /* Codebook Indices */ for (k = 0; k < psEncC.nb_subfr; k++) { Inlines.OpusAssert(psIndices.LTPIndex[k] >= 0 && psIndices.LTPIndex[k] < (8 << psIndices.PERIndex)); psRangeEnc.enc_icdf(psIndices.LTPIndex[k], Tables.silk_LTP_gain_iCDF_ptrs[psIndices.PERIndex], 8); } /**********************/ /* Encode LTP scaling */ /**********************/ if (condCoding == SilkConstants.CODE_INDEPENDENTLY) { Inlines.OpusAssert(psIndices.LTP_scaleIndex >= 0 && psIndices.LTP_scaleIndex < 3); psRangeEnc.enc_icdf(psIndices.LTP_scaleIndex, Tables.silk_LTPscale_iCDF, 8); } Inlines.OpusAssert(condCoding == 0 || psIndices.LTP_scaleIndex == 0); } psEncC.ec_prevSignalType = psIndices.signalType; /***************/ /* Encode seed */ /***************/ Inlines.OpusAssert(psIndices.Seed >= 0 && psIndices.Seed < 4); psRangeEnc.enc_icdf(psIndices.Seed, Tables.silk_uniform4_iCDF, 8); }
/* Decode side-information parameters from payload */ internal static void silk_decode_indices( SilkChannelDecoder psDec, /* I/O State */ EntropyCoder psRangeDec, /* I/O Compressor data structure */ int FrameIndex, /* I Frame number */ int decode_LBRR, /* I Flag indicating LBRR data is being decoded */ int condCoding /* I The type of conditional coding to use */ ) { int i, k, Ix; int decode_absolute_lagIndex, delta_lagIndex; short[] ec_ix = new short[psDec.LPC_order]; byte[] pred_Q8 = new byte[psDec.LPC_order]; /*******************************************/ /* Decode signal type and quantizer offset */ /*******************************************/ if (decode_LBRR != 0 || psDec.VAD_flags[FrameIndex] != 0) { Ix = psRangeDec.dec_icdf(Tables.silk_type_offset_VAD_iCDF, 8) + 2; } else { Ix = psRangeDec.dec_icdf(Tables.silk_type_offset_no_VAD_iCDF, 8); } psDec.indices.signalType = (sbyte)Inlines.silk_RSHIFT(Ix, 1); psDec.indices.quantOffsetType = (sbyte)(Ix & 1); /****************/ /* Decode gains */ /****************/ /* First subframe */ if (condCoding == SilkConstants.CODE_CONDITIONALLY) { /* Conditional coding */ psDec.indices.GainsIndices[0] = (sbyte)psRangeDec.dec_icdf(Tables.silk_delta_gain_iCDF, 8); } else { /* Independent coding, in two stages: MSB bits followed by 3 LSBs */ psDec.indices.GainsIndices[0] = (sbyte)Inlines.silk_LSHIFT(psRangeDec.dec_icdf(Tables.silk_gain_iCDF[psDec.indices.signalType], 8), 3); psDec.indices.GainsIndices[0] += (sbyte)psRangeDec.dec_icdf(Tables.silk_uniform8_iCDF, 8); } /* Remaining subframes */ for (i = 1; i < psDec.nb_subfr; i++) { psDec.indices.GainsIndices[i] = (sbyte)psRangeDec.dec_icdf(Tables.silk_delta_gain_iCDF, 8); } /**********************/ /* Decode LSF Indices */ /**********************/ psDec.indices.NLSFIndices[0] = (sbyte)psRangeDec.dec_icdf(psDec.psNLSF_CB.CB1_iCDF, (psDec.indices.signalType >> 1) * psDec.psNLSF_CB.nVectors, 8); NLSF.silk_NLSF_unpack(ec_ix, pred_Q8, psDec.psNLSF_CB, psDec.indices.NLSFIndices[0]); Inlines.OpusAssert(psDec.psNLSF_CB.order == psDec.LPC_order); for (i = 0; i < psDec.psNLSF_CB.order; i++) { Ix = psRangeDec.dec_icdf(psDec.psNLSF_CB.ec_iCDF, (ec_ix[i]), 8); if (Ix == 0) { Ix -= psRangeDec.dec_icdf(Tables.silk_NLSF_EXT_iCDF, 8); } else if (Ix == 2 * SilkConstants.NLSF_QUANT_MAX_AMPLITUDE) { Ix += psRangeDec.dec_icdf(Tables.silk_NLSF_EXT_iCDF, 8); } psDec.indices.NLSFIndices[i + 1] = (sbyte)(Ix - SilkConstants.NLSF_QUANT_MAX_AMPLITUDE); } /* Decode LSF interpolation factor */ if (psDec.nb_subfr == SilkConstants.MAX_NB_SUBFR) { psDec.indices.NLSFInterpCoef_Q2 = (sbyte)psRangeDec.dec_icdf(Tables.silk_NLSF_interpolation_factor_iCDF, 8); } else { psDec.indices.NLSFInterpCoef_Q2 = 4; } if (psDec.indices.signalType == SilkConstants.TYPE_VOICED) { /*********************/ /* Decode pitch lags */ /*********************/ /* Get lag index */ decode_absolute_lagIndex = 1; if (condCoding == SilkConstants.CODE_CONDITIONALLY && psDec.ec_prevSignalType == SilkConstants.TYPE_VOICED) { /* Decode Delta index */ delta_lagIndex = (short)psRangeDec.dec_icdf(Tables.silk_pitch_delta_iCDF, 8); if (delta_lagIndex > 0) { delta_lagIndex = delta_lagIndex - 9; psDec.indices.lagIndex = (short)(psDec.ec_prevLagIndex + delta_lagIndex); decode_absolute_lagIndex = 0; } } if (decode_absolute_lagIndex != 0) { /* Absolute decoding */ psDec.indices.lagIndex = (short)(psRangeDec.dec_icdf(Tables.silk_pitch_lag_iCDF, 8) * Inlines.silk_RSHIFT(psDec.fs_kHz, 1)); psDec.indices.lagIndex += (short)psRangeDec.dec_icdf(psDec.pitch_lag_low_bits_iCDF, 8); } psDec.ec_prevLagIndex = psDec.indices.lagIndex; /* Get countour index */ psDec.indices.contourIndex = (sbyte)psRangeDec.dec_icdf(psDec.pitch_contour_iCDF, 8); /********************/ /* Decode LTP gains */ /********************/ /* Decode PERIndex value */ psDec.indices.PERIndex = (sbyte)psRangeDec.dec_icdf(Tables.silk_LTP_per_index_iCDF, 8); for (k = 0; k < psDec.nb_subfr; k++) { psDec.indices.LTPIndex[k] = (sbyte)psRangeDec.dec_icdf(Tables.silk_LTP_gain_iCDF_ptrs[psDec.indices.PERIndex], 8); } /**********************/ /* Decode LTP scaling */ /**********************/ if (condCoding == SilkConstants.CODE_INDEPENDENTLY) { psDec.indices.LTP_scaleIndex = (sbyte)psRangeDec.dec_icdf(Tables.silk_LTPscale_iCDF, 8); } else { psDec.indices.LTP_scaleIndex = 0; } } psDec.ec_prevSignalType = psDec.indices.signalType; /***************/ /* Decode seed */ /***************/ psDec.indices.Seed = (sbyte)psRangeDec.dec_icdf(Tables.silk_uniform4_iCDF, 8); }