Implemented stereo at the decoder side
authorjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Thu, 7 Nov 2002 22:13:16 +0000 (22:13 +0000)
committerjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Thu, 7 Nov 2002 22:13:16 +0000 (22:13 +0000)
git-svn-id: http://svn.xiph.org/trunk/speex@4096 0101bb08-14d6-0310-b084-bc0e0c8e3800

libspeex/Makefile.am
libspeex/speex_stereo.h
libspeex/stereo.c
src/speexdec.c
src/speexenc.c

index 5d381a7..88482d9 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in. -*-Makefile-*-
 
-# $Id: Makefile.am,v 1.45 2002/11/05 15:57:19 jm Exp $
+# $Id: Makefile.am,v 1.46 2002/11/07 22:13:15 jm Exp $
 
 # Disable automatic dependency tracking if using other tools than gcc and gmake
 #AUTOMAKE_OPTIONS = no-dependencies
@@ -60,7 +60,7 @@ noinst_HEADERS = lsp.h \
        ltp_sse.h \
        filters_sse.h \
        math_approx.h \
-       stereo.h
+       speex_stereo.h
        
        
 libspeex_la_LDFLAGS = -release $(LT_RELEASE)
index 38ce3ea..d745d00 100644 (file)
@@ -39,10 +39,12 @@ typedef struct SpeexStereoState {
    float e_ratio;
 } SpeexStereoState;
 
-#define SPEEX_DEFAULT_STEREO_STATE {1,2}
+#define SPEEX_STEREO_STATE_INIT {1,.5}
 
-void encode_stereo(float *data, int frame_size, SpeexBits *bits);
+void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits);
 
-void decode_stereo(float *data, int frame_size, SpeexStereoState *stereo);
+void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo);
+
+int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data);
 
 #endif
index 4885d4e..74b9fe9 100644 (file)
@@ -37,8 +37,6 @@
 /*float e_ratio_quant[4] = {1, 1.26, 1.587, 2};*/
 static float e_ratio_quant[4] = {.25, .315, .397, .5};
 
-#include <stdio.h>
-
 void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits)
 {
    int i, tmp;
@@ -81,9 +79,10 @@ void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo)
    float balance, e_ratio;
    int i;
    float e_tot=0, e_left, e_right, e_sum;
+
    balance=stereo->balance;
    e_ratio=stereo->e_ratio;
-   for (i=frame_size-1;i>=0;i++)
+   for (i=frame_size-1;i>=0;i--)
    {
       e_tot += data[i]*data[i];
    }
@@ -93,15 +92,15 @@ void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo)
 
    e_left  = sqrt(e_left/e_tot);
    e_right = sqrt(e_right/e_tot);
-   
-   for (i=frame_size-1;i>=0;i++)
+
+   for (i=frame_size-1;i>=0;i--)
    {
-      data[2*i] = e_left*data[i];
-      data[2*i+1] = e_right*data[i];
+      float ftmp=data[i];
+      data[2*i] = e_left*ftmp;
+      data[2*i+1] = e_right*ftmp;
    }
 }
 
-
 int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data)
 {
    SpeexStereoState *stereo;
@@ -112,7 +111,7 @@ int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data)
    if (speex_bits_unpack_unsigned(bits, 1))
       sign=-1;
    tmp = speex_bits_unpack_unsigned(bits, 5);
-   stereo->balance = sign*exp(.25*tmp);
+   stereo->balance = exp(sign*.25*tmp);
 
    tmp = speex_bits_unpack_unsigned(bits, 2);
    stereo->e_ratio = e_ratio_quant[tmp];
index 09e7d5e..0f22cc2 100644 (file)
@@ -60,6 +60,8 @@
 #include <string.h>
 #include "wav_io.h"
 #include "speex_header.h"
+#include "speex_stereo.h"
+#include "speex_callbacks.h"
 #include "misc.h"
 
 #define MAX_FRAME_SIZE 2000
@@ -91,7 +93,7 @@ static void print_comments(char *comments, int length)
    }
 }
 
-FILE *out_file_open(char *outFile, int rate)
+FILE *out_file_open(char *outFile, int rate, int *channels)
 {
    FILE *fout=NULL;
    /*Open output file*/
@@ -110,6 +112,8 @@ FILE *out_file_open(char *outFile, int rate)
       }
       
       stereo=0;
+      if (*channels=2)
+         stereo=1;
       if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1)
       {
          perror("SNDCTL_DSP_STEREO");
@@ -118,8 +122,10 @@ FILE *out_file_open(char *outFile, int rate)
       }
       if (stereo!=0)
       {
+         if (*channels==1)
+            fprintf (stderr, "Cannot set mono mode, will decode in stereo\n");
+         *channels=2;
          fprintf (stderr, "Cannot set mono mode\n");
-         exit(1);
       }
 
       if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate)==-1)
@@ -160,7 +166,7 @@ FILE *out_file_open(char *outFile, int rate)
             exit(1);
          }
          if (strcmp(outFile+strlen(outFile)-4,".wav")==0 || strcmp(outFile+strlen(outFile)-4,".WAV")==0)
-            write_wav_header(fout, rate, 1, 0, 0);
+            write_wav_header(fout, rate, *channels, 0, 0);
       }
    }
    return fout;
@@ -190,6 +196,8 @@ void usage()
    printf (" --no-enh              Disable perceptual enhancement (default FOR NOW)\n");
    printf (" --force-nb            Force decoding in narrowband, even for wideband\n");
    printf (" --force-wb            Force decoding in wideband, even for narrowband\n");
+   printf (" --mono                Force decoding in mono\n");
+   printf (" --stereo              Force decoding in stereo\n");
    printf (" --packet-loss n       Simulate n %% random packet loss\n");
    printf (" -V                    Verbose mode (show bit-rate)\n"); 
    printf (" -h, --help            This help\n");
@@ -207,13 +215,14 @@ void version()
    printf ("Speex decoder version " VERSION " (compiled " __DATE__ ")\n");
 }
 
-static void *process_header(ogg_packet *op, int enh_enabled, int *frame_size, int *rate, int *nframes, int forceMode)
+static void *process_header(ogg_packet *op, int enh_enabled, int *frame_size, int *rate, int *nframes, int forceMode, int *channels, SpeexStereoState *stereo)
 {
    void *st;
    SpeexMode *mode;
    SpeexHeader *header;
    int modeID;
-   
+   SpeexCallback callback;
+      
    header = speex_packet_to_header((char*)op->packet, op->bytes);
    if (!header)
    {
@@ -246,6 +255,11 @@ static void *process_header(ogg_packet *op, int enh_enabled, int *frame_size, in
    st = speex_decoder_init(mode);
    speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled);
    speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size);
+
+   callback.callback_id = SPEEX_INBAND_STEREO;
+   callback.func = speex_std_stereo_request_handler;
+   callback.data = stereo;
+   speex_decoder_ctl(st, SPEEX_SET_HANDLER, &callback);
    
    /* FIXME: need to adjust in case the forceMode option is set */
    *rate = header->rate;
@@ -254,6 +268,9 @@ static void *process_header(ogg_packet *op, int enh_enabled, int *frame_size, in
    if (header->mode==0 && forceMode==1)
       *rate*=2;
    *nframes = header->frames_per_packet;
+
+   if (*channels==-1)
+      *channels = header->nb_channels;
    
    fprintf (stderr, "Decoding %d Hz audio using %s mode", 
             *rate, mode->modeName);
@@ -292,6 +309,8 @@ int main(int argc, char **argv)
       {"no-pf", no_argument, NULL, 0},
       {"force-nb", no_argument, NULL, 0},
       {"force-wb", no_argument, NULL, 0},
+      {"mono", no_argument, NULL, 0},
+      {"stereo", no_argument, NULL, 0},
       {"packet-loss", required_argument, NULL, 0},
       {0, 0, 0, 0}
    };
@@ -307,6 +326,8 @@ int main(int argc, char **argv)
    int forceMode=-1;
    int audio_size=0;
    float loss_percent=-1;
+   SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;
+   int channels=-1;
 
    enh_enabled = 0;
 
@@ -349,6 +370,12 @@ int main(int argc, char **argv)
          } else if (strcmp(long_options[option_index].name,"force-wb")==0)
          {
             forceMode=1;
+         } else if (strcmp(long_options[option_index].name,"mono")==0)
+         {
+            channels=1;
+         } else if (strcmp(long_options[option_index].name,"stereo")==0)
+         {
+            channels=2;
          } else if (strcmp(long_options[option_index].name,"packet-loss")==0)
          {
             loss_percent = atof(optarg);
@@ -437,12 +464,12 @@ int main(int argc, char **argv)
             if (packet_count==0)
             {
                int rate;
-               st = process_header(&op, enh_enabled, &frame_size, &rate, &nframes, forceMode);
+               st = process_header(&op, enh_enabled, &frame_size, &rate, &nframes, forceMode, &channels, &stereo);
                if (!nframes)
                   nframes=1;
                if (!st)
                   exit(1);
-               fout = out_file_open(outFile, rate);
+               fout = out_file_open(outFile, rate, &channels);
 
             } else if (packet_count==1){
                print_comments((char*)op.packet, op.bytes);
@@ -471,6 +498,9 @@ int main(int argc, char **argv)
                   else
                      speex_decode(st, NULL, output);
 
+                  if (channels==2)
+                     speex_decode_stereo(output, frame_size, &stereo);
+
                   if (print_bitrate) {
                      int tmp;
                      char ch=13;
@@ -479,7 +509,7 @@ int main(int argc, char **argv)
                      fprintf (stderr, "Bitrate is use: %d bps     ", tmp);
                   }
                   /*PCM saturation (just in case)*/
-                  for (i=0;i<frame_size;i++)
+                  for (i=0;i<frame_size*channels;i++)
                   {
                      if (output[i]>32000.0)
                         output[i]=32000.0;
@@ -487,15 +517,17 @@ int main(int argc, char **argv)
                         output[i]=-32000.0;
                   }
                   /*Convert to short and save to output file*/
-                  for (i=0;i<frame_size;i++)
+                  for (i=0;i<frame_size*channels;i++)
                      out[i]=(short)le_short((short)output[i]);
 #if defined WIN32 || defined _WIN32
                   if (strlen(outFile)==0)
-                      WIN_Play_Samples (out, sizeof(short) * frame_size);
+                      WIN_Play_Samples (out, sizeof(short) * frame_size*channels);
                   else
 #endif
-                  fwrite(out, sizeof(short), frame_size, fout);
-                  audio_size+=sizeof(short)*frame_size;
+                  fwrite(out, sizeof(short), frame_size*channels, fout);
+                  
+                  /*FIXME: Not sure we should multiply by channels here*/
+                  audio_size+=sizeof(short)*frame_size*channels;
                }
             }
             packet_count++;
index 73ed967..338c0a4 100644 (file)
@@ -42,6 +42,7 @@
 #include <ogg/ogg.h>
 #include "wav_io.h"
 #include "speex_header.h"
+#include "speex_stereo.h"
 #include "misc.h"
 
 #if defined WIN32 || defined _WIN32
@@ -441,6 +442,7 @@ int main(int argc, char **argv)
    speex_init_header(&header, rate, 1, mode);
    header.frames_per_packet=nframes;
    header.vbr=vbr_enabled;
+   header.nb_channels = chan;
 
    fprintf (stderr, "Encoding %d Hz audio using %s mode\n", 
             header.rate, mode->modeName);