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