Some pitch prediction work.
authorJean-Marc Valin <Jean-Marc.Valin@csiro.au>
Fri, 30 Nov 2007 05:57:43 +0000 (16:57 +1100)
committerJean-Marc Valin <Jean-Marc.Valin@csiro.au>
Fri, 30 Nov 2007 05:57:43 +0000 (16:57 +1100)
libcelt/bands.c
libcelt/bands.h
libcelt/celt.c

index 30021a6..6fbcf54 100644 (file)
 #include "bands.h"
 
 const int qbank[NBANDS+2] =   {0, 2, 4, 6, 8, 12, 16, 20, 24, 28, 36, 44, 52, 68, 84, 116, 128};
+int qpulses[] = {4, 5, 4, 4, 3,  3,  3,  3,  3,  4,  4,  4,  0,  0,  0}; //c: 134 bits
+#define WAVEFORM_END 52
 
+/* Start frequency of each band */
+int pbank[] = {0, 4, 8, 12, 20, WAVEFORM_END, 128};
 
 /* Compute the energy in each of the bands */
 void compute_bands(float *X, int B, float *bank)
@@ -56,7 +60,7 @@ void normalise_bands(float *X, int B, float *bank)
    for (i=0;i<NBANDS;i++)
    {
       int j;
-      float x = 1.f/bank[i];
+      float x = 1.f/(1e-10+bank[i]);
       for (j=B*qbank[i];j<B*qbank[i+1];j++)
          X[j] *= x;
    }
@@ -80,6 +84,61 @@ void denormalise_bands(float *X, int B, float *bank)
 }
 
 
+/* Compute the best gain for each "pitch band" */
+void compute_pitch_gain(float *X, int B, float *P, float *gains, float *bank)
+{
+   int i;
+   float w[B*qbank[NBANDS]];
+   for (i=0;i<NBANDS;i++)
+   {
+      int j;
+      for (j=B*qbank[i];j<B*qbank[i+1];j++)
+         w[j] = bank[i];
+   }
+
+   
+   for (i=0;i<PBANDS;i++)
+   {
+      float Sxy=0;
+      float Sxx = 0;
+      int j;
+      float gain;
+      for (j=B*pbank[i];j<B*pbank[i+1];j++)
+      {
+         Sxy += X[j]*P[j]*w[j];
+         Sxx += X[j]*X[j]*w[j];
+      }
+      gain = Sxy/(1e-10+Sxx);
+      //gain = Sxy/(2*(pbank[i+1]-pbank[i]));
+      //if (i<3)
+      //gain *= 1+.02*gain;
+      if (gain > .90)
+         gain = .90;
+      if (gain < 0.0)
+         gain = 0.0;
+      
+      gains[i] = gain;
+   }
+   for (i=B*pbank[PBANDS];i<B*pbank[PBANDS+1];i++)
+      P[i] = 0;
+}
+
+/* Apply the (quantised) gain to each "pitch band" */
+void pitch_quant_bands(float *X, int B, float *P, float *gains)
+{
+   int i;
+   for (i=0;i<PBANDS;i++)
+   {
+      int j;
+      for (j=B*pbank[i];j<B*pbank[i+1];j++)
+         P[j] *= gains[i];
+      //printf ("%f ", gain);
+   }
+   for (i=B*pbank[PBANDS];i<B*pbank[PBANDS+1];i++)
+      P[i] = 0;
+}
+
+
 /* Scales the pulse-codebook entry in each band such that unit-energy is conserved when 
    adding the pitch */
 void pitch_renormalise_bands(float *X, int B, float *P)
@@ -105,7 +164,7 @@ void pitch_renormalise_bands(float *X, int B, float *P)
       Rxx = 0;
       for (j=B*qbank[i];j<B*qbank[i+1];j++)
       {
-         X[j*2-1] = P[j]+gain1*X[j];
+         X[j] = P[j]+gain1*X[j];
          Rxx += X[j]*X[j];
       }
    }
index 244e69f..8b09297 100644 (file)
 #ifndef BANDS_H
 #define BANDS_H
 
+/* Number of constant-energy bands */
 #define NBANDS 15
+/* Number of bands only for the pitch prediction */
+#define PBANDS 5
 
 void compute_bands(float *X, int B, float *bands);
 
@@ -40,6 +43,10 @@ void normalise_bands(float *X, int B, float *bands);
 
 void denormalise_bands(float *X, int B, float *bands);
 
+void compute_pitch_gain(float *X, int B, float *P, float *gains, float *bank);
+
+void pitch_quant_bands(float *X, int B, float *P, float *gains);
+
 void pitch_renormalise_bands(float *X, int B, float *P);
 
 #endif /* BANDS_H */
index 46bb955..1542273 100644 (file)
@@ -55,8 +55,6 @@ struct CELTState_ {
    float *mdct_overlap;
    float *out_mem;
 
-   float *bandE;
-
 };
 
 
@@ -78,7 +76,6 @@ CELTState *celt_encoder_new(int blockSize, int blocksPerFrame)
    st->in_mem = celt_alloc(N*sizeof(float));
    st->mdct_overlap = celt_alloc(N*sizeof(float));
    st->out_mem = celt_alloc(MAX_PERIOD*sizeof(float));
-   st->bandE = celt_alloc(NBANDS*sizeof(float));
    for (i=0;i<N;i++)
       st->window[i] = st->window[2*N-i-1] = sin(.5*M_PI* sin(.5*M_PI*(i+.5)/N) * sin(.5*M_PI*(i+.5)/N));
    return st;
@@ -99,8 +96,6 @@ void celt_encoder_destroy(CELTState *st)
    celt_free(st->mdct_overlap);
    celt_free(st->out_mem);
    
-   celt_free(st->bandE);
-
    celt_free(st);
 }
 
@@ -131,6 +126,9 @@ int celt_encode(CELTState *st, short *pcm)
    
    float X[B*N]; /**< Interleaved signal MDCTs */
    float P[B*N]; /**< Interleaved pitch MDCTs*/
+   float bandEp[NBANDS];
+   float bandE[NBANDS];
+   float gains[PBANDS];
    int pitch_index;
    
    /* FIXME: Add preemphasis */
@@ -164,18 +162,34 @@ int celt_encode(CELTState *st, short *pcm)
    printf ("\n");*/
    
    /* Band normalisation */
-   compute_bands(X, B, st->bandE);
-   normalise_bands(X, B, st->bandE);
+   compute_bands(X, B, bandE);
+   //for (i=0;i<NBANDS;i++) printf("%f ",bandE[i]);printf("\n"); 
+   normalise_bands(X, B, bandE);
    
-   compute_bands(P, B, st->bandE);
-   normalise_bands(P, B, st->bandE);
+   compute_bands(P, B, bandEp);
+   normalise_bands(P, B, bandEp);
 
    /* Pitch prediction */
+   compute_pitch_gain(X, B, P, gains, bandE);
+   //quantise_pitch(gains, PBANDS);
+   pitch_quant_bands(X, B, P, gains);
+   
+   for (i=0;i<B*N;i++) printf("%f ",P[i]);printf("\n");
+   /* Subtract the pitch prediction from the signal to encode */
+   for (i=0;i<B*N;i++)
+      X[i] -= P[i];
 
    /* Residual quantisation */
+   if (1) {
+      float tmpE[NBANDS];
+      compute_bands(X, B, tmpE);
+      normalise_bands(X, B, tmpE);
+      pitch_renormalise_bands(X, B, P);
+   }
+   //quant_bands(X, P);
    
    /* Synthesis */
-   denormalise_bands(X, B, st->bandE);
+   denormalise_bands(X, B, bandE);
 
    CELT_MOVE(st->out_mem, st->out_mem+B*N, MAX_PERIOD-B*N);
    /* Compute inverse MDCTs */