Fixes a rare integer overflow in the SILK "50% of max rate" rule
[opus.git] / src / test_opus.c
1 /* Copyright (c) 2007-2008 CSIRO
2    Copyright (c) 2007-2009 Xiph.Org Foundation
3    Written by Jean-Marc Valin */
4 /*
5    Redistribution and use in source and binary forms, with or without
6    modification, are permitted provided that the following conditions
7    are met:
8
9    - Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11
12    - Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15
16    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
20    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <math.h>
36 #include <string.h>
37 #include "opus.h"
38 #include "debug.h"
39 #include "opus_types.h"
40
41 #define MAX_PACKET 1500
42
43 void print_usage( char* argv[] )
44 {
45     fprintf(stderr, "Usage: %s [-e] <application> <sampling rate (Hz)> <channels (1/2)> "
46         "<bits per second>  [options] <input> <output>\n", argv[0]);
47     fprintf(stderr, "       %s -d <sampling rate (Hz)> <channels (1/2)> "
48         "[options] <input> <output>\n\n", argv[0]);
49     fprintf(stderr, "mode: voip | audio | restricted-lowdelay\n" );
50     fprintf(stderr, "options:\n" );
51     fprintf(stderr, "-e                   : only runs the encoder (output the bit-stream)\n" );
52     fprintf(stderr, "-d                   : only runs the decoder (reads the bit-stream as input)\n" );
53     fprintf(stderr, "-cbr                 : enable constant bitrate; default: variable bitrate\n" );
54     fprintf(stderr, "-cvbr                : enable constrained variable bitrate; default: unconstrained\n" );
55     fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
56     fprintf(stderr, "-framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20 \n" );
57     fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
58     fprintf(stderr, "-complexity <comp>   : complexity, 0 (lowest) ... 10 (highest); default: 10\n" );
59     fprintf(stderr, "-inbandfec           : enable SILK inband FEC\n" );
60     fprintf(stderr, "-forcemono           : force mono encoding, even for stereo input\n" );
61     fprintf(stderr, "-dtx                 : enable SILK DTX\n" );
62     fprintf(stderr, "-loss <perc>         : simulate packet loss, in percent (0-100); default: 0\n" );
63 }
64
65 #ifdef _WIN32
66 #   define STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y)
67 #else
68 #   include <strings.h>
69 #   define STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
70 #endif
71
72 static void int_to_char(opus_uint32 i, unsigned char ch[4])
73 {
74     ch[0] = i>>24;
75     ch[1] = (i>>16)&0xFF;
76     ch[2] = (i>>8)&0xFF;
77     ch[3] = i&0xFF;
78 }
79
80 static opus_uint32 char_to_int(unsigned char ch[4])
81 {
82     return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16)
83          | ((opus_uint32)ch[2]<< 8) |  (opus_uint32)ch[3];
84 }
85
86 int main(int argc, char *argv[])
87 {
88     int err;
89     char *inFile, *outFile;
90     FILE *fin, *fout;
91     OpusEncoder *enc=NULL;
92     OpusDecoder *dec=NULL;
93     int args;
94     int len[2];
95     int frame_size, channels;
96     opus_int32 bitrate_bps=0;
97     unsigned char *data[2];
98     opus_int32 sampling_rate;
99     int use_vbr;
100     int max_payload_bytes;
101     int complexity;
102     int use_inbandfec;
103     int use_dtx;
104     int forcechannels;
105     int cvbr = 0;
106     int packet_loss_perc;
107     opus_int32 count=0, count_act=0;
108     int k;
109     int skip=0;
110     int stop=0;
111     short *in, *out;
112     int application=OPUS_APPLICATION_AUDIO;
113     double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
114     int bandwidth=-1;
115     const char *bandwidth_string;
116     int lost = 0, lost_prev = 1;
117     int toggle = 0;
118     opus_uint32 enc_final_range[2];
119     opus_uint32 dec_final_range;
120     int encode_only=0, decode_only=0;
121     int max_frame_size = 960*6;
122     int curr_read=0;
123     int sweep_bps = 0;
124
125     if (argc < 5 )
126     {
127        print_usage( argv );
128        return 1;
129     }
130
131     fprintf(stderr, "%s\n", opus_get_version_string());
132
133     args = 1;
134     if (strcmp(argv[args], "-e")==0)
135     {
136         encode_only = 1;
137         args++;
138     } else if (strcmp(argv[args], "-d")==0)
139     {
140         decode_only = 1;
141         args++;
142     }
143     if (!decode_only && argc < 7 )
144     {
145        print_usage( argv );
146        return 1;
147     }
148
149     if (!decode_only)
150     {
151        if (strcmp(argv[args], "voip")==0)
152           application = OPUS_APPLICATION_VOIP;
153        else if (strcmp(argv[args], "restricted-lowdelay")==0)
154           application = OPUS_APPLICATION_RESTRICTED_LOWDELAY;
155        else if (strcmp(argv[args], "audio")!=0) {
156           fprintf(stderr, "unknown application: %s\n", argv[args]);
157           print_usage(argv);
158           return 1;
159        }
160        args++;
161     }
162     sampling_rate = (opus_int32)atol(argv[args]);
163     args++;
164     channels = atoi(argv[args]);
165     args++;
166     if (!decode_only)
167     {
168        bitrate_bps = (opus_int32)atol(argv[args]);
169        args++;
170     }
171
172     if (sampling_rate != 8000 && sampling_rate != 12000 && sampling_rate != 16000
173      && sampling_rate != 24000 && sampling_rate != 48000)
174     {
175         fprintf(stderr, "Supported sampling rates are 8000, 12000, 16000, "
176                 "24000 and 48000.\n");
177         return 1;
178     }
179     frame_size = sampling_rate/50;
180
181     /* defaults: */
182     use_vbr = 1;
183     bandwidth = OPUS_AUTO;
184     max_payload_bytes = MAX_PACKET;
185     complexity = 10;
186     use_inbandfec = 0;
187     forcechannels = OPUS_AUTO;
188     use_dtx = 0;
189     packet_loss_perc = 0;
190     max_frame_size = 960*6;
191     curr_read=0;
192
193     while( args < argc - 2 ) {
194         /* process command line options */
195         if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cbr" ) == 0 ) {
196             use_vbr = 0;
197             args++;
198         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-bandwidth" ) == 0 ) {
199             if (strcmp(argv[ args + 1 ], "NB")==0)
200                 bandwidth = OPUS_BANDWIDTH_NARROWBAND;
201             else if (strcmp(argv[ args + 1 ], "MB")==0)
202                 bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
203             else if (strcmp(argv[ args + 1 ], "WB")==0)
204                 bandwidth = OPUS_BANDWIDTH_WIDEBAND;
205             else if (strcmp(argv[ args + 1 ], "SWB")==0)
206                 bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
207             else if (strcmp(argv[ args + 1 ], "FB")==0)
208                 bandwidth = OPUS_BANDWIDTH_FULLBAND;
209             else {
210                 fprintf(stderr, "Unknown bandwidth %s. Supported are NB, MB, WB, SWB, FB.\n", argv[ args + 1 ]);
211                 return 1;
212             }
213             args += 2;
214         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-framesize" ) == 0 ) {
215             if (strcmp(argv[ args + 1 ], "2.5")==0)
216                 frame_size = sampling_rate/400;
217             else if (strcmp(argv[ args + 1 ], "5")==0)
218                 frame_size = sampling_rate/200;
219             else if (strcmp(argv[ args + 1 ], "10")==0)
220                 frame_size = sampling_rate/100;
221             else if (strcmp(argv[ args + 1 ], "20")==0)
222                 frame_size = sampling_rate/50;
223             else if (strcmp(argv[ args + 1 ], "40")==0)
224                 frame_size = sampling_rate/25;
225             else if (strcmp(argv[ args + 1 ], "60")==0)
226                 frame_size = 3*sampling_rate/50;
227             else {
228                 fprintf(stderr, "Unsupported frame size: %s ms. Supported are 2.5, 5, 10, 20, 40, 60.\n", argv[ args + 1 ]);
229                 return 1;
230             }
231             args += 2;
232         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-max_payload" ) == 0 ) {
233             max_payload_bytes = atoi( argv[ args + 1 ] );
234             args += 2;
235         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-complexity" ) == 0 ) {
236             complexity = atoi( argv[ args + 1 ] );
237             args += 2;
238         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandfec" ) == 0 ) {
239             use_inbandfec = 1;
240             args++;
241         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-forcemono" ) == 0 ) {
242             forcechannels = 1;
243             args++;
244         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cvbr" ) == 0 ) {
245             cvbr = 1;
246             args++;
247         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-dtx") == 0 ) {
248             use_dtx = 1;
249             args++;
250         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
251             packet_loss_perc = atoi( argv[ args + 1 ] );
252             args += 2;
253         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-sweep" ) == 0 ) {
254             sweep_bps = atoi( argv[ args + 1 ] );
255             args += 2;
256         } else {
257             printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
258             print_usage( argv );
259             return 1;
260         }
261     }
262
263     if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
264     {
265         fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
266                           MAX_PACKET);
267         return 1;
268     }
269
270     inFile = argv[argc-2];
271     fin = fopen(inFile, "rb");
272     if (!fin)
273     {
274         fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
275         return 1;
276     }
277     outFile = argv[argc-1];
278     fout = fopen(outFile, "wb+");
279     if (!fout)
280     {
281         fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
282         return 1;
283     }
284
285     if (!decode_only)
286     {
287        enc = opus_encoder_create(sampling_rate, channels, application, &err);
288        if (err != OPUS_OK)
289        {
290           fprintf(stderr, "Cannot create encoder: %s\n", opus_strerror(err));
291           return 1;
292        }
293        opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
294        opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
295        opus_encoder_ctl(enc, OPUS_SET_VBR(use_vbr));
296        opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
297        opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
298        opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(use_inbandfec));
299        opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(forcechannels));
300        opus_encoder_ctl(enc, OPUS_SET_DTX(use_dtx));
301        opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
302
303        opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
304     }
305     if (!encode_only)
306     {
307        dec = opus_decoder_create(sampling_rate, channels, &err);
308        if (err != OPUS_OK)
309        {
310           fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
311           return 1;
312        }
313     }
314
315
316     switch(bandwidth)
317     {
318     case OPUS_BANDWIDTH_NARROWBAND:
319          bandwidth_string = "narrowband";
320          break;
321     case OPUS_BANDWIDTH_MEDIUMBAND:
322          bandwidth_string = "mediumband";
323          break;
324     case OPUS_BANDWIDTH_WIDEBAND:
325          bandwidth_string = "wideband";
326          break;
327     case OPUS_BANDWIDTH_SUPERWIDEBAND:
328          bandwidth_string = "superwideband";
329          break;
330     case OPUS_BANDWIDTH_FULLBAND:
331          bandwidth_string = "fullband";
332          break;
333     case OPUS_AUTO:
334          bandwidth_string = "auto";
335          break;
336     default:
337          bandwidth_string = "unknown";
338          break;
339     }
340
341     if (decode_only)
342        fprintf(stderr, "Decoding with %ld Hz output (%d channels)\n", (long)sampling_rate, channels);
343     else
344        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);
345
346     in = (short*)malloc(frame_size*channels*sizeof(short));
347     out = (short*)malloc(max_frame_size*channels*sizeof(short));
348     data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
349     if ( use_inbandfec ) {
350         data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
351     }
352     while (!stop)
353     {
354         if (decode_only)
355         {
356             unsigned char ch[4];
357             err = fread(ch, 1, 4, fin);
358             if (feof(fin))
359                 break;
360             len[toggle] = char_to_int(ch);
361             if (len[toggle]>max_payload_bytes || len[toggle]<0)
362             {
363                 fprintf(stderr, "Invalid payload length: %d\n",len[toggle]);
364                 break;
365             }
366             err = fread(ch, 1, 4, fin);
367             enc_final_range[toggle] = char_to_int(ch);
368             err = fread(data[toggle], 1, len[toggle], fin);
369             if (err<len[toggle])
370             {
371                 fprintf(stderr, "Ran out of input, expecting %d bytes got %d\n",len[toggle],err);
372                 break;
373             }
374         } else {
375             err = fread(in, sizeof(short)*channels, frame_size, fin);
376             curr_read = err;
377             if (curr_read < frame_size)
378             {
379                 int i;
380                 for (i=curr_read*channels;i<frame_size*channels;i++)
381                    in[i] = 0;
382                 stop = 1;
383             }
384
385             len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
386             if (sweep_bps!=0)
387             {
388                bitrate_bps += sweep_bps;
389                /* safety */
390                if (bitrate_bps<1000)
391                   bitrate_bps = 1000;
392                opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
393             }
394             opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range[toggle]));
395             if (len[toggle] < 0)
396             {
397                 fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
398                 return 1;
399             }
400         }
401
402         if (encode_only)
403         {
404             unsigned char int_field[4];
405             int_to_char(len[toggle], int_field);
406             fwrite(int_field, 1, 4, fout);
407             int_to_char(enc_final_range[toggle], int_field);
408             fwrite(int_field, 1, 4, fout);
409             fwrite(data[toggle], 1, len[toggle], fout);
410         } else {
411             int output_samples;
412             lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
413             if( count >= use_inbandfec ) {
414                 /* delay by one packet when using in-band FEC */
415                 if( use_inbandfec  ) {
416                     if( lost_prev ) {
417                         /* attempt to decode with in-band FEC from next packet */
418                         output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1);
419                     } else {
420                         /* regular decode */
421                         output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0);
422                     }
423                 } else {
424                     output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0);
425                 }
426                 if (output_samples>0)
427                 {
428                     fwrite(out+skip, sizeof(short)*channels, output_samples-skip, fout);
429                     skip = 0;
430                 } else {
431                    fprintf(stderr, "error decoding frame: %s\n", opus_strerror(output_samples));
432                 }
433             }
434         }
435
436         if (!encode_only)
437            opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
438         /* compare final range encoder rng values of encoder and decoder */
439         if( enc_final_range[toggle^use_inbandfec]!=0  && !encode_only && !lost && !lost_prev &&
440                         dec_final_range != enc_final_range[toggle^use_inbandfec] ) {
441             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);
442             return 0;
443         }
444
445         lost_prev = lost;
446
447         /* count bits */
448         bits += len[toggle]*8;
449         if( count >= use_inbandfec ) {
450             nrg = 0.0;
451             if (!decode_only)
452             {
453                 for ( k = 0; k < frame_size * channels; k++ ) {
454                     nrg += in[ k ] * (double)in[ k ];
455                 }
456             }
457             if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
458                 bits_act += len[toggle]*8;
459                 count_act++;
460             }
461             /* Variance */
462             bits2 += len[toggle]*len[toggle]*64;
463         }
464         count++;
465         toggle = (toggle + use_inbandfec) & 1;
466     }
467     fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
468     if (!decode_only)
469        fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
470     fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
471     /* Close any files to which intermediate results were stored */
472     SILK_DEBUG_STORE_CLOSE_FILES
473     silk_TimerSave("opus_timing.txt");
474     opus_encoder_destroy(enc);
475     opus_decoder_destroy(dec);
476     free(data[0]);
477     if (use_inbandfec)
478         free(data[1]);
479     fclose(fin);
480     fclose(fout);
481     free(in);
482     free(out);
483     return 0;
484 }