コード例 #1
0
        private int AccumulateFit(float[] flr, float[] mdct, int x0, int x1, ref FitAccumulation fits, int n)
        {
            int xa = 0, ya = 0, x2a = 0, xya = 0, na = 0, xb = 0, yb = 0, x2b = 0, xyb = 0, nb = 0;

            fits.x0 = x0;
            fits.x1 = x1;

            if (x1 >= n)
            {
                x1 = n - 1;
            }

            for (var i = x0; i <= x1; i++)
            {
                var quantized = DecibelQuant(flr[i]);
                if (quantized != 0)
                {
                    if (mdct[i] + _floor.TwoFitAtten >= flr[i])
                    {
                        xa  += i;
                        ya  += quantized;
                        x2a += i * i;
                        xya += i * quantized;
                        na++;
                    }
                    else
                    {
                        xb  += i;
                        yb  += quantized;
                        x2b += i * i;
                        xyb += i * quantized;
                        nb++;
                    }
                }
            }

            fits.xa  = xa;
            fits.ya  = ya;
            fits.x2a = x2a;
            fits.xya = xya;
            fits.an  = na;

            fits.xb  = xb;
            fits.yb  = yb;
            fits.x2b = x2b;
            fits.xyb = xyb;
            fits.bn  = nb;

            return(na);
        }
コード例 #2
0
ファイル: FloorLookup.cs プロジェクト: zcaalock/valkyrie
        public int[] Fit(IList <float> logmdct, IList <float> logmask)
        {
            var n = _n;

            var nonzero   = 0;
            var fits      = new FitAccumulation[Posit + 1];
            var fitValueA = new int[Posit + 2];  // index by range list position
            var fitValueB = new int[Posit + 2];  // index by range list position

            var loneighbor = new int[Posit + 2]; // sorted index of range list position (+2)
            var hineighbor = new int[Posit + 2];
            var memo       = new int[Posit + 2];

            for (var i = 0; i < _posts; i++)
            {
                fitValueA[i] = -200; // mark all unused
            }
            for (var i = 0; i < _posts; i++)
            {
                fitValueB[i] = -200; // mark all unused
            }
            for (var i = 0; i < _posts; i++)
            {
                loneighbor[i] = 0; // 0 for the implicit 0 post
            }
            for (var i = 0; i < _posts; i++)
            {
                hineighbor[i] = 1; // 1 for the implicit post at n
            }
            for (var i = 0; i < _posts; i++)
            {
                memo[i] = -1; // no neighbor yet
            }
            // quantize the relevant floor points and collect them into line fit
            // structures (one per minimal division) at the same time
            if (_posts == 0)
            {
                nonzero = AccumulateFit(logmask, logmdct, 0, n, ref fits[0], n);
            }
            else
            {
                for (var i = 0; i < _posts - 1; i++)
                {
                    nonzero += AccumulateFit(logmask, logmdct, _sortedIndex[i], _sortedIndex[i + 1], ref fits[i], n);
                }
            }

            if (nonzero != 0)
            {
                // start by fitting the implicit base case....
                int y0, y1;
                FitLine(fits, 0, _posts - 1, out y0, out y1);

                fitValueA[0] = y0;
                fitValueB[0] = y0;
                fitValueB[1] = y1;
                fitValueA[1] = y1;

                // Non degenerate case
                // start progressive splitting.  This is a greedy, non-optimal
                // algorithm, but simple and close enough to the best
                // answer.
                for (var i = 2; i < _posts; i++)
                {
                    var sortPosition = _reverseIndex[i];
                    var ln           = loneighbor[sortPosition];
                    var hn           = hineighbor[sortPosition];

                    // eliminate repeat searches of a particular range with a memo
                    if (memo[ln] != hn)
                    {
                        // haven't performed this error search yet
                        var lowSortPosition  = _reverseIndex[ln];
                        var highSortPosition = _reverseIndex[hn];
                        memo[ln] = hn;

                        {
                            // A note: we want to bound/minimize *local*, not global, error
                            var lx = _floor.PostList[ln];
                            var hx = _floor.PostList[hn];
                            var ly = PostY(new List <int>(fitValueA), new List <int>(fitValueB), ln);
                            var hy = PostY(new List <int>(fitValueA), new List <int>(fitValueB), hn);

                            if ((ly == -1) || (hy == -1))
                            {
                                throw new InvalidOperationException("An error occurred during minimization");
                            }

                            if (InspectError(lx, hx, ly, hy, logmask, logmdct))
                            {
                                // outside error bounds/begin search area.  Split it.
                                int ly0, ly1, hy0, hy1;
                                var ret0 = FitLine(fits, lowSortPosition, sortPosition - lowSortPosition, out ly0,
                                                   out ly1);
                                var ret1 = FitLine(fits, sortPosition, highSortPosition - sortPosition, out hy0, out hy1);

                                if (ret0 != 0)
                                {
                                    ly0 = ly;
                                    ly1 = hy0;
                                }
                                if (ret1 != 0)
                                {
                                    hy0 = ly1;
                                    hy1 = hy;
                                }

                                if ((ret0 != 0) && (ret1 != 0))
                                {
                                    fitValueA[i] = -200;
                                    fitValueB[i] = -200;
                                }
                                else
                                {
                                    // store new edge values
                                    fitValueB[ln] = ly0;
                                    if (ln == 0)
                                    {
                                        fitValueA[ln] = ly0;
                                    }
                                    fitValueA[i]  = ly1;
                                    fitValueB[i]  = hy0;
                                    fitValueA[hn] = hy1;
                                    if (hn == 1)
                                    {
                                        fitValueB[hn] = hy1;
                                    }

                                    if ((ly1 >= 0) || (hy0 >= 0))
                                    {
                                        // store new neighbor values
                                        for (var j = sortPosition - 1; j >= 0; j--)
                                        {
                                            if (hineighbor[j] == hn)
                                            {
                                                hineighbor[j] = i;
                                            }
                                            else
                                            {
                                                break;
                                            }
                                        }

                                        for (var j = sortPosition + 1; j < _posts; j++)
                                        {
                                            if (loneighbor[j] == ln)
                                            {
                                                loneighbor[j] = i;
                                            }
                                            else
                                            {
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                fitValueA[i] = -200;
                                fitValueB[i] = -200;
                            }
                        }
                    }
                }

                var output = new int[_posts];

                output[0] = PostY(new List <int>(fitValueA), new List <int>(fitValueB), 0);
                output[1] = PostY(new List <int>(fitValueA), new List <int>(fitValueB), 1);

                // fill in posts marked as not using a fit; we will zero
                // back out to 'unused' when encoding them so int as curve
                // interpolation doesn't force them into use
                for (var i = 2; i < _posts; i++)
                {
                    var ln = _lowNeighbor[i - 2];
                    var hn = _highNeighbor[i - 2];
                    var x0 = _floor.PostList[ln];
                    var x1 = _floor.PostList[hn];
                    y0 = output[ln];
                    y1 = output[hn];

                    var predicted = RenderPoint(x0, x1, y0, y1, _floor.PostList[i]);
                    var vx        = PostY(new List <int>(fitValueA), new List <int>(fitValueB), i);

                    if ((vx >= 0) && (predicted != vx))
                    {
                        output[i] = vx;
                    }
                    else
                    {
                        output[i] = predicted | 0x8000;
                    }
                }

                return(output);
            }

            return(null);
        }