Including redundant frames in the final range coder state
[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 constrained variable bitrate; default: unconstrained\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
242     inFile = argv[argc-2];
243     fin = fopen(inFile, "rb");
244     if (!fin)
245     {
246         fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
247         return 1;
248     }
249     outFile = argv[argc-1];
250     fout = fopen(outFile, "wb+");
251     if (!fout)
252     {
253         fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
254         return 1;
255     }
256
257     enc = opus_encoder_create(sampling_rate, channels, application);
258     dec = opus_decoder_create(sampling_rate, channels);
259
260     if (enc==NULL)
261     {
262         fprintf(stderr, "Failed to create an encoder\n");
263         exit(1);
264     }
265     if (dec==NULL)
266     {
267         fprintf(stderr, "Failed to create a decoder\n");
268         exit(1);
269     }
270
271     opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
272     opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
273     opus_encoder_ctl(enc, OPUS_SET_VBR(use_vbr));
274     opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
275     opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
276     opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
277     opus_encoder_ctl(enc, OPUS_SET_FORCE_MONO(forcemono));
278     opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx));
279     opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
280
281     skip = 5*sampling_rate/1000;
282     /* When SILK resamples, add 18 samples delay */
283     /*if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
284         skip += 18;*/
285
286     switch(bandwidth)
287     {
288     case OPUS_BANDWIDTH_NARROWBAND:
289          bandwidth_string = "narrowband";
290          break;
291     case OPUS_BANDWIDTH_MEDIUMBAND:
292          bandwidth_string = "mediumband";
293          break;
294     case OPUS_BANDWIDTH_WIDEBAND:
295          bandwidth_string = "wideband";
296          break;
297     case OPUS_BANDWIDTH_SUPERWIDEBAND:
298          bandwidth_string = "superwideband";
299          break;
300     case OPUS_BANDWIDTH_FULLBAND:
301          bandwidth_string = "fullband";
302          break;
303     case OPUS_BANDWIDTH_AUTO:
304          bandwidth_string = "auto";
305          break;
306     default:
307          bandwidth_string = "unknown";
308     }
309
310     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);
311
312     in = (short*)malloc(frame_size*channels*sizeof(short));
313     out = (short*)malloc(max_frame_size*channels*sizeof(short));
314     data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
315     if ( use_inbandfec ) {
316         data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
317     }
318     while (!stop)
319     {
320         if (decode_only)
321         {
322             unsigned char ch[4];
323             err = fread(ch, 1, 4, fin);
324             if (feof(fin))
325                 break;
326             len[toggle] = char_to_int(ch);
327             if (len[toggle]>max_payload_bytes || len[toggle]<0)
328             {
329                 fprintf(stderr, "Invalid payload length: %d\n",len[toggle]);
330                 break;
331             }
332             err = fread(ch, 1, 4, fin);
333             enc_final_range[toggle] = char_to_int(ch);
334             err = fread(data[toggle], 1, len[toggle], fin);
335             if (err<len[toggle])
336             {
337                 fprintf(stderr, "Ran out of input, expecting %d bytes got %d\n",len[toggle],err);
338                 break;
339             }
340         } else {
341             err = fread(in, sizeof(short)*channels, frame_size, fin);
342             curr_read = err;
343             if (curr_read < frame_size)
344             {
345                 int i;
346                 for (i=curr_read*channels;i<frame_size*channels;i++)
347                    in[i] = 0;
348                 stop = 1;
349             }
350
351             len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
352             enc_final_range[toggle] = opus_encoder_get_final_range( enc );
353             if (len[toggle] < 0)
354             {
355                 fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
356                 return 1;
357             }
358         }
359
360         if (encode_only)
361         {
362             unsigned char int_field[4];
363             int_to_char(len[toggle], int_field);
364             fwrite(int_field, 1, 4, fout);
365             int_to_char(enc_final_range[toggle], int_field);
366             fwrite(int_field, 1, 4, fout);
367             fwrite(data[toggle], 1, len[toggle], fout);
368         } else {
369             int output_samples;
370             lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
371             if( count >= use_inbandfec ) {
372                 /* delay by one packet when using in-band FEC */
373                 if( use_inbandfec  ) {
374                     if( lost_prev ) {
375                         /* attempt to decode with in-band FEC from next packet */
376                         output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1);
377                     } else {
378                         /* regular decode */
379                         output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0);
380                     }
381                 } else {
382                     output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0);
383                 }
384                 if (output_samples>0)
385                 {
386                     fwrite(out+skip, sizeof(short)*channels, output_samples-skip, fout);
387                     skip = 0;
388                 } else {
389                    fprintf(stderr, "error decoding frame: %s\n", opus_strerror(output_samples));
390                 }
391             }
392         }
393
394         /* compare final range encoder rng values of encoder and decoder */
395         if( enc_final_range[toggle^use_inbandfec]!=0  && !encode_only && !lost && !lost_prev &&
396              opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) {
397             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 ));
398             return 0;
399         }
400
401         lost_prev = lost;
402
403         /* count bits */
404         bits += len[toggle]*8;
405         if( count >= use_inbandfec ) {
406             nrg = 0.0;
407             if (!decode_only)
408             {
409                 for ( k = 0; k < frame_size * channels; k++ ) {
410                     nrg += in[ k ] * (double)in[ k ];
411                 }
412             }
413             if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
414                 bits_act += len[toggle]*8;
415                 count_act++;
416             }
417             /* Variance */
418             bits2 += len[toggle]*len[toggle]*64;
419         }
420         count++;
421         toggle = (toggle + use_inbandfec) & 1;
422     }
423     fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
424     fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
425     fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
426     /* Close any files to which intermediate results were stored */
427     SILK_DEBUG_STORE_CLOSE_FILES
428     silk_TimerSave("opus_timing.txt");
429     opus_encoder_destroy(enc);
430     opus_decoder_destroy(dec);
431     free(data[0]);
432     if (use_inbandfec)
433         free(data[1]);
434     fclose(fin);
435     fclose(fout);
436     free(in);
437     free(out);
438     return 0;
439 }