Fixes a crash in silk prefill (used for mode switching)
[opus.git] / src / test_opus.c
index 1916584..fa52d89 100644 (file)
 #include <string.h>
 #include "opus.h"
 #include "silk_debug.h"
-
+#include "celt_types.h"
 
 #define MAX_PACKET 1500
 
 void print_usage( char* argv[] ) 
 {
-    fprintf(stderr, "Usage: %s <mode (0/1/2)> <sampling rate (Hz)> <channels> "
+    fprintf(stderr, "Usage: %s [-e | -d] <application (0/1)> <sampling rate (Hz)> <channels (1/2)> "
         "<bits per second>  [options] <input> <output>\n\n", argv[0]);
-    fprintf(stderr, "mode: 0 for auto, 1 for voice, 2 for audio:\n" );
+    fprintf(stderr, "mode: 0 for VoIP, 1 for audio:\n" );
     fprintf(stderr, "options:\n" );
-    fprintf(stderr, "-cbr                 : enable constant bitrate; default: VBR\n" );
-    fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB>  : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
-    fprintf(stderr, "-framesize <2.5|5|10|20|40|60>  : frame size in ms; default: 20 \n" );
+    fprintf(stderr, "-e                   : only runs the encoder (output the bit-stream)\n" );
+    fprintf(stderr, "-d                   : only runs the decoder (reads the bit-stream as input)\n" );
+    fprintf(stderr, "-cbr                 : enable constant bitrate; default: variable bitrate\n" );
+    fprintf(stderr, "-cvbr                : enable constraint variable bitrate; default: unconstraint\n" );
+    fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
+    fprintf(stderr, "-framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20 \n" );
     fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
     fprintf(stderr, "-complexity <comp>   : complexity, 0 (lowest) ... 10 (highest); default: 10\n" );
     fprintf(stderr, "-inbandfec           : enable SILK inband FEC\n" );
@@ -63,6 +66,19 @@ void print_usage( char* argv[] )
 #      define STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
 #endif 
 
+static void int_to_char(celt_uint32 i, unsigned char ch[4])
+{
+    ch[0] = i>>24;
+    ch[1] = (i>>16)&0xFF;
+    ch[2] = (i>>8)&0xFF;
+    ch[3] = i&0xFF;
+}
+
+static celt_uint32 char_to_int(unsigned char ch[4])
+{
+    return ((celt_uint32)ch[0]<<24) | ((celt_uint32)ch[1]<<16)
+         | ((celt_uint32)ch[2]<< 8) |  (celt_uint32)ch[3];
+}
 
 int main(int argc, char *argv[])
 {
@@ -91,7 +107,7 @@ int main(int argc, char *argv[])
    int stop=0;
    int tot_read=0, tot_written=0;
    short *in, *out;
-   int mode;
+   int application;
    double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
    int bandwidth=-1;
    const char *bandwidth_string;
@@ -99,6 +115,7 @@ int main(int argc, char *argv[])
    int lost, lost_prev = 1;
    int toggle = 0;
    int enc_final_range[2];
+   int encode_only=0, decode_only=0;
 
    if (argc < 7 )
    {
@@ -106,7 +123,18 @@ int main(int argc, char *argv[])
       return 1;
    }
 
-   mode = atoi(argv[1]) + OPUS_MODE_AUTO;
+   if (strcmp(argv[1], "-e")==0)
+   {
+       encode_only = 1;
+       argv++;
+       argc--;
+   } else if (strcmp(argv[1], "-d")==0)
+   {
+       decode_only = 1;
+       argv++;
+       argc--;
+   }
+   application = atoi(argv[1]) + OPUS_APPLICATION_VOIP;
    sampling_rate = atoi(argv[2]);
    channels = atoi(argv[3]);
    bitrate_bps = atoi(argv[4]);
@@ -122,7 +150,7 @@ int main(int argc, char *argv[])
 
    /* defaults: */
    use_vbr = 1;
-   bandwidth=BANDWIDTH_AUTO;
+   bandwidth=OPUS_BANDWIDTH_AUTO;
    internal_sampling_rate_Hz = sampling_rate;
    max_payload_bytes = MAX_PACKET;
    complexity = 10;
@@ -139,15 +167,15 @@ int main(int argc, char *argv[])
             args++;
         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-bandwidth" ) == 0 ) {
             if (strcmp(argv[ args + 1 ], "NB")==0)
-                bandwidth = BANDWIDTH_NARROWBAND;
+                bandwidth = OPUS_BANDWIDTH_NARROWBAND;
             else if (strcmp(argv[ args + 1 ], "MB")==0)
-                bandwidth = BANDWIDTH_MEDIUMBAND;
+                bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
             else if (strcmp(argv[ args + 1 ], "WB")==0)
-                bandwidth = BANDWIDTH_WIDEBAND;
+                bandwidth = OPUS_BANDWIDTH_WIDEBAND;
             else if (strcmp(argv[ args + 1 ], "SWB")==0)
-                bandwidth = BANDWIDTH_SUPERWIDEBAND;
+                bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
             else if (strcmp(argv[ args + 1 ], "FB")==0)
-                bandwidth = BANDWIDTH_FULLBAND;
+                bandwidth = OPUS_BANDWIDTH_FULLBAND;
             else {
                 fprintf(stderr, "Unknown bandwidth %s. Supported are NB, MB, WB, SWB, FB.\n", argv[ args + 1 ]);
                 return 1;
@@ -199,8 +227,8 @@ int main(int argc, char *argv[])
         }
    }
 
-   if( mode < OPUS_MODE_AUTO || mode > OPUS_MODE_AUDIO) {
-      fprintf (stderr, "mode must be: 0, 1 or 2\n");
+   if( application < OPUS_APPLICATION_VOIP || application > OPUS_APPLICATION_AUDIO) {
+      fprintf (stderr, "mode must be: 0 or 1\n");
       return 1;
    }
 
@@ -232,7 +260,7 @@ int main(int argc, char *argv[])
       return 1;
    }
 
-   enc = opus_encoder_create(sampling_rate, channels);
+   enc = opus_encoder_create(sampling_rate, channels, application);
    dec = opus_decoder_create(sampling_rate, channels);
 
    if (enc==NULL)
@@ -246,7 +274,6 @@ int main(int argc, char *argv[])
       exit(1);
    }
 
-   opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
    opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
    opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
@@ -264,22 +291,22 @@ int main(int argc, char *argv[])
 
    switch(bandwidth)
    {
-   case BANDWIDTH_NARROWBAND:
+   case OPUS_BANDWIDTH_NARROWBAND:
           bandwidth_string = "narrowband";
           break;
-   case BANDWIDTH_MEDIUMBAND:
+   case OPUS_BANDWIDTH_MEDIUMBAND:
           bandwidth_string = "mediumband";
           break;
-   case BANDWIDTH_WIDEBAND:
+   case OPUS_BANDWIDTH_WIDEBAND:
           bandwidth_string = "wideband";
           break;
-   case BANDWIDTH_SUPERWIDEBAND:
+   case OPUS_BANDWIDTH_SUPERWIDEBAND:
           bandwidth_string = "superwideband";
           break;
-   case BANDWIDTH_FULLBAND:
+   case OPUS_BANDWIDTH_FULLBAND:
           bandwidth_string = "fullband";
           break;
-   case BANDWIDTH_AUTO:
+   case OPUS_BANDWIDTH_AUTO:
           bandwidth_string = "auto";
           break;
    default:
@@ -296,54 +323,77 @@ int main(int argc, char *argv[])
    }
    while (!stop)
    {
-
-      err = fread(in, sizeof(short), frame_size*channels, fin);
-      tot_read += err;
-      if (err < frame_size*channels)
+      if (decode_only)
       {
-          int i;
-          for (i=err;i<frame_size*channels;i++)
-              in[i] = 0;
-      }
+          unsigned char ch[4];
+          err = fread(ch, 1, 4, fin);
+          len[toggle] = char_to_int(ch);
+          err = fread(ch, 1, 4, fin);
+          enc_final_range[toggle] = char_to_int(ch);
+          err = fread(data[toggle], 1, len[toggle], fin);
+          if (feof(fin))
+              break;
+          tot_read += frame_size*channels;
+      } else {
+          err = fread(in, sizeof(short), frame_size*channels, fin);
+          tot_read += err;
+          if (err < frame_size*channels)
+          {
+              int i;
+              for (i=err;i<frame_size*channels;i++)
+                  in[i] = 0;
+              stop = 1;
+          }
 
-      len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
+          len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
 #if OPUS_TEST_RANGE_CODER_STATE
-      enc_final_range[toggle] = opus_encoder_get_final_range( enc );
+          enc_final_range[toggle] = opus_encoder_get_final_range( enc );
 #endif
-      if (len[toggle] < 0)
-      {
-         fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
-         return 1;
+          if (len[toggle] < 0)
+          {
+              fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
+              return 1;
+          }
       }
 
-      lost = rand()%100 < packet_loss_perc || len[toggle]==0;
-      if( count >= use_inbandfec ) {
-          /* delay by one packet when using in-band FEC */
-          if( use_inbandfec  ) {
-              if( lost_prev ) {
-                  /* attempt to decode with in-band FEC from next packet */
-                  opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 1);
+      if (encode_only)
+      {
+          unsigned char int_field[4];
+          int_to_char(len[toggle], int_field);
+          fwrite(int_field, 1, 4, fout);
+          int_to_char(enc_final_range[toggle], int_field);
+          fwrite(int_field, 1, 4, fout);
+          fwrite(data[toggle], 1, len[toggle], fout);
+      } else {
+          lost = rand()%100 < packet_loss_perc || len[toggle]==0;
+          if( count >= use_inbandfec ) {
+              /* delay by one packet when using in-band FEC */
+              if( use_inbandfec  ) {
+                  if( lost_prev ) {
+                      /* attempt to decode with in-band FEC from next packet */
+                      opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 1);
+                  } else {
+                      /* regular decode */
+                      opus_decode(dec, data[1-toggle], len[1-toggle], out, frame_size, 0);
+                  }
               } else {
-                  /* regular decode */
-                  opus_decode(dec, data[1-toggle], len[1-toggle], out, frame_size, 0);
+                  opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 0);
               }
-          } else {
-              opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 0);
-          }
-          write_samples = frame_size-skip;
-          tot_written += write_samples*channels;
-          if (tot_written > tot_read)
-          {
-              write_samples -= (tot_written-tot_read)/channels;
-              stop = 1;
+              write_samples = frame_size-skip;
+              tot_written += write_samples*channels;
+              if (tot_written > tot_read)
+              {
+                  write_samples -= (tot_written-tot_read)/channels;
+              }
+              fwrite(out+skip, sizeof(short), write_samples*channels, fout);
+              skip = 0;
           }
-          fwrite(out+skip, sizeof(short), write_samples*channels, fout);
-          skip = 0;
       }
 
 #if OPUS_TEST_RANGE_CODER_STATE
       /* compare final range encoder rng values of encoder and decoder */
-      if( !lost && !lost_prev && opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) {
+      if( !encode_only && !lost && !lost_prev
+         && opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) {
           fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %d.\n", count);
           return 0;
       }