Remove warning added by 4cc9a459.
[opus.git] / src / test_opus.c
index 0ce6ec5..0e88681 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 <math.h>
 #include <string.h>
 #include "opus.h"
-#include "SKP_debug.h"
-
+#include "debug.h"
+#include "opus_types.h"
 
-#define MAX_PACKET 1024
+#define MAX_PACKET 1500
 
-void print_usage( char* argv[] ) 
+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, "Usage: %s [-e] <application> <sampling rate (Hz)> <channels (1/2)> "
+        "<bits per second>  [options] <input> <output>\n", argv[0]);
+    fprintf(stderr, "       %s -d <sampling rate (Hz)> <channels (1/2)> "
+        "[options] <input> <output>\n\n", argv[0]);
+    fprintf(stderr, "mode: voip | audio | restricted-lowdelay\n" );
     fprintf(stderr, "options:\n" );
-    fprintf(stderr, "-vbr                 : enable variable bitrate (recommended for SILK)\n" );
-    fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB>  : audio bandwidth (from narrowband to fullband)\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 constrained variable bitrate; default: unconstrained\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" );
+    fprintf(stderr, "-forcemono           : force mono encoding, even for stereo input\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)
+#   define STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y)
 #else
-#      define STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
-#endif 
+#   include <strings.h>
+#   define STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
+#endif
 
+static void int_to_char(opus_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 opus_uint32 char_to_int(unsigned char ch[4])
+{
+    return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16)
+         | ((opus_uint32)ch[2]<< 8) |  (opus_uint32)ch[3];
+}
 
 int main(int argc, char *argv[])
 {
-   int err;
-   char *inFile, *outFile;
-   FILE *fin, *fout;
-   OpusEncoder *enc;
-   OpusDecoder *dec;
-   int args;
-   int len;
-   int frame_size, channels;
-   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 tot_read=0, tot_written=0;
-   short *in, *out;
-   int mode;
-   double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
-   int bandwidth=-1;
+    int err;
+    char *inFile, *outFile;
+    FILE *fin, *fout;
+    OpusEncoder *enc=NULL;
+    OpusDecoder *dec=NULL;
+    int args;
+    int len[2];
+    int frame_size, channels;
+    opus_int32 bitrate_bps=0;
+    unsigned char *data[2];
+    opus_int32 sampling_rate;
+    int use_vbr;
+    int max_payload_bytes;
+    int complexity;
+    int use_inbandfec;
+    int use_dtx;
+    int forcechannels;
+    int cvbr = 0;
+    int packet_loss_perc;
+    opus_int32 count=0, count_act=0;
+    int k;
+    int skip=0;
+    int stop=0;
+    short *in, *out;
+    int application=OPUS_APPLICATION_AUDIO;
+    double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
+    int bandwidth=-1;
+    const char *bandwidth_string;
+    int lost = 0, lost_prev = 1;
+    int toggle = 0;
+    opus_uint32 enc_final_range[2];
+    opus_uint32 dec_final_range;
+    int encode_only=0, decode_only=0;
+    int max_frame_size = 960*6;
+    int curr_read=0;
+    int sweep_bps = 0;
+
+    if (argc < 5 )
+    {
+       print_usage( argv );
+       return 1;
+    }
 
-   if (argc < 8 )
-   {
-      print_usage( argv );
-      return 1;
-   }
+    fprintf(stderr, "%s\n", opus_get_version_string());
 
-   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]);
+    args = 1;
+    if (strcmp(argv[args], "-e")==0)
+    {
+        encode_only = 1;
+        args++;
+    } else if (strcmp(argv[args], "-d")==0)
+    {
+        decode_only = 1;
+        args++;
+    }
+    if (!decode_only && argc < 7 )
+    {
+       print_usage( argv );
+       return 1;
+    }
+
+    if (!decode_only)
+    {
+       if (strcmp(argv[args], "voip")==0)
+          application = OPUS_APPLICATION_VOIP;
+       else if (strcmp(argv[args], "restricted-lowdelay")==0)
+          application = OPUS_APPLICATION_RESTRICTED_LOWDELAY;
+       else if (strcmp(argv[args], "audio")!=0) {
+          fprintf(stderr, "unknown application: %s\n", argv[args]);
+          print_usage(argv);
+          return 1;
+       }
+       args++;
+    }
+    sampling_rate = (opus_int32)atol(argv[args]);
+    args++;
+    channels = atoi(argv[args]);
+    args++;
+    if (!decode_only)
+    {
+       bitrate_bps = (opus_int32)atol(argv[args]);
+       args++;
+    }
 
-   /* defaults: */
-   use_vbr = 0;
-   bandwidth=-1;
-   internal_sampling_rate_Hz = sampling_rate;
-   max_payload_bytes = MAX_PACKET;
-   complexity = 10;
-   use_inbandfec = 0;
-   use_dtx = 0;
-   packet_loss_perc = 0;
+    if (sampling_rate != 8000 && sampling_rate != 12000 && sampling_rate != 16000
+     && sampling_rate != 24000 && sampling_rate != 48000)
+    {
+        fprintf(stderr, "Supported sampling rates are 8000, 12000, 16000, "
+                "24000 and 48000.\n");
+        return 1;
+    }
+    frame_size = sampling_rate/50;
 
-   args = 6;
-   while( args < argc - 2 ) {
-       /* process command line options */
-        if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-vbr" ) == 0 ) {
-            use_vbr = 1;
+    /* defaults: */
+    use_vbr = 1;
+    bandwidth = OPUS_AUTO;
+    max_payload_bytes = MAX_PACKET;
+    complexity = 10;
+    use_inbandfec = 0;
+    forcechannels = OPUS_AUTO;
+    use_dtx = 0;
+    packet_loss_perc = 0;
+    max_frame_size = 960*6;
+    curr_read=0;
+
+    while( args < argc - 2 ) {
+        /* process command line options */
+        if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cbr" ) == 0 ) {
+            use_vbr = 0;
             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;
             }
             args += 2;
+        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-framesize" ) == 0 ) {
+            if (strcmp(argv[ args + 1 ], "2.5")==0)
+                frame_size = sampling_rate/400;
+            else if (strcmp(argv[ args + 1 ], "5")==0)
+                frame_size = sampling_rate/200;
+            else if (strcmp(argv[ args + 1 ], "10")==0)
+                frame_size = sampling_rate/100;
+            else if (strcmp(argv[ args + 1 ], "20")==0)
+                frame_size = sampling_rate/50;
+            else if (strcmp(argv[ args + 1 ], "40")==0)
+                frame_size = sampling_rate/25;
+            else if (strcmp(argv[ args + 1 ], "60")==0)
+                frame_size = 3*sampling_rate/50;
+            else {
+                fprintf(stderr, "Unsupported frame size: %s ms. Supported are 2.5, 5, 10, 20, 40, 60.\n", argv[ args + 1 ]);
+                return 1;
+            }
+            args += 2;
         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-max_payload" ) == 0 ) {
             max_payload_bytes = atoi( argv[ args + 1 ] );
             args += 2;
@@ -148,159 +238,247 @@ 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 ], "-forcemono" ) == 0 ) {
+            forcechannels = 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++;
         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
             packet_loss_perc = atoi( argv[ args + 1 ] );
             args += 2;
+        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-sweep" ) == 0 ) {
+            sweep_bps = atoi( argv[ args + 1 ] );
+            args += 2;
         } else {
             printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
             print_usage( argv );
             return 1;
         }
-   }
+    }
 
-   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, "max_payload_bytes must be between 0 and %d\n",
+                          MAX_PACKET);
+        return 1;
+    }
 
-   if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
-   {
-      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");
+    if (!fin)
+    {
+        fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
+        return 1;
+    }
+    outFile = argv[argc-1];
+    fout = fopen(outFile, "wb+");
+    if (!fout)
+    {
+        fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
+        return 1;
+    }
 
-   inFile = argv[argc-2];
-   fin = fopen(inFile, "rb");
-   if (!fin)
-   {
-      fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
-      return 1;
-   }
-   outFile = argv[argc-1];
-   fout = fopen(outFile, "wb+");
-   if (!fout)
-   {
-      fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
-      return 1;
-   }
-
-   if (mode==MODE_SILK_ONLY)
-   {
-       if (bandwidth == BANDWIDTH_SUPERWIDEBAND || bandwidth == BANDWIDTH_FULLBAND)
+    if (!decode_only)
+    {
+       enc = opus_encoder_create(sampling_rate, channels, application, &err);
+       if (err != OPUS_OK)
        {
-           fprintf (stderr, "Predictive mode only supports up to wideband\n");
-           return 1;
+          fprintf(stderr, "Cannot create encoder: %s\n", opus_strerror(err));
+          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)
+       opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
+       opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
+       opus_encoder_ctl(enc, OPUS_SET_VBR(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(use_inbandfec));
+       opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(forcechannels));
+       opus_encoder_ctl(enc, OPUS_SET_DTX(use_dtx));
+       opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
+
+       opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
+    }
+    if (!encode_only)
+    {
+       dec = opus_decoder_create(sampling_rate, channels, &err);
+       if (err != OPUS_OK)
        {
-           fprintf (stderr, "Transform mode does not support mediumband\n");
-           return 1;
+          fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
+          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));
+    switch(bandwidth)
+    {
+    case OPUS_BANDWIDTH_NARROWBAND:
+         bandwidth_string = "narrowband";
+         break;
+    case OPUS_BANDWIDTH_MEDIUMBAND:
+         bandwidth_string = "mediumband";
+         break;
+    case OPUS_BANDWIDTH_WIDEBAND:
+         bandwidth_string = "wideband";
+         break;
+    case OPUS_BANDWIDTH_SUPERWIDEBAND:
+         bandwidth_string = "superwideband";
+         break;
+    case OPUS_BANDWIDTH_FULLBAND:
+         bandwidth_string = "fullband";
+         break;
+    case OPUS_AUTO:
+         bandwidth_string = "auto";
+         break;
+    default:
+         bandwidth_string = "unknown";
+         break;
+    }
 
-   if (bandwidth != -1)
-       opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
+    if (decode_only)
+       fprintf(stderr, "Decoding with %ld Hz output (%d channels)\n", (long)sampling_rate, channels);
+    else
+       fprintf(stderr, "Encoding %ld Hz input at %.3f kb/s in %s mode with %d-sample frames.\n", (long)sampling_rate, bitrate_bps*0.001, bandwidth_string, frame_size);
 
-   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));
+    in = (short*)malloc(frame_size*channels*sizeof(short));
+    out = (short*)malloc(max_frame_size*channels*sizeof(short));
+    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)
+    {
+        if (decode_only)
+        {
+            unsigned char ch[4];
+            err = fread(ch, 1, 4, fin);
+            if (feof(fin))
+                break;
+            len[toggle] = char_to_int(ch);
+            if (len[toggle]>max_payload_bytes || len[toggle]<0)
+            {
+                fprintf(stderr, "Invalid payload length: %d\n",len[toggle]);
+                break;
+            }
+            err = fread(ch, 1, 4, fin);
+            enc_final_range[toggle] = char_to_int(ch);
+            err = fread(data[toggle], 1, len[toggle], fin);
+            if (err<len[toggle])
+            {
+                fprintf(stderr, "Ran out of input, expecting %d bytes got %d\n",len[toggle],err);
+                break;
+            }
+        } else {
+            err = fread(in, sizeof(short)*channels, frame_size, fin);
+            curr_read = err;
+            if (curr_read < frame_size)
+            {
+                int i;
+                for (i=curr_read*channels;i<frame_size*channels;i++)
+                   in[i] = 0;
+                stop = 1;
+            }
 
-   //skip = 5*sampling_rate/1000 + 18;      // 18 is when SILK resamples
-   skip = 5*sampling_rate/1000;
+            len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
+            if (sweep_bps!=0)
+            {
+               bitrate_bps += sweep_bps;
+               /* safety */
+               if (bitrate_bps<1000)
+                  bitrate_bps = 1000;
+               opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
+            }
+            opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range[toggle]));
+            if (len[toggle] < 0)
+            {
+                fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
+                return 1;
+            }
+        }
 
-   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;
-      int lost;
-      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;
-      }
-      len = opus_encode(enc, in, frame_size, data, max_payload_bytes);
-      if (len <= 0)
-      {
-         fprintf (stderr, "opus_encode() returned %d\n", len);
-         return 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 {
+            int output_samples;
+            lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
+            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 */
+                        output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1);
+                    } else {
+                        /* regular decode */
+                        output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0);
+                    }
+                } else {
+                    output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0);
+                }
+                if (output_samples>0)
+                {
+                    fwrite(out+skip, sizeof(short)*channels, output_samples-skip, fout);
+                    skip = 0;
+                } else {
+                   fprintf(stderr, "error decoding frame: %s\n", opus_strerror(output_samples));
+                }
+            }
+        }
 
-      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;
-      }
-      fwrite(out+skip, sizeof(short), (write_samples-skip)*channels, fout);
-      skip = 0;
+        if (!encode_only)
+           opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
+        /* compare final range encoder rng values of encoder and decoder */
+        if( enc_final_range[toggle^use_inbandfec]!=0  && !encode_only && !lost && !lost_prev &&
+                       dec_final_range != enc_final_range[toggle^use_inbandfec] ) {
+            fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %ld: 0x%8lx vs 0x%8lx\n", (long)count, (unsigned long)enc_final_range[toggle^use_inbandfec], (unsigned long)dec_final_range);
+            return 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 ) ) {
-          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++;
-      }
-         /* Variance */
-         bits2 += len*len*64;
-   }
-   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);
-   fclose(fout);
-   free(in);
-   free(out);
-   return 0;
+        /* count bits */
+        bits += len[toggle]*8;
+        if( count >= use_inbandfec ) {
+            nrg = 0.0;
+            if (!decode_only)
+            {
+                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;
+        }
+        count++;
+        toggle = (toggle + use_inbandfec) & 1;
+    }
+    fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
+    if (!decode_only)
+       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);
+    /* Close any files to which intermediate results were stored */
+    SILK_DEBUG_STORE_CLOSE_FILES
+    silk_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);
+    free(out);
+    return 0;
 }