Ejemplo n.º 1
0
        private int tryGlobalStepsize(algo_t that, int[] sfwork, int[] vbrsfmin, int delta)
        {
            var xrpow_max = that.cod_info.xrpow_max;
            var sftemp    = new int[L3Side.SFBMAX];
            int nbits;
            var vbrmax = 0;

            for (var i = 0; i < L3Side.SFBMAX; ++i)
            {
                var gain = sfwork[i] + delta;
                if (gain < vbrsfmin[i])
                {
                    gain = vbrsfmin[i];
                }

                if (gain > 255)
                {
                    gain = 255;
                }

                if (vbrmax < gain)
                {
                    vbrmax = gain;
                }

                sftemp[i] = gain;
            }

            that.alloc.alloc(that, sftemp, vbrsfmin, vbrmax);
            bitcount(that);
            nbits = quantizeAndCountBits(that);
            that.cod_info.xrpow_max = xrpow_max;
            return(nbits);
        }
Ejemplo n.º 2
0
        private int tryThatOne(algo_t that, int[] sftemp, int[] vbrsfmin, int vbrmax)
        {
            var xrpow_max = that.cod_info.xrpow_max;
            var nbits     = QuantizePVT.LARGE_BITS;

            that.alloc.alloc(that, sftemp, vbrsfmin, vbrmax);
            bitcount(that);
            nbits  = quantizeAndCountBits(that);
            nbits += that.cod_info.part2_length;
            that.cod_info.xrpow_max = xrpow_max;
            return(nbits);
        }
Ejemplo n.º 3
0
        private void bitcount(algo_t that)
        {
            bool rc;

            if (that.gfc.mode_gr == 2)
            {
                rc = tak.scale_bitcount(that.cod_info);
            }
            else
            {
                rc = tak.scale_bitcount_lsf(that.gfc, that.cod_info);
            }

            if (!rc)
            {
                return;
            }

            /* this should not happen due to the way the scalefactors are selected */
            throw new Exception("INTERNAL ERROR IN VBR NEW CODE (986), please send bug report");
        }
Ejemplo n.º 4
0
        private void searchGlobalStepsizeMax(algo_t that, int[] sfwork, int[] vbrsfmin, int target)
        {
            var cod_info = that.cod_info;

            var gain = cod_info.global_gain;
            var curr = gain;
            var gain_ok = 1024;
            var nbits = QuantizePVT.LARGE_BITS;
            int l = gain, r = 512;

            Debug.Assert(gain >= 0);
            while (l <= r)
            {
                curr  = (l + r) >> 1;
                nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain);
                if (nbits == 0 || nbits + cod_info.part2_length < target)
                {
                    r       = curr - 1;
                    gain_ok = curr;
                }
                else
                {
                    l = curr + 1;
                    if (gain_ok == 1024)
                    {
                        gain_ok = curr;
                    }
                }
            }

            if (gain_ok != curr)
            {
                curr  = gain_ok;
                nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain);
            }
        }
Ejemplo n.º 5
0
        private void outOfBitsStrategy(algo_t that, int[] sfwork, int[] vbrsfmin, int target)
        {
            var wrk = new int[L3Side.SFBMAX];

            var dm = sfDepth(sfwork);

            var p = that.cod_info.global_gain;

            /* PART 1 */
            {
                var bi    = dm / 2;
                var bi_ok = -1;
                var bu    = 0;
                var bo    = dm;
                for (;;)
                {
                    var sfmax = flattenDistribution(sfwork, wrk, dm, bi, p);
                    var nbits = tryThatOne(that, wrk, vbrsfmin, sfmax);
                    if (nbits <= target)
                    {
                        bi_ok = bi;
                        bo    = bi - 1;
                    }
                    else
                    {
                        bu = bi + 1;
                    }

                    if (bu <= bo)
                    {
                        bi = (bu + bo) / 2;
                    }
                    else
                    {
                        break;
                    }
                }

                if (bi_ok >= 0)
                {
                    if (bi != bi_ok)
                    {
                        var sfmax = flattenDistribution(sfwork, wrk, dm, bi_ok, p);
                        tryThatOne(that, wrk, vbrsfmin, sfmax);
                    }

                    return;
                }
            }
            /* PART 2: */
            {
                var bi    = (255 + p) / 2;
                var bi_ok = -1;
                var bu    = p;
                var bo    = 255;
                for (;;)
                {
                    var sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi);
                    var nbits = tryThatOne(that, wrk, vbrsfmin, sfmax);
                    if (nbits <= target)
                    {
                        bi_ok = bi;
                        bo    = bi - 1;
                    }
                    else
                    {
                        bu = bi + 1;
                    }

                    if (bu <= bo)
                    {
                        bi = (bu + bo) / 2;
                    }
                    else
                    {
                        break;
                    }
                }

                if (bi_ok >= 0)
                {
                    if (bi != bi_ok)
                    {
                        var sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi_ok);
                        tryThatOne(that, wrk, vbrsfmin, sfmax);
                    }

                    return;
                }
            }
            /* fall back to old code, likely to be never called */
            searchGlobalStepsizeMax(that, wrk, vbrsfmin, target);
        }
Ejemplo n.º 6
0
 private int quantizeAndCountBits(algo_t that)
 {
     quantize_x34(that);
     that.cod_info.part2_3_length = tak.noquant_count_bits(that.gfc, that.cod_info, null);
     return(that.cod_info.part2_3_length);
 }
Ejemplo n.º 7
0
        /// <summary>
        ///     quantize xr34 based on scalefactors
        ///     block_xr34
        ///     @author Mark Taylor 2000-??-??
        ///     @author Robert Hegemann 2000-10-20 made functions of them
        /// </summary>
        private void quantize_x34(algo_t that)
        {
            var x         = new double[4];
            var xr34_orig = 0;

            var cod_info = that.cod_info;

            var ifqstep = cod_info.scalefac_scale == 0 ? 2 : 4;
            var l3 = 0;
            int j = 0, sfb = 0;

            var max_nonzero_coeff = cod_info.max_nonzero_coeff;

            Debug.Assert(cod_info.max_nonzero_coeff >= 0);
            Debug.Assert(cod_info.max_nonzero_coeff < 576);
            while (j <= max_nonzero_coeff)
            {
                var s = (cod_info.scalefac[sfb] + (cod_info.preflag != 0 ? qupvt.pretab[sfb] : 0)) * ifqstep +
                        cod_info.subblock_gain[cod_info.window[sfb]] * 8;

                var sfac = cod_info.global_gain - s;

                var sfpow34 = qupvt.ipow20[sfac];

                var w = cod_info.width[sfb];

                var m = max_nonzero_coeff - j + 1;
                var l = w;
                int remaining;
                Debug.Assert(cod_info.global_gain - s >= 0);
                Debug.Assert(cod_info.width[sfb] >= 0);
                if (l > m)
                {
                    l = m;
                }

                j += w;
                ++sfb;
                l       >>= 1;
                remaining = l & 1;
                for (l >>= 1; l > 0; --l)
                {
                    x[0] = sfpow34 * that.xr34orig[xr34_orig + 0];
                    x[1] = sfpow34 * that.xr34orig[xr34_orig + 1];
                    x[2] = sfpow34 * that.xr34orig[xr34_orig + 2];
                    x[3] = sfpow34 * that.xr34orig[xr34_orig + 3];
                    k_34_4(x, cod_info.l3_enc, l3);
                    l3        += 4;
                    xr34_orig += 4;
                }

                if (remaining != 0)
                {
                    x[0] = sfpow34 * that.xr34orig[xr34_orig + 0];
                    x[1] = sfpow34 * that.xr34orig[xr34_orig + 1];
                    k_34_2(x, cod_info.l3_enc, l3);
                    l3        += 2;
                    xr34_orig += 2;
                }
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        ///     calc_short_block_vbr_sf(), calc_long_block_vbr_sf()
        ///     a variation for vbr-mtrh
        ///     @author Mark Taylor 2000-??-??
        ///     @author Robert Hegemann 2000-10-25 made functions of it
        /// </summary>
        private int block_sf(algo_t that, float[] l3_xmin, int[] vbrsf, int[] vbrsfmin)
        {
            float max_xr34;

            var xr = that.cod_info.xr;

            var xr34_orig = that.xr34orig;

            var width = that.cod_info.width;

            var max_nonzero_coeff = that.cod_info.max_nonzero_coeff;
            var maxsf             = 0;
            var sfb = 0;
            int j = 0, i = 0;

            var psymax = that.cod_info.psymax;

            Debug.Assert(that.cod_info.max_nonzero_coeff >= 0);
            that.mingain_l    = 0;
            that.mingain_s[0] = 0;
            that.mingain_s[1] = 0;
            that.mingain_s[2] = 0;
            while (j <= max_nonzero_coeff)
            {
                var w = width[sfb];

                var m = max_nonzero_coeff - j + 1;
                var l = w;
                int m1, m2;
                if (l > m)
                {
                    l = m;
                }

                max_xr34      = max_x34(xr34_orig, j, l);
                m1            = findLowestScalefac(max_xr34);
                vbrsfmin[sfb] = m1;
                if (that.mingain_l < m1)
                {
                    that.mingain_l = m1;
                }

                if (that.mingain_s[i] < m1)
                {
                    that.mingain_s[i] = m1;
                }

                if (++i > 2)
                {
                    i = 0;
                }

                if (sfb < psymax)
                {
                    if (belowNoiseFloor(xr, j, l3_xmin[sfb], l) == 0)
                    {
                        m2 = find_scalefac_x34(xr, xr34_orig, j, l3_xmin[sfb], l, m1);
                        if (maxsf < m2)
                        {
                            maxsf = m2;
                        }
                    }
                    else
                    {
                        m2    = 255;
                        maxsf = 255;
                    }
                }
                else
                {
                    if (maxsf < m1)
                    {
                        maxsf = m1;
                    }

                    m2 = maxsf;
                }

                vbrsf[sfb] = m2;
                ++sfb;
                j += w;
            }

            for (; sfb < L3Side.SFBMAX; ++sfb)
            {
                vbrsf[sfb]    = maxsf;
                vbrsfmin[sfb] = 0;
            }

            return(maxsf);
        }
Ejemplo n.º 9
0
        internal virtual int VBR_encode_frame(
            LameInternalFlags gfc,
            float[][][] xr34orig,
            float[][][] l3_xmin,
            int[][] max_bits)
        {
            var sfwork_ = Arrays.ReturnRectangularArray <int>(2, 2, L3Side.SFBMAX);

            var vbrsfmin_ = Arrays.ReturnRectangularArray <int>(2, 2, L3Side.SFBMAX);

            var that_ = Arrays.ReturnRectangularArray <algo_t>(2, 2);

            var ngr = gfc.mode_gr;

            var nch = gfc.channels_out;

            var max_nbits_ch = Arrays.ReturnRectangularArray <int>(2, 2);
            var max_nbits_gr = new int[2];
            var max_nbits_fr = 0;

            var use_nbits_ch = Arrays.ReturnRectangularArray <int>(2, 2);
            var use_nbits_gr = new int[2];
            var use_nbits_fr = 0;

            /*
             * set up some encoding parameters
             */
            for (var gr = 0; gr < ngr; ++gr)
            {
                max_nbits_gr[gr] = 0;
                for (var ch = 0; ch < nch; ++ch)
                {
                    max_nbits_ch[gr][ch]   = max_bits[gr][ch];
                    use_nbits_ch[gr][ch]   = 0;
                    max_nbits_gr[gr]      += max_bits[gr][ch];
                    max_nbits_fr          += max_bits[gr][ch];
                    that_[gr][ch]          = new algo_t();
                    that_[gr][ch].gfc      = gfc;
                    that_[gr][ch].cod_info = gfc.l3_side.tt[gr][ch];
                    that_[gr][ch].xr34orig = xr34orig[gr][ch];
                    if (that_[gr][ch].cod_info.block_type == Encoder.SHORT_TYPE)
                    {
                        that_[gr][ch].alloc = new ShortBlockConstrain(this);
                    }
                    else
                    {
                        that_[gr][ch].alloc = new LongBlockConstrain(this);
                    }
                } // for ch
            }

            /*
             * searches scalefactors
             */
            for (var gr = 0; gr < ngr; ++gr)
            {
                for (var ch = 0; ch < nch; ++ch)
                {
                    if (max_bits[gr][ch] > 0)
                    {
                        var that     = that_[gr][ch];
                        var sfwork   = sfwork_[gr][ch];
                        var vbrsfmin = vbrsfmin_[gr][ch];
                        int vbrmax;
                        vbrmax = block_sf(that, l3_xmin[gr][ch], sfwork, vbrsfmin);
                        that.alloc.alloc(that, sfwork, vbrsfmin, vbrmax);
                        bitcount(that);
                    }
                }
            }

            /*
             * encode 'as is'
             */
            use_nbits_fr = 0;
            for (var gr = 0; gr < ngr; ++gr)
            {
                use_nbits_gr[gr] = 0;
                for (var ch = 0; ch < nch; ++ch)
                {
                    var that = that_[gr][ch];
                    if (max_bits[gr][ch] > 0)
                    {
                        var max_nonzero_coeff = that.cod_info.max_nonzero_coeff;
                        Debug.Assert(max_nonzero_coeff < 576);
                        Arrays.Fill(that.cod_info.l3_enc, max_nonzero_coeff, 576, 0);
                        quantizeAndCountBits(that);
                    }

                    use_nbits_ch[gr][ch] = reduce_bit_usage(gfc, gr, ch);
                    use_nbits_gr[gr]    += use_nbits_ch[gr][ch];
                } // for ch

                use_nbits_fr += use_nbits_gr[gr];
            }

            /*
             * check bit constrains
             */
            if (use_nbits_fr <= max_nbits_fr)
            {
                var ok = true;
                for (var gr = 0; gr < ngr; ++gr)
                {
                    if (use_nbits_gr[gr] > LameInternalFlags.MAX_BITS_PER_GRANULE)
                    {
                        ok = false;
                    }

                    for (var ch = 0; ch < nch; ++ch)
                    {
                        if (use_nbits_ch[gr][ch] > LameInternalFlags.MAX_BITS_PER_CHANNEL)
                        {
                            ok = false;
                        }
                    }
                }

                if (ok)
                {
                    return(use_nbits_fr);
                }
            }

            /*
             * OK, we are in trouble and have to define how many bits are to be used
             * for each granule
             */
            {
                var ok     = true;
                var sum_fr = 0;
                for (var gr = 0; gr < ngr; ++gr)
                {
                    max_nbits_gr[gr] = 0;
                    for (var ch = 0; ch < nch; ++ch)
                    {
                        if (use_nbits_ch[gr][ch] > LameInternalFlags.MAX_BITS_PER_CHANNEL)
                        {
                            max_nbits_ch[gr][ch] = LameInternalFlags.MAX_BITS_PER_CHANNEL;
                        }
                        else
                        {
                            max_nbits_ch[gr][ch] = use_nbits_ch[gr][ch];
                        }

                        max_nbits_gr[gr] += max_nbits_ch[gr][ch];
                    }

                    if (max_nbits_gr[gr] > LameInternalFlags.MAX_BITS_PER_GRANULE)
                    {
                        var   f = new float[2];
                        float s = 0;
                        for (var ch = 0; ch < nch; ++ch)
                        {
                            if (max_nbits_ch[gr][ch] > 0)
                            {
                                f[ch] = (float)Math.Sqrt(Math.Sqrt(max_nbits_ch[gr][ch]));
                                s    += f[ch];
                            }
                            else
                            {
                                f[ch] = 0;
                            }
                        }

                        for (var ch = 0; ch < nch; ++ch)
                        {
                            if (s > 0)
                            {
                                max_nbits_ch[gr][ch] = (int)(LameInternalFlags.MAX_BITS_PER_GRANULE * f[ch] / s);
                            }
                            else
                            {
                                max_nbits_ch[gr][ch] = 0;
                            }
                        }

                        if (nch > 1)
                        {
                            if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32)
                            {
                                max_nbits_ch[gr][1] += max_nbits_ch[gr][0];
                                max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32;
                                max_nbits_ch[gr][0]  = use_nbits_ch[gr][0] + 32;
                            }

                            if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32)
                            {
                                max_nbits_ch[gr][0] += max_nbits_ch[gr][1];
                                max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32;
                                max_nbits_ch[gr][1]  = use_nbits_ch[gr][1] + 32;
                            }

                            if (max_nbits_ch[gr][0] > LameInternalFlags.MAX_BITS_PER_CHANNEL)
                            {
                                max_nbits_ch[gr][0] = LameInternalFlags.MAX_BITS_PER_CHANNEL;
                            }

                            if (max_nbits_ch[gr][1] > LameInternalFlags.MAX_BITS_PER_CHANNEL)
                            {
                                max_nbits_ch[gr][1] = LameInternalFlags.MAX_BITS_PER_CHANNEL;
                            }
                        }

                        max_nbits_gr[gr] = 0;
                        for (var ch = 0; ch < nch; ++ch)
                        {
                            max_nbits_gr[gr] += max_nbits_ch[gr][ch];
                        }
                    }

                    sum_fr += max_nbits_gr[gr];
                }

                if (sum_fr > max_nbits_fr)
                {
                    {
                        var   f = new float[2];
                        float s = 0;
                        for (var gr = 0; gr < ngr; ++gr)
                        {
                            if (max_nbits_gr[gr] > 0)
                            {
                                f[gr] = (float)Math.Sqrt(max_nbits_gr[gr]);
                                s    += f[gr];
                            }
                            else
                            {
                                f[gr] = 0;
                            }
                        }

                        for (var gr = 0; gr < ngr; ++gr)
                        {
                            if (s > 0)
                            {
                                max_nbits_gr[gr] = (int)(max_nbits_fr * f[gr] / s);
                            }
                            else
                            {
                                max_nbits_gr[gr] = 0;
                            }
                        }
                    }
                    if (ngr > 1)
                    {
                        if (max_nbits_gr[0] > use_nbits_gr[0] + 125)
                        {
                            max_nbits_gr[1] += max_nbits_gr[0];
                            max_nbits_gr[1] -= use_nbits_gr[0] + 125;
                            max_nbits_gr[0]  = use_nbits_gr[0] + 125;
                        }

                        if (max_nbits_gr[1] > use_nbits_gr[1] + 125)
                        {
                            max_nbits_gr[0] += max_nbits_gr[1];
                            max_nbits_gr[0] -= use_nbits_gr[1] + 125;
                            max_nbits_gr[1]  = use_nbits_gr[1] + 125;
                        }

                        for (var gr = 0; gr < ngr; ++gr)
                        {
                            if (max_nbits_gr[gr] > LameInternalFlags.MAX_BITS_PER_GRANULE)
                            {
                                max_nbits_gr[gr] = LameInternalFlags.MAX_BITS_PER_GRANULE;
                            }
                        }
                    }

                    for (var gr = 0; gr < ngr; ++gr)
                    {
                        var   f = new float[2];
                        float s = 0;
                        for (var ch = 0; ch < nch; ++ch)
                        {
                            if (max_nbits_ch[gr][ch] > 0)
                            {
                                f[ch] = (float)Math.Sqrt(max_nbits_ch[gr][ch]);
                                s    += f[ch];
                            }
                            else
                            {
                                f[ch] = 0;
                            }
                        }

                        for (var ch = 0; ch < nch; ++ch)
                        {
                            if (s > 0)
                            {
                                max_nbits_ch[gr][ch] = (int)(max_nbits_gr[gr] * f[ch] / s);
                            }
                            else
                            {
                                max_nbits_ch[gr][ch] = 0;
                            }
                        }

                        if (nch > 1)
                        {
                            if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32)
                            {
                                max_nbits_ch[gr][1] += max_nbits_ch[gr][0];
                                max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32;
                                max_nbits_ch[gr][0]  = use_nbits_ch[gr][0] + 32;
                            }

                            if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32)
                            {
                                max_nbits_ch[gr][0] += max_nbits_ch[gr][1];
                                max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32;
                                max_nbits_ch[gr][1]  = use_nbits_ch[gr][1] + 32;
                            }

                            for (var ch = 0; ch < nch; ++ch)
                            {
                                if (max_nbits_ch[gr][ch] > LameInternalFlags.MAX_BITS_PER_CHANNEL)
                                {
                                    max_nbits_ch[gr][ch] = LameInternalFlags.MAX_BITS_PER_CHANNEL;
                                }
                            }
                        }
                    }
                }

                /* sanity check */
                sum_fr = 0;
                for (var gr = 0; gr < ngr; ++gr)
                {
                    var sum_gr = 0;
                    for (var ch = 0; ch < nch; ++ch)
                    {
                        sum_gr += max_nbits_ch[gr][ch];
                        if (max_nbits_ch[gr][ch] > LameInternalFlags.MAX_BITS_PER_CHANNEL)
                        {
                            ok = false;
                        }
                    }

                    sum_fr += sum_gr;
                    if (sum_gr > LameInternalFlags.MAX_BITS_PER_GRANULE)
                    {
                        ok = false;
                    }
                }

                if (sum_fr > max_nbits_fr)
                {
                    ok = false;
                }

                if (!ok)
                {
                    for (var gr = 0; gr < ngr; ++gr)
                    {
                        for (var ch = 0; ch < nch; ++ch)
                        {
                            max_nbits_ch[gr][ch] = max_bits[gr][ch];
                        }
                    }
                }
            }
            /* we already called the 'best_scalefac_store' function, so we need to reset some variables before we can do it again.  */
            for (var ch = 0; ch < nch; ++ch)
            {
                gfc.l3_side.scfsi[ch][0] = 0;
                gfc.l3_side.scfsi[ch][1] = 0;
                gfc.l3_side.scfsi[ch][2] = 0;
                gfc.l3_side.scfsi[ch][3] = 0;
            }

            for (var gr = 0; gr < ngr; ++gr)
            {
                for (var ch = 0; ch < nch; ++ch)
                {
                    gfc.l3_side.tt[gr][ch].scalefac_compress = 0;
                }
            }

            /* alter our encoded data, until it fits into the target bitrate  */
            use_nbits_fr = 0;
            for (var gr = 0; gr < ngr; ++gr)
            {
                use_nbits_gr[gr] = 0;
                for (var ch = 0; ch < nch; ++ch)
                {
                    var that = that_[gr][ch];
                    use_nbits_ch[gr][ch] = 0;
                    if (max_bits[gr][ch] > 0)
                    {
                        var sfwork   = sfwork_[gr][ch];
                        var vbrsfmin = vbrsfmin_[gr][ch];
                        cutDistribution(sfwork, sfwork, that.cod_info.global_gain);
                        outOfBitsStrategy(that, sfwork, vbrsfmin, max_nbits_ch[gr][ch]);
                    }

                    use_nbits_ch[gr][ch] = reduce_bit_usage(gfc, gr, ch);
                    Debug.Assert(use_nbits_ch[gr][ch] <= max_nbits_ch[gr][ch]);
                    use_nbits_gr[gr] += use_nbits_ch[gr][ch];
                } // for ch

                use_nbits_fr += use_nbits_gr[gr];
            }

            /* check bit constrains, but it should always be ok, if there are no bugs ;-)  */
            if (use_nbits_fr <= max_nbits_fr)
            {
                return(use_nbits_fr);
            }

            throw new Exception(
                      string.Format(
                          "INTERNAL ERROR IN VBR NEW CODE (1313), please send bug report\n" +
                          "maxbits={0:D} usedbits={1:D}\n",
                          max_nbits_fr,
                          use_nbits_fr));
        }