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