ref: 903dbf755852d556323de201443653ad915d1bac
parent: ab3784e99faeafc954d1011364c2161fb91ce640
author: Jean-Marc Valin <[email protected]>
date: Thu Aug 26 16:06:49 EDT 2010
Inverse MDCT no longer keeps channels interleaved. This simplifications also fixes a few bugs in the PLC (hope it didn't create some new ones).
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -97,7 +97,7 @@
celt_word32 preemph_memD[2];
celt_sig *in_mem;
- celt_sig *out_mem;
+ celt_sig *out_mem[2];
celt_word16 *oldBandE;
};
@@ -162,7 +162,9 @@
st->fold_decision = 1;
st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig));
- st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig));
+ st->out_mem[0] = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig));
+ if (C==2)
+ st->out_mem[1] = st->out_mem[0] + MAX_PERIOD+st->overlap;
st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
@@ -205,7 +207,7 @@
check_mode(st->mode);
celt_free(st->in_mem);
- celt_free(st->out_mem);
+ celt_free(st->out_mem[0]);
celt_free(st->oldBandE);
st->marker = ENCODERFREED;
@@ -331,7 +333,7 @@
/** Compute the IMDCT and apply window for all sub-frames and
all channels in a frame */
-static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig *X, int transient_time, int transient_shift, celt_sig * restrict out_mem, int _C, int LM)
+static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig *X, int transient_time, int transient_shift, celt_sig * restrict out_mem[], int _C, int LM)
{
int c, N4;
const int C = CHANNELS(_C);
@@ -342,7 +344,7 @@
{
int j;
if (transient_shift==0 && C==1 && !shortBlocks) {
- clt_mdct_backward(&mode->mdct, X, out_mem+C*(MAX_PERIOD-N-N4), mode->window, overlap, mode->maxLM-LM);
+ clt_mdct_backward(&mode->mdct, X, out_mem[0]+(MAX_PERIOD-N-N4), mode->window, overlap, mode->maxLM-LM);
} else {
VARDECL(celt_word32, x);
VARDECL(celt_word32, tmp);
@@ -390,15 +392,15 @@
/* The first and last part would need to be set to zero
if we actually wanted to use them. */
for (j=0;j<overlap;j++)
- out_mem[C*(MAX_PERIOD-N)+C*j+c] += x[j+N4];
+ out_mem[c][MAX_PERIOD-N+j] += x[j+N4];
for (;j<overlap+N;j++)
- out_mem[C*(MAX_PERIOD-N)+C*j+c] = x[j+N4];
+ out_mem[c][MAX_PERIOD-N+j] = x[j+N4];
RESTORE_STACK;
}
}
}
-static void deemphasis(celt_sig *in, celt_word16 *pcm, int N, int _C, const celt_word16 *coef, celt_sig *mem)
+static void deemphasis(celt_sig *in[], celt_word16 *pcm, int N, int _C, const celt_word16 *coef, celt_sig *mem)
{
const int C = CHANNELS(_C);
int c;
@@ -408,7 +410,7 @@
celt_sig * restrict x;
celt_word16 * restrict y;
celt_sig m = mem[c];
- x = &in[C*(MAX_PERIOD-N)+c];
+ x = &in[c][MAX_PERIOD-N];
y = pcm+c;
for (j=0;j<N;j++)
{
@@ -417,7 +419,7 @@
- MULT16_32_Q15(coef[1], *x);
tmp = SHL32(MULT16_32_Q15(coef[3], tmp), 2);
*y = SCALEOUT(SIG2WORD16(tmp));
- x+=C;
+ x++;
y+=C;
}
mem[c] = m;
@@ -940,7 +942,9 @@
/* Synthesis */
denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M);
- CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
+ CELT_MOVE(st->out_mem[0], st->out_mem[0]+N, MAX_PERIOD+st->overlap-N);
+ if (C==2)
+ CELT_MOVE(st->out_mem[1], st->out_mem[1]+N, MAX_PERIOD+st->overlap-N);
for (c=0;c<C;c++)
for (i=0;i<M*st->mode->eBands[st->start];i++)
@@ -1217,8 +1221,8 @@
celt_sig preemph_memD[2];
- celt_sig *out_mem;
- celt_word32 *decode_mem;
+ celt_sig *out_mem[2];
+ celt_word32 *decode_mem[2];
celt_word16 *oldBandE;
@@ -1282,9 +1286,12 @@
st->start = 0;
st->end = st->mode->effEBands;
- st->decode_mem = (celt_sig*)celt_alloc((DECODE_BUFFER_SIZE+st->overlap)*C*sizeof(celt_sig));
- st->out_mem = st->decode_mem+DECODE_BUFFER_SIZE-MAX_PERIOD;
-
+ st->decode_mem[0] = (celt_sig*)celt_alloc((DECODE_BUFFER_SIZE+st->overlap)*C*sizeof(celt_sig));
+ if (C==2)
+ st->decode_mem[1] = st->decode_mem[0] + (DECODE_BUFFER_SIZE+st->overlap);
+ st->out_mem[0] = st->decode_mem[0]+DECODE_BUFFER_SIZE-MAX_PERIOD;
+ if (C==2)
+ st->out_mem[1] = st->decode_mem[1]+DECODE_BUFFER_SIZE-MAX_PERIOD;
st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
st->lpc = (celt_word16*)celt_alloc(C*LPC_ORDER*sizeof(celt_word16));
@@ -1331,7 +1338,7 @@
the free functions in this order is a violation of the API.*/
check_mode(st->mode);
- celt_free(st->decode_mem);
+ celt_free(st->decode_mem[0]);
celt_free(st->oldBandE);
celt_free(st->lpc);
@@ -1389,7 +1396,7 @@
offset = MAX_PERIOD-pitch_index;
for (i=0;i<MAX_PERIOD;i++)
- exc[i] = ROUND16(st->out_mem[i*C+c], SIG_SHIFT);
+ exc[i] = ROUND16(st->out_mem[c][i], SIG_SHIFT);
if (st->loss_count == 0)
{
@@ -1444,7 +1451,7 @@
decay = MULT16_16_Q15(decay, decay);
}
e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT);
- S1 += SHR32(MULT16_16(st->out_mem[offset+i],st->out_mem[offset+i]),8);
+ S1 += SHR32(MULT16_16(st->out_mem[c][offset+i],st->out_mem[c][offset+i]),8);
}
iir(e, st->lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
@@ -1472,7 +1479,7 @@
}
for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
- st->out_mem[C*i+c] = st->out_mem[C*(N+i)+c];
+ st->out_mem[c][i] = st->out_mem[c][N+i];
/* Apply TDAC to the concealed audio so that it blends with the
previous and next frames */
@@ -1485,13 +1492,13 @@
MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]);
tmp1 = MULT16_32_Q15(fade, tmp1);
tmp2 = MULT16_32_Q15(fade, tmp2);
- st->out_mem[C*(MAX_PERIOD+i)+c] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp2);
- st->out_mem[C*(MAX_PERIOD+overlap-i-1)+c] = MULT16_32_Q15(st->mode->window[i], tmp2);
- st->out_mem[C*(MAX_PERIOD-N+i)+c] += MULT16_32_Q15(st->mode->window[i], tmp1);
- st->out_mem[C*(MAX_PERIOD-N+overlap-i-1)+c] -= MULT16_32_Q15(st->mode->window[overlap-i-1], tmp1);
+ st->out_mem[c][MAX_PERIOD+i] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp2);
+ st->out_mem[c][MAX_PERIOD+overlap-i-1] = MULT16_32_Q15(st->mode->window[i], tmp2);
+ st->out_mem[c][MAX_PERIOD-N+i] += MULT16_32_Q15(st->mode->window[i], tmp1);
+ st->out_mem[c][MAX_PERIOD-N+overlap-i-1] -= MULT16_32_Q15(st->mode->window[overlap-i-1], tmp1);
}
for (i=0;i<N-overlap;i++)
- st->out_mem[C*(MAX_PERIOD-N+overlap+i)+c] = MULT16_32_Q15(fade, e[overlap+i]);
+ st->out_mem[c][MAX_PERIOD-N+overlap+i] = MULT16_32_Q15(fade, e[overlap+i]);
}
deemphasis(st->out_mem, pcm, N, C, st->mode->preemph, st->preemph_memD);
@@ -1659,8 +1666,9 @@
/* Synthesis */
denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M);
-
- CELT_MOVE(st->decode_mem, st->decode_mem+C*N, C*(DECODE_BUFFER_SIZE+st->overlap-N));
+ CELT_MOVE(st->decode_mem[0], st->decode_mem[0]+N, DECODE_BUFFER_SIZE+st->overlap-N);
+ if (C==2)
+ CELT_MOVE(st->decode_mem[1], st->decode_mem[1]+N, DECODE_BUFFER_SIZE+st->overlap-N);
for (c=0;c<C;c++)
for (i=0;i<M*st->mode->eBands[st->start];i++)
--- a/libcelt/pitch.c
+++ b/libcelt/pitch.c
@@ -96,20 +96,20 @@
}
}
-void pitch_downsample(const celt_sig * restrict x, celt_word16 * restrict x_lp, int len, int end, int _C, celt_sig * restrict xmem, celt_word16 * restrict filt_mem)
+void pitch_downsample(celt_sig * restrict x[], celt_word16 * restrict x_lp, int len, int end, int _C, celt_sig * restrict xmem, celt_word16 * restrict filt_mem)
{
int i;
const int C = CHANNELS(_C);
for (i=1;i<len>>1;i++)
- x_lp[i] = SHR32(HALF32(HALF32(x[(2*i-1)*C]+x[(2*i+1)*C])+x[2*i*C]), SIG_SHIFT);
- x_lp[0] = SHR32(HALF32(HALF32(*xmem+x[C])+x[0]), SIG_SHIFT);
- *xmem = x[end-C];
+ x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), SIG_SHIFT);
+ x_lp[0] = SHR32(HALF32(HALF32(*xmem+x[0][1])+x[0][0]), SIG_SHIFT);
+ *xmem = x[0][end-1];
if (C==2)
{
for (i=1;i<len>>1;i++)
- x_lp[i] = SHR32(HALF32(HALF32(x[(2*i-1)*C+1]+x[(2*i+1)*C+1])+x[2*i*C+1]), SIG_SHIFT);
- x_lp[0] += SHR32(HALF32(HALF32(x[C+1])+x[1]), SIG_SHIFT);
- *xmem += x[end-C+1];
+ x_lp[i] = SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), SIG_SHIFT);
+ x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), SIG_SHIFT);
+ *xmem += x[1][end-1];
}
}
--- a/libcelt/pitch.h
+++ b/libcelt/pitch.h
@@ -41,7 +41,7 @@
#include "modes.h"
-void pitch_downsample(const celt_sig * restrict x, celt_word16 * restrict x_lp, int len, int end, int _C, celt_sig * restrict xmem, celt_word16 * restrict filt_mem);
+void pitch_downsample(celt_sig * restrict x[], celt_word16 * restrict x_lp, int len, int end, int _C, celt_sig * restrict xmem, celt_word16 * restrict filt_mem);
void pitch_search(const CELTMode *m, const celt_word16 * restrict x_lp, celt_word16 * restrict y, int len, int max_pitch, int *pitch, celt_sig *xmem, int M);