Esempio n. 1
0
        internal static void renormalise_vector(int[] X, int X_ptr, int N, int gain)
        {
            int i;
            int k;
            int E;
            int g;
            int t;
            int xptr;

#if UNSAFE
            unsafe
            {
                fixed(int *px_base = X)
                {
                    int *px = px_base + X_ptr;

                    E = CeltConstants.EPSILON + Kernels.celt_inner_prod(px, px, N);
                }
            }
#else
            E = CeltConstants.EPSILON + Kernels.celt_inner_prod(X, X_ptr, X, X_ptr, N);
#endif
            k = Inlines.celt_ilog2(E) >> 1;
            t = Inlines.VSHR32(E, 2 * (k - 7));
            g = Inlines.MULT16_16_P15(Inlines.celt_rsqrt_norm(t), gain);

            xptr = X_ptr;
            for (i = 0; i < N; i++)
            {
                X[xptr] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.MULT16_16(g, X[xptr]), k + 1));
                xptr++;
            }
            /*return celt_sqrt(E);*/
        }
Esempio n. 2
0
        internal static int pitch_xcorr(
            int[] _x,
            int[] _y,
            int[] xcorr,
            int len,
            int max_pitch)
        {
            int i;
            int maxcorr = 1;

            Inlines.OpusAssert(max_pitch > 0);
            for (i = 0; i < max_pitch - 3; i += 4)
            {
                int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
                Kernels.xcorr_kernel(_x, _y, i, ref sum0, ref sum1, ref sum2, ref sum3, len);
                xcorr[i]     = sum0;
                xcorr[i + 1] = sum1;
                xcorr[i + 2] = sum2;
                xcorr[i + 3] = sum3;
                sum0         = Inlines.MAX32(sum0, sum1);
                sum2         = Inlines.MAX32(sum2, sum3);
                sum0         = Inlines.MAX32(sum0, sum2);
                maxcorr      = Inlines.MAX32(maxcorr, sum0);
            }
            /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
            for (; i < max_pitch; i++)
            {
                int inner_sum = Kernels.celt_inner_prod(_x, 0, _y, i, len);
                xcorr[i] = inner_sum;
                maxcorr  = Inlines.MAX32(maxcorr, inner_sum);
            }
            return(maxcorr);
        }
Esempio n. 3
0
        internal static int stereo_itheta(int[] X, int X_ptr, int[] Y, int Y_ptr, int stereo, int N)
        {
            int i;
            int itheta;
            int mid, side;
            int Emid, Eside;

            Emid = Eside = CeltConstants.EPSILON;
            if (stereo != 0)
            {
                for (i = 0; i < N; i++)
                {
                    int m, s;
                    m     = Inlines.ADD16(Inlines.SHR16(X[X_ptr + i], 1), Inlines.SHR16(Y[Y_ptr + i], 1));
                    s     = Inlines.SUB16(Inlines.SHR16(X[X_ptr + i], 1), Inlines.SHR16(Y[Y_ptr + i], 1));
                    Emid  = Inlines.MAC16_16(Emid, m, m);
                    Eside = Inlines.MAC16_16(Eside, s, s);
                }
            }
            else
            {
                Emid  += Kernels.celt_inner_prod(X, X_ptr, X, X_ptr, N);
                Eside += Kernels.celt_inner_prod(Y, Y_ptr, Y, Y_ptr, N);
            }
            mid  = (Inlines.celt_sqrt(Emid));
            side = (Inlines.celt_sqrt(Eside));
            /* 0.63662 = 2/pi */
            itheta = Inlines.MULT16_16_Q15(((short)(0.5 + (0.63662f) * (((int)1) << (15)))) /*Inlines.QCONST16(0.63662f, 15)*/, Inlines.celt_atan2p(side, mid));

            return(itheta);
        }
        internal static unsafe int pitch_xcorr(
            short[] _x,
            int _x_ptr,
            short[] _y,
            int _y_ptr,
            int[] xcorr,
            int len,
            int max_pitch)
        {
            int i;
            int maxcorr = 1;

            Inlines.OpusAssert(max_pitch > 0);
            fixed(int *pxcorr = xcorr)
            {
                fixed(short *px_base = _x, py_base = _y)
                {
                    short *px = px_base + _x_ptr;

                    for (i = 0; i < max_pitch - 3; i += 4)
                    {
                        int    sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
                        short *py = py_base + _y_ptr + i;
                        Kernels.xcorr_kernel(px, py, ref sum0, ref sum1, ref sum2, ref sum3, len);

                        int *pxcorr2 = pxcorr + i;
                        pxcorr2[0] = sum0;
                        pxcorr2[1] = sum1;
                        pxcorr2[2] = sum2;
                        pxcorr2[3] = sum3;
                        sum0       = Inlines.MAX32(sum0, sum1);
                        sum2       = Inlines.MAX32(sum2, sum3);
                        sum0       = Inlines.MAX32(sum0, sum2);
                        maxcorr    = Inlines.MAX32(maxcorr, sum0);
                    }
                    /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
                    for (; i < max_pitch; i++)
                    {
                        short *py        = py_base + _y_ptr + i;
                        int    inner_sum = Kernels.celt_inner_prod(px, py, len);
                        xcorr[i] = inner_sum;
                        maxcorr  = Inlines.MAX32(maxcorr, inner_sum);
                    }
                }
            }

            return(maxcorr);
        }
Esempio n. 5
0
        internal static void celt_iir(
            int[] _x,
            int _x_ptr,
            int[] den,
            int[] _y,
            int _y_ptr,
            int N,
            int ord,
            int[] mem)
        {
            int i, j;

            int[] rden = new int[ord];
            int[] y    = new int[N + ord];
            Inlines.OpusAssert((ord & 3) == 0);

            for (i = 0; i < ord; i++)
            {
                rden[i] = den[ord - i - 1];
            }
            for (i = 0; i < ord; i++)
            {
                y[i] = (0 - mem[ord - i - 1]);
            }
            for (; i < N + ord; i++)
            {
                y[i] = 0;
            }
            for (i = 0; i < N - 3; i += 4)
            {
                /* Unroll by 4 as if it were an FIR filter */
                int sum0 = _x[_x_ptr + i];
                int sum1 = _x[_x_ptr + i + 1];
                int sum2 = _x[_x_ptr + i + 2];
                int sum3 = _x[_x_ptr + i + 3];
                Kernels.xcorr_kernel(rden, y, i, ref sum0, ref sum1, ref sum2, ref sum3, ord);

                /* Patch up the result to compensate for the fact that this is an IIR */
                y[i + ord]         = (0 - Inlines.ROUND16((sum0), CeltConstants.SIG_SHIFT));
                _y[_y_ptr + i]     = sum0;
                sum1               = Inlines.MAC16_16(sum1, y[i + ord], den[0]);
                y[i + ord + 1]     = (0 - Inlines.ROUND16((sum1), CeltConstants.SIG_SHIFT));
                _y[_y_ptr + i + 1] = sum1;
                sum2               = Inlines.MAC16_16(sum2, y[i + ord + 1], den[0]);
                sum2               = Inlines.MAC16_16(sum2, y[i + ord], den[1]);
                y[i + ord + 2]     = (0 - Inlines.ROUND16((sum2), CeltConstants.SIG_SHIFT));
                _y[_y_ptr + i + 2] = sum2;

                sum3               = Inlines.MAC16_16(sum3, y[i + ord + 2], den[0]);
                sum3               = Inlines.MAC16_16(sum3, y[i + ord + 1], den[1]);
                sum3               = Inlines.MAC16_16(sum3, y[i + ord], den[2]);
                y[i + ord + 3]     = (0 - Inlines.ROUND16((sum3), CeltConstants.SIG_SHIFT));
                _y[_y_ptr + i + 3] = sum3;
            }
            for (; i < N; i++)
            {
                int sum = _x[_x_ptr + i];
                for (j = 0; j < ord; j++)
                {
                    sum -= Inlines.MULT16_16(rden[j], y[i + j]);
                }
                y[i + ord]     = Inlines.ROUND16((sum), CeltConstants.SIG_SHIFT);
                _y[_y_ptr + i] = sum;
            }
            for (i = 0; i < ord; i++)
            {
                mem[i] = (_y[_y_ptr + N - i - 1]);
            }
        }
Esempio n. 6
0
        internal static int remove_doubling(int[] x, int maxperiod, int minperiod,
                                            int N, ref int T0_, int prev_period, int prev_gain)
        {
            int k, i, T, T0;
            int g, g0;
            int pg;
            int yy, xx, xy, xy2;

            int[] xcorr = new int[3];
            int   best_xy, best_yy;
            int   offset;
            int   minperiod0 = minperiod;

            maxperiod   /= 2;
            minperiod   /= 2;
            T0_         /= 2;
            prev_period /= 2;
            N           /= 2;
            int x_ptr = maxperiod;

            if (T0_ >= maxperiod)
            {
                T0_ = maxperiod - 1;
            }

            T = T0 = T0_;
            int[] yy_lookup = new int[maxperiod + 1];
            Kernels.dual_inner_prod(x, x_ptr, x, x_ptr, x, x_ptr - T0, N, out xx, out xy);
            yy_lookup[0] = xx;
            yy           = xx;
            for (i = 1; i <= maxperiod; i++)
            {
                int xi = x_ptr - i;
                yy           = yy + Inlines.MULT16_16(x[xi], x[xi]) - Inlines.MULT16_16(x[xi + N], x[xi + N]);
                yy_lookup[i] = Inlines.MAX32(0, yy);
            }
            yy      = yy_lookup[T0];
            best_xy = xy;
            best_yy = yy;

            {
                int x2y2;
                int sh, t;
                x2y2 = 1 + Inlines.HALF32(Inlines.MULT32_32_Q31(xx, yy));
                sh   = Inlines.celt_ilog2(x2y2) >> 1;
                t    = Inlines.VSHR32(x2y2, 2 * (sh - 7));
                g    = (Inlines.VSHR32(Inlines.MULT16_32_Q15(Inlines.celt_rsqrt_norm(t), xy), sh + 1));
                g0   = g;
            }

            /* Look for any pitch at T/k */
            for (k = 2; k <= 15; k++)
            {
                int T1, T1b;
                int g1;
                int cont = 0;
                int thresh;
                T1 = Inlines.celt_udiv(2 * T0 + k, 2 * k);
                if (T1 < minperiod)
                {
                    break;
                }

                /* Look for another strong correlation at T1b */
                if (k == 2)
                {
                    if (T1 + T0 > maxperiod)
                    {
                        T1b = T0;
                    }
                    else
                    {
                        T1b = T0 + T1;
                    }
                }
                else
                {
                    T1b = Inlines.celt_udiv(2 * second_check[k] * T0 + k, 2 * k);
                }

                Kernels.dual_inner_prod(x, x_ptr, x, x_ptr - T1, x, x_ptr - T1b, N, out xy, out xy2);

                xy += xy2;
                yy  = yy_lookup[T1] + yy_lookup[T1b];

                {
                    int x2y2;
                    int sh, t;
                    x2y2 = 1 + Inlines.MULT32_32_Q31(xx, yy);
                    sh   = Inlines.celt_ilog2(x2y2) >> 1;
                    t    = Inlines.VSHR32(x2y2, 2 * (sh - 7));
                    g1   = (Inlines.VSHR32(Inlines.MULT16_32_Q15(Inlines.celt_rsqrt_norm(t), xy), sh + 1));
                }

                if (Inlines.abs(T1 - prev_period) <= 1)
                {
                    cont = prev_gain;
                }
                else if (Inlines.abs(T1 - prev_period) <= 2 && 5 * k * k < T0)
                {
                    cont = Inlines.HALF16(prev_gain);
                }
                else
                {
                    cont = 0;
                }
                thresh = Inlines.MAX16(((short)(0.5 + (.3f) * (((int)1) << (15)))) /*Inlines.QCONST16(.3f, 15)*/, (Inlines.MULT16_16_Q15(((short)(0.5 + (.7f) * (((int)1) << (15)))) /*Inlines.QCONST16(.7f, 15)*/, g0) - cont));

                /* Bias against very high pitch (very short period) to avoid false-positives
                 * due to short-term correlation */
                if (T1 < 3 * minperiod)
                {
                    thresh = Inlines.MAX16(((short)(0.5 + (.4f) * (((int)1) << (15)))) /*Inlines.QCONST16(.4f, 15)*/, (Inlines.MULT16_16_Q15(((short)(0.5 + (.85f) * (((int)1) << (15)))) /*Inlines.QCONST16(.85f, 15)*/, g0) - cont));
                }
                else if (T1 < 2 * minperiod)
                {
                    thresh = Inlines.MAX16(((short)(0.5 + (.5f) * (((int)1) << (15)))) /*Inlines.QCONST16(.5f, 15)*/, (Inlines.MULT16_16_Q15(((short)(0.5 + (.9f) * (((int)1) << (15)))) /*Inlines.QCONST16(.9f, 15)*/, g0) - cont));
                }
                if (g1 > thresh)
                {
                    best_xy = xy;
                    best_yy = yy;
                    T       = T1;
                    g       = g1;
                }
            }

            best_xy = Inlines.MAX32(0, best_xy);
            if (best_yy <= best_xy)
            {
                pg = CeltConstants.Q15ONE;
            }
            else
            {
                pg = (Inlines.SHR32(Inlines.frac_div32(best_xy, best_yy + 1), 16));
            }

            for (k = 0; k < 3; k++)
            {
                xcorr[k] = Kernels.celt_inner_prod(x, x_ptr, x, x_ptr - (T + k - 1), N);
            }

            if ((xcorr[2] - xcorr[0]) > Inlines.MULT16_32_Q15(((short)(0.5 + (.7f) * (((int)1) << (15)))) /*Inlines.QCONST16(.7f, 15)*/, xcorr[1] - xcorr[0]))
            {
                offset = 1;
            }
            else if ((xcorr[0] - xcorr[2]) > Inlines.MULT16_32_Q15(((short)(0.5 + (.7f) * (((int)1) << (15)))) /*Inlines.QCONST16(.7f, 15)*/, xcorr[1] - xcorr[2]))
            {
                offset = -1;
            }
            else
            {
                offset = 0;
            }

            if (pg > g)
            {
                pg = g;
            }

            T0_ = 2 * T + offset;

            if (T0_ < minperiod0)
            {
                T0_ = minperiod0;
            }

            return(pg);
        }