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