Improvements to the perceptual enhancement code: smoother pitch comb
authorjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Fri, 20 Dec 2002 07:16:10 +0000 (07:16 +0000)
committerjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Fri, 20 Dec 2002 07:16:10 +0000 (07:16 +0000)
filter, better tuning, and a stupid bugfix (gain hard-coded to .5).

git-svn-id: http://svn.xiph.org/trunk/speex@4162 0101bb08-14d6-0310-b084-bc0e0c8e3800

libspeex/filters.c
libspeex/filters.h
libspeex/modes.c
libspeex/nb_celp.c
libspeex/nb_celp.h

index 6b871db..8846ed6 100644 (file)
@@ -211,6 +211,13 @@ void fir_mem_up(float *x, float *a, float *y, int N, int M, float *mem, void *st
 }
 
 
+void comp_filter_mem_init (CombFilterMem *mem)
+{
+   mem->last_pitch=0;
+   mem->last_pitch_gain[0]=mem->last_pitch_gain[1]=mem->last_pitch_gain[2]=0;
+   mem->smooth_gain=1;
+}
+
 void comb_filter(
 float *exc,          /*decoded excitation*/
 float *new_exc,      /*enhanced excitation*/
@@ -219,33 +226,67 @@ int p,               /*LPC order*/
 int nsf,             /*sub-frame size*/
 int pitch,           /*pitch period*/
 float *pitch_gain,   /*pitch gain (3-tap)*/
-float  comb_gain     /*gain of comb filter*/
+float  comb_gain,    /*gain of comb filter*/
+CombFilterMem *mem
 )
 {
    int i;
    float exc_energy=0, new_exc_energy=0;
    float gain;
-
+   float step;
+   float fact;
    /*Compute excitation energy prior to enhancement*/
    for (i=0;i<nsf;i++)
       exc_energy+=exc[i]*exc[i];
 
+   /*Some gain adjustment is pitch is too high or if unvoiced*/
+   {
+      float g=0;
+      g = .5*fabs(pitch_gain[0]+pitch_gain[1]+pitch_gain[2] +
+      mem->last_pitch_gain[0] + mem->last_pitch_gain[1] + mem->last_pitch_gain[2]);
+      if (g>1.3)
+         comb_gain*=1.3/g;
+      if (g<.5)
+         comb_gain*=2*g;
+   }
+   step = 1.0/nsf;
+   fact=0;
    /*Apply pitch comb-filter (filter out noise between pitch harmonics)*/
    for (i=0;i<nsf;i++)
    {
-      new_exc[i] = exc[i] + comb_gain * (
+      fact += step;
+
+      new_exc[i] = exc[i] + comb_gain * fact * (
                                          pitch_gain[0]*exc[i-pitch+1] +
                                          pitch_gain[1]*exc[i-pitch] +
                                          pitch_gain[2]*exc[i-pitch-1]
+                                         )
+      + comb_gain * (1-fact) * (
+                                         mem->last_pitch_gain[0]*exc[i-mem->last_pitch+1] +
+                                         mem->last_pitch_gain[1]*exc[i-mem->last_pitch] +
+                                         mem->last_pitch_gain[2]*exc[i-mem->last_pitch-1]
                                          );
    }
-   
+
+   mem->last_pitch_gain[0] = pitch_gain[0];
+   mem->last_pitch_gain[1] = pitch_gain[1];
+   mem->last_pitch_gain[2] = pitch_gain[2];
+   mem->last_pitch = pitch;
+
    /*Gain after enhancement*/
    for (i=0;i<nsf;i++)
       new_exc_energy+=new_exc[i]*new_exc[i];
 
    /*Compute scaling factor and normalize energy*/
    gain = sqrt(exc_energy)/sqrt(.1+new_exc_energy);
+   if (gain < .5)
+      gain=.5;
+   if (gain>1)
+      gain=1;
+
    for (i=0;i<nsf;i++)
-      new_exc[i] *= gain;
+   {
+      mem->smooth_gain = .96*mem->smooth_gain + .04*gain;
+      new_exc[i] *= mem->smooth_gain;
+   }
 }
index bbc9bb6..32cb3fd 100644 (file)
 #ifndef FILTERS_H
 #define FILTERS_H
 
+
+typedef struct CombFilterMem {
+   int   last_pitch;
+   float last_pitch_gain[3];
+   float smooth_gain;
+} CombFilterMem;
+
+
 void qmf_decomp(float *xx, float *aa, float *y1, float *y2, int N, int M, float *mem, void *stack);
 void fir_mem_up(float *x, float *a, float *y, int N, int M, float *mem, void *stack);
 
@@ -53,6 +61,8 @@ void syn_percep_zero(float *x, float *ak, float *awk1, float *awk2, float *y, in
 
 void residue_percep_zero(float *xx, float *ak, float *awk1, float *awk2, float *y, int N, int ord, void *stack);
 
+void comp_filter_mem_init (CombFilterMem *mem);
+
 void comb_filter(
 float *exc,          /*decoded excitation*/
 float *new_exc,      /*enhanced excitation*/
@@ -61,7 +71,8 @@ int p,               /*LPC order*/
 int nsf,             /*sub-frame size*/
 int pitch,           /*pitch period*/
 float *pitch_gain,   /*pitch gain (3-tap)*/
-float  comb_gain     /*gain of comb filter*/
+float  comb_gain,    /*gain of comb filter*/
+CombFilterMem *mem
 );
 
 
index 660ab72..bb4cea3 100644 (file)
@@ -168,7 +168,7 @@ static SpeexSubmode nb_submode1 = {
    noise_codebook_quant,
    noise_codebook_unquant,
    NULL,
-   0, 0, -1,
+   .7, .7, -1,
    43
 };
 
@@ -190,7 +190,7 @@ static SpeexSubmode nb_submode2 = {
    split_cb_shape_sign_unquant,
    &split_cb_nb_vlbr,
 
-   0.75, 0.6, .6,
+   0.7, 0.5, .55,
    119
 };
 
@@ -212,7 +212,7 @@ static SpeexSubmode nb_submode3 = {
    split_cb_shape_sign_unquant,
    &split_cb_nb_lbr,
 
-   0.75, 0.6, .5,
+   0.7, 0.55, .45,
    160
 };
 
@@ -234,7 +234,7 @@ static SpeexSubmode nb_submode4 = {
    split_cb_shape_sign_unquant,
    &split_cb_nb_med,
 
-   0.72, 0.65, .3,
+   0.7, 0.63, .35,
    220
 };
 
@@ -256,7 +256,7 @@ static SpeexSubmode nb_submode5 = {
    split_cb_shape_sign_unquant,
    &split_cb_nb,
 
-   0.7, 0.65, .2,
+   0.7, 0.65, .25,
    300
 };
 
@@ -300,7 +300,7 @@ static SpeexSubmode nb_submode7 = {
    split_cb_shape_sign_unquant,
    &split_cb_nb,
 
-   0.65, 0.65, 0,
+   0.65, 0.65, -1,
    492
 };
 
index 6d09c05..3eee450 100644 (file)
@@ -873,6 +873,8 @@ void *nb_decoder_init(SpeexMode *m)
    st->old_qlsp = (float*)speex_alloc(st->lpcSize*sizeof(float));
    st->interp_qlsp = (float*)speex_alloc(st->lpcSize*sizeof(float));
    st->mem_sp = (float*)speex_alloc(5*st->lpcSize*sizeof(float));
+   st->comb_mem = (CombFilterMem *) speex_alloc(sizeof(CombFilterMem));
+   comp_filter_mem_init (st->comb_mem);
 
    st->pi_gain = (float*)speex_alloc(st->nbSubframes*sizeof(float));
    st->last_pitch = 40;
@@ -908,6 +910,7 @@ void nb_decoder_destroy(void *state)
    speex_free(st->stack);
    speex_free(st->mem_sp);
    speex_free(st->pi_gain);
+   speex_free(st->comb_mem);
    
    speex_free(state);
 }
@@ -1221,7 +1224,6 @@ int nb_decode(void *state, SpeexBits *bits, float *out)
          k1=SUBMODE(lpc_enh_k1);
          k2=SUBMODE(lpc_enh_k2);
          k3=(1-(1-r*k1)/(1-r*k2))/r;
-         k3=k1-k2;
          if (!st->lpc_enh_enabled)
          {
             k1=k2;
@@ -1408,9 +1410,9 @@ int nb_decode(void *state, SpeexBits *bits, float *out)
          sp[i]=exc[i];
 
       /* Signal synthesis */
-      if (st->lpc_enh_enabled && SUBMODE(comb_gain>0))
+      if (st->lpc_enh_enabled && SUBMODE(comb_gain)>0)
          comb_filter(exc, sp, st->interp_qlpc, st->lpcSize, st->subframeSize,
-                              pitch, pitch_gain, .5);
+                              pitch, pitch_gain, SUBMODE(comb_gain), st->comb_mem);
       if (st->lpc_enh_enabled)
       {
          /* Use enhanced LPC filter */
index ba1a55c..d47717d 100644 (file)
@@ -40,6 +40,7 @@
 #include "speex_bits.h"
 #include "speex_callbacks.h"
 #include "vbr.h"
+#include "filters.h"
 
 /**Structure representing the full state of the narrowband encoder*/
 typedef struct EncState {
@@ -157,7 +158,7 @@ typedef struct DecState {
    SpeexSubmode **submodes; /**< Sub-mode data */
    int    submodeID;      /**< Activated sub-mode */
    int    lpc_enh_enabled; /**< 1 when LPC enhancer is on, 0 otherwise */
-
+   CombFilterMem *comb_mem;
    SpeexCallback speex_callbacks[SPEEX_MAX_CALLBACKS];
 
    SpeexCallback user_callback;