Fixes a bunch of valgrind errors when decoding random junk
[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 "silk_debug.h"
39 #include "celt_types.h"
40
41 #define MAX_PACKET 1500
42
43 void print_usage( char* argv[] ) 
44 {
45     fprintf(stderr, "Usage: %s [-e | -d] <application (0/1)> <sampling rate (Hz)> <channels (1/2)> "
46         "<bits per second>  [options] <input> <output>\n\n", argv[0]);
47     fprintf(stderr, "mode: 0 for VoIP, 1 for audio:\n" );
48     fprintf(stderr, "options:\n" );
49     fprintf(stderr, "-e                   : only runs the encoder (output the bit-stream)\n" );
50     fprintf(stderr, "-d                   : only runs the decoder (reads the bit-stream as input)\n" );
51     fprintf(stderr, "-cbr                 : enable constant bitrate; default: variable bitrate\n" );
52     fprintf(stderr, "-cvbr                : enable constraint variable bitrate; default: unconstraint\n" );
53     fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
54     fprintf(stderr, "-framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20 \n" );
55     fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
56     fprintf(stderr, "-complexity <comp>   : complexity, 0 (lowest) ... 10 (highest); default: 10\n" );
57     fprintf(stderr, "-inbandfec           : enable SILK inband FEC\n" );
58     fprintf(stderr, "-forcemono           : force mono encoding, even for stereo input\n" );
59     fprintf(stderr, "-dtx                 : enable SILK DTX\n" );
60     fprintf(stderr, "-loss <perc>         : simulate packet loss, in percent (0-100); default: 0\n" );
61 }
62
63 #ifdef _WIN32
64 #       define STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y)
65 #else
66 #       define STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
67 #endif 
68
69 static void int_to_char(celt_uint32 i, unsigned char ch[4])
70 {
71     ch[0] = i>>24;
72     ch[1] = (i>>16)&0xFF;
73     ch[2] = (i>>8)&0xFF;
74     ch[3] = i&0xFF;
75 }
76
77 static celt_uint32 char_to_int(unsigned char ch[4])
78 {
79     return ((celt_uint32)ch[0]<<24) | ((celt_uint32)ch[1]<<16)
80          | ((celt_uint32)ch[2]<< 8) |  (celt_uint32)ch[3];
81 }
82
83 int main(int argc, char *argv[])
84 {
85    int err;
86    char *inFile, *outFile;
87    FILE *fin, *fout;
88    OpusEncoder *enc;
89    OpusDecoder *dec;
90    int args;
91    int len[2];
92    int frame_size, channels;
93    int bitrate_bps;
94    unsigned char *data[2];
95    int sampling_rate;
96    int use_vbr;
97    int internal_sampling_rate_Hz;
98    int max_payload_bytes;
99    int complexity;
100    int use_inbandfec;
101    int use_dtx;
102    int forcemono;
103    int cvbr = 0;
104    int packet_loss_perc;
105    int count=0, count_act=0, k;
106    int skip;
107    int stop=0;
108    int tot_read=0, tot_written=0;
109    short *in, *out;
110    int application;
111    double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
112    int bandwidth=-1;
113    const char *bandwidth_string;
114    int write_samples;
115    int lost, lost_prev = 1;
116    int toggle = 0;
117    int enc_final_range[2];
118    int encode_only=0, decode_only=0;
119
120    if (argc < 7 )
121    {
122       print_usage( argv );
123       return 1;
124    }
125
126    if (strcmp(argv[1], "-e")==0)
127    {
128        encode_only = 1;
129        argv++;
130        argc--;
131    } else if (strcmp(argv[1], "-d")==0)
132    {
133        decode_only = 1;
134        argv++;
135        argc--;
136    }
137    application = atoi(argv[1]) + OPUS_APPLICATION_VOIP;
138    sampling_rate = atoi(argv[2]);
139    channels = atoi(argv[3]);
140    bitrate_bps = atoi(argv[4]);
141
142    if (sampling_rate != 8000 && sampling_rate != 12000 && sampling_rate != 16000
143            && sampling_rate != 24000 && sampling_rate != 48000)
144    {
145        fprintf(stderr, "Supported sampling rates are 8000, 12000, 16000, "
146                "24000 and 48000.\n");
147        return 1;
148    }
149    frame_size = sampling_rate/50;
150
151    /* defaults: */
152    use_vbr = 1;
153    bandwidth=OPUS_BANDWIDTH_AUTO;
154    internal_sampling_rate_Hz = sampling_rate;
155    max_payload_bytes = MAX_PACKET;
156    complexity = 10;
157    use_inbandfec = 0;
158    forcemono = 0;
159    use_dtx = 0;
160    packet_loss_perc = 0;
161    int max_frame_size = 960*3;
162
163    args = 5;
164    while( args < argc - 2 ) {
165        /* process command line options */
166         if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cbr" ) == 0 ) {
167             use_vbr = 0;
168             args++;
169         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-bandwidth" ) == 0 ) {
170             if (strcmp(argv[ args + 1 ], "NB")==0)
171                 bandwidth = OPUS_BANDWIDTH_NARROWBAND;
172             else if (strcmp(argv[ args + 1 ], "MB")==0)
173                 bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
174             else if (strcmp(argv[ args + 1 ], "WB")==0)
175                 bandwidth = OPUS_BANDWIDTH_WIDEBAND;
176             else if (strcmp(argv[ args + 1 ], "SWB")==0)
177                 bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
178             else if (strcmp(argv[ args + 1 ], "FB")==0)
179                 bandwidth = OPUS_BANDWIDTH_FULLBAND;
180             else {
181                 fprintf(stderr, "Unknown bandwidth %s. Supported are NB, MB, WB, SWB, FB.\n", argv[ args + 1 ]);
182                 return 1;
183             }
184             args += 2;
185         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-framesize" ) == 0 ) {
186             if (strcmp(argv[ args + 1 ], "2.5")==0)
187                 frame_size = sampling_rate/400;
188             else if (strcmp(argv[ args + 1 ], "5")==0)
189                 frame_size = sampling_rate/200;
190             else if (strcmp(argv[ args + 1 ], "10")==0)
191                 frame_size = sampling_rate/100;
192             else if (strcmp(argv[ args + 1 ], "20")==0)
193                 frame_size = sampling_rate/50;
194             else if (strcmp(argv[ args + 1 ], "40")==0)
195                 frame_size = sampling_rate/25;
196             else if (strcmp(argv[ args + 1 ], "60")==0)
197                 frame_size = 3*sampling_rate/50;
198             else {
199                 fprintf(stderr, "Unsupported frame size: %s ms. Supported are 2.5, 5, 10, 20, 40, 60.\n", argv[ args + 1 ]);
200                 return 1;
201             }
202             args += 2;
203         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-max_payload" ) == 0 ) {
204             max_payload_bytes = atoi( argv[ args + 1 ] );
205             args += 2;
206         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-complexity" ) == 0 ) {
207             complexity = atoi( argv[ args + 1 ] );
208             args += 2;
209         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandfec" ) == 0 ) {
210             use_inbandfec = 1;
211             args++;
212         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-forcemono" ) == 0 ) {
213             forcemono = 1;
214             args++;
215         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cvbr" ) == 0 ) {
216             cvbr = 1;
217             args++;
218         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-dtx") == 0 ) {
219             use_dtx = 1;
220             args++;
221         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
222             packet_loss_perc = atoi( argv[ args + 1 ] );
223             args += 2;
224         } else {
225             printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
226             print_usage( argv );
227             return 1;
228         }
229    }
230
231    if( application < OPUS_APPLICATION_VOIP || application > OPUS_APPLICATION_AUDIO) {
232       fprintf (stderr, "mode must be: 0 or 1\n");
233       return 1;
234    }
235
236    if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
237    {
238       fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
239                         MAX_PACKET);
240       return 1;
241    }
242    if (bitrate_bps < 0 || bitrate_bps*frame_size/sampling_rate > max_payload_bytes*8)
243    {
244       fprintf (stderr, "bytes per packet must be between 0 and %d\n",
245                         max_payload_bytes);
246       return 1;
247    }
248
249    inFile = argv[argc-2];
250    fin = fopen(inFile, "rb");
251    if (!fin)
252    {
253       fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
254       return 1;
255    }
256    outFile = argv[argc-1];
257    fout = fopen(outFile, "wb+");
258    if (!fout)
259    {
260       fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
261       return 1;
262    }
263
264    enc = opus_encoder_create(sampling_rate, channels, application);
265    dec = opus_decoder_create(sampling_rate, channels);
266
267    if (enc==NULL)
268    {
269       fprintf(stderr, "Failed to create an encoder\n");
270       exit(1);
271    }
272    if (dec==NULL)
273    {
274       fprintf(stderr, "Failed to create a decoder\n");
275       exit(1);
276    }
277
278    opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
279    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
280    opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
281    opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
282    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
283    opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
284    opus_encoder_ctl(enc, OPUS_SET_FORCE_MONO(forcemono));
285    opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx));
286    opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
287
288    skip = 5*sampling_rate/1000;
289    /* When SILK resamples, add 18 samples delay */
290    /*if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
291            skip += 18;*/
292
293    switch(bandwidth)
294    {
295    case OPUS_BANDWIDTH_NARROWBAND:
296            bandwidth_string = "narrowband";
297            break;
298    case OPUS_BANDWIDTH_MEDIUMBAND:
299            bandwidth_string = "mediumband";
300            break;
301    case OPUS_BANDWIDTH_WIDEBAND:
302            bandwidth_string = "wideband";
303            break;
304    case OPUS_BANDWIDTH_SUPERWIDEBAND:
305            bandwidth_string = "superwideband";
306            break;
307    case OPUS_BANDWIDTH_FULLBAND:
308            bandwidth_string = "fullband";
309            break;
310    case OPUS_BANDWIDTH_AUTO:
311            bandwidth_string = "auto";
312            break;
313    default:
314            bandwidth_string = "unknown";
315    }
316
317    fprintf(stderr, "Encoding %d Hz input at %.3f kb/s in %s mode with %d-sample frames.\n", sampling_rate, bitrate_bps*0.001, bandwidth_string, frame_size);
318
319    in = (short*)malloc(frame_size*channels*sizeof(short));
320    out = (short*)malloc(max_frame_size*channels*sizeof(short));
321    data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
322    if( use_inbandfec ) {
323        data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
324    }
325    while (!stop)
326    {
327       if (decode_only)
328       {
329           unsigned char ch[4];
330           err = fread(ch, 1, 4, fin);
331           len[toggle] = char_to_int(ch);
332           if (len[toggle]>max_payload_bytes || len[toggle]<0)
333           {
334                   fprintf(stderr, "Invalid payload length\n");
335                   break;
336           }
337           err = fread(ch, 1, 4, fin);
338           enc_final_range[toggle] = char_to_int(ch);
339           err = fread(data[toggle], 1, len[toggle], fin);
340           if (feof(fin))
341               break;
342           tot_read += frame_size*channels;
343       } else {
344           err = fread(in, sizeof(short), frame_size*channels, fin);
345           tot_read += err;
346           if (err < frame_size*channels)
347           {
348               int i;
349               for (i=err;i<frame_size*channels;i++)
350                   in[i] = 0;
351               stop = 1;
352           }
353
354           len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
355 #if OPUS_TEST_RANGE_CODER_STATE
356           enc_final_range[toggle] = opus_encoder_get_final_range( enc );
357 #endif
358           if (len[toggle] < 0)
359           {
360               fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
361               return 1;
362           }
363       }
364
365       if (encode_only)
366       {
367           unsigned char int_field[4];
368           int_to_char(len[toggle], int_field);
369           fwrite(int_field, 1, 4, fout);
370           int_to_char(enc_final_range[toggle], int_field);
371           fwrite(int_field, 1, 4, fout);
372           fwrite(data[toggle], 1, len[toggle], fout);
373       } else {
374           int output_samples;
375           lost = rand()%100 < packet_loss_perc || len[toggle]==0;
376           if( count >= use_inbandfec ) {
377               /* delay by one packet when using in-band FEC */
378               if( use_inbandfec  ) {
379                   if( lost_prev ) {
380                       /* attempt to decode with in-band FEC from next packet */
381                           output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1);
382                   } else {
383                       /* regular decode */
384                           output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0);
385                   }
386               } else {
387                   output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0);
388               }
389               if (output_samples>0)
390               {
391                   write_samples = output_samples-skip;
392                   tot_written += write_samples*channels;
393                   if (tot_written > tot_read)
394                   {
395                           write_samples -= (tot_written-tot_read)/channels;
396                   }
397                   fwrite(out+skip, sizeof(short), write_samples*channels, fout);
398                   skip = 0;
399               }
400           }
401       }
402
403 #if OPUS_TEST_RANGE_CODER_STATE
404       /* compare final range encoder rng values of encoder and decoder */
405       if( !encode_only && !lost && !lost_prev
406          && opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) {
407           fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %d.\n", count);
408           return 0;
409       }
410 #endif
411
412       lost_prev = lost;
413
414       /* count bits */
415       bits += len[toggle]*8;
416       if( count >= use_inbandfec ) {
417           nrg = 0.0;
418           if (!decode_only)
419           {
420                   for ( k = 0; k < frame_size * channels; k++ ) {
421                           nrg += in[ k ] * (double)in[ k ];
422                   }
423           }
424           if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
425               bits_act += len[toggle]*8;
426               count_act++;
427           }
428               /* Variance */
429               bits2 += len[toggle]*len[toggle]*64;
430       }
431       count++;
432       toggle = (toggle + use_inbandfec) & 1;
433    }
434    fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
435    fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
436    fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
437    /* Close any files to which intermediate results were stored */
438    SILK_DEBUG_STORE_CLOSE_FILES
439    silk_TimerSave("opus_timing.txt");
440    opus_encoder_destroy(enc);
441    opus_decoder_destroy(dec);
442    free(data[0]);
443    if (use_inbandfec)
444            free(data[1]);
445    fclose(fin);
446    fclose(fout);
447    free(in);
448    free(out);
449    return 0;
450 }