ref: 0cc4d9659aaa35c8a21af0e7a8927bf9132315bf
parent: a1c2d71803b0a4a0ceac644270b9ff23ee81a3f3
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Wed May 31 23:14:13 EDT 2017
Adding leakage modelling to boost bands We boost bands that either cause leakage or are filled with leakage
--- a/celt/celt.h
+++ b/celt/celt.h
@@ -50,6 +50,8 @@
#define CELTDecoder OpusCustomDecoder
#define CELTMode OpusCustomMode
+#define LEAK_BANDS 19
+
typedef struct {
int valid;
float tonality;
@@ -60,6 +62,8 @@
float vad_prob;
int bandwidth;
float activity_probability;
+ /* Store as Q6 char to save space. */
+ unsigned char leak_boost[LEAK_BANDS];
} AnalysisInfo;
typedef struct {
--- a/celt/celt_encoder.c
+++ b/celt/celt_encoder.c
@@ -964,7 +964,7 @@
static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2,
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)
+ int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc, AnalysisInfo *analysis)
{
int i, c;
opus_int32 tot_boost=0;
@@ -1054,14 +1054,26 @@
}
for (i=start;i<end;i++)
{
- int width;
- int boost;
- int boost_bits;
-
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;
+
follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT));
width = C*(eBands[i+1]-eBands[i])<<LM;
@@ -1893,7 +1905,7 @@
maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets,
st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr,
- eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc);
+ eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc, &st->analysis);
/* For LFE, everything interesting is in the first band */
if (st->lfe)
offsets[0] = IMIN(8, effectiveBytes/3);
--- a/src/analysis.c
+++ b/src/analysis.c
@@ -290,6 +290,9 @@
2.163313f, 1.260756f, 1.116868f, 1.918795f
};
+#define LEAKAGE_OFFSET 2.5f
+#define LEAKAGE_SLOPE 2.f
+
#ifdef FIXED_POINT
/* For fixed-point, the input is +/-2^15 shifted up by SIG_SHIFT, so we need to
compensate for that in the energy. */
@@ -336,6 +339,9 @@
float tonality2[240];
float midE[8];
float spec_variability=0;
+ float band_log2[NB_TBANDS+1];
+ float leakage_from[NB_TBANDS+1];
+ float leakage_to[NB_TBANDS+1];
SAVE_STACK;
alpha = 1.f/IMIN(10, 1+tonal->count);
@@ -461,6 +467,22 @@
}
relativeE = 0;
frame_loudness = 0;
+ /* The energy of the very first band is special because of DC. */
+ {
+ float E = 0;
+ float X1r, X2r;
+ X1r = 2*(float)out[0].r;
+ X2r = 2*(float)out[0].i;
+ E = X1r*X1r + X2r*X2r;
+ for (i=1;i<4;i++)
+ {
+ float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
+ + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
+ E += binE;
+ }
+ E = SCALE_ENER(E);
+ band_log2[0] = (float).5*log2(E+1e-10f);
+ }
for (b=0;b<NB_TBANDS;b++)
{
float E=0, tE=0, nE=0;
@@ -490,6 +512,7 @@
frame_loudness += (float)sqrt(E+1e-10f);
logE[b] = (float)log(E+1e-10f);
+ band_log2[b+1] = (float).5*log2(E+1e-10f);
tonal->logE[tonal->E_count][b] = logE[b];
if (tonal->count==0)
tonal->highE[b] = tonal->lowE[b] = logE[b];
@@ -540,6 +563,35 @@
/*printf("%f %f ", band_tonality[b], stationarity);*/
tonal->prev_band_tonality[b] = band_tonality[b];
}
+
+ leakage_from[0] = band_log2[0];
+ leakage_to[0] = band_log2[0] - LEAKAGE_OFFSET;
+ for (b=1;b<NB_TBANDS+1;b++)
+ {
+ float leak_slope = LEAKAGE_SLOPE*(tbands[b]-tbands[b-1])/4;
+ leakage_from[b] = MIN16(leakage_from[b-1]+leak_slope, band_log2[b]);
+ leakage_to[b] = MAX16(leakage_to[b-1]-leak_slope, band_log2[b]-LEAKAGE_OFFSET);
+ }
+ for (b=NB_TBANDS-2;b>=0;b--)
+ {
+ float leak_slope = LEAKAGE_SLOPE*(tbands[b+1]-tbands[b])/4;
+ leakage_from[b] = MIN16(leakage_from[b+1]+leak_slope, leakage_from[b]);
+ leakage_to[b] = MAX16(leakage_to[b+1]-leak_slope, leakage_to[b]);
+ }
+ celt_assert(NB_TBANDS+1 <= LEAK_BANDS);
+ for (b=0;b<NB_TBANDS+1;b++)
+ {
+ /* leak_boost[] is made up of two terms. The first, based on leakage_high[],
+ represents the boost needed to overcome the amount of analysis leakage
+ cause in a weaker band b by louder neighroubing bands.
+ The second, based on leakage_low[], applies to a loud band b for
+ which the quantization noise causes synthesis leakage to the weaker
+ neighbouring bands. */
+ float boost = MAX16(0, leakage_to[b] - band_log2[b]) +
+ MAX16(0, band_log2[b] - (leakage_from[b]+LEAKAGE_OFFSET));
+ info->leak_boost[b] = IMIN(255, (int)floor(.5 + 64.f*boost));
+ }
+ for (;b<LEAK_BANDS;b++) info->leak_boost[b] = 0;
for (i=0;i<NB_FRAMES;i++)
{