shithub: opus

Download patch

ref: ffa13474efdc59f0ddc095c7c5e389b37ec9c946
parent: 14bccef8e72559af928c8689fdae215e15184667
author: Jean-Marc Valin <[email protected]>
date: Mon Dec 10 11:54:17 EST 2007

Adding stereo support. Doesn't work yet, but at least it doesn't break
mono

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -41,7 +41,7 @@
 {
    int i, B;
    const int *eBands = m->eBands;
-   B = m->nbMdctBlocks;
+   B = m->nbMdctBlocks*m->nbChannels;
    for (i=0;i<m->nbEBands;i++)
    {
       int j;
@@ -57,7 +57,7 @@
 {
    int i, B;
    const int *eBands = m->eBands;
-   B = m->nbMdctBlocks;
+   B = m->nbMdctBlocks*m->nbChannels;
    for (i=0;i<m->nbEBands;i++)
    {
       int j;
@@ -74,7 +74,7 @@
 {
    int i, B;
    const int *eBands = m->eBands;
-   B = m->nbMdctBlocks;
+   B = m->nbMdctBlocks*m->nbChannels;
    for (i=0;i<m->nbEBands;i++)
    {
       int j;
@@ -93,7 +93,7 @@
    int i, B;
    const int *eBands = m->eBands;
    const int *pBands = m->pBands;
-   B = m->nbMdctBlocks;
+   B = m->nbMdctBlocks*m->nbChannels;
    float w[B*eBands[m->nbEBands]];
    for (i=0;i<m->nbEBands;i++)
    {
@@ -134,7 +134,7 @@
 {
    int i, B;
    const int *pBands = m->pBands;
-   B = m->nbMdctBlocks;
+   B = m->nbMdctBlocks*m->nbChannels;
    for (i=0;i<m->nbPBands;i++)
    {
       int j;
@@ -150,7 +150,7 @@
 {
    int i, j, B;
    const int *eBands = m->eBands;
-   B = m->nbMdctBlocks;
+   B = m->nbMdctBlocks*m->nbChannels;
    float norm[B*eBands[m->nbEBands+1]];
    
    for (i=0;i<m->nbEBands;i++)
@@ -180,7 +180,7 @@
 {
    int i, j, B;
    const int *eBands = m->eBands;
-   B = m->nbMdctBlocks;
+   B = m->nbMdctBlocks*m->nbChannels;
    float norm[B*eBands[m->nbEBands+1]];
    
    for (i=0;i<m->nbEBands;i++)
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -49,13 +49,14 @@
    int frame_size;
    int block_size;
    int nb_blocks;
-      
+   int channels;
+   
    ec_byte_buffer buf;
    ec_enc         enc;
 
    float preemph;
-   float preemph_memE;
-   float preemph_memD;
+   float *preemph_memE;
+   float *preemph_memD;
    
    mdct_lookup mdct_lookup;
    void *fft;
@@ -72,9 +73,10 @@
 
 CELTEncoder *celt_encoder_new(const CELTMode *mode)
 {
-   int i, N, B;
+   int i, N, B, C;
    N = mode->mdctSize;
    B = mode->nbMdctBlocks;
+   C = mode->nbChannels;
    CELTEncoder *st = celt_alloc(sizeof(CELTEncoder));
    
    st->mode = mode;
@@ -89,9 +91,9 @@
    st->fft = spx_fft_init(MAX_PERIOD);
    
    st->window = celt_alloc(2*N*sizeof(float));
-   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->in_mem = celt_alloc(N*C*sizeof(float));
+   st->mdct_overlap = celt_alloc(N*C*sizeof(float));
+   st->out_mem = celt_alloc(MAX_PERIOD*C*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));
    
@@ -98,6 +100,9 @@
    st->oldBandE = celt_alloc(mode->nbEBands*sizeof(float));
 
    st->preemph = 0.8;
+   st->preemph_memE = celt_alloc(C*sizeof(float));;
+   st->preemph_memD = celt_alloc(C*sizeof(float));;
+
    return st;
 }
 
@@ -148,83 +153,95 @@
    }
 }
 
-static void compute_mdcts(mdct_lookup *mdct_lookup, float *window, float *in, float *out, int N, int B)
+static void compute_mdcts(mdct_lookup *mdct_lookup, float *window, float *in, float *out, int N, int B, int C)
 {
-   int i;
-   for (i=0;i<B;i++)
+   int i, c;
+   for (c=0;c<C;c++)
    {
-      int j;
-      float x[2*N];
-      float tmp[N];
-      for (j=0;j<2*N;j++)
-         x[j] = window[j]*in[i*N+j];
-      mdct_forward(mdct_lookup, x, tmp);
-      /* Interleaving the sub-frames */
-      for (j=0;j<N;j++)
-         out[B*j+i] = tmp[j];
+      for (i=0;i<B;i++)
+      {
+         int j;
+         float x[2*N];
+         float tmp[N];
+         for (j=0;j<2*N;j++)
+            x[j] = window[j]*in[(B+1)*N*c+i*N+j];
+         mdct_forward(mdct_lookup, x, tmp);
+         /* Interleaving the sub-frames */
+         for (j=0;j<N;j++)
+            out[C*B*j+C*i+c] = tmp[j];
+      }
    }
-
 }
 
-static void compute_inv_mdcts(mdct_lookup *mdct_lookup, float *window, float *X, float *out_mem, float *mdct_overlap, int N, int B)
+static void compute_inv_mdcts(mdct_lookup *mdct_lookup, float *window, float *X, float *out_mem, float *mdct_overlap, int N, int B, int C)
 {
-   int i;
-   for (i=0;i<B;i++)
+   int i, c;
+   for (c=0;c<C;c++)
    {
-      int j;
-      float x[2*N];
-      float tmp[N];
-      /* De-interleaving the sub-frames */
-      for (j=0;j<N;j++)
-         tmp[j] = X[B*j+i];
-      mdct_backward(mdct_lookup, tmp, x);
-      for (j=0;j<2*N;j++)
-         x[j] = window[j]*x[j];
-      for (j=0;j<N;j++)
-         out_mem[MAX_PERIOD+(i-B)*N+j] = x[j]+mdct_overlap[j];
-      for (j=0;j<N;j++)
-         mdct_overlap[j] = x[N+j];
+      for (i=0;i<B;i++)
+      {
+         int j;
+         float x[2*N];
+         float tmp[N];
+         /* De-interleaving the sub-frames */
+         for (j=0;j<N;j++)
+            tmp[j] = X[C*B*j+C*i+c];
+         mdct_backward(mdct_lookup, tmp, x);
+         for (j=0;j<2*N;j++)
+            x[j] = window[j]*x[j];
+         for (j=0;j<N;j++)
+            out_mem[C*(MAX_PERIOD+(i-B)*N)+C*j+c] = x[j]+mdct_overlap[C*j+c];
+         for (j=0;j<N;j++)
+            mdct_overlap[C*j+c] = x[N+j];
+      }
    }
 }
 
 int celt_encode(CELTEncoder *st, short *pcm)
 {
-   int i, N, B;
+   int i, c, N, B, C;
    N = st->block_size;
    B = st->nb_blocks;
-   float in[(B+1)*N];
+   C = st->mode->nbChannels;
+   float in[(B+1)*C*N];
    
-   float X[B*N];         /**< Interleaved signal MDCTs */
-   float P[B*N];         /**< Interleaved pitch MDCTs*/
+   float X[B*C*N];         /**< Interleaved signal MDCTs */
+   float P[B*C*N];         /**< Interleaved pitch MDCTs*/
    float bandE[st->mode->nbEBands];
    float gains[st->mode->nbPBands];
    int pitch_index;
    
-   for (i=0;i<N;i++)
-      in[i] = st->in_mem[i];
-   for (;i<(B+1)*N;i++)
+   for (c=0;c<C;c++)
    {
-      float tmp = pcm[i-N];
-      in[i] = tmp - st->preemph*st->preemph_memE;
-      st->preemph_memE = tmp;
+      for (i=0;i<N;i++)
+         in[C*i+c] = st->in_mem[C*i+c];
+      for (;i<(B+1)*N;i++)
+      {
+         float tmp = pcm[C*(i-N)+c];
+         in[C*i+c] = tmp - st->preemph*st->preemph_memE[c];
+         st->preemph_memE[c] = tmp;
+      }
+      for (i=0;i<N;i++)
+         st->in_mem[C*i+c] = in[C*(B*N+i)+c];
    }
-   for (i=0;i<N;i++)
-      st->in_mem[i] = in[B*N+i];
-
+   //for (i=0;i<(B+1)*C*N;i++) printf ("%f(%d) ", in[i], i); printf ("\n");
    /* Compute MDCTs */
-   compute_mdcts(&st->mdct_lookup, st->window, in, X, N, B);
+   compute_mdcts(&st->mdct_lookup, st->window, in, X, N, B, C);
    
    /* Pitch analysis */
-   for (i=0;i<N;i++)
+   for (c=0;c<C;c++)
    {
-      in[i] *= st->window[i];
-      in[B*N+i] *= st->window[N+i];
+      for (i=0;i<N;i++)
+      {
+         in[C*i+c] *= st->window[i];
+         in[C*(B*N+i)+c] *= st->window[N+i];
+      }
    }
    find_spectral_pitch(st->fft, in, st->out_mem, MAX_PERIOD, (B+1)*N, &pitch_index);
    ec_enc_uint(&st->enc, pitch_index, MAX_PERIOD-(B+1)*N);
    
    /* Compute MDCTs of the pitch part */
-   compute_mdcts(&st->mdct_lookup, st->window, st->out_mem+pitch_index, P, N, B);
+   compute_mdcts(&st->mdct_lookup, st->window, st->out_mem+pitch_index*C, P, N, B, C);
    
    /*int j;
    for (j=0;j<B*N;j++)
@@ -255,7 +272,7 @@
 
    //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++)
+   for (i=0;i<B*C*N;i++)
       X[i] -= P[i];
 
    /*float sum=0;
@@ -280,18 +297,21 @@
 
    //inv_haar1(X, B*N);
 
-   CELT_MOVE(st->out_mem, st->out_mem+B*N, MAX_PERIOD-B*N);
+   CELT_MOVE(st->out_mem, st->out_mem+C*B*N, C*(MAX_PERIOD-B*N));
    /* Compute inverse MDCTs */
-   compute_inv_mdcts(&st->mdct_lookup, st->window, X, st->out_mem, st->mdct_overlap, N, B);
+   compute_inv_mdcts(&st->mdct_lookup, st->window, X, st->out_mem, st->mdct_overlap, N, B, C);
 
-   for (i=0;i<B;i++)
+   for (c=0;c<C;c++)
    {
-      int j;
-      for (j=0;j<N;j++)
+      for (i=0;i<B;i++)
       {
-         float tmp = st->out_mem[MAX_PERIOD+(i-B)*N+j] + st->preemph*st->preemph_memD;
-         st->preemph_memD = tmp;
-         pcm[i*N+j] = (short)floor(.5+tmp);
+         int j;
+         for (j=0;j<N;j++)
+         {
+            float tmp = st->out_mem[C*(MAX_PERIOD+(i-B)*N)+C*j+c] + st->preemph*st->preemph_memD[c];
+            st->preemph_memD[c] = tmp;
+            pcm[C*i*N+C*j+c] = (short)floor(.5+tmp);
+         }
       }
    }
    return 0;
@@ -331,7 +351,7 @@
    ec_enc         enc;
 
    float preemph;
-   float preemph_memD;
+   float *preemph_memD;
    
    mdct_lookup mdct_lookup;
    
@@ -346,9 +366,10 @@
 
 CELTDecoder *celt_decoder_new(const CELTMode *mode)
 {
-   int i, N, B;
+   int i, N, B, C;
    N = mode->mdctSize;
    B = mode->nbMdctBlocks;
+   C = mode->nbChannels;
    CELTDecoder *st = celt_alloc(sizeof(CELTDecoder));
    
    st->mode = mode;
@@ -359,8 +380,8 @@
    mdct_init(&st->mdct_lookup, 2*N);
    
    st->window = celt_alloc(2*N*sizeof(float));
-   st->mdct_overlap = celt_alloc(N*sizeof(float));
-   st->out_mem = celt_alloc(MAX_PERIOD*sizeof(float));
+   st->mdct_overlap = celt_alloc(N*C*sizeof(float));
+   st->out_mem = celt_alloc(MAX_PERIOD*C*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));
    
@@ -367,7 +388,8 @@
    st->oldBandE = celt_alloc(mode->nbEBands*sizeof(float));
 
    st->preemph = 0.8;
-   
+   st->preemph_memD = celt_alloc(C*sizeof(float));;
+
    st->last_pitch_index = 0;
    return st;
 }
@@ -392,43 +414,46 @@
 
 static void celt_decode_lost(CELTDecoder *st, short *pcm)
 {
-   int i, N, B;
+   int i, c, N, B, C;
    N = st->block_size;
    B = st->nb_blocks;
-   
-   float X[B*N];         /**< Interleaved signal MDCTs */
+   C = st->mode->nbChannels;
+   float X[C*B*N];         /**< Interleaved signal MDCTs */
    int pitch_index;
    
    pitch_index = st->last_pitch_index;
    
    /* Use the pitch MDCT as the "guessed" signal */
-   compute_mdcts(&st->mdct_lookup, st->window, st->out_mem+pitch_index, X, N, B);
+   compute_mdcts(&st->mdct_lookup, st->window, st->out_mem+pitch_index*C, X, N, B, C);
 
-   CELT_MOVE(st->out_mem, st->out_mem+B*N, MAX_PERIOD-B*N);
+   CELT_MOVE(st->out_mem, st->out_mem+C*B*N, C*(MAX_PERIOD-B*N));
    /* Compute inverse MDCTs */
-   compute_inv_mdcts(&st->mdct_lookup, st->window, X, st->out_mem, st->mdct_overlap, N, B);
+   compute_inv_mdcts(&st->mdct_lookup, st->window, X, st->out_mem, st->mdct_overlap, N, B, C);
 
-   for (i=0;i<B;i++)
+   for (c=0;c<C;c++)
    {
-      int j;
-      for (j=0;j<N;j++)
+      for (i=0;i<B;i++)
       {
-         float tmp = st->out_mem[MAX_PERIOD+(i-B)*N+j] + st->preemph*st->preemph_memD;
-         st->preemph_memD = tmp;
-         pcm[i*N+j] = (short)floor(.5+tmp);
+         int j;
+         for (j=0;j<N;j++)
+         {
+            float tmp = st->out_mem[C*(MAX_PERIOD+(i-B)*N)+C*j+c] + st->preemph*st->preemph_memD[c];
+            st->preemph_memD[c] = tmp;
+            pcm[C*i*N+C*j+c] = (short)floor(.5+tmp);
+         }
       }
    }
-
 }
 
 int celt_decode(CELTDecoder *st, char *data, int len, short *pcm)
 {
-   int i, N, B;
+   int i, c, N, B, C;
    N = st->block_size;
    B = st->nb_blocks;
+   C = st->mode->nbChannels;
    
-   float X[B*N];         /**< Interleaved signal MDCTs */
-   float P[B*N];         /**< Interleaved pitch MDCTs*/
+   float X[C*B*N];         /**< Interleaved signal MDCTs */
+   float P[C*B*N];         /**< Interleaved pitch MDCTs*/
    float bandE[st->mode->nbEBands];
    float gains[st->mode->nbPBands];
    int pitch_index;
@@ -452,7 +477,7 @@
    unquant_energy(st->mode, bandE, st->oldBandE, &dec);
    
    /* Pitch MDCT */
-   compute_mdcts(&st->mdct_lookup, st->window, st->out_mem+pitch_index, P, N, B);
+   compute_mdcts(&st->mdct_lookup, st->window, st->out_mem+pitch_index*C, P, N, B, C);
 
    //haar1(P, B*N);
 
@@ -476,17 +501,21 @@
 
    //inv_haar1(X, B*N);
 
-   CELT_MOVE(st->out_mem, st->out_mem+B*N, MAX_PERIOD-B*N);
+   CELT_MOVE(st->out_mem, st->out_mem+C*B*N, C*(MAX_PERIOD-B*N));
    /* Compute inverse MDCTs */
-   compute_inv_mdcts(&st->mdct_lookup, st->window, X, st->out_mem, st->mdct_overlap, N, B);
-   for (i=0;i<B;i++)
+   compute_inv_mdcts(&st->mdct_lookup, st->window, X, st->out_mem, st->mdct_overlap, N, B, C);
+
+   for (c=0;c<C;c++)
    {
-      int j;
-      for (j=0;j<N;j++)
+      for (i=0;i<B;i++)
       {
-         float tmp = st->out_mem[MAX_PERIOD+(i-B)*N+j] + st->preemph*st->preemph_memD;
-         st->preemph_memD = tmp;
-         pcm[i*N+j] = (short)floor(.5+tmp);
+         int j;
+         for (j=0;j<N;j++)
+         {
+            float tmp = st->out_mem[C*(MAX_PERIOD+(i-B)*N)+C*j+c] + st->preemph*st->preemph_memD[c];
+            st->preemph_memD[c] = tmp;
+            pcm[C*i*N+C*j+c] = (short)floor(.5+tmp);
+         }
       }
    }
    return 0;
--- a/libcelt/celt.h
+++ b/libcelt/celt.h
@@ -40,6 +40,7 @@
 extern const CELTMode const *celt_mode1;
 extern const CELTMode const *celt_mode2;
 extern const CELTMode const *celt_mode3;
+extern const CELTMode const *celt_mode4;
 
 /* Encoder stuff */
 
--- a/libcelt/modes.c
+++ b/libcelt/modes.c
@@ -51,6 +51,7 @@
    256,         /**< frameSize */
    128,         /**< mdctSize */
    2,           /**< nbMdctBlocks */
+   1,           /**< channels */
    
    NBANDS128,   /**< nbEBands */
    PBANDS128,   /**< nbPBands */
@@ -66,6 +67,7 @@
    256,         /**< frameSize */
    128,         /**< mdctSize */
    2,           /**< nbMdctBlocks */
+   1,           /**< channels */
    
    NBANDS128,   /**< nbEBands */
    PBANDS128,   /**< nbPBands */
@@ -76,11 +78,11 @@
    qpulses2     /**< nbPulses */
 };
 
-/* Approx 38 kbps @ 44.1 kHz */
 const CELTMode mode3 = {
    512,         /**< frameSize */
    256,         /**< mdctSize */
    2,           /**< nbMdctBlocks */
+   1,           /**< channels */
    
    NBANDS128,   /**< nbEBands */
    PBANDS128,   /**< nbPBands */
@@ -91,6 +93,22 @@
    qpulses2     /**< nbPulses */
 };
 
+const CELTMode mode4 = {
+   256,         /**< frameSize */
+   128,         /**< mdctSize */
+   2,           /**< nbMdctBlocks */
+   2,           /**< channels */
+   
+   NBANDS128,   /**< nbEBands */
+   PBANDS128,   /**< nbPBands */
+   PITCH_END128,/**< pitchEnd */
+   
+   qbank1,      /**< eBands */
+   pbank1,      /**< pBands*/
+   qpulses2     /**< nbPulses */
+};
+
 const CELTMode const *celt_mode1 = &mode1;
 const CELTMode const *celt_mode2 = &mode2;
 const CELTMode const *celt_mode3 = &mode3;
+const CELTMode const *celt_mode4 = &mode4;
--- a/libcelt/modes.h
+++ b/libcelt/modes.h
@@ -38,6 +38,7 @@
    int          frameSize;
    int          mdctSize;
    int          nbMdctBlocks;
+   int          nbChannels;
    
    int          nbEBands;
    int          nbPBands;
--- a/libcelt/testcelt.c
+++ b/libcelt/testcelt.c
@@ -35,7 +35,6 @@
 #include <stdlib.h>
 
 #define FRAME_SIZE 256
-#define NBLOCKS 2
 
 int main(int argc, char *argv[])
 {   
@@ -52,8 +51,8 @@
    outFile = argv[2];
    fout = fopen(outFile, "wb+");
    
-   enc = celt_encoder_new(celt_mode1);
-   dec = celt_decoder_new(celt_mode1);
+   enc = celt_encoder_new(celt_mode2);
+   dec = celt_decoder_new(celt_mode2);
    
    while (!feof(fin))
    {
@@ -61,11 +60,14 @@
       celt_encode(enc, in);
       data = celt_encoder_get_bytes(enc, &len);
       //printf ("%d\n", len);
+#if 1
+      /* this is to simulate packet loss */
       if (rand()%100==-1)
          celt_decode(dec, NULL, len, in);
       else
          celt_decode(dec, data, len, in);
       fwrite(in, sizeof(short), FRAME_SIZE, fout);
+#endif
    }
    //data = celt_encoder_get_bytes(enc, &len);
    //printf ("%d bytes total\n", len);