New bandwidth detection code
[opus.git] / src / opus_demo.c
index 06f30e1..09b12a3 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 Internet Society, IETF or IETF Trust, nor the
-   names of specific 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
@@ -68,13 +63,6 @@ void print_usage( char* argv[] )
     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
-#   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;
@@ -107,7 +95,7 @@ static void check_encoder_option(int decode_only, const char *opt)
    }
 }
 
-int silk8_test[][4] = {
+static const int silk8_test[][4] = {
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*3, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*2, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960,   1},
@@ -118,7 +106,7 @@ int silk8_test[][4] = {
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480,   2}
 };
 
-int silk12_test[][4] = {
+static const int silk12_test[][4] = {
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*3, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*2, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960,   1},
@@ -129,7 +117,7 @@ int silk12_test[][4] = {
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 480,   2}
 };
 
-int silk16_test[][4] = {
+static const int silk16_test[][4] = {
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*3, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*2, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960,   1},
@@ -140,21 +128,21 @@ int silk16_test[][4] = {
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480,   2}
 };
 
-int hybrid24_test[][4] = {
+static const int hybrid24_test[][4] = {
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 2},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 2}
 };
 
-int hybrid48_test[][4] = {
+static const int hybrid48_test[][4] = {
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 1},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 2},
       {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 2}
 };
 
-int celt_test[][4] = {
+static const int celt_test[][4] = {
       {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND,      960, 1},
       {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 1},
       {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND,      960, 1},
@@ -197,7 +185,7 @@ int celt_test[][4] = {
 
 };
 
-int celt_hq_test[][4] = {
+static const int celt_hq_test[][4] = {
       {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND,      960, 2},
       {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND,      480, 2},
       {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND,      240, 2},
@@ -216,6 +204,7 @@ int main(int argc, char *argv[])
     int frame_size, channels;
     opus_int32 bitrate_bps=0;
     unsigned char *data[2];
+    unsigned char *fbytes;
     opus_int32 sampling_rate;
     int use_vbr;
     int max_payload_bytes;
@@ -227,7 +216,7 @@ int main(int argc, char *argv[])
     int packet_loss_perc;
     opus_int32 count=0, count_act=0;
     int k;
-    int skip=0;
+    opus_int32 skip=0;
     int stop=0;
     short *in, *out;
     int application=OPUS_APPLICATION_AUDIO;
@@ -245,7 +234,7 @@ int main(int argc, char *argv[])
     int random_framesize=0, newsize=0, delayed_celt=0;
     int sweep_max=0, sweep_min=0;
     int random_fec=0;
-    int (*mode_list)[4]=NULL;
+    const int (*mode_list)[4]=NULL;
     int nb_modes_in_list=0;
     int curr_mode=0;
     int curr_mode_count=0;
@@ -322,11 +311,11 @@ int main(int argc, char *argv[])
 
     while( args < argc - 2 ) {
         /* process command line options */
-        if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cbr" ) == 0 ) {
+        if( strcmp( argv[ args ], "-cbr" ) == 0 ) {
             check_encoder_option(decode_only, "-cbr");
             use_vbr = 0;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-bandwidth" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-bandwidth" ) == 0 ) {
             check_encoder_option(decode_only, "-bandwidth");
             if (strcmp(argv[ args + 1 ], "NB")==0)
                 bandwidth = OPUS_BANDWIDTH_NARROWBAND;
@@ -345,7 +334,7 @@ int main(int argc, char *argv[])
                 return EXIT_FAILURE;
             }
             args += 2;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-framesize" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-framesize" ) == 0 ) {
             check_encoder_option(decode_only, "-framesize");
             if (strcmp(argv[ args + 1 ], "2.5")==0)
                 frame_size = sampling_rate/400;
@@ -366,80 +355,80 @@ int main(int argc, char *argv[])
                 return EXIT_FAILURE;
             }
             args += 2;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-max_payload" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-max_payload" ) == 0 ) {
             check_encoder_option(decode_only, "-max_payload");
             max_payload_bytes = atoi( argv[ args + 1 ] );
             args += 2;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-complexity" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-complexity" ) == 0 ) {
             check_encoder_option(decode_only, "-complexity");
             complexity = atoi( argv[ args + 1 ] );
             args += 2;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandfec" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-inbandfec" ) == 0 ) {
             use_inbandfec = 1;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-forcemono" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-forcemono" ) == 0 ) {
             check_encoder_option(decode_only, "-forcemono");
             forcechannels = 1;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cvbr" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-cvbr" ) == 0 ) {
             check_encoder_option(decode_only, "-cvbr");
             cvbr = 1;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-dtx") == 0 ) {
+        } else if( strcmp( argv[ args ], "-dtx") == 0 ) {
             check_encoder_option(decode_only, "-dtx");
             use_dtx = 1;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-loss" ) == 0 ) {
             check_decoder_option(encode_only, "-loss");
             packet_loss_perc = atoi( argv[ args + 1 ] );
             args += 2;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-sweep" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-sweep" ) == 0 ) {
             check_encoder_option(decode_only, "-sweep");
             sweep_bps = atoi( argv[ args + 1 ] );
             args += 2;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-random_framesize" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-random_framesize" ) == 0 ) {
             check_encoder_option(decode_only, "-random_framesize");
             random_framesize = 1;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-sweep_max" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-sweep_max" ) == 0 ) {
             check_encoder_option(decode_only, "-sweep_max");
             sweep_max = atoi( argv[ args + 1 ] );
             args += 2;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-random_fec" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-random_fec" ) == 0 ) {
             check_encoder_option(decode_only, "-random_fec");
             random_fec = 1;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-silk8k_test" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-silk8k_test" ) == 0 ) {
             check_encoder_option(decode_only, "-silk8k_test");
             mode_list = silk8_test;
             nb_modes_in_list = 8;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-silk12k_test" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-silk12k_test" ) == 0 ) {
             check_encoder_option(decode_only, "-silk12k_test");
             mode_list = silk12_test;
             nb_modes_in_list = 8;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-silk16k_test" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-silk16k_test" ) == 0 ) {
             check_encoder_option(decode_only, "-silk16k_test");
             mode_list = silk16_test;
             nb_modes_in_list = 8;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-hybrid24k_test" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-hybrid24k_test" ) == 0 ) {
             check_encoder_option(decode_only, "-hybrid24k_test");
             mode_list = hybrid24_test;
             nb_modes_in_list = 4;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-hybrid48k_test" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-hybrid48k_test" ) == 0 ) {
             check_encoder_option(decode_only, "-hybrid48k_test");
             mode_list = hybrid48_test;
             nb_modes_in_list = 4;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-celt_test" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-celt_test" ) == 0 ) {
             check_encoder_option(decode_only, "-celt_test");
             mode_list = celt_test;
             nb_modes_in_list = 32;
             args++;
-        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-celt_hq_test" ) == 0 ) {
+        } else if( strcmp( argv[ args ], "-celt_hq_test" ) == 0 ) {
             check_encoder_option(decode_only, "-celt_hq_test");
             mode_list = celt_hq_test;
             nb_modes_in_list = 4;
@@ -509,6 +498,7 @@ int main(int argc, char *argv[])
        opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
 
        opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
+       opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));
     }
     if (!encode_only)
     {
@@ -559,6 +549,7 @@ int main(int argc, char *argv[])
 
     in = (short*)malloc(max_frame_size*channels*sizeof(short));
     out = (short*)malloc(max_frame_size*channels*sizeof(short));
+    fbytes = (unsigned char*)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));
@@ -618,6 +609,7 @@ int main(int argc, char *argv[])
                 break;
             }
         } else {
+            int i;
             if (mode_list!=NULL)
             {
                 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(mode_list[curr_mode][1]));
@@ -625,11 +617,17 @@ int main(int argc, char *argv[])
                 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(mode_list[curr_mode][3]));
                 frame_size = mode_list[curr_mode][2];
             }
-            err = fread(in, sizeof(short)*channels, frame_size, fin);
+            err = fread(fbytes, sizeof(short)*channels, frame_size, fin);
             curr_read = err;
+            for(i=0;i<curr_read*channels;i++)
+            {
+                opus_int32 s;
+                s=fbytes[2*i+1]<<8|fbytes[2*i];
+                s=((s&0xFFFF)^0x8000)-0x8000;
+                in[i]=s;
+            }
             if (curr_read < frame_size)
             {
-                int i;
                 for (i=curr_read*channels;i<frame_size*channels;i++)
                    in[i] = 0;
                 stop = 1;
@@ -686,23 +684,35 @@ int main(int argc, char *argv[])
         } else {
             int output_samples;
             lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
+            if (lost)
+               opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
+            else
+               output_samples = max_frame_size;
             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);
+                        output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 1);
                     } else {
                         /* regular decode */
-                        output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0);
+                        output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, output_samples, 0);
                     }
                 } else {
-                    output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0);
+                    output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 0);
                 }
                 if (output_samples>0)
                 {
                     if (output_samples>skip) {
-                       if (fwrite(out+skip*channels, sizeof(short)*channels, output_samples-skip, fout) != (unsigned)(output_samples-skip)){
+                       int i;
+                       for(i=0;i<(output_samples-skip)*channels;i++)
+                       {
+                          short s;
+                          s=out[i+(skip*channels)];
+                          fbytes[2*i]=s&0xFF;
+                          fbytes[2*i+1]=(s>>8)&0xFF;
+                       }
+                       if (fwrite(fbytes, sizeof(short)*channels, output_samples-skip, fout) != (unsigned)(output_samples-skip)){
                           fprintf(stderr, "Error writing.\n");
                           return EXIT_FAILURE;
                        }
@@ -758,7 +768,7 @@ int main(int argc, char *argv[])
     }
     fprintf (stderr, "average bitrate:             %7.3f kb/s\n",
                      1e-3*bits*sampling_rate/(frame_size*(double)count));
-    fprintf (stderr, "maximum bitrate:             %7.3f bkp/s\n",
+    fprintf (stderr, "maximum bitrate:             %7.3f kb/s\n",
                      1e-3*bits_max*sampling_rate/frame_size);
     if (!decode_only)
        fprintf (stderr, "active bitrate:              %7.3f kb/s\n",
@@ -777,5 +787,6 @@ int main(int argc, char *argv[])
     fclose(fout);
     free(in);
     free(out);
+    free(fbytes);
     return EXIT_SUCCESS;
 }