diff options
author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2011-12-23 20:58:43 +0400 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2012-07-03 22:39:44 +0400 |
commit | 6fdc0ab80e42b6f1b10f6d2b46383c7aa387b87f (patch) | |
tree | 38ba9230542a609b6b35e41ba9b28843ff5396ee | |
parent | 565276b1970ba558e7ca7355144178743dae991d (diff) |
Fixes some issues discovered with a log sweep
- New DC rejection filter that avoids numerical issues
- Higher cap on HF dynalloc
- Proper filter memory for transient detector
- Prevents transient detector from detecting low-freq tones as transients
-rw-r--r-- | celt/celt.c | 45 | ||||
-rw-r--r-- | src/opus_encoder.c | 33 |
2 files changed, 54 insertions, 24 deletions
diff --git a/celt/celt.c b/celt/celt.c index 4e47caf5..925c33c8 100644 --- a/celt/celt.c +++ b/celt/celt.c @@ -179,6 +179,7 @@ struct OpusCustomEncoder { int consec_transient; AnalysisInfo analysis; + opus_val32 transient_mem[8]; opus_val32 preemph_memE[2]; opus_val32 preemph_memD[2]; @@ -293,7 +294,8 @@ static inline opus_val16 SIG2WORD16(celt_sig x) } static int transient_analysis(const opus_val32 * restrict in, int len, int C, - int overlap, opus_val16 *tf_estimate, int *tf_chan, AnalysisInfo *analysis) + int overlap, opus_val16 *tf_estimate, int *tf_chan, + AnalysisInfo *analysis, opus_val32 *transient_mem) { int i; VARDECL(opus_val16, tmp); @@ -306,7 +308,7 @@ static int transient_analysis(const opus_val32 * restrict in, int len, int C, VARDECL(opus_val16, bins); opus_val16 T1, T2, T3, T4, T5; opus_val16 follower; - opus_val16 coef[2][4] = {{-2.f, 1.f, -1.f, .5f}, {0.005f, -0.995f, -1.92, .95}}; + opus_val16 coef[2][4] = {{-2.f, 1.f, -1.f, .5f}, {-1.9995f, 1.f, -1.88375f, .9025f}}; int filterID; int metric=0; int fmetric=0, bmetric=0; @@ -325,8 +327,8 @@ static int transient_analysis(const opus_val32 * restrict in, int len, int C, { for (c=0;c<C;c++) { - mem0=0; - mem1=0; + mem0 = transient_mem[filterID*4+c*2]; + mem1 = transient_mem[filterID*4+c*2+1]; for (i=0;i<len;i++) tmp[i] = SHR32(in[i+c*len],SIG_SHIFT); @@ -336,6 +338,11 @@ static int transient_analysis(const opus_val32 * restrict in, int len, int C, opus_val32 x,y; x = tmp[i]; y = ADD32(mem0, x); + if (i==len-overlap) + { + transient_mem[filterID*4+c*2]=mem0; + transient_mem[filterID*4+c*2+1]=mem1; + } #ifdef FIXED_POINT mem0 = mem1 + y - SHL32(x,1); mem1 = x - SHR32(y,1); @@ -347,9 +354,6 @@ static int transient_analysis(const opus_val32 * restrict in, int len, int C, #endif tmp[i] = EXTRACT16(SHR32(y,2)); } - /* First few samples are bad because we don't propagate the memory */ - for (i=0;i<12;i++) - tmp[i] = 0; maxbin=0; for (i=0;i<N;i++) @@ -358,7 +362,6 @@ static int transient_analysis(const opus_val32 * restrict in, int len, int C, opus_val16 max_abs=0; for (j=0;j<2*block;j++) max_abs = MAX16(max_abs, ABS16(tmp[i*block+j])); - //printf("%f ", max_abs); bins[i] = max_abs; maxbin = MAX16(maxbin, bins[i]); } @@ -412,7 +415,7 @@ static int transient_analysis(const opus_val32 * restrict in, int len, int C, bmetric = 5*count1 + 4*count2 + 3*count3 + 2*count4 + count5; metric = fmetric+bmetric; - //if (metric>40) + /*if (metric>40)*/ if (metric>30+20*MAX16(analysis->tonality, analysis->noisiness)) is_transient=1; @@ -428,7 +431,7 @@ static int transient_analysis(const opus_val32 * restrict in, int len, int C, #ifdef FUZZING is_transient = rand()&0x1; #endif - //printf("%d %f %f %f %f\n", is_transient, *tf_estimate, tf_max, analysis->tonality, analysis->noisiness); + /*printf("%d %f %d %f %f\n", is_transient, *tf_estimate, tf_max, analysis->tonality, analysis->noisiness);*/ return is_transient; } @@ -681,7 +684,7 @@ static int tf_analysis(const CELTMode *m, int len, int C, int isTransient, metric[i] = best_level; else metric[i] = -best_level; - //printf("%d ", metric[i]); + /*printf("%d ", metric[i]);*/ *tf_sum += (isTransient ? LM : 0) - metric[i]; } /*printf("\n");*/ @@ -730,7 +733,7 @@ static int tf_analysis(const CELTMode *m, int len, int C, int isTransient, else tf_res[i] = path0[i+1]; } - //printf("%d %f\n", *tf_sum, tf_estimate); + /*printf("%d %f\n", *tf_sum, tf_estimate);*/ RESTORE_STACK; #ifdef FUZZING tf_select = rand()&0x1; @@ -778,7 +781,7 @@ static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM, tf_select = 0; for (i=start;i<end;i++) tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]]; - //for(i=0;i<end;i++)printf("%d ", isTransient ? LM-tf_res[i] : -tf_res[i]);printf("\n"); + /*for(i=0;i<end;i++)printf("%d ", isTransient ? LM-tf_res[i] : -tf_res[i]);printf("\n");*/ } static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM, ec_dec *dec) @@ -1207,7 +1210,7 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && st->analysis.tonality > .3 && (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period)) pitch_change = 1; - //printf("%d %d %f %f\n", pitch_change, pitch_index, gain1, st->analysis.tonality); + /*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) @@ -1306,7 +1309,7 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f if (st->complexity > 1) { isTransient = transient_analysis(in, N+st->overlap, CC, - st->overlap, &tf_estimate, &tf_chan, &st->analysis); + st->overlap, &tf_estimate, &tf_chan, &st->analysis, st->transient_mem); if (isTransient) shortBlocks = M; } @@ -1435,33 +1438,33 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f follower[c*st->mode->nbEBands] = bandLogE2[c*st->mode->nbEBands]; for (i=1;i<st->mode->nbEBands;i++) follower[c*st->mode->nbEBands+i] = MIN16(follower[c*st->mode->nbEBands+i-1]+1.5, bandLogE2[c*st->mode->nbEBands+i]); - for (i=st->mode->nbEBands-2;i>=0;i--) + for (i=st->end-2;i>=0;i--) follower[c*st->mode->nbEBands+i] = MIN16(follower[c*st->mode->nbEBands+i], MIN16(follower[c*st->mode->nbEBands+i+1]+2, bandLogE2[c*st->mode->nbEBands+i])); } while (++c<2); if (C==2) { - for (i=st->start;i<st->end-1;i++) + for (i=st->start;i<st->end;i++) { follower[st->mode->nbEBands+i] = MAX16(follower[st->mode->nbEBands+i], follower[ i]-4); follower[ i] = MAX16(follower[ i], follower[st->mode->nbEBands+i]-4); follower[i] = HALF16(MAX16(0, bandLogE[i]-follower[i]) + MAX16(0, bandLogE[st->mode->nbEBands+i]-follower[st->mode->nbEBands+i])); } } else { - for (i=st->start;i<st->end-1;i++) + for (i=st->start;i<st->end;i++) { follower[i] = MAX16(0, bandLogE[i]-follower[i]); } } - for (i=st->start;i<st->end-1;i++) + for (i=st->start;i<st->end;i++) { int width; int boost; - follower[i] = MIN16(follower[i], QCONST16(2, DB_SHIFT)); if (i<8) follower[i] *= 2; if (i>=12) follower[i] *= .5; + follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT)); width = C*(st->mode->eBands[i+1]-st->mode->eBands[i])<<LM; if (width<6) { @@ -1676,7 +1679,7 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f /*printf ("+%d\n", adjust);*/ } nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes); - //printf("%d\n", nbCompressedBytes*50*8); + /*printf("%d\n", nbCompressedBytes*50*8);*/ /* This moves the raw bits to take into account the new compressed size */ ec_enc_shrink(enc, nbCompressedBytes); } diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 17390635..91a9f344 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -368,6 +368,29 @@ static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *ou #endif } +static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) +{ + int c, i; + float coef; + + coef = 4.*cutoff_Hz/Fs; + for (c=0;c<channels;c++) + { + for (i=0;i<len;i++) + { + opus_val32 x, tmp, y; + x = in[channels*i+c]; + /* First stage */ + tmp = x-hp_mem[2*c]; + hp_mem[2*c] = hp_mem[2*c] + coef*(x - hp_mem[2*c]); + /* Second stage */ + y = tmp - hp_mem[2*c+1]; + hp_mem[2*c+1] = hp_mem[2*c+1] + coef*(tmp - hp_mem[2*c+1]); + out[channels*i+c] = y; + } + } +} + static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2, int overlap, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs) { @@ -856,9 +879,13 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s { hp_cutoff(pcm, cutoff_Hz, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); } else { - hp_cutoff(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); - /*for (i=0;i<frame_size*st->channels;i++) - pcm_buf[total_buffer*st->channels + i] = pcm[i];*/ +#ifdef FIXED_POINT + /* FIXME: Replace by a fixed-point version of dc_reject */ + for (i=0;i<frame_size*st->channels;i++) + pcm_buf[total_buffer*st->channels + i] = pcm[i]; +#else + dc_reject(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); +#endif } #ifndef FIXED_POINT |