e1884f377f97ae8541067068ac03e8dd39ddab39
[opus.git] / src / opus_demo.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 static void check_decoder_option(int encode_only, const char *opt)
87 {
88    if (encode_only)
89    {
90       fprintf(stderr, "option %s is only for decoding\n", opt);
91       exit(EXIT_FAILURE);
92    }
93 }
94
95 static void check_encoder_option(int decode_only, const char *opt)
96 {
97    if (decode_only)
98    {
99       fprintf(stderr, "option %s is only for encoding\n", opt);
100       exit(EXIT_FAILURE);
101    }
102 }
103
104 int main(int argc, char *argv[])
105 {
106     int err;
107     char *inFile, *outFile;
108     FILE *fin, *fout;
109     OpusEncoder *enc=NULL;
110     OpusDecoder *dec=NULL;
111     int args;
112     int len[2];
113     int frame_size, channels;
114     opus_int32 bitrate_bps=0;
115     unsigned char *data[2];
116     opus_int32 sampling_rate;
117     int use_vbr;
118     int max_payload_bytes;
119     int complexity;
120     int use_inbandfec;
121     int use_dtx;
122     int forcechannels;
123     int cvbr = 0;
124     int packet_loss_perc;
125     opus_int32 count=0, count_act=0;
126     int k;
127     int skip=0;
128     int stop=0;
129     short *in, *out;
130     int application=OPUS_APPLICATION_AUDIO;
131     double bits=0.0, bits_max=0.0, bits_act=0.0, bits2=0.0, nrg;
132     int bandwidth=-1;
133     const char *bandwidth_string;
134     int lost = 0, lost_prev = 1;
135     int toggle = 0;
136     opus_uint32 enc_final_range[2];
137     opus_uint32 dec_final_range;
138     int encode_only=0, decode_only=0;
139     int max_frame_size = 960*6;
140     int curr_read=0;
141     int sweep_bps = 0;
142
143     if (argc < 5 )
144     {
145        print_usage( argv );
146        return EXIT_FAILURE;
147     }
148
149     fprintf(stderr, "%s\n", opus_get_version_string());
150
151     args = 1;
152     if (strcmp(argv[args], "-e")==0)
153     {
154         encode_only = 1;
155         args++;
156     } else if (strcmp(argv[args], "-d")==0)
157     {
158         decode_only = 1;
159         args++;
160     }
161     if (!decode_only && argc < 7 )
162     {
163        print_usage( argv );
164        return EXIT_FAILURE;
165     }
166
167     if (!decode_only)
168     {
169        if (strcmp(argv[args], "voip")==0)
170           application = OPUS_APPLICATION_VOIP;
171        else if (strcmp(argv[args], "restricted-lowdelay")==0)
172           application = OPUS_APPLICATION_RESTRICTED_LOWDELAY;
173        else if (strcmp(argv[args], "audio")!=0) {
174           fprintf(stderr, "unknown application: %s\n", argv[args]);
175           print_usage(argv);
176           return EXIT_FAILURE;
177        }
178        args++;
179     }
180     sampling_rate = (opus_int32)atol(argv[args]);
181     args++;
182     channels = atoi(argv[args]);
183     args++;
184     if (!decode_only)
185     {
186        bitrate_bps = (opus_int32)atol(argv[args]);
187        args++;
188     }
189
190     if (sampling_rate != 8000 && sampling_rate != 12000
191      && sampling_rate != 16000 && sampling_rate != 24000
192      && sampling_rate != 48000)
193     {
194         fprintf(stderr, "Supported sampling rates are 8000, 12000, "
195                 "16000, 24000 and 48000.\n");
196         return EXIT_FAILURE;
197     }
198     frame_size = sampling_rate/50;
199
200     /* defaults: */
201     use_vbr = 1;
202     bandwidth = OPUS_AUTO;
203     max_payload_bytes = MAX_PACKET;
204     complexity = 10;
205     use_inbandfec = 0;
206     forcechannels = OPUS_AUTO;
207     use_dtx = 0;
208     packet_loss_perc = 0;
209     max_frame_size = 960*6;
210     curr_read=0;
211
212     while( args < argc - 2 ) {
213         /* process command line options */
214         if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cbr" ) == 0 ) {
215             check_encoder_option(decode_only, "-cbr");
216             use_vbr = 0;
217             args++;
218         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-bandwidth" ) == 0 ) {
219             check_encoder_option(decode_only, "-bandwidth");
220             if (strcmp(argv[ args + 1 ], "NB")==0)
221                 bandwidth = OPUS_BANDWIDTH_NARROWBAND;
222             else if (strcmp(argv[ args + 1 ], "MB")==0)
223                 bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
224             else if (strcmp(argv[ args + 1 ], "WB")==0)
225                 bandwidth = OPUS_BANDWIDTH_WIDEBAND;
226             else if (strcmp(argv[ args + 1 ], "SWB")==0)
227                 bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
228             else if (strcmp(argv[ args + 1 ], "FB")==0)
229                 bandwidth = OPUS_BANDWIDTH_FULLBAND;
230             else {
231                 fprintf(stderr, "Unknown bandwidth %s. "
232                                 "Supported are NB, MB, WB, SWB, FB.\n",
233                                 argv[ args + 1 ]);
234                 return EXIT_FAILURE;
235             }
236             args += 2;
237         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-framesize" ) == 0 ) {
238             check_encoder_option(decode_only, "-framesize");
239             if (strcmp(argv[ args + 1 ], "2.5")==0)
240                 frame_size = sampling_rate/400;
241             else if (strcmp(argv[ args + 1 ], "5")==0)
242                 frame_size = sampling_rate/200;
243             else if (strcmp(argv[ args + 1 ], "10")==0)
244                 frame_size = sampling_rate/100;
245             else if (strcmp(argv[ args + 1 ], "20")==0)
246                 frame_size = sampling_rate/50;
247             else if (strcmp(argv[ args + 1 ], "40")==0)
248                 frame_size = sampling_rate/25;
249             else if (strcmp(argv[ args + 1 ], "60")==0)
250                 frame_size = 3*sampling_rate/50;
251             else {
252                 fprintf(stderr, "Unsupported frame size: %s ms. "
253                                 "Supported are 2.5, 5, 10, 20, 40, 60.\n",
254                                 argv[ args + 1 ]);
255                 return EXIT_FAILURE;
256             }
257             args += 2;
258         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-max_payload" ) == 0 ) {
259             check_encoder_option(decode_only, "-max_payload");
260             max_payload_bytes = atoi( argv[ args + 1 ] );
261             args += 2;
262         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-complexity" ) == 0 ) {
263             check_encoder_option(decode_only, "-complexity");
264             complexity = atoi( argv[ args + 1 ] );
265             args += 2;
266         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandfec" ) == 0 ) {
267             use_inbandfec = 1;
268             args++;
269         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-forcemono" ) == 0 ) {
270             check_encoder_option(decode_only, "-forcemono");
271             forcechannels = 1;
272             args++;
273         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cvbr" ) == 0 ) {
274             check_encoder_option(decode_only, "-cvbr");
275             cvbr = 1;
276             args++;
277         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-dtx") == 0 ) {
278             check_encoder_option(decode_only, "-dtx");
279             use_dtx = 1;
280             args++;
281         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
282             check_decoder_option(encode_only, "-loss");
283             packet_loss_perc = atoi( argv[ args + 1 ] );
284             args += 2;
285         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-sweep" ) == 0 ) {
286             check_encoder_option(decode_only, "-sweep");
287             sweep_bps = atoi( argv[ args + 1 ] );
288             args += 2;
289         } else {
290             printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
291             print_usage( argv );
292             return EXIT_FAILURE;
293         }
294     }
295
296     if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
297     {
298         fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
299                           MAX_PACKET);
300         return EXIT_FAILURE;
301     }
302
303     inFile = argv[argc-2];
304     fin = fopen(inFile, "rb");
305     if (!fin)
306     {
307         fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
308         return EXIT_FAILURE;
309     }
310     outFile = argv[argc-1];
311     fout = fopen(outFile, "wb+");
312     if (!fout)
313     {
314         fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
315         fclose(fin);
316         return EXIT_FAILURE;
317     }
318
319     if (!decode_only)
320     {
321        enc = opus_encoder_create(sampling_rate, channels, application, &err);
322        if (err != OPUS_OK)
323        {
324           fprintf(stderr, "Cannot create encoder: %s\n", opus_strerror(err));
325           fclose(fin);
326           fclose(fout);
327           return EXIT_FAILURE;
328        }
329        opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
330        opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
331        opus_encoder_ctl(enc, OPUS_SET_VBR(use_vbr));
332        opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
333        opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
334        opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(use_inbandfec));
335        opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(forcechannels));
336        opus_encoder_ctl(enc, OPUS_SET_DTX(use_dtx));
337        opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
338
339        opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
340     }
341     if (!encode_only)
342     {
343        dec = opus_decoder_create(sampling_rate, channels, &err);
344        if (err != OPUS_OK)
345        {
346           fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
347           fclose(fin);
348           fclose(fout);
349           return EXIT_FAILURE;
350        }
351     }
352
353
354     switch(bandwidth)
355     {
356     case OPUS_BANDWIDTH_NARROWBAND:
357          bandwidth_string = "narrowband";
358          break;
359     case OPUS_BANDWIDTH_MEDIUMBAND:
360          bandwidth_string = "mediumband";
361          break;
362     case OPUS_BANDWIDTH_WIDEBAND:
363          bandwidth_string = "wideband";
364          break;
365     case OPUS_BANDWIDTH_SUPERWIDEBAND:
366          bandwidth_string = "superwideband";
367          break;
368     case OPUS_BANDWIDTH_FULLBAND:
369          bandwidth_string = "fullband";
370          break;
371     case OPUS_AUTO:
372          bandwidth_string = "auto";
373          break;
374     default:
375          bandwidth_string = "unknown";
376          break;
377     }
378
379     if (decode_only)
380        fprintf(stderr, "Decoding with %ld Hz output (%d channels)\n",
381                        (long)sampling_rate, channels);
382     else
383        fprintf(stderr, "Encoding %ld Hz input at %.3f kb/s "
384                        "in %s mode with %d-sample frames.\n",
385                        (long)sampling_rate, bitrate_bps*0.001,
386                        bandwidth_string, frame_size);
387
388     in = (short*)malloc(frame_size*channels*sizeof(short));
389     out = (short*)malloc(max_frame_size*channels*sizeof(short));
390     data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
391     if ( use_inbandfec ) {
392         data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
393     }
394     while (!stop)
395     {
396         if (decode_only)
397         {
398             unsigned char ch[4];
399             err = fread(ch, 1, 4, fin);
400             if (feof(fin))
401                 break;
402             len[toggle] = char_to_int(ch);
403             if (len[toggle]>max_payload_bytes || len[toggle]<0)
404             {
405                 fprintf(stderr, "Invalid payload length: %d\n",len[toggle]);
406                 break;
407             }
408             err = fread(ch, 1, 4, fin);
409             enc_final_range[toggle] = char_to_int(ch);
410             err = fread(data[toggle], 1, len[toggle], fin);
411             if (err<len[toggle])
412             {
413                 fprintf(stderr, "Ran out of input, "
414                                 "expecting %d bytes got %d\n",
415                                 len[toggle],err);
416                 break;
417             }
418         } else {
419             err = fread(in, sizeof(short)*channels, frame_size, fin);
420             curr_read = err;
421             if (curr_read < frame_size)
422             {
423                 int i;
424                 for (i=curr_read*channels;i<frame_size*channels;i++)
425                    in[i] = 0;
426                 stop = 1;
427             }
428
429             len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
430             if (sweep_bps!=0)
431             {
432                bitrate_bps += sweep_bps;
433                /* safety */
434                if (bitrate_bps<1000)
435                   bitrate_bps = 1000;
436                opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
437             }
438             opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range[toggle]));
439             if (len[toggle] < 0)
440             {
441                 fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
442                 fclose(fin);
443                 fclose(fout);
444                 return EXIT_FAILURE;
445             }
446         }
447
448         if (encode_only)
449         {
450             unsigned char int_field[4];
451             int_to_char(len[toggle], int_field);
452             fwrite(int_field, 1, 4, fout);
453             int_to_char(enc_final_range[toggle], int_field);
454             fwrite(int_field, 1, 4, fout);
455             fwrite(data[toggle], 1, len[toggle], fout);
456         } else {
457             int output_samples;
458             lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
459             if( count >= use_inbandfec ) {
460                 /* delay by one packet when using in-band FEC */
461                 if( use_inbandfec  ) {
462                     if( lost_prev ) {
463                         /* attempt to decode with in-band FEC from next packet */
464                         output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1);
465                     } else {
466                         /* regular decode */
467                         output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0);
468                     }
469                 } else {
470                     output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0);
471                 }
472                 if (output_samples>0)
473                 {
474                     fwrite(out+skip*channels, sizeof(short)*channels, output_samples-skip, fout);
475                     skip = 0;
476                 } else {
477                    fprintf(stderr, "error decoding frame: %s\n",
478                                    opus_strerror(output_samples));
479                 }
480             }
481         }
482
483         if (!encode_only)
484            opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
485         /* compare final range encoder rng values of encoder and decoder */
486         if( enc_final_range[toggle^use_inbandfec]!=0  && !encode_only
487          && !lost && !lost_prev
488          && dec_final_range != enc_final_range[toggle^use_inbandfec] ) {
489             fprintf (stderr, "Error: Range coder state mismatch "
490                              "between encoder and decoder "
491                              "in frame %ld: 0x%8lx vs 0x%8lx\n",
492                          (long)count,
493                          (unsigned long)enc_final_range[toggle^use_inbandfec],
494                          (unsigned long)dec_final_range);
495             fclose(fin);
496             fclose(fout);
497             return EXIT_FAILURE;
498         }
499
500         lost_prev = lost;
501
502         /* count bits */
503         bits += len[toggle]*8;
504         bits_max = ( len[toggle]*8 > bits_max ) ? len[toggle]*8 : bits_max;
505         if( count >= use_inbandfec ) {
506             nrg = 0.0;
507             if (!decode_only)
508             {
509                 for ( k = 0; k < frame_size * channels; k++ ) {
510                     nrg += in[ k ] * (double)in[ k ];
511                 }
512             }
513             if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
514                 bits_act += len[toggle]*8;
515                 count_act++;
516             }
517             /* Variance */
518             bits2 += len[toggle]*len[toggle]*64;
519         }
520         count++;
521         toggle = (toggle + use_inbandfec) & 1;
522     }
523     fprintf (stderr, "average bitrate:             %7.3f kb/s\n",
524                      1e-3*bits*sampling_rate/(frame_size*(double)count));
525     fprintf (stderr, "maximum bitrate:             %7.3f bkp/s\n",
526                      1e-3*bits_max*sampling_rate/frame_size);
527     if (!decode_only)
528        fprintf (stderr, "active bitrate:              %7.3f kb/s\n",
529                1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
530     fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n",
531             1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
532     /* Close any files to which intermediate results were stored */
533     SILK_DEBUG_STORE_CLOSE_FILES
534     silk_TimerSave("opus_timing.txt");
535     opus_encoder_destroy(enc);
536     opus_decoder_destroy(dec);
537     free(data[0]);
538     if (use_inbandfec)
539         free(data[1]);
540     fclose(fin);
541     fclose(fout);
542     free(in);
543     free(out);
544     return EXIT_SUCCESS;
545 }