/** Encoder state @briefEncoderstate
*/ struct OpusCustomEncoder { const OpusCustomMode *mode; /**< Mode used by the encoder */ int channels; int stream_channels;
int force_intra; int clip; int disable_pf; int complexity; int upsample; int start, end;
opus_int32 bitrate; int vbr; int signalling; int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */ int loss_rate; int lsb_depth; int lfe; int disable_inv; int arch; #ifdef ENABLE_QEXT int enable_qext; int qext_scale; #endif
/* Everything beyond this point gets cleared on a reset */ #define ENCODER_RESET_START rng
opus_uint32 rng; int spread_decision;
opus_val32 delayedIntra; int tonal_average; int lastCodedBands; int hf_average; int tapset_decision;
int prefilter_period;
opus_val16 prefilter_gain; int prefilter_tapset; #ifdef RESYNTH int prefilter_period_old;
opus_val16 prefilter_gain_old; int prefilter_tapset_old; #endif int consec_transient;
AnalysisInfo analysis;
SILKInfo silk_info;
#ifdef RESYNTH #ifdef ENABLE_QEXT /* +MAX_PERIOD/2 to make space for overlap */
celt_sig syn_mem[2][2*DEC_PITCH_BUF_SIZE+MAX_PERIOD]; #else /* +MAX_PERIOD/2 to make space for overlap */
celt_sig syn_mem[2][DEC_PITCH_BUF_SIZE+MAX_PERIOD/2]; #endif #endif
*weak_transient = 0; /* For lower bitrates, let's be more conservative and have a forward masking decayof3.3dB/ms.Thisavoidshavingtocodetransientsatverylow bitrate(mostlyforhybrid),whichcanresultinunstableenergyand/or
partial collapse. */ if (allow_weak_transients)
{ #ifdef FIXED_POINT
forward_shift = 5; #else
forward_decay = QCONST16(.03125f,15); #endif
}
len2=len/2; for (c=0;c<C;c++)
{
opus_val32 mean;
opus_int32 unmask=0;
opus_val32 norm;
opus_val16 maxE;
mem0=0;
mem1=0; /* High-pass filter: (1 - 2*z^-1 + z^-2) / (1 - z^-1 + .5*z^-2) */ for (i=0;i<len;i++)
{ #ifndef FIXED_POINT float mem00; #endif
opus_val32 x,y;
x = SHR32(in[i+c*len],in_shift);
y = ADD32(mem0, x); #ifdef FIXED_POINT
mem0 = mem1 + y - SHL32(x,1);
mem1 = x - SHR32(y,1); #else /* Original code: mem0=mem1+y-2*x; mem1=x-.5f*y;
Modified code to shorten dependency chains: */
mem00=mem0;
mem0 = mem0 - x + .5f*mem1;
mem1 = x - mem00; #endif
tmp[i] = SROUND16(y, 2); /*printf("%f ", tmp[i]);*/
} /*printf("\n");*/ /* First few samples are bad because we don't propagate the memory */
OPUS_CLEAR(tmp, 12);
#ifdef FIXED_POINT /* Normalize tmp to max range */
{ int shift=0;
shift = 14-celt_ilog2(MAX16(1, celt_maxabs16(tmp, len))); if (shift!=0)
{ for (i=0;i<len;i++)
tmp[i] = SHL16(tmp[i], shift);
}
} #endif
mean=0;
mem0=0; /* Grouping by two to reduce complexity */ /* Forward pass to compute the post-echo threshold*/ for (i=0;i<len2;i++)
{
opus_val32 x2 = PSHR32(MULT16_16(tmp[2*i],tmp[2*i]) + MULT16_16(tmp[2*i+1],tmp[2*i+1]),4);
mean += PSHR32(x2, 12); #ifdef FIXED_POINT /* FIXME: Use PSHR16() instead */
mem0 = mem0 + PSHR32(x2-mem0,forward_shift);
tmp[i] = PSHR32(mem0, 12); #else
mem0 = x2 + (1.f-forward_decay)*mem0;
tmp[i] = forward_decay*mem0; #endif
}
/* Compute the ratio of the "frame energy" over the harmonic mean of the energy. Thisessentiallycorrespondstoabitrate-normalizedtemporalnoise-to-mask
ratio */
/* As a compromise with the old transient detector, frame energy is the
geometric mean of the energy and half the max */ #ifdef FIXED_POINT /* Costs two sqrt() to avoid overflows */
mean = MULT16_16(celt_sqrt(mean), celt_sqrt(MULT16_16(maxE,len2>>1))); #else
mean = celt_sqrt(mean * maxE*.5*len2); #endif /* Inverse of the mean energy in Q15+6 */
norm = SHL32(EXTEND32(len2),6+14)/ADD32(EPSILON,SHR32(mean,1)); /* Compute harmonic mean discarding the unreliable boundaries
The data is smooth, so we only take 1/4th of the samples */
unmask=0; /* We should never see NaNs here. If we find any, then something really bad happened and we better abort beforeitdoesanydamagelateron.Iftheseassertsaredisabled(nohardening),thenthetable lookupafewlinesbelow(id=...)islikelytocrashdurtoanout-of-boundsread.DONOTFIX
that crash on NaN since it could result in a worse issue later on. */
celt_assert(!celt_isnan(tmp[0]));
celt_assert(!celt_isnan(norm)); for (i=12;i<len2-5;i+=4)
{ int id; #ifdef FIXED_POINT
id = MAX32(0,MIN32(127,MULT16_32_Q15(tmp[i]+EPSILON,norm))); /* Do not round to nearest */ #else
id = (int)MAX32(0,MIN32(127,floor(64*norm*(tmp[i]+EPSILON)))); /* Do not round to nearest */ #endif
unmask += inv_table[id];
} /*printf("%d\n", unmask);*/ /* Normalize, compensate for the 1/4th of the sample and the factor of 6 in the inverse table */
unmask = 64*unmask*4/(6*(len2-17)); if (unmask>mask_metric)
{
*tf_chan = c;
mask_metric = unmask;
}
}
is_transient = mask_metric>200; /* Prevent the transient detector from confusing the partial cycle of a
very low frequency tone with a transient. */ if (toneishness > QCONST32(.98f, 29) && tone_freq < QCONST16(0.026f, 13))
{
is_transient = 0;
mask_metric = 0;
} /* For low bitrates, define "weak transients" that need to be
handled differently to avoid partial collapse. */ if (allow_weak_transients && is_transient && mask_metric<600) {
is_transient = 0;
*weak_transient = 1;
} /* Arbitrary metric for VBR boost */
tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42); /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */
*tf_estimate = celt_sqrt(MAX32(0, SHL32(MULT16_16(QCONST16(0.0069,14),MIN16(163,tf_max)),14)-QCONST32(0.139,28))); /*printf("%d %f\n", tf_max, mask_metric);*/
RESTORE_STACK; #ifdef FUZZING
is_transient = rand()&0x1; #endif /*printf("%d %f %d\n", is_transient, (float)*tf_estimate, tf_max);*/ return is_transient;
}
/* Looks for sudden increases of energy to decide whether we need to patch
the transient decision */ staticint patch_transient_decision(celt_glog *newE, celt_glog *oldE, int nbEBands, int start, int end, int C)
{ int i, c;
opus_val32 mean_diff=0;
celt_glog spread_old[26]; /* Apply an aggressive (-6 dB/Bark) spreading function to the old frame to
avoid false detection caused by irrelevant bands */ if (C==1)
{
spread_old[start] = oldE[start]; for (i=start+1;i<end;i++)
spread_old[i] = MAXG(spread_old[i-1]-GCONST(1.0f), oldE[i]);
} else {
spread_old[start] = MAXG(oldE[start],oldE[start+nbEBands]); for (i=start+1;i<end;i++)
spread_old[i] = MAXG(spread_old[i-1]-GCONST(1.0f),
MAXG(oldE[i],oldE[i+nbEBands]));
} for (i=end-2;i>=start;i--)
spread_old[i] = MAXG(spread_old[i], spread_old[i+1]-GCONST(1.0f)); /* Compute mean increase */
c=0; do { for (i=IMAX(2,start);i<end-1;i++)
{
opus_val16 x1, x2;
x1 = MAXG(0, newE[i + c*nbEBands]);
x2 = MAXG(0, spread_old[i]);
mean_diff = ADD32(mean_diff, MAXG(0, SUB32(x1, x2)));
}
} while (++c<C);
mean_diff = DIV32(mean_diff, C*(end-1-IMAX(2,start))); /*printf("%f %f %d\n", mean_diff, max_diff, count);*/ return mean_diff > GCONST(1.f);
}
/** Apply window and compute the MDCT for all sub-frames and
all channels in a frame */ staticvoid compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * OPUS_RESTRICT in,
celt_sig * OPUS_RESTRICT out, int C, int CC, int LM, int upsample, int arch)
{ constint overlap = mode->overlap; int N; int B; int shift; int i, b, c; if (shortBlocks)
{
B = shortBlocks;
N = mode->shortMdctSize;
shift = mode->maxLM;
} else {
B = 1;
N = mode->shortMdctSize<<LM;
shift = mode->maxLM-LM;
}
c=0; do { for (b=0;b<B;b++)
{ /* Interleaving the sub-frames while doing the MDCTs */
clt_mdct_forward(&mode->mdct, in+c*(B*N+overlap)+b*N,
&out[b+c*N*B], mode->window, overlap, shift, B,
arch);
}
} while (++c<CC); if (CC==2&&C==1)
{ for (i=0;i<B*N;i++)
out[i] = ADD32(HALF32(out[i]), HALF32(out[B*N+i]));
} if (upsample != 1)
{
c=0; do
{ int bound = B*N/upsample; for (i=0;i<bound;i++)
out[c*B*N+i] *= upsample;
OPUS_CLEAR(&out[c*B*N+bound], B*N-bound);
} while (++c<C);
}
}
void celt_preemphasis(const opus_res * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp, int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip)
{ int i;
opus_val16 coef0;
celt_sig m; int Nu;
coef0 = coef[0];
m = *mem;
/* Fast path for the normal 48kHz case and no clipping */ if (coef[1] == 0 && upsample == 1 && !clip)
{ for (i=0;i<N;i++)
{
celt_sig x;
x = RES2SIG(pcmp[CC*i]); /* Apply pre-emphasis */
inp[i] = x - m;
m = MULT16_32_Q15(coef0, x);
}
*mem = m; return;
}
Nu = N/upsample; if (upsample!=1)
{
OPUS_CLEAR(inp, N);
} for (i=0;i<Nu;i++)
inp[i*upsample] = RES2SIG(pcmp[CC*i]);
#ifndef FIXED_POINT if (clip)
{ /* Clip input to avoid encoding non-portable files */ for (i=0;i<Nu;i++)
inp[i*upsample] = MAX32(-65536.f, MIN32(65536.f,inp[i*upsample]));
} #elifdefined(ENABLE_RES24) if (clip)
{ /* Clip input to avoid encoding non-portable files */ for (i=0;i<Nu;i++)
inp[i*upsample] = MAX32(-(65536<<SIG_SHIFT), MIN32(65536<<SIG_SHIFT,inp[i*upsample]));
} #else
(void)clip; /* Avoids a warning about clip being unused. */ #endif #ifdefined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) || defined(ENABLE_QEXT) if (coef[1] != 0)
{
opus_val16 coef1 = coef[1]; #ifdefined(FIXED_POINT) && defined(ENABLE_QEXT) /* If we need the extra precision, we use the fact that coef[3] is exact to do a Newton-Raphson
iteration and get us more precision on coef[2]. */
opus_val32 coef2_q30 = SHL32(coef[2], 18) + PSHR32(MULT16_16(QCONST32(1.f, 25) - MULT16_16(coef[3], coef[2]), coef[2]), 7);
celt_assert(SIG_SHIFT == 12); #else
opus_val16 coef2 = coef[2]; #endif for (i=0;i<N;i++)
{
celt_sig x, tmp;
x = inp[i]; /* Apply pre-emphasis */ #ifdefined(FIXED_POINT) && defined(ENABLE_QEXT)
tmp = SHL32(MULT32_32_Q31(coef2_q30, x), 1); #else
tmp = SHL32(MULT16_32_Q15(coef2, x), 15-SIG_SHIFT); #endif
inp[i] = tmp + m;
m = MULT16_32_Q15(coef1, inp[i]) - MULT16_32_Q15(coef0, tmp);
}
} else #endif
{ for (i=0;i<N;i++)
{
celt_sig x;
x = inp[i]; /* Apply pre-emphasis */
inp[i] = x - m;
m = MULT16_32_Q15(coef0, x);
}
}
*mem = m;
}
static opus_val32 l1_metric(const celt_norm *tmp, int N, int LM, opus_val16 bias)
{ int i;
opus_val32 L1;
L1 = 0; for (i=0;i<N;i++)
L1 += EXTEND32(ABS16(SHR32(tmp[i], NORM_SHIFT-14))); /* When in doubt, prefer good freq resolution */
L1 = MAC16_32_Q15(L1, LM*bias, L1); return L1;
}
staticint tf_analysis(const CELTMode *m, int len, int isTransient, int *tf_res, int lambda, celt_norm *X, int N0, int LM,
opus_val16 tf_estimate, int tf_chan, int *importance)
{ int i;
VARDECL(int, metric); int cost0; int cost1;
VARDECL(int, path0);
VARDECL(int, path1);
VARDECL(celt_norm, tmp);
VARDECL(celt_norm, tmp_1); int sel; int selcost[2]; int tf_select=0;
opus_val16 bias;
for (i=0;i<len;i++)
{ int k, N; int narrow;
opus_val32 L1, best_L1; int best_level=0;
N = (m->eBands[i+1]-m->eBands[i])<<LM; /* band is too narrow to be split down to LM=-1 */
narrow = (m->eBands[i+1]-m->eBands[i])==1;
OPUS_COPY(tmp, &X[tf_chan*N0 + (m->eBands[i]<<LM)], N); /* Just add the right channel if we're in stereo */ /*if (C==2) for(j=0;j<N;j++)
tmp[j] = ADD16(SHR16(tmp[j], 1),SHR16(X[N0+j+(m->eBands[i]<<LM)], 1));*/
L1 = l1_metric(tmp, N, isTransient ? LM : 0, bias);
best_L1 = L1; /* Check the -1 case for transients */ if (isTransient && !narrow)
{
OPUS_COPY(tmp_1, tmp, N);
haar1(tmp_1, N>>LM, 1<<LM);
L1 = l1_metric(tmp_1, N, LM+1, bias); if (L1<best_L1)
{
best_L1 = L1;
best_level = -1;
}
} /*printf ("%f ", L1);*/ for (k=0;k<LM+!(isTransient||narrow);k++)
{ int B;
if (isTransient)
B = (LM-k-1); else
B = k+1;
haar1(tmp, N>>k, 1<<k);
L1 = l1_metric(tmp, N, B, bias);
if (L1 < best_L1)
{
best_L1 = L1;
best_level = k+1;
}
} /*printf ("%d ", isTransient ? LM-best_level : best_level);*/ /* metric is in Q1 to be able to select the mid-point (-0.5) for narrower bands */ if (isTransient)
metric[i] = 2*best_level; else
metric[i] = -2*best_level; /* For bands that can't be split to -1, set the metric to the half-way point to avoid
biasing the decision */ if (narrow && (metric[i]==0 || metric[i]==-2*LM))
metric[i]-=1; /*printf("%d ", metric[i]/2 + (!isTransient)*LM);*/
} /*printf("\n");*/ /* Search for the optimal tf resolution, including tf_select */
tf_select = 0; for (sel=0;sel<2;sel++)
{
cost0 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*sel+0]);
cost1 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*sel+1]) + (isTransient ? 0 : lambda); for (i=1;i<len;i++)
{ int curr0, curr1;
curr0 = IMIN(cost0, cost1 + lambda);
curr1 = IMIN(cost0 + lambda, cost1);
cost0 = curr0 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+0]);
cost1 = curr1 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+1]);
}
cost0 = IMIN(cost0, cost1);
selcost[sel]=cost0;
} /* For now, we're conservative and only allow tf_select=1 for transients.
* If tests confirm it's useful for non-transients, we could allow it. */ if (selcost[1]<selcost[0] && isTransient)
tf_select=1;
cost0 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*tf_select+0]);
cost1 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*tf_select+1]) + (isTransient ? 0 : lambda); /* Viterbi forward pass */ for (i=1;i<len;i++)
{ int curr0, curr1; int from0, from1;
staticint stereo_analysis(const CELTMode *m, const celt_norm *X, int LM, int N0)
{ int i; int thetas;
opus_val32 sumLR = EPSILON, sumMS = EPSILON;
/* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */ for (i=0;i<13;i++)
{ int j; for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++)
{
opus_val32 L, R, M, S; /* We cast to 32-bit first because of the -32768 case */
L = SHR32(X[j], NORM_SHIFT-14);
R = SHR32(X[N0+j], NORM_SHIFT-14);
M = ADD32(L, R);
S = SUB32(L, R);
sumLR = ADD32(sumLR, ADD32(ABS32(L), ABS32(R)));
sumMS = ADD32(sumMS, ADD32(ABS32(M), ABS32(S)));
}
}
sumMS = MULT16_32_Q15(QCONST16(0.707107f, 15), sumMS);
thetas = 13; /* We don't need thetas for lower bands with LM<=1 */ if (LM<=1)
thetas -= 8; return MULT16_32_Q15((m->eBands[13]<<(LM+1))+thetas, sumMS)
> MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR);
}
static celt_glog dynalloc_analysis(const celt_glog *bandLogE, const celt_glog *bandLogE2, const celt_glog *oldBandE, int nbEBands, int start, int end, int C, int *offsets, int lsb_depth, const opus_int16 *logN, int isTransient, int vbr, int constrained_vbr, const opus_int16 *eBands, int LM, int effectiveBytes, opus_int32 *tot_boost_, int lfe, celt_glog *surround_dynalloc,
AnalysisInfo *analysis, int *importance, int *spread_weight, opus_val16 tone_freq, opus_val32 toneishness
ARG_QEXT(int qext_scale))
{ int i, c;
opus_int32 tot_boost=0;
celt_glog maxDepth;
VARDECL(celt_glog, follower);
VARDECL(celt_glog, noise_floor);
VARDECL(celt_glog, bandLogE3);
SAVE_STACK;
ALLOC(follower, C*nbEBands, celt_glog);
ALLOC(noise_floor, C*nbEBands, celt_glog);
ALLOC(bandLogE3, nbEBands, celt_glog);
OPUS_CLEAR(offsets, nbEBands); /* Dynamic allocation code */
maxDepth=-GCONST(31.9f); for (i=0;i<end;i++)
{ /* Noise floor must take into account eMeans, the depth, the width of the bands
and the preemphasis filter (approx. square of bark band ID) */
noise_floor[i] = GCONST(0.0625f)*logN[i]
+GCONST(.5f)+SHL32(9-lsb_depth,DB_SHIFT)-SHL32(eMeans[i],DB_SHIFT-4)
+GCONST(.0062f)*(i+5)*(i+5);
}
c=0;do
{ for (i=0;i<end;i++)
maxDepth = MAXG(maxDepth, bandLogE[c*nbEBands+i]-noise_floor[i]);
} while (++c<C);
{ /* Compute a really simple masking model to avoid taking into account completely masked
bands when computing the spreading decision. */
VARDECL(celt_glog, mask);
VARDECL(celt_glog, sig);
ALLOC(mask, nbEBands, celt_glog);
ALLOC(sig, nbEBands, celt_glog); for (i=0;i<end;i++)
mask[i] = bandLogE[i]-noise_floor[i]; if (C==2)
{ for (i=0;i<end;i++)
mask[i] = MAXG(mask[i], bandLogE[nbEBands+i]-noise_floor[i]);
}
OPUS_COPY(sig, mask, end); for (i=1;i<end;i++)
mask[i] = MAXG(mask[i], mask[i-1] - GCONST(2.f)); for (i=end-2;i>=0;i--)
mask[i] = MAXG(mask[i], mask[i+1] - GCONST(3.f)); for (i=0;i<end;i++)
{ /* Compute SMR: Mask is never more than 72 dB below the peak and never below the noise floor.*/
celt_glog smr = sig[i]-MAXG(MAXG(0, maxDepth-GCONST(12.f)), mask[i]); /* Clamp SMR to make sure we're not shifting by something negative or too large. */ #ifdef FIXED_POINT /* FIXME: Use PSHR16() instead */ int shift = -PSHR32(MAXG(-GCONST(5.f), MING(0, smr)), DB_SHIFT); #else int shift = IMIN(5, IMAX(0, -(int)floor(.5f + smr))); #endif
spread_weight[i] = 32 >> shift;
} /*for (i=0;i<end;i++) printf("%d",spread_weight[i]);
printf("\n");*/
} /* Make sure that dynamic allocation can't make us bust the budget. Weenablethefeaturestartingat24kb/sfor20-msframes
and 96 kb/s for 2.5 ms frames. */ if (effectiveBytes >= (30 + 5*LM) && !lfe)
{ int last=0;
c=0;do
{
celt_glog offset;
celt_glog tmp;
celt_glog *f;
OPUS_COPY(bandLogE3, &bandLogE2[c*nbEBands], end); if (LM==0) { /* For 2.5 ms frames, the first 8 bands have just one bin, so the energyishighlyunreliable(highvariance).Forthatreason, wetakethemaxwiththepreviousenergysothatatleast2bins
are getting used. */ for (i=0;i<IMIN(8,end);i++) bandLogE3[i] = MAXG(bandLogE2[c*nbEBands+i], oldBandE[c*nbEBands+i]);
}
f = &follower[c*nbEBands];
f[0] = bandLogE3[0]; for (i=1;i<end;i++)
{ /* The last band to be at least 3 dB higher than the previous one isthelastwe'llconsider.Otherwise,werunintoproblemson
bandlimited signals. */ if (bandLogE3[i] > bandLogE3[i-1]+GCONST(.5f))
last=i;
f[i] = MING(f[i-1]+GCONST(1.5f), bandLogE3[i]);
} for (i=last-1;i>=0;i--)
f[i] = MING(f[i], MING(f[i+1]+GCONST(2.f), bandLogE3[i]));
/* Combine with a median filter to avoid dynalloc triggering unnecessarily. The"offset"valuecontrolshowconservativeweare--ahigheroffset
reduces the impact of the median filter and makes dynalloc use more bits. */
offset = GCONST(1.f); for (i=2;i<end-2;i++)
f[i] = MAXG(f[i], median_of_5(&bandLogE3[i-2])-offset);
tmp = median_of_3(&bandLogE3[0])-offset;
f[0] = MAXG(f[0], tmp);
f[1] = MAXG(f[1], tmp);
tmp = median_of_3(&bandLogE3[end-3])-offset;
f[end-2] = MAXG(f[end-2], tmp);
f[end-1] = MAXG(f[end-1], tmp);
for (i=0;i<end;i++)
f[i] = MAXG(f[i], noise_floor[i]);
} while (++c<C); if (C==2)
{ for (i=start;i<end;i++)
{ /* Consider 24 dB "cross-talk" */
follower[nbEBands+i] = MAXG(follower[nbEBands+i], follower[ i]-GCONST(4.f));
follower[ i] = MAXG(follower[ i], follower[nbEBands+i]-GCONST(4.f));
follower[i] = HALF32(MAXG(0, bandLogE[i]-follower[i]) + MAXG(0, bandLogE[nbEBands+i]-follower[nbEBands+i]));
}
} else { for (i=start;i<end;i++)
{
follower[i] = MAXG(0, bandLogE[i]-follower[i]);
}
} for (i=start;i<end;i++)
follower[i] = MAXG(follower[i], surround_dynalloc[i]); for (i=start;i<end;i++)
{ #ifdef FIXED_POINT
importance[i] = PSHR32(13*celt_exp2_db(MING(follower[i], GCONST(4.f))), 16); #else
importance[i] = (int)floor(.5f+13*celt_exp2_db(MING(follower[i], GCONST(4.f)))); #endif
} /* For non-transient CBR/CVBR frames, halve the dynalloc contribution */ if ((!vbr || constrained_vbr)&&!isTransient)
{ for (i=start;i<end;i++)
follower[i] = HALF32(follower[i]);
} for (i=start;i<end;i++)
{ if (i<8)
follower[i] *= 2; if (i>=12)
follower[i] = HALF32(follower[i]);
} /* Compensate for Opus' under-allocation on tones. */ if (toneishness > QCONST32(.98f, 29)) { #ifdef FIXED_POINT int freq_bin = PSHR32(QEXT_SCALE((opus_val32)tone_freq)*QCONST16(120/M_PI, 9), 13+9); #else int freq_bin = (int)floor(.5 + QEXT_SCALE(tone_freq)*120/M_PI); #endif for (i=start;i<end;i++) { if (freq_bin >= eBands[i] && freq_bin <= eBands[i+1]) follower[i] += GCONST(2.f); if (freq_bin >= eBands[i]-1 && freq_bin <= eBands[i+1]+1) follower[i] += GCONST(1.f); if (freq_bin >= eBands[i]-2 && freq_bin <= eBands[i+1]+2) follower[i] += GCONST(1.f); if (freq_bin >= eBands[i]-3 && freq_bin <= eBands[i+1]+3) follower[i] += GCONST(.5f);
} if (freq_bin >= eBands[end]) {
follower[end-1] += GCONST(2.f);
follower[end-2] += GCONST(1.f);
}
} #ifdef DISABLE_FLOAT_API
(void)analysis; #else if (analysis->valid)
{ for (i=start;i<IMIN(LEAK_BANDS, end);i++)
follower[i] = follower[i] + GCONST(1.f/64.f)*analysis->leak_boost[i];
} #endif if (effectiveBytes>320) follower[0] += MIN32(GCONST(1.5f), GCONST(1e-3f)*(effectiveBytes-320)); for (i=start;i<end;i++)
{ int width; int boost; int boost_bits;
#ifdef FIXED_POINT void normalize_tone_input(opus_val16 *x, int len) {
opus_val32 ac0=len; int i; int shift; for (i=0;i<len;i++) {
ac0 = ADD32(ac0, SHR32(MULT16_16(x[i], x[i]), 10));
}
shift = 5 - (28-celt_ilog2(ac0))/2; if (shift > 0) { for (i=0;i<len;i++) {
x[i] = PSHR32(x[i], shift);
}
}
} int acos_approx(opus_val32 x) {
opus_val16 x14;
opus_val32 tmp; int flip = x<0;
x = abs(x);
x14 = x>>15;
tmp = (762*x14>>14)-3308;
tmp = (tmp*x14>>14)+25726;
tmp = tmp*celt_sqrt(IMAX(0, (1<<30) - (x<<1)))>>16; if (flip) tmp = 25736 - tmp; return tmp;
} #endif
/* Compute the LPC coefficients using a least-squares fit for both forward and backward prediction. */ staticint tone_lpc(const opus_val16 *x, int len, int delay, opus_val32 *lpc) { int i;
opus_val32 r00=0, r01=0, r11=0, r02=0, r12=0, r22=0;
opus_val32 edges;
opus_val32 num0, num1, den;
celt_assert(len > 2*delay); /* Compute correlations as if using the forward prediction covariance method. */ for (i=0;i<len-2*delay;i++) {
r00 += MULT16_16(x[i],x[i]);
r01 += MULT16_16(x[i],x[i+delay]);
r02 += MULT16_16(x[i],x[i+2*delay]);
}
edges = 0; for (i=0;i<delay;i++) edges += MULT16_16(x[len+i-2*delay],x[len+i-2*delay]) - MULT16_16(x[i],x[i]);
r11 = r00+edges;
edges = 0; for (i=0;i<delay;i++) edges += MULT16_16(x[len+i-delay],x[len+i-delay]) - MULT16_16(x[i+delay],x[i+delay]);
r22 = r11+edges;
edges = 0; for (i=0;i<delay;i++) edges += MULT16_16(x[len+i-2*delay],x[len+i-delay]) - MULT16_16(x[i],x[i+delay]);
r12 = r01+edges; /* Reverse and sum to get the backward contribution. */
{
opus_val32 R00, R01, R11, R02, R12, R22;
R00 = r00 + r22;
R01 = r01 + r12;
R11 = 2*r11;
R02 = 2*r02;
R12 = r12 + r01;
R22 = r00 + r22;
r00 = R00;
r01 = R01;
r11 = R11;
r02 = R02;
r12 = R12;
r22 = R22;
} /* Solve A*x=b, where A=[r00, r01; r01, r11] and b=[r02; r12]. */
den = MULT32_32_Q31(r00,r11) - MULT32_32_Q31(r01,r01); #ifdef FIXED_POINT if (den <= SHR32(MULT32_32_Q31(r00,r11), 10)) return1; #else if (den < .001f*MULT32_32_Q31(r00,r11)) return1; #endif
num1 = MULT32_32_Q31(r02,r11) - MULT32_32_Q31(r01,r12); if (num1 >= den) lpc[1] = QCONST32(1.f, 29); elseif (num1 <= -den) lpc[1] = -QCONST32(1.f, 29); else lpc[1] = frac_div32_q29(num1, den);
num0 = MULT32_32_Q31(r00,r12) - MULT32_32_Q31(r02,r01); if (HALF32(num0) >= den) lpc[0] = QCONST32(1.999999f, 29); elseif (HALF32(num0) <= -den) lpc[0] = -QCONST32(1.999999f, 29); else lpc[0] = frac_div32_q29(num0, den); /*printf("%f %f\n", lpc[0], lpc[1]);*/ return0;
}
/* Detects pure of nearly pure tones so we can prevent them from causing problems with the encoder. */ static opus_val16 tone_detect(const celt_sig *in, int CC, int N, opus_val32 *toneishness, opus_int32 Fs) { int i; int delay = 1; int fail;
opus_val32 lpc[2];
opus_val16 freq;
VARDECL(opus_val16, x);
SAVE_STACK;
ALLOC(x, N, opus_val16); /* Shift by SIG_SHIFT+2 (+3 for stereo) to account for HF gain of the preemphasis filter. */ if (CC==2) { for (i=0;i<N;i++) x[i] = PSHR32(ADD32(SHR32(in[i], 1), SHR32(in[i+N], 1)), SIG_SHIFT+2);
} else { for (i=0;i<N;i++) x[i] = PSHR32(in[i], SIG_SHIFT+2);
} #ifdef FIXED_POINT
normalize_tone_input(x, N); #endif
fail = tone_lpc(x, N, delay, lpc); /* If our LPC filter resonates too close to DC, retry the analysis with down-sampling. */ while (delay <= Fs/3000 && (fail || (lpc[0] > QCONST32(1.f, 29) && lpc[1] < 0))) {
delay *= 2;
fail = tone_lpc(x, N, delay, lpc);
} /* Check that our filter has complex roots. */ if (!fail && MULT32_32_Q31(lpc[0],lpc[0]) + MULT32_32_Q31(QCONST32(3.999999, 29), lpc[1]) < 0) { /* Squared radius of the poles. */
*toneishness = -lpc[1]; #ifdef FIXED_POINT
freq = (acos_approx(lpc[0]>>1)+delay/2)/delay; #else
freq = acos(.5f*lpc[0])/delay; #endif
} else {
freq = -1;
*toneishness=0;
} /*printf("%f %f %f %f\n", freq, lpc[0], lpc[1], *toneishness);*/
RESTORE_STACK; return freq;
}
staticint run_prefilter(CELTEncoder *st, celt_sig *in, celt_sig *prefilter_mem, int CC, int N, int prefilter_tapset, int *pitch, opus_val16 *gain, int *qgain, int enabled, int complexity, opus_val16 tf_estimate, int nbAvailableBytes, AnalysisInfo *analysis, opus_val16 tone_freq, opus_val32 toneishness ARG_QEXT(int qext_scale))
{ int c;
VARDECL(celt_sig, _pre);
celt_sig *pre[2]; const CELTMode *mode; int pitch_index;
opus_val16 gain1;
opus_val16 pf_threshold; int pf_on; int qg; int overlap; int min_period, max_period;
opus_val32 before[2]={0}, after[2]={0}; int cancel_pitch=0;
SAVE_STACK;
c=0; do {
OPUS_COPY(pre[c], prefilter_mem+c*max_period, max_period);
OPUS_COPY(pre[c]+max_period, in+c*(N+overlap)+overlap, N);
} while (++c<CC);
/* If we detect that the signal is dominated by a single tone, don't rely on the standard pitch
estimator, as it can become unreliable. */ if (enabled && toneishness > QCONST32(.99f, 29)) { int multiple=1; /* Using aliased version of the postfilter above 24 kHz.
First value is purposely slightly above pi to avoid triggering for Fs=48kHz. */ if (QEXT_SCALE(tone_freq) >= QCONST16(3.1416f, 13)) tone_freq = QCONST16(3.141593f, 13) - tone_freq; /* If the pitch is too high for our post-filter, apply pitch doubling until
we can get something that fits (not ideal, but better than nothing). */ while (QEXT_SCALE(tone_freq) >= multiple*QCONST16(0.39f, 13)) multiple++; if (QEXT_SCALE(tone_freq) > QCONST16(0.006148f, 13)) { #ifdef FIXED_POINT
pitch_index = IMIN((51472*multiple+QEXT_SCALE(tone_freq)/2)/QEXT_SCALE(tone_freq), COMBFILTER_MAXPERIOD-2); #else
pitch_index = IMIN((int)floor(.5+2.f*M_PI*multiple/QEXT_SCALE(tone_freq)), COMBFILTER_MAXPERIOD-2); #endif
} else { /* If the pitch is too low, using a very high pitch will actually give us an improvement duetotheDCcomponentofthefilterthatwillbeclosetoourtone.Again,notideal,
but if we only have a single tone, it's better than nothing. */
pitch_index = COMBFILTER_MINPERIOD;
}
gain1 = QCONST16(.75f, 15);
} elseif (enabled && complexity >= 5) {
VARDECL(opus_val16, pitch_buf);
ALLOC(pitch_buf, (max_period+N)>>1, opus_val16);
pitch_downsample(pre, pitch_buf, (max_period+N)>>1, CC, 2, st->arch); /* Don't search for the fir last 1.5 octave of the range because
there's too many false-positives due to short-term correlation */
pitch_search(pitch_buf+(max_period>>1), pitch_buf, N,
max_period-3*min_period, &pitch_index,
st->arch);
pitch_index = max_period-pitch_index;
gain1 = remove_doubling(pitch_buf, max_period, min_period,
N, &pitch_index, st->prefilter_period, st->prefilter_gain, st->arch); if (pitch_index > max_period-QEXT_SCALE(2))
pitch_index = max_period-QEXT_SCALE(2); #ifdef ENABLE_QEXT
pitch_index /= qext_scale; #endif
gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1); /*printf("%d %d %f %f\n", pitch_change, pitch_index, gain1, st->analysis.tonality);*/ if (st->loss_rate>2)
gain1 = HALF32(gain1); if (st->loss_rate>4)
gain1 = HALF32(gain1); if (st->loss_rate>8)
gain1 = 0;
} else {
gain1 = 0;
pitch_index = COMBFILTER_MINPERIOD;
} #ifndef DISABLE_FLOAT_API if (analysis->valid)
gain1 = (opus_val16)(gain1 * analysis->max_pitch_ratio); #else
(void)analysis; #endif /* Gain threshold for enabling the prefilter/postfilter */
pf_threshold = QCONST16(.2f,15);
/* Adjusting the threshold based on rate and continuity */ if (abs(pitch_index-st->prefilter_period)*10>pitch_index)
{
pf_threshold += QCONST16(.2f,15); /* Completely disable the prefilter on strong transients without continuity. */ if (tf_estimate > QCONST16(.98f, 14))
gain1 = 0;
} if (nbAvailableBytes<25)
pf_threshold += QCONST16(.1f,15); if (nbAvailableBytes<35)
pf_threshold += QCONST16(.1f,15); if (st->prefilter_gain > QCONST16(.4f,15))
pf_threshold -= QCONST16(.1f,15); if (st->prefilter_gain > QCONST16(.55f,15))
pf_threshold -= QCONST16(.1f,15);
/* Hard threshold at 0.2 */
pf_threshold = MAX16(pf_threshold, QCONST16(.2f,15)); if (gain1<pf_threshold)
{
gain1 = 0;
pf_on = 0;
qg = 0;
} else { /*This block is not gated by a total bits check only because
of the nbAvailableBytes check above.*/ if (ABS16(gain1-st->prefilter_gain)<QCONST16(.1f,15))
gain1=st->prefilter_gain;
staticint compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32 base_target, int LM, opus_int32 bitrate, int lastCodedBands, int C, int intensity, int constrained_vbr, opus_val16 stereo_saving, int tot_boost,
opus_val16 tf_estimate, int pitch_change, celt_glog maxDepth, int lfe, int has_surround_mask, celt_glog surround_masking,
celt_glog temporal_vbr ARG_QEXT(int enable_qext))
{ /* The target rate in 8th bits per frame */
opus_int32 target; int coded_bins; int coded_bands;
opus_val16 tf_calibration; int nbEBands; const opus_int16 *eBands;
/* Make VBR less aggressive for constrained VBR because we can't keep a higher bitrate
for long. Needs tuning. */ if ((!has_surround_mask||lfe) && constrained_vbr)
{
target = base_target + (opus_int32)MULT16_32_Q15(QCONST16(0.67f, 15), target-base_target);
}
frame_size *= st->upsample; for (LM=0;LM<=mode->maxLM;LM++) if (mode->shortMdctSize<<LM==frame_size) break; if (LM>mode->maxLM)
{
RESTORE_STACK; return OPUS_BAD_ARG;
}
M=1<<LM;
N = M*mode->shortMdctSize;
#ifdefined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) if (st->signalling && enc==NULL)
{ int tmp = (mode->effEBands-end)>>1;
end = st->end = IMAX(1, mode->effEBands-tmp);
compressed[0] = tmp<<5;
compressed[0] |= LM<<3;
compressed[0] |= (C==2)<<2; /* Convert "standard mode" to Opus header */ # ifndef ENABLE_QEXT if (mode->Fs==48000 && mode->shortMdctSize==120) # endif
{ int c0 = toOpus(compressed[0]); if (c0<0)
{
RESTORE_STACK; return OPUS_BAD_ARG;
}
compressed[0] = c0;
}
compressed++;
nbCompressedBytes--;
} #else
celt_assert(st->signalling==0); #endif
/* Can't produce more than 1275 output bytes for the main payload, plus any QEXT extra data. */
nbCompressedBytes = IMIN(nbCompressedBytes,packet_size_cap);
if (enc==NULL)
{
ec_enc_init(&_enc, compressed, nbCompressedBytes);
enc = &_enc;
}
if (vbr_rate>0)
{ /* Computes the max bit-rate allowed in VBR mode to avoid violating the targetrateandbuffering. Wemustdothisupfrontsothatbust-preventionlogictriggers
correctly if we don't have enough bits. */ if (st->constrained_vbr)
{
opus_int32 vbr_bound;
opus_int32 max_allowed; /* We could use any multiple of vbr_rate as bound (depending on the delay). Thisisclampedtoensureweuseatleasttwobytesiftheencoder
was entirely empty, but to allow 0 in hybrid mode. */
vbr_bound = vbr_rate;
max_allowed = IMIN(IMAX(tell==1?2:0,
(vbr_rate+vbr_bound-st->vbr_reservoir)>>(BITRES+3)),
nbAvailableBytes); if(max_allowed < nbAvailableBytes)
{
nbCompressedBytes = nbFilledBytes+max_allowed;
nbAvailableBytes = max_allowed;
ec_enc_shrink(enc, nbCompressedBytes);
}
}
}
total_bits = nbCompressedBytes*8;
effEnd = end; if (effEnd > mode->effEBands)
effEnd = mode->effEBands;
ALLOC(in, CC*(N+overlap), celt_sig);
sample_max=MAX32(st->overlap_max, celt_maxabs_res(pcm, CC*(N-overlap)/st->upsample));
st->overlap_max=celt_maxabs_res(pcm+CC*(N-overlap)/st->upsample, CC*overlap/st->upsample);
sample_max=MAX32(sample_max, st->overlap_max); #ifdef FIXED_POINT
silence = (sample_max==0); #else
silence = (sample_max <= (opus_val16)1/(1<<st->lsb_depth)); #endif #ifdef FUZZING if ((rand()&0x3F)==0)
silence = 1; #endif if (tell==1)
ec_enc_bit_logp(enc, silence, 15); else
silence=0; if (silence)
{ /*In VBR mode there is no need to send more than the minimum. */ if (vbr_rate>0)
{
effectiveBytes=nbCompressedBytes=IMIN(nbCompressedBytes, nbFilledBytes+2);
total_bits=nbCompressedBytes*8;
nbAvailableBytes=2;
ec_enc_shrink(enc, nbCompressedBytes);
} #ifdef ENABLE_QEXT elseif (st->enable_qext) {
nbCompressedBytes = IMIN(nbCompressedBytes, 1275);
nbAvailableBytes = nbCompressedBytes - nbFilledBytes;
total_bits = nbCompressedBytes*8;
ec_enc_shrink(enc, nbCompressedBytes);
} #endif /* Pretend we've filled all the remaining bits with zeros
(that's what the initialiser did anyway) */
tell = nbCompressedBytes*8;
enc->nbits_total+=tell-ec_tell(enc);
}
c=0; do { int need_clip=0; #ifdef FIXED_POINT
need_clip = st->clip && sample_max>65536<<RES_SHIFT; #else
need_clip = st->clip && sample_max>65536.f; #endif
celt_preemphasis(pcm+c, in+c*(N+overlap)+overlap, N, CC, st->upsample,
mode->preemph, st->preemph_memE+c, need_clip);
OPUS_COPY(in+c*(N+overlap), &prefilter_mem[(1+c)*QEXT_SCALE(COMBFILTER_MAXPERIOD)-overlap], overlap);
} while (++c<CC);
tone_freq = tone_detect(in, CC, N+overlap, &toneishness, mode->Fs);
isTransient = 0;
shortBlocks = 0; if (st->complexity >= 1 && !st->lfe)
{ /* Reduces the likelihood of energy instability on fricatives at low bitrate inhybridmode.Itseemslikewestillwanttohaverealtransientsonvowels
though (small SILK quantization offset value). */ int allow_weak_transients = hybrid && effectiveBytes<15 && st->silk_info.signalType != 2;
isTransient = transient_analysis(in, N+overlap, CC,
&tf_estimate, &tf_chan, allow_weak_transients, &weak_transient, tone_freq, toneishness);
}
toneishness = MIN32(toneishness, QCONST32(1.f, 29)-SHL32(tf_estimate, 15)); /* Find pitch period and gain */
{ int enabled; int qg;
enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && !hybrid && !silence && tell+16<=total_bits && !st->disable_pf;
prefilter_tapset = st->tapset_decision;
pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, st->complexity, tf_estimate, nbAvailableBytes, &st->analysis, tone_freq, toneishness ARG_QEXT(qext_scale)); if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3)
&& (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period))
pitch_change = 1; if (pf_on==0)
{ if(!hybrid && tell+16<=total_bits)
ec_enc_bit_logp(enc, 0, 1);
} else { /*This block is not gated by a total bits check only because
of the nbAvailableBytes check above.*/ int octave;
ec_enc_bit_logp(enc, 1, 1);
pitch_index += 1;
octave = EC_ILOG(pitch_index)-5;
ec_enc_uint(enc, octave, 6);
ec_enc_bits(enc, pitch_index-(16<<octave), 4+octave);
pitch_index -= 1;
ec_enc_bits(enc, qg, 3);
ec_enc_icdf(enc, prefilter_tapset, tapset_icdf, 2);
}
} if (LM>0 && ec_tell(enc)+3<=total_bits)
{ if (isTransient)
shortBlocks = M;
} else {
isTransient = 0;
transient_got_disabled=1;
}
compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch); /* This should catch any NaN in the CELT input. Since we're not supposed to see any (they're filtered
at the Opus layer), just abort. */
celt_assert(!celt_isnan(freq[0]) && (C==1 || !celt_isnan(freq[N]))); if (CC==2&&C==1)
tf_chan = 0;
compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
ALLOC(surround_dynalloc, C*nbEBands, celt_glog);
OPUS_CLEAR(surround_dynalloc, end); /* This computes how much masking takes place between surround channels */ if (!hybrid&&st->energy_mask&&!st->lfe)
{ int mask_end; int midband; int count_dynalloc;
opus_val32 mask_avg=0;
opus_val32 diff=0; int count=0;
mask_end = IMAX(2,st->lastCodedBands); for (c=0;c<C;c++)
{ for(i=0;i<mask_end;i++)
{
celt_glog mask;
opus_val16 mask16;
mask = MAXG(MING(st->energy_mask[nbEBands*c+i],
GCONST(.25f)), -GCONST(2.0f)); if (mask > 0)
mask = HALF32(mask);
mask16 = SHR32(mask, DB_SHIFT-10);
mask_avg += MULT16_16(mask16, eBands[i+1]-eBands[i]);
count += eBands[i+1]-eBands[i];
diff += MULT16_16(mask16, 1+2*i-mask_end);
}
}
celt_assert(count>0);
mask_avg = SHL32(DIV32_16(mask_avg,count), DB_SHIFT-10);
mask_avg += GCONST(.2f);
diff = SHL32(diff*6/(C*(mask_end-1)*(mask_end+1)*mask_end), DB_SHIFT-10); /* Again, being conservative */
diff = HALF32(diff);
diff = MAX32(MIN32(diff, GCONST(.031f)), -GCONST(.031f)); /* Find the band that's in the middle of the coded spectrum */ for (midband=0;eBands[midband+1] < eBands[mask_end]/2;midband++);
count_dynalloc=0; for(i=0;i<mask_end;i++)
{
opus_val32 lin;
celt_glog unmask;
lin = mask_avg + diff*(i-midband); if (C==2)
unmask = MAXG(st->energy_mask[i], st->energy_mask[nbEBands+i]); else
unmask = st->energy_mask[i];
unmask = MING(unmask, GCONST(.0f));
unmask -= lin; if (unmask > GCONST(.25f))
{
surround_dynalloc[i] = unmask - GCONST(.25f);
count_dynalloc++;
}
} if (count_dynalloc>=3)
{ /* If we need dynalloc in many bands, it's probably because our
initial masking rate was too low. */
mask_avg += GCONST(.25f); if (mask_avg>0)
{ /* Something went really wrong in the original calculations,
disabling masking. */
mask_avg = 0;
diff = 0;
OPUS_CLEAR(surround_dynalloc, mask_end);
} else { for(i=0;i<mask_end;i++)
surround_dynalloc[i] = MAXG(0, surround_dynalloc[i]-GCONST(.25f));
}
}
mask_avg += GCONST(.2f); /* Convert to 1/64th units used for the trim */
surround_trim = 64*diff; /*printf("%d %d ", mask_avg, surround_trim);*/
surround_masking = mask_avg;
} /* Temporal VBR (but not for LFE) */ if (!st->lfe)
{
celt_glog follow=-QCONST32(10.0f, DB_SHIFT-5);
opus_val32 frame_avg=0;
celt_glog offset = shortBlocks?HALF32(SHL32(LM, DB_SHIFT-5)):0; for(i=start;i<end;i++)
{
follow = MAXG(follow-QCONST32(1.0f, DB_SHIFT-5), SHR32(bandLogE[i],5)-offset); if (C==2)
follow = MAXG(follow, SHR32(bandLogE[i+nbEBands],5)-offset);
frame_avg += follow;
}
frame_avg /= (end-start);
temporal_vbr = SUB32(SHL32(frame_avg, 5),st->spec_avg);
temporal_vbr = MING(GCONST(3.f), MAXG(-GCONST(1.5f), temporal_vbr));
st->spec_avg += MULT16_32_Q15(QCONST16(.02f, 15), temporal_vbr);
} /*for (i=0;i<21;i++) printf("%f",bandLogE[i]);
printf("\n");*/
if (!secondMdct)
{
OPUS_COPY(bandLogE2, bandLogE, C*nbEBands);
}
/* Last chance to catch any transient we might have missed in the
time-domain analysis */ if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe && !hybrid)
{ if (patch_transient_decision(bandLogE, oldBandE, nbEBands, start, end, C))
{
isTransient = 1;
shortBlocks = M;
compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch);
compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
amp2Log2(mode, effEnd, end, bandE, bandLogE, C); /* Compensate for the scaling of short vs long mdcts */ for (c=0;c<C;c++)
{ for (i=0;i<end;i++)
bandLogE2[nbEBands*c+i] += HALF32(SHL32(LM, DB_SHIFT));
}
tf_estimate = QCONST16(.2f,14);
}
}
if (LM>0 && ec_tell(enc)+3<=total_bits)
ec_enc_bit_logp(enc, isTransient, 3);
ALLOC(tf_res, nbEBands, int); /* Disable variable tf resolution for hybrid and at very low bitrate */ if (enable_tf_analysis)
{ int lambda;
lambda = IMAX(80, 20480/effectiveBytes + 2);
tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, tf_estimate, tf_chan, importance); for (i=effEnd;i<end;i++)
tf_res[i] = tf_res[effEnd-1];
} elseif (hybrid && weak_transient)
{ /* For weak transients, we rely on the fact that improving time resolution using TFonalongwindowisimperfectandwillnotresultinanenergycollapseat
low bitrate. */ for (i=0;i<end;i++)
tf_res[i] = 1;
tf_select=0;
} elseif (hybrid && effectiveBytes<15 && st->silk_info.signalType != 2)
{ /* For low bitrate hybrid, we force temporal resolution to 5 ms rather than 2.5 ms. */ for (i=0;i<end;i++)
tf_res[i] = 0;
tf_select=isTransient;
} else { for (i=0;i<end;i++)
tf_res[i] = isTransient;
tf_select=0;
}
ALLOC(error, C*nbEBands, celt_glog);
c=0; do { for (i=start;i<end;i++)
{ /* When the energy is stable, slightly bias energy quantization towards thepreviouserrortomakethegainmorestable(aconstantoffsetis
better than fluctuations). */ if (ABS32(SUB32(bandLogE[i+c*nbEBands], oldBandE[i+c*nbEBands])) < GCONST(2.f))
{
bandLogE[i+c*nbEBands] -= MULT16_32_Q15(QCONST16(0.25f, 15), energyError[i+c*nbEBands]);
}
}
} while (++c < C);
quant_coarse_energy(mode, start, end, effEnd, bandLogE,
oldBandE, total_bits, error, enc,
C, LM, nbAvailableBytes, st->force_intra,
&st->delayedIntra, st->complexity >= 4, st->loss_rate, st->lfe);
/* For LFE, everything interesting is in the first band */ if (st->lfe)
offsets[0] = IMIN(8, effectiveBytes/3);
ALLOC(cap, nbEBands, int);
init_caps(mode,cap,LM,C);
dynalloc_logp = 6;
total_bits<<=BITRES;
total_boost = 0;
tell = ec_tell_frac(enc); for (i=start;i<end;i++)
{ int width, quanta; int dynalloc_loop_logp; int boost; int j;
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; for (j = 0; tell+(dynalloc_loop_logp<<BITRES) < total_bits-total_boost
&& boost < cap[i]; j++)
{ int flag;
flag = j<offsets[i];
ec_enc_bit_logp(enc, flag, dynalloc_loop_logp);
tell = ec_tell_frac(enc); if (!flag) break;
boost += quanta;
total_boost += quanta;
dynalloc_loop_logp = 1;
} /* Making dynalloc more likely */ if (j)
dynalloc_logp = IMAX(2, dynalloc_logp-1);
offsets[i] = boost;
}
/* In VBR mode the frame size must not be reduced so much that it would resultintheencoderrunningoutofbits. Themarginof2bytesensuresthatnoneofthebust-preventionlogic
in the decoder will have triggered so far. */
min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2; /* Take into account the 37 bits we need to have left in the packet to signalaredundantframeinhybridmode.Creatingashorterpacketwould
create an entropy coder desync. */ if (hybrid)
min_allowed = IMAX(min_allowed, (tell0_frac+(37<<BITRES)+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)); /* Variable bitrate */ if (vbr_rate>0)
{
opus_val16 alpha;
opus_int32 delta; /* The target rate in 8th bits per frame */
opus_int32 target, base_target; int lm_diff = mode->maxLM - LM;
/* Don't attempt to use more than 510 kb/s, even for frames smaller than 20 ms.
The CELT allocator will just not be able to use more than that anyway. */
nbCompressedBytes = IMIN(nbCompressedBytes,packet_size_cap>>(3-LM)); if (!hybrid)
{
base_target = vbr_rate - ((40*C+20)<<BITRES);
} else {
base_target = IMAX(0, vbr_rate - ((9*C+4)<<BITRES));
}
if (st->constrained_vbr)
base_target += (st->vbr_offset>>lm_diff);
if (!hybrid)
{
target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate,
st->lastCodedBands, C, st->intensity, st->constrained_vbr,
st->stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth,
st->lfe, st->energy_mask!=NULL, surround_masking,
temporal_vbr ARG_QEXT(st->enable_qext));
} else {
target = base_target; /* Tonal frames (offset<100) need more bits than noisy (offset>100) ones. */ if (st->silk_info.offset < 100) target += 12 << BITRES >> (3-LM); if (st->silk_info.offset > 100) target -= 18 << BITRES >> (3-LM); /* Boosting bitrate on transients and vowels with significant temporal
spikes. */
target += (opus_int32)MULT16_16_Q14(tf_estimate-QCONST16(.25f,14), (50<<BITRES)); /* If we have a strong transient, let's make sure it has enough bits to code
the first two bands, so that it can use folding rather than noise. */ if (tf_estimate > QCONST16(.7f,14))
target = IMAX(target, 50<<BITRES);
} /* The current offset is removed from the target and the space used
so far is added*/
target=target+tell;
/* By how much did we "miss" the target on that frame */
delta = target - vbr_rate;
target=nbAvailableBytes<<(BITRES+3);
/*If the frame is silent we don't adjust our drift, otherwise theencoderwillshoottoveryhighratesafterhittinga spanofsilence,butwedoallowthebitrestorefill. Thismeansthatwe'llundershootourtargetinCVBR/VBRmodes
on files with lots of silence. */ if(silence)
{
nbAvailableBytes = 2;
target = 2*8<<BITRES;
delta = 0;
}
if (st->vbr_count < 970)
{
st->vbr_count++;
alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16));
} else
alpha = QCONST16(.001f,15); /* How many bits have we used in excess of what we're allowed */ if (st->constrained_vbr)
st->vbr_reservoir += target - vbr_rate; /*printf ("%d\n", st->vbr_reservoir);*/
/* Compute the offset we need to apply in order to reach the target */ if (st->constrained_vbr)
{
st->vbr_drift += (opus_int32)MULT16_32_Q15(alpha,(delta*(1<<lm_diff))-st->vbr_offset-st->vbr_drift);
st->vbr_offset = -st->vbr_drift;
} /*printf ("%d\n", st->vbr_drift);*/
if (st->constrained_vbr && st->vbr_reservoir < 0)
{ /* We're under the min value -- increase rate */ int adjust = (-st->vbr_reservoir)/(8<<BITRES); /* Unless we're just coding silence */
nbAvailableBytes += silence?0:adjust;
st->vbr_reservoir = 0; /*printf ("+%d\n", adjust);*/
}
nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes); /*printf("%d\n", nbCompressedBytes*50*8);*/ /* This moves the raw bits to take into account the new compressed size */
ec_enc_shrink(enc, nbCompressedBytes);
} #ifdef ENABLE_QEXT if (st->enable_qext) { int new_compressedBytes; /* Don't give any bits for the first 80 kb/s per channel. Then 80% of the excess. */
opus_int32 offset = bitrate_to_bits(C*80000, mode->Fs, frame_size)/8;
qext_bytes = IMAX(nbCompressedBytes-1275, IMAX(0, (nbCompressedBytes-offset)*4/5)); if (qext_bytes > 20) {
opus_int32 target;
opus_val16 scale;
target = ((nbCompressedBytes-qext_bytes/3)*8<<BITRES); if (!vbr_rate) {
opus_val16 tf_estimate2;
target -= ((40*C+20)<<BITRES);
tf_estimate2 = MIN32(QCONST16(1.f, 14), 2*EXTEND32(tf_estimate));
target = compute_vbr(mode, &st->analysis, target, LM, equiv_rate,
st->lastCodedBands, C, st->intensity, st->constrained_vbr,
st->stereo_saving, tot_boost, tf_estimate2, pitch_change, maxDepth,
st->lfe, st->energy_mask!=NULL, surround_masking,
temporal_vbr ARG_QEXT(st->enable_qext));
target += tell;
}
scale = PSHR32(toneishness,14);
scale = Q15ONE - MULT16_16_Q15(scale, scale);
qext_bytes = IMAX(nbCompressedBytes-1275, IMAX(21, qext_bytes));
}
padding_len_bytes = (qext_bytes+253)/254;
qext_bytes = IMIN(qext_bytes, nbCompressedBytes-min_allowed-padding_len_bytes-1);
padding_len_bytes = (qext_bytes+253)/254; if (qext_bytes > 20) {
new_compressedBytes = nbCompressedBytes-qext_bytes-padding_len_bytes-1;
ec_enc_shrink(enc, new_compressedBytes); if (compressed == NULL) {
compressed = enc->buf;
}
compressed[-1] |= 0x03; /* Code 3 packet */
enc->buf += 1+padding_len_bytes;
OPUS_MOVE(compressed+1+padding_len_bytes, compressed, new_compressedBytes);
compressed[0] = 0x41; /* Set padding */ for (i=0;i<padding_len_bytes-1;i++) compressed[i+1] = 255;
compressed[padding_len_bytes] = qext_bytes%254 == 0 ? 254 : qext_bytes%254;
ext_payload = compressed+padding_len_bytes+1+new_compressedBytes;
ext_payload[0] = QEXT_EXTENSION_ID<<1;
ext_payload += 1;
qext_bytes -= 1;
OPUS_CLEAR(ext_payload, qext_bytes);
ec_enc_init(&ext_enc, ext_payload, qext_bytes);
nbCompressedBytes = new_compressedBytes; if (end == nbEBands && (mode->Fs == 48000 || mode->Fs == 96000) && (mode->shortMdctSize==120*qext_scale || mode->shortMdctSize==90*qext_scale)) {
compute_qext_mode(&qext_mode_struct, mode);
qext_mode = &qext_mode_struct;
qext_end = (qext_scale == 2) ? NB_QEXT_BANDS : 2;
ec_enc_bit_logp(&ext_enc, qext_end == NB_QEXT_BANDS, 1);
}
} else {
ec_enc_init(&ext_enc, NULL, 0);
qext_bytes = 0;
}
} else {
ec_enc_init(&ext_enc, NULL, 0);
} #endif
/* We reuse freq[] as scratch space for the de-emphasis */
deemphasis(out_mem, (opus_res*)pcm, N, CC, st->upsample, mode->preemph, st->preemph_memD, 0);
st->prefilter_period_old = st->prefilter_period;
st->prefilter_gain_old = st->prefilter_gain;
st->prefilter_tapset_old = st->prefilter_tapset;
} #endif
if (CC==2&&C==1) {
OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands);
}
if (!isTransient)
{
OPUS_COPY(oldLogE2, oldLogE, CC*nbEBands);
OPUS_COPY(oldLogE, oldBandE, CC*nbEBands);
} else { for (i=0;i<CC*nbEBands;i++)
oldLogE[i] = MING(oldLogE[i], 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<CC);
if (isTransient || transient_got_disabled)
st->consec_transient++; else
st->consec_transient=0;
st->rng = enc->rng;
/* If there's any room left (can only happen for very high rates),
it's already filled with zeros */
ec_enc_done(enc); #ifdef ENABLE_QEXT
ec_enc_done(&ext_enc); if (qext_bytes > 0)
nbCompressedBytes += padding_len_bytes+2+qext_bytes; if (qext_bytes) st->rng = st->rng ^ ext_enc.rng; if (ec_get_error(&ext_enc)) return OPUS_INTERNAL_ERROR; #endif #ifdefined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) if (st->signalling)
nbCompressedBytes++; #endif
RESTORE_STACK; if (ec_get_error(enc)) return OPUS_INTERNAL_ERROR; else return nbCompressedBytes;
}
int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
{
va_list ap;
va_start(ap, request); switch (request)
{ case OPUS_SET_COMPLEXITY_REQUEST:
{ int value = va_arg(ap, opus_int32); if (value<0 || value>10) goto bad_arg;
st->complexity = value;
} 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_PREDICTION_REQUEST:
{ int value = va_arg(ap, opus_int32); if (value<0 || value>2) goto bad_arg;
st->disable_pf = value<=1;
st->force_intra = value==0;
} break; case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
{ int value = va_arg(ap, opus_int32); if (value<0 || value>100) goto bad_arg;
st->loss_rate = value;
} break; case OPUS_SET_VBR_CONSTRAINT_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
st->constrained_vbr = value;
} break; case OPUS_SET_VBR_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
st->vbr = value;
} break; case OPUS_SET_BITRATE_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32); if (value<=500 && value!=OPUS_BITRATE_MAX) goto bad_arg;
value = IMIN(value, 750000*st->channels);
st->bitrate = 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 OPUS_SET_LSB_DEPTH_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32); if (value<8 || value>24) goto bad_arg;
st->lsb_depth=value;
} break; case OPUS_GET_LSB_DEPTH_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
*value=st->lsb_depth;
} 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; #ifdef ENABLE_QEXT case OPUS_SET_QEXT_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32); if(value<0 || value>1)
{ goto bad_arg;
}
st->enable_qext = value;
} break; case OPUS_GET_QEXT_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*); if (!value)
{ goto bad_arg;
}
*value = st->enable_qext;
} break; #endif case OPUS_RESET_STATE:
{ int i;
celt_glog *oldBandE, *oldLogE, *oldLogE2;
oldBandE = (celt_glog*)(st->in_mem+st->channels*(st->mode->overlap+QEXT_SCALE2(COMBFILTER_MAXPERIOD, st->qext_scale)));
oldLogE = oldBandE + st->channels*st->mode->nbEBands;
oldLogE2 = oldLogE + st->channels*st->mode->nbEBands;
OPUS_CLEAR((char*)&st->ENCODER_RESET_START,
opus_custom_encoder_get_size(st->mode, st->channels)-
((char*)&st->ENCODER_RESET_START - (char*)st)); for (i=0;i<st->channels*st->mode->nbEBands;i++)
oldLogE[i]=oldLogE2[i]=-GCONST(28.f);
st->vbr_offset = 0;
st->delayedIntra = 1;
st->spread_decision = SPREAD_NORMAL;
st->tonal_average = 256;
st->hf_average = 0;
st->tapset_decision = 0;
} break; #ifdefined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) case CELT_SET_INPUT_CLIPPING_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
st->clip = value;
} break; #endif case CELT_SET_SIGNALLING_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
st->signalling = value;
} break; case CELT_SET_ANALYSIS_REQUEST:
{
AnalysisInfo *info = va_arg(ap, AnalysisInfo *); if (info)
OPUS_COPY(&st->analysis, info, 1);
} break; case CELT_SET_SILK_INFO_REQUEST:
{
SILKInfo *info = va_arg(ap, SILKInfo *); if (info)
OPUS_COPY(&st->silk_info, info, 1);
} 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 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_LFE_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
st->lfe = value;
} break; case OPUS_SET_ENERGY_MASK_REQUEST:
{
celt_glog *value = va_arg(ap, celt_glog*);
st->energy_mask = value;
} 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.53Angebot
(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.