Newer
Older
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2010 Xiph.Org Foundation
Copyright (c) 2008 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define CELT_DECODER_C
#include "cpu_support.h"
#include "os_support.h"
#include "mdct.h"
#include <math.h>
#include "celt.h"
#include "pitch.h"
#include "bands.h"
#include "modes.h"
#include "entcode.h"
#include "quant_bands.h"
#include "rate.h"
#include "stack_alloc.h"
#include "mathops.h"
#include "float_cast.h"
#include <stdarg.h>
#include "celt_lpc.h"
#include "vq.h"
#if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT)
#define NORM_ALIASING_HACK
#endif
/**********************************************************************/
/* */
/* DECODER */
/* */
/**********************************************************************/
#define DECODE_BUFFER_SIZE 2048
/** Decoder state
@brief Decoder state
*/
struct OpusCustomDecoder {
const OpusCustomMode *mode;
int overlap;
int channels;
int stream_channels;
int downsample;
int start, end;
int signalling;
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* Everything beyond this point gets cleared on a reset */
#define DECODER_RESET_START rng
opus_uint32 rng;
int error;
int last_pitch_index;
int loss_count;
int postfilter_period;
int postfilter_period_old;
opus_val16 postfilter_gain;
opus_val16 postfilter_gain_old;
int postfilter_tapset;
int postfilter_tapset_old;
celt_sig preemph_memD[2];
celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
/* opus_val16 lpc[], Size = channels*LPC_ORDER */
/* opus_val16 oldEBands[], Size = 2*mode->nbEBands */
/* opus_val16 oldLogE[], Size = 2*mode->nbEBands */
/* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */
/* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */
};
int celt_decoder_get_size(int channels)
{
const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
return opus_custom_decoder_get_size(mode, channels);
}
OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels)
{
int size = sizeof(struct CELTDecoder)
+ (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
+ channels*LPC_ORDER*sizeof(opus_val16)
+ 4*2*mode->nbEBands*sizeof(opus_val16);
return size;
}
#ifdef CUSTOM_MODES
CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error)
{
int ret;
CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels));
ret = opus_custom_decoder_init(st, mode, channels);
if (ret != OPUS_OK)
{
opus_custom_decoder_destroy(st);
st = NULL;
}
if (error)
*error = ret;
return st;
}
#endif /* CUSTOM_MODES */
int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels)
{
int ret;
ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
if (ret != OPUS_OK)
return ret;
st->downsample = resampling_factor(sampling_rate);
if (st->downsample==0)
return OPUS_BAD_ARG;
else
return OPUS_OK;
}
OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels)
{
if (channels < 0 || channels > 2)
return OPUS_BAD_ARG;
if (st==NULL)
return OPUS_ALLOC_FAIL;
OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels));
st->mode = mode;
st->overlap = mode->overlap;
st->stream_channels = st->channels = channels;
st->downsample = 1;
st->start = 0;
st->end = st->mode->effEBands;
st->signalling = 1;
st->arch = opus_select_arch();
st->loss_count = 0;
opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
return OPUS_OK;
}
#ifdef CUSTOM_MODES
void opus_custom_decoder_destroy(CELTDecoder *st)
{
opus_free(st);
}
#endif /* CUSTOM_MODES */
#ifndef RESYNTH
static
#endif

Jean-Marc Valin
committed
void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef,

Jean-Marc Valin
committed
celt_sig *mem, int accum)
int apply_downsampling=0;
opus_val16 coef0;

Jean-Marc Valin
committed
VARDECL(celt_sig, scratch);
SAVE_STACK;

Jean-Marc Valin
committed
#ifndef FIXED_POINT
(void)accum;
celt_assert(accum==0);
#endif

Jean-Marc Valin
committed
ALLOC(scratch, N, celt_sig);
coef0 = coef[0];
Nd = N/downsample;
c=0; do {
int j;
celt_sig * OPUS_RESTRICT x;
opus_val16 * OPUS_RESTRICT y;
celt_sig m = mem[c];
x =in[c];
y = pcm+c;
#ifdef CUSTOM_MODES
if (coef[1] != 0)
opus_val16 coef1 = coef[1];
opus_val16 coef3 = coef[3];
m = MULT16_32_Q15(coef0, tmp)
- MULT16_32_Q15(coef1, x[j]);
tmp = SHL32(MULT16_32_Q15(coef3, tmp), 2);
apply_downsampling=1;
} else
{
/* Shortcut for the standard (non-custom modes) case */
m = MULT16_32_Q15(coef0, tmp);
apply_downsampling=1;
} else {
/* Shortcut for the standard (non-custom modes) case */

Jean-Marc Valin
committed
#ifdef FIXED_POINT
if (accum)

Jean-Marc Valin
committed
for (j=0;j<N;j++)
{
celt_sig tmp = x[j] + m + VERY_SMALL;
m = MULT16_32_Q15(coef0, tmp);
y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp))));
}
} else
#endif
{
for (j=0;j<N;j++)
{
celt_sig tmp = x[j] + m + VERY_SMALL;
m = MULT16_32_Q15(coef0, tmp);
y[j*C] = SCALEOUT(SIG2WORD16(tmp));
}
if (apply_downsampling)
{
/* Perform down-sampling */

Jean-Marc Valin
committed
#ifdef FIXED_POINT
if (accum)
{
for (j=0;j<Nd;j++)
y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(scratch[j*downsample]))));
} else
#endif
{
for (j=0;j<Nd;j++)
y[j*C] = SCALEOUT(SIG2WORD16(scratch[j*downsample]));
}

Jean-Marc Valin
committed
RESTORE_STACK;

Jean-Marc Valin
committed
#ifndef RESYNTH
static
#endif
void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
opus_val16 *oldBandE, int start, int effEnd, int C, int CC,
int isTransient, int LM, int downsample,
int silence, int arch)

Jean-Marc Valin
committed
{
int c, i;
int M;
int b;
int B;
int N, NB;
int shift;

Jean-Marc Valin
committed
int nbEBands;
int overlap;
VARDECL(celt_sig, freq);
SAVE_STACK;
overlap = mode->overlap;
nbEBands = mode->nbEBands;
N = mode->shortMdctSize<<LM;
ALLOC(freq, N, celt_sig); /**< Interleaved signal MDCTs */
M = 1<<LM;
if (isTransient)
{
B = M;
NB = mode->shortMdctSize;
shift = mode->maxLM;
} else {
B = 1;
NB = mode->shortMdctSize<<LM;
shift = mode->maxLM-LM;
}

Jean-Marc Valin
committed
if (CC==2&&C==1)
{
/* Copying a mono streams to two channels */
celt_sig *freq2;
denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
downsample, silence);
/* Store a temporary copy in the output buffer because the IMDCT destroys its input. */
freq2 = out_syn[1]+overlap/2;
OPUS_COPY(freq2, freq, N);
for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq2[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq[b], out_syn[1]+NB*b, mode->window, overlap, shift, B, arch);

Jean-Marc Valin
committed
} else if (CC==1&&C==2)
{
/* Downmixing a stereo stream to mono */
celt_sig *freq2;
freq2 = out_syn[0]+overlap/2;
denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
downsample, silence);
/* Use the output buffer as temp array before downmixing. */
denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
downsample, silence);
for (i=0;i<N;i++)
freq[i] = HALF32(ADD32(freq[i],freq2[i]));
for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);

Jean-Marc Valin
committed
} else {
/* Normal case (mono or stereo) */
c=0; do {
denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M,
downsample, silence);
for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);

Jean-Marc Valin
committed
} while (++c<CC);
}
RESTORE_STACK;
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
}
static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM, ec_dec *dec)
{
int i, curr, tf_select;
int tf_select_rsv;
int tf_changed;
int logp;
opus_uint32 budget;
opus_uint32 tell;
budget = dec->storage*8;
tell = ec_tell(dec);
logp = isTransient ? 2 : 4;
tf_select_rsv = LM>0 && tell+logp+1<=budget;
budget -= tf_select_rsv;
tf_changed = curr = 0;
for (i=start;i<end;i++)
{
if (tell+logp<=budget)
{
curr ^= ec_dec_bit_logp(dec, logp);
tell = ec_tell(dec);
tf_changed |= curr;
}
tf_res[i] = curr;
logp = isTransient ? 4 : 5;
}
tf_select = 0;
if (tf_select_rsv &&
tf_select_table[LM][4*isTransient+0+tf_changed] !=
tf_select_table[LM][4*isTransient+2+tf_changed])
{
tf_select = ec_dec_bit_logp(dec, 1);
}
for (i=start;i<end;i++)
{
tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
}
}
/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
current value corresponds to a pitch of 66.67 Hz. */
#define PLC_PITCH_LAG_MAX (720)
/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
pitch of 480 Hz. */
#define PLC_PITCH_LAG_MIN (100)
static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
{
int pitch_index;
VARDECL( opus_val16, lp_pitch_buf );
SAVE_STACK;
ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
pitch_downsample(decode_mem, lp_pitch_buf,
DECODE_BUFFER_SIZE, C, arch);
pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf,
DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX,
PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, arch);
pitch_index = PLC_PITCH_LAG_MAX-pitch_index;
RESTORE_STACK;
return pitch_index;
}
static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
const int C = st->channels;
celt_sig *decode_mem[2];
opus_val16 *lpc;
opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
const OpusCustomMode *mode;
int nbEBands;
int overlap;
int start;
int loss_count;
int noise_based;
const opus_int16 *eBands;
SAVE_STACK;
mode = st->mode;
nbEBands = mode->nbEBands;
overlap = mode->overlap;
eBands = mode->eBands;
c=0; do {
decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap);
out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N;
lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C);
oldBandE = lpc+C*LPC_ORDER;
oldLogE = oldBandE + 2*nbEBands;
oldLogE2 = oldLogE + 2*nbEBands;
backgroundLogE = oldLogE2 + 2*nbEBands;
loss_count = st->loss_count;
start = st->start;
noise_based = loss_count >= 5 || start != 0;
if (noise_based)
{
/* Noise-based PLC/CNG */
opus_val16 decay;
end = st->end;
effEnd = IMAX(start, IMIN(end, mode->effEBands));
/* This is an ugly hack that breaks aliasing rules and would be easily broken,
but it saves almost 4kB of stack. */
X = (celt_norm*)(out_syn[C-1]+overlap/2);
#else
ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
/* Energy decay */
decay = loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT);
c=0; do
{
for (i=start;i<end;i++)
oldBandE[c*nbEBands+i] = MAX16(backgroundLogE[c*nbEBands+i], oldBandE[c*nbEBands+i] - decay);
} while (++c<C);
seed = st->rng;
for (c=0;c<C;c++)
{
{
int j;
int boffs;
int blen;
boffs = N*c+(eBands[i]<<LM);
blen = (eBands[i+1]-eBands[i])<<LM;
for (j=0;j<blen;j++)
{
seed = celt_lcg_rand(seed);
X[boffs+j] = (celt_norm)((opus_int32)seed>>20);
}
renormalise_vector(X+boffs, blen, Q15ONE, st->arch);
}
}
st->rng = seed;
c=0; do {
OPUS_MOVE(decode_mem[c], decode_mem[c]+N,
DECODE_BUFFER_SIZE-N+(overlap>>1));

Jean-Marc Valin
committed
celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch);
} else {
/* Pitch-based PLC */
const opus_val16 *window;
opus_val16 fade = Q15ONE;
int pitch_index;
VARDECL(opus_val16, exc);
st->last_pitch_index = pitch_index = celt_plc_pitch_search(decode_mem, C, st->arch);
} else {
pitch_index = st->last_pitch_index;
fade = QCONST16(.8f,15);
}
ALLOC(etmp, overlap, opus_val32);
ALLOC(exc, MAX_PERIOD, opus_val16);
opus_val16 decay;
opus_val16 attenuation;
celt_sig *buf;
int extrapolation_offset;
int extrapolation_len;
int exc_length;
int j;
buf = decode_mem[c];
for (i=0;i<MAX_PERIOD;i++) {
exc[i] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD+i], SIG_SHIFT);
}
opus_val32 ac[LPC_ORDER+1];
/* Compute LPC coefficients for the last MAX_PERIOD samples before
the first loss so we can work in the excitation-filter domain. */
_celt_autocorr(exc, ac, window, overlap,
LPC_ORDER, MAX_PERIOD, st->arch);
#ifdef FIXED_POINT
ac[0] += SHR32(ac[0],13);
#else
ac[0] *= 1.0001f;
#endif
/* Use lag windowing to stabilize the Levinson-Durbin recursion. */
for (i=1;i<=LPC_ORDER;i++)
{
/*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
#ifdef FIXED_POINT
ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
#else
#endif
}
_celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
}
/* We want the excitation for 2 pitch periods in order to look for a
decaying signal, but we can't get more than MAX_PERIOD. */
exc_length = IMIN(2*pitch_index, MAX_PERIOD);
/* Initialize the LPC history with the samples just before the start
of the region for which we're computing the excitation. */
{
opus_val16 lpc_mem[LPC_ORDER];
for (i=0;i<LPC_ORDER;i++)
{
lpc_mem[i] =
ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-i], SIG_SHIFT);
}
/* Compute the excitation for exc_length samples before the loss. */
celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem, st->arch);
/* Check if the waveform is decaying, and if so how fast.
We do this to avoid adding energy when concealing in a segment
#ifdef FIXED_POINT
int shift = IMAX(0,2*celt_zlog2(celt_maxabs16(&exc[MAX_PERIOD-exc_length], exc_length))-20);
#endif
decay_length = exc_length>>1;
for (i=0;i<decay_length;i++)
opus_val16 e;
e = exc[MAX_PERIOD-decay_length+i];
E1 += SHR32(MULT16_16(e, e), shift);
E2 += SHR32(MULT16_16(e, e), shift);
E1 = MIN32(E1, E2);
decay = celt_sqrt(frac_div32(SHR32(E1, 1), E2));
/* Move the decoder memory one frame to the left to give us room to
add the data for the new frame. We ignore the overlap that extends
past the end of the buffer, because we aren't going to use it. */
OPUS_MOVE(buf, buf+N, DECODE_BUFFER_SIZE-N);
/* Extrapolate from the end of the excitation with a period of
"pitch_index", scaling down each period by an additional factor of
"decay". */
extrapolation_offset = MAX_PERIOD-pitch_index;
/* We need to extrapolate enough samples to cover a complete MDCT
window (including overlap/2 samples on both sides). */
extrapolation_len = N+overlap;
/* We also apply fading if this is not the first loss. */
attenuation = MULT16_16_Q15(fade, decay);
for (i=j=0;i<extrapolation_len;i++,j++)
if (j >= pitch_index) {
j -= pitch_index;
attenuation = MULT16_16_Q15(attenuation, decay);
buf[DECODE_BUFFER_SIZE-N+i] =
SHL32(EXTEND32(MULT16_16_Q15(attenuation,
exc[extrapolation_offset+j])), SIG_SHIFT);
/* Compute the energy of the previously decoded signal whose
excitation we're copying. */
tmp = ROUND16(
buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j],
SIG_SHIFT);
S1 += SHR32(MULT16_16(tmp, tmp), 8);
{
opus_val16 lpc_mem[LPC_ORDER];
/* Copy the last decoded samples (prior to the overlap region) to
synthesis filter memory so we can have a continuous signal. */
for (i=0;i<LPC_ORDER;i++)
lpc_mem[i] = ROUND16(buf[DECODE_BUFFER_SIZE-N-1-i], SIG_SHIFT);
/* Apply the synthesis filter to convert the excitation back into
the signal domain. */
celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER,
/* Check if the synthesis energy is higher than expected, which can
happen with the signal changes during our window. If so,
attenuate. */
opus_val16 tmp = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT);
S2 += SHR32(MULT16_16(tmp, tmp), 8);
/* This checks for an "explosion" in the synthesis. */
#ifdef FIXED_POINT
if (!(S1 > SHR32(S2,2)))
#else
/* The float test is written this way to catch NaNs in the output
of the IIR filter at the same time. */
for (i=0;i<extrapolation_len;i++)
buf[DECODE_BUFFER_SIZE-N+i] = 0;
} else if (S1 < S2)
{
opus_val16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
for (i=0;i<overlap;i++)
opus_val16 tmp_g = Q15ONE
- MULT16_16_Q15(window[i], Q15ONE-ratio);
buf[DECODE_BUFFER_SIZE-N+i] =
MULT16_32_Q15(tmp_g, buf[DECODE_BUFFER_SIZE-N+i]);
}
for (i=overlap;i<extrapolation_len;i++)
{
buf[DECODE_BUFFER_SIZE-N+i] =
MULT16_32_Q15(ratio, buf[DECODE_BUFFER_SIZE-N+i]);
/* Apply the pre-filter to the MDCT overlap for the next frame because
the post-filter will be re-applied in the decoder after the MDCT
overlap. */
comb_filter(etmp, buf+DECODE_BUFFER_SIZE,
st->postfilter_period, st->postfilter_period, overlap,
-st->postfilter_gain, -st->postfilter_gain,
st->postfilter_tapset, st->postfilter_tapset, NULL, 0, st->arch);
/* Simulate TDAC on the concealed audio so that it blends with the
for (i=0;i<overlap/2;i++)
{
buf[DECODE_BUFFER_SIZE+i] =
MULT16_32_Q15(window[i], etmp[overlap-1-i])
+ MULT16_32_Q15(window[overlap-i-1], etmp[i]);
}
} while (++c<C);
}

Jean-Marc Valin
committed
int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum)
{
int c, i, N;
int spread_decision;
opus_int32 bits;
ec_dec _dec;

Jean-Marc Valin
committed
celt_norm *X;
#else

Jean-Marc Valin
committed
#endif
VARDECL(int, fine_quant);
VARDECL(int, pulses);
VARDECL(int, cap);
VARDECL(int, offsets);
VARDECL(int, fine_priority);
VARDECL(int, tf_res);
VARDECL(unsigned char, collapse_masks);
celt_sig *decode_mem[2];
celt_sig *out_syn[2];
opus_val16 *lpc;
opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
int shortBlocks;
int isTransient;
int intra_ener;
const int CC = st->channels;
int LM, M;
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
int effEnd;
int codedBands;
int alloc_trim;
int postfilter_pitch;
opus_val16 postfilter_gain;
int intensity=0;
int dual_stereo=0;
opus_int32 total_bits;
opus_int32 balance;
opus_int32 tell;
int dynalloc_logp;
int postfilter_tapset;
int anti_collapse_rsv;
int anti_collapse_on=0;
int silence;
int C = st->stream_channels;
const OpusCustomMode *mode;
int nbEBands;
int overlap;
const opus_int16 *eBands;
ALLOC_STACK;
mode = st->mode;
nbEBands = mode->nbEBands;
overlap = mode->overlap;
eBands = mode->eBands;
frame_size *= st->downsample;
lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC);
oldBandE = lpc+CC*LPC_ORDER;
oldLogE = oldBandE + 2*nbEBands;
oldLogE2 = oldLogE + 2*nbEBands;
backgroundLogE = oldLogE2 + 2*nbEBands;
#ifdef CUSTOM_MODES
if (st->signalling && data!=NULL)
{
int data0=data[0];
/* Convert "standard mode" to Opus header */
if (mode->Fs==48000 && mode->shortMdctSize==120)
{
data0 = fromOpus(data0);
if (data0<0)
return OPUS_INVALID_PACKET;
}
st->end = end = IMAX(1, mode->effEBands-2*(data0>>5));
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
LM = (data0>>3)&0x3;
C = 1 + ((data0>>2)&0x1);
data++;
len--;
if (LM>mode->maxLM)
return OPUS_INVALID_PACKET;
if (frame_size < mode->shortMdctSize<<LM)
return OPUS_BUFFER_TOO_SMALL;
else
frame_size = mode->shortMdctSize<<LM;
} else {
#else
{
#endif
for (LM=0;LM<=mode->maxLM;LM++)
if (mode->shortMdctSize<<LM==frame_size)
break;
if (LM>mode->maxLM)
return OPUS_BAD_ARG;
}
M=1<<LM;
if (len<0 || len>1275 || pcm==NULL)
return OPUS_BAD_ARG;
N = M*mode->shortMdctSize;
c=0; do {
decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap);
out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N;
} while (++c<CC);
if (effEnd > mode->effEBands)
effEnd = mode->effEBands;
if (data == NULL || len<=1)
{
celt_decode_lost(st, N, LM);
deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
RESTORE_STACK;
return frame_size/st->downsample;
}
if (dec == NULL)
{
ec_dec_init(&_dec,(unsigned char*)data,len);
dec = &_dec;
}
if (C==1)
{
for (i=0;i<nbEBands;i++)
oldBandE[i]=MAX16(oldBandE[i],oldBandE[nbEBands+i]);
}
total_bits = len*8;
tell = ec_tell(dec);
if (tell >= total_bits)
silence = 1;
else if (tell==1)
silence = ec_dec_bit_logp(dec, 15);
else
silence = 0;
if (silence)
{
/* Pretend we've read all the remaining bits */
tell = len*8;
dec->nbits_total+=tell-ec_tell(dec);
}
postfilter_gain = 0;
postfilter_pitch = 0;
postfilter_tapset = 0;
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
{
if(ec_dec_bit_logp(dec, 1))
{
int qg, octave;
octave = ec_dec_uint(dec, 6);
postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave)-1;
qg = ec_dec_bits(dec, 3);
if (ec_tell(dec)+2<=total_bits)
postfilter_tapset = ec_dec_icdf(dec, tapset_icdf, 2);
postfilter_gain = QCONST16(.09375f,15)*(qg+1);
}
tell = ec_tell(dec);
}
if (LM > 0 && tell+3 <= total_bits)
{
isTransient = ec_dec_bit_logp(dec, 3);
tell = ec_tell(dec);
}
else
isTransient = 0;
if (isTransient)
shortBlocks = M;
else
shortBlocks = 0;
/* Decode the global flags (first symbols in the stream) */
intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0;
/* Get band energies */
unquant_coarse_energy(mode, start, end, oldBandE,
intra_ener, dec, C, LM);
ALLOC(tf_res, nbEBands, int);
tf_decode(start, end, isTransient, tf_res, LM, dec);
tell = ec_tell(dec);
spread_decision = SPREAD_NORMAL;
if (tell+4 <= total_bits)
spread_decision = ec_dec_icdf(dec, spread_icdf, 5);
ALLOC(cap, nbEBands, int);
init_caps(mode,cap,LM,C);
ALLOC(offsets, nbEBands, int);
dynalloc_logp = 6;
total_bits<<=BITRES;
tell = ec_tell_frac(dec);
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
{
int width, quanta;
int dynalloc_loop_logp;
int boost;
width = C*(eBands[i+1]-eBands[i])<<LM;
/* quanta is 6 bits, but no more than 1 bit/sample
and no less than 1/8 bit/sample */
quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
dynalloc_loop_logp = dynalloc_logp;
boost = 0;
while (tell+(dynalloc_loop_logp<<BITRES) < total_bits && boost < cap[i])
{
int flag;
flag = ec_dec_bit_logp(dec, dynalloc_loop_logp);
tell = ec_tell_frac(dec);
if (!flag)
break;
boost += quanta;
total_bits -= quanta;
dynalloc_loop_logp = 1;
}
offsets[i] = boost;
/* Making dynalloc more likely */
if (boost>0)
dynalloc_logp = IMAX(2, dynalloc_logp-1);
}
ALLOC(fine_quant, nbEBands, int);
alloc_trim = tell+(6<<BITRES) <= total_bits ?
ec_dec_icdf(dec, trim_icdf, 7) : 5;
bits = (((opus_int32)len*8)<<BITRES) - ec_tell_frac(dec) - 1;
anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0;
bits -= anti_collapse_rsv;
ALLOC(pulses, nbEBands, int);
ALLOC(fine_priority, nbEBands, int);
codedBands = compute_allocation(mode, start, end, offsets, cap,
alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
fine_quant, fine_priority, C, LM, dec, 0, 0, 0);
unquant_fine_energy(mode, start, end, oldBandE, fine_quant, dec, C);

Jean-Marc Valin
committed
c=0; do {
OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap/2);
} while (++c<CC);
/* Decode fixed codebook */
ALLOC(collapse_masks, C*nbEBands, unsigned char);

Jean-Marc Valin
committed

Jean-Marc Valin
committed
/* This is an ugly hack that breaks aliasing rules and would be easily broken,
but it saves almost 4kB of stack. */
X = (celt_norm*)(out_syn[CC-1]+overlap/2);
#else
ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */

Jean-Marc Valin
committed
#endif
quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, st->arch);
if (anti_collapse_rsv > 0)
{
anti_collapse_on = ec_dec_bits(dec, 1);
}
unquant_energy_finalise(mode, start, end, oldBandE,
fine_quant, fine_priority, len*8-ec_tell(dec), dec, C);
if (anti_collapse_on)
anti_collapse(mode, X, collapse_masks, LM, C, N,
start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng, st->arch);
if (silence)
{
for (i=0;i<C*nbEBands;i++)
oldBandE[i] = -QCONST16(28.f,DB_SHIFT);
}
celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd,
C, CC, isTransient, LM, st->downsample, silence, st->arch);