Ejemplo n.º 1
0
        /// <summary>
        /// Decode mid/side predictors
        /// </summary>
        /// <param name="psRangeDec">I/O  Compressor data structure</param>
        /// <param name="pred_Q13">O Predictors</param>
        internal static void silk_stereo_decode_pred(
            EntropyCoder psRangeDec,
            int[] pred_Q13)
        {
            int n;

            int[][] ix = Arrays.InitTwoDimensionalArray <int>(2, 3);
            int     low_Q13, step_Q13;

            // Entropy decoding
            n        = psRangeDec.dec_icdf(Tables.silk_stereo_pred_joint_iCDF, 8);
            ix[0][2] = Inlines.silk_DIV32_16(n, 5);
            ix[1][2] = n - 5 * ix[0][2];
            for (n = 0; n < 2; n++)
            {
                ix[n][0] = psRangeDec.dec_icdf(Tables.silk_uniform3_iCDF, 8);
                ix[n][1] = psRangeDec.dec_icdf(Tables.silk_uniform5_iCDF, 8);
            }

            // Dequantize
            for (n = 0; n < 2; n++)
            {
                ix[n][0] += 3 * ix[n][2];
                low_Q13   = Tables.silk_stereo_pred_quant_Q13[ix[n][0]];
                step_Q13  = Inlines.silk_SMULWB(Tables.silk_stereo_pred_quant_Q13[ix[n][0] + 1] - low_Q13,
                                                ((int)((0.5f / SilkConstants.STEREO_QUANT_SUB_STEPS) * ((long)1 << (16)) + 0.5)) /*Inlines.SILK_CONST(0.5f / SilkConstants.STEREO_QUANT_SUB_STEPS, 16)*/);
                pred_Q13[n] = Inlines.silk_SMLABB(low_Q13, step_Q13, 2 * ix[n][1] + 1);
            }

            /* Subtract second from first predictor (helps when actually applying these) */
            pred_Q13[0] -= pred_Q13[1];
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Decode mid-only flag
 /// </summary>
 /// <param name="psRangeDec">I/O  Compressor data structure</param>
 /// <param name="decode_only_mid">O    Flag that only mid channel has been coded</param>
 internal static void silk_stereo_decode_mid_only(
     EntropyCoder psRangeDec,
     BoxedValueInt decode_only_mid
     )
 {
     /* Decode flag that only mid channel is coded */
     decode_only_mid.Val = psRangeDec.dec_icdf(Tables.silk_stereo_only_code_mid_iCDF, 8);
 }
Ejemplo n.º 3
0
        private sbyte DecodeSign(ContextVector contextVector, int x, int y)
        {
            contextVector.GetSignCodingContextLabelAndXorBit(out int contextLabel, out int xorBit);
            var cx      = GetContext(contextLabel);
            var d       = EntropyCoder.DecodeNextBit(cx);
            var signBit = d ^ xorBit;
            var sign    = (sbyte)((signBit == 0) ? 1 : -1);

            UpdateNeighbourContextVectors(x, y, sign);
            return(sign);
        }
Ejemplo n.º 4
0
 internal static void encode_split(
     EntropyCoder psRangeEnc, /* I/O  compressor data structure                   */
     int p_child1,            /* I    pulse amplitude of first child subframe     */
     int p,                   /* I    pulse amplitude of current subframe         */
     byte[] shell_table       /* I    table of shell cdfs                         */
     )
 {
     if (p > 0)
     {
         psRangeEnc.enc_icdf(p_child1, shell_table, Tables.silk_shell_code_table_offsets[p], 8);
     }
 }
Ejemplo n.º 5
0
        public static byte[] EncodeJPEG(Image jpgImage)
        {
            Tiler                 imgtiler;
            ForwCompTransf        fctransf;
            ImgDataConverter      converter;
            EncoderSpecs          encSpec;
            ForwardWT             dwt;
            Quantizer             quant;
            ROIScaler             rois;
            EntropyCoder          ecoder;
            PostCompRateAllocator ralloc;
            HeaderEncoder         headenc;
            CodestreamWriter      bwriter;

            float rate = Single.MaxValue;

            ImgReaderGDI imgsrc = new ImgReaderGDI(jpgImage);

            imgtiler = new Tiler(imgsrc, 0, 0, 0, 0, jpgImage.Width, jpgImage.Height);
            int ntiles = imgtiler.getNumTiles();

            encSpec = new EncoderSpecs(ntiles, 3, imgsrc, pl);

            fctransf  = new ForwCompTransf(imgtiler, encSpec);
            converter = new ImgDataConverter(fctransf);
            dwt       = ForwardWT.createInstance(converter, pl, encSpec);
            quant     = Quantizer.createInstance(dwt, encSpec);
            rois      = ROIScaler.createInstance(quant, pl, encSpec);
            ecoder    = EntropyCoder.createInstance(rois, pl, encSpec.cblks,
                                                    encSpec.pss, encSpec.bms,
                                                    encSpec.mqrs, encSpec.rts,
                                                    encSpec.css, encSpec.sss,
                                                    encSpec.lcs, encSpec.tts);

            using (MemoryStream stream = new MemoryStream())
            {
                bwriter = new FileCodestreamWriter(stream, Int32.MaxValue);
                ralloc  = PostCompRateAllocator.createInstance(ecoder, pl, rate, bwriter, encSpec);

                headenc = new HeaderEncoder(imgsrc, new bool[3], dwt, imgtiler, encSpec, rois, ralloc, pl);
                ralloc.HeaderEncoder = headenc;
                headenc.encodeMainHeader();
                ralloc.initialize();
                headenc.reset();
                headenc.encodeMainHeader();
                bwriter.commitBitstreamHeader(headenc);

                ralloc.runAndWrite();
                bwriter.close();

                return(stream.ToArray());
            }
        }
Ejemplo n.º 6
0
        internal static int ec_laplace_decode(EntropyCoder dec, uint fs, int decay)
        {
            int  val = 0;
            uint fl;
            uint fm;

            fm = dec.decode_bin(15);
            fl = 0;

            if (fm >= fs)
            {
                val++;
                fl = fs;
                fs = ec_laplace_get_freq1(fs, decay) + LAPLACE_MINP;
                /* Search the decaying part of the PDF.*/
                while (fs > LAPLACE_MINP && fm >= fl + 2 * fs)
                {
                    fs *= 2;
                    fl += fs;
                    fs  = (uint)(((fs - 2 * LAPLACE_MINP) * (int)decay) >> 15);
                    fs += LAPLACE_MINP;
                    val++;
                }
                /* Everything beyond that has probability LAPLACE_MINP. */
                if (fs <= LAPLACE_MINP)
                {
                    int di;
                    di   = (int)(fm - fl) >> (LAPLACE_LOG_MINP + 1);
                    val += di;
                    fl  += (uint)(2 * di * LAPLACE_MINP);
                }
                if (fm < fl + fs)
                {
                    val = -val;
                }
                else
                {
                    fl += fs;
                }
            }

            Inlines.OpusAssert(fl < 32768);
            Inlines.OpusAssert(fs > 0);
            Inlines.OpusAssert(fl <= fm);
            Inlines.OpusAssert(fm < Inlines.IMIN(fl + fs, 32768));

            dec.dec_update(fl, Inlines.IMIN(fl + fs, 32768), 32768);
            return(val);
        }
Ejemplo n.º 7
0
        /** Decode pulse vector and combine the result with the pitch vector to produce
         *  the final normalised signal in the current band. */
        internal static uint alg_unquant(int[] X, int X_ptr, int N, int K, int spread, int B,
                                         EntropyCoder dec, int gain)
        {
            int  Ryy;
            uint collapse_mask;

            int[] iy = new int[N];
            Inlines.OpusAssert(K > 0, "alg_unquant() needs at least one pulse");
            Inlines.OpusAssert(N > 1, "alg_unquant() needs at least two dimensions");
            Ryy = CWRS.decode_pulses(iy, N, K, dec);
            normalise_residual(iy, X, X_ptr, N, Ryy, gain);
            exp_rotation(X, X_ptr, N, -1, B, K, spread);
            collapse_mask = extract_collapse_mask(iy, N, B);

            return(collapse_mask);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Entropy code the mid/side quantization indices
        /// </summary>
        /// <param name="psRangeEnc">I/O  Compressor data structure</param>
        /// <param name="ix">I    Quantization indices [ 2 ][ 3 ]</param>
        internal static void silk_stereo_encode_pred(EntropyCoder psRangeEnc, sbyte[][] ix)
        {
            int n;

            /* Entropy coding */
            n = 5 * ix[0][2] + ix[1][2];
            Inlines.OpusAssert(n < 25);
            psRangeEnc.enc_icdf(n, Tables.silk_stereo_pred_joint_iCDF, 8);
            for (n = 0; n < 2; n++)
            {
                Inlines.OpusAssert(ix[n][0] < 3);
                Inlines.OpusAssert(ix[n][1] < SilkConstants.STEREO_QUANT_SUB_STEPS);
                psRangeEnc.enc_icdf(ix[n][0], Tables.silk_uniform3_iCDF, 8);
                psRangeEnc.enc_icdf(ix[n][1], Tables.silk_uniform5_iCDF, 8);
            }
        }
Ejemplo n.º 9
0
        internal static void ec_laplace_encode(EntropyCoder enc, ref int value, uint fs, int decay)
        {
            uint fl;
            int  val = value;

            fl = 0;
            if (val != 0)
            {
                int s;
                int i;
                s   = 0 - (val < 0 ? 1 : 0);
                val = (val + s) ^ s;
                fl  = fs;
                fs  = ec_laplace_get_freq1(fs, decay);

                /* Search the decaying part of the PDF.*/
                for (i = 1; fs > 0 && i < val; i++)
                {
                    fs *= 2;
                    fl += fs + 2 * LAPLACE_MINP;
                    fs  = (uint)((fs * (int)decay) >> 15);
                }

                /* Everything beyond that has probability LAPLACE_MINP. */
                if (fs == 0)
                {
                    int di;
                    int ndi_max;
                    ndi_max = (int)(32768 - fl + LAPLACE_MINP - 1) >> LAPLACE_LOG_MINP;
                    ndi_max = (ndi_max - s) >> 1;
                    di      = Inlines.IMIN(val - i, ndi_max - 1);
                    fl     += (uint)(2 * di + 1 + s) * LAPLACE_MINP;
                    fs      = Inlines.IMIN(LAPLACE_MINP, 32768 - fl);
                    value   = (i + di + s) ^ s;
                }
                else
                {
                    fs += LAPLACE_MINP;
                    fl += (uint)(fs & ~s);
                }
                Inlines.OpusAssert(fl + fs <= 32768);
                Inlines.OpusAssert(fs > 0);
            }

            enc.encode_bin(fl, fl + fs, 15);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Decodes signs of excitation
        /// </summary>
        /// <param name="psRangeDec">I/O  Compressor data structure</param>
        /// <param name="pulses">I/O  pulse signal</param>
        /// <param name="length">I    length of input</param>
        /// <param name="signalType">I    Signal type</param>
        /// <param name="quantOffsetType">I    Quantization offset type</param>
        /// <param name="sum_pulses">I    Sum of absolute pulses per block [MAX_NB_SHELL_BLOCKS]</param>
        internal static void silk_decode_signs(
            EntropyCoder psRangeDec,
            short[] pulses,
            int length,
            int signalType,
            int quantOffsetType,
            int[] sum_pulses)
        {
            int i, j, p;

            byte[] icdf = new byte[2];
            int    q_ptr;

            byte[] icdf_table = Tables.silk_sign_iCDF;
            int    icdf_ptr;

            icdf[1]  = 0;
            q_ptr    = 0;
            i        = Inlines.silk_SMULBB(7, Inlines.silk_ADD_LSHIFT(quantOffsetType, signalType, 1));
            icdf_ptr = i;
            length   = Inlines.silk_RSHIFT(length + SilkConstants.SHELL_CODEC_FRAME_LENGTH / 2, SilkConstants.LOG2_SHELL_CODEC_FRAME_LENGTH);

            for (i = 0; i < length; i++)
            {
                p = sum_pulses[i];

                if (p > 0)
                {
                    icdf[0] = icdf_table[icdf_ptr + Inlines.silk_min(p & 0x1F, 6)];
                    for (j = 0; j < SilkConstants.SHELL_CODEC_FRAME_LENGTH; j++)
                    {
                        if (pulses[q_ptr + j] > 0)
                        {
                            /* attach sign */
                            pulses[q_ptr + j] *= (short)(silk_dec_map(psRangeDec.dec_icdf(icdf, 8)));
                        }
                    }
                }

                q_ptr += SilkConstants.SHELL_CODEC_FRAME_LENGTH;
            }
        }
Ejemplo n.º 11
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="p_child1">O    pulse amplitude of first child subframe</param>
 /// <param name="child1_ptr"></param>
 /// <param name="p_child2">O    pulse amplitude of second child subframe</param>
 /// <param name="p_child2_ptr"></param>
 /// <param name="psRangeDec">I/O  Compressor data structure</param>
 /// <param name="p">I    pulse amplitude of current subframe</param>
 /// <param name="shell_table">I    table of shell cdfs</param>
 internal static void decode_split(
     short[] p_child1,
     int child1_ptr,
     short[] p_child2,
     int p_child2_ptr,
     EntropyCoder psRangeDec,
     int p,
     byte[] shell_table)
 {
     if (p > 0)
     {
         p_child1[child1_ptr]   = (short)(psRangeDec.dec_icdf(shell_table, (Tables.silk_shell_code_table_offsets[p]), 8));
         p_child2[p_child2_ptr] = (short)(p - p_child1[child1_ptr]);
     }
     else
     {
         p_child1[child1_ptr]   = 0;
         p_child2[p_child2_ptr] = 0;
     }
 }
Ejemplo n.º 12
0
        private void RunSignificancePassOnCoefficient(int x, int y, bool includeZeroContext)
        {
            var coefficient = CoefficientArray[GetCoefficientIndex(x, y)];

            if (coefficient.Sign == 0)
            {
                var contextLabel = coefficient.ContextVector.GetSignificanceCodingContextLabel(CodeBlock.Subband.SubbandType);
                if ((contextLabel != 0) || includeZeroContext)
                {
                    var cx = GetContext(contextLabel);
                    if (EntropyCoder.DecodeNextBit(cx) == 1)
                    {
                        var sign = DecodeSign(coefficient.ContextVector, x, y);
                        coefficient.ApplySignificance(sign, CurrentCodingPass.BitPlane);
                    }
                    else
                    {
                        coefficient.ApplySignificance(0, CurrentCodingPass.BitPlane);
                    }
                }
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Encodes signs of excitation
        /// </summary>
        /// <param name="psRangeEnc">I/O  Compressor data structure</param>
        /// <param name="pulses">I    pulse signal</param>
        /// <param name="length">I    length of input</param>
        /// <param name="signalType">I    Signal type</param>
        /// <param name="quantOffsetType">I    Quantization offset type</param>
        /// <param name="sum_pulses">I    Sum of absolute pulses per block [MAX_NB_SHELL_BLOCKS]</param>
        internal static void silk_encode_signs(
            EntropyCoder psRangeEnc,
            sbyte[] pulses,
            int length,
            int signalType,
            int quantOffsetType,
            int[] sum_pulses)
        {
            int i, j, p;

            byte[] icdf = new byte[2];
            int    q_ptr;

            byte[] sign_icdf = Tables.silk_sign_iCDF;
            int    icdf_ptr;

            icdf[1]  = 0;
            q_ptr    = 0;
            i        = Inlines.silk_SMULBB(7, Inlines.silk_ADD_LSHIFT(quantOffsetType, signalType, 1));
            icdf_ptr = i;
            length   = Inlines.silk_RSHIFT(length + (SilkConstants.SHELL_CODEC_FRAME_LENGTH / 2), SilkConstants.LOG2_SHELL_CODEC_FRAME_LENGTH);
            for (i = 0; i < length; i++)
            {
                p = sum_pulses[i];
                if (p > 0)
                {
                    icdf[0] = sign_icdf[icdf_ptr + Inlines.silk_min(p & 0x1F, 6)];
                    for (j = q_ptr; j < q_ptr + SilkConstants.SHELL_CODEC_FRAME_LENGTH; j++)
                    {
                        if (pulses[j] != 0)
                        {
                            psRangeEnc.enc_icdf(silk_enc_map(pulses[j]), icdf, 8);
                        }
                    }
                }

                q_ptr += SilkConstants.SHELL_CODEC_FRAME_LENGTH;
            }
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Shell encoder, operates on one shell code frame of 16 pulses
        /// </summary>
        /// <param name="psRangeEnc">I/O  compressor data structure</param>
        /// <param name="pulses0">I    data: nonnegative pulse amplitudes</param>
        /// <param name="pulses0_ptr"></param>
        internal static void silk_shell_encoder(EntropyCoder psRangeEnc, int[] pulses0, int pulses0_ptr)
        {
            int[] pulses1 = new int[8];
            int[] pulses2 = new int[4];
            int[] pulses3 = new int[2];
            int[] pulses4 = new int[1];

            /* this function operates on one shell code frame of 16 pulses */
            Inlines.OpusAssert(SilkConstants.SHELL_CODEC_FRAME_LENGTH == 16);

            /* tree representation per pulse-subframe */
            combine_pulses(pulses1, pulses0, pulses0_ptr, 8);
            combine_pulses(pulses2, pulses1, 4);
            combine_pulses(pulses3, pulses2, 2);
            combine_pulses(pulses4, pulses3, 1);

            encode_split(psRangeEnc, pulses3[0], pulses4[0], Tables.silk_shell_code_table3);

            encode_split(psRangeEnc, pulses2[0], pulses3[0], Tables.silk_shell_code_table2);

            encode_split(psRangeEnc, pulses1[0], pulses2[0], Tables.silk_shell_code_table1);
            encode_split(psRangeEnc, pulses0[pulses0_ptr], pulses1[0], Tables.silk_shell_code_table0);
            encode_split(psRangeEnc, pulses0[pulses0_ptr + 2], pulses1[1], Tables.silk_shell_code_table0);

            encode_split(psRangeEnc, pulses1[2], pulses2[1], Tables.silk_shell_code_table1);
            encode_split(psRangeEnc, pulses0[pulses0_ptr + 4], pulses1[2], Tables.silk_shell_code_table0);
            encode_split(psRangeEnc, pulses0[pulses0_ptr + 6], pulses1[3], Tables.silk_shell_code_table0);

            encode_split(psRangeEnc, pulses2[2], pulses3[1], Tables.silk_shell_code_table2);

            encode_split(psRangeEnc, pulses1[4], pulses2[2], Tables.silk_shell_code_table1);
            encode_split(psRangeEnc, pulses0[pulses0_ptr + 8], pulses1[4], Tables.silk_shell_code_table0);
            encode_split(psRangeEnc, pulses0[pulses0_ptr + 10], pulses1[5], Tables.silk_shell_code_table0);

            encode_split(psRangeEnc, pulses1[6], pulses2[3], Tables.silk_shell_code_table1);
            encode_split(psRangeEnc, pulses0[pulses0_ptr + 12], pulses1[6], Tables.silk_shell_code_table0);
            encode_split(psRangeEnc, pulses0[pulses0_ptr + 14], pulses1[7], Tables.silk_shell_code_table0);
        }
Ejemplo n.º 15
0
        /* Shell decoder, operates on one shell code frame of 16 pulses */
        internal static void silk_shell_decoder(
            short[] pulses0,                    /* O    data: nonnegative pulse amplitudes          */
            int pulses0_ptr,
            EntropyCoder psRangeDec,            /* I/O  Compressor data structure                   */
            int pulses4                         /* I    number of pulses per pulse-subframe         */
            )
        {
            short[] pulses1 = new short[8];
            short[] pulses2 = new short[4];
            short[] pulses3 = new short[2];

            /* this function operates on one shell code frame of 16 pulses */
            Inlines.OpusAssert(SilkConstants.SHELL_CODEC_FRAME_LENGTH == 16);

            decode_split(pulses3, 0, pulses3, 1, psRangeDec, pulses4, Tables.silk_shell_code_table3);

            decode_split(pulses2, 0, pulses2, 1, psRangeDec, pulses3[0], Tables.silk_shell_code_table2);

            decode_split(pulses1, 0, pulses1, 1, psRangeDec, pulses2[0], Tables.silk_shell_code_table1);
            decode_split(pulses0, pulses0_ptr, pulses0, pulses0_ptr + 1, psRangeDec, pulses1[0], Tables.silk_shell_code_table0);
            decode_split(pulses0, pulses0_ptr + 2, pulses0, pulses0_ptr + 3, psRangeDec, pulses1[1], Tables.silk_shell_code_table0);

            decode_split(pulses1, 2, pulses1, 3, psRangeDec, pulses2[1], Tables.silk_shell_code_table1);
            decode_split(pulses0, pulses0_ptr + 4, pulses0, pulses0_ptr + 5, psRangeDec, pulses1[2], Tables.silk_shell_code_table0);
            decode_split(pulses0, pulses0_ptr + 6, pulses0, pulses0_ptr + 7, psRangeDec, pulses1[3], Tables.silk_shell_code_table0);

            decode_split(pulses2, 2, pulses2, 3, psRangeDec, pulses3[1], Tables.silk_shell_code_table2);

            decode_split(pulses1, 4, pulses1, 5, psRangeDec, pulses2[2], Tables.silk_shell_code_table1);
            decode_split(pulses0, pulses0_ptr + 8, pulses0, pulses0_ptr + 9, psRangeDec, pulses1[4], Tables.silk_shell_code_table0);
            decode_split(pulses0, pulses0_ptr + 10, pulses0, pulses0_ptr + 11, psRangeDec, pulses1[5], Tables.silk_shell_code_table0);

            decode_split(pulses1, 6, pulses1, 7, psRangeDec, pulses2[3], Tables.silk_shell_code_table1);
            decode_split(pulses0, pulses0_ptr + 12, pulses0, pulses0_ptr + 13, psRangeDec, pulses1[6], Tables.silk_shell_code_table0);
            decode_split(pulses0, pulses0_ptr + 14, pulses0, pulses0_ptr + 15, psRangeDec, pulses1[7], Tables.silk_shell_code_table0);
        }
Ejemplo n.º 16
0
        internal static void unquant_fine_energy(CeltMode m, int start, int end, int[] oldEBands, int[] fine_quant, EntropyCoder dec, int C)
        {
            int i, c;

            /* Decode finer resolution */
            for (i = start; i < end; i++)
            {
                if (fine_quant[i] <= 0)
                {
                    continue;
                }
                c = 0;
                do
                {
                    int q2;
                    int offset;
                    q2     = (int)dec.dec_bits((uint)fine_quant[i]);
                    offset = Inlines.SUB16((Inlines.SHR32(
                                                Inlines.SHL32(q2, CeltConstants.DB_SHIFT) +
                                                ((short)(0.5 + (.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(.5f, CeltConstants.DB_SHIFT)*/, fine_quant[i])),
                                           ((short)(0.5 + (.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(.5f, CeltConstants.DB_SHIFT)*/); // opus bug: unnecessary extend32
                    oldEBands[i + c * m.nbEBands] += offset;
                } while (++c < C);
            }
        }
Ejemplo n.º 17
0
        internal static void unquant_coarse_energy(CeltMode m, int start, int end, int[] oldEBands, int intra, EntropyCoder dec, int C, int LM)
        {
            byte[] prob_model = Tables.e_prob_model[LM][intra];
            int    i, c;

            int[] prev = { 0, 0 };
            int   coef;
            int   beta;
            int   budget;
            int   tell;

            if (intra != 0)
            {
                coef = 0;
                beta = beta_intra;
            }
            else
            {
                beta = beta_coef[LM];
                coef = pred_coef[LM];
            }

            budget = (int)dec.storage * 8;

            /* Decode at a fixed coarse resolution */
            for (i = start; i < end; i++)
            {
                c = 0;
                do
                {
                    int qi;
                    int q;
                    int tmp;

                    /* It would be better to express this invariant as a
                     * test on C at function entry, but that isn't enough
                     * to make the static analyzer happy. */
                    Inlines.OpusAssert(c < 2);
                    tell = dec.tell();
                    if (budget - tell >= 15)
                    {
                        int pi;
                        pi = 2 * Inlines.IMIN(i, 20);
                        qi = Laplace.ec_laplace_decode(dec,
                                                       (uint)prob_model[pi] << 7, prob_model[pi + 1] << 6);
                    }
                    else if (budget - tell >= 2)
                    {
                        qi = dec.dec_icdf(small_energy_icdf, 2);
                        qi = (qi >> 1) ^ -(qi & 1);
                    }
                    else if (budget - tell >= 1)
                    {
                        qi = 0 - dec.dec_bit_logp(1);
                    }
                    else
                    {
                        qi = -1;
                    }
                    q = (int)Inlines.SHL32(qi, CeltConstants.DB_SHIFT); // opus bug: useless extend32

                    oldEBands[i + c * m.nbEBands] = Inlines.MAX16((0 - ((short)(0.5 + (9.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(9.0f, CeltConstants.DB_SHIFT)*/), oldEBands[i + c * m.nbEBands]);
                    tmp = Inlines.PSHR32(Inlines.MULT16_16(coef, oldEBands[i + c * m.nbEBands]), 8) + prev[c] + Inlines.SHL32(q, 7);
                    tmp = Inlines.MAX32(-((int)(0.5 + (28.0f) * (((int)1) << (CeltConstants.DB_SHIFT + 7)))) /*Inlines.QCONST32(28.0f, CeltConstants.DB_SHIFT + 7)*/, tmp);
                    oldEBands[i + c * m.nbEBands] = (Inlines.PSHR32(tmp, 7));
                    prev[c] = prev[c] + Inlines.SHL32(q, 7) - Inlines.MULT16_16(beta, Inlines.PSHR32(q, 8));
                } while (++c < C);
            }
        }
Ejemplo n.º 18
0
        internal static void quant_fine_energy(CeltMode m, int start, int end, int[][] oldEBands, int[][] error, int[] fine_quant, EntropyCoder enc, int C)
        {
            int i, c;

            /* Encode finer resolution */
            for (i = start; i < end; i++)
            {
                int frac = (1 << fine_quant[i]);
                if (fine_quant[i] <= 0)
                {
                    continue;
                }
                c = 0;
                do
                {
                    int q2;
                    int offset;
                    /* Has to be without rounding */
                    q2 = (error[c][i] + ((short)(0.5 + (.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(.5f, CeltConstants.DB_SHIFT)*/) >> (CeltConstants.DB_SHIFT - fine_quant[i]);
                    if (q2 > frac - 1)
                    {
                        q2 = frac - 1;
                    }
                    if (q2 < 0)
                    {
                        q2 = 0;
                    }
                    enc.enc_bits((uint)q2, (uint)fine_quant[i]);
                    offset = Inlines.SUB16(
                        (Inlines.SHR32(
                             Inlines.SHL32(q2, CeltConstants.DB_SHIFT) + ((short)(0.5 + (.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(.5f, CeltConstants.DB_SHIFT)*/,
                             fine_quant[i])),
                        ((short)(0.5 + (.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(.5f, CeltConstants.DB_SHIFT)*/);
                    oldEBands[c][i] += offset;
                    error[c][i]     -= offset;
                } while (++c < C);
            }
        }
Ejemplo n.º 19
0
        internal static void quant_coarse_energy(CeltMode m, int start, int end, int effEnd,
                                                 int[][] eBands, int[][] oldEBands, uint budget,
                                                 int[][] error, EntropyCoder enc, int C, int LM, int nbAvailableBytes,
                                                 int force_intra, ref int delayedIntra, int two_pass, int loss_rate, int lfe)
        {
            int intra;
            int max_decay;

            int[][]      oldEBands_intra;
            int[][]      error_intra;
            EntropyCoder enc_start_state = new EntropyCoder(); // [porting note] stack variable
            uint         tell;
            int          badness1 = 0;
            int          intra_bias;
            int          new_distortion;


            intra          = (force_intra != 0 || (two_pass == 0 && delayedIntra > 2 * C * (end - start) && nbAvailableBytes > (end - start) * C)) ? 1 : 0;
            intra_bias     = (int)((budget * delayedIntra * loss_rate) / (C * 512));
            new_distortion = loss_distortion(eBands, oldEBands, start, effEnd, m.nbEBands, C);

            tell = (uint)enc.tell();
            if (tell + 3 > budget)
            {
                two_pass = intra = 0;
            }

            max_decay = ((short)(0.5 + (16.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(16.0f, CeltConstants.DB_SHIFT)*/;
            if (end - start > 10)
            {
                max_decay = (Inlines.MIN32(max_decay, Inlines.SHL32(nbAvailableBytes, CeltConstants.DB_SHIFT - 3))); // opus bug: useless extend32
            }
            if (lfe != 0)
            {
                max_decay = ((short)(0.5 + (3.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(3.0f, CeltConstants.DB_SHIFT)*/;
            }
            enc_start_state.Assign(enc);

            oldEBands_intra = Arrays.InitTwoDimensionalArray <int>(C, m.nbEBands);
            error_intra     = Arrays.InitTwoDimensionalArray <int>(C, m.nbEBands);
            Array.Copy(oldEBands[0], 0, oldEBands_intra[0], 0, m.nbEBands);
            if (C == 2)
            {
                Array.Copy(oldEBands[1], 0, oldEBands_intra[1], 0, m.nbEBands);
            }

            if (two_pass != 0 || intra != 0)
            {
                badness1 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands_intra, (int)budget,
                                                    (int)tell, Tables.e_prob_model[LM][1], error_intra, enc, C, LM, 1, max_decay, lfe);
            }

            if (intra == 0)
            {
                int          intra_buf;
                EntropyCoder enc_intra_state = new EntropyCoder(); // [porting note] stack variable
                int          tell_intra;
                uint         nstart_bytes;
                uint         nintra_bytes;
                uint         save_bytes;
                int          badness2;
                byte[]       intra_bits = null;

                tell_intra = (int)enc.tell_frac();

                enc_intra_state.Assign(enc);

                nstart_bytes = enc_start_state.range_bytes();
                nintra_bytes = enc_intra_state.range_bytes();
                intra_buf    = enc_intra_state.buf_ptr + (int)nstart_bytes;
                save_bytes   = nintra_bytes - nstart_bytes;

                if (save_bytes != 0)
                {
                    intra_bits = new byte[(int)save_bytes];
                    /* Copy bits from intra bit-stream */
                    Array.Copy(enc_intra_state.buf, intra_buf, intra_bits, 0, (int)save_bytes);
                }

                enc.Assign(enc_start_state);

                badness2 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands, (int)budget,
                                                    (int)tell, Tables.e_prob_model[LM][intra], error, enc, C, LM, 0, max_decay, lfe);

                if (two_pass != 0 && (badness1 < badness2 || (badness1 == badness2 && ((int)enc.tell_frac()) + intra_bias > tell_intra)))
                {
                    enc.Assign(enc_intra_state);
                    /* Copy intra bits to bit-stream */
                    if (intra_bits != null)
                    {
                        Array.Copy(intra_bits, 0, enc_intra_state.buf, intra_buf, (int)(nintra_bytes - nstart_bytes));
                    }
                    Array.Copy(oldEBands_intra[0], 0, oldEBands[0], 0, m.nbEBands);
                    Array.Copy(error_intra[0], 0, error[0], 0, m.nbEBands);
                    if (C == 2)
                    {
                        Array.Copy(oldEBands_intra[1], 0, oldEBands[1], 0, m.nbEBands);
                        Array.Copy(error_intra[1], 0, error[1], 0, m.nbEBands);
                    }
                    intra = 1;
                }
            }
            else
            {
                Array.Copy(oldEBands_intra[0], 0, oldEBands[0], 0, m.nbEBands);
                Array.Copy(error_intra[0], 0, error[0], 0, m.nbEBands);
                if (C == 2)
                {
                    Array.Copy(oldEBands_intra[1], 0, oldEBands[1], 0, m.nbEBands);
                    Array.Copy(error_intra[1], 0, error[1], 0, m.nbEBands);
                }
            }

            if (intra != 0)
            {
                delayedIntra = new_distortion;
            }
            else
            {
                delayedIntra = Inlines.ADD32(Inlines.MULT16_32_Q15(Inlines.MULT16_16_Q15(pred_coef[LM], pred_coef[LM]), delayedIntra),
                                             new_distortion);
            }
        }
Ejemplo n.º 20
0
        internal int celt_decode_with_ec(byte[] data, int data_ptr,
                                         int len, short[] pcm, int pcm_ptr, int frame_size, EntropyCoder dec, int accum)
        {
            int c, i, N;
            int spread_decision;
            int bits;

            int[][] X;
            int[]   fine_quant;
            int[]   pulses;
            int[]   cap;
            int[]   offsets;
            int[]   fine_priority;
            int[]   tf_res;
            byte[]  collapse_masks;
            int[][] out_syn      = new int[2][];
            int[]   out_syn_ptrs = new int[2];
            int[]   oldBandE, oldLogE, oldLogE2, backgroundLogE;

            int      shortBlocks;
            int      isTransient;
            int      intra_ener;
            int      CC = this.channels;
            int      LM, M;
            int      start;
            int      end;
            int      effEnd;
            int      codedBands;
            int      alloc_trim;
            int      postfilter_pitch;
            int      postfilter_gain;
            int      intensity   = 0;
            int      dual_stereo = 0;
            int      total_bits;
            int      balance;
            int      tell;
            int      dynalloc_logp;
            int      postfilter_tapset;
            int      anti_collapse_rsv;
            int      anti_collapse_on = 0;
            int      silence;
            int      C = this.stream_channels;
            CeltMode mode; // porting note: pointer
            int      nbEBands;
            int      overlap;

            short[] eBands;

            mode        = this.mode;
            nbEBands    = mode.nbEBands;
            overlap     = mode.overlap;
            eBands      = mode.eBands;
            start       = this.start;
            end         = this.end;
            frame_size *= this.downsample;

            oldBandE       = this.oldEBands;
            oldLogE        = this.oldLogE;
            oldLogE2       = this.oldLogE2;
            backgroundLogE = this.backgroundLogE;

            {
                for (LM = 0; LM <= mode.maxLM; LM++)
                {
                    if (mode.shortMdctSize << LM == frame_size)
                    {
                        break;
                    }
                }
                if (LM > mode.maxLM)
                {
                    return(OpusError.OPUS_BAD_ARG);
                }
            }
            M = 1 << LM;

            if (len < 0 || len > 1275 || pcm == null)
            {
                return(OpusError.OPUS_BAD_ARG);
            }

            N = M * mode.shortMdctSize;
            c = 0; do
            {
                out_syn[c]      = this.decode_mem[c];
                out_syn_ptrs[c] = CeltConstants.DECODE_BUFFER_SIZE - N;
            } while (++c < CC);

            effEnd = end;
            if (effEnd > mode.effEBands)
            {
                effEnd = mode.effEBands;
            }

            if (data == null || len <= 1)
            {
                this.celt_decode_lost(N, LM);
                CeltCommon.deemphasis(out_syn, out_syn_ptrs, pcm, pcm_ptr, N, CC, this.downsample, mode.preemph, this.preemph_memD, accum);

                return(frame_size / this.downsample);
            }

            if (dec == null)
            {
                // If no entropy decoder was passed into this function, we need to create
                // a new one here for local use only. It only exists in this function scope.
                dec = new EntropyCoder();
                dec.dec_init(data, data_ptr, (uint)len);
            }

            if (C == 1)
            {
                for (i = 0; i < nbEBands; i++)
                {
                    oldBandE[i] = Inlines.MAX16(oldBandE[i], oldBandE[nbEBands + i]);
                }
            }

            total_bits = len * 8;
            tell       = dec.tell();

            if (tell >= total_bits)
            {
                silence = 1;
            }
            else if (tell == 1)
            {
                silence = dec.dec_bit_logp(15);
            }
            else
            {
                silence = 0;
            }

            if (silence != 0)
            {
                /* Pretend we've read all the remaining bits */
                tell             = len * 8;
                dec.nbits_total += tell - dec.tell();
            }

            postfilter_gain   = 0;
            postfilter_pitch  = 0;
            postfilter_tapset = 0;
            if (start == 0 && tell + 16 <= total_bits)
            {
                if (dec.dec_bit_logp(1) != 0)
                {
                    int qg, octave;
                    octave           = (int)dec.dec_uint(6);
                    postfilter_pitch = (16 << octave) + (int)dec.dec_bits(4 + (uint)octave) - 1;
                    qg = (int)dec.dec_bits(3);
                    if (dec.tell() + 2 <= total_bits)
                    {
                        postfilter_tapset = dec.dec_icdf(Tables.tapset_icdf, 2);
                    }
                    postfilter_gain = ((short)(0.5 + (.09375f) * (((int)1) << (15)))) /*Inlines.QCONST16(.09375f, 15)*/ * (qg + 1);
                }
                tell = dec.tell();
            }

            if (LM > 0 && tell + 3 <= total_bits)
            {
                isTransient = dec.dec_bit_logp(3);
                tell        = dec.tell();
            }
            else
            {
                isTransient = 0;
            }

            if (isTransient != 0)
            {
                shortBlocks = M;
            }
            else
            {
                shortBlocks = 0;
            }

            /* Decode the global flags (first symbols in the stream) */
            intra_ener = tell + 3 <= total_bits?dec.dec_bit_logp(3) : 0;

            /* Get band energies */
            QuantizeBands.unquant_coarse_energy(mode, start, end, oldBandE,
                                                intra_ener, dec, C, LM);

            tf_res = new int[nbEBands];
            CeltCommon.tf_decode(start, end, isTransient, tf_res, LM, dec);

            tell            = dec.tell();
            spread_decision = Spread.SPREAD_NORMAL;
            if (tell + 4 <= total_bits)
            {
                spread_decision = dec.dec_icdf(Tables.spread_icdf, 5);
            }

            cap = new int[nbEBands];

            CeltCommon.init_caps(mode, cap, LM, C);

            offsets = new int[nbEBands];

            dynalloc_logp = 6;
            total_bits  <<= EntropyCoder.BITRES;
            tell          = (int)dec.tell_frac();
            for (i = start; i < end; i++)
            {
                int width, quanta;
                int dynalloc_loop_logp;
                int boost;
                width = C * (eBands[i + 1] - eBands[i]) << LM;

                /* quanta is 6 bits, but no more than 1 bit/sample
                 * and no less than 1/8 bit/sample */
                quanta             = Inlines.IMIN(width << EntropyCoder.BITRES, Inlines.IMAX(6 << EntropyCoder.BITRES, width));
                dynalloc_loop_logp = dynalloc_logp;
                boost = 0;
                while (tell + (dynalloc_loop_logp << EntropyCoder.BITRES) < total_bits && boost < cap[i])
                {
                    int flag;
                    flag = dec.dec_bit_logp((uint)dynalloc_loop_logp);
                    tell = (int)dec.tell_frac();
                    if (flag == 0)
                    {
                        break;
                    }
                    boost             += quanta;
                    total_bits        -= quanta;
                    dynalloc_loop_logp = 1;
                }
                offsets[i] = boost;
                /* Making dynalloc more likely */
                if (boost > 0)
                {
                    dynalloc_logp = Inlines.IMAX(2, dynalloc_logp - 1);
                }
            }

            fine_quant = new int[nbEBands];
            alloc_trim = tell + (6 << EntropyCoder.BITRES) <= total_bits?
                         dec.dec_icdf(Tables.trim_icdf, 7) : 5;

            bits = (((int)len * 8) << EntropyCoder.BITRES) - (int)dec.tell_frac() - 1;
            anti_collapse_rsv = isTransient != 0 && LM >= 2 && bits >= ((LM + 2) << EntropyCoder.BITRES) ? (1 << EntropyCoder.BITRES) : 0;
            bits -= anti_collapse_rsv;

            pulses        = new int[nbEBands];
            fine_priority = new int[nbEBands];

            codedBands = Rate.compute_allocation(mode, start, end, offsets, cap,
                                                 alloc_trim, ref intensity, ref dual_stereo, bits, out balance, pulses,
                                                 fine_quant, fine_priority, C, LM, dec, 0, 0, 0);

            QuantizeBands.unquant_fine_energy(mode, start, end, oldBandE, fine_quant, dec, C);

            c = 0;
            do
            {
                Arrays.MemMoveInt(decode_mem[c], N, 0, CeltConstants.DECODE_BUFFER_SIZE - N + overlap / 2);
            } while (++c < CC);

            /* Decode fixed codebook */
            collapse_masks = new byte[C * nbEBands];

            X = Arrays.InitTwoDimensionalArray <int>(C, N);   /**< Interleaved normalised MDCTs */

            Bands.quant_all_bands(0, mode, start, end, X[0], C == 2 ? X[1] : null, collapse_masks,
                                  null, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
                                  len * (8 << EntropyCoder.BITRES) - anti_collapse_rsv, balance, dec, LM, codedBands, ref this.rng);

            if (anti_collapse_rsv > 0)
            {
                anti_collapse_on = (int)dec.dec_bits(1);
            }

            QuantizeBands.unquant_energy_finalise(mode, start, end, oldBandE,
                                                  fine_quant, fine_priority, len * 8 - dec.tell(), dec, C);

            if (anti_collapse_on != 0)
            {
                Bands.anti_collapse(mode, X, collapse_masks, LM, C, N,
                                    start, end, oldBandE, oldLogE, oldLogE2, pulses, this.rng);
            }

            if (silence != 0)
            {
                for (i = 0; i < C * nbEBands; i++)
                {
                    oldBandE[i] = -((short)(0.5 + (28.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(28.0f, CeltConstants.DB_SHIFT)*/;
                }
            }

            CeltCommon.celt_synthesis(mode, X, out_syn, out_syn_ptrs, oldBandE, start, effEnd,
                                      C, CC, isTransient, LM, this.downsample, silence);

            c = 0; do
            {
                this.postfilter_period     = Inlines.IMAX(this.postfilter_period, CeltConstants.COMBFILTER_MINPERIOD);
                this.postfilter_period_old = Inlines.IMAX(this.postfilter_period_old, CeltConstants.COMBFILTER_MINPERIOD);
                CeltCommon.comb_filter(out_syn[c], out_syn_ptrs[c], out_syn[c], out_syn_ptrs[c], this.postfilter_period_old, this.postfilter_period, mode.shortMdctSize,
                                       this.postfilter_gain_old, this.postfilter_gain, this.postfilter_tapset_old, this.postfilter_tapset,
                                       mode.window, overlap);
                if (LM != 0)
                {
                    CeltCommon.comb_filter(
                        out_syn[c], out_syn_ptrs[c] + (mode.shortMdctSize),
                        out_syn[c], out_syn_ptrs[c] + (mode.shortMdctSize),
                        this.postfilter_period, postfilter_pitch, N - mode.shortMdctSize,
                        this.postfilter_gain, postfilter_gain, this.postfilter_tapset, postfilter_tapset,
                        mode.window, overlap);
                }
            } while (++c < CC);
            this.postfilter_period_old = this.postfilter_period;
            this.postfilter_gain_old   = this.postfilter_gain;
            this.postfilter_tapset_old = this.postfilter_tapset;
            this.postfilter_period     = postfilter_pitch;
            this.postfilter_gain       = postfilter_gain;
            this.postfilter_tapset     = postfilter_tapset;
            if (LM != 0)
            {
                this.postfilter_period_old = this.postfilter_period;
                this.postfilter_gain_old   = this.postfilter_gain;
                this.postfilter_tapset_old = this.postfilter_tapset;
            }

            if (C == 1)
            {
                Array.Copy(oldBandE, 0, oldBandE, nbEBands, nbEBands);
            }

            /* In case start or end were to change */
            if (isTransient == 0)
            {
                int max_background_increase;
                Array.Copy(oldLogE, oldLogE2, 2 * nbEBands);
                Array.Copy(oldBandE, oldLogE, 2 * nbEBands);

                /* In normal circumstances, we only allow the noise floor to increase by
                 * up to 2.4 dB/second, but when we're in DTX, we allow up to 6 dB
                 * increase for each update.*/
                if (this.loss_count < 10)
                {
                    max_background_increase = M * ((short)(0.5 + (0.001f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(0.001f, CeltConstants.DB_SHIFT)*/;
                }
                else
                {
                    max_background_increase = ((short)(0.5 + (1.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(1.0f, CeltConstants.DB_SHIFT)*/;
                }
                for (i = 0; i < 2 * nbEBands; i++)
                {
                    backgroundLogE[i] = Inlines.MIN16(backgroundLogE[i] + max_background_increase, oldBandE[i]);
                }
            }
            else
            {
                for (i = 0; i < 2 * nbEBands; i++)
                {
                    oldLogE[i] = Inlines.MIN16(oldLogE[i], oldBandE[i]);
                }
            }
            c = 0; do
            {
                for (i = 0; i < start; i++)
                {
                    oldBandE[c * nbEBands + i] = 0;
                    oldLogE[c * nbEBands + i]  = oldLogE2[c * nbEBands + i] = -((short)(0.5 + (28.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(28.0f, CeltConstants.DB_SHIFT)*/;
                }
                for (i = end; i < nbEBands; i++)
                {
                    oldBandE[c * nbEBands + i] = 0;
                    oldLogE[c * nbEBands + i]  = oldLogE2[c * nbEBands + i] = -((short)(0.5 + (28.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(28.0f, CeltConstants.DB_SHIFT)*/;
                }
            } while (++c < 2);
            this.rng = dec.rng;

            CeltCommon.deemphasis(out_syn, out_syn_ptrs, pcm, pcm_ptr, N, CC, this.downsample, mode.preemph, this.preemph_memD, accum);
            this.loss_count = 0;

            if (dec.tell() > 8 * len)
            {
                return(OpusError.OPUS_INTERNAL_ERROR);
            }
            if (dec.get_error() != 0)
            {
                this.error = 1;
            }
            return(frame_size / this.downsample);
        }
Ejemplo n.º 21
0
 internal static int decode_pulses(int[] _y, int _n, int _k, EntropyCoder _dec)
 {
     return(cwrsi(_n, _k, _dec.dec_uint(CELT_PVQ_V(_n, _k)), _y));
 }
Ejemplo n.º 22
0
 /// <summary>
 /// Entropy code the mid-only flag
 /// </summary>
 /// <param name="psRangeEnc">I/O  Compressor data structure</param>
 /// <param name="mid_only_flag"></param>
 internal static void silk_stereo_encode_mid_only(EntropyCoder psRangeEnc, sbyte mid_only_flag)
 {
     /* Encode flag that only mid channel is coded */
     psRangeEnc.enc_icdf(mid_only_flag, Tables.silk_stereo_only_code_mid_iCDF, 8);
 }
Ejemplo n.º 23
0
        internal static int compute_allocation(CeltMode m, int start, int end, int[] offsets, int[] cap, int alloc_trim, ref int intensity, ref int dual_stereo,
                                               int total, out int balance, int[] pulses, int[] ebits, int[] fine_priority, int C, int LM, EntropyCoder ec, int encode, int prev, int signalBandwidth)
        {
            int lo, hi, len, j;
            int codedBands;
            int skip_start;
            int skip_rsv;
            int intensity_rsv;
            int dual_stereo_rsv;

            total      = Inlines.IMAX(total, 0);
            len        = m.nbEBands;
            skip_start = start;
            /* Reserve a bit to signal the end of manually skipped bands. */
            skip_rsv = total >= 1 << EntropyCoder.BITRES ? 1 << EntropyCoder.BITRES : 0;
            total   -= skip_rsv;
            /* Reserve bits for the intensity and dual stereo parameters. */
            intensity_rsv = dual_stereo_rsv = 0;
            if (C == 2)
            {
                intensity_rsv = LOG2_FRAC_TABLE[end - start];
                if (intensity_rsv > total)
                {
                    intensity_rsv = 0;
                }
                else
                {
                    total          -= intensity_rsv;
                    dual_stereo_rsv = total >= 1 << EntropyCoder.BITRES ? 1 << EntropyCoder.BITRES : 0;
                    total          -= dual_stereo_rsv;
                }
            }

            int[] bits1       = new int[len];
            int[] bits2       = new int[len];
            int[] thresh      = new int[len];
            int[] trim_offset = new int[len];

            for (j = start; j < end; j++)
            {
                /* Below this threshold, we're sure not to allocate any PVQ bits */
                thresh[j] = Inlines.IMAX((C) << EntropyCoder.BITRES, (3 * (m.eBands[j + 1] - m.eBands[j]) << LM << EntropyCoder.BITRES) >> 4);
                /* Tilt of the allocation curve */
                trim_offset[j] = C * (m.eBands[j + 1] - m.eBands[j]) * (alloc_trim - 5 - LM) * (end - j - 1)
                                 * (1 << (LM + EntropyCoder.BITRES)) >> 6;

                /* Giving less resolution to single-coefficient bands because they get
                 * more benefit from having one coarse value per coefficient*/
                if ((m.eBands[j + 1] - m.eBands[j]) << LM == 1)
                {
                    trim_offset[j] -= C << EntropyCoder.BITRES;
                }
            }
            lo = 1;
            hi = m.nbAllocVectors - 1;
            do
            {
                int done = 0;
                int psum = 0;
                int mid  = (lo + hi) >> 1;
                for (j = end; j-- > start;)
                {
                    int bitsj;
                    int N = m.eBands[j + 1] - m.eBands[j];
                    bitsj = C * N * m.allocVectors[mid * len + j] << LM >> 2;

                    if (bitsj > 0)
                    {
                        bitsj = Inlines.IMAX(0, bitsj + trim_offset[j]);
                    }

                    bitsj += offsets[j];

                    if (bitsj >= thresh[j] || done != 0)
                    {
                        done = 1;
                        /* Don't allocate more than we can actually use */
                        psum += Inlines.IMIN(bitsj, cap[j]);
                    }
                    else
                    {
                        if (bitsj >= C << EntropyCoder.BITRES)
                        {
                            psum += C << EntropyCoder.BITRES;
                        }
                    }
                }
                if (psum > total)
                {
                    hi = mid - 1;
                }
                else
                {
                    lo = mid + 1;
                }
                /*printf ("lo = %d, hi = %d\n", lo, hi);*/
            } while (lo <= hi);

            hi = lo--;
            /*printf ("interp between %d and %d\n", lo, hi);*/

            for (j = start; j < end; j++)
            {
                int bits1j, bits2j;
                int N = m.eBands[j + 1] - m.eBands[j];
                bits1j = C * N * m.allocVectors[lo * len + j] << LM >> 2;
                bits2j = hi >= m.nbAllocVectors ?
                         cap[j] : C * N * m.allocVectors[hi * len + j] << LM >> 2;
                if (bits1j > 0)
                {
                    bits1j = Inlines.IMAX(0, bits1j + trim_offset[j]);
                }
                if (bits2j > 0)
                {
                    bits2j = Inlines.IMAX(0, bits2j + trim_offset[j]);
                }
                if (lo > 0)
                {
                    bits1j += offsets[j];
                }
                bits2j += offsets[j];
                if (offsets[j] > 0)
                {
                    skip_start = j;
                }
                bits2j   = Inlines.IMAX(0, bits2j - bits1j);
                bits1[j] = bits1j;
                bits2[j] = bits2j;
            }

            codedBands = interp_bits2pulses(m, start, end, skip_start, bits1, bits2, thresh, cap,
                                            total, out balance, skip_rsv, ref intensity, intensity_rsv, ref dual_stereo, dual_stereo_rsv,
                                            pulses, ebits, fine_priority, C, LM, ec, encode, prev, signalBandwidth);

            return(codedBands);
        }
Ejemplo n.º 24
0
        internal static int interp_bits2pulses(CeltMode m, int start, int end, int skip_start,
                                               int[] bits1, int[] bits2, int[] thresh, int[] cap, int total, out int _balance,
                                               int skip_rsv, ref int intensity, int intensity_rsv, ref int dual_stereo, int dual_stereo_rsv, int[] bits,
                                               int[] ebits, int[] fine_priority, int C, int LM, EntropyCoder ec, int encode, int prev, int signalBandwidth)
        {
            int psum;
            int lo, hi;
            int i, j;
            int logM;
            int stereo;
            int codedBands = -1;
            int alloc_floor;
            int left, percoeff;
            int done;
            int balance;


            alloc_floor = C << EntropyCoder.BITRES;
            stereo      = C > 1 ? 1 : 0;

            logM = LM << EntropyCoder.BITRES;
            lo   = 0;
            hi   = 1 << ALLOC_STEPS;
            for (i = 0; i < ALLOC_STEPS; i++)
            {
                int mid = (lo + hi) >> 1;
                psum = 0;
                done = 0;
                for (j = end; j-- > start;)
                {
                    int tmp = bits1[j] + (mid * (int)bits2[j] >> ALLOC_STEPS);
                    if (tmp >= thresh[j] || done != 0)
                    {
                        done = 1;
                        /* Don't allocate more than we can actually use */
                        psum += Inlines.IMIN(tmp, cap[j]);
                    }
                    else
                    {
                        if (tmp >= alloc_floor)
                        {
                            psum += alloc_floor;
                        }
                    }
                }
                if (psum > total)
                {
                    hi = mid;
                }
                else
                {
                    lo = mid;
                }
            }
            psum = 0;
            /*printf ("interp bisection gave %d\n", lo);*/
            done = 0;
            for (j = end; j-- > start;)
            {
                int tmp = bits1[j] + (lo * bits2[j] >> ALLOC_STEPS);
                if (tmp < thresh[j] && done == 0)
                {
                    if (tmp >= alloc_floor)
                    {
                        tmp = alloc_floor;
                    }
                    else
                    {
                        tmp = 0;
                    }
                }
                else
                {
                    done = 1;
                }

                /* Don't allocate more than we can actually use */
                tmp     = Inlines.IMIN(tmp, cap[j]);
                bits[j] = tmp;
                psum   += tmp;
            }

            /* Decide which bands to skip, working backwards from the end. */
            for (codedBands = end; ; codedBands--)
            {
                int band_width;
                int band_bits;
                int rem;
                j = codedBands - 1;

                /* Never skip the first band, nor a band that has been boosted by
                 *  dynalloc.
                 * In the first case, we'd be coding a bit to signal we're going to waste
                 *  all the other bits.
                 * In the second case, we'd be coding a bit to redistribute all the bits
                 *  we just signaled should be cocentrated in this band. */
                if (j <= skip_start)
                {
                    /* Give the bit we reserved to end skipping back. */
                    total += skip_rsv;
                    break;
                }

                /*Figure out how many left-over bits we would be adding to this band.
                *  This can include bits we've stolen back from higher, skipped bands.*/
                left       = total - psum;
                percoeff   = Inlines.celt_udiv(left, m.eBands[codedBands] - m.eBands[start]);
                left      -= (m.eBands[codedBands] - m.eBands[start]) * percoeff;
                rem        = Inlines.IMAX(left - (m.eBands[j] - m.eBands[start]), 0);
                band_width = m.eBands[codedBands] - m.eBands[j];
                band_bits  = (int)(bits[j] + percoeff * band_width + rem);

                /*Only code a skip decision if we're above the threshold for this band.
                 * Otherwise it is force-skipped.
                 * This ensures that we have enough bits to code the skip flag.*/
                if (band_bits >= Inlines.IMAX(thresh[j], alloc_floor + (1 << EntropyCoder.BITRES)))
                {
                    if (encode != 0)
                    {
                        /*This if() block is the only part of the allocation function that
                         * is not a mandatory part of the bitstream: any bands we choose to
                         * skip here must be explicitly signaled.*/
                        /*Choose a threshold with some hysteresis to keep bands from
                         * fluctuating in and out.*/
#if FUZZING
                        if ((new Random().Next() & 0x1) == 0)
#else
                        if (codedBands <= start + 2 || (band_bits > ((j < prev ? 7 : 9) * band_width << LM << EntropyCoder.BITRES) >> 4 && j <= signalBandwidth))
#endif
                        {
                            ec.enc_bit_logp(1, 1);
                            break;
                        }
                        ec.enc_bit_logp(0, 1);
                    }
                    else if (ec.dec_bit_logp(1) != 0)
                    {
                        break;
                    }
                    /*We used a bit to skip this band.*/
                    psum      += 1 << EntropyCoder.BITRES;
                    band_bits -= 1 << EntropyCoder.BITRES;
                }
                /*Reclaim the bits originally allocated to this band.*/
                psum -= bits[j] + intensity_rsv;
                if (intensity_rsv > 0)
                {
                    intensity_rsv = LOG2_FRAC_TABLE[j - start];
                }
                psum += intensity_rsv;
                if (band_bits >= alloc_floor)
                {
                    /*If we have enough for a fine energy bit per channel, use it.*/
                    psum   += alloc_floor;
                    bits[j] = alloc_floor;
                }
                else
                {
                    /*Otherwise this band gets nothing at all.*/
                    bits[j] = 0;
                }
            }

            Inlines.OpusAssert(codedBands > start);
            /* Code the intensity and dual stereo parameters. */
            if (intensity_rsv > 0)
            {
                if (encode != 0)
                {
                    intensity = Inlines.IMIN(intensity, codedBands);
                    ec.enc_uint((uint)(intensity - start), (uint)(codedBands + 1 - start));
                }
                else
                {
                    intensity = start + (int)ec.dec_uint((uint)(codedBands + 1 - start));
                }
            }
            else
            {
                intensity = 0;
            }

            if (intensity <= start)
            {
                total          += dual_stereo_rsv;
                dual_stereo_rsv = 0;
            }
            if (dual_stereo_rsv > 0)
            {
                if (encode != 0)
                {
                    ec.enc_bit_logp(dual_stereo, 1);
                }
                else
                {
                    dual_stereo = ec.dec_bit_logp(1);
                }
            }
            else
            {
                dual_stereo = 0;
            }

            /* Allocate the remaining bits */
            left     = total - psum;
            percoeff = Inlines.celt_udiv(left, m.eBands[codedBands] - m.eBands[start]);
            left    -= (m.eBands[codedBands] - m.eBands[start]) * percoeff;
            for (j = start; j < codedBands; j++)
            {
                bits[j] += ((int)percoeff * (m.eBands[j + 1] - m.eBands[j]));
            }
            for (j = start; j < codedBands; j++)
            {
                int tmp = (int)Inlines.IMIN(left, m.eBands[j + 1] - m.eBands[j]);
                bits[j] += tmp;
                left    -= tmp;
            }
            /*for (j=0;j<end;j++)printf("%d ", bits[j]);printf("\n");*/

            balance = 0;
            for (j = start; j < codedBands; j++)
            {
                int N0, N, den;
                int offset;
                int NClogN;
                int excess, bit;

                Inlines.OpusAssert(bits[j] >= 0);
                N0  = m.eBands[j + 1] - m.eBands[j];
                N   = N0 << LM;
                bit = (int)bits[j] + balance;

                if (N > 1)
                {
                    excess  = Inlines.MAX32(bit - cap[j], 0);
                    bits[j] = bit - excess;

                    /* Compensate for the extra DoF in stereo */
                    den = (C * N + ((C == 2 && N > 2 && (dual_stereo == 0) && j < intensity) ? 1 : 0));

                    NClogN = den * (m.logN[j] + logM);

                    /* Offset for the number of fine bits by log2(N)/2 + FINE_OFFSET
                     * compared to their "fair share" of total/N */
                    offset = (NClogN >> 1) - den * CeltConstants.FINE_OFFSET;

                    /* N=2 is the only point that doesn't match the curve */
                    if (N == 2)
                    {
                        offset += den << EntropyCoder.BITRES >> 2;
                    }

                    /* Changing the offset for allocating the second and third
                     *  fine energy bit */
                    if (bits[j] + offset < den * 2 << EntropyCoder.BITRES)
                    {
                        offset += NClogN >> 2;
                    }
                    else if (bits[j] + offset < den * 3 << EntropyCoder.BITRES)
                    {
                        offset += NClogN >> 3;
                    }

                    /* Divide with rounding */
                    ebits[j] = Inlines.IMAX(0, (bits[j] + offset + (den << (EntropyCoder.BITRES - 1))));
                    ebits[j] = Inlines.celt_udiv(ebits[j], den) >> EntropyCoder.BITRES;

                    /* Make sure not to bust */
                    if (C * ebits[j] > (bits[j] >> EntropyCoder.BITRES))
                    {
                        ebits[j] = bits[j] >> stereo >> EntropyCoder.BITRES;
                    }

                    /* More than that is useless because that's about as far as PVQ can go */
                    ebits[j] = Inlines.IMIN(ebits[j], CeltConstants.MAX_FINE_BITS);

                    /* If we rounded down or capped this band, make it a candidate for the
                     *  final fine energy pass */
                    fine_priority[j] = (ebits[j] * (den << EntropyCoder.BITRES) >= bits[j] + offset) ? 1 : 0;

                    /* Remove the allocated fine bits; the rest are assigned to PVQ */
                    bits[j] -= C * ebits[j] << EntropyCoder.BITRES;
                }
                else
                {
                    /* For N=1, all bits go to fine energy except for a single sign bit */
                    excess           = Inlines.MAX32(0, bit - (C << EntropyCoder.BITRES));
                    bits[j]          = bit - excess;
                    ebits[j]         = 0;
                    fine_priority[j] = 1;
                }

                /* Fine energy can't take advantage of the re-balancing in
                 *  quant_all_bands().
                 * Instead, do the re-balancing here.*/
                if (excess > 0)
                {
                    int extra_fine;
                    int extra_bits;
                    extra_fine       = Inlines.IMIN(excess >> (stereo + EntropyCoder.BITRES), CeltConstants.MAX_FINE_BITS - ebits[j]);
                    ebits[j]        += extra_fine;
                    extra_bits       = extra_fine * C << EntropyCoder.BITRES;
                    fine_priority[j] = (extra_bits >= excess - balance) ? 1 : 0;
                    excess          -= extra_bits;
                }
                balance = excess;

                Inlines.OpusAssert(bits[j] >= 0);
                Inlines.OpusAssert(ebits[j] >= 0);
            }

            /* Save any remaining bits over the cap for the rebalancing in
             *  quant_all_bands(). */
            _balance = balance;

            /* The skipped bands use all their bits for fine energy. */
            for (; j < end; j++)
            {
                ebits[j] = bits[j] >> stereo >> EntropyCoder.BITRES;
                Inlines.OpusAssert(C * ebits[j] << EntropyCoder.BITRES == bits[j]);
                bits[j]          = 0;
                fine_priority[j] = (ebits[j] < 1) ? 1 : 0;
            }

            return(codedBands);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Encode quantization indices of excitation
        /// </summary>
        /// <param name="psRangeEnc">I/O  compressor data structure</param>
        /// <param name="signalType">I    Signal type</param>
        /// <param name="quantOffsetType">I    quantOffsetType</param>
        /// <param name="pulses">I    quantization indices</param>
        /// <param name="frame_length">I    Frame length</param>
        internal static void silk_encode_pulses(
            EntropyCoder psRangeEnc,
            int signalType,
            int quantOffsetType,
            sbyte[] pulses,
            int frame_length)
        {
            int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0;
            int abs_q, minSumBits_Q5, sumBits_Q5;

            int[] abs_pulses;
            int[] sum_pulses;
            int[] nRshifts;
            int[] pulses_comb = new int[8];
            int   abs_pulses_ptr;
            int   pulses_ptr;

            byte[] nBits_ptr;

            Arrays.MemSetInt(pulses_comb, 0, 8);

            /****************************/
            /* Prepare for shell coding */
            /****************************/
            /* Calculate number of shell blocks */
            Inlines.OpusAssert(1 << SilkConstants.LOG2_SHELL_CODEC_FRAME_LENGTH == SilkConstants.SHELL_CODEC_FRAME_LENGTH);
            iter = Inlines.silk_RSHIFT(frame_length, SilkConstants.LOG2_SHELL_CODEC_FRAME_LENGTH);
            if (iter * SilkConstants.SHELL_CODEC_FRAME_LENGTH < frame_length)
            {
                Inlines.OpusAssert(frame_length == 12 * 10); /* Make sure only happens for 10 ms @ 12 kHz */
                iter++;
                Arrays.MemSetWithOffset <sbyte>(pulses, 0, frame_length, SilkConstants.SHELL_CODEC_FRAME_LENGTH);
            }

            /* Take the absolute value of the pulses */
            abs_pulses = new int[iter * SilkConstants.SHELL_CODEC_FRAME_LENGTH];
            Inlines.OpusAssert((SilkConstants.SHELL_CODEC_FRAME_LENGTH & 3) == 0);

            // unrolled loop
            for (i = 0; i < iter * SilkConstants.SHELL_CODEC_FRAME_LENGTH; i += 4)
            {
                abs_pulses[i + 0] = (int)Inlines.silk_abs(pulses[i + 0]);
                abs_pulses[i + 1] = (int)Inlines.silk_abs(pulses[i + 1]);
                abs_pulses[i + 2] = (int)Inlines.silk_abs(pulses[i + 2]);
                abs_pulses[i + 3] = (int)Inlines.silk_abs(pulses[i + 3]);
            }

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

                while (true)
                {
                    /* 1+1 . 2 */
                    scale_down = combine_and_check(pulses_comb, 0, abs_pulses, abs_pulses_ptr, Tables.silk_max_pulses_table[0], 8);
                    /* 2+2 . 4 */
                    scale_down += combine_and_check(pulses_comb, pulses_comb, Tables.silk_max_pulses_table[1], 4);
                    /* 4+4 . 8 */
                    scale_down += combine_and_check(pulses_comb, pulses_comb, Tables.silk_max_pulses_table[2], 2);
                    /* 8+8 . 16 */
                    scale_down += combine_and_check(sum_pulses, i, pulses_comb, 0, Tables.silk_max_pulses_table[3], 1);

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

                abs_pulses_ptr += SilkConstants.SHELL_CODEC_FRAME_LENGTH;
            }

            /**************/
            /* Rate level */
            /**************/
            /* find rate level that leads to fewest bits for coding of pulses per block info */
            minSumBits_Q5 = int.MaxValue;
            for (k = 0; k < SilkConstants.N_RATE_LEVELS - 1; k++)
            {
                nBits_ptr  = Tables.silk_pulses_per_block_BITS_Q5[k];
                sumBits_Q5 = Tables.silk_rate_levels_BITS_Q5[signalType >> 1][k];
                for (i = 0; i < iter; i++)
                {
                    if (nRshifts[i] > 0)
                    {
                        sumBits_Q5 += nBits_ptr[SilkConstants.SILK_MAX_PULSES + 1];
                    }
                    else
                    {
                        sumBits_Q5 += nBits_ptr[sum_pulses[i]];
                    }
                }
                if (sumBits_Q5 < minSumBits_Q5)
                {
                    minSumBits_Q5  = sumBits_Q5;
                    RateLevelIndex = k;
                }
            }

            psRangeEnc.enc_icdf(RateLevelIndex, Tables.silk_rate_levels_iCDF[signalType >> 1], 8);

            /***************************************************/
            /* Sum-Weighted-Pulses Encoding                    */
            /***************************************************/
            for (i = 0; i < iter; i++)
            {
                if (nRshifts[i] == 0)
                {
                    psRangeEnc.enc_icdf(sum_pulses[i], Tables.silk_pulses_per_block_iCDF[RateLevelIndex], 8);
                }
                else
                {
                    psRangeEnc.enc_icdf(SilkConstants.SILK_MAX_PULSES + 1, Tables.silk_pulses_per_block_iCDF[RateLevelIndex], 8);
                    for (k = 0; k < nRshifts[i] - 1; k++)
                    {
                        psRangeEnc.enc_icdf(SilkConstants.SILK_MAX_PULSES + 1, Tables.silk_pulses_per_block_iCDF[SilkConstants.N_RATE_LEVELS - 1], 8);
                    }

                    psRangeEnc.enc_icdf(sum_pulses[i], Tables.silk_pulses_per_block_iCDF[SilkConstants.N_RATE_LEVELS - 1], 8);
                }
            }

            /******************/
            /* Shell Encoding */
            /******************/
            for (i = 0; i < iter; i++)
            {
                if (sum_pulses[i] > 0)
                {
                    ShellCoder.silk_shell_encoder(psRangeEnc, abs_pulses, i * SilkConstants.SHELL_CODEC_FRAME_LENGTH);
                }
            }

            /****************/
            /* LSB Encoding */
            /****************/
            for (i = 0; i < iter; i++)
            {
                if (nRshifts[i] > 0)
                {
                    pulses_ptr = i * SilkConstants.SHELL_CODEC_FRAME_LENGTH;
                    nLS        = nRshifts[i] - 1;
                    for (k = 0; k < SilkConstants.SHELL_CODEC_FRAME_LENGTH; k++)
                    {
                        abs_q = (sbyte)Inlines.silk_abs(pulses[pulses_ptr + k]);
                        for (j = nLS; j > 0; j--)
                        {
                            bit = Inlines.silk_RSHIFT(abs_q, j) & 1;
                            psRangeEnc.enc_icdf(bit, Tables.silk_lsb_iCDF, 8);
                        }
                        bit = abs_q & 1;
                        psRangeEnc.enc_icdf(bit, Tables.silk_lsb_iCDF, 8);
                    }
                }
            }

            /****************/
            /* Encode signs */
            /****************/
            CodeSigns.silk_encode_signs(psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses);
        }
Ejemplo n.º 26
0
        internal static void unquant_energy_finalise(CeltMode m, int start, int end, int[] oldEBands, int[] fine_quant, int[] fine_priority, int bits_left, EntropyCoder dec, int C)
        {
            int i, prio, c;

            /* Use up the remaining bits */
            for (prio = 0; prio < 2; prio++)
            {
                for (i = start; i < end && bits_left >= C; i++)
                {
                    if (fine_quant[i] >= CeltConstants.MAX_FINE_BITS || fine_priority[i] != prio)
                    {
                        continue;
                    }
                    c = 0;
                    do
                    {
                        int q2;
                        int offset;
                        q2     = (int)dec.dec_bits(1);
                        offset = Inlines.SHR16((Inlines.SHL16((q2), CeltConstants.DB_SHIFT) - ((short)(0.5 + (.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(.5f, CeltConstants.DB_SHIFT)*/), fine_quant[i] + 1);
                        oldEBands[i + c * m.nbEBands] += offset;
                        bits_left--;
                    } while (++c < C);
                }
            }
        }
Ejemplo n.º 27
0
        internal static int quant_coarse_energy_impl(CeltMode m, int start, int end,
                                                     int[][] eBands, int[][] oldEBands,
                                                     int budget, int tell,
                                                     byte[] prob_model, int[][] error, EntropyCoder enc,
                                                     int C, int LM, int intra, int max_decay, int lfe)
        {
            int i, c;
            int badness = 0;

            int[] prev = { 0, 0 };
            int   coef;
            int   beta;

            if (tell + 3 <= budget)
            {
                enc.enc_bit_logp(intra, 3);
            }

            if (intra != 0)
            {
                coef = 0;
                beta = beta_intra;
            }
            else
            {
                beta = beta_coef[LM];
                coef = pred_coef[LM];
            }

            /* Encode at a fixed coarse resolution */
            for (i = start; i < end; i++)
            {
                c = 0;
                do
                {
                    int bits_left;
                    int qi, qi0;
                    int q;
                    int x;
                    int f, tmp;
                    int oldE;
                    int decay_bound;
                    x    = eBands[c][i];
                    oldE = Inlines.MAX16(-((short)(0.5 + (9.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(9.0f, CeltConstants.DB_SHIFT)*/, oldEBands[c][i]);
                    f    = Inlines.SHL32(Inlines.EXTEND32(x), 7) - Inlines.PSHR32(Inlines.MULT16_16(coef, oldE), 8) - prev[c];
                    /* Rounding to nearest integer here is really important! */
                    qi          = (f + ((int)(0.5 + (.5f) * (((int)1) << (CeltConstants.DB_SHIFT + 7)))) /*Inlines.QCONST32(.5f, CeltConstants.DB_SHIFT + 7)*/) >> (CeltConstants.DB_SHIFT + 7);
                    decay_bound = Inlines.EXTRACT16(Inlines.MAX32(-((short)(0.5 + (28.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(28.0f, CeltConstants.DB_SHIFT)*/,
                                                                  Inlines.SUB32((int)oldEBands[c][i], max_decay)));

                    /* Prevent the energy from going down too quickly (e.g. for bands
                     * that have just one bin) */
                    if (qi < 0 && x < decay_bound)
                    {
                        qi += (int)Inlines.SHR16(Inlines.SUB16(decay_bound, x), CeltConstants.DB_SHIFT);
                        if (qi > 0)
                        {
                            qi = 0;
                        }
                    }
                    qi0 = qi;

                    /* If we don't have enough bits to encode all the energy, just assume
                     *  something safe. */
                    tell      = enc.tell();
                    bits_left = budget - tell - 3 * C * (end - i);
                    if (i != start && bits_left < 30)
                    {
                        if (bits_left < 24)
                        {
                            qi = Inlines.IMIN(1, qi);
                        }
                        if (bits_left < 16)
                        {
                            qi = Inlines.IMAX(-1, qi);
                        }
                    }
                    if (lfe != 0 && i >= 2)
                    {
                        qi = Inlines.IMIN(qi, 0);
                    }
                    if (budget - tell >= 15)
                    {
                        int pi;
                        pi = 2 * Inlines.IMIN(i, 20);
                        Laplace.ec_laplace_encode(enc, ref qi, (((uint)prob_model[pi]) << 7), ((int)prob_model[pi + 1]) << 6);
                    }
                    else if (budget - tell >= 2)
                    {
                        qi = Inlines.IMAX(-1, Inlines.IMIN(qi, 1));
                        enc.enc_icdf(2 * qi ^ (0 - (qi < 0 ? 1 : 0)), small_energy_icdf, 2);
                    }
                    else if (budget - tell >= 1)
                    {
                        qi = Inlines.IMIN(0, qi);
                        enc.enc_bit_logp(-qi, 1);
                    }
                    else
                    {
                        qi = -1;
                    }
                    error[c][i] = (Inlines.PSHR32(f, 7) - Inlines.SHL16((qi), CeltConstants.DB_SHIFT));
                    badness    += Inlines.abs(qi0 - qi);
                    q           = (int)Inlines.SHL32(qi, CeltConstants.DB_SHIFT); // opus bug: useless extend32

                    tmp             = Inlines.PSHR32(Inlines.MULT16_16(coef, oldE), 8) + prev[c] + Inlines.SHL32(q, 7);
                    tmp             = Inlines.MAX32(-((int)(0.5 + (28.0f) * (((int)1) << (CeltConstants.DB_SHIFT + 7)))) /*Inlines.QCONST32(28.0f, CeltConstants.DB_SHIFT + 7)*/, tmp);
                    oldEBands[c][i] = (Inlines.PSHR32(tmp, 7));
                    prev[c]         = prev[c] + Inlines.SHL32(q, 7) - Inlines.MULT16_16(beta, Inlines.PSHR32(q, 8));
                } while (++c < C);
            }
            return(lfe != 0 ? 0 : badness);
        }
Ejemplo n.º 28
0
        internal static uint alg_quant(int[] X, int X_ptr, int N, int K, int spread, int B, EntropyCoder enc
                                       )
        {
            int[] y = new int[N];
            int[] iy = new int[N];
            int[] signx = new int[N];
            int   i, j;
            int   s;
            int   pulsesLeft;
            int   sum;
            int   xy;
            int   yy;
            uint  collapse_mask;

            Inlines.OpusAssert(K > 0, "alg_quant() needs at least one pulse");
            Inlines.OpusAssert(N > 1, "alg_quant() needs at least two dimensions");

            exp_rotation(X, X_ptr, N, 1, B, K, spread);

            /* Get rid of the sign */
            sum = 0;
            j   = 0;
            do
            {
                int xpj = X_ptr + j;

                /* OPT: Make sure the following two lines result in conditional moves
                 * rather than branches. */
                signx[j] = X[xpj] > 0 ? 1 : -1;
                X[xpj]   = Inlines.ABS16(X[xpj]);

                iy[j] = 0;
                y[j]  = 0;
            } while (++j < N);

            xy = yy = 0;

            pulsesLeft = K;

            /* Do a pre-search by projecting on the pyramid */
            if (K > (N >> 1))
            {
                int rcp;
                j = 0; do
                {
                    sum += X[X_ptr + j];
                } while (++j < N);

                /* If X is too small, just replace it with a pulse at 0 */

                /* Prevents infinities and NaNs from causing too many pulses
                *  to be allocated. 64 is an approximation of infinity here. */
                if (sum <= K)
                {
                    X[X_ptr] = ((short)(0.5 + (1.0f) * (((int)1) << (14)))) /*Inlines.QCONST16(1.0f, 14)*/;
                    j        = X_ptr + 1;
                    do
                    {
                        X[j] = 0;
                    } while (++j < N + X_ptr);

                    sum = ((short)(0.5 + (1.0f) * (((int)1) << (14)))) /*Inlines.QCONST16(1.0f, 14)*/;
                }

                rcp = Inlines.EXTRACT16(Inlines.MULT16_32_Q16((K - 1), Inlines.celt_rcp(sum)));
                j   = 0;

                do
                {
                    /* It's really important to round *towards zero* here */
                    iy[j]       = Inlines.MULT16_16_Q15(X[X_ptr + j], rcp);
                    y[j]        = (int)iy[j];
                    yy          = (Inlines.MAC16_16(yy, y[j], y[j]));
                    xy          = Inlines.MAC16_16(xy, X[X_ptr + j], y[j]);
                    y[j]       *= 2;
                    pulsesLeft -= iy[j];
                } while (++j < N);
            }

            Inlines.OpusAssert(pulsesLeft >= 1, "Allocated too many pulses in the quick pass");

            /* This should never happen, but just in case it does (e.g. on silence)
             * we fill the first bin with pulses. */
            if (pulsesLeft > N + 3)
            {
                int tmp = (int)pulsesLeft;
                yy         = (Inlines.MAC16_16(yy, tmp, tmp));
                yy         = (Inlines.MAC16_16(yy, tmp, y[0]));
                iy[0]     += pulsesLeft;
                pulsesLeft = 0;
            }

            s = 1;
            for (i = 0; i < pulsesLeft; i++)
            {
                int best_id;
                int best_num = 0 - CeltConstants.VERY_LARGE16;
                int best_den = 0;
                int rshift   = 1 + Inlines.celt_ilog2(K - pulsesLeft + i + 1);
                best_id = 0;

                /* The squared magnitude term gets added anyway, so we might as well
                 * add it outside the loop */
                yy = Inlines.ADD16(yy, 1); // opus bug - was add32
                j  = 0;
                do
                {
                    int Rxy, Ryy;
                    /* Temporary sums of the new pulse(s) */
                    Rxy = Inlines.EXTRACT16(Inlines.SHR32(Inlines.ADD32(xy, Inlines.EXTEND32(X[X_ptr + j])), rshift));
                    /* We're multiplying y[j] by two so we don't have to do it here */
                    Ryy = Inlines.ADD16(yy, y[j]);

                    /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
                     * Rxy is positive because the sign is pre-computed) */
                    Rxy = Inlines.MULT16_16_Q15(Rxy, Rxy);

                    /* The idea is to check for num/den >= best_num/best_den, but that way
                     * we can do it without any division */
                    /* OPT: Make sure to use conditional moves here */
                    if (Inlines.MULT16_16(best_den, Rxy) > Inlines.MULT16_16(Ryy, best_num))
                    {
                        best_den = Ryy;
                        best_num = Rxy;
                        best_id  = j;
                    }
                } while (++j < N);

                /* Updating the sums of the new pulse(s) */
                xy = Inlines.ADD32(xy, Inlines.EXTEND32(X[X_ptr + best_id]));
                /* We're multiplying y[j] by two so we don't have to do it here */
                yy = Inlines.ADD16(yy, y[best_id]);

                /* Only now that we've made the final choice, update y/iy */
                /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
                y[best_id] = (y[best_id] + (2 * s));
                iy[best_id]++;
            }

            /* Put the original sign back */
            j = 0;
            do
            {
                X[X_ptr + j] = (Inlines.MULT16_16(signx[j], X[X_ptr + j]));

                /* OPT: Make sure your compiler uses a conditional move here rather than
                 *   a branch. */
                iy[j] = signx[j] < 0 ? -iy[j] : iy[j];
            } while (++j < N);

            CWRS.encode_pulses(iy, N, K, enc);

            collapse_mask = extract_collapse_mask(iy, N, B);

            return(collapse_mask);
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Encode frame with Silk
        /// Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what
        /// encControl.payloadSize_ms is set to
        /// </summary>
        /// <param name="psEnc">I/O  State</param>
        /// <param name="encControl">I    Control status</param>
        /// <param name="samplesIn">I    Speech sample input vector</param>
        /// <param name="nSamplesIn">I    Number of samples in input vector</param>
        /// <param name="psRangeEnc">I/O  Compressor data structure</param>
        /// <param name="nBytesOut">I/O  Number of bytes in payload (input: Max bytes)</param>
        /// <param name="prefillFlag">I    Flag to indicate prefilling buffers no coding</param>
        /// <returns>error code</returns>
        internal static int silk_Encode(
            SilkEncoder psEnc,
            EncControlState encControl,
            short[] samplesIn,
            int nSamplesIn,
            EntropyCoder psRangeEnc,
            BoxedValueInt nBytesOut,
            int prefillFlag)
        {
            int ret = SilkError.SILK_NO_ERROR;
            int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0;
            int nSamplesToBuffer, nSamplesToBufferMax, nBlocksOf10ms;
            int nSamplesFromInput = 0, nSamplesFromInputMax;
            int speech_act_thr_for_switch_Q8;
            int TargetRate_bps, channelRate_bps, LBRR_symbol, sum;

            int[]   MStargetRates_bps = new int[2];
            short[] buf;
            int     transition, curr_block, tot_blocks;

            nBytesOut.Val = 0;

            if (encControl.reducedDependency != 0)
            {
                psEnc.state_Fxx[0].first_frame_after_reset = 1;
                psEnc.state_Fxx[1].first_frame_after_reset = 1;
            }
            psEnc.state_Fxx[0].nFramesEncoded = psEnc.state_Fxx[1].nFramesEncoded = 0;

            /* Check values in encoder control structure */
            ret += encControl.check_control_input();
            if (ret != SilkError.SILK_NO_ERROR)
            {
                Inlines.OpusAssert(false);
                return(ret);
            }

            encControl.switchReady = 0;

            if (encControl.nChannelsInternal > psEnc.nChannelsInternal)
            {
                /* Mono . Stereo transition: init state of second channel and stereo state */
                ret += SilkEncoder.silk_init_encoder(psEnc.state_Fxx[1]);

                Arrays.MemSetShort(psEnc.sStereo.pred_prev_Q13, 0, 2);
                Arrays.MemSetShort(psEnc.sStereo.sSide, 0, 2);
                psEnc.sStereo.mid_side_amp_Q0[0] = 0;
                psEnc.sStereo.mid_side_amp_Q0[1] = 1;
                psEnc.sStereo.mid_side_amp_Q0[2] = 0;
                psEnc.sStereo.mid_side_amp_Q0[3] = 1;
                psEnc.sStereo.width_prev_Q14     = 0;
                psEnc.sStereo.smth_width_Q14     = (short)(((int)((1.0f) * ((long)1 << (14)) + 0.5)) /*Inlines.SILK_CONST(1.0f, 14)*/);
                if (psEnc.nChannelsAPI == 2)
                {
                    psEnc.state_Fxx[1].resampler_state.Assign(psEnc.state_Fxx[0].resampler_state);
                    Array.Copy(psEnc.state_Fxx[0].In_HP_State, psEnc.state_Fxx[1].In_HP_State, 2);
                }
            }

            transition = ((encControl.payloadSize_ms != psEnc.state_Fxx[0].PacketSize_ms) || (psEnc.nChannelsInternal != encControl.nChannelsInternal)) ? 1 : 0;

            psEnc.nChannelsAPI      = encControl.nChannelsAPI;
            psEnc.nChannelsInternal = encControl.nChannelsInternal;

            nBlocksOf10ms = Inlines.silk_DIV32(100 * nSamplesIn, encControl.API_sampleRate);
            tot_blocks    = (nBlocksOf10ms > 1) ? nBlocksOf10ms >> 1 : 1;
            curr_block    = 0;
            if (prefillFlag != 0)
            {
                /* Only accept input length of 10 ms */
                if (nBlocksOf10ms != 1)
                {
                    Inlines.OpusAssert(false);
                    return(SilkError.SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES);
                }
                /* Reset Encoder */
                for (n = 0; n < encControl.nChannelsInternal; n++)
                {
                    ret += SilkEncoder.silk_init_encoder(psEnc.state_Fxx[n]);
                    Inlines.OpusAssert(ret == SilkError.SILK_NO_ERROR);
                }
                tmp_payloadSize_ms        = encControl.payloadSize_ms;
                encControl.payloadSize_ms = 10;
                tmp_complexity            = encControl.complexity;
                encControl.complexity     = 0;
                for (n = 0; n < encControl.nChannelsInternal; n++)
                {
                    psEnc.state_Fxx[n].controlled_since_last_payload = 0;
                    psEnc.state_Fxx[n].prefillFlag = 1;
                }
            }
            else
            {
                /* Only accept input lengths that are a multiple of 10 ms */
                if (nBlocksOf10ms * encControl.API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0)
                {
                    Inlines.OpusAssert(false);
                    return(SilkError.SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES);
                }
                /* Make sure no more than one packet can be produced */
                if (1000 * (int)nSamplesIn > encControl.payloadSize_ms * encControl.API_sampleRate)
                {
                    Inlines.OpusAssert(false);
                    return(SilkError.SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES);
                }
            }

            TargetRate_bps = Inlines.silk_RSHIFT32(encControl.bitRate, encControl.nChannelsInternal - 1);

            for (n = 0; n < encControl.nChannelsInternal; n++)
            {
                /* Force the side channel to the same rate as the mid */
                int force_fs_kHz = (n == 1) ? psEnc.state_Fxx[0].fs_kHz : 0;
                ret += psEnc.state_Fxx[n].silk_control_encoder(encControl, TargetRate_bps, psEnc.allowBandwidthSwitch, n, force_fs_kHz);

                if (ret != SilkError.SILK_NO_ERROR)
                {
                    Inlines.OpusAssert(false);
                    return(ret);
                }

                if (psEnc.state_Fxx[n].first_frame_after_reset != 0 || transition != 0)
                {
                    for (i = 0; i < psEnc.state_Fxx[0].nFramesPerPacket; i++)
                    {
                        psEnc.state_Fxx[n].LBRR_flags[i] = 0;
                    }
                }

                psEnc.state_Fxx[n].inDTX = psEnc.state_Fxx[n].useDTX;
            }

            Inlines.OpusAssert(encControl.nChannelsInternal == 1 || psEnc.state_Fxx[0].fs_kHz == psEnc.state_Fxx[1].fs_kHz);

            /* Input buffering/resampling and encoding */
            nSamplesToBufferMax  = 10 * nBlocksOf10ms * psEnc.state_Fxx[0].fs_kHz;
            nSamplesFromInputMax =
                Inlines.silk_DIV32_16(nSamplesToBufferMax *
                                      psEnc.state_Fxx[0].API_fs_Hz,
                                      (short)(psEnc.state_Fxx[0].fs_kHz * 1000));

            buf = new short[nSamplesFromInputMax];

            int samplesIn_ptr = 0;

            while (true)
            {
                nSamplesToBuffer  = psEnc.state_Fxx[0].frame_length - psEnc.state_Fxx[0].inputBufIx;
                nSamplesToBuffer  = Inlines.silk_min(nSamplesToBuffer, nSamplesToBufferMax);
                nSamplesFromInput = Inlines.silk_DIV32_16(nSamplesToBuffer * psEnc.state_Fxx[0].API_fs_Hz, psEnc.state_Fxx[0].fs_kHz * 1000);

                /* Resample and write to buffer */
                if (encControl.nChannelsAPI == 2 && encControl.nChannelsInternal == 2)
                {
                    int id = psEnc.state_Fxx[0].nFramesEncoded;
                    for (n = 0; n < nSamplesFromInput; n++)
                    {
                        buf[n] = samplesIn[samplesIn_ptr + (2 * n)];
                    }

                    /* Making sure to start both resamplers from the same state when switching from mono to stereo */
                    if (psEnc.nPrevChannelsInternal == 1 && id == 0)
                    {
                        //silk_memcpy(&psEnc.state_Fxx[1].resampler_state, &psEnc.state_Fxx[0].resampler_state, sizeof(psEnc.state_Fxx[1].resampler_state));
                        psEnc.state_Fxx[1].resampler_state.Assign(psEnc.state_Fxx[0].resampler_state);
                    }

                    ret += Resampler.silk_resampler(
                        psEnc.state_Fxx[0].resampler_state,
                        psEnc.state_Fxx[0].inputBuf,
                        psEnc.state_Fxx[0].inputBufIx + 2,
                        buf,
                        0,
                        nSamplesFromInput);

                    psEnc.state_Fxx[0].inputBufIx += nSamplesToBuffer;

                    nSamplesToBuffer = psEnc.state_Fxx[1].frame_length - psEnc.state_Fxx[1].inputBufIx;
                    nSamplesToBuffer = Inlines.silk_min(nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc.state_Fxx[1].fs_kHz);
                    for (n = 0; n < nSamplesFromInput; n++)
                    {
                        buf[n] = samplesIn[samplesIn_ptr + (2 * n) + 1];
                    }
                    ret += Resampler.silk_resampler(
                        psEnc.state_Fxx[1].resampler_state,
                        psEnc.state_Fxx[1].inputBuf,
                        psEnc.state_Fxx[1].inputBufIx + 2,
                        buf,
                        0,
                        nSamplesFromInput);

                    psEnc.state_Fxx[1].inputBufIx += nSamplesToBuffer;
                }
                else if (encControl.nChannelsAPI == 2 && encControl.nChannelsInternal == 1)
                {
                    /* Combine left and right channels before resampling */
                    for (n = 0; n < nSamplesFromInput; n++)
                    {
                        sum    = samplesIn[samplesIn_ptr + (2 * n)] + samplesIn[samplesIn_ptr + (2 * n) + 1];
                        buf[n] = (short)Inlines.silk_RSHIFT_ROUND(sum, 1);
                    }

                    ret += Resampler.silk_resampler(
                        psEnc.state_Fxx[0].resampler_state,
                        psEnc.state_Fxx[0].inputBuf,
                        psEnc.state_Fxx[0].inputBufIx + 2,
                        buf,
                        0,
                        nSamplesFromInput);

                    /* On the first mono frame, average the results for the two resampler states  */
                    if (psEnc.nPrevChannelsInternal == 2 && psEnc.state_Fxx[0].nFramesEncoded == 0)
                    {
                        ret += Resampler.silk_resampler(
                            psEnc.state_Fxx[1].resampler_state,
                            psEnc.state_Fxx[1].inputBuf,
                            psEnc.state_Fxx[1].inputBufIx + 2,
                            buf,
                            0,
                            nSamplesFromInput);

                        for (n = 0; n < psEnc.state_Fxx[0].frame_length; n++)
                        {
                            psEnc.state_Fxx[0].inputBuf[psEnc.state_Fxx[0].inputBufIx + n + 2] =
                                (short)(Inlines.silk_RSHIFT(psEnc.state_Fxx[0].inputBuf[psEnc.state_Fxx[0].inputBufIx + n + 2]
                                                            + psEnc.state_Fxx[1].inputBuf[psEnc.state_Fxx[1].inputBufIx + n + 2], 1));
                        }
                    }

                    psEnc.state_Fxx[0].inputBufIx += nSamplesToBuffer;
                }
                else
                {
                    Inlines.OpusAssert(encControl.nChannelsAPI == 1 && encControl.nChannelsInternal == 1);
                    Array.Copy(samplesIn, samplesIn_ptr, buf, 0, nSamplesFromInput);
                    ret += Resampler.silk_resampler(
                        psEnc.state_Fxx[0].resampler_state,
                        psEnc.state_Fxx[0].inputBuf,
                        psEnc.state_Fxx[0].inputBufIx + 2,
                        buf,
                        0,
                        nSamplesFromInput);

                    psEnc.state_Fxx[0].inputBufIx += nSamplesToBuffer;
                }

                samplesIn_ptr += (nSamplesFromInput * encControl.nChannelsAPI);
                nSamplesIn    -= nSamplesFromInput;

                /* Default */
                psEnc.allowBandwidthSwitch = 0;

                /* Silk encoder */
                if (psEnc.state_Fxx[0].inputBufIx >= psEnc.state_Fxx[0].frame_length)
                {
                    /* Enough data in input buffer, so encode */
                    Inlines.OpusAssert(psEnc.state_Fxx[0].inputBufIx == psEnc.state_Fxx[0].frame_length);
                    Inlines.OpusAssert(encControl.nChannelsInternal == 1 || psEnc.state_Fxx[1].inputBufIx == psEnc.state_Fxx[1].frame_length);

                    /* Deal with LBRR data */
                    if (psEnc.state_Fxx[0].nFramesEncoded == 0 && prefillFlag == 0)
                    {
                        /* Create space at start of payload for VAD and FEC flags */
                        byte[] iCDF = { 0, 0 };
                        iCDF[0] = (byte)(256 - Inlines.silk_RSHIFT(256, (psEnc.state_Fxx[0].nFramesPerPacket + 1) * encControl.nChannelsInternal));
                        psRangeEnc.enc_icdf(0, iCDF, 8);

                        /* Encode any LBRR data from previous packet */
                        /* Encode LBRR flags */
                        for (n = 0; n < encControl.nChannelsInternal; n++)
                        {
                            LBRR_symbol = 0;
                            for (i = 0; i < psEnc.state_Fxx[n].nFramesPerPacket; i++)
                            {
                                LBRR_symbol |= Inlines.silk_LSHIFT(psEnc.state_Fxx[n].LBRR_flags[i], i);
                            }

                            psEnc.state_Fxx[n].LBRR_flag = (sbyte)(LBRR_symbol > 0 ? 1 : 0);
                            if (LBRR_symbol != 0 && psEnc.state_Fxx[n].nFramesPerPacket > 1)
                            {
                                psRangeEnc.enc_icdf(LBRR_symbol - 1, Tables.silk_LBRR_flags_iCDF_ptr[psEnc.state_Fxx[n].nFramesPerPacket - 2], 8);
                            }
                        }

                        /* Code LBRR indices and excitation signals */
                        for (i = 0; i < psEnc.state_Fxx[0].nFramesPerPacket; i++)
                        {
                            for (n = 0; n < encControl.nChannelsInternal; n++)
                            {
                                if (psEnc.state_Fxx[n].LBRR_flags[i] != 0)
                                {
                                    int condCoding;

                                    if (encControl.nChannelsInternal == 2 && n == 0)
                                    {
                                        Stereo.silk_stereo_encode_pred(psRangeEnc, psEnc.sStereo.predIx[i]);
                                        /* For LBRR data there's no need to code the mid-only flag if the side-channel LBRR flag is set */
                                        if (psEnc.state_Fxx[1].LBRR_flags[i] == 0)
                                        {
                                            Stereo.silk_stereo_encode_mid_only(psRangeEnc, psEnc.sStereo.mid_only_flags[i]);
                                        }
                                    }

                                    /* Use conditional coding if previous frame available */
                                    if (i > 0 && psEnc.state_Fxx[n].LBRR_flags[i - 1] != 0)
                                    {
                                        condCoding = SilkConstants.CODE_CONDITIONALLY;
                                    }
                                    else
                                    {
                                        condCoding = SilkConstants.CODE_INDEPENDENTLY;
                                    }

                                    EncodeIndices.silk_encode_indices(psEnc.state_Fxx[n], psRangeEnc, i, 1, condCoding);
                                    EncodePulses.silk_encode_pulses(psRangeEnc, psEnc.state_Fxx[n].indices_LBRR[i].signalType, psEnc.state_Fxx[n].indices_LBRR[i].quantOffsetType,
                                                                    psEnc.state_Fxx[n].pulses_LBRR[i], psEnc.state_Fxx[n].frame_length);
                                }
                            }
                        }

                        /* Reset LBRR flags */
                        for (n = 0; n < encControl.nChannelsInternal; n++)
                        {
                            Arrays.MemSetInt(psEnc.state_Fxx[n].LBRR_flags, 0, SilkConstants.MAX_FRAMES_PER_PACKET);
                        }

                        psEnc.nBitsUsedLBRR = psRangeEnc.tell();
                    }

                    HPVariableCutoff.silk_HP_variable_cutoff(psEnc.state_Fxx);

                    /* Total target bits for packet */
                    nBits = Inlines.silk_DIV32_16(Inlines.silk_MUL(encControl.bitRate, encControl.payloadSize_ms), 1000);

                    /* Subtract bits used for LBRR */
                    if (prefillFlag == 0)
                    {
                        nBits -= psEnc.nBitsUsedLBRR;
                    }

                    /* Divide by number of uncoded frames left in packet */
                    nBits = Inlines.silk_DIV32_16(nBits, psEnc.state_Fxx[0].nFramesPerPacket);

                    /* Convert to bits/second */
                    if (encControl.payloadSize_ms == 10)
                    {
                        TargetRate_bps = Inlines.silk_SMULBB(nBits, 100);
                    }
                    else
                    {
                        TargetRate_bps = Inlines.silk_SMULBB(nBits, 50);
                    }

                    /* Subtract fraction of bits in excess of target in previous frames and packets */
                    TargetRate_bps -= Inlines.silk_DIV32_16(Inlines.silk_MUL(psEnc.nBitsExceeded, 1000), TuningParameters.BITRESERVOIR_DECAY_TIME_MS);

                    if (prefillFlag == 0 && psEnc.state_Fxx[0].nFramesEncoded > 0)
                    {
                        /* Compare actual vs target bits so far in this packet */
                        int bitsBalance = psRangeEnc.tell() - psEnc.nBitsUsedLBRR - nBits * psEnc.state_Fxx[0].nFramesEncoded;
                        TargetRate_bps -= Inlines.silk_DIV32_16(Inlines.silk_MUL(bitsBalance, 1000), TuningParameters.BITRESERVOIR_DECAY_TIME_MS);
                    }

                    /* Never exceed input bitrate */
                    TargetRate_bps = Inlines.silk_LIMIT(TargetRate_bps, encControl.bitRate, 5000);

                    /* Convert Left/Right to Mid/Side */
                    if (encControl.nChannelsInternal == 2)
                    {
                        BoxedValueSbyte midOnlyFlagBoxed = new BoxedValueSbyte(psEnc.sStereo.mid_only_flags[psEnc.state_Fxx[0].nFramesEncoded]);
                        Stereo.silk_stereo_LR_to_MS(psEnc.sStereo,
                                                    psEnc.state_Fxx[0].inputBuf,
                                                    2,
                                                    psEnc.state_Fxx[1].inputBuf,
                                                    2,
                                                    psEnc.sStereo.predIx[psEnc.state_Fxx[0].nFramesEncoded],
                                                    midOnlyFlagBoxed,
                                                    MStargetRates_bps,
                                                    TargetRate_bps,
                                                    psEnc.state_Fxx[0].speech_activity_Q8,
                                                    encControl.toMono,
                                                    psEnc.state_Fxx[0].fs_kHz,
                                                    psEnc.state_Fxx[0].frame_length);

                        psEnc.sStereo.mid_only_flags[psEnc.state_Fxx[0].nFramesEncoded] = midOnlyFlagBoxed.Val;

                        if (midOnlyFlagBoxed.Val == 0)
                        {
                            /* Reset side channel encoder memory for first frame with side coding */
                            if (psEnc.prev_decode_only_middle == 1)
                            {
                                psEnc.state_Fxx[1].sShape.Reset();
                                psEnc.state_Fxx[1].sPrefilt.Reset();
                                psEnc.state_Fxx[1].sNSQ.Reset();
                                Arrays.MemSetShort(psEnc.state_Fxx[1].prev_NLSFq_Q15, 0, SilkConstants.MAX_LPC_ORDER);
                                Arrays.MemSetInt(psEnc.state_Fxx[1].sLP.In_LP_State, 0, 2);

                                psEnc.state_Fxx[1].prevLag                 = 100;
                                psEnc.state_Fxx[1].sNSQ.lagPrev            = 100;
                                psEnc.state_Fxx[1].sShape.LastGainIndex    = 10;
                                psEnc.state_Fxx[1].prevSignalType          = SilkConstants.TYPE_NO_VOICE_ACTIVITY;
                                psEnc.state_Fxx[1].sNSQ.prev_gain_Q16      = 65536;
                                psEnc.state_Fxx[1].first_frame_after_reset = 1;
                            }

                            psEnc.state_Fxx[1].silk_encode_do_VAD();
                        }
                        else
                        {
                            psEnc.state_Fxx[1].VAD_flags[psEnc.state_Fxx[0].nFramesEncoded] = 0;
                        }

                        if (prefillFlag == 0)
                        {
                            Stereo.silk_stereo_encode_pred(psRangeEnc, psEnc.sStereo.predIx[psEnc.state_Fxx[0].nFramesEncoded]);
                            if (psEnc.state_Fxx[1].VAD_flags[psEnc.state_Fxx[0].nFramesEncoded] == 0)
                            {
                                Stereo.silk_stereo_encode_mid_only(psRangeEnc, psEnc.sStereo.mid_only_flags[psEnc.state_Fxx[0].nFramesEncoded]);
                            }
                        }
                    }
                    else
                    {
                        /* Buffering */
                        Array.Copy(psEnc.sStereo.sMid, psEnc.state_Fxx[0].inputBuf, 2);
                        Array.Copy(psEnc.state_Fxx[0].inputBuf, psEnc.state_Fxx[0].frame_length, psEnc.sStereo.sMid, 0, 2);
                    }

                    psEnc.state_Fxx[0].silk_encode_do_VAD();

                    /* Encode */
                    for (n = 0; n < encControl.nChannelsInternal; n++)
                    {
                        int maxBits, useCBR;

                        /* Handling rate constraints */
                        maxBits = encControl.maxBits;
                        if (tot_blocks == 2 && curr_block == 0)
                        {
                            maxBits = maxBits * 3 / 5;
                        }

                        else if (tot_blocks == 3)
                        {
                            if (curr_block == 0)
                            {
                                maxBits = maxBits * 2 / 5;
                            }
                            else if (curr_block == 1)
                            {
                                maxBits = maxBits * 3 / 4;
                            }
                        }

                        useCBR = (encControl.useCBR != 0 && curr_block == tot_blocks - 1) ? 1 : 0;

                        if (encControl.nChannelsInternal == 1)
                        {
                            channelRate_bps = TargetRate_bps;
                        }
                        else
                        {
                            channelRate_bps = MStargetRates_bps[n];
                            if (n == 0 && MStargetRates_bps[1] > 0)
                            {
                                useCBR = 0;
                                /* Give mid up to 1/2 of the max bits for that frame */
                                maxBits -= encControl.maxBits / (tot_blocks * 2);
                            }
                        }

                        if (channelRate_bps > 0)
                        {
                            int condCoding;

                            psEnc.state_Fxx[n].silk_control_SNR(channelRate_bps);

                            /* Use independent coding if no previous frame available */
                            if (psEnc.state_Fxx[0].nFramesEncoded - n <= 0)
                            {
                                condCoding = SilkConstants.CODE_INDEPENDENTLY;
                            }
                            else if (n > 0 && psEnc.prev_decode_only_middle != 0)
                            {
                                /* If we skipped a side frame in this packet, we don't
                                 * need LTP scaling; the LTP state is well-defined. */
                                condCoding = SilkConstants.CODE_INDEPENDENTLY_NO_LTP_SCALING;
                            }
                            else
                            {
                                condCoding = SilkConstants.CODE_CONDITIONALLY;
                            }

                            ret += psEnc.state_Fxx[n].silk_encode_frame(nBytesOut, psRangeEnc, condCoding, maxBits, useCBR);
                            Inlines.OpusAssert(ret == SilkError.SILK_NO_ERROR);
                        }

                        psEnc.state_Fxx[n].controlled_since_last_payload = 0;
                        psEnc.state_Fxx[n].inputBufIx = 0;
                        psEnc.state_Fxx[n].nFramesEncoded++;
                    }

                    psEnc.prev_decode_only_middle = psEnc.sStereo.mid_only_flags[psEnc.state_Fxx[0].nFramesEncoded - 1];

                    /* Insert VAD and FEC flags at beginning of bitstream */
                    if (nBytesOut.Val > 0 && psEnc.state_Fxx[0].nFramesEncoded == psEnc.state_Fxx[0].nFramesPerPacket)
                    {
                        flags = 0;
                        for (n = 0; n < encControl.nChannelsInternal; n++)
                        {
                            for (i = 0; i < psEnc.state_Fxx[n].nFramesPerPacket; i++)
                            {
                                flags  = Inlines.silk_LSHIFT(flags, 1);
                                flags |= (int)psEnc.state_Fxx[n].VAD_flags[i];
                            }
                            flags  = Inlines.silk_LSHIFT(flags, 1);
                            flags |= (int)psEnc.state_Fxx[n].LBRR_flag;
                        }

                        if (prefillFlag == 0)
                        {
                            psRangeEnc.enc_patch_initial_bits((uint)flags, (uint)((psEnc.state_Fxx[0].nFramesPerPacket + 1) * encControl.nChannelsInternal));
                        }

                        /* Return zero bytes if all channels DTXed */
                        if (psEnc.state_Fxx[0].inDTX != 0 && (encControl.nChannelsInternal == 1 || psEnc.state_Fxx[1].inDTX != 0))
                        {
                            nBytesOut.Val = 0;
                        }

                        psEnc.nBitsExceeded += nBytesOut.Val * 8;
                        psEnc.nBitsExceeded -= Inlines.silk_DIV32_16(Inlines.silk_MUL(encControl.bitRate, encControl.payloadSize_ms), 1000);
                        psEnc.nBitsExceeded  = Inlines.silk_LIMIT(psEnc.nBitsExceeded, 0, 10000);

                        /* Update flag indicating if bandwidth switching is allowed */
                        speech_act_thr_for_switch_Q8 = Inlines.silk_SMLAWB(((int)((TuningParameters.SPEECH_ACTIVITY_DTX_THRES) * ((long)1 << (8)) + 0.5)) /*Inlines.SILK_CONST(TuningParameters.SPEECH_ACTIVITY_DTX_THRES, 8)*/,
                                                                           ((int)(((1 - TuningParameters.SPEECH_ACTIVITY_DTX_THRES) / TuningParameters.MAX_BANDWIDTH_SWITCH_DELAY_MS) * ((long)1 << (16 + 8)) + 0.5)) /*Inlines.SILK_CONST((1 - TuningParameters.SPEECH_ACTIVITY_DTX_THRES) / TuningParameters.MAX_BANDWIDTH_SWITCH_DELAY_MS, 16 + 8)*/,
                                                                           psEnc.timeSinceSwitchAllowed_ms);
                        if (psEnc.state_Fxx[0].speech_activity_Q8 < speech_act_thr_for_switch_Q8)
                        {
                            psEnc.allowBandwidthSwitch      = 1;
                            psEnc.timeSinceSwitchAllowed_ms = 0;
                        }
                        else
                        {
                            psEnc.allowBandwidthSwitch       = 0;
                            psEnc.timeSinceSwitchAllowed_ms += encControl.payloadSize_ms;
                        }
                    }

                    if (nSamplesIn == 0)
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }

                curr_block++;
            }

            psEnc.nPrevChannelsInternal = encControl.nChannelsInternal;

            encControl.allowBandwidthSwitch      = psEnc.allowBandwidthSwitch;
            encControl.inWBmodeWithoutVariableLP = (psEnc.state_Fxx[0].fs_kHz == 16 && psEnc.state_Fxx[0].sLP.mode == 0) ? 1 : 0;
            encControl.internalSampleRate        = Inlines.silk_SMULBB(psEnc.state_Fxx[0].fs_kHz, 1000);
            encControl.stereoWidth_Q14           = encControl.toMono != 0 ? 0 : psEnc.sStereo.smth_width_Q14;

            if (prefillFlag != 0)
            {
                encControl.payloadSize_ms = tmp_payloadSize_ms;
                encControl.complexity     = tmp_complexity;

                for (n = 0; n < encControl.nChannelsInternal; n++)
                {
                    psEnc.state_Fxx[n].controlled_since_last_payload = 0;
                    psEnc.state_Fxx[n].prefillFlag = 0;
                }
            }

            return(ret);
        }
Ejemplo n.º 30
0
 internal static void encode_pulses(int[] _y, int _n, int _k, EntropyCoder _enc)
 {
     Inlines.OpusAssert(_k > 0);
     _enc.enc_uint(icwrs(_n, _y), CELT_PVQ_V(_n, _k));
 }