3-tap pitch predictor seems to work
authorjmvalin <jmvalin@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Sat, 16 Feb 2002 06:02:17 +0000 (06:02 +0000)
committerjmvalin <jmvalin@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Sat, 16 Feb 2002 06:02:17 +0000 (06:02 +0000)
git-svn-id: http://svn.xiph.org/trunk/speex@3060 0101bb08-14d6-0310-b084-bc0e0c8e3800

libspeex/ltp.c
libspeex/ltp.h
libspeex/speex.c

index 6ffa174..ee61ec2 100644 (file)
@@ -4,10 +4,7 @@
 */
 
 
-/*static float lp4[] = {0.00139, 0.00853, 0.01465, -0.00000, -0.04766, -0.10610, -0.11333, 0.00000, 0.25616, 0.59397, 0.88498, 1.00000, 0.88498, 0.59397, 0.25616,  0.00000, -0.11333, -0.10610, -0.04766, -0.00000, 0.01465, 0.00853, 0.00139};
- */
-
-
+#define abs(x) ((x)<0 ? -(x) : (x))
 /* Computes the open-loop pitch prediction. Returns pitch period and pitch gain */
 int open_loop_ltp(float *x, int len, int start, int end, float *gain)
    /*  x:     time-domain signal (note, x[-end] must be valid)
@@ -40,8 +37,8 @@ int open_loop_ltp(float *x, int len, int start, int end, float *gain)
    return best_period;
 }
 
-
-int three_tap_ltp(float *x, int len, int start, int end, float *gain)
+/* Computes a three-tap pitch predictor */
+int three_tap_ltp(float *x, int len, int start, int end, float gain[3])
 
    /*  x:     time-domain signal (note, x[-end] must be valid)
        len:   length of the x signal
@@ -52,7 +49,7 @@ int three_tap_ltp(float *x, int len, int start, int end, float *gain)
 {
    int i, period, best_period=0;
    float total, score[3]={0,0,0}, best_score=-1, corr[3]={0,0,0}, energy[3]={0,0,0};
-   float best_energy[3], best_corr[3];
+   float best_energy[3], best_corr[3], best_gain=0;
    float A[3][3];
    for (period = start; period <= end; period++)
    {
@@ -73,29 +70,77 @@ int three_tap_ltp(float *x, int len, int start, int end, float *gain)
             best_corr[i]=corr[i];
             best_energy[i]=energy[i];
          }
-         *gain = corr[1]/(energy[1]+1);
+         best_gain = corr[1]/(energy[1]+1);
       }
+      score[2]=score[1];
+      score[1]=score[0];
       corr[2]=corr[1];
       corr[1]=corr[0];
       energy[2]=energy[1];
       energy[1]=energy[0];
    }
-   A[0][0]=energy[0];
-   A[1][1]=energy[1];
-   A[2][2]=energy[2];
+   A[0][0]=best_energy[0]+1;
+   A[1][1]=best_energy[1]+1;
+   A[2][2]=best_energy[2]+1;
    A[0][1]=0;
    A[0][2]=0;
    for (i=0;i<len;i++)
    {
-      A[0][1] += x[i-best_period]*x[i-best_period-1];
-      A[0][2] += x[i-best_period]*x[i-best_period-2];
+      A[0][1] += x[i-best_period+1]*x[i-best_period];
+      A[0][2] += x[i-best_period+2]*x[i-best_period];
    }
    A[1][0]=A[0][1];
    A[2][0]=A[0][2];
-   A[1][2]=A[0][1] - x[-best_period]*x[-best_period-1
-                   + x[len-best_period]*x[len-best_period-1];
+   A[1][2]=A[0][1] - x[-best_period+1]*x[-best_period
+                   + x[len-best_period]*x[len-best_period+1];
    A[2][1]=A[1][2];
-   return best_period-1;
+   /*for (i=0;i<3;i++)
+      printf ("%f %f %f\n", A[i][0], A[i][1], A[i][2]);
+      printf ("\n%f %f %f\n", best_corr[0], best_corr[1], best_corr[2]);*/
+   {
+      float tmp=A[1][0]/A[0][0];
+      for (i=0;i<3;i++)
+         A[1][i] -= tmp*A[0][i];
+      best_corr[1] -= tmp*best_corr[0];
+
+      tmp=A[2][0]/A[0][0];
+      for (i=0;i<3;i++)
+         A[2][i] -= tmp*A[0][i];
+      best_corr[2] -= tmp*best_corr[0];
+      
+      tmp=A[2][1]/A[1][1];
+      A[2][2] -= tmp*A[1][2];
+      best_corr[2] -= tmp*best_corr[1];
+
+      best_corr[2] /= A[2][2];
+      best_corr[1] = (best_corr[1] - A[1][2]*best_corr[2])/A[1][1];
+      best_corr[0] = (best_corr[0] - A[0][2]*best_corr[2] - A[0][1]*best_corr[1])/A[0][0];
+      /*printf ("\n%f %f %f\n", best_corr[0], best_corr[1], best_corr[2]);*/
+
+   }
+   gain[0]=best_corr[2];gain[1]=best_corr[1];gain[2]=best_corr[0];
+   
+   if (!((abs(gain[0]) + abs(gain[1]) + abs(gain[2])<2) 
+         && abs(gain[0]+gain[1]+gain[2]) < 1.2 
+         && abs(gain[0]+gain[1]+gain[2]) > -.2 ))
+   {
+      gain[0]=0;gain[1]=best_gain;gain[2]=0;
+      if (best_gain > 1.2)
+         gain[1]=1.2;
+      else if (best_gain<-.2)
+         gain[1]=-.2;
+      else 
+         gain[1]=best_gain;
+   }
+   return best_period-2;
 }
 
 
+void predictor_three_tap(float *x, int len, int period, float *gain)
+{
+   int i;
+   for (i=0;i<len;i++)
+   {
+      x[i] -= gain[0]*x[i-period] + gain[1]*x[i-period-1] + gain[2]*x[i-period-2];
+   }
+}
index 4007388..69a0084 100644 (file)
@@ -4,3 +4,5 @@
 */
 
 int open_loop_ltp(float *x, int len, int start, int end, float *gain);
+
+int three_tap_ltp(float *x, int len, int start, int end, float gain[3]);
index 8f6f340..c78a339 100644 (file)
@@ -118,7 +118,7 @@ void encode(EncState *st, float *in, int *outSize, void *bits)
 
    for (sub=0;sub<st->nbSubframes;sub++)
    {
-      float tmp, gain;
+      float tmp, gain[3];
       int pitch, offset;
 
       offset = st->subframeSize*sub;
@@ -157,8 +157,11 @@ void encode(EncState *st, float *in, int *outSize, void *bits)
       }
 
       /* Find pitch gain and delay */
-      pitch = open_loop_ltp(st->wframe+offset, st->subframeSize, 20, 120, &gain);
-      printf ("pitch = %d, gain = %f\n",pitch,gain);
+      pitch = three_tap_ltp(st->wframe+offset, st->subframeSize, 20, 120, gain);
+      /*pitch = open_loop_ltp(st->wframe+offset, st->subframeSize, 20, 120, gain);*/
+      
+      /*printf ("pitch = %d, gain = %f\n",pitch,gain);*/
+      printf ("pitch = %d, gain = %f %f %f\n",pitch,gain[0], gain[1], gain[2]);
    }
 
    printf ("\n");