Added a post-filter for narrowband (and thus 0-4 kHz in wideband)
authorjmvalin <jmvalin@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Wed, 29 May 2002 03:41:29 +0000 (03:41 +0000)
committerjmvalin <jmvalin@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Wed, 29 May 2002 03:41:29 +0000 (03:41 +0000)
git-svn-id: http://svn.xiph.org/trunk/speex@3329 0101bb08-14d6-0310-b084-bc0e0c8e3800

libspeex/Makefile.am
libspeex/ltp.c
libspeex/ltp.h
libspeex/modes.c
libspeex/modes.h
libspeex/nb_celp.c
libspeex/nb_celp.h
libspeex/post_filter.c [new file with mode: 0644]
libspeex/post_filter.h [new file with mode: 0644]

index 6133824..8f1bee3 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in. -*-Makefile-*-
 
-# $Id: Makefile.am,v 1.28 2002/05/15 21:47:51 jmvalin Exp $
+# $Id: Makefile.am,v 1.29 2002/05/29 03:41:28 jmvalin Exp $
 
 # Disable automatic dependency tracking if using other tools than gcc and gmake
 #AUTOMAKE_OPTIONS = no-dependencies
@@ -26,7 +26,8 @@ libspeex_la_SOURCES = nb_celp.c \
        vbr.c \
        hexc_table.c \
        exc_5_256_table.c \
-       exc_5_64_table.c
+       exc_5_64_table.c \
+       post_filter.c
 
 
 include_HEADERS =  speex.h \
@@ -43,7 +44,8 @@ noinst_HEADERS = lsp.h \
        vq.h \
        modes.h \
        sb_celp.h \
-       vbr.h
+       vbr.h \
+       post_filter.h
        
        
 libspeex_la_LDFLAGS = -release $(LT_RELEASE)
index 410e3ed..560ed70 100644 (file)
@@ -230,8 +230,9 @@ float *stack
 
 }
 
-void pitch_search_3tap_unquant(
+int pitch_search_3tap_unquant(
 float target[],                 /* Target vector */
+float *sw,
 float ak[],                     /* LPCs for this subframe */
 float awk1[],                   /* Weighted LPCs #1 for this subframe */
 float awk2[],                   /* Weighted LPCs #2 for this subframe */
@@ -242,7 +243,8 @@ int   end,                      /* Largest pitch value allowed */
 int   p,                        /* Number of LPC coeffs */
 int   nsf,                      /* Number of samples in subframe */
 SpeexBits *bits,
-float *stack
+float *stack,
+float *exc2
 )
 {
    int i,j;
@@ -322,6 +324,7 @@ float *stack
    }
 #endif
    POP(stack);
+   return pitch;
 }
 
 
@@ -537,6 +540,8 @@ int   start,                    /* Smallest pitch value allowed */
 int   end,                      /* Largest pitch value allowed */
 void *par,
 int   nsf,                      /* Number of samples in subframe */
+int *pitch_val,
+float *gain_val,
 SpeexBits *bits,
 float *stack,
 int lost)
@@ -567,6 +572,10 @@ int lost)
             gain[i]*=fact;
       }
    }
+
+   *pitch_val = pitch;
+   *gain_val = gain[0]+gain[1]+gain[2];
+
 #ifdef DEBUG
    printf ("unquantized pitch: %d %f %f %f\n", pitch, gain[0], gain[1], gain[2]);
 #endif
index 312e8b3..5267203 100644 (file)
@@ -68,8 +68,9 @@ float *exc2
 );
 
 /** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
-void pitch_search_3tap_unquant(
+int pitch_search_3tap_unquant(
 float target[],                 /* Target vector */
+float *sw,
 float ak[],                     /* LPCs for this subframe */
 float awk1[],                   /* Weighted LPCs #1 for this subframe */
 float awk2[],                   /* Weighted LPCs #2 for this subframe */
@@ -80,7 +81,8 @@ int   end,                      /* Largest pitch value allowed */
 int   p,                        /* Number of LPC coeffs */
 int   nsf,                      /* Number of samples in subframe */
 SpeexBits *bits,
-float *stack
+float *stack,
+float *exc2
 );
 
 /*Unquantize adaptive codebook and update pitch contribution*/
@@ -90,6 +92,8 @@ int   start,                    /* Smallest pitch value allowed */
 int   end,                      /* Largest pitch value allowed */
 void *par,
 int   nsf,                      /* Number of samples in subframe */
+int *pitch_val,
+float *gain_val,
 SpeexBits *bits,
 float *stack,
 int lost
index 103a61a..3d77e8a 100644 (file)
@@ -32,7 +32,6 @@
 extern float gain_cdbk_nb[];
 extern float hexc_table[];
 extern float exc_5_256_table[];
-/*extern float exc_8_256_table[];*/
 extern float exc_5_64_table[];
 
 /* Parameters for Long-Term Prediction (LTP)*/
index 987fbe7..0bdbc61 100644 (file)
@@ -38,7 +38,7 @@ typedef int (*ltp_quant_func)(float *, float *, float *, float *,
                                 int, int, SpeexBits*, float *, float *);
 
 /*Long-term un-quantize*/
-typedef void (*ltp_unquant_func)(float *, int, int, void *, int, SpeexBits*, float*, int);
+typedef void (*ltp_unquant_func)(float *, int, int, void *, int, int *, float *, SpeexBits*, float*, int);
 
 
 typedef void (*innovation_quant_func)(float *, float *, float *, float *, void *, int, int, 
index dd37046..871f15f 100644 (file)
@@ -30,6 +30,7 @@
 #include "stack_alloc.h"
 #include "vq.h"
 #include "speex_bits.h"
+#include "post_filter.h"
 
 #ifndef M_PI
 #define M_PI           3.14159265358979323846  /* pi */
@@ -429,7 +430,7 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
          ener=sign/sqrt(.01+ener/st->subframeSize);
          for (i=0;i<st->subframeSize;i++)
          {
-            if (i%4==0)
+            if (i%10==0)
                printf ("\nexc ");
             printf ("%f ", ener*st->buf2[i]);
          }
@@ -485,6 +486,8 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
             exc[i] += st->buf2[i];
 #endif
          POP(st->stack);
+         for (i=0;i<st->subframeSize;i++)
+            target[i]*=ener;
 
       }
 #endif
@@ -493,9 +496,9 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
       for (i=0;i<st->subframeSize;i++)
          enoise += target[i]*target[i];
       snr = 10*log10((esig+1)/(enoise+1));
-#ifdef DEBUG
+
       printf ("seg SNR = %f\n", snr);
-#endif
+
       /*Keep the previous memory*/
       for (i=0;i<st->lpcSize;i++)
          mem[i]=st->mem_sp[i];
@@ -585,10 +588,14 @@ void *nb_decoder_init(SpeexMode *m)
    st->frame = st->inBuf + st->bufSize - st->windowSize;
    st->excBuf = malloc(st->bufSize*sizeof(float));
    st->exc = st->excBuf + st->bufSize - st->windowSize;
+   st->exc2Buf = malloc(st->bufSize*sizeof(float));
+   st->exc2 = st->exc2Buf + st->bufSize - st->windowSize;
    for (i=0;i<st->bufSize;i++)
       st->inBuf[i]=0;
    for (i=0;i<st->bufSize;i++)
       st->excBuf[i]=0;
+   for (i=0;i<st->bufSize;i++)
+      st->exc2Buf[i]=0;
 
    st->interp_qlpc = malloc((st->lpcSize+1)*sizeof(float));
    st->qlsp = malloc(st->lpcSize*sizeof(float));
@@ -607,6 +614,7 @@ void nb_decoder_destroy(void *state)
    st=state;
    free(st->inBuf);
    free(st->excBuf);
+   free(st->exc2Buf);
    free(st->interp_qlpc);
    free(st->qlsp);
    free(st->old_qlsp);
@@ -622,11 +630,14 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
 {
    DecState *st;
    int i, sub;
+   int pitch;
+   float pitch_gain;
 
    st=state;
 
    memmove(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
    memmove(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
+   memmove(st->exc2Buf, st->exc2Buf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
 
 
    st->lsp_unquant(st->qlsp, st->lpcSize, bits);
@@ -640,7 +651,7 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
    for (sub=0;sub<st->nbSubframes;sub++)
    {
       int offset;
-      float *sp, *exc, tmp;
+      float *sp, *exc, *exc2, tmp;
       
       /* Offset relative to start of frame */
       offset = st->subframeSize*sub;
@@ -648,6 +659,8 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
       sp=st->frame+offset;
       /* Excitation */
       exc=st->exc+offset;
+      /* Excitation after post-filter*/
+      exc2=st->exc2+offset;
 
       /* LSP interpolation (quantized and unquantized) */
       tmp = (.5 + sub)/st->nbSubframes;
@@ -672,7 +685,7 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
          exc[i]=0;
 
       /*Adaptive codebook contribution*/
-      st->ltp_unquant(exc, st->min_pitch, st->max_pitch, st->ltp_params, st->subframeSize, bits, st->stack, lost);
+      st->ltp_unquant(exc, st->min_pitch, st->max_pitch, st->ltp_params, st->subframeSize, &pitch, &pitch_gain, bits, st->stack, lost);
       
 
       {
@@ -697,8 +710,13 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
          POP(st->stack);
       }
 
+      for (i=0;i<st->subframeSize;i++)
+         exc2[i]=exc[i];
+      /*nb_post_filter(exc, exc2, st->interp_qlpc, st->lpcSize, st->subframeSize,
+        pitch, pitch_gain, st->stack);*/
+
       /*Compute decoded signal*/
-      syn_filt_mem(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp);
+      syn_filt_mem(exc2, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp);
 
    }
    
index 08f6e28..bb2af28 100644 (file)
@@ -105,7 +105,9 @@ typedef struct DecState {
    float *inBuf;          /* Input buffer (original signal) */
    float *frame;          /* Start of original frame */
    float *excBuf;         /* Excitation buffer */
+   float *exc2Buf;        /* Excitation (after post-filter) buffer */
    float *exc;            /* Start of excitation frame */
+   float *exc2;           /* Start of excitation frame after post-filter*/
    float *qlsp;           /* Quantized LSPs for current frame */
    float *old_qlsp;       /* Quantized LSPs for previous frame */
    float *interp_qlsp;    /* Interpolated quantized LSPs */
diff --git a/libspeex/post_filter.c b/libspeex/post_filter.c
new file mode 100644 (file)
index 0000000..cacb3bc
--- /dev/null
@@ -0,0 +1,62 @@
+/* Copyright (C) 2002 Jean-Marc Valin 
+   File: post_filter.c
+   Post-filtering routines: processing to enhance perceptual quality
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+   
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <math.h>
+#include "filters.h"
+#include "stack_alloc.h"
+
+/* Perceptual post-filter for narrowband */
+void nb_post_filter(
+float *exc, 
+float *new_exc, 
+float *ak, 
+int p, 
+int nsf,
+int pitch,
+float pitch_gain,
+float *stack)
+{
+   int i;
+   float exc_energy=0, new_exc_energy=0;
+   float *awk;
+   float gain;
+
+   awk = PUSH(stack, p);
+   
+   bw_lpc (0.1, ak, awk, p);
+
+   for (i=0;i<nsf;i++)
+      exc_energy+=exc[i]*exc[i];
+
+   for (i=0;i<nsf;i++)
+   {
+      new_exc[i] = exc[i] + .4*pitch_gain*exc[i-pitch];
+   }
+   
+   syn_filt(new_exc, awk, new_exc, nsf, p);
+
+   for (i=0;i<nsf;i++)
+      new_exc_energy+=new_exc[i]*new_exc[i];
+
+   gain = sqrt(exc_energy)/sqrt(.1+new_exc_energy);
+   for (i=0;i<nsf;i++)
+      new_exc[i] *= gain;
+
+   POP(stack);
+}
diff --git a/libspeex/post_filter.h b/libspeex/post_filter.h
new file mode 100644 (file)
index 0000000..d16c4bc
--- /dev/null
@@ -0,0 +1,35 @@
+/* Copyright (C) 2002 Jean-Marc Valin 
+   File: post_filter.h
+   Post-filtering routines: processing to enhance perceptual quality
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+   
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef POST_FILTER_H
+#define POST_FILTER_H
+
+/* Perceptual post-filter for narrowband */
+void nb_post_filter(
+float *exc, 
+float *new_exc, 
+float *ak, 
+int p, 
+int nsf,
+int pitch,
+float pitch_gain,
+float *stack);
+
+
+#endif