shithub: opus

Download patch

ref: d35d67754304c8412848c6596ecb5db8f99ae1e0
parent: 163b02eb8e2434607fed2e4247a15c5f88e10b62
author: Jean-Marc Valin <[email protected]>
date: Fri Oct 16 19:16:47 EDT 2009

Constrain the pitch gain to prevent potential instabilities.

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -211,7 +211,7 @@
    }
 }
 
-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 @@
       *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;
--- a/libcelt/bands.h
+++ b/libcelt/bands.h
@@ -71,7 +71,7 @@
  * @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);
 
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -88,6 +88,7 @@
    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 @@
    {
       
       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)