/** * Function enc_lag3() * Encoding of fractional pitch lag with 1/3 resolution. * <pre> * The pitch range for the first subframe is divided as follows: * 19 1/3 to 84 2/3 resolution 1/3 * 85 to 143 resolution 1 * * The period in the first subframe is encoded with 8 bits. * For the range with fractions: * index = (T-19)*3 + frac - 1; where T=[19..85] and frac=[-1,0,1] * and for the integer only range * index = (T - 85) + 197; where T=[86..143] *---------------------------------------------------------------------- * For the second subframe a resolution of 1/3 is always used, and the * search range is relative to the lag in the first subframe. * If t0 is the lag in the first subframe then * t_min=t0-5 and t_max=t0+4 and the range is given by * t_min - 2/3 to t_max + 2/3 * * The period in the 2nd subframe is encoded with 5 bits: * index = (T-(t_min-1))*3 + frac - 1; where T[t_min-1 .. t_max+1] * </pre> * * @param T0 input : Pitch delay * @param T0_frac input : Fractional pitch delay * @param T0_min in/out: Minimum search delay * @param T0_max in/out: Maximum search delay * @param pit_min input : Minimum pitch delay * @param pit_max input : Maximum pitch delay * @param pit_flag input : Flag for 1st subframe * @return Return index of encoding */ public static int enc_lag3( int T0, int T0_frac, IntReference T0_min, IntReference T0_max, int pit_min, int pit_max, int pit_flag ) { int index; int _T0_min = T0_min.value, _T0_max = T0_max.value; if (pit_flag == 0) /* if 1st subframe */ { /* encode pitch delay (with fraction) */ if (T0 <= 85) { index = T0 * 3 - 58 + T0_frac; } else { index = T0 + 112; } /* find T0_min and T0_max for second subframe */ _T0_min = T0 - 5; if (_T0_min < pit_min) { _T0_min = pit_min; } _T0_max = _T0_min + 9; if (_T0_max > pit_max) { _T0_max = pit_max; _T0_min = _T0_max - 9; } } else /* second subframe */ { index = T0 - _T0_min; index = index * 3 + 2 + T0_frac; } T0_min.value = _T0_min; T0_max.value = _T0_max; return(index); }
/** * Computes best (shortest) integer LTP delay + fine search * * @param t0 input : pitch delay given by coder * @param ptr_sig_in input : input signal (with delay line) * @param ptr_sig_in_offset input : input signal offset * @param ltpdel output: delay = *ltpdel - *phase / f_up * @param phase output: phase * @param num_gltp output: numerator of LTP gain * @param den_gltp output: denominator of LTP gain * @param y_up * @param off_yup */ private void search_del( int t0, float[] ptr_sig_in, int ptr_sig_in_offset, IntReference ltpdel, IntReference phase, FloatReference num_gltp, FloatReference den_gltp, float[] y_up, IntReference off_yup ) { var tab_hup_s = TabLd8k.tab_hup_s; /* pointers on tables of constants */ int ptr_h; /* Variables and local arrays */ float[] tab_den0 = new float[F_UP_PST - 1], tab_den1 = new float[F_UP_PST - 1]; int ptr_den0, ptr_den1; int ptr_sig_past, ptr_sig_past0; int ptr1; int i, n, ioff, i_max; float ener, num, numsq, den0, den1; float den_int, num_int; float den_max, num_max, numsq_max; int phi_max; int lambda, phi; float temp0, temp1; int ptr_y_up; /* Compute current signal energy */ ener = 0.0f; for (i = 0; i < L_SUBFR; i++) { ener += ptr_sig_in[ptr_sig_in_offset + i] * ptr_sig_in[ptr_sig_in_offset + i]; } if (ener < 0.1f) { num_gltp.value = 0.0f; den_gltp.value = 1.0f; ltpdel.value = 0; phase.value = 0; return; } /* Selects best of 3 integer delays */ /* Maximum of 3 numerators around t0 */ /* coder LTP delay */ lambda = t0 - 1; ptr_sig_past = ptr_sig_in_offset - lambda; num_int = -1.0e30f; /* initialization used only to suppress Microsoft Visual C++ warnings */ i_max = 0; for (i = 0; i < 3; i++) { num = 0.0f; for (n = 0; n < L_SUBFR; n++) { num += ptr_sig_in[ptr_sig_in_offset + n] * ptr_sig_in[ptr_sig_past + n]; } if (num > num_int) { i_max = i; num_int = num; } ptr_sig_past--; } if (num_int <= 0.0f) { num_gltp.value = 0.0f; den_gltp.value = 1.0f; ltpdel.value = 0; phase.value = 0; return; } /* Calculates denominator for lambda_max */ lambda += i_max; ptr_sig_past = ptr_sig_in_offset - lambda; den_int = 0.0f; for (n = 0; n < L_SUBFR; n++) { den_int += ptr_sig_in[ptr_sig_past + n] * ptr_sig_in[ptr_sig_past + n]; } if (den_int < 0.1f) { num_gltp.value = 0.0f; den_gltp.value = 1.0f; ltpdel.value = 0; phase.value = 0; return; } /* Select best phase around lambda */ /* Compute y_up & denominators */ ptr_y_up = 0; den_max = den_int; ptr_den0 = 0; ptr_den1 = 0; ptr_h = 0; ptr_sig_past0 = ptr_sig_in_offset + LH_UP_S - 1 - lambda; /* points on lambda_max+1 */ /* loop on phase */ for (phi = 1; phi < F_UP_PST; phi++) { /* Computes criterion for (lambda_max+1) - phi/F_UP_PST */ /* and lambda_max - phi/F_UP_PST */ ptr_sig_past = ptr_sig_past0; /* computes y_up[n] */ for (n = 0; n <= L_SUBFR; n++) { ptr1 = ptr_sig_past++; temp0 = 0.0f; for (i = 0; i < LH2_S; i++) { temp0 += tab_hup_s[ptr_h + i] * ptr_sig_in[ptr1 - i]; } y_up[ptr_y_up + n] = temp0; } /* recursive computation of den0 (lambda_max+1) and den1 (lambda_max) */ /* common part to den0 and den1 */ temp0 = 0.0f; for (n = 1; n < L_SUBFR; n++) { temp0 += y_up[ptr_y_up + n] * y_up[ptr_y_up + n]; } /* den0 */ den0 = temp0 + y_up[ptr_y_up + 0] * y_up[ptr_y_up + 0]; tab_den0[ptr_den0] = den0; ptr_den0++; /* den1 */ den1 = temp0 + y_up[ptr_y_up + L_SUBFR] * y_up[ptr_y_up + L_SUBFR]; tab_den1[ptr_den1] = den1; ptr_den1++; if (Math.Abs(y_up[ptr_y_up + 0]) > Math.Abs(y_up[ptr_y_up + L_SUBFR])) { if (den0 > den_max) { den_max = den0; } } else { if (den1 > den_max) { den_max = den1; } } ptr_y_up += L_SUBFRP1; ptr_h += LH2_S; } if (den_max < 0.1f) { num_gltp.value = 0.0f; den_gltp.value = 1.0f; ltpdel.value = 0; phase.value = 0; return; } /* Computation of the numerators */ /* and selection of best num*num/den */ /* for non null phases */ /* Initialize with null phase */ num_max = num_int; den_max = den_int; numsq_max = num_max * num_max; phi_max = 0; ioff = 1; ptr_den0 = 0; ptr_den1 = 0; ptr_y_up = 0; /* if den_max = 0 : will be selected and declared unvoiced */ /* if num!=0 & den=0 : will be selected and declared unvoiced */ /* degenerated seldom cases, switch off LT is OK */ /* Loop on phase */ for (phi = 1; phi < F_UP_PST; phi++) { /* computes num for lambda_max+1 - phi/F_UP_PST */ num = 0.0f; for (n = 0; n < L_SUBFR; n++) { num += ptr_sig_in[n] * y_up[ptr_y_up + n]; } if (num < 0.0f) { num = 0.0f; } numsq = num * num; /* selection if num/sqrt(den0) max */ den0 = tab_den0[ptr_den0]; ptr_den0++; temp0 = numsq * den_max; temp1 = numsq_max * den0; if (temp0 > temp1) { num_max = num; numsq_max = numsq; den_max = den0; ioff = 0; phi_max = phi; } /* computes num for lambda_max - phi/F_UP_PST */ ptr_y_up++; num = 0.0f; for (n = 0; n < L_SUBFR; n++) { num += ptr_sig_in[n] * y_up[ptr_y_up + n]; } if (num < 0.0f) { num = 0.0f; } numsq = num * num; /* selection if num/sqrt(den1) max */ den1 = tab_den1[ptr_den1]; ptr_den1++; temp0 = numsq * den_max; temp1 = numsq_max * den1; if (temp0 > temp1) { num_max = num; numsq_max = numsq; den_max = den1; ioff = 1; phi_max = phi; } ptr_y_up += L_SUBFR; } /* test if normalised crit0[iopt] > THRESCRIT */ if (num_max == 0.0f || den_max <= 0.1f) { num_gltp.value = 0.0f; den_gltp.value = 1.0f; ltpdel.value = 0; phase.value = 0; return; } /* comparison num * num */ /* with ener * den x THRESCRIT */ temp1 = den_max * ener * THRESCRIT; if (numsq_max >= temp1) { ltpdel.value = lambda + 1 - ioff; off_yup.value = ioff; phase.value = phi_max; num_gltp.value = num_max; den_gltp.value = den_max; } else { num_gltp.value = 0.0f; den_gltp.value = 1.0f; ltpdel.value = 0; phase.value = 0; } }
/** * Find the pitch period with 1/3 subsample resolution * * @param exc input : excitation buffer * @param exc_offset input : excitation buffer offset * @param xn input : target vector * @param h input : impulse response of filters. * @param l_subfr input : Length of frame to compute pitch * @param t0_min input : minimum value in the searched range * @param t0_max input : maximum value in the searched range * @param i_subfr input : indicator for first subframe * @param pit_frac output: chosen fraction * @return integer part of pitch period */ public static int pitch_fr3( float[] exc, /* */ int exc_offset, float[] xn, /* */ float[] h, /* */ int l_subfr, /* */ int t0_min, /* */ int t0_max, /* */ int i_subfr, /* */ IntReference pit_frac /* */ ) { var L_INTER4 = Ld8k.L_INTER4; int i, frac; int lag, t_min, t_max; float max; float corr_int; var corr_v = new float[10 + 2 * L_INTER4]; /* size: 2*L_INTER4+t0_max-t0_min+1 */ float[] corr; int corr_offset; /* Find interval to compute normalized correlation */ t_min = t0_min - L_INTER4; t_max = t0_max + L_INTER4; corr = corr_v; /* corr[t_min:t_max] */ corr_offset = -t_min; /* Compute normalized correlation between target and filtered excitation */ norm_corr(exc, exc_offset, xn, h, l_subfr, t_min, t_max, corr, corr_offset); /* find integer pitch */ max = corr[corr_offset + t0_min]; lag = t0_min; for (i = t0_min + 1; i <= t0_max; i++) { if (corr[corr_offset + i] >= max) { max = corr[corr_offset + i]; lag = i; } } /* If first subframe and lag > 84 do not search fractionnal pitch */ if (i_subfr == 0 && lag > 84) { pit_frac.value = 0; return(lag); } /* test the fractions around lag and choose the one which maximizes * the interpolated normalized correlation */ corr_offset += lag; max = interpol_3(corr, corr_offset, -2); frac = -2; for (i = -1; i <= 2; i++) { corr_int = interpol_3(corr, corr_offset, i); if (corr_int > max) { max = corr_int; frac = i; } } /* limit the fraction value in the interval [-1,0,1] */ if (frac == -2) { frac = 1; lag -= 1; } if (frac == 2) { frac = -1; lag += 1; } pit_frac.value = frac; return(lag); }
/** * Harmonic postfilter * * @param t0 input : pitch delay given by coder * @param ptr_sig_in input : postfilter input filter (residu2) * @param ptr_sig_in_offset input : postfilter input filter offset * @param ptr_sig_pst0 output: harmonic postfilter output * @param ptr_sig_pst0_offset input: harmonic postfilter offset * @return voicing decision 0 = uv, > 0 delay */ private int pst_ltp( int t0, float[] ptr_sig_in, int ptr_sig_in_offset, float[] ptr_sig_pst0, int ptr_sig_pst0_offset ) { int vo; /* Declare variables */ int ltpdel, phase; float num_gltp, den_gltp; float num2_gltp, den2_gltp; float gain_plt; var y_up = new float[SIZ_Y_UP]; float[] ptr_y_up; int ptr_y_up_offset; int off_yup; /* Sub optimal delay search */ var _ltpdel = new IntReference(); var _phase = new IntReference(); var _num_gltp = new FloatReference(); var _den_gltp = new FloatReference(); var _off_yup = new IntReference(); search_del( t0, ptr_sig_in, ptr_sig_in_offset, _ltpdel, _phase, _num_gltp, _den_gltp, y_up, _off_yup); ltpdel = _ltpdel.value; phase = _phase.value; num_gltp = _num_gltp.value; den_gltp = _den_gltp.value; off_yup = _off_yup.value; vo = ltpdel; if (num_gltp == 0.0f) { Util.copy(ptr_sig_in, ptr_sig_in_offset, ptr_sig_pst0, ptr_sig_pst0_offset, L_SUBFR); } else { if (phase == 0) { ptr_y_up = ptr_sig_in; ptr_y_up_offset = ptr_sig_in_offset - ltpdel; } else { /* Filtering with long filter */ var _num2_gltp = new FloatReference(); var _den2_gltp = new FloatReference(); compute_ltp_l( ptr_sig_in, ptr_sig_in_offset, ltpdel, phase, ptr_sig_pst0, ptr_sig_pst0_offset, _num2_gltp, _den2_gltp); num2_gltp = _num2_gltp.value; den2_gltp = _den2_gltp.value; if (select_ltp(num_gltp, den_gltp, num2_gltp, den2_gltp) == 1) { /* select short filter */ ptr_y_up = y_up; ptr_y_up_offset = (phase - 1) * L_SUBFRP1 + off_yup; } else { /* select long filter */ num_gltp = num2_gltp; den_gltp = den2_gltp; ptr_y_up = ptr_sig_pst0; ptr_y_up_offset = ptr_sig_pst0_offset; } } if (num_gltp > den_gltp) { gain_plt = MIN_GPLT; } else { gain_plt = den_gltp / (den_gltp + GAMMA_G * num_gltp); } /* filtering by H0(z) (harmonic filter) */ filt_plt( ptr_sig_in, ptr_sig_in_offset, ptr_y_up, ptr_y_up_offset, ptr_sig_pst0, ptr_sig_pst0_offset, gain_plt); } return(vo); }