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