Ejemplo n.º 1
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);
            }
        }