ref: 00a98f5debf8ccd3ec64732f0c2592bb5cf42a2c
parent: f1916a14fdb81543a7a5dc59aca77f357f8522a8
author: Jean-Marc Valin <[email protected]>
date: Mon Jan 31 06:19:03 EST 2011
Making the stereo encoder capable of encoding in mono
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -96,6 +96,7 @@
const CELTMode *mode; /**< Mode used by the encoder */
int overlap;
int channels;
+ int stream_channels;
int force_intra;
int complexity;
@@ -216,7 +217,7 @@
st->mode = mode;
st->overlap = mode->overlap;
- st->channels = channels;
+ st->stream_channels = st->channels = channels;
st->upsample = 1;
st->start = 0;
@@ -870,7 +871,8 @@
int shortBlocks=0;
int isTransient=0;
int resynth;
- const int C = CHANNELS(st->channels);
+ const int CC = CHANNELS(st->channels);
+ const int C = CHANNELS(st->stream_channels);
int LM, M;
int tf_select;
int nbFilledBytes, nbAvailableBytes;
@@ -907,12 +909,12 @@
return CELT_BAD_ARG;
M=1<<LM;
- prefilter_mem = st->in_mem+C*(st->overlap);
- _overlap_mem = prefilter_mem+C*COMBFILTER_MAXPERIOD;
+ prefilter_mem = st->in_mem+CC*(st->overlap);
+ _overlap_mem = prefilter_mem+CC*COMBFILTER_MAXPERIOD;
/*_overlap_mem = st->in_mem+C*(st->overlap);*/
- oldBandE = (celt_word16*)(st->in_mem+C*(2*st->overlap+COMBFILTER_MAXPERIOD));
- oldLogE = oldBandE + C*st->mode->nbEBands;
- oldLogE2 = oldLogE + C*st->mode->nbEBands;
+ oldBandE = (celt_word16*)(st->in_mem+CC*(2*st->overlap+COMBFILTER_MAXPERIOD));
+ oldLogE = oldBandE + CC*st->mode->nbEBands;
+ oldLogE2 = oldLogE + CC*st->mode->nbEBands;
if (enc==NULL)
{
@@ -963,7 +965,7 @@
effEnd = st->mode->effEBands;
N = M*st->mode->shortMdctSize;
- ALLOC(in, C*(N+st->overlap), celt_sig);
+ ALLOC(in, CC*(N+st->overlap), celt_sig);
/* Find pitch period and gain */
{
@@ -971,7 +973,7 @@
celt_sig *pre[2];
SAVE_STACK;
c = 0;
- ALLOC(_pre, C*(N+COMBFILTER_MAXPERIOD), celt_sig);
+ ALLOC(_pre, CC*(N+COMBFILTER_MAXPERIOD), celt_sig);
pre[0] = _pre;
pre[1] = _pre + (N+COMBFILTER_MAXPERIOD);
@@ -990,7 +992,7 @@
if (++count==st->upsample)
{
count=0;
- pcmp+=C;
+ pcmp+=CC;
} else {
x = 0;
}
@@ -1004,7 +1006,7 @@
}
CELT_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD);
CELT_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+st->overlap)+st->overlap, N);
- } while (++c<C);
+ } while (++c<CC);
if (tell==1)
ec_enc_bit_logp(enc, silence, 15);
@@ -1031,7 +1033,7 @@
VARDECL(celt_word16, pitch_buf);
ALLOC(pitch_buf, (COMBFILTER_MAXPERIOD+N)>>1, celt_word16);
- pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, C);
+ pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, CC);
pitch_search(pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N,
COMBFILTER_MAXPERIOD-COMBFILTER_MINPERIOD, &pitch_index);
pitch_index = COMBFILTER_MAXPERIOD-pitch_index;
@@ -1120,7 +1122,7 @@
CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N);
}
#endif /* ENABLE_POSTFILTER */
- } while (++c<C);
+ } while (++c<CC);
RESTORE_STACK;
}
@@ -1137,7 +1139,7 @@
{
if (st->complexity > 1)
{
- isTransient = transient_analysis(in, N+st->overlap, C,
+ isTransient = transient_analysis(in, N+st->overlap, CC,
st->overlap);
if (isTransient)
shortBlocks = M;
@@ -1145,12 +1147,17 @@
ec_enc_bit_logp(enc, isTransient, 3);
}
- ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
- ALLOC(bandE,st->mode->nbEBands*C, celt_ener);
- ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16);
+ ALLOC(freq, CC*N, celt_sig); /**< Interleaved signal MDCTs */
+ ALLOC(bandE,st->mode->nbEBands*CC, celt_ener);
+ ALLOC(bandLogE,st->mode->nbEBands*CC, celt_word16);
/* Compute MDCTs */
- compute_mdcts(st->mode, shortBlocks, in, freq, C, LM);
+ compute_mdcts(st->mode, shortBlocks, in, freq, CC, LM);
+ if (CC==2&&C==1)
+ {
+ for (i=0;i<N;i++)
+ freq[i] = ADD32(HALF32(freq[i]), HALF32(freq[N+i]));
+ }
if (st->upsample != 1)
{
c=0; do
@@ -1454,7 +1461,7 @@
denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M);
CELT_MOVE(st->syn_mem[0], st->syn_mem[0]+N, MAX_PERIOD);
- if (C==2)
+ if (CC==2)
CELT_MOVE(st->syn_mem[1], st->syn_mem[1]+N, MAX_PERIOD);
c=0; do
@@ -1466,15 +1473,21 @@
freq[c*N+i] = 0;
while (++c<C);
+ if (CC==2&&C==1)
+ {
+ for (i=0;i<N;i++)
+ freq[N+i] = freq[i];
+ }
+
out_mem[0] = st->syn_mem[0]+MAX_PERIOD;
- if (C==2)
+ if (CC==2)
out_mem[1] = st->syn_mem[1]+MAX_PERIOD;
c=0; do
overlap_mem[c] = _overlap_mem + c*st->overlap;
- while (++c<C);
+ while (++c<CC);
- compute_inv_mdcts(st->mode, shortBlocks, freq, out_mem, overlap_mem, C, LM);
+ compute_inv_mdcts(st->mode, shortBlocks, freq, out_mem, overlap_mem, CC, LM);
#ifdef ENABLE_POSTFILTER
c=0; do {
@@ -1493,10 +1506,10 @@
st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset,
st->mode->window, st->mode->overlap);
}
- } while (++c<C);
+ } while (++c<CC);
#endif /* ENABLE_POSTFILTER */
- deemphasis(out_mem, (celt_word16*)pcm, N, C, st->upsample, st->mode->preemph, st->preemph_memD);
+ deemphasis(out_mem, (celt_word16*)pcm, N, CC, st->upsample, st->mode->preemph, st->preemph_memD);
st->prefilter_period_old = st->prefilter_period;
st->prefilter_gain_old = st->prefilter_gain;
st->prefilter_tapset_old = st->prefilter_tapset;
@@ -1507,6 +1520,11 @@
st->prefilter_gain = gain1;
st->prefilter_tapset = prefilter_tapset;
+ if (CC==2&&C==1) {
+ for (i=0;i<st->mode->nbEBands;i++)
+ oldBandE[st->mode->nbEBands+i]=oldBandE[i];
+ }
+
/* In case start or end were to change */
c=0; do
{
@@ -1514,15 +1532,15 @@
oldBandE[c*st->mode->nbEBands+i]=0;
for (i=st->end;i<st->mode->nbEBands;i++)
oldBandE[c*st->mode->nbEBands+i]=0;
- } while (++c<C);
+ } while (++c<CC);
if (!isTransient)
{
- for (i=0;i<C*st->mode->nbEBands;i++)
+ for (i=0;i<CC*st->mode->nbEBands;i++)
oldLogE2[i] = oldLogE[i];
- for (i=0;i<C*st->mode->nbEBands;i++)
+ for (i=0;i<CC*st->mode->nbEBands;i++)
oldLogE[i] = oldBandE[i];
} else {
- for (i=0;i<C*st->mode->nbEBands;i++)
+ for (i=0;i<CC*st->mode->nbEBands;i++)
oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]);
}
if (isTransient)
@@ -1694,6 +1712,14 @@
value = 3072000;
frame_rate = ((st->mode->Fs<<3)+(N>>1))/N;
st->vbr_rate_norm = value>0?IMAX(1,((value<<(BITRES+3))+(frame_rate>>1))/frame_rate):0;
+ }
+ break;
+ case CELT_SET_CHANNELS_REQUEST:
+ {
+ celt_int32 value = va_arg(ap, celt_int32);
+ if (value<1 || value>2)
+ goto bad_arg;
+ st->stream_channels = value;
}
break;
case CELT_RESET_STATE: