Corrects many places where int was used where opus_int32 was needed.
[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     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 forcemono;
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
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 = (opus_int32)atol(argv[2]);
142     channels = atoi(argv[3]);
143     bitrate_bps = (opus_int32)atol(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 {
228             printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
229             print_usage( argv );
230             return 1;
231         }
232     }
233
234     if( application < OPUS_APPLICATION_VOIP || application > OPUS_APPLICATION_AUDIO) {
235         fprintf (stderr, "mode must be: 0 or 1\n");
236         return 1;
237     }
238
239     if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
240     {
241         fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
242                           MAX_PACKET);
243         return 1;
244     }
245
246     inFile = argv[argc-2];
247     fin = fopen(inFile, "rb");
248     if (!fin)
249     {
250         fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
251         return 1;
252     }
253     outFile = argv[argc-1];
254     fout = fopen(outFile, "wb+");
255     if (!fout)
256     {
257         fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
258         return 1;
259     }
260
261     enc = opus_encoder_create(sampling_rate, channels, application, &err);
262     if (err != OPUS_OK)
263     {
264        fprintf(stderr, "Cannot create encoder: %s\n", opus_strerror(err));
265        return 1;
266     }
267     dec = opus_decoder_create(sampling_rate, channels, &err);
268     if (err != OPUS_OK)
269     {
270        fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
271        return 1;
272     }
273
274     if (enc==NULL)
275     {
276         fprintf(stderr, "Failed to create an encoder\n");
277         exit(1);
278     }
279     if (dec==NULL)
280     {
281         fprintf(stderr, "Failed to create a decoder\n");
282         exit(1);
283     }
284
285     opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
286     opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
287     opus_encoder_ctl(enc, OPUS_SET_VBR(use_vbr));
288     opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
289     opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
290     opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(use_inbandfec));
291     opus_encoder_ctl(enc, OPUS_SET_FORCE_MONO(forcemono));
292     opus_encoder_ctl(enc, OPUS_SET_DTX(use_dtx));
293     opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
294
295     skip = 5*sampling_rate/1000;
296     /* When SILK resamples, add 18 samples delay */
297     /*if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
298         skip += 18;*/
299
300     switch(bandwidth)
301     {
302     case OPUS_BANDWIDTH_NARROWBAND:
303          bandwidth_string = "narrowband";
304          break;
305     case OPUS_BANDWIDTH_MEDIUMBAND:
306          bandwidth_string = "mediumband";
307          break;
308     case OPUS_BANDWIDTH_WIDEBAND:
309          bandwidth_string = "wideband";
310          break;
311     case OPUS_BANDWIDTH_SUPERWIDEBAND:
312          bandwidth_string = "superwideband";
313          break;
314     case OPUS_BANDWIDTH_FULLBAND:
315          bandwidth_string = "fullband";
316          break;
317     case OPUS_BANDWIDTH_AUTO:
318          bandwidth_string = "auto";
319          break;
320     default:
321          bandwidth_string = "unknown";
322          break;
323     }
324
325     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);
326
327     in = (short*)malloc(frame_size*channels*sizeof(short));
328     out = (short*)malloc(max_frame_size*channels*sizeof(short));
329     data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
330     if ( use_inbandfec ) {
331         data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
332     }
333     while (!stop)
334     {
335         if (decode_only)
336         {
337             unsigned char ch[4];
338             err = fread(ch, 1, 4, fin);
339             if (feof(fin))
340                 break;
341             len[toggle] = char_to_int(ch);
342             if (len[toggle]>max_payload_bytes || len[toggle]<0)
343             {
344                 fprintf(stderr, "Invalid payload length: %d\n",len[toggle]);
345                 break;
346             }
347             err = fread(ch, 1, 4, fin);
348             enc_final_range[toggle] = char_to_int(ch);
349             err = fread(data[toggle], 1, len[toggle], fin);
350             if (err<len[toggle])
351             {
352                 fprintf(stderr, "Ran out of input, expecting %d bytes got %d\n",len[toggle],err);
353                 break;
354             }
355         } else {
356             err = fread(in, sizeof(short)*channels, frame_size, fin);
357             curr_read = err;
358             if (curr_read < frame_size)
359             {
360                 int i;
361                 for (i=curr_read*channels;i<frame_size*channels;i++)
362                    in[i] = 0;
363                 stop = 1;
364             }
365
366             len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
367             opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range[toggle]));
368             if (len[toggle] < 0)
369             {
370                 fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
371                 return 1;
372             }
373         }
374
375         if (encode_only)
376         {
377             unsigned char int_field[4];
378             int_to_char(len[toggle], int_field);
379             fwrite(int_field, 1, 4, fout);
380             int_to_char(enc_final_range[toggle], int_field);
381             fwrite(int_field, 1, 4, fout);
382             fwrite(data[toggle], 1, len[toggle], fout);
383         } else {
384             int output_samples;
385             lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
386             if( count >= use_inbandfec ) {
387                 /* delay by one packet when using in-band FEC */
388                 if( use_inbandfec  ) {
389                     if( lost_prev ) {
390                         /* attempt to decode with in-band FEC from next packet */
391                         output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1);
392                     } else {
393                         /* regular decode */
394                         output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0);
395                     }
396                 } else {
397                     output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0);
398                 }
399                 if (output_samples>0)
400                 {
401                     fwrite(out+skip, sizeof(short)*channels, output_samples-skip, fout);
402                     skip = 0;
403                 } else {
404                    fprintf(stderr, "error decoding frame: %s\n", opus_strerror(output_samples));
405                 }
406             }
407         }
408
409         opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
410         /* compare final range encoder rng values of encoder and decoder */
411         if( enc_final_range[toggle^use_inbandfec]!=0  && !encode_only && !lost && !lost_prev &&
412                         dec_final_range != enc_final_range[toggle^use_inbandfec] ) {
413             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);
414             return 0;
415         }
416
417         lost_prev = lost;
418
419         /* count bits */
420         bits += len[toggle]*8;
421         if( count >= use_inbandfec ) {
422             nrg = 0.0;
423             if (!decode_only)
424             {
425                 for ( k = 0; k < frame_size * channels; k++ ) {
426                     nrg += in[ k ] * (double)in[ k ];
427                 }
428             }
429             if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
430                 bits_act += len[toggle]*8;
431                 count_act++;
432             }
433             /* Variance */
434             bits2 += len[toggle]*len[toggle]*64;
435         }
436         count++;
437         toggle = (toggle + use_inbandfec) & 1;
438     }
439     fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
440     fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
441     fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
442     /* Close any files to which intermediate results were stored */
443     SILK_DEBUG_STORE_CLOSE_FILES
444     silk_TimerSave("opus_timing.txt");
445     opus_encoder_destroy(enc);
446     opus_decoder_destroy(dec);
447     free(data[0]);
448     if (use_inbandfec)
449         free(data[1]);
450     fclose(fin);
451     fclose(fout);
452     free(in);
453     free(out);
454     return 0;
455 }