Wideband code cleanup, first shot at an "ultra-wideband" mode at 32 kHz,
authorjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Wed, 30 Oct 2002 22:12:19 +0000 (22:12 +0000)
committerjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Wed, 30 Oct 2002 22:12:19 +0000 (22:12 +0000)
but still buggy.

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

libspeex/Makefile.am
libspeex/math_approx.h
libspeex/modes.c
libspeex/nb_celp.c
libspeex/sb_celp.c
libspeex/sb_celp.h
libspeex/speex.h
libspeex/testenc_uwb.c [new file with mode: 0644]

index 0e5ca72..eb592d7 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in. -*-Makefile-*-
 
-# $Id: Makefile.am,v 1.43 2002/10/30 20:27:03 jm Exp $
+# $Id: Makefile.am,v 1.44 2002/10/30 22:12:19 jm Exp $
 
 # Disable automatic dependency tracking if using other tools than gcc and gmake
 #AUTOMAKE_OPTIONS = no-dependencies
@@ -62,10 +62,13 @@ noinst_HEADERS = lsp.h \
        
 libspeex_la_LDFLAGS = -release $(LT_RELEASE)
 
-noinst_PROGRAMS = testenc testenc_wb
+noinst_PROGRAMS = testenc testenc_wb testenc_uwb
 
 testenc_SOURCES = testenc.c
 testenc_LDADD = libspeex.la
 
 testenc_wb_SOURCES = testenc_wb.c
 testenc_wb_LDADD = libspeex.la
+
+testenc_uwb_SOURCES = testenc_uwb.c
+testenc_uwb_LDADD = libspeex.la
index 87b7502..c917ffd 100644 (file)
@@ -1 +1,39 @@
+/* Copyright (C) 2002 Jean-Marc Valin 
+   File: math_approx.c
+   Various math approximation functions for Speex
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MATH_APPROX_H
+#define MATH_APPROX_H
+
 float speex_cos(float x);
+
+
+#endif
index 56471ef..98a36d6 100644 (file)
@@ -323,6 +323,7 @@ static SpeexNBMode nb_mode = {
 };
 
 
+/* Default mode for narrowband */
 SpeexMode speex_nb_mode = {
    &nb_mode,
    nb_mode_query,
@@ -339,6 +340,9 @@ SpeexMode speex_nb_mode = {
    &nb_decoder_ctl,
 };
 
+
+/* Wideband part */
+
 static SpeexSubmode wb_submode1 = {
    0,
    0,
@@ -446,7 +450,7 @@ static SpeexSBMode sb_wb_mode = {
 SpeexMode speex_wb_mode = {
    &sb_wb_mode,
    wb_mode_query,
-   "full-rate wideband (sub-band CELP)",
+   "wideband (sub-band CELP)",
    1,
    4,
    &sb_encoder_init,
@@ -461,6 +465,46 @@ SpeexMode speex_wb_mode = {
 
 
 
+/* "Ultra-wideband" mode stuff */
+
+
+
+/* Split-band "ultra-wideband" (32 kbps) CELP mode*/
+static SpeexSBMode sb_uwb_mode = {
+   &speex_wb_mode,
+   320,    /*frameSize*/
+   80,     /*subframeSize*/
+   8,     /*lpcSize*/
+   1280,    /*bufSize*/
+   .9,    /*gamma1*/
+   0.6,    /*gamma2*/
+   .002,   /*lag_factor*/
+   1.0001, /*lpc_floor*/
+   0.0,    /*preemph*/
+   {NULL, &wb_submode1, NULL, NULL, NULL, NULL, NULL, NULL},
+   1
+};
+
+
+SpeexMode speex_uwb_mode = {
+   &sb_uwb_mode,
+   wb_mode_query,
+   "ultra-wideband (sub-band CELP)",
+   1,
+   4,
+   &sb_encoder_init,
+   &sb_encoder_destroy,
+   &sb_encode,
+   &sb_decoder_init,
+   &sb_decoder_destroy,
+   &sb_decode,
+   &sb_encoder_ctl,
+   &sb_decoder_ctl,
+};
+
+
+
+
 void *speex_encoder_init(SpeexMode *mode)
 {
    return mode->enc_init(mode);
index 1782f69..ff98827 100644 (file)
@@ -1283,6 +1283,30 @@ void nb_encoder_ctl(void *state, int request, void *ptr)
       else
          (*(int*)ptr) = 50*(NB_SUBMODE_BITS+1);
       break;
+   case SPEEX_GET_PI_GAIN:
+      {
+         int i;
+         float *g = (float*)ptr;
+         for (i=0;i<st->nbSubframes;i++)
+            g[i]=st->pi_gain[i];
+      }
+      break;
+   case SPEEX_GET_EXC:
+      {
+         int i;
+         float *e = (float*)ptr;
+         for (i=0;i<st->frameSize;i++)
+            e[i]=st->exc[i];
+      }
+      break;
+   case SPEEX_GET_INNOV:
+      {
+         int i;
+         float *e = (float*)ptr;
+         for (i=0;i<st->frameSize;i++)
+            e[i]=st->innov[i];
+      }
+      break;
    default:
       fprintf(stderr, "Unknown nb_ctl request: %d\n", request);
    }
@@ -1325,6 +1349,30 @@ void nb_decoder_ctl(void *state, int request, void *ptr)
          st->user_callback.callback_id=c->callback_id;
       }
       break;
+   case SPEEX_GET_PI_GAIN:
+      {
+         int i;
+         float *g = (float*)ptr;
+         for (i=0;i<st->nbSubframes;i++)
+            g[i]=st->pi_gain[i];
+      }
+      break;
+   case SPEEX_GET_EXC:
+      {
+         int i;
+         float *e = (float*)ptr;
+         for (i=0;i<st->frameSize;i++)
+            e[i]=st->exc[i];
+      }
+      break;
+   case SPEEX_GET_INNOV:
+      {
+         int i;
+         float *e = (float*)ptr;
+         for (i=0;i<st->frameSize;i++)
+            e[i]=st->innov[i];
+      }
+      break;
    default:
       fprintf(stderr, "Unknown nb_ctl request: %d\n", request);
    }
index 290a6fb..d4e0569 100644 (file)
@@ -135,7 +135,7 @@ void *sb_encoder_init(SpeexMode *m)
    st->mode = m;
    mode = (SpeexSBMode*)m->mode;
 
-   st->st_low = nb_encoder_init(mode->nb_mode);
+   st->st_low = speex_encoder_init(mode->nb_mode);
    st->full_frame_size = 2*mode->frameSize;
    st->frame_size = mode->frameSize;
    st->subframeSize = mode->subframeSize;
@@ -146,7 +146,9 @@ void *sb_encoder_init(SpeexMode *m)
 
    st->submodes=mode->submodes;
    st->submodeID=mode->defaultSubmode;
+   
    {
+      /* FIXME: Should do this without explicit reference to a mode */
       int mod=6;
       speex_encoder_ctl(st->st_low, SPEEX_SET_MODE, &mod);
    }
@@ -156,7 +158,7 @@ void *sb_encoder_init(SpeexMode *m)
    st->gamma1=mode->gamma1;
    st->gamma2=mode->gamma2;
    st->first=1;
-   st->stack = speex_alloc(10000*sizeof(float));
+   st->stack = speex_alloc(20000*sizeof(float));
 
    st->x0d=(float*)speex_alloc(st->frame_size*sizeof(float));
    st->x1d=(float*)speex_alloc(st->frame_size*sizeof(float));
@@ -205,6 +207,7 @@ void *sb_encoder_init(SpeexMode *m)
    st->interp_qlsp = (float*)speex_alloc(st->lpcSize*sizeof(float));
    st->interp_lpc = (float*)speex_alloc((st->lpcSize+1)*sizeof(float));
    st->interp_qlpc = (float*)speex_alloc((st->lpcSize+1)*sizeof(float));
+   st->pi_gain = (float*)speex_alloc(st->nbSubframes*sizeof(float));
 
    st->mem_sp = (float*)speex_alloc(st->lpcSize*sizeof(float));
    st->mem_sp2 = (float*)speex_alloc(st->lpcSize*sizeof(float));
@@ -218,7 +221,7 @@ void sb_encoder_destroy(void *state)
 {
    SBEncState *st=(SBEncState*)state;
 
-   nb_encoder_destroy(st->st_low);
+   speex_encoder_destroy(st->st_low);
    speex_free(st->x0d);
    speex_free(st->x1d);
    speex_free(st->high);
@@ -253,6 +256,7 @@ void sb_encoder_destroy(void *state)
    speex_free(st->mem_sp);
    speex_free(st->mem_sp2);
    speex_free(st->mem_sw);
+   speex_free(st->pi_gain);
 
    speex_free(st->stack);
 
@@ -266,15 +270,16 @@ void sb_encode(void *state, float *in, SpeexBits *bits)
    int i, roots, sub;
    void *stack;
    float *mem, *innov, *syn_resp;
+   float *low_pi_gain, *low_exc, *low_innov;
 
    st = (SBEncState*)state;
    stack=st->stack;
 
    /* Compute the two sub-bands by filtering with h0 and h1*/
    qmf_decomp(in, h0, st->x0d, st->x1d, st->full_frame_size, QMF_ORDER, st->h0_mem, stack);
-
+    
    /* Encode the narrowband part*/
-   nb_encode(st->st_low, st->x0d, bits);
+   speex_encode(st->st_low, st->x0d, bits);
 
    speex_bits_pack(bits, 1, 1);
    speex_bits_pack(bits, st->submodeID, SB_SUBMODE_BITS);
@@ -287,8 +292,15 @@ void sb_encode(void *state, float *in, SpeexBits *bits)
 
    speex_move(st->excBuf, st->excBuf+st->frame_size, (st->bufSize-st->frame_size)*sizeof(float));
 
-   /* Start encoding the high-band */
 
+   low_pi_gain = PUSH(stack, st->nbSubframes, float);
+   low_exc = PUSH(stack, st->frame_size, float);
+   low_innov = PUSH(stack, st->frame_size, float);
+   speex_encoder_ctl(st->st_low, SPEEX_GET_PI_GAIN, low_pi_gain);
+   speex_encoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc);
+   speex_encoder_ctl(st->st_low, SPEEX_GET_INNOV, low_innov);
+   
+   /* Start encoding the high-band */
    for (i=0;i<st->windowSize;i++)
       st->buf[i] = st->high[i] * st->window[i];
 
@@ -421,7 +433,8 @@ void sb_encode(void *state, float *in, SpeexBits *bits)
          rh += tmp*st->interp_qlpc[i];
          tmp = -tmp;
       }
-      rl = ((EncState*)st->st_low)->pi_gain[sub];
+      rl = low_pi_gain[sub];
+      st->pi_gain[sub]=rh;
       rl=1/(fabs(rl)+.01);
       rh=1/(fabs(rh)+.01);
       /* Compute ratio, will help predict the gain */
@@ -441,7 +454,7 @@ void sb_encode(void *state, float *in, SpeexBits *bits)
          float g;
          /*speex_bits_pack(bits, 1, 1);*/
          for (i=0;i<st->subframeSize;i++)
-            el+=sqr(((EncState*)st->st_low)->innov[offset+i]);
+            el+=sqr(low_innov[offset+i]);
 
          /* Gain to use if we want to use the low-band excitation for high-band */
          g=eh/(.01+el);
@@ -465,7 +478,7 @@ void sb_encode(void *state, float *in, SpeexBits *bits)
          float gc, scale, scale_1;
 
          for (i=0;i<st->subframeSize;i++)
-            el+=sqr(((EncState*)st->st_low)->exc[offset+i]);
+            el+=sqr(low_exc[offset+i]);
          /*speex_bits_pack(bits, 0, 1);*/
 
          gc = sqrt(1+eh)*filter_ratio/sqrt((1+el)*st->subframeSize);
@@ -611,7 +624,7 @@ void *sb_decoder_init(SpeexMode *m)
    st->mode = m;
    mode=(SpeexSBMode*)m->mode;
 
-   st->st_low = nb_decoder_init(mode->nb_mode);
+   st->st_low = speex_decoder_init(mode->nb_mode);
    st->full_frame_size = 2*mode->frameSize;
    st->frame_size = mode->frameSize;
    st->subframeSize = 40;
@@ -622,7 +635,7 @@ void *sb_decoder_init(SpeexMode *m)
    st->submodeID=mode->defaultSubmode;
 
    st->first=1;
-   st->stack = speex_alloc(10000*sizeof(float));
+   st->stack = speex_alloc(20000*sizeof(float));
 
    st->x0d=(float*)speex_alloc(st->frame_size*sizeof(float));
    st->x1d=(float*)speex_alloc(st->frame_size*sizeof(float));
@@ -642,6 +655,7 @@ void *sb_decoder_init(SpeexMode *m)
    st->interp_qlsp = (float*)speex_alloc(st->lpcSize*sizeof(float));
    st->interp_qlpc = (float*)speex_alloc((st->lpcSize+1)*sizeof(float));
 
+   st->pi_gain = (float*)speex_alloc(st->nbSubframes*sizeof(float));
    st->mem_sp = (float*)speex_alloc(st->lpcSize*sizeof(float));
    return st;
 }
@@ -650,7 +664,7 @@ void sb_decoder_destroy(void *state)
 {
    SBDecState *st;
    st = (SBDecState*)state;
-   nb_decoder_destroy(st->st_low);
+   speex_decoder_destroy(st->st_low);
    speex_free(st->x0d);
    speex_free(st->x1d);
    speex_free(st->high);
@@ -666,6 +680,7 @@ void sb_decoder_destroy(void *state)
    speex_free(st->old_qlsp);
    speex_free(st->interp_qlsp);
    speex_free(st->interp_qlpc);
+   speex_free(st->pi_gain);
 
    speex_free(st->mem_sp);
 
@@ -702,12 +717,13 @@ int sb_decode(void *state, SpeexBits *bits, float *out)
    int wideband;
    int ret;
    void *stack;
+   float *low_pi_gain, *low_exc, *low_innov;
 
    st = (SBDecState*)state;
    stack=st->stack;
 
    /* Decode the low-band */
-   ret = nb_decode(st->st_low, bits, st->x0d);
+   ret = speex_decode(st->st_low, bits, st->x0d);
 
    /* If error decoding the narrowband part, propagate error */
    if (ret!=0)
@@ -758,6 +774,13 @@ int sb_decode(void *state, SpeexBits *bits, float *out)
 
    }
 
+   low_pi_gain = PUSH(stack, st->nbSubframes, float);
+   low_exc = PUSH(stack, st->frame_size, float);
+   low_innov = PUSH(stack, st->frame_size, float);
+   speex_decoder_ctl(st->st_low, SPEEX_GET_PI_GAIN, low_pi_gain);
+   speex_decoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc);
+   speex_decoder_ctl(st->st_low, SPEEX_GET_INNOV, low_innov);
+
 
    SUBMODE(lsp_unquant)(st->qlsp, st->lpcSize, bits);
    
@@ -800,7 +823,8 @@ int sb_decode(void *state, SpeexBits *bits, float *out)
             rh += tmp*st->interp_qlpc[i];
             tmp = -tmp;
          }
-         rl = ((DecState*)st->st_low)->pi_gain[sub];
+         rl = low_pi_gain[sub];
+         st->pi_gain[sub]=rh;
          rl=1/(fabs(rl)+.01);
          rh=1/(fabs(rh)+.01);
          filter_ratio=fabs(.01+rh)/(.01+fabs(rl));
@@ -814,7 +838,7 @@ int sb_decode(void *state, SpeexBits *bits, float *out)
          int quant;
 
          for (i=0;i<st->subframeSize;i++)
-            el+=sqr(((DecState*)st->st_low)->innov[offset+i]);
+            el+=sqr(low_innov[offset+i]);
          quant = speex_bits_unpack_unsigned(bits, 5);
          g= exp(((float)quant-27)/8.0);
          
@@ -823,12 +847,12 @@ int sb_decode(void *state, SpeexBits *bits, float *out)
          
          /* High-band excitation using the low-band excitation and a gain */
          for (i=0;i<st->subframeSize;i++)
-            exc[i]=.8*g*((DecState*)st->st_low)->innov[offset+i];
+            exc[i]=.8*g*low_innov[offset+i];
       } else {
          float gc, scale;
          int qgc = speex_bits_unpack_unsigned(bits, 4);
          for (i=0;i<st->subframeSize;i++)
-            el+=sqr(((DecState*)st->st_low)->exc[offset+i]);
+            el+=sqr(low_exc[offset+i]);
 
 
          gc = exp((1/3.7)*qgc-2);
@@ -973,6 +997,34 @@ void sb_encoder_ctl(void *state, int request, void *ptr)
       else
          (*(int*)ptr) += 50*(SB_SUBMODE_BITS+1);
       break;
+   case SPEEX_GET_PI_GAIN:
+      {
+         int i;
+         float *g = (float*)ptr;
+         for (i=0;i<st->nbSubframes;i++)
+            g[i]=st->pi_gain[i];
+      }
+      break;
+   case SPEEX_GET_EXC:
+      {
+         int i;
+         float *e = (float*)ptr;
+         for (i=0;i<st->full_frame_size;i++)
+            e[i]=0;
+         for (i=0;i<st->frame_size;i++)
+            e[2*i]=st->exc[i];
+      }
+      break;
+   case SPEEX_GET_INNOV:
+      {
+         int i;
+         float *e = (float*)ptr;
+         for (i=0;i<st->full_frame_size;i++)
+            e[i]=0;
+         for (i=0;i<st->frame_size;i++)
+            e[2*i]=st->exc[i];
+      }
+      break;
    default:
       fprintf(stderr, "Unknown nb_ctl request: %d\n", request);
    }
@@ -998,6 +1050,34 @@ void sb_decoder_ctl(void *state, int request, void *ptr)
       else
          (*(int*)ptr) += 50*(SB_SUBMODE_BITS+1);
       break;
+   case SPEEX_GET_PI_GAIN:
+      {
+         int i;
+         float *g = (float*)ptr;
+         for (i=0;i<st->nbSubframes;i++)
+            g[i]=st->pi_gain[i];
+      }
+      break;
+   case SPEEX_GET_EXC:
+      {
+         int i;
+         float *e = (float*)ptr;
+         for (i=0;i<st->full_frame_size;i++)
+            e[i]=0;
+         for (i=0;i<st->frame_size;i++)
+            e[2*i]=st->exc[i];
+      }
+      break;
+   case SPEEX_GET_INNOV:
+      {
+         int i;
+         float *e = (float*)ptr;
+         for (i=0;i<st->full_frame_size;i++)
+            e[i]=0;
+         for (i=0;i<st->frame_size;i++)
+            e[2*i]=st->exc[i];
+      }
+      break;
    default:
       fprintf(stderr, "Unknown sb_ctl request: %d\n", request);
    }
index 7e193ce..6311570 100644 (file)
@@ -88,6 +88,7 @@ typedef struct SBEncState {
    float *mem_sp;              /**< Synthesis signal memory */
    float *mem_sp2;
    float *mem_sw;              /**< Perceptual signal memory */
+   float *pi_gain;
 
    SpeexSubmode **submodes;
    int    submodeID;
@@ -120,6 +121,7 @@ typedef struct SBDecState {
    float *interp_qlpc;
 
    float *mem_sp;
+   float *pi_gain;
 
    SpeexSubmode **submodes;
    int    submodeID;
index b76924b..5b6b72c 100644 (file)
@@ -100,6 +100,11 @@ extern "C" {
 #define SPEEX_SET_USER_HANDLER 22
 
 
+   /* Used internally, not to be used in applications */
+#define SPEEX_GET_PI_GAIN 100
+#define SPEEX_GET_EXC     101
+#define SPEEX_GET_INNOV   102
+
 
 /* Preserving compatibility:*/
 /** Equivalent to SPEEX_SET_ENH */
@@ -278,6 +283,9 @@ extern SpeexMode speex_nb_mode;
 /** Default wideband mode */
 extern SpeexMode speex_wb_mode;
 
+/** Default "ultra-wideband" mode */
+extern SpeexMode speex_uwb_mode;
+
 /** List of all modes availavle */
 extern SpeexMode *speex_mode_list[SPEEX_NB_MODES];
 
diff --git a/libspeex/testenc_uwb.c b/libspeex/testenc_uwb.c
new file mode 100644 (file)
index 0000000..38a7131
--- /dev/null
@@ -0,0 +1,106 @@
+#include "speex.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define FRAME_SIZE 640
+#include <math.h>
+int main(int argc, char **argv)
+{
+   char *inFile, *outFile, *bitsFile;
+   FILE *fin, *fout, *fbits=NULL;
+   short in[FRAME_SIZE];
+   float input[FRAME_SIZE], bak[FRAME_SIZE], bak2[FRAME_SIZE];
+   char cbits[200];
+   int nbBits;
+   int i;
+   void *st;
+   void *dec;
+   SpeexBits bits;
+   int tmp;
+   int bitCount=0;
+
+   for (i=0;i<FRAME_SIZE;i++)
+      bak2[i]=0;
+   st = speex_encoder_init(&speex_uwb_mode);
+   dec = speex_decoder_init(&speex_uwb_mode);
+   
+   /*tmp=0;
+   speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp);
+   tmp=0;
+   speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp);
+   tmp=10;
+   speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp);
+   tmp=3;
+   speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp);
+   tmp=3;
+   speex_encoder_ctl(st, SPEEX_SET_HIGH_MODE, &tmp);
+   tmp=6;
+   speex_encoder_ctl(st, SPEEX_SET_LOW_MODE, &tmp);
+   */
+   if (argc != 4 && argc != 3)
+   { 
+      fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc);
+      exit(1);
+   }
+   inFile = argv[1];
+   fin = fopen(inFile, "r");
+   outFile = argv[2];
+   fout = fopen(outFile, "w");
+   if (argc==4)
+   {
+      bitsFile = argv[3];
+      fbits = fopen(bitsFile, "w");
+   }
+   speex_bits_init(&bits);
+   while (!feof(fin))
+   {
+      fread(in, sizeof(short), FRAME_SIZE, fin);
+      if (feof(fin))
+         break;
+      for (i=0;i<FRAME_SIZE;i++)
+         bak[i]=input[i]=in[i];
+      speex_bits_reset(&bits);
+      speex_encode(st, input, &bits);
+      nbBits = speex_bits_write(&bits, cbits, 200);
+      bitCount+=bits.nbBits;
+      printf ("Encoding frame in %d bits\n", nbBits*8);
+      if (argc==4)
+         fwrite(cbits, 1, nbBits, fbits);
+      {
+         float enoise=0, esig=0, snr;
+         for (i=0;i<FRAME_SIZE;i++)
+         {
+            enoise+=(bak2[i]-input[i])*(bak2[i]-input[i]);
+            esig += bak2[i]*bak2[i];
+         }
+         snr = 10*log10((esig+1)/(enoise+1));
+         printf ("real SNR = %f\n", snr);
+      }
+      speex_bits_rewind(&bits);
+      
+      speex_decode(dec, &bits, input);
+
+      /* Save the bits here */
+      for (i=0;i<FRAME_SIZE;i++)
+      {
+         if (input[i]>32000)
+            input[i]=32000;
+         else if (input[i]<-32000)
+            input[i]=-32000;
+      }
+      speex_bits_reset(&bits);
+      for (i=0;i<FRAME_SIZE;i++)
+         in[i]=(short)input[i];
+      for (i=0;i<FRAME_SIZE;i++)
+         bak2[i]=bak[i];
+      fwrite(in, sizeof(short), FRAME_SIZE, fout);
+   }
+   
+   fprintf (stderr, "Total encoded size: %d bits\n", bitCount);
+   speex_encoder_destroy(st);
+   speex_decoder_destroy(dec);
+   speex_bits_destroy(&bits);
+   fclose(fin);
+   fclose(fout);
+   return 1;
+}