/* 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.
*/
/** Encoder state @brief Encoder state
*/ 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;
/* 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;
*weak_transient = 0; /* For lower bitrates, let's be more conservative and have a forward masking decay of 3.3 dB/ms. This avoids having to code transients at very low bitrate (mostly for hybrid), which can result in unstable energy and/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],SIG_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_val16 x2 = PSHR32(MULT16_16(tmp[2*i],tmp[2*i]) + MULT16_16(tmp[2*i+1],tmp[2*i+1]),16);
mean += x2; #ifdef FIXED_POINT /* FIXME: Use PSHR16() instead */
tmp[i] = mem0 + PSHR32(x2-mem0,forward_shift);
mem0 = tmp[i]; #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. This essentially corresponds to a bitrate-normalized temporal noise-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 before it does any damage later on. If these asserts are disabled (no hardening), then the table lookup a few lines below (id = ...) is likely to crash dur to an out-of-bounds read. DO NOT FIX
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; /* 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(opus_val16 *newE, opus_val16 *oldE, int nbEBands, int start, int end, int C)
{ int i, c;
opus_val32 mean_diff=0;
opus_val16 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] = MAX16(spread_old[i-1]-QCONST16(1.0f, DB_SHIFT), oldE[i]);
} else {
spread_old[start] = MAX16(oldE[start],oldE[start+nbEBands]); for (i=start+1;i<end;i++)
spread_old[i] = MAX16(spread_old[i-1]-QCONST16(1.0f, DB_SHIFT),
MAX16(oldE[i],oldE[i+nbEBands]));
} for (i=end-2;i>=start;i--)
spread_old[i] = MAX16(spread_old[i], spread_old[i+1]-QCONST16(1.0f, DB_SHIFT)); /* Compute mean increase */
c=0; do { for (i=IMAX(2,start);i<end-1;i++)
{
opus_val16 x1, x2;
x1 = MAX16(0, newE[i + c*nbEBands]);
x2 = MAX16(0, spread_old[i]);
mean_diff = ADD32(mean_diff, EXTEND32(MAX16(0, SUB16(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 > QCONST16(1.f, DB_SHIFT);
}
/** 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_val16 * 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++)
{
opus_val16 x;
x = SCALEIN(pcmp[CC*i]); /* Apply pre-emphasis */
inp[i] = SHL32(x, SIG_SHIFT) - m;
m = SHR32(MULT16_16(coef0, x), 15-SIG_SHIFT);
}
*mem = m; return;
}
Nu = N/upsample; if (upsample!=1)
{
OPUS_CLEAR(inp, N);
} for (i=0;i<Nu;i++)
inp[i*upsample] = SCALEIN(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]));
} #else
(void)clip; /* Avoids a warning about clip being unused. */ #endif #ifdef CUSTOM_MODES if (coef[1] != 0)
{
opus_val16 coef1 = coef[1];
opus_val16 coef2 = coef[2]; for (i=0;i<N;i++)
{
celt_sig x, tmp;
x = inp[i]; /* Apply pre-emphasis */
tmp = MULT16_16(coef2, x);
inp[i] = tmp + m;
m = MULT16_32_Q15(coef1, inp[i]) - MULT16_32_Q15(coef0, tmp);
}
} else #endif
{ for (i=0;i<N;i++)
{
opus_val16 x;
x = inp[i]; /* Apply pre-emphasis */
inp[i] = SHL32(x, SIG_SHIFT) - m;
m = SHR32(MULT16_16(coef0, x), 15-SIG_SHIFT);
}
}
*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(tmp[i])); /* 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 = EXTEND32(X[j]);
R = EXTEND32(X[N0+j]);
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 opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2, const opus_val16 *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, opus_val16 *surround_dynalloc,
AnalysisInfo *analysis, int *importance, int *spread_weight)
{ int i, c;
opus_int32 tot_boost=0;
opus_val16 maxDepth;
VARDECL(opus_val16, follower);
VARDECL(opus_val16, noise_floor);
VARDECL(opus_val16, bandLogE3);
SAVE_STACK;
ALLOC(follower, C*nbEBands, opus_val16);
ALLOC(noise_floor, C*nbEBands, opus_val16);
ALLOC(bandLogE3, nbEBands, opus_val16);
OPUS_CLEAR(offsets, nbEBands); /* Dynamic allocation code */
maxDepth=-QCONST16(31.9f, DB_SHIFT); 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] = MULT16_16(QCONST16(0.0625f, DB_SHIFT),logN[i])
+QCONST16(.5f,DB_SHIFT)+SHL16(9-lsb_depth,DB_SHIFT)-SHL16(eMeans[i],6)
+MULT16_16(QCONST16(.0062,DB_SHIFT),(i+5)*(i+5));
}
c=0;do
{ for (i=0;i<end;i++)
maxDepth = MAX16(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(opus_val16, mask);
VARDECL(opus_val16, sig);
ALLOC(mask, nbEBands, opus_val16);
ALLOC(sig, nbEBands, opus_val16); for (i=0;i<end;i++)
mask[i] = bandLogE[i]-noise_floor[i]; if (C==2)
{ for (i=0;i<end;i++)
mask[i] = MAX16(mask[i], bandLogE[nbEBands+i]-noise_floor[i]);
}
OPUS_COPY(sig, mask, end); for (i=1;i<end;i++)
mask[i] = MAX16(mask[i], mask[i-1] - QCONST16(2.f, DB_SHIFT)); for (i=end-2;i>=0;i--)
mask[i] = MAX16(mask[i], mask[i+1] - QCONST16(3.f, DB_SHIFT)); for (i=0;i<end;i++)
{ /* Compute SMR: Mask is never more than 72 dB below the peak and never below the noise floor.*/
opus_val16 smr = sig[i]-MAX16(MAX16(0, maxDepth-QCONST16(12.f, DB_SHIFT)), 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(MAX16(-QCONST16(5.f, DB_SHIFT), MIN16(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. We enable the feature starting at 24 kb/s for 20-ms frames
and 96 kb/s for 2.5 ms frames. */ if (effectiveBytes >= (30 + 5*LM) && !lfe)
{ int last=0;
c=0;do
{
opus_val16 offset;
opus_val16 tmp;
opus_val16 *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 energy is highly unreliable (high variance). For that reason, we take the max with the previous energy so that at least 2 bins
are getting used. */ for (i=0;i<IMIN(8,end);i++) bandLogE3[i] = MAX16(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 is the last we'll consider. Otherwise, we run into problems on
bandlimited signals. */ if (bandLogE3[i] > bandLogE3[i-1]+QCONST16(.5f,DB_SHIFT))
last=i;
f[i] = MIN16(f[i-1]+QCONST16(1.5f,DB_SHIFT), bandLogE3[i]);
} for (i=last-1;i>=0;i--)
f[i] = MIN16(f[i], MIN16(f[i+1]+QCONST16(2.f,DB_SHIFT), bandLogE3[i]));
/* Combine with a median filter to avoid dynalloc triggering unnecessarily. The "offset" value controls how conservative we are -- a higher offset
reduces the impact of the median filter and makes dynalloc use more bits. */
offset = QCONST16(1.f, DB_SHIFT); for (i=2;i<end-2;i++)
f[i] = MAX16(f[i], median_of_5(&bandLogE3[i-2])-offset);
tmp = median_of_3(&bandLogE3[0])-offset;
f[0] = MAX16(f[0], tmp);
f[1] = MAX16(f[1], tmp);
tmp = median_of_3(&bandLogE3[end-3])-offset;
f[end-2] = MAX16(f[end-2], tmp);
f[end-1] = MAX16(f[end-1], tmp);
for (i=0;i<end;i++)
f[i] = MAX16(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] = MAX16(follower[nbEBands+i], follower[ i]-QCONST16(4.f,DB_SHIFT));
follower[ i] = MAX16(follower[ i], follower[nbEBands+i]-QCONST16(4.f,DB_SHIFT));
follower[i] = HALF16(MAX16(0, bandLogE[i]-follower[i]) + MAX16(0, bandLogE[nbEBands+i]-follower[nbEBands+i]));
}
} else { for (i=start;i<end;i++)
{
follower[i] = MAX16(0, bandLogE[i]-follower[i]);
}
} for (i=start;i<end;i++)
follower[i] = MAX16(follower[i], surround_dynalloc[i]); for (i=start;i<end;i++)
{ #ifdef FIXED_POINT
importance[i] = PSHR32(13*celt_exp2(MIN16(follower[i], QCONST16(4.f, DB_SHIFT))), 16); #else
importance[i] = (int)floor(.5f+13*celt_exp2(MIN16(follower[i], QCONST16(4.f, DB_SHIFT)))); #endif
} /* For non-transient CBR/CVBR frames, halve the dynalloc contribution */ if ((!vbr || constrained_vbr)&&!isTransient)
{ for (i=start;i<end;i++)
follower[i] = HALF16(follower[i]);
} for (i=start;i<end;i++)
{ if (i<8)
follower[i] *= 2; if (i>=12)
follower[i] = HALF16(follower[i]);
} #ifdef DISABLE_FLOAT_API
(void)analysis; #else if (analysis->valid)
{ for (i=start;i<IMIN(LEAK_BANDS, end);i++)
follower[i] = follower[i] + QCONST16(1.f/64.f, DB_SHIFT)*analysis->leak_boost[i];
} #endif for (i=start;i<end;i++)
{ int width; int boost; int boost_bits;
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 nbAvailableBytes, AnalysisInfo *analysis)
{ 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;
SAVE_STACK;
c=0; do {
OPUS_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD);
OPUS_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+overlap)+overlap, N);
} while (++c<CC);
if (enabled)
{
VARDECL(opus_val16, pitch_buf);
ALLOC(pitch_buf, (COMBFILTER_MAXPERIOD+N)>>1, opus_val16);
pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, CC, 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+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N,
COMBFILTER_MAXPERIOD-3*COMBFILTER_MINPERIOD, &pitch_index,
st->arch);
pitch_index = COMBFILTER_MAXPERIOD-pitch_index;
gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD,
N, &pitch_index, st->prefilter_period, st->prefilter_gain, st->arch); if (pitch_index > COMBFILTER_MAXPERIOD-2)
pitch_index = COMBFILTER_MAXPERIOD-2;
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); 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, opus_val16 maxDepth, int lfe, int has_surround_mask, opus_val16 surround_masking,
opus_val16 temporal_vbr)
{ /* 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);
}
/* Don't allow more than doubling the rate */
target = IMIN(2*base_target, target);
return target;
}
int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsignedchar *compressed, int nbCompressedBytes, ec_enc *enc)
{ int i, c, N;
opus_int32 bits;
ec_enc _enc;
VARDECL(celt_sig, in);
VARDECL(celt_sig, freq);
VARDECL(celt_norm, X);
VARDECL(celt_ener, bandE);
VARDECL(opus_val16, bandLogE);
VARDECL(opus_val16, bandLogE2);
VARDECL(int, fine_quant);
VARDECL(opus_val16, error);
VARDECL(int, pulses);
VARDECL(int, cap);
VARDECL(int, offsets);
VARDECL(int, importance);
VARDECL(int, spread_weight);
VARDECL(int, fine_priority);
VARDECL(int, tf_res);
VARDECL(unsignedchar, collapse_masks);
celt_sig *prefilter_mem;
opus_val16 *oldBandE, *oldLogE, *oldLogE2, *energyError; int shortBlocks=0; int isTransient=0; constint CC = st->channels; constint C = st->stream_channels; int LM, M; int tf_select; int nbFilledBytes, nbAvailableBytes; int start; int end; int effEnd; int codedBands; int alloc_trim; int pitch_index=COMBFILTER_MINPERIOD;
opus_val16 gain1 = 0; int dual_stereo=0; int effectiveBytes; int dynalloc_logp;
opus_int32 vbr_rate;
opus_int32 total_bits;
opus_int32 total_boost;
opus_int32 balance;
opus_int32 tell;
opus_int32 tell0_frac; int prefilter_tapset=0; int pf_on; int anti_collapse_rsv; int anti_collapse_on=0; int silence=0; int tf_chan = 0;
opus_val16 tf_estimate; int pitch_change=0;
opus_int32 tot_boost;
opus_val32 sample_max;
opus_val16 maxDepth; const OpusCustomMode *mode; int nbEBands; int overlap; const opus_int16 *eBands; int secondMdct; int signalBandwidth; int transient_got_disabled=0;
opus_val16 surround_masking=0;
opus_val16 temporal_vbr=0;
opus_val16 surround_trim = 0;
opus_int32 equiv_rate; int hybrid; int weak_transient = 0; int enable_tf_analysis;
VARDECL(opus_val16, surround_dynalloc);
ALLOC_STACK;
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;
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 target rate and buffering. We must do this up front so that bust-prevention logic triggers
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). This is clamped to ensure we use at least two bytes if the encoder
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_maxabs16(pcm, C*(N-overlap)/st->upsample));
st->overlap_max=celt_maxabs16(pcm+C*(N-overlap)/st->upsample, C*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);
} /* 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; #ifndef FIXED_POINT
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);
} while (++c<CC);
/* Find pitch period and gain */
{ int enabled; int qg;
enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && !hybrid && !silence && !st->disable_pf
&& st->complexity >= 5;
prefilter_tapset = st->tapset_decision;
pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes, &st->analysis); 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);
}
}
isTransient = 0;
shortBlocks = 0; if (st->complexity >= 1 && !st->lfe)
{ /* Reduces the likelihood of energy instability on fricatives at low bitrate in hybrid mode. It seems like we still want to have real transients on vowels
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);
} 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, opus_val16);
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++)
{
opus_val16 mask;
mask = MAX16(MIN16(st->energy_mask[nbEBands*c+i],
QCONST16(.25f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT)); if (mask > 0)
mask = HALF16(mask);
mask_avg += MULT16_16(mask, eBands[i+1]-eBands[i]);
count += eBands[i+1]-eBands[i];
diff += MULT16_16(mask, 1+2*i-mask_end);
}
}
celt_assert(count>0);
mask_avg = DIV32_16(mask_avg,count);
mask_avg += QCONST16(.2f, DB_SHIFT);
diff = diff*6/(C*(mask_end-1)*(mask_end+1)*mask_end); /* Again, being conservative */
diff = HALF32(diff);
diff = MAX32(MIN32(diff, QCONST32(.031f, DB_SHIFT)), -QCONST32(.031f, DB_SHIFT)); /* 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;
opus_val16 unmask;
lin = mask_avg + diff*(i-midband); if (C==2)
unmask = MAX16(st->energy_mask[i], st->energy_mask[nbEBands+i]); else
unmask = st->energy_mask[i];
unmask = MIN16(unmask, QCONST16(.0f, DB_SHIFT));
unmask -= lin; if (unmask > QCONST16(.25f, DB_SHIFT))
{
surround_dynalloc[i] = unmask - QCONST16(.25f, DB_SHIFT);
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 += QCONST16(.25f, DB_SHIFT); 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] = MAX16(0, surround_dynalloc[i]-QCONST16(.25f, DB_SHIFT));
}
}
mask_avg += QCONST16(.2f, DB_SHIFT); /* 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)
{
opus_val16 follow=-QCONST16(10.0f,DB_SHIFT);
opus_val32 frame_avg=0;
opus_val16 offset = shortBlocks?HALF16(SHL16(LM, DB_SHIFT)):0; for(i=start;i<end;i++)
{
follow = MAX16(follow-QCONST16(1.f, DB_SHIFT), bandLogE[i]-offset); if (C==2)
follow = MAX16(follow, bandLogE[i+nbEBands]-offset);
frame_avg += follow;
}
frame_avg /= (end-start);
temporal_vbr = SUB16(frame_avg,st->spec_avg);
temporal_vbr = MIN16(QCONST16(3.f, DB_SHIFT), MAX16(-QCONST16(1.5f, DB_SHIFT), temporal_vbr));
st->spec_avg += MULT16_16_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] += HALF16(SHL16(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 TF on a long window is imperfect and will not result in an energy collapse at
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, opus_val16);
c=0; do { for (i=start;i<end;i++)
{ /* When the energy is stable, slightly bias energy quantization towards the previous error to make the gain more stable (a constant offset is
better than fluctuations). */ if (ABS32(SUB32(bandLogE[i+c*nbEBands], oldBandE[i+c*nbEBands])) < QCONST16(2.f, DB_SHIFT))
{
bandLogE[i+c*nbEBands] -= MULT16_16_Q15(energyError[i+c*nbEBands], QCONST16(0.25f, 15));
}
}
} 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);
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.