/* ** Copyright 2003-2010, VisualOn, Inc. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ /*********************************************************************** * File: pitch_f4.c * * * * Description: 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" #define UP_SAMP 4 #define L_INTERPOL1 4 #define UNUSED(x) (void)(x) /* Local functions */ #ifdef ASM_OPT void Norm_corr_asm( Word16 exc[], /* (i) : excitation buffer */ Word16 xn[], /* (i) : target vector */ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ Word16 L_subfr, 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 */ ); #else 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, 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 */ ); #endif static Word16 Interpol_4( /* (o) : interpolated value */ Word16 * x, /* (i) : input vector */ Word32 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 */ ) { Word32 fraction, i; Word16 t_min, t_max; Word16 max, t0, 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 = t0_min - L_INTERPOL1; t_max = t0_max + L_INTERPOL1; corr = &corr_v[-t_min]; /* Compute normalized correlation between target and filtered excitation */ #ifdef ASM_OPT /* asm optimization branch */ Norm_corr_asm(exc, xn, h, L_subfr, t_min, t_max, corr); #else Norm_Corr(exc, xn, h, L_subfr, t_min, t_max, corr); #endif /* Find integer pitch */ max = corr[t0_min]; t0 = t0_min; for (i = t0_min + 1; i <= t0_max; i++) { if (corr[i] >= max) { max = corr[i]; t0 = i; } } /* If first subframe and t0 >= t0_fr1, do not search fractionnal pitch */ if ((i_subfr == 0) && (t0 >= t0_fr1)) { *pit_frac = 0; 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; /* 1/4 subsample resolution */ fraction = -3; if ((t0_fr2 == PIT_MIN)||((i_subfr == 0) && (t0 >= t0_fr2))) { step = 2; /* 1/2 subsample resolution */ fraction = -2; } if(t0 == t0_min) { fraction = 0; } max = Interpol_4(&corr[t0], fraction); for (i = fraction + step; i <= 3; i += step) { temp = Interpol_4(&corr[t0], i); if(temp > max) { max = temp; fraction = i; } } /* limit the fraction value in the interval [0,1,2,3] */ if (fraction < 0) { fraction += UP_SAMP; t0 -= 1; } *pit_frac = fraction; return (t0); } /*********************************************************************************** * Function: Norm_Corr() * * * * Description: 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). * ************************************************************************************/ #ifndef ASM_OPT 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, 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 */ { Word32 i, k, t; Word32 corr, exp_corr, norm, exp, scale; Word16 exp_norm, excf[L_SUBFR], tmp; Word32 L_tmp, L_tmp1, L_tmp2; UNUSED(L_subfr); /* compute the filtered excitation for the first delay t_min */ k = -t_min; #ifdef ASM_OPT /* asm optimization branch */ Convolve_asm(&exc[k], h, excf, 64); #else Convolve(&exc[k], h, excf, 64); #endif /* Compute rounded down 1/sqrt(energy of xn[]) */ L_tmp = 0; for (i = 0; i < 64; i+=4) { L_tmp += (xn[i] * xn[i]); L_tmp += (xn[i+1] * xn[i+1]); L_tmp += (xn[i+2] * xn[i+2]); L_tmp += (xn[i+3] * xn[i+3]); } L_tmp = (L_tmp << 1) + 1; exp = norm_l(L_tmp); exp = (32 - exp); //exp = exp + 2; /* energy of xn[] x 2 + rounded up */ scale = -(exp >> 1); /* (1<> L_tmp2; } else { L_tmp = L_tmp << L_tmp2; } corr_norm[t] = vo_round(L_tmp); /* modify the filtered excitation excf[] for the next iteration */ if(t != t_max) { k = -(t + 1); tmp = exc[k]; for (i = 63; i > 0; i--) { excf[i] = add1(vo_mult(tmp, h[i]), excf[i - 1]); } excf[0] = vo_mult(tmp, h[0]); } } return; } #endif /************************************************************************************ * Function: Interpol_4() * * * * Description: 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[4][8] = { {-12, 420, -1732, 5429, 13418, -1242, 73, 32}, {-26, 455, -2142, 9910, 9910, -2142, 455, -26}, {32, 73, -1242, 13418, 5429, -1732, 420, -12}, {206, -766, 1376, 14746, 1376, -766, 206, 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 */ Word32 frac /* (i) : fraction (-4..+3) */ ) { Word16 sum; Word32 k, L_sum; Word16 *ptr; if (frac < 0) { frac += UP_SAMP; x--; } x = x - L_INTERPOL1 + 1; k = UP_SAMP - 1 - frac; ptr = &(inter4_1[k][0]); L_sum = vo_mult32(x[0], (*ptr++)); L_sum += vo_mult32(x[1], (*ptr++)); L_sum += vo_mult32(x[2], (*ptr++)); L_sum += vo_mult32(x[3], (*ptr++)); L_sum += vo_mult32(x[4], (*ptr++)); L_sum += vo_mult32(x[5], (*ptr++)); L_sum += vo_mult32(x[6], (*ptr++)); L_sum += vo_mult32(x[7], (*ptr++)); sum = extract_h(L_add(L_shl2(L_sum, 2), 0x8000)); return (sum); }