ref: 120b9c56f2afff5e8bf5e9cf8c06a6c8df744384
dir: /amr-wb/pitch_f4.c/
/*-----------------------------------------------------------------------* * PITCH_F4.C * *-----------------------------------------------------------------------* * Find the closed loop pitch period with 1/4 subsample resolution. * *-----------------------------------------------------------------------*/ #include "typedef.h" #include "basic_op.h" #include "math_op.h" #include "acelp.h" #include "cnst.h" #include "count.h" #define UP_SAMP 4 #define L_INTERPOL1 4 /* Local functions */ static void Norm_Corr( Word16 exc[], /* (i) : excitation buffer */ Word16 xn[], /* (i) : target vector */ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ Word16 L_subfr, /* (i) : Length of subframe */ Word16 t_min, /* (i) : minimum value of pitch lag. */ Word16 t_max, /* (i) : maximum value of pitch lag. */ Word16 corr_norm[] /* (o) Q15 : normalized correlation */ ); static Word16 Interpol_4( /* (o) : interpolated value */ Word16 * x, /* (i) : input vector */ Word16 frac /* (i) : fraction (-4..+3) */ ); Word16 Pitch_fr4( /* (o) : pitch period. */ Word16 exc[], /* (i) : excitation buffer */ Word16 xn[], /* (i) : target vector */ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ Word16 t0_min, /* (i) : minimum value in the searched range. */ Word16 t0_max, /* (i) : maximum value in the searched range. */ Word16 * pit_frac, /* (o) : chosen fraction (0, 1, 2 or 3). */ Word16 i_subfr, /* (i) : indicator for first subframe. */ Word16 t0_fr2, /* (i) : minimum value for resolution 1/2 */ Word16 t0_fr1, /* (i) : minimum value for resolution 1 */ Word16 L_subfr /* (i) : Length of subframe */ ) { Word16 i; Word16 t_min, t_max; Word16 max, t0, fraction, step, temp; Word16 *corr; Word16 corr_v[40]; /* Total length = t0_max-t0_min+1+2*L_inter */ /* Find interval to compute normalized correlation */ t_min = sub(t0_min, L_INTERPOL1); t_max = add(t0_max, L_INTERPOL1); corr = &corr_v[-t_min]; move16(); /* Compute normalized correlation between target and filtered excitation */ Norm_Corr(exc, xn, h, L_subfr, t_min, t_max, corr); /* Find integer pitch */ max = corr[t0_min]; move16(); t0 = t0_min; move16(); for (i = add(t0_min, 1); i <= t0_max; i++) { test(); if (sub(corr[i], max) >= 0) { max = corr[i]; move16(); t0 = i; move16(); } } /* If first subframe and t0 >= t0_fr1, do not search fractionnal pitch */ test();test(); if ((i_subfr == 0) && (sub(t0, t0_fr1) >= 0)) { *pit_frac = 0; move16(); return (t0); } /*------------------------------------------------------------------* * Search fractionnal pitch with 1/4 subsample resolution. * * Test the fractions around t0 and choose the one which maximizes * * the interpolated normalized correlation. * *------------------------------------------------------------------*/ step = 1; move16(); /* 1/4 subsample resolution */ fraction = -3; move16(); test();test();test(); if (((i_subfr == 0) && (sub(t0, t0_fr2) >= 0)) || (sub(t0_fr2, PIT_MIN) == 0)) { step = 2; move16(); /* 1/2 subsample resolution */ fraction = -2; move16(); } test(); if (sub(t0, t0_min) == 0) { fraction = 0; move16(); } max = Interpol_4(&corr[t0], fraction); for (i = add(fraction, step); i <= 3; i = (Word16) (i + step)) { temp = Interpol_4(&corr[t0], i); test(); if (sub(temp, max) > 0) { max = temp; move16(); fraction = i; move16(); } } /* limit the fraction value in the interval [0,1,2,3] */ test(); if (fraction < 0) { fraction = add(fraction, UP_SAMP); t0 = sub(t0, 1); } *pit_frac = fraction; move16(); return (t0); } /*--------------------------------------------------------------------------* * Function Norm_Corr() * * ~~~~~~~~~~~~~~~~~~~~ * * Find the normalized correlation between the target vector and the * * filtered past excitation. * * (correlation between target and filtered excitation divided by the * * square root of energy of target and filtered excitation). * *--------------------------------------------------------------------------*/ static void Norm_Corr( Word16 exc[], /* (i) : excitation buffer */ Word16 xn[], /* (i) : target vector */ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ Word16 L_subfr, /* (i) : Length of subframe */ Word16 t_min, /* (i) : minimum value of pitch lag. */ Word16 t_max, /* (i) : maximum value of pitch lag. */ Word16 corr_norm[]) /* (o) Q15 : normalized correlation */ { Word16 i, k, t; Word16 corr, exp_corr, norm, exp_norm, exp, scale; Word16 excf[L_SUBFR]; Word32 L_tmp; /* compute the filtered excitation for the first delay t_min */ k = negate(t_min); Convolve(&exc[k], h, excf, L_subfr); /* Compute rounded down 1/sqrt(energy of xn[]) */ L_tmp = 1L; move32(); for (i = 0; i < L_subfr; i++) L_tmp = L_mac(L_tmp, xn[i], xn[i]); exp = norm_l(L_tmp); exp = sub(30, exp); exp = add(exp, 2); /* energy of xn[] x 2 + rounded up */ scale = negate(shr(exp, 1)); /* (1<<scale) < 1/sqrt(energy rounded) */ /* loop for every possible period */ for (t = t_min; t <= t_max; t++) { /* Compute correlation between xn[] and excf[] */ L_tmp = 1L; move32(); for (i = 0; i < L_subfr; i++) L_tmp = L_mac(L_tmp, xn[i], excf[i]); exp = norm_l(L_tmp); L_tmp = L_shl(L_tmp, exp); exp_corr = sub(30, exp); corr = extract_h(L_tmp); /* Compute 1/sqrt(energy of excf[]) */ L_tmp = 1L; move32(); for (i = 0; i < L_subfr; i++) L_tmp = L_mac(L_tmp, excf[i], excf[i]); exp = norm_l(L_tmp); L_tmp = L_shl(L_tmp, exp); exp_norm = sub(30, exp); Isqrt_n(&L_tmp, &exp_norm); norm = extract_h(L_tmp); /* Normalize correlation = correlation * (1/sqrt(energy)) */ L_tmp = L_mult(corr, norm); L_tmp = L_shl(L_tmp, add(add(exp_corr, exp_norm), scale)); corr_norm[t] = round(L_tmp); move16(); /* modify the filtered excitation excf[] for the next iteration */ test(); if (sub(t, t_max) != 0) { k--; move16(); for (i = (Word16) (L_subfr - 1); i > 0; i--) { /* saturation can occur in add() */ excf[i] = add(mult(exc[k], h[i]), excf[i - 1]); move16(); } excf[0] = mult(exc[k], h[0]); move16(); } } return; } /*--------------------------------------------------------------------------* * Procedure Interpol_4() * * ~~~~~~~~~~~~~~~~~~~~~~ * * For interpolating the normalized correlation with 1/4 resolution. * *--------------------------------------------------------------------------*/ /* 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) in Q14 */ static Word16 inter4_1[UP_SAMP * 2 * L_INTERPOL1] = { -12, -26, 32, 206, 420, 455, 73, -766, -1732, -2142, -1242, 1376, 5429, 9910, 13418, 14746, 13418, 9910, 5429, 1376, -1242, -2142, -1732, -766, 73, 455, 420, 206, 32, -26, -12, 0 }; /*** Coefficients in floating point static float inter4_1[UP_SAMP*L_INTERPOL1+1] = { 0.900000, 0.818959, 0.604850, 0.331379, 0.083958, -0.075795, -0.130717, -0.105685, -0.046774, 0.004467, 0.027789, 0.025642, 0.012571, 0.001927, -0.001571, -0.000753, 0.000000}; ***/ static Word16 Interpol_4( /* (o) : interpolated value */ Word16 * x, /* (i) : input vector */ Word16 frac /* (i) : fraction (-4..+3) */ ) { Word16 i, k, sum; Word32 L_sum; test(); if (frac < 0) { frac = add(frac, UP_SAMP); x--; move16(); } x = x - L_INTERPOL1 + 1; move16(); L_sum = 0L; move32(); for (i = 0, k = sub(sub(UP_SAMP, 1), frac); i < 2 * L_INTERPOL1; i++, k += UP_SAMP) { L_sum = L_mac(L_sum, x[i], inter4_1[k]); } sum = round(L_shl(L_sum, 1)); return (sum); }