Esempio n. 1
0
        /// <summary>
        /// Updates CNG estimate, and applies the CNG when packet was lost
        /// </summary>
        /// <param name="psDec">I/O  Decoder state</param>
        /// <param name="psDecCtrl">I/O  Decoder control</param>
        /// <param name="frame">I/O  Signal</param>
        /// <param name="length">I    Length of residual</param>
        internal static void silk_CNG(
            SilkChannelDecoder psDec,
            SilkDecoderControl psDecCtrl,
            short[] frame,
            int frame_ptr,
            int length)
        {
            int i, subfr;
            int sum_Q6, max_Gain_Q16, gain_Q16;

            short[]  A_Q12 = new short[psDec.LPC_order];
            CNGState psCNG = psDec.sCNG;

            if (psDec.fs_kHz != psCNG.fs_kHz)
            {
                /* Reset state */
                silk_CNG_Reset(psDec);

                psCNG.fs_kHz = psDec.fs_kHz;
            }

            if (psDec.lossCnt == 0 && psDec.prevSignalType == SilkConstants.TYPE_NO_VOICE_ACTIVITY)
            {
                /* Update CNG parameters */

                /* Smoothing of LSF's  */
                for (i = 0; i < psDec.LPC_order; i++)
                {
                    psCNG.CNG_smth_NLSF_Q15[i] += (short)(Inlines.silk_SMULWB((int)psDec.prevNLSF_Q15[i] - (int)psCNG.CNG_smth_NLSF_Q15[i], SilkConstants.CNG_NLSF_SMTH_Q16));
                }

                /* Find the subframe with the highest gain */
                max_Gain_Q16 = 0;
                subfr        = 0;
                for (i = 0; i < psDec.nb_subfr; i++)
                {
                    if (psDecCtrl.Gains_Q16[i] > max_Gain_Q16)
                    {
                        max_Gain_Q16 = psDecCtrl.Gains_Q16[i];
                        subfr        = i;
                    }
                }

                /* Update CNG excitation buffer with excitation from this subframe */
                Arrays.MemMoveInt(psCNG.CNG_exc_buf_Q14, 0, psDec.subfr_length, (psDec.nb_subfr - 1) * psDec.subfr_length);

                /* Smooth gains */
                for (i = 0; i < psDec.nb_subfr; i++)
                {
                    psCNG.CNG_smth_Gain_Q16 += Inlines.silk_SMULWB(psDecCtrl.Gains_Q16[i] - psCNG.CNG_smth_Gain_Q16, SilkConstants.CNG_GAIN_SMTH_Q16);
                }
            }

            /* Add CNG when packet is lost or during DTX */
            if (psDec.lossCnt != 0)
            {
                int[] CNG_sig_Q10 = new int[length + SilkConstants.MAX_LPC_ORDER];

                /* Generate CNG excitation */
                gain_Q16 = Inlines.silk_SMULWW(psDec.sPLC.randScale_Q14, psDec.sPLC.prevGain_Q16[1]);
                if (gain_Q16 >= (1 << 21) || psCNG.CNG_smth_Gain_Q16 > (1 << 23))
                {
                    gain_Q16 = Inlines.silk_SMULTT(gain_Q16, gain_Q16);
                    gain_Q16 = Inlines.silk_SUB_LSHIFT32(Inlines.silk_SMULTT(psCNG.CNG_smth_Gain_Q16, psCNG.CNG_smth_Gain_Q16), gain_Q16, 5);
                    gain_Q16 = Inlines.silk_LSHIFT32(Inlines.silk_SQRT_APPROX(gain_Q16), 16);
                }
                else
                {
                    gain_Q16 = Inlines.silk_SMULWW(gain_Q16, gain_Q16);
                    gain_Q16 = Inlines.silk_SUB_LSHIFT32(Inlines.silk_SMULWW(psCNG.CNG_smth_Gain_Q16, psCNG.CNG_smth_Gain_Q16), gain_Q16, 5);
                    gain_Q16 = Inlines.silk_LSHIFT32(Inlines.silk_SQRT_APPROX(gain_Q16), 8);
                }
                silk_CNG_exc(CNG_sig_Q10, SilkConstants.MAX_LPC_ORDER, psCNG.CNG_exc_buf_Q14, gain_Q16, length, ref psCNG.rand_seed);

                /* Convert CNG NLSF to filter representation */
                NLSF.silk_NLSF2A(A_Q12, psCNG.CNG_smth_NLSF_Q15, psDec.LPC_order);

                /* Generate CNG signal, by synthesis filtering */
                Array.Copy(psCNG.CNG_synth_state, CNG_sig_Q10, SilkConstants.MAX_LPC_ORDER);

                for (i = 0; i < length; i++)
                {
                    int lpci = SilkConstants.MAX_LPC_ORDER + i;
                    Inlines.OpusAssert(psDec.LPC_order == 10 || psDec.LPC_order == 16);
                    /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
                    sum_Q6 = Inlines.silk_RSHIFT(psDec.LPC_order, 1);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 1], A_Q12[0]);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 2], A_Q12[1]);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 3], A_Q12[2]);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 4], A_Q12[3]);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 5], A_Q12[4]);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 6], A_Q12[5]);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 7], A_Q12[6]);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 8], A_Q12[7]);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 9], A_Q12[8]);
                    sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 10], A_Q12[9]);

                    if (psDec.LPC_order == 16)
                    {
                        sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 11], A_Q12[10]);
                        sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 12], A_Q12[11]);
                        sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 13], A_Q12[12]);
                        sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 14], A_Q12[13]);
                        sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 15], A_Q12[14]);
                        sum_Q6 = Inlines.silk_SMLAWB(sum_Q6, CNG_sig_Q10[lpci - 16], A_Q12[15]);
                    }

                    /* Update states */
                    CNG_sig_Q10[lpci] = Inlines.silk_ADD_LSHIFT(CNG_sig_Q10[lpci], sum_Q6, 4);

                    frame[frame_ptr + i] = Inlines.silk_ADD_SAT16(frame[frame_ptr + i], (short)(Inlines.silk_RSHIFT_ROUND(CNG_sig_Q10[lpci], 10)));
                }

                Array.Copy(CNG_sig_Q10, length, psCNG.CNG_synth_state, 0, SilkConstants.MAX_LPC_ORDER);
            }
            else
            {
                Arrays.MemSetInt(psCNG.CNG_synth_state, 0, psDec.LPC_order);
            }
        }
Esempio n. 2
0
        /* Finds LPC vector from correlations, and converts to NLSF */
        internal static void silk_find_LPC(
            SilkChannelEncoder psEncC,                  /* I/O  Encoder state                                                               */
            short[] NLSF_Q15,                           /* O    NLSFs                                                                       */
            short[] x,                                  /* I    Input signal                                                                */
            int minInvGain_Q30                          /* I    Inverse of max prediction gain                                              */
            )
        {
            int k, subfr_length;

            int[]         a_Q16 = new int[SilkConstants.MAX_LPC_ORDER];
            int           isInterpLower, shift;
            int           res_nrg0, res_nrg1;
            int           rshift0, rshift1;
            BoxedValueInt scratch_box1 = new BoxedValueInt();
            BoxedValueInt scratch_box2 = new BoxedValueInt();

            /* Used only for LSF interpolation */
            int[] a_tmp_Q16 = new int[SilkConstants.MAX_LPC_ORDER];
            int   res_nrg_interp, res_nrg, res_tmp_nrg;
            int   res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q;

            short[] a_tmp_Q12 = new short[SilkConstants.MAX_LPC_ORDER];
            short[] NLSF0_Q15 = new short[SilkConstants.MAX_LPC_ORDER];

            subfr_length = psEncC.subfr_length + psEncC.predictLPCOrder;

            /* Default: no interpolation */
            psEncC.indices.NLSFInterpCoef_Q2 = 4;

            /* Burg AR analysis for the full frame */
            BurgModified.silk_burg_modified(scratch_box1, scratch_box2, a_Q16, x, 0, minInvGain_Q30, subfr_length, psEncC.nb_subfr, psEncC.predictLPCOrder);
            res_nrg   = scratch_box1.Val;
            res_nrg_Q = scratch_box2.Val;

            if (psEncC.useInterpolatedNLSFs != 0 && psEncC.first_frame_after_reset == 0 && psEncC.nb_subfr == SilkConstants.MAX_NB_SUBFR)
            {
                short[] LPC_res;

                /* Optimal solution for last 10 ms */
                BurgModified.silk_burg_modified(scratch_box1, scratch_box2, a_tmp_Q16, x, (2 * subfr_length), minInvGain_Q30, subfr_length, 2, psEncC.predictLPCOrder);
                res_tmp_nrg   = scratch_box1.Val;
                res_tmp_nrg_Q = scratch_box2.Val;

                /* subtract residual energy here, as that's easier than adding it to the    */
                /* residual energy of the first 10 ms in each iteration of the search below */
                shift = res_tmp_nrg_Q - res_nrg_Q;
                if (shift >= 0)
                {
                    if (shift < 32)
                    {
                        res_nrg = res_nrg - Inlines.silk_RSHIFT(res_tmp_nrg, shift);
                    }
                }
                else
                {
                    Inlines.OpusAssert(shift > -32);
                    res_nrg   = Inlines.silk_RSHIFT(res_nrg, -shift) - res_tmp_nrg;
                    res_nrg_Q = res_tmp_nrg_Q;
                }

                /* Convert to NLSFs */
                NLSF.silk_A2NLSF(NLSF_Q15, a_tmp_Q16, psEncC.predictLPCOrder);

                LPC_res = new short[2 * subfr_length];

                /* Search over interpolation indices to find the one with lowest residual energy */
                for (k = 3; k >= 0; k--)
                {
                    /* Interpolate NLSFs for first half */
                    Inlines.silk_interpolate(NLSF0_Q15, psEncC.prev_NLSFq_Q15, NLSF_Q15, k, psEncC.predictLPCOrder);

                    /* Convert to LPC for residual energy evaluation */
                    NLSF.silk_NLSF2A(a_tmp_Q12, NLSF0_Q15, psEncC.predictLPCOrder);

                    /* Calculate residual energy with NLSF interpolation */
                    Filters.silk_LPC_analysis_filter(LPC_res, 0, x, 0, a_tmp_Q12, 0, 2 * subfr_length, psEncC.predictLPCOrder);

                    SumSqrShift.silk_sum_sqr_shift(out res_nrg0, out rshift0, LPC_res, psEncC.predictLPCOrder, subfr_length - psEncC.predictLPCOrder);

                    SumSqrShift.silk_sum_sqr_shift(out res_nrg1, out rshift1, LPC_res, psEncC.predictLPCOrder + subfr_length, subfr_length - psEncC.predictLPCOrder);

                    /* Add subframe energies from first half frame */
                    shift = rshift0 - rshift1;
                    if (shift >= 0)
                    {
                        res_nrg1         = Inlines.silk_RSHIFT(res_nrg1, shift);
                        res_nrg_interp_Q = -rshift0;
                    }
                    else
                    {
                        res_nrg0         = Inlines.silk_RSHIFT(res_nrg0, -shift);
                        res_nrg_interp_Q = -rshift1;
                    }
                    res_nrg_interp = Inlines.silk_ADD32(res_nrg0, res_nrg1);

                    /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */
                    shift = res_nrg_interp_Q - res_nrg_Q;
                    if (shift >= 0)
                    {
                        if (Inlines.silk_RSHIFT(res_nrg_interp, shift) < res_nrg)
                        {
                            isInterpLower = (true ? 1 : 0);
                        }
                        else
                        {
                            isInterpLower = (false ? 1 : 0);
                        }
                    }
                    else
                    {
                        if (-shift < 32)
                        {
                            if (res_nrg_interp < Inlines.silk_RSHIFT(res_nrg, -shift))
                            {
                                isInterpLower = (true ? 1 : 0);
                            }
                            else
                            {
                                isInterpLower = (false ? 1 : 0);
                            }
                        }
                        else
                        {
                            isInterpLower = (false ? 1 : 0);
                        }
                    }

                    /* Determine whether current interpolated NLSFs are best so far */
                    if (isInterpLower == (true ? 1 : 0))
                    {
                        /* Interpolation has lower residual energy */
                        res_nrg   = res_nrg_interp;
                        res_nrg_Q = res_nrg_interp_Q;
                        psEncC.indices.NLSFInterpCoef_Q2 = (sbyte)k;
                    }
                }
            }

            if (psEncC.indices.NLSFInterpCoef_Q2 == 4)
            {
                /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */
                NLSF.silk_A2NLSF(NLSF_Q15, a_Q16, psEncC.predictLPCOrder);
            }

            Inlines.OpusAssert(psEncC.indices.NLSFInterpCoef_Q2 == 4 || (psEncC.useInterpolatedNLSFs != 0 && psEncC.first_frame_after_reset == 0 && psEncC.nb_subfr == SilkConstants.MAX_NB_SUBFR));
        }
Esempio n. 3
0
        /* Decode parameters from payload */
        internal static void silk_decode_parameters(
            SilkChannelDecoder psDec,           /* I/O  State                                       */
            SilkDecoderControl psDecCtrl,       /* I/O  Decoder control                             */
            int condCoding                      /* I    The type of conditional coding to use       */
            )
        {
            int i, k, Ix;

            short[]   pNLSF_Q15  = new short[psDec.LPC_order];
            short[]   pNLSF0_Q15 = new short[psDec.LPC_order];
            sbyte[][] cbk_ptr_Q7;

            /* Dequant Gains */
            BoxedValueSbyte boxedLastGainIndex = new BoxedValueSbyte(psDec.LastGainIndex);

            GainQuantization.silk_gains_dequant(psDecCtrl.Gains_Q16, psDec.indices.GainsIndices,
                                                boxedLastGainIndex, condCoding == SilkConstants.CODE_CONDITIONALLY ? 1 : 0, psDec.nb_subfr);
            psDec.LastGainIndex = boxedLastGainIndex.Val;

            /****************/
            /* Decode NLSFs */
            /****************/
            NLSF.silk_NLSF_decode(pNLSF_Q15, psDec.indices.NLSFIndices, psDec.psNLSF_CB);

            /* Convert NLSF parameters to AR prediction filter coefficients */
            NLSF.silk_NLSF2A(psDecCtrl.PredCoef_Q12[1], pNLSF_Q15, psDec.LPC_order);

            /* If just reset, e.g., because internal Fs changed, do not allow interpolation */
            /* improves the case of packet loss in the first frame after a switch           */
            if (psDec.first_frame_after_reset == 1)
            {
                psDec.indices.NLSFInterpCoef_Q2 = 4;
            }

            if (psDec.indices.NLSFInterpCoef_Q2 < 4)
            {
                /* Calculation of the interpolated NLSF0 vector from the interpolation factor, */
                /* the previous NLSF1, and the current NLSF1                                   */
                for (i = 0; i < psDec.LPC_order; i++)
                {
                    pNLSF0_Q15[i] = (short)(psDec.prevNLSF_Q15[i] + Inlines.silk_RSHIFT(Inlines.silk_MUL(psDec.indices.NLSFInterpCoef_Q2,
                                                                                                         pNLSF_Q15[i] - psDec.prevNLSF_Q15[i]), 2));
                }

                /* Convert NLSF parameters to AR prediction filter coefficients */
                NLSF.silk_NLSF2A(psDecCtrl.PredCoef_Q12[0], pNLSF0_Q15, psDec.LPC_order);
            }
            else
            {
                /* Copy LPC coefficients for first half from second half */
                Array.Copy(psDecCtrl.PredCoef_Q12[1], psDecCtrl.PredCoef_Q12[0], psDec.LPC_order);
            }

            Array.Copy(pNLSF_Q15, psDec.prevNLSF_Q15, psDec.LPC_order);

            /* After a packet loss do BWE of LPC coefs */
            if (psDec.lossCnt != 0)
            {
                BWExpander.silk_bwexpander(psDecCtrl.PredCoef_Q12[0], psDec.LPC_order, SilkConstants.BWE_AFTER_LOSS_Q16);
                BWExpander.silk_bwexpander(psDecCtrl.PredCoef_Q12[1], psDec.LPC_order, SilkConstants.BWE_AFTER_LOSS_Q16);
            }

            if (psDec.indices.signalType == SilkConstants.TYPE_VOICED)
            {
                /*********************/
                /* Decode pitch lags */
                /*********************/

                /* Decode pitch values */
                DecodePitch.silk_decode_pitch(psDec.indices.lagIndex, psDec.indices.contourIndex, psDecCtrl.pitchL, psDec.fs_kHz, psDec.nb_subfr);

                /* Decode Codebook Index */
                cbk_ptr_Q7 = Tables.silk_LTP_vq_ptrs_Q7[psDec.indices.PERIndex]; /* set pointer to start of codebook */

                for (k = 0; k < psDec.nb_subfr; k++)
                {
                    Ix = psDec.indices.LTPIndex[k];
                    for (i = 0; i < SilkConstants.LTP_ORDER; i++)
                    {
                        psDecCtrl.LTPCoef_Q14[k * SilkConstants.LTP_ORDER + i] = (short)(Inlines.silk_LSHIFT(cbk_ptr_Q7[Ix][i], 7));
                    }
                }

                /**********************/
                /* Decode LTP scaling */
                /**********************/
                Ix = psDec.indices.LTP_scaleIndex;
                psDecCtrl.LTP_scale_Q14 = Tables.silk_LTPScales_table_Q14[Ix];
            }
            else
            {
                Arrays.MemSetInt(psDecCtrl.pitchL, 0, psDec.nb_subfr);
                Arrays.MemSetShort(psDecCtrl.LTPCoef_Q14, 0, SilkConstants.LTP_ORDER * psDec.nb_subfr);
                psDec.indices.PERIndex  = 0;
                psDecCtrl.LTP_scale_Q14 = 0;
            }
        }
Esempio n. 4
0
        /// <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);
        }
Esempio n. 5
0
        internal static void silk_find_pred_coefs(
            SilkChannelEncoder psEnc,                   /* I/O  encoder state                                                               */
            SilkEncoderControl psEncCtrl,               /* I/O  encoder control                                                             */
            short[] res_pitch,                          /* I    Residual from pitch analysis                                                */
            short[] x,                                  /* I    Speech signal                                                               */
            int x_ptr,
            int condCoding                              /* I    The type of conditional coding to use                                       */
            )
        {
            int i;

            int[]   invGains_Q16 = new int[SilkConstants.MAX_NB_SUBFR];
            int[]   local_gains  = new int[SilkConstants.MAX_NB_SUBFR];
            int[]   Wght_Q15     = new int[SilkConstants.MAX_NB_SUBFR];
            short[] NLSF_Q15     = new short[SilkConstants.MAX_LPC_ORDER];
            int     x_ptr2;
            int     x_pre_ptr;

            short[] LPC_in_pre;
            int     tmp, min_gain_Q16, minInvGain_Q30;

            int[] LTP_corrs_rshift = new int[SilkConstants.MAX_NB_SUBFR];

            /* weighting for weighted least squares */
            min_gain_Q16 = int.MaxValue >> 6;
            for (i = 0; i < psEnc.nb_subfr; i++)
            {
                min_gain_Q16 = Inlines.silk_min(min_gain_Q16, psEncCtrl.Gains_Q16[i]);
            }
            for (i = 0; i < psEnc.nb_subfr; i++)
            {
                /* Divide to Q16 */
                Inlines.OpusAssert(psEncCtrl.Gains_Q16[i] > 0);
                /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */
                invGains_Q16[i] = Inlines.silk_DIV32_varQ(min_gain_Q16, psEncCtrl.Gains_Q16[i], 16 - 2);

                /* Ensure Wght_Q15 a minimum value 1 */
                invGains_Q16[i] = Inlines.silk_max(invGains_Q16[i], 363);

                /* Square the inverted gains */
                Inlines.OpusAssert(invGains_Q16[i] == Inlines.silk_SAT16(invGains_Q16[i]));
                tmp         = Inlines.silk_SMULWB(invGains_Q16[i], invGains_Q16[i]);
                Wght_Q15[i] = Inlines.silk_RSHIFT(tmp, 1);

                /* Invert the inverted and normalized gains */
                local_gains[i] = Inlines.silk_DIV32(((int)1 << 16), invGains_Q16[i]);
            }

            LPC_in_pre = new short[psEnc.nb_subfr * psEnc.predictLPCOrder + psEnc.frame_length];
            if (psEnc.indices.signalType == SilkConstants.TYPE_VOICED)
            {
                int[] WLTP;

                /**********/
                /* VOICED */
                /**********/
                Inlines.OpusAssert(psEnc.ltp_mem_length - psEnc.predictLPCOrder >= psEncCtrl.pitchL[0] + SilkConstants.LTP_ORDER / 2);

                WLTP = new int[psEnc.nb_subfr * SilkConstants.LTP_ORDER * SilkConstants.LTP_ORDER];

                /* LTP analysis */
                BoxedValueInt boxed_codgain = new BoxedValueInt(psEncCtrl.LTPredCodGain_Q7);
                FindLTP.silk_find_LTP(psEncCtrl.LTPCoef_Q14, WLTP, boxed_codgain,
                                      res_pitch, psEncCtrl.pitchL, Wght_Q15, psEnc.subfr_length,
                                      psEnc.nb_subfr, psEnc.ltp_mem_length, LTP_corrs_rshift);
                psEncCtrl.LTPredCodGain_Q7 = boxed_codgain.Val;

                /* Quantize LTP gain parameters */
                BoxedValueSbyte boxed_periodicity = new BoxedValueSbyte(psEnc.indices.PERIndex);
                BoxedValueInt   boxed_gain        = new BoxedValueInt(psEnc.sum_log_gain_Q7);
                QuantizeLTPGains.silk_quant_LTP_gains(psEncCtrl.LTPCoef_Q14, psEnc.indices.LTPIndex, boxed_periodicity,
                                                      boxed_gain, WLTP, psEnc.mu_LTP_Q9, psEnc.LTPQuantLowComplexity, psEnc.nb_subfr
                                                      );
                psEnc.indices.PERIndex = boxed_periodicity.Val;
                psEnc.sum_log_gain_Q7  = boxed_gain.Val;

                /* Control LTP scaling */
                LTPScaleControl.silk_LTP_scale_ctrl(psEnc, psEncCtrl, condCoding);

                /* Create LTP residual */
                LTPAnalysisFilter.silk_LTP_analysis_filter(LPC_in_pre, x, x_ptr - psEnc.predictLPCOrder, psEncCtrl.LTPCoef_Q14,
                                                           psEncCtrl.pitchL, invGains_Q16, psEnc.subfr_length, psEnc.nb_subfr, psEnc.predictLPCOrder);
            }
            else
            {
                /************/
                /* UNVOICED */
                /************/
                /* Create signal with prepended subframes, scaled by inverse gains */
                x_ptr2    = x_ptr - psEnc.predictLPCOrder;
                x_pre_ptr = 0;
                for (i = 0; i < psEnc.nb_subfr; i++)
                {
                    Inlines.silk_scale_copy_vector16(LPC_in_pre, x_pre_ptr, x, x_ptr2, invGains_Q16[i],
                                                     psEnc.subfr_length + psEnc.predictLPCOrder);
                    x_pre_ptr += psEnc.subfr_length + psEnc.predictLPCOrder;
                    x_ptr2    += psEnc.subfr_length;
                }

                Arrays.MemSetShort(psEncCtrl.LTPCoef_Q14, 0, psEnc.nb_subfr * SilkConstants.LTP_ORDER);
                psEncCtrl.LTPredCodGain_Q7 = 0;
                psEnc.sum_log_gain_Q7      = 0;
            }

            /* Limit on total predictive coding gain */
            if (psEnc.first_frame_after_reset != 0)
            {
                minInvGain_Q30 = ((int)((1.0f / SilkConstants.MAX_PREDICTION_POWER_GAIN_AFTER_RESET) * ((long)1 << (30)) + 0.5)) /*Inlines.SILK_CONST(1.0f / SilkConstants.MAX_PREDICTION_POWER_GAIN_AFTER_RESET, 30)*/;
            }
            else
            {
                minInvGain_Q30 = Inlines.silk_log2lin(Inlines.silk_SMLAWB(16 << 7, (int)psEncCtrl.LTPredCodGain_Q7, ((int)((1.0f / 3f) * ((long)1 << (16)) + 0.5)) /*Inlines.SILK_CONST(1.0f / 3f, 16)*/));      /* Q16 */
                minInvGain_Q30 = Inlines.silk_DIV32_varQ(minInvGain_Q30,
                                                         Inlines.silk_SMULWW(((int)((SilkConstants.MAX_PREDICTION_POWER_GAIN) * ((long)1 << (0)) + 0.5)) /*Inlines.SILK_CONST(SilkConstants.MAX_PREDICTION_POWER_GAIN, 0)*/,
                                                                             Inlines.silk_SMLAWB(((int)((0.25f) * ((long)1 << (18)) + 0.5)) /*Inlines.SILK_CONST(0.25f, 18)*/, ((int)((0.75f) * ((long)1 << (18)) + 0.5)) /*Inlines.SILK_CONST(0.75f, 18)*/, psEncCtrl.coding_quality_Q14)), 14);
            }

            /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */
            FindLPC.silk_find_LPC(psEnc, NLSF_Q15, LPC_in_pre, minInvGain_Q30);

            /* Quantize LSFs */
            NLSF.silk_process_NLSFs(psEnc, psEncCtrl.PredCoef_Q12, NLSF_Q15, psEnc.prev_NLSFq_Q15);

            /* Calculate residual energy using quantized LPC coefficients */
            ResidualEnergy.silk_residual_energy(psEncCtrl.ResNrg, psEncCtrl.ResNrgQ, LPC_in_pre, psEncCtrl.PredCoef_Q12, local_gains,
                                                psEnc.subfr_length, psEnc.nb_subfr, psEnc.predictLPCOrder);

            /* Copy to prediction struct for use in next frame for interpolation */
            Array.Copy(NLSF_Q15, psEnc.prev_NLSFq_Q15, SilkConstants.MAX_LPC_ORDER);
        }
Esempio n. 6
0
        /* 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);
        }