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);*/ }
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); }
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); }
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); }