fixed-point: converted PLC filters and LPC parameters
authorJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Fri, 1 Jan 2010 14:33:17 +0000 (09:33 -0500)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Fri, 1 Jan 2010 14:33:17 +0000 (09:33 -0500)
libcelt/celt.c
libcelt/plc.c

index 527e323..3f2409b 100644 (file)
@@ -1097,7 +1097,7 @@ struct CELTDecoder {
    celt_word16 *oldBandE;
    
 #ifdef NEW_PLC
-   float *lpc;
+   celt_word16 *lpc;
 #endif
 
    int last_pitch_index;
@@ -1175,7 +1175,7 @@ CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
    st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
 
 #ifdef NEW_PLC
-   st->lpc = (float*)celt_alloc(C*LPC_ORDER*sizeof(float));
+   st->lpc = (celt_word16*)celt_alloc(C*LPC_ORDER*sizeof(celt_word16));
 #endif
 
    st->loss_count = 0;
@@ -1291,11 +1291,11 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
       float ac[LPC_ORDER+1];
       float decay = 1;
       float S1=0;
-      float mem[LPC_ORDER]={0};
+      celt_word16 mem[LPC_ORDER]={0};
 
       offset = MAX_PERIOD-pitch_index;
       for (i=0;i<MAX_PERIOD;i++)
-         exc[i] = SHR32(st->out_mem[i*C+c], SIG_SHIFT);
+         exc[i] = ROUND16(st->out_mem[i*C+c], SIG_SHIFT);
 
       if (st->loss_count == 0)
       {
@@ -1311,10 +1311,10 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
             ac[i] -= ac[i]*(.008*i)*(.008*i);
          }
 
-         _celt_lpc(st->lpc, ac, LPC_ORDER);
+         _celt_lpc(st->lpc+c*LPC_ORDER, ac, LPC_ORDER);
       }
-      fir(exc, st->lpc, exc, MAX_PERIOD, LPC_ORDER, mem);
-
+      fir(exc, st->lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
+      /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
       /* Check if the waveform is decaying (and if so how fast) */
       {
          float E1=0, E2=0;
@@ -1345,7 +1345,7 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
          S1 += st->out_mem[offset+i]*1.*st->out_mem[offset+i];
       }
 
-      iir(e, st->lpc, e, len+st->mode->overlap, LPC_ORDER, mem);
+      iir(e, st->lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
 
       {
          float S2=0;
index 8d6d9a5..41d0bf7 100644 (file)
@@ -4,7 +4,7 @@
 #endif
 
 float _celt_lpc(
-      float       *lpc, /* out: [0...p-1] LPC coefficients      */
+      celt_word16       *_lpc, /* out: [0...p-1] LPC coefficients      */
 const float *ac,  /* in:  [0...p] autocorrelation values  */
 int          p
 )
@@ -12,6 +12,11 @@ int          p
    int i, j;  
    float r;
    float error = ac[0];
+#ifdef FIXED_POINT
+   float lpc[LPC_ORDER];
+#else
+   float *lpc = _lpc;
+#endif
 
    if (ac[0] == 0)
    {
@@ -44,56 +49,56 @@ int          p
    }
 #ifdef FIXED_POINT
    for (i=0;i<p;i++)
-      lpc[i] = (1./4096)*floor(.5+4096*lpc[i]);
+      _lpc[i] = floor(.5+4096*lpc[i]);
 #endif
    return error;
 }
 
 void fir(const celt_word16 *x,
-         const float *num,
+         const celt_word16 *num,
          celt_word16 *y,
          int N,
          int ord,
-         float *mem)
+         celt_word16 *mem)
 {
    int i,j;
 
    for (i=0;i<N;i++)
    {
-      float sum = x[i];
+      celt_word32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
       for (j=0;j<ord;j++)
       {
-         sum += num[j]*mem[j];
+         sum += MULT16_16(num[j],mem[j]);
       }
       for (j=ord-1;j>=1;j--)
       {
          mem[j]=mem[j-1];
       }
       mem[0] = x[i];
-      y[i] = sum;
+      y[i] = ROUND16(sum, SIG_SHIFT);
    }
 }
 
 void iir(const celt_word32 *x,
-         const float *den,
+         const celt_word16 *den,
          celt_word32 *y,
          int N,
          int ord,
-         float *mem)
+         celt_word16 *mem)
 {
    int i,j;
    for (i=0;i<N;i++)
    {
-      float sum = x[i];
+      celt_word32 sum = x[i];
       for (j=0;j<ord;j++)
       {
-         sum -= den[j]*mem[j];
+         sum -= MULT16_16(den[j],mem[j]);
       }
       for (j=ord-1;j>=1;j--)
       {
          mem[j]=mem[j-1];
       }
-      mem[0] = sum;
+      mem[0] = ROUND16(sum,SIG_SHIFT);
       y[i] = sum;
    }
 }