/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save CPUtimeinthePLCpitchsearchbymakingthissmallerthanMAX_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)
/** Decoder state @briefDecoderstate
*/ struct OpusCustomDecoder { const OpusCustomMode *mode; int overlap; int channels; int stream_channels;
int downsample; int start, end; int signalling; int disable_inv; int complexity; int arch; #ifdef ENABLE_QEXT int qext_scale; #endif
/* 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_duration; int plc_duration; int last_frame_type; int skip_plc; int postfilter_period; int postfilter_period_old;
opus_val16 postfilter_gain;
opus_val16 postfilter_gain_old; int postfilter_tapset; int postfilter_tapset_old; int prefilter_and_fold;
celt_sig preemph_memD[2];
#ifdef ENABLE_DEEP_PLC
opus_int16 plc_pcm[PLC_UPDATE_SAMPLES]; int plc_fill; float plc_preemphasis_mem; #endif
#ifdefined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS) /* Make basic checks on the CELT state to ensure we don't end
up writing all over memory. */ void validate_celt_decoder(CELTDecoder *st)
{ #if !defined(CUSTOM_MODES) && !defined(ENABLE_OPUS_CUSTOM_API) && !defined(ENABLE_QEXT)
celt_assert(st->mode == opus_custom_mode_create(48000, 960, NULL));
celt_assert(st->overlap == 120);
celt_assert(st->end <= 21); #else /* From Section 4.3 in the spec: "The normal CELT layer uses 21 of those bands, thoughOpusCustom(seeSection6.2)mayuseadifferentnumberofbands"
#if !defined(CUSTOM_MODES) && !defined(ENABLE_OPUS_CUSTOM_API) && !defined(ENABLE_QEXT) /* Special case for stereo with no downsampling and no accumulation. This is quitecommonandwecanmakeitfasterbyprocessingbothchannelsinthe
same loop, reducing overhead due to the dependency loop in the IIR filter. */ staticvoid deemphasis_stereo_simple(celt_sig *in[], opus_res *pcm, int N, const opus_val16 coef0,
celt_sig *mem)
{
celt_sig * OPUS_RESTRICT x0;
celt_sig * OPUS_RESTRICT x1;
celt_sig m0, m1; int j;
x0=in[0];
x1=in[1];
m0 = mem[0];
m1 = mem[1]; for (j=0;j<N;j++)
{
celt_sig tmp0, tmp1; /* Add VERY_SMALL to x[] first to reduce dependency chain. */
tmp0 = SATURATE(x0[j] + VERY_SMALL + m0, SIG_SAT);
tmp1 = SATURATE(x1[j] + VERY_SMALL + m1, SIG_SAT);
m0 = MULT16_32_Q15(coef0, tmp0);
m1 = MULT16_32_Q15(coef0, tmp1);
pcm[2*j ] = SIG2RES(tmp0);
pcm[2*j+1] = SIG2RES(tmp1);
}
mem[0] = m0;
mem[1] = m1;
} #endif
#ifndef RESYNTH static #endif void deemphasis(celt_sig *in[], opus_res *pcm, int N, int C, int downsample, const opus_val16 *coef,
celt_sig *mem, int accum)
{ int c; int Nd; int apply_downsampling=0;
opus_val16 coef0;
VARDECL(celt_sig, scratch);
SAVE_STACK; #if !defined(CUSTOM_MODES) && !defined(ENABLE_OPUS_CUSTOM_API) && !defined(ENABLE_QEXT) /* Short version for common case. */ if (downsample == 1 && C == 2 && !accum)
{
deemphasis_stereo_simple(in, pcm, N, coef[0], mem); return;
} #endif
ALLOC(scratch, N, celt_sig);
coef0 = coef[0];
Nd = N/downsample;
c=0; do { int j;
celt_sig * OPUS_RESTRICT x;
opus_res * OPUS_RESTRICT y;
celt_sig m = mem[c];
x =in[c];
y = pcm+c; #ifdefined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) || defined(ENABLE_QEXT) if (coef[1] != 0)
{
opus_val16 coef1 = coef[1];
opus_val16 coef3 = coef[3]; for (j=0;j<N;j++)
{
celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT);
m = MULT16_32_Q15(coef0, tmp)
- MULT16_32_Q15(coef1, x[j]);
tmp = SHL32(MULT16_32_Q15(coef3, tmp), 2);
scratch[j] = tmp;
}
apply_downsampling=1;
} else #endif if (downsample>1)
{ /* Shortcut for the standard (non-custom modes) case */ for (j=0;j<N;j++)
{
celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT);
m = MULT16_32_Q15(coef0, tmp);
scratch[j] = tmp;
}
apply_downsampling=1;
} else { /* Shortcut for the standard (non-custom modes) case */ if (accum)
{ for (j=0;j<N;j++)
{
celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT);
m = MULT16_32_Q15(coef0, tmp);
y[j*C] = ADD_RES(y[j*C], SIG2RES(tmp));
}
} else
{ for (j=0;j<N;j++)
{
celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT);
m = MULT16_32_Q15(coef0, tmp);
y[j*C] = SIG2RES(tmp);
}
}
}
mem[c] = m;
if (apply_downsampling)
{ /* Perform down-sampling */ if (accum)
{ for (j=0;j<Nd;j++)
y[j*C] = ADD_RES(y[j*C], SIG2RES(scratch[j*downsample]));
} else
{ for (j=0;j<Nd;j++)
y[j*C] = SIG2RES(scratch[j*downsample]);
}
}
} while (++c<C);
RESTORE_STACK;
}
#ifndef RESYNTH static #endif void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
celt_glog *oldBandE, int start, int effEnd, int C, int CC, int isTransient, int LM, int downsample, int silence, int arch ARG_QEXT(const CELTMode *qext_mode) ARG_QEXT(const celt_glog *qext_bandLogE) ARG_QEXT(int qext_end))
{ int c, i; int M; int b; int B; int N, NB; int shift; 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; #ifdef ENABLE_QEXT if (mode->Fs != 96000) qext_end=2; #endif
if (isTransient)
{
B = M;
NB = mode->shortMdctSize;
shift = mode->maxLM;
} else {
B = 1;
NB = mode->shortMdctSize<<LM;
shift = mode->maxLM-LM;
}
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); #ifdef ENABLE_QEXT if (qext_mode)
denormalise_bands(qext_mode, X, freq, qext_bandLogE, 0, qext_end, M,
downsample, silence); #endif /* 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);
} elseif (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); #ifdef ENABLE_QEXT if (qext_mode)
{
denormalise_bands(qext_mode, X, freq, qext_bandLogE, 0, qext_end, M,
downsample, silence);
denormalise_bands(qext_mode, X+N, freq2, qext_bandLogE+NB_QEXT_BANDS, 0, qext_end, M,
downsample, silence);
} #endif for (i=0;i<N;i++)
freq[i] = ADD32(HALF32(freq[i]), HALF32(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);
} else { /* Normal case (mono or stereo) */
c=0; do {
denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M,
downsample, silence); #ifdef ENABLE_QEXT if (qext_mode)
denormalise_bands(qext_mode, X+c*N, freq, qext_bandLogE+c*NB_QEXT_BANDS, 0, qext_end, M,
downsample, silence); #endif for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
} while (++c<CC);
} /* Saturate IMDCT output so that we can't overflow in the pitch postfilter
or in the */
c=0; do { for (i=0;i<N;i++)
out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
} while (++c<CC);
RESTORE_STACK;
}
staticvoid 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;
staticvoid prefilter_and_fold(CELTDecoder * OPUS_RESTRICT st, int N)
{ int c; int CC; int i; int overlap;
celt_sig *decode_mem[2]; const OpusCustomMode *mode; int decode_buffer_size; #ifdef ENABLE_QEXT int qext_scale; #endif
VARDECL(opus_val32, etmp);
SAVE_STACK #ifdef ENABLE_QEXT
qext_scale = st->qext_scale; #endif
decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
mode = st->mode;
overlap = st->overlap;
CC = st->channels;
ALLOC(etmp, overlap, opus_val32);
c=0; do {
decode_mem[c] = st->_decode_mem + c*(decode_buffer_size+overlap);
} while (++c<CC);
c=0; do { /* Apply the pre-filter to the MDCT overlap for the next frame because thepost-filterwillbere-appliedinthedecoderaftertheMDCT
overlap. */
comb_filter(etmp, decode_mem[c]+decode_buffer_size-N,
st->postfilter_period_old, st->postfilter_period, overlap,
-st->postfilter_gain_old, -st->postfilter_gain,
st->postfilter_tapset_old, st->postfilter_tapset, NULL, 0, st->arch);
/* Simulate TDAC on the concealed audio so that it blends with the
MDCT of the next frame. */ for (i=0;i<overlap/2;i++)
{
decode_mem[c][decode_buffer_size-N+i] =
MULT16_32_Q15(COEF2VAL16(mode->window[i]), etmp[overlap-1-i])
+ MULT16_32_Q15 (COEF2VAL16(mode->window[overlap-i-1]), etmp[i]);
}
} while (++c<CC);
RESTORE_STACK;
}
/* 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);
ALLOC(_exc, max_period+CELT_LPC_ORDER, opus_val16);
ALLOC(fir_tmp, exc_length, opus_val16);
exc = _exc+CELT_LPC_ORDER;
window = mode->window;
c=0; do {
opus_val16 decay;
opus_val16 attenuation;
opus_val32 S1=0;
celt_sig *buf; int extrapolation_offset; int extrapolation_len; int j;
buf = decode_mem[c]; for (i=0;i<max_period+CELT_LPC_ORDER;i++)
exc[i-CELT_LPC_ORDER] = SROUND16(buf[decode_buffer_size-max_period-CELT_LPC_ORDER+i], SIG_SHIFT);
if (st->last_frame_type != FRAME_PLC_PERIODIC && !(last_neural && curr_neural))
{
opus_val32 ac[CELT_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,
CELT_LPC_ORDER, max_period, st->arch); /* Add a noise floor of -40 dB. */ #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<=CELT_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
ac[i] -= ac[i]*(0.008f*0.008f)*i*i; #endif
}
_celt_lpc(lpc+c*CELT_LPC_ORDER, ac, CELT_LPC_ORDER); #ifdef FIXED_POINT /* For fixed-point, apply bandwidth expansion until we can guarantee that nooverflowcanhappenintheIIRfilter.Thismeans:
32768*sum(abs(filter)) < 2^31 */ while (1) {
opus_val16 tmp=Q15ONE;
opus_val32 sum=QCONST16(1., SIG_SHIFT); for (i=0;i<CELT_LPC_ORDER;i++)
sum += ABS16(lpc[c*CELT_LPC_ORDER+i]); if (sum < 65535) break; for (i=0;i<CELT_LPC_ORDER;i++)
{
tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
lpc[c*CELT_LPC_ORDER+i] = MULT16_16_Q15(lpc[c*CELT_LPC_ORDER+i], tmp);
}
} #endif
} /* Initialize the LPC history with the samples just before the start
of the region for which we're computing the excitation. */
{ /* Compute the excitation for exc_length samples before the loss. We need the copy
because celt_fir() cannot filter in-place. */
celt_fir(exc+max_period-exc_length, lpc+c*CELT_LPC_ORDER,
fir_tmp, exc_length, CELT_LPC_ORDER, st->arch);
OPUS_COPY(exc+max_period-exc_length, fir_tmp, exc_length);
}
/* Check if the waveform is decaying, and if so how fast. Wedothistoavoidaddingenergywhenconcealinginasegment
with decaying energy. */
{
opus_val32 E1=1, E2=1; int decay_length; #ifdef FIXED_POINT int shift = IMAX(0,2*celt_zlog2(celt_maxabs16(&exc[max_period-exc_length], exc_length))-20); #ifdef ENABLE_QEXT if (st->qext_scale==2) shift++; #endif #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);
e = exc[max_period-2*decay_length+i];
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 addthedataforthenewframe.Weignoretheoverlapthatextends
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",scalingdowneachperiodbyanadditionalfactorof
"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++)
{
opus_val16 tmp; 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 = SROUND16(
buf[decode_buffer_size-max_period-N+extrapolation_offset+j],
SIG_SHIFT);
S1 += SHR32(MULT16_16(tmp, tmp), 11);
}
{
opus_val16 lpc_mem[CELT_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<CELT_LPC_ORDER;i++)
lpc_mem[i] = SROUND16(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*CELT_LPC_ORDER,
buf+decode_buffer_size-N, extrapolation_len, CELT_LPC_ORDER,
lpc_mem, st->arch); #ifdef FIXED_POINT for (i=0; i < extrapolation_len; i++)
buf[decode_buffer_size-N+i] = SATURATE(buf[decode_buffer_size-N+i], SIG_SAT); #endif
}
/* Check if the synthesis energy is higher than expected, which can happenwiththesignalchangesduringourwindow.Ifso,
attenuate. */
{
opus_val32 S2=0; for (i=0;i<extrapolation_len;i++)
{
opus_val16 tmp = SROUND16(buf[decode_buffer_size-N+i], SIG_SHIFT);
S2 += SHR32(MULT16_16(tmp, tmp), 11);
} /* 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. */ if (!(S1 > 0.2f*S2)) #endif
{ for (i=0;i<extrapolation_len;i++)
buf[decode_buffer_size-N+i] = 0;
} elseif (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(COEF2VAL16(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]);
}
}
}
} while (++c<C);
#ifdef ENABLE_DEEP_PLC if (curr_neural) { float overlap_mem; int samples_needed16k;
celt_sig *buf;
VARDECL(float, buf_copy);
buf = decode_mem[0];
ALLOC(buf_copy, C*overlap, float);
c=0; do {
OPUS_COPY(buf_copy+c*overlap, &decode_mem[c][decode_buffer_size-N], overlap);
} while (++c<C);
/* Need enough samples from the PLC to cover the frame size, resampling delay,
and the overlap at the end. */
samples_needed16k = (N+SINC_ORDER+overlap)/3; if (!last_neural) {
st->plc_fill = 0;
} while (st->plc_fill < samples_needed16k) {
lpcnet_plc_conceal(lpcnet, &st->plc_pcm[st->plc_fill]);
st->plc_fill += FRAME_SIZE;
} /* Resample to 48 kHz. */ for (i=0;i<(N+overlap)/3;i++) { int j; float sum; for (sum=0, j=0;j<17;j++) sum += 3*st->plc_pcm[i+j]*sinc_filter[3*j];
buf[decode_buffer_size-N+3*i] = sum; for (sum=0, j=0;j<16;j++) sum += 3*st->plc_pcm[i+j+1]*sinc_filter[3*j+2];
buf[decode_buffer_size-N+3*i+1] = sum; for (sum=0, j=0;j<16;j++) sum += 3*st->plc_pcm[i+j+1]*sinc_filter[3*j+1];
buf[decode_buffer_size-N+3*i+2] = sum;
}
OPUS_MOVE(st->plc_pcm, &st->plc_pcm[N/3], st->plc_fill-N/3);
st->plc_fill -= N/3; for (i=0;i<N;i++) { float tmp = buf[decode_buffer_size-N+i];
buf[decode_buffer_size-N+i] -= PREEMPHASIS*st->plc_preemphasis_mem;
st->plc_preemphasis_mem = tmp;
}
overlap_mem = st->plc_preemphasis_mem; for (i=0;i<overlap;i++) { float tmp = buf[decode_buffer_size+i];
buf[decode_buffer_size+i] -= PREEMPHASIS*overlap_mem;
overlap_mem = tmp;
} /* For now, we just do mono PLC. */ if (C==2) OPUS_COPY(decode_mem[1], decode_mem[0], decode_buffer_size+overlap);
c=0; do { /* Cross-fade with 48-kHz non-neural PLC for the first 2.5 ms to avoid a discontinuity. */ if (!last_neural) { for (i=0;i<overlap;i++) decode_mem[c][decode_buffer_size-N+i] = (1-window[i])*buf_copy[c*overlap+i] + (window[i])*decode_mem[c][decode_buffer_size-N+i];
}
} while (++c<C);
} #endif
st->prefilter_and_fold = 1;
}
/* Saturate to something large to avoid wrap-around. */
st->loss_duration = IMIN(10000, loss_duration+(1<<LM));
st->plc_duration = IMIN(10000, st->plc_duration+(1<<LM)); #ifdef ENABLE_DRED if (curr_frame_type == FRAME_DRED) {
st->plc_duration = 0;
st->skip_plc = 0;
} #endif
st->last_frame_type = curr_frame_type;
RESTORE_STACK;
}
#ifdef ENABLE_QEXT staticvoid decode_qext_stereo_params(ec_dec *ec, int qext_end, int *qext_intensity, int*qext_dual_stereo) {
*qext_intensity = ec_dec_uint(ec, qext_end+1); if (*qext_intensity != 0) *qext_dual_stereo = ec_dec_bit_logp(ec, 1); else *qext_dual_stereo = 0;
} #endif
int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, constunsignedchar *data, int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum #ifdef ENABLE_DEEP_PLC
,LPCNetPLCState *lpcnet #endif
ARG_QEXT(constunsignedchar *qext_payload) ARG_QEXT(int qext_payload_len)
)
{ int c, i, N; int spread_decision;
opus_int32 bits;
ec_dec _dec;
VARDECL(celt_norm, X);
VARDECL(int, fine_quant);
VARDECL(int, pulses);
VARDECL(int, cap);
VARDECL(int, offsets);
VARDECL(int, fine_priority);
VARDECL(int, tf_res);
VARDECL(unsignedchar, collapse_masks);
celt_sig *decode_mem[2];
celt_sig *out_syn[2];
celt_glog *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
int shortBlocks; int isTransient; int intra_ener; constint CC = st->channels; int LM, M; int start; int end; 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;
celt_glog max_background_increase; int decode_buffer_size; #ifdef ENABLE_QEXT
opus_int32 qext_bits;
ec_dec ext_dec; int qext_bytes=0; int qext_end=0; int qext_intensity=0; int qext_dual_stereo=0;
VARDECL(int, extra_quant);
VARDECL(int, extra_pulses); const CELTMode *qext_mode = NULL;
CELTMode qext_mode_struct; int qext_scale; #else # define qext_bytes 0 #endif
ALLOC_STACK; #ifdef ENABLE_QEXT
qext_scale = st->qext_scale; #endif
decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
#ifdef ENABLE_QEXT if (qext_payload) {
ec_dec_init(&ext_dec, (unsignedchar*)qext_payload, qext_payload_len);
qext_bytes = qext_payload_len;
} else {
ec_dec_init(&ext_dec, NULL, 0);
} #endif #ifdefined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) if (st->signalling && data!=NULL)
{ int data0=data[0]; /* Convert "standard mode" to Opus header */ # ifndef ENABLE_QEXT if (mode->Fs==48000 && mode->shortMdctSize==120) # endif
{
data0 = fromOpus(data0); if (data0<0) return OPUS_INVALID_PACKET;
}
st->end = end = IMAX(1, mode->effEBands-2*(data0>>5));
LM = (data0>>3)&0x3;
C = 1 + ((data0>>2)&0x1); if ((data[0] & 0x03) == 0x03) {
data++;
len--; if (len<=0) return OPUS_INVALID_PACKET; if (data[0] & 0x40) { int p; int padding=0;
data++;
len--; do { int tmp; if (len<=0) return OPUS_INVALID_PACKET;
p = *data++;
len--;
tmp = p==255 ? 254: p;
len -= tmp;
padding += tmp;
} while (p==255);
padding--; if (len <= 0 || padding<0) return OPUS_INVALID_PACKET; #ifdef ENABLE_QEXT
qext_bytes = padding; if (data[len] != QEXT_EXTENSION_ID<<1)
qext_bytes=0;
ec_dec_init(&ext_dec, (unsignedchar*)data+len+1, qext_bytes); #endif
}
} else
{
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);
effEnd = end; if (effEnd > mode->effEBands)
effEnd = mode->effEBands;
if (data == NULL || len<=1)
{
celt_decode_lost(st, N, LM #ifdef ENABLE_DEEP_PLC
, lpcnet #endif
);
deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
RESTORE_STACK; return frame_size/st->downsample;
} #ifdef ENABLE_DEEP_PLC else { /* FIXME: This is a bit of a hack just to make sure opus_decode_native() knows we're no longer in PLC. */ if (lpcnet) lpcnet->blend = 0;
} #endif
/* Check if there are at least two packets received consecutively before
* turning on the pitch-based PLC */ if (st->loss_duration == 0) st->skip_plc = 0;
if (dec == NULL)
{
ec_dec_init(&_dec,(unsignedchar*)data,len);
dec = &_dec;
}
if (C==1)
{ for (i=0;i<nbEBands;i++)
oldBandE[i]=MAXG(oldBandE[i],oldBandE[nbEBands+i]);
}
total_bits = len*8;
tell = ec_tell(dec);
if (tell >= total_bits)
silence = 1; elseif (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);
}
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; /* If recovering from packet loss, make sure we make the energy prediction safe to reduce the
risk of getting loud artifacts. */ if (!intra_ener && st->loss_duration != 0) {
c=0; do
{
celt_glog safety = 0; int missing = IMIN(10, st->loss_duration>>LM); if (LM==0) safety = GCONST(1.5f); elseif (LM==1) safety = GCONST(.5f); for (i=start;i<end;i++)
{ if (oldBandE[c*nbEBands+i] < MAXG(oldLogE[c*nbEBands+i], oldLogE2[c*nbEBands+i])) { /* If energy is going down already, continue the trend. */
opus_val32 slope;
opus_val32 E0, E1, E2;
E0 = oldBandE[c*nbEBands+i];
E1 = oldLogE[c*nbEBands+i];
E2 = oldLogE2[c*nbEBands+i];
slope = MAX32(E1 - E0, HALF32(E2 - E0));
slope = MING(slope, GCONST(2.f));
E0 -= MAX32(0, (1+missing)*slope);
oldBandE[c*nbEBands+i] = MAX32(-GCONST(20.f), E0);
} else { /* Otherwise take the min of the last frames. */
oldBandE[c*nbEBands+i] = MING(MING(oldBandE[c*nbEBands+i], oldLogE[c*nbEBands+i]), oldLogE2[c*nbEBands+i]);
} /* Shorter frames have more natural fluctuations -- play it safe. */
oldBandE[c*nbEBands+i] -= safety;
}
} while (++c<2);
} /* Get band energies */
unquant_coarse_energy(mode, start, end, oldBandE,
intra_ener, dec, C, LM);
dynalloc_logp = 6;
total_bits<<=BITRES;
tell = ec_tell_frac(dec); for (i=start;i<end;i++)
{ 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);
}
if (C==1)
OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands);
if (!isTransient)
{
OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands);
OPUS_COPY(oldLogE, oldBandE, 2*nbEBands);
} else { for (i=0;i<2*nbEBands;i++)
oldLogE[i] = MING(oldLogE[i], oldBandE[i]);
} /* In normal circumstances, we only allow the noise floor to increase by upto2.4dB/second,butwhenwe'reinDTXwegivetheweightof
all missing packets to the update packet. */
max_background_increase = IMIN(160, st->loss_duration+M)*GCONST(0.001f); for (i=0;i<2*nbEBands;i++)
backgroundLogE[i] = MING(backgroundLogE[i] + max_background_increase, oldBandE[i]); /* In case start or end were to change */
c=0; do
{ for (i=0;i<start;i++)
{
oldBandE[c*nbEBands+i]=0;
oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-GCONST(28.f);
} for (i=end;i<nbEBands;i++)
{
oldBandE[c*nbEBands+i]=0;
oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-GCONST(28.f);
}
} while (++c<2);
st->rng = dec->rng; #ifdef ENABLE_QEXT if (qext_bytes) st->rng = st->rng ^ ext_dec.rng; #endif
#ifdefined(FIXED_POINT) && !defined(ENABLE_RES24) int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, constunsignedchar *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
{ return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
} #else int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, constunsignedchar *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
{ int j, ret, C, N;
VARDECL(opus_res, out);
ALLOC_STACK;
if (pcm==NULL) return OPUS_BAD_ARG;
C = st->channels;
N = frame_size;
ALLOC(out, C*N, opus_res);
ret = celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0); if (ret>0) for (j=0;j<C*ret;j++)
pcm[j]=RES2INT16(out[j]);
RESTORE_STACK; return ret;
} #endif
#ifdefined(FIXED_POINT) && defined(ENABLE_RES24) int opus_custom_decode24(CELTDecoder * OPUS_RESTRICT st, constunsignedchar *data, int len, opus_int32 * OPUS_RESTRICT pcm, int frame_size)
{ return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
} #else int opus_custom_decode24(CELTDecoder * OPUS_RESTRICT st, constunsignedchar *data, int len, opus_int32 * OPUS_RESTRICT pcm, int frame_size)
{ int j, ret, C, N;
VARDECL(opus_res, out);
ALLOC_STACK;
if (pcm==NULL) return OPUS_BAD_ARG;
C = st->channels;
N = frame_size;
ALLOC(out, C*N, opus_res);
ret = celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0); if (ret>0) for (j=0;j<C*ret;j++)
pcm[j]=RES2INT24(out[j]);
RESTORE_STACK; return ret;
} #endif
#ifndef DISABLE_FLOAT_API
# if !defined(FIXED_POINT) int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, constunsignedchar *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
{ return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
} # else int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, constunsignedchar *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
{ int j, ret, C, N;
VARDECL(opus_res, out);
ALLOC_STACK;
if (pcm==NULL) return OPUS_BAD_ARG;
C = st->channels;
N = frame_size;
ALLOC(out, C*N, opus_res);
ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0); if (ret>0) for (j=0;j<C*ret;j++)
pcm[j]=RES2FLOAT(out[j]);
RESTORE_STACK; return ret;
} # endif
#endif
#endif/* CUSTOM_MODES */
int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
{
va_list ap;
va_start(ap, request); switch (request)
{ case OPUS_SET_COMPLEXITY_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32); if(value<0 || value>10)
{ goto bad_arg;
}
st->complexity = value;
} break; case OPUS_GET_COMPLEXITY_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*); if (!value)
{ goto bad_arg;
}
*value = st->complexity;
} break; case CELT_SET_START_BAND_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32); if (value<0 || value>=st->mode->nbEBands) goto bad_arg;
st->start = value;
} break; case CELT_SET_END_BAND_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32); if (value<1 || value>st->mode->nbEBands) goto bad_arg;
st->end = value;
} break; case CELT_SET_CHANNELS_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32); if (value<1 || value>2) goto bad_arg;
st->stream_channels = value;
} break; case CELT_GET_AND_CLEAR_ERROR_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*); if (value==NULL) goto bad_arg;
*value=st->error;
st->error = 0;
} break; case OPUS_GET_LOOKAHEAD_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*); if (value==NULL) goto bad_arg;
*value = st->overlap/st->downsample;
} break; case OPUS_RESET_STATE:
{ int i;
celt_glog *oldBandE, *oldLogE, *oldLogE2; int decode_buffer_size; #ifdef ENABLE_QEXT int qext_scale = st->qext_scale; #endif
decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
oldBandE = (celt_glog*)(st->_decode_mem+(decode_buffer_size+st->overlap)*st->channels);
oldLogE = oldBandE + 2*st->mode->nbEBands;
oldLogE2 = oldLogE + 2*st->mode->nbEBands;
OPUS_CLEAR((char*)&st->DECODER_RESET_START,
opus_custom_decoder_get_size(st->mode, st->channels)-
((char*)&st->DECODER_RESET_START - (char*)st)); for (i=0;i<2*st->mode->nbEBands;i++)
oldLogE[i]=oldLogE2[i]=-GCONST(28.f);
st->skip_plc = 1;
st->last_frame_type = FRAME_NONE;
} break; case OPUS_GET_PITCH_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*); if (value==NULL) goto bad_arg;
*value = st->postfilter_period;
} break; case CELT_GET_MODE_REQUEST:
{ const CELTMode ** value = va_arg(ap, const CELTMode**); if (value==0) goto bad_arg;
*value=st->mode;
} break; case CELT_SET_SIGNALLING_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
st->signalling = value;
} break; case OPUS_GET_FINAL_RANGE_REQUEST:
{
opus_uint32 * value = va_arg(ap, opus_uint32 *); if (value==0) goto bad_arg;
*value=st->rng;
} break; case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32); if(value<0 || value>1)
{ goto bad_arg;
}
st->disable_inv = value;
} break; case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*); if (!value)
{ goto bad_arg;
}
*value = st->disable_inv;
} break; default: goto bad_request;
}
va_end(ap); return OPUS_OK;
bad_arg:
va_end(ap); return OPUS_BAD_ARG;
bad_request:
va_end(ap); return OPUS_UNIMPLEMENTED;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.29Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.