Better options for test_opus
authorKoen Vos <koen.vos@skype.net>
Tue, 1 Feb 2011 15:44:48 +0000 (10:44 -0500)
committerJean-Marc Valin <jean-marc.valin@octasic.com>
Tue, 1 Feb 2011 15:44:48 +0000 (10:44 -0500)
src/test_opus.c

index 2766421..7353f43 100644 (file)
 #include <math.h>
 #include <string.h>
 #include "opus.h"
+#include "SKP_debug.h"
 
 
 #define MAX_PACKET 1024
 
+void print_usage( char* argv[] ) 
+{
+    fprintf(stderr, "Usage: %s <mode (0/1/2)> <sampling rate (Hz)> <channels> <frame size (samples)> "
+        "<bits per second>  [options] <input> <output>\n\n", argv[0]);
+    fprintf(stderr, "mode: 0 for SILK, 1 for hybrid, 2 for CELT:\n" );
+    fprintf(stderr, "options:\n" );
+    fprintf(stderr, "-vbr                 : enable variable bitrate (recommended for SILK)\n" );
+    fprintf(stderr, "-internal_rate <Hz>  : internal sampling rate in Hz, default: input smplng rate\n" );
+    fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
+    fprintf(stderr, "-complexity <comp>   : SILK complexity, 0: low, 1: medium, 2: high; default: 2\n" );
+    fprintf(stderr, "-inbandfec           : enable SILK inband FEC\n" );
+    fprintf(stderr, "-dtx                 : enable SILK DTX\n" );
+    fprintf(stderr, "-loss <perc>         : simulate packet loss, in percent (0-100); default: 0\n" );
+}
+
+#ifdef _WIN32
+#      define STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y)
+#else
+#      define STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
+#endif 
+
+
 int main(int argc, char *argv[])
 {
    int err;
@@ -50,45 +73,96 @@ int main(int argc, char *argv[])
    FILE *fin, *fout;
    OpusEncoder *enc;
    OpusDecoder *dec;
+   int args;
    int len;
    int frame_size, channels;
-   int bytes_per_packet;
-   unsigned char data[MAX_PACKET];
-   int rate;
-   int loss = 0;
-   int count = 0;
+   int bitrate_bps;
+   unsigned char *data;
+   int sampling_rate;
+   int use_vbr;
+   int internal_sampling_rate_Hz;
+   int max_payload_bytes;
+   int complexity;
+   int use_inbandfec;
+   int use_dtx;
+   int packet_loss_perc;
+   int count=0, count_act=0, k;
    int skip;
    int stop=0;
-   int vbr=0;
    int tot_read=0, tot_written=0;
    short *in, *out;
-   int mode=MODE_HYBRID;
-   double bits=0;
-   if (argc != 9 && argc != 8 && argc != 7)
+   int mode;
+   double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
+
+   if (argc < 8 )
    {
-      fprintf (stderr, "Usage: test_opus <rate (kHz)> <channels> <frame size> "
-               " <bytes per packet>  [<VBR rate (kb/s)>] [<packet loss rate>] "
-               "<input> <output>\n");
+      print_usage( argv );
       return 1;
    }
 
-   rate = atoi(argv[1]);
-   channels = atoi(argv[2]);
-   frame_size = atoi(argv[3]);
+   mode = atoi(argv[1]) + MODE_SILK_ONLY;
+   sampling_rate = atoi(argv[2]);
+   channels = atoi(argv[3]);
+   frame_size = atoi(argv[4]);
+   bitrate_bps = atoi(argv[5]);
 
-   bytes_per_packet = atoi(argv[4]);
+   /* defaults: */
+   use_vbr = 0;
+   internal_sampling_rate_Hz = sampling_rate;
+   max_payload_bytes = MAX_PACKET;
+   complexity = 2;
+   use_inbandfec = 0;
+   use_dtx = 0;
+   packet_loss_perc = 0;
 
-   if (argc >= 8)
-       vbr = atoi(argv[5]);
-   if (argc >= 9)
-       loss = atoi(argv[6]);
+   args = 6;
+   while( args < argc - 2 ) {
+       /* process command line options */
+        if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-vbr" ) == 0 ) {
+            use_vbr = 1;
+            args++;
+        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-internal_rate" ) == 0 ) {
+            internal_sampling_rate_Hz = atoi( argv[ args + 1 ] );
+            args += 2;
+        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-max_payload" ) == 0 ) {
+            max_payload_bytes = atoi( argv[ args + 1 ] );
+            args += 2;
+        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-complexity" ) == 0 ) {
+            complexity = atoi( argv[ args + 1 ] );
+            args += 2;
+        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandfec" ) == 0 ) {
+            use_inbandfec = 1;
+            args++;
+        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-fec") == 0 ) {
+            use_dtx = 1;
+            args++;
+        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
+            packet_loss_perc = atoi( argv[ args + 1 ] );
+            args += 2;
+        } else {
+            printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
+            print_usage( argv );
+            return 1;
+        }
+   }
 
-   if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
+   if( mode < MODE_SILK_ONLY || mode > MODE_CELT_ONLY ) {
+      fprintf (stderr, "mode must be: 0, 1 or 2\n");
+      return 1;
+   }
+
+   if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
    {
-      fprintf (stderr, "bytes per packet must be between 0 and %d\n",
+      fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
                         MAX_PACKET);
       return 1;
    }
+   if (bitrate_bps < 0 || bitrate_bps*frame_size/sampling_rate > max_payload_bytes*8)
+   {
+      fprintf (stderr, "bytes per packet must be between 0 and %d\n",
+                        max_payload_bytes);
+      return 1;
+   }
 
    inFile = argv[argc-2];
    fin = fopen(inFile, "rb");
@@ -105,17 +179,40 @@ int main(int argc, char *argv[])
       return 1;
    }
 
-   enc = opus_encoder_create(rate, channels);
-   dec = opus_decoder_create(rate, channels);
+   enc = opus_encoder_create(sampling_rate, channels);
+   dec = opus_decoder_create(sampling_rate, channels);
 
-   mode = MODE_HYBRID;
-   opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(BANDWIDTH_FULLBAND));
    opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
+   opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
+
+   if( internal_sampling_rate_Hz == 48000 ) {
+       opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(BANDWIDTH_FULLBAND));
+   } else if( internal_sampling_rate_Hz == 32000 ) {
+       opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(BANDWIDTH_SUPERWIDEBAND));
+   //} else if( internal_sampling_rate_Hz == 24000 ) {
+   //    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(BANDWIDTH_EXTRAWIDEBAND));
+   } else if( internal_sampling_rate_Hz == 16000 ) {
+       opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(BANDWIDTH_WIDEBAND));
+   } else if( internal_sampling_rate_Hz == 12000 ) {
+       opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(BANDWIDTH_MEDIUMBAND));
+   } else if( internal_sampling_rate_Hz == 8000 ) {
+       opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(BANDWIDTH_NARROWBAND));
+   } else {
+      fprintf (stderr, "Unsupported internal sampling rate %d\n", internal_sampling_rate_Hz);
+      return 1;
+   }
+
+   opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
+   opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
+   opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
+   opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx));
 
-   skip = 5*rate/1000 + 10;
+   //skip = 5*sampling_rate/1000 + 18;      // 18 is when SILK resamples
+   skip = 5*sampling_rate/1000;
 
    in = (short*)malloc(frame_size*channels*sizeof(short));
    out = (short*)malloc(frame_size*channels*sizeof(short));
+   data = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
    while (!stop)
    {
       int write_samples;
@@ -127,14 +224,14 @@ int main(int argc, char *argv[])
           for (i=err;i<frame_size*channels;i++)
               in[i] = 0;
       }
-      len = opus_encode(enc, in, frame_size, data, bytes_per_packet);
+      len = opus_encode(enc, in, frame_size, data, max_payload_bytes);
       if (len <= 0)
       {
          fprintf (stderr, "opus_encode() returned %d\n", len);
          return 1;
       }
-      bits += len*8;
-      opus_decode(dec, rand()%100<loss ? NULL : data, len, out, frame_size);
+
+      opus_decode(dec, rand()%100<packet_loss_perc ? NULL : data, len, out, frame_size);
       count++;
       tot_written += (frame_size-skip)*channels;
       write_samples = frame_size;
@@ -145,8 +242,24 @@ int main(int argc, char *argv[])
       }
       fwrite(out+skip, sizeof(short), (write_samples-skip)*channels, fout);
       skip = 0;
+
+      /* count bits */
+      bits += len*8;
+      nrg = 0.0;
+      for ( k = 0; k < frame_size * channels; k++ ) {
+          nrg += out[ k ] * (double)out[ k ];
+      }
+      if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
+          bits_act += len*8;
+          count_act++;
+      }
+         /* Variance */
+         bits2 += len*len*64;
    }
-   fprintf (stderr, "average bit-rate: %f kb/s\n", bits*rate/(frame_size*(double)count));
+   fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
+   fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
+   fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
+   DEBUG_STORE_CLOSE_FILES             /* Close any files to which intermediate results were stored */
    opus_encoder_destroy(enc);
    opus_decoder_destroy(dec);
    fclose(fin);