From dfa847a25de8f75370a10b12533d8f6fc87ff733 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Mon, 17 Jan 2011 11:37:08 -0500 Subject: [PATCH] Support for multiple postfilter tapsets Supporting three different tapsets with different roll-offs. The default is now a 5-tap post-filter with a 13 kHz cutoff frequency. --- libcelt/celt.c | 101 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/libcelt/celt.c b/libcelt/celt.c index c623f39f..84e2d95f 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -86,9 +86,11 @@ struct CELTEncoder { int prefilter_period; celt_word16 prefilter_gain; + int prefilter_tapset; #ifdef RESYNTH int prefilter_period_old; celt_word16 prefilter_gain_old; + int prefilter_tapset_old; #endif /* VBR-related parameters */ @@ -389,40 +391,46 @@ static void deemphasis(celt_sig *in[], celt_word16 *pcm, int N, int _C, const ce #ifdef ENABLE_POSTFILTER static void comb_filter(celt_word32 *y, celt_word32 *x, int T0, int T1, int N, - int C, celt_word16 g0, celt_word16 g1, const celt_word16 *window, int overlap) + int C, celt_word16 g0, celt_word16 g1, int tapset0, int tapset1, + const celt_word16 *window, int overlap) { int i; /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */ celt_word16 g00, g01, g02, g10, g11, g12; - celt_word16 t0, t1, t2; - /* zeros at theta = +/- 5*pi/6 */ - t0 = QCONST16(.26795f, 15); - t1 = QCONST16(.46410f, 15); - t2 = QCONST16(.26795f, 15); - g00 = MULT16_16_Q15(g0, t0); - g01 = MULT16_16_Q15(g0, t1); - g02 = MULT16_16_Q15(g0, t2); - g10 = MULT16_16_Q15(g1, t0); - g11 = MULT16_16_Q15(g1, t1); - g12 = MULT16_16_Q15(g1, t2); + static const celt_word16 gains[3][3] = { + {QCONST16(0.30690f, 15), QCONST16(0.21701f, 15), QCONST16(0.12954f, 15)}, + {QCONST16(0.46410f, 15), QCONST16(0.26795f, 15), QCONST16(0.f, 15)}, + {QCONST16(0.8f, 15), QCONST16(0.1f, 15), QCONST16(0.f, 15)}}; + g00 = MULT16_16_Q15(g0, gains[tapset0][0]); + g01 = MULT16_16_Q15(g0, gains[tapset0][1]); + g02 = MULT16_16_Q15(g0, gains[tapset0][2]); + g10 = MULT16_16_Q15(g1, gains[tapset1][0]); + g11 = MULT16_16_Q15(g1, gains[tapset1][1]); + g12 = MULT16_16_Q15(g1, gains[tapset1][2]); for (i=0;iprefilter_period, st->prefilter_gain); - if (pitch_index > COMBFILTER_MAXPERIOD) - pitch_index = COMBFILTER_MAXPERIOD; + if (pitch_index > COMBFILTER_MAXPERIOD-2) + pitch_index = COMBFILTER_MAXPERIOD-2; gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1); + prefilter_tapset = 0; } else { gain1 = 0; } @@ -959,11 +969,16 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i qg = floor(.5+gain1*8)-2; #endif 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<1, 1); } /*printf("%d %f\n", pitch_index, gain1);*/ #else /* ENABLE_POSTFILTER */ @@ -976,7 +991,8 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i CELT_COPY(in+c*(N+st->overlap), st->in_mem+c*(st->overlap), st->overlap); #ifdef ENABLE_POSTFILTER comb_filter(in+c*(N+st->overlap)+st->overlap, pre[c]+COMBFILTER_MAXPERIOD, - st->prefilter_period, pitch_index, N, C, -st->prefilter_gain, -gain1, st->mode->window, st->mode->overlap); + st->prefilter_period, pitch_index, N, C, -st->prefilter_gain, -gain1, + st->prefilter_tapset, prefilter_tapset, st->mode->window, st->mode->overlap); #endif /* ENABLE_POSTFILTER */ CELT_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap); @@ -1306,12 +1322,15 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i if (LM!=0) { comb_filter(out_mem[c], out_mem[c], st->prefilter_period, st->prefilter_period, st->overlap, C, - st->prefilter_gain, st->prefilter_gain, NULL, 0); + st->prefilter_gain, st->prefilter_gain, st->prefilter_tapset, st->prefilter_tapset, + NULL, 0); comb_filter(out_mem[c]+st->overlap, out_mem[c]+st->overlap, st->prefilter_period, pitch_index, N-st->overlap, C, - st->prefilter_gain, gain1, st->mode->window, st->mode->overlap); + st->prefilter_gain, gain1, st->prefilter_tapset, prefilter_tapset, + st->mode->window, st->mode->overlap); } else { comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, N, C, - st->prefilter_gain_old, st->prefilter_gain, st->mode->window, st->mode->overlap); + st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset, + st->mode->window, st->mode->overlap); } } while (++cmode->preemph, st->preemph_memD); st->prefilter_period_old = st->prefilter_period; st->prefilter_gain_old = st->prefilter_gain; + st->prefilter_tapset_old = st->prefilter_tapset; } #endif st->prefilter_period = pitch_index; st->prefilter_gain = gain1; + st->prefilter_tapset = prefilter_tapset; /* In case start or end were to change */ for (i=0;istart;i++) @@ -1548,6 +1569,8 @@ struct CELTDecoder { int postfilter_period_old; celt_word16 postfilter_gain; celt_word16 postfilter_gain_old; + int postfilter_tapset; + int postfilter_tapset_old; celt_sig preemph_memD[2]; @@ -1763,7 +1786,8 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p #ifdef ENABLE_POSTFILTER /* Apply post-filter to the MDCT overlap of the previous frame */ comb_filter(out_mem[c]+MAX_PERIOD, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, C, - st->postfilter_gain, st->postfilter_gain, NULL, 0); + st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset, + NULL, 0); #endif /* ENABLE_POSTFILTER */ for (i=0;imode->overlap-N;i++) @@ -1785,7 +1809,8 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p #ifdef ENABLE_POSTFILTER /* Apply pre-filter to the MDCT overlap for the next frame (post-filter will be applied then) */ comb_filter(e, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, C, - -st->postfilter_gain, -st->postfilter_gain, NULL, 0); + -st->postfilter_gain, -st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset, + NULL, 0); #endif /* ENABLE_POSTFILTER */ for (i=0;ipostfilter_period, st->postfilter_period, st->overlap, C, - st->postfilter_gain, st->postfilter_gain, NULL, 0); + st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset, + NULL, 0); comb_filter(out_syn[c]+st->overlap, out_syn[c]+st->overlap, st->postfilter_period, postfilter_pitch, N-st->overlap, C, - st->postfilter_gain, postfilter_gain, st->mode->window, st->mode->overlap); + st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset, + st->mode->window, st->mode->overlap); } else { comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, N-st->overlap, C, - st->postfilter_gain_old, st->postfilter_gain, st->mode->window, st->mode->overlap); + st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset, + st->mode->window, st->mode->overlap); } } while (++cpostfilter_period_old = st->postfilter_period; st->postfilter_gain_old = st->postfilter_gain; + st->postfilter_tapset_old = st->postfilter_tapset; st->postfilter_period = postfilter_pitch; st->postfilter_gain = postfilter_gain; + st->postfilter_tapset = postfilter_tapset; #endif /* ENABLE_POSTFILTER */ /* In case start or end were to change */