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