package org.red5.app.sip.codecs.g729; //package org.mobicents.media.server.impl.dsp.audio.g729; public class Pitch { /*---------------------------------------------------------------------------- * pitch_ol - compute the open loop pitch lag *---------------------------------------------------------------------------- */ public static int pitch_ol( /* output: open-loop pitch lag */ float signal[],int signals, /* input : signal to compute pitch */ /* s[-PIT_MAX : l_frame-1] */ int pit_min, /* input : minimum pitch lag */ int pit_max, /* input : maximum pitch lag */ int l_frame /* input : error minimization window */ ) { FloatPointer max1 = new FloatPointer(), max2 =new FloatPointer(), max3 = new FloatPointer(); int p_max1, p_max2, p_max3; /*--------------------------------------------------------------------* * The pitch lag search is divided in three sections. * * Each section cannot have a pitch multiple. * * We find a maximum for each section. * * We compare the maxima of each section by favoring small lag. * * * * First section: lag delay = PIT_MAX to 80 * * Second section: lag delay = 79 to 40 * * Third section: lag delay = 39 to 20 * *--------------------------------------------------------------------*/ p_max1 = lag_max(signal, signals, l_frame, pit_max, 80 , max1); p_max2 = lag_max(signal, signals, l_frame, 79 , 40 , max2); p_max3 = lag_max(signal, signals, l_frame, 39 , pit_min , max3); /*--------------------------------------------------------------------* * Compare the 3 sections maxima, and favor small lag. * *--------------------------------------------------------------------*/ if ( max1.value * LD8KConstants.THRESHPIT < max2.value ) { max1.value = max2.value; p_max1 = p_max2; } if ( max1.value * LD8KConstants.THRESHPIT < max3.value ) p_max1 = p_max3; return (p_max1); } /*---------------------------------------------------------------------------- * lag_max - Find the lag that has maximum correlation *---------------------------------------------------------------------------- */ public static int lag_max( /* output: lag found */ float signal[], int signals, /* input : Signal to compute the open loop pitch signal[-142:-1] should be known. */ int l_frame, /* input : Length of frame to compute pitch */ int lagmax, /* input : maximum lag */ int lagmin, /* input : minimum lag */ FloatPointer cor_max /* input : normalized correlation of selected lag */ ) { int i, j; int p=0, p1; float max, t0; int p_max=0; max = LD8KConstants.FLT_MIN_G729; for (i = lagmax; i >= lagmin; i--) { p = 0;//signal; p1 = -i;//&signal[-i]; t0 = (float)0.0; for (j=0; j<l_frame; j++) { t0 += signal[signals + p++] * signal[signals + p1++]; } if (t0 >= max) { max = t0; p_max = i; } } /* compute energy */ t0 = (float)0.01; /* to avoid division by zero */ p = -p_max; for(i=0; i<l_frame; i++, p++) { t0 += signal[signals + p] * signal[signals + p]; } t0 = inv_sqrt(t0); /* 1/sqrt(energy) */ cor_max.value = max * t0; /* max/sqrt(energy) */ return(p_max); } /*---------------------------------------------------------------------------- * pitch_fr3 - find the pitch period with 1/3 subsample resolution *---------------------------------------------------------------------------- */ public static int pitch_fr3( /* output: integer part of pitch period */ float exc[],int excs, /* input : excitation buffer */ float xn[],int xns, /* input : target vector */ float h[], int hs, /* input : impulse response of filters. */ int l_subfr, /* input : Length of frame to compute pitch */ int t0_min, /* input : minimum value in the searched range */ int t0_max, /* input : maximum value in the searched range */ int i_subfr, /* input : indicator for first subframe */ IntegerPointer pit_frac /* output: chosen fraction */ ) { int i, frac; int lag, t_min, t_max; float max; float corr_int; float corr_v[] = new float[10+2*LD8KConstants.L_INTER4]; /* size: 2*L_INTER4+t0_max-t0_min+1 */ int corr; /* Find interval to compute normalized correlation */ t_min = t0_min - LD8KConstants.L_INTER4; t_max = t0_max + LD8KConstants.L_INTER4; corr = -t_min; /* corr[t_min:t_max] */ /* Compute normalized correlation between target and filtered excitation */ norm_corr(exc, excs, xn, xns, h, hs, l_subfr, t_min, t_max, corr_v, corr); /* find integer pitch */ max = corr_v[corr+t0_min]; lag = t0_min; for(i= t0_min+1; i<=t0_max; i++) { if( corr_v[corr+i] >= max) { max = corr_v[corr+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 */ max = interpol_3(corr_v, corr+lag, -2); frac = -2; for (i = -1; i <= 2; i++) { corr_int = interpol_3(corr_v, corr+lag, 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; } /*---------------------------------------------------------------------------- * norm_corr - Find the normalized correlation between the target vector and * the filtered past excitation. *---------------------------------------------------------------------------- */ public static void norm_corr( float exc[],int excs, /* input : excitation buffer */ float xn[],int xns, /* input : target vector */ float h[],int hs, /* input : imp response of synth and weighting flt */ int l_subfr, /* input : Length of frame to compute pitch */ int t_min, /* input : minimum value of searched range */ int t_max, /* input : maximum value of search range */ float corr_norm[], int cs /* output: normalized correlation (correlation between target and filtered excitation divided by the square root of energy of filtered excitation) */ ) { int i, j, k; float excf[] = new float[LD8KConstants.L_SUBFR]; /* filtered past excitation */ float alp, s, norm; k = -t_min; /* compute the filtered excitation for the first delay t_min */ Filter.convolve(exc,excs+k, h, 0, excf, 0, l_subfr); /* loop for every possible period */ for (i = t_min; i <= t_max; i++) { /* Compute 1/sqrt(energie of excf[]) */ alp = (float)0.01; for (j = 0; j < l_subfr; j++) alp += excf[j]*excf[j]; norm = inv_sqrt(alp); /* Compute correlation between xn[] and excf[] */ s = (float)0.0; for (j = 0; j < l_subfr; j++) s += xn[xns+j]*excf[j]; /* Normalize correlation = correlation * (1/sqrt(energie)) */ corr_norm[cs+i] = s*norm; /* modify the filtered excitation excf[] for the next iteration */ if (i != t_max) { k--; for (j = l_subfr-1; j > 0; j--) excf[j] = excf[j-1] + exc[excs+k]*h[j]; excf[0] = exc[excs+k]; } } return; } /*---------------------------------------------------------------------------- * g_pitch - compute adaptive codebook gain and compute <y1,y1> , -2<xn,y1> *---------------------------------------------------------------------------- */ public static float g_pitch( /* output: pitch gain */ float xn[],int xns, /* input : target vector */ float y1[],int y1s, /* input : filtered adaptive codebook vector */ float g_coeff[],int gs, /* output: <y1,y1> and -2<xn,y1> */ int l_subfr /* input : vector dimension */ ) { float xy, yy, gain; int i; xy = (float)0.0; for (i = 0; i < l_subfr; i++) { xy += xn[xns+i] * y1[y1s+i]; } yy = (float)0.01; for (i = 0; i < l_subfr; i++) { yy += y1[y1s+i] * y1[y1s+i]; /* energy of filtered excitation */ } g_coeff[gs+0] = yy; g_coeff[gs+1] = (float)-2.0*xy +(float)0.01; /* find pitch gain and bound it by [0,1.2] */ gain = xy/yy; if (gain<(float)0.0) gain = (float)0.0; if (gain>LD8KConstants.GAIN_PIT_MAX) gain = LD8KConstants.GAIN_PIT_MAX; return gain; } /*----------------------------------------------------------------------* * Function enc_lag3() * * ~~~~~~~~~~ * * Encoding of fractional pitch lag with 1/3 resolution. * *----------------------------------------------------------------------* * 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] * *----------------------------------------------------------------------*/ public static int enc_lag3( /* output: Return index of encoding */ int T0, /* input : Pitch delay */ int T0_frac, /* input : Fractional pitch delay */ IntegerPointer T0_min, /* in/out: Minimum search delay */ IntegerPointer T0_max, /* in/out: Maximum search delay */ int pit_min, /* input : Minimum pitch delay */ int pit_max, /* input : Maximum pitch delay */ int pit_flag /* input : Flag for 1st subframe */ ) { int index; 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.value = T0 - 5; if (T0_min.value < pit_min) T0_min.value = pit_min; T0_max.value = T0_min.value + 9; if (T0_max.value > pit_max) { T0_max.value = pit_max; T0_min.value = T0_max.value - 9; } } else /* second subframe */ { index = T0 - T0_min.value; index = index*3 + 2 + T0_frac; } return index; } /*---------------------------------------------------------------------------- * interpol_3 - For interpolating the normalized correlation *---------------------------------------------------------------------------- */ public static float interpol_3( /* output: interpolated value */ float []x,int xs, /* input : function to be interpolated */ int frac /* input : fraction value to evaluate */ ) { int i; float s; int x1, x2, c1, c2; if (frac < 0) { frac += LD8KConstants.UP_SAMP; xs--; } x1 = 0; x2 = 1; c1 = frac;//&inter_3[frac]; c2 = LD8KConstants.UP_SAMP-frac;//&inter_3[LD8KConstants.UP_SAMP-frac]; s = (float)0.0; for(i=0; i< LD8KConstants.L_INTER4; i++, c1+=LD8KConstants.UP_SAMP, c2+=LD8KConstants.UP_SAMP) s+= (x[xs+x1--]) * (TabLD8k.inter_3[c1]) + (x[xs+x2++]) * (TabLD8k.inter_3[c2]); return s; } /*---------------------------------------------------------------------------- * inv_sqrt - compute y = 1 / sqrt(x) *---------------------------------------------------------------------------- */ static float inv_sqrt( /* output: 1/sqrt(x) */ float x /* input : value of x */ ) { return ((float)1.0 / (float)Math.sqrt((double)x) ); } }