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);