/* Copyright (C) 2002 Jean-Marc Valin File: ltp.c Lont-Term Prediction functions This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "ltp.h" #include "cb_search.h" #include "stack_alloc.h" #include "filters.h" #include "bits.h" #define abs(x) ((x)<0 ? -(x) : (x)) void open_loop_pitch(float *sw, int start, int end, int len, int *pitch, int *vuv) { int i; float e0, corr, energy, best_gain=0, pred_gain, best_corr=0, best_energy=0; float score, best_score=-1; e0=xcorr(sw, sw, len); energy=xcorr(sw-start, sw-start, len); for (i=start;i<=end;i++) { corr=xcorr(sw, sw-i, len); score=corr*corr/(energy+1); if (score>best_score) { if ((abs(i-2**pitch)>4 && abs(i-3**pitch)>6) || score>1.2*best_score) { best_score=score; best_gain=corr/(energy+1); best_corr=corr; best_energy=energy; *pitch=i; } } /* Update energy for next pitch*/ energy+=sw[-i-1]*sw[-i-1] - sw[-i+len]*sw[-i+len]; } pred_gain=e0/(1+fabs(e0+best_gain*best_gain*best_energy-2*best_gain*best_corr)); #ifdef DEBUG printf ("pred = %f\n", pred_gain); #endif *vuv=1; } void closed_loop_fractional_pitch( float target[], /* Target vector */ float ak[], /* LPCs for this subframe */ float awk1[], /* Weighted LPCs #1 for this subframe */ float awk2[], /* Weighted LPCs #2 for this subframe */ float exc[], /* Overlapping codebook */ float *filt, /* Over-sampling filter */ int filt_side, /* Over-sampling factor */ int fact, /* Over-sampling factor */ int start, /* Smallest pitch value allowed */ int end, /* Largest pitch value allowed */ float *gain, /* 3-tab gains of optimum entry */ int *pitch, /* Index of optimum entry */ int p, /* Number of LPC coeffs */ int nsf, /* Number of samples in subframe */ float *stack ) { int i, j, size, filt_size, base, frac=0, best_cor=0; float *oexc_mem, *oexc, *exc_ptr, *fexc, *f, frac_pitch=0, best_score=-1, best_gain=0; float sc; float corr[3]; float A[3][3]; #if 1 sc = overlap_cb_search(target, ak, awk1, awk2, &exc[-end], end-start+1, gain, pitch, p, nsf); *pitch=end-*pitch; #ifdef DEBUG printf ("ol score: %d %f\n", *pitch, sc); #endif #endif base=*pitch; exc_ptr=exc-*pitch; size = fact*nsf + filt_side*2 + 16*fact; filt_size = 2*filt_side+1; oexc_mem = PUSH(stack, size); oexc=oexc_mem+filt_side; fexc = PUSH(stack, size/fact); f=filt+filt_side; for(i=0;ibest_score) { best_cor = correction; *pitch = base+8-correction; frac = j; best_gain=*gain; frac_pitch = *pitch-(j/(float)fact); best_score=score; } #ifdef DEBUG printf ("corr: %d %d %f\n", correction, *pitch, score); #endif } /*for (i=0;i1.2) best_gain=1.2; if (best_gain<-.2) best_gain=-.2;*/ for (i=0;i=0;i--) exc[i]=gain[0]*exc[i-pitch+1]+gain[1]*exc[i-pitch]+gain[2]*exc[i-pitch-1]; #if 0 if (0){ float tmp1=0,tmp2=0; for (i=0;igain_cdbk; gain_cdbk_size=1<gain_bits; tmp = PUSH(stack, 3*nsf); x[0]=tmp; x[1]=tmp+nsf; x[2]=tmp+2*nsf; /* Perform closed-loop 1-tap search*/ overlap_cb_search(target, ak, awk1, awk2, &exc[-end], end-start+1, gain, &pitch, p, nsf); /* Real pitch value */ pitch=end-pitch; for (i=0;i<3;i++) { residue_zero(&exc[-pitch-1+i],awk1,x[i],nsf,p); syn_filt_zero(x[i],ak,x[i],nsf,p); syn_filt_zero(x[i],awk2,x[i],nsf,p); } for (i=0;i<3;i++) corr[i]=xcorr(x[i],target,nsf); for (i=0;i<3;i++) for (j=0;j<=i;j++) A[i][j]=A[j][i]=xcorr(x[i],x[j],nsf); { int j; float C[9]; float *ptr=gain_cdbk; int best_cdbk=0; float best_sum=0; C[0]=corr[2]; C[1]=corr[1]; C[2]=corr[0]; C[3]=A[1][2]; C[4]=A[0][1]; C[5]=A[0][2]; C[6]=A[2][2]; C[7]=A[1][1]; C[8]=A[0][0]; for (i=0;ibest_sum || i==0) { best_sum=sum; best_cdbk=i; } } gain[0] = gain_cdbk[best_cdbk*12]; gain[1] = gain_cdbk[best_cdbk*12+1]; gain[2] = gain_cdbk[best_cdbk*12+2]; frame_bits_pack(bits,pitch-start,params->pitch_bits); frame_bits_pack(bits,best_cdbk,params->gain_bits); } /*FIXME: backward or forward? (ie recursive or not?)*/ /*for (i=0;i=0;i--) exc[i]=gain[0]*exc[i-pitch+1]+gain[1]*exc[i-pitch]+gain[2]*exc[i-pitch-1]; #ifdef DEBUG printf ("3-tap pitch = %d, gains = [%f %f %f]\n",pitch, gain[0], gain[1], gain[2]); { float tmp1=0,tmp2=0; for (i=0;igain_cdbk; pitch = frame_bits_unpack_unsigned(bits, params->pitch_bits); pitch += start; gain_index = frame_bits_unpack_unsigned(bits, params->gain_bits); gain[0] = gain_cdbk[gain_index*12]; gain[1] = gain_cdbk[gain_index*12+1]; gain[2] = gain_cdbk[gain_index*12+2]; #ifdef DEBUG printf ("unquantized pitch: %d %f %f %f\n", pitch, gain[0], gain[1], gain[2]); #endif /*FIXME: backward or forward? (ie recursive or not?)*/ /*for(i=0;i=0;i--) { exc[i]=gain[0]*exc[i-pitch+1] + gain[1]*exc[i-pitch] + gain[2]*exc[i-pitch-1]; } }