diff options
author | Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> | 2009-10-17 07:16:47 +0400 |
---|---|---|
committer | Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> | 2009-10-17 07:16:47 +0400 |
commit | d35d67754304c8412848c6596ecb5db8f99ae1e0 (patch) | |
tree | 02f13177457e797d59490df4dc11511db54e27f1 | |
parent | 163b02eb8e2434607fed2e4247a15c5f88e10b62 (diff) |
Constrain the pitch gain to prevent potential instabilities.
-rw-r--r-- | libcelt/bands.c | 12 | ||||
-rw-r--r-- | libcelt/bands.h | 2 | ||||
-rw-r--r-- | libcelt/celt.c | 3 |
3 files changed, 14 insertions, 3 deletions
diff --git a/libcelt/bands.c b/libcelt/bands.c index 6ce27b7..7024487 100644 --- a/libcelt/bands.c +++ b/libcelt/bands.c @@ -211,7 +211,7 @@ void denormalise_bands(const CELTMode *m, const celt_norm_t * restrict X, celt_s } } -int compute_pitch_gain(const CELTMode *m, const celt_sig_t *X, const celt_sig_t *P, int norm_rate, int *gain_id, int _C) +int compute_pitch_gain(const CELTMode *m, const celt_sig_t *X, const celt_sig_t *P, int norm_rate, int *gain_id, int _C, celt_word16_t *gain_prod) { int j, c; celt_word16_t g; @@ -281,6 +281,16 @@ int compute_pitch_gain(const CELTMode *m, const celt_sig_t *X, const celt_sig_t *gain_id = floor(20*(g-.5)); } #endif + /* This prevents the pitch gain from being above 1.0 for too long by bounding the + maximum error amplification factor to 2.0 */ + g = ADD16(QCONST16(.5,14), MULT16_16_16(QCONST16(.05,14),*gain_id)); + *gain_prod = MAX16(QCONST32(1., 13), MULT16_16_Q14(*gain_prod,g)); + if (*gain_prod>QCONST32(2., 13)) + { + *gain_id=9; + *gain_prod = QCONST32(2., 13); + } + if (*gain_id < 0) { *gain_id = 0; diff --git a/libcelt/bands.h b/libcelt/bands.h index 19d2940..5927726 100644 --- a/libcelt/bands.h +++ b/libcelt/bands.h @@ -71,7 +71,7 @@ void denormalise_bands(const CELTMode *m, const celt_norm_t * restrict X, celt_s * @param gains Gain computed for each pitch band (returned) * @param bank Square root of the energy for each band */ -int compute_pitch_gain(const CELTMode *m, const celt_sig_t *X, const celt_sig_t *P, int norm_rate, int *gain_id, int _C); +int compute_pitch_gain(const CELTMode *m, const celt_sig_t *X, const celt_sig_t *P, int norm_rate, int *gain_id, int _C, celt_word16_t *gain_prod); void apply_pitch(const CELTMode *m, celt_sig_t *X, const celt_sig_t *P, int gain_id, int pred, int _C); diff --git a/libcelt/celt.c b/libcelt/celt.c index af99728..e7872da 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -88,6 +88,7 @@ struct CELTEncoder { int delayedIntra; celt_word16_t tonal_average; int fold_decision; + celt_word16_t gain_prod; int VBR_rate; /* Target number of 16th bits per frame */ celt_word16_t * restrict preemph_memE; @@ -650,7 +651,7 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_si { compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C); - has_pitch = compute_pitch_gain(st->mode, freq, pitch_freq, norm_rate, &gain_id, C); + has_pitch = compute_pitch_gain(st->mode, freq, pitch_freq, norm_rate, &gain_id, C, &st->gain_prod); } if (has_pitch) |