Fixes 60 ms speech mode
[opus.git] / src / test_opus.c
index ab40dd8..797c872 100644 (file)
    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
 #include "SKP_debug.h"
 
 
-#define MAX_PACKET 1024
+#define MAX_PACKET 1500
 
 void print_usage( char* argv[] ) 
 {
     fprintf(stderr, "Usage: %s <mode (0/1/2)> <sampling rate (Hz)> <channels> "
         "<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, "mode: 0 for auto, 1 for voice, 2 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" );
@@ -75,10 +71,10 @@ int main(int argc, char *argv[])
    OpusEncoder *enc;
    OpusDecoder *dec;
    int args;
-   int len;
+   int len[2];
    int frame_size, channels;
    int bitrate_bps;
-   unsigned char *data;
+   unsigned char *data[2];
    int sampling_rate;
    int use_vbr;
    int internal_sampling_rate_Hz;
@@ -86,6 +82,7 @@ int main(int argc, char *argv[])
    int complexity;
    int use_inbandfec;
    int use_dtx;
+   int cvbr = 0;
    int packet_loss_perc;
    int count=0, count_act=0, k;
    int skip;
@@ -96,6 +93,10 @@ int main(int argc, char *argv[])
    double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
    int bandwidth=-1;
    const char *bandwidth_string;
+   int write_samples;
+   int lost, lost_prev = 1;
+   int toggle = 0;
+   int enc_final_range[2];
 
    if (argc < 7 )
    {
@@ -103,7 +104,7 @@ int main(int argc, char *argv[])
       return 1;
    }
 
-   mode = atoi(argv[1]) + MODE_SILK_ONLY;
+   mode = atoi(argv[1]) + OPUS_MODE_AUTO;
    sampling_rate = atoi(argv[2]);
    channels = atoi(argv[3]);
    bitrate_bps = atoi(argv[4]);
@@ -112,7 +113,7 @@ int main(int argc, char *argv[])
 
    /* defaults: */
    use_vbr = 1;
-   bandwidth=-1;
+   bandwidth=BANDWIDTH_AUTO;
    internal_sampling_rate_Hz = sampling_rate;
    max_payload_bytes = MAX_PACKET;
    complexity = 10;
@@ -120,24 +121,6 @@ int main(int argc, char *argv[])
    use_dtx = 0;
    packet_loss_perc = 0;
 
-   switch(sampling_rate)
-   {
-   case 8000:
-          bandwidth = BANDWIDTH_NARROWBAND;
-          break;
-   case 12000:
-          bandwidth = BANDWIDTH_MEDIUMBAND;
-          break;
-   case 16000:
-          bandwidth = BANDWIDTH_WIDEBAND;
-          break;
-   case 24000:
-          bandwidth = BANDWIDTH_SUPERWIDEBAND;
-          break;
-   case 48000:
-          bandwidth = BANDWIDTH_FULLBAND;
-          break;
-   }
    args = 5;
    while( args < argc - 2 ) {
        /* process command line options */
@@ -187,6 +170,9 @@ int main(int argc, char *argv[])
         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandfec" ) == 0 ) {
             use_inbandfec = 1;
             args++;
+        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cvbr" ) == 0 ) {
+            cvbr = 1;
+            args++;
         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-dtx") == 0 ) {
             use_dtx = 1;
             args++;
@@ -200,7 +186,7 @@ int main(int argc, char *argv[])
         }
    }
 
-   if( mode < MODE_SILK_ONLY || mode > MODE_CELT_ONLY ) {
+   if( mode < OPUS_MODE_AUTO || mode > OPUS_MODE_AUDIO) {
       fprintf (stderr, "mode must be: 0, 1 or 2\n");
       return 1;
    }
@@ -233,53 +219,23 @@ int main(int argc, char *argv[])
       return 1;
    }
 
-   if (mode==MODE_SILK_ONLY)
-   {
-       if (bandwidth == BANDWIDTH_SUPERWIDEBAND || bandwidth == BANDWIDTH_FULLBAND)
-       {
-           fprintf (stderr, "Predictive mode only supports up to wideband\n");
-           return 1;
-       }
-   }
-   if (mode==MODE_HYBRID)
-   {
-       if (bandwidth != BANDWIDTH_SUPERWIDEBAND && bandwidth != BANDWIDTH_FULLBAND)
-       {
-           fprintf (stderr, "Hybrid mode only supports superwideband and fullband\n");
-           return 1;
-       }
-   }
-   if (mode==MODE_CELT_ONLY)
-   {
-       if (bandwidth == BANDWIDTH_MEDIUMBAND)
-       {
-           fprintf (stderr, "Transform mode does not support mediumband\n");
-           return 1;
-       }
-   }
-
    enc = opus_encoder_create(sampling_rate, channels);
    dec = opus_decoder_create(sampling_rate, channels);
 
    opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
    opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
-
-   if (bandwidth == -1)
-   {
-       fprintf (stderr, "Please specify a bandwidth when the sampling rate does not match one exactly\n");
-       return 1;
-   }
    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
-
    opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
+   opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
    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));
+   opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
 
    skip = 5*sampling_rate/1000;
    /* When SILK resamples, add 18 samples delay */
-   if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
-          skip += 18;
+   /*if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
+          skip += 18;*/
 
    switch(bandwidth)
    {
@@ -298,6 +254,9 @@ int main(int argc, char *argv[])
    case BANDWIDTH_FULLBAND:
           bandwidth_string = "fullband";
           break;
+   case BANDWIDTH_AUTO:
+          bandwidth_string = "auto";
+          break;
    default:
           bandwidth_string = "unknown";
    }
@@ -306,11 +265,13 @@ int main(int argc, char *argv[])
 
    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));
+   data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
+   if( use_inbandfec ) {
+       data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
+   }
    while (!stop)
    {
-      int write_samples;
-      int lost;
+
       err = fread(in, sizeof(short), frame_size*channels, fin);
       tot_read += err;
       if (err < frame_size*channels)
@@ -319,53 +280,80 @@ 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, max_payload_bytes);
-      if (len <= 0)
+
+      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 );
+#endif
+      if (len[toggle] < 0)
       {
-         fprintf (stderr, "opus_encode() returned %d\n", len);
+         fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
          return 1;
       }
 
-      lost = rand()%100<packet_loss_perc;
-      opus_decode(dec, lost ? NULL : data, len, out, frame_size);
-      count++;
-      tot_written += (frame_size-skip)*channels;
-      write_samples = frame_size;
-      if (tot_written > tot_read && skip==0)
-      {
-          write_samples -= (tot_written-tot_read)/channels;
-          stop = 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);
+              } else {
+                  /* regular decode */
+                  opus_decode(dec, data[1-toggle], len[1-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;
+          }
+          fwrite(out+skip, sizeof(short), write_samples*channels, fout);
+          skip = 0;
       }
-      fwrite(out+skip, sizeof(short), (write_samples-skip)*channels, fout);
-      skip = 0;
 
 #if OPUS_TEST_RANGE_CODER_STATE
       /* compare final range encoder rng values of encoder and decoder */
-      if( !lost && opus_decoder_get_final_range( dec ) != opus_encoder_get_final_range( enc ) ) {
+      if( !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.\n");
           return 0;
       }
 #endif
 
+      lost_prev = lost;
+
       /* 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++;
+      bits += len[toggle]*8;
+      if( count >= use_inbandfec ) {
+          nrg = 0.0;
+          for ( k = 0; k < frame_size * channels; k++ ) {
+              nrg += in[ k ] * (double)in[ k ];
+          }
+          if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
+              bits_act += len[toggle]*8;
+              count_act++;
+          }
+             /* Variance */
+             bits2 += len[toggle]*len[toggle]*64;
       }
-         /* Variance */
-         bits2 += len*len*64;
+      count++;
+      toggle = (toggle + use_inbandfec) & 1;
    }
    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 */
+   /* Close any files to which intermediate results were stored */
+   DEBUG_STORE_CLOSE_FILES
+   SKP_TimerSave("opus_timing.txt");
    opus_encoder_destroy(enc);
    opus_decoder_destroy(dec);
+   free(data[0]);
+   if (use_inbandfec)
+          free(data[1]);
    fclose(fin);
    fclose(fout);
    free(in);