Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.xiph.org/xiph/opus.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/celt
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@jmvalin.ca>2013-10-02 01:06:09 +0400
committerJean-Marc Valin <jmvalin@jmvalin.ca>2013-10-02 01:06:09 +0400
commit7c60625f808e66abe016401eb449e9940916b3c1 (patch)
tree10e47c9416906fd08812be1d23d51a18b71fd6ee /celt
parentc435f06b308e52d7a5d2aad9eec98a1541832b47 (diff)
parent6b9087aa6efbb98731216d2b03cc977826fd6062 (diff)
Merge branch 'exp_surround1'
Diffstat (limited to 'celt')
-rw-r--r--celt/arch.h1
-rw-r--r--celt/celt.h18
-rw-r--r--celt/celt_encoder.c124
-rw-r--r--celt/fixed_generic.h1
4 files changed, 95 insertions, 49 deletions
diff --git a/celt/arch.h b/celt/arch.h
index 78e2635f..f9c98567 100644
--- a/celt/arch.h
+++ b/celt/arch.h
@@ -185,6 +185,7 @@ typedef float celt_ener;
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
#define MULT16_16_Q11_32(a,b) ((a)*(b))
+#define MULT16_16_Q11(a,b) ((a)*(b))
#define MULT16_16_Q13(a,b) ((a)*(b))
#define MULT16_16_Q14(a,b) ((a)*(b))
#define MULT16_16_Q15(a,b) ((a)*(b))
diff --git a/celt/celt.h b/celt/celt.h
index 0911c72f..cdb76c8b 100644
--- a/celt/celt.h
+++ b/celt/celt.h
@@ -52,11 +52,11 @@ extern "C" {
typedef struct {
int valid;
- opus_val16 tonality;
- opus_val16 tonality_slope;
- opus_val16 noisiness;
- opus_val16 activity;
- opus_val16 music_prob;
+ float tonality;
+ float tonality_slope;
+ float noisiness;
+ float activity;
+ float music_prob;
int bandwidth;
}AnalysisInfo;
@@ -109,10 +109,7 @@ typedef struct {
#define OPUS_SET_LFE_REQUEST 10024
#define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, __opus_check_int(x)
-#define OPUS_SET_ENERGY_SAVE_REQUEST 10026
-#define OPUS_SET_ENERGY_SAVE(x) OPUS_SET_ENERGY_SAVE_REQUEST, __opus_check_val16_ptr(x)
-
-#define OPUS_SET_ENERGY_MASK_REQUEST 10028
+#define OPUS_SET_ENERGY_MASK_REQUEST 10026
#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x)
/* Encoder stuff */
@@ -193,6 +190,9 @@ extern const signed char tf_select_table[4][8];
int resampling_factor(opus_int32 rate);
+void 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);
+
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
const opus_val16 *window, int overlap);
diff --git a/celt/celt_encoder.c b/celt/celt_encoder.c
index 31bea1bb..241fb372 100644
--- a/celt/celt_encoder.c
+++ b/celt/celt_encoder.c
@@ -111,7 +111,6 @@ struct OpusCustomEncoder {
opus_val32 overlap_max;
opus_val16 stereo_saving;
int intensity;
- opus_val16 *energy_save;
opus_val16 *energy_mask;
opus_val16 spec_avg;
@@ -452,7 +451,7 @@ static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * OPUS
}
-static void preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
+void 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;
@@ -744,7 +743,7 @@ static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM,
static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
const opus_val16 *bandLogE, int end, int LM, int C, int N0,
AnalysisInfo *analysis, opus_val16 *stereo_saving, opus_val16 tf_estimate,
- int intensity)
+ int intensity, opus_val16 surround_trim)
{
int i;
opus_val32 diff=0;
@@ -818,11 +817,12 @@ static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
if (diff < -QCONST16(10.f, DB_SHIFT))
trim_index++;
trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), SHR16(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 ));
+ trim -= SHR16(surround_trim, DB_SHIFT-8);
trim -= 2*SHR16(tf_estimate, 14-8);
-#ifndef FIXED_POINT
+#ifndef DISABLE_FLOAT_API
if (analysis->valid)
{
- trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), 2*(analysis->tonality_slope+.05f)));
+ trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), QCONST16(2.f, 8)*(analysis->tonality_slope+.05f)));
}
#endif
@@ -877,7 +877,7 @@ static int stereo_analysis(const CELTMode *m, const celt_norm *X,
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)
+ int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc)
{
int i, c;
opus_int32 tot_boost=0;
@@ -940,6 +940,8 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
follower[i] = MAX16(0, bandLogE[i]-follower[i]);
}
}
+ for (i=start;i<end;i++)
+ follower[i] = MAX16(follower[i], surround_dynalloc[i]);
/* For non-transient CBR/CVBR frames, halve the dynalloc contribution */
if ((!vbr || constrained_vbr)&&!isTransient)
{
@@ -1140,7 +1142,7 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
target = base_target;
/*printf("%f %f %f %f %d %d ", st->analysis.activity, st->analysis.tonality, tf_estimate, st->stereo_saving, tot_boost, coded_bands);*/
-#ifndef FIXED_POINT
+#ifndef DISABLE_FLOAT_API
if (analysis->valid && analysis->activity<.4)
target -= (opus_int32)((coded_bins<<BITRES)*(.4f-analysis->activity));
#endif
@@ -1165,7 +1167,7 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
QCONST16(0.02f,14) : QCONST16(0.04f,14);
target += (opus_int32)SHL32(MULT16_32_Q15(tf_estimate-tf_calibration, target),1);
-#ifndef FIXED_POINT
+#ifndef DISABLE_FLOAT_API
/* Apply tonality boost */
if (analysis->valid && !lfe)
{
@@ -1291,6 +1293,8 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
int transient_got_disabled=0;
opus_val16 surround_masking=0;
opus_val16 temporal_vbr=0;
+ opus_val16 surround_trim = 0;
+ VARDECL(opus_val16, surround_dynalloc);
ALLOC_STACK;
mode = st->mode;
@@ -1526,37 +1530,83 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
}
}
amp2Log2(mode, effEnd, st->end, bandE, bandLogE, C);
- if (st->energy_save)
- {
- opus_val16 offset = shortBlocks?HALF16(SHL16(LM, DB_SHIFT)):0;
-#ifdef FIXED_POINT
- /* Compensate for the 1/8 gain we apply in the fixed-point downshift to avoid overflows. */
- offset -= QCONST16(3.0f, DB_SHIFT);
-#endif
- for(i=0;i<C*nbEBands;i++)
- st->energy_save[i]=bandLogE[i]-offset;
- st->energy_save=NULL;
- }
+
+ ALLOC(surround_dynalloc, C*nbEBands, opus_val16);
+ for(i=0;i<st->end;i++)
+ surround_dynalloc[i] = 0;
/* This computes how much masking takes place between surround channels */
- if (st->energy_mask&&!st->lfe)
+ if (st->start==0&&st->energy_mask&&!st->lfe)
{
+ int mask_end;
+ int midband;
+ int count_dynalloc;
opus_val32 mask_avg=0;
- opus_val16 offset = shortBlocks?HALF16(SHL16(LM, DB_SHIFT)):0;
+ opus_val32 diff=0;
+ int count=0;
+ mask_end = st->lastCodedBands;
for (c=0;c<C;c++)
{
- opus_val16 followE, followMask;
- followE = followMask = -QCONST16(14.f, DB_SHIFT);
- for(i=0;i<st->end;i++)
+ for(i=0;i<mask_end;i++)
{
- /* We use a simple follower to approximate the masking spreading function. */
- followE = MAX16(followE-QCONST16(1.f, DB_SHIFT), bandLogE[nbEBands*c+i]-offset);
- followMask = MAX16(followMask-QCONST16(1.f, DB_SHIFT), st->energy_mask[nbEBands*c+i]);
- mask_avg += followE-followMask;
+ 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);
}
}
- surround_masking = DIV32_16(mask_avg,C*st->end) + QCONST16(.7f, DB_SHIFT);
- surround_masking = MIN16(MAX16(surround_masking, -QCONST16(2.f, DB_SHIFT)), QCONST16(.2f, DB_SHIFT));
- surround_masking -= HALF16(HALF16(surround_masking));
+ 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;
+ for(i=0;i<mask_end;i++)
+ surround_dynalloc[i] = 0;
+ } 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)
@@ -1683,7 +1733,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, st->start, st->end, C, offsets,
st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr,
- eBands, LM, effectiveBytes, &tot_boost, st->lfe);
+ eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc);
/* For LFE, everything interesting is in the first band */
if (st->lfe)
offsets[0] = IMIN(8, effectiveBytes/3);
@@ -1756,7 +1806,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
alloc_trim = 5;
else
alloc_trim = alloc_trim_analysis(mode, X, bandLogE,
- st->end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate, st->intensity);
+ st->end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate, st->intensity, surround_trim);
ec_enc_icdf(enc, alloc_trim, trim_icdf, 7);
tell = ec_tell_frac(enc);
}
@@ -1859,7 +1909,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0;
bits -= anti_collapse_rsv;
signalBandwidth = st->end-1;
-#ifndef FIXED_POINT
+#ifndef DISABLE_FLOAT_API
if (st->analysis.valid)
{
int min_bandwidth;
@@ -2261,12 +2311,6 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
st->lfe = value;
}
break;
- case OPUS_SET_ENERGY_SAVE_REQUEST:
- {
- opus_val16 *value = va_arg(ap, opus_val16*);
- st->energy_save=value;
- }
- break;
case OPUS_SET_ENERGY_MASK_REQUEST:
{
opus_val16 *value = va_arg(ap, opus_val16*);
diff --git a/celt/fixed_generic.h b/celt/fixed_generic.h
index 0e77976e..657e67c8 100644
--- a/celt/fixed_generic.h
+++ b/celt/fixed_generic.h
@@ -116,6 +116,7 @@
#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
+#define MULT16_16_Q11(a,b) (SHR(MULT16_16((a),(b)),11))
#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))