test_opus error messages
[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
40
41 #define MAX_PACKET 1500
42
43 void print_usage( char* argv[] ) 
44 {
45     fprintf(stderr, "Usage: %s <mode (0/1/2)> <sampling rate (Hz)> <channels> "
46         "<bits per second>  [options] <input> <output>\n\n", argv[0]);
47     fprintf(stderr, "mode: 0 for auto, 1 for voice, 2 for audio:\n" );
48     fprintf(stderr, "options:\n" );
49     fprintf(stderr, "-cbr                 : enable constant bitrate; default: VBR\n" );
50     fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB>  : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
51     fprintf(stderr, "-framesize <2.5|5|10|20|40|60>  : frame size in ms; default: 20 \n" );
52     fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
53     fprintf(stderr, "-complexity <comp>   : complexity, 0 (lowest) ... 10 (highest); default: 10\n" );
54     fprintf(stderr, "-inbandfec           : enable SILK inband FEC\n" );
55     fprintf(stderr, "-forcemono           : force mono encoding, even for stereo input\n" );
56     fprintf(stderr, "-dtx                 : enable SILK DTX\n" );
57     fprintf(stderr, "-loss <perc>         : simulate packet loss, in percent (0-100); default: 0\n" );
58 }
59
60 #ifdef _WIN32
61 #       define STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y)
62 #else
63 #       define STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
64 #endif 
65
66
67 int main(int argc, char *argv[])
68 {
69    int err;
70    char *inFile, *outFile;
71    FILE *fin, *fout;
72    OpusEncoder *enc;
73    OpusDecoder *dec;
74    int args;
75    int len[2];
76    int frame_size, channels;
77    int bitrate_bps;
78    unsigned char *data[2];
79    int sampling_rate;
80    int use_vbr;
81    int internal_sampling_rate_Hz;
82    int max_payload_bytes;
83    int complexity;
84    int use_inbandfec;
85    int use_dtx;
86    int forcemono;
87    int cvbr = 0;
88    int packet_loss_perc;
89    int count=0, count_act=0, k;
90    int skip;
91    int stop=0;
92    int tot_read=0, tot_written=0;
93    short *in, *out;
94    int mode;
95    double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
96    int bandwidth=-1;
97    const char *bandwidth_string;
98    int write_samples;
99    int lost, lost_prev = 1;
100    int toggle = 0;
101    int enc_final_range[2];
102
103    if (argc < 7 )
104    {
105       print_usage( argv );
106       return 1;
107    }
108
109    mode = atoi(argv[1]) + OPUS_MODE_AUTO;
110    sampling_rate = atoi(argv[2]);
111    channels = atoi(argv[3]);
112    bitrate_bps = atoi(argv[4]);
113
114    if (sampling_rate != 8000 && sampling_rate != 12000 && sampling_rate != 16000
115            && sampling_rate != 24000 && sampling_rate != 48000)
116    {
117        fprintf(stderr, "Supported sampling rates are 8000, 12000, 16000, "
118                "24000 and 48000.\n");
119        return 1;
120    }
121    frame_size = sampling_rate/50;
122
123    /* defaults: */
124    use_vbr = 1;
125    bandwidth=BANDWIDTH_AUTO;
126    internal_sampling_rate_Hz = sampling_rate;
127    max_payload_bytes = MAX_PACKET;
128    complexity = 10;
129    use_inbandfec = 0;
130    forcemono = 0;
131    use_dtx = 0;
132    packet_loss_perc = 0;
133
134    args = 5;
135    while( args < argc - 2 ) {
136        /* process command line options */
137         if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cbr" ) == 0 ) {
138             use_vbr = 0;
139             args++;
140         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-bandwidth" ) == 0 ) {
141             if (strcmp(argv[ args + 1 ], "NB")==0)
142                 bandwidth = BANDWIDTH_NARROWBAND;
143             else if (strcmp(argv[ args + 1 ], "MB")==0)
144                 bandwidth = BANDWIDTH_MEDIUMBAND;
145             else if (strcmp(argv[ args + 1 ], "WB")==0)
146                 bandwidth = BANDWIDTH_WIDEBAND;
147             else if (strcmp(argv[ args + 1 ], "SWB")==0)
148                 bandwidth = BANDWIDTH_SUPERWIDEBAND;
149             else if (strcmp(argv[ args + 1 ], "FB")==0)
150                 bandwidth = BANDWIDTH_FULLBAND;
151             else {
152                 fprintf(stderr, "Unknown bandwidth %s. Supported are NB, MB, WB, SWB, FB.\n", argv[ args + 1 ]);
153                 return 1;
154             }
155             args += 2;
156         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-framesize" ) == 0 ) {
157             if (strcmp(argv[ args + 1 ], "2.5")==0)
158                 frame_size = sampling_rate/400;
159             else if (strcmp(argv[ args + 1 ], "5")==0)
160                 frame_size = sampling_rate/200;
161             else if (strcmp(argv[ args + 1 ], "10")==0)
162                 frame_size = sampling_rate/100;
163             else if (strcmp(argv[ args + 1 ], "20")==0)
164                 frame_size = sampling_rate/50;
165             else if (strcmp(argv[ args + 1 ], "40")==0)
166                 frame_size = sampling_rate/25;
167             else if (strcmp(argv[ args + 1 ], "60")==0)
168                 frame_size = 3*sampling_rate/50;
169             else {
170                 fprintf(stderr, "Unsupported frame size: %s ms. Supported are 2.5, 5, 10, 20, 40, 60.\n", argv[ args + 1 ]);
171                 return 1;
172             }
173             args += 2;
174         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-max_payload" ) == 0 ) {
175             max_payload_bytes = atoi( argv[ args + 1 ] );
176             args += 2;
177         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-complexity" ) == 0 ) {
178             complexity = atoi( argv[ args + 1 ] );
179             args += 2;
180         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandfec" ) == 0 ) {
181             use_inbandfec = 1;
182             args++;
183         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-forcemono" ) == 0 ) {
184             forcemono = 1;
185             args++;
186         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cvbr" ) == 0 ) {
187             cvbr = 1;
188             args++;
189         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-dtx") == 0 ) {
190             use_dtx = 1;
191             args++;
192         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
193             packet_loss_perc = atoi( argv[ args + 1 ] );
194             args += 2;
195         } else {
196             printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
197             print_usage( argv );
198             return 1;
199         }
200    }
201
202    if( mode < OPUS_MODE_AUTO || mode > OPUS_MODE_AUDIO) {
203       fprintf (stderr, "mode must be: 0, 1 or 2\n");
204       return 1;
205    }
206
207    if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
208    {
209       fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
210                         MAX_PACKET);
211       return 1;
212    }
213    if (bitrate_bps < 0 || bitrate_bps*frame_size/sampling_rate > max_payload_bytes*8)
214    {
215       fprintf (stderr, "bytes per packet must be between 0 and %d\n",
216                         max_payload_bytes);
217       return 1;
218    }
219
220    inFile = argv[argc-2];
221    fin = fopen(inFile, "rb");
222    if (!fin)
223    {
224       fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
225       return 1;
226    }
227    outFile = argv[argc-1];
228    fout = fopen(outFile, "wb+");
229    if (!fout)
230    {
231       fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
232       return 1;
233    }
234
235    enc = opus_encoder_create(sampling_rate, channels);
236    dec = opus_decoder_create(sampling_rate, channels);
237
238    if (enc==NULL)
239    {
240       fprintf(stderr, "Failed to create an encoder\n");
241       exit(1);
242    }
243    if (dec==NULL)
244    {
245       fprintf(stderr, "Failed to create a decoder\n");
246       exit(1);
247    }
248
249    opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
250    opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
251    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
252    opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
253    opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
254    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
255    opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
256    opus_encoder_ctl(enc, OPUS_SET_FORCE_MONO(forcemono));
257    opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx));
258    opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
259
260    skip = 5*sampling_rate/1000;
261    /* When SILK resamples, add 18 samples delay */
262    /*if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
263            skip += 18;*/
264
265    switch(bandwidth)
266    {
267    case BANDWIDTH_NARROWBAND:
268            bandwidth_string = "narrowband";
269            break;
270    case BANDWIDTH_MEDIUMBAND:
271            bandwidth_string = "mediumband";
272            break;
273    case BANDWIDTH_WIDEBAND:
274            bandwidth_string = "wideband";
275            break;
276    case BANDWIDTH_SUPERWIDEBAND:
277            bandwidth_string = "superwideband";
278            break;
279    case BANDWIDTH_FULLBAND:
280            bandwidth_string = "fullband";
281            break;
282    case BANDWIDTH_AUTO:
283            bandwidth_string = "auto";
284            break;
285    default:
286            bandwidth_string = "unknown";
287    }
288
289    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);
290
291    in = (short*)malloc(frame_size*channels*sizeof(short));
292    out = (short*)malloc(frame_size*channels*sizeof(short));
293    data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
294    if( use_inbandfec ) {
295        data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
296    }
297    while (!stop)
298    {
299
300       err = fread(in, sizeof(short), frame_size*channels, fin);
301       tot_read += err;
302       if (err < frame_size*channels)
303       {
304           int i;
305           for (i=err;i<frame_size*channels;i++)
306               in[i] = 0;
307       }
308
309       len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
310 #if OPUS_TEST_RANGE_CODER_STATE
311       enc_final_range[toggle] = opus_encoder_get_final_range( enc );
312 #endif
313       if (len[toggle] < 0)
314       {
315          fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
316          return 1;
317       }
318
319       lost = rand()%100 < packet_loss_perc || len[toggle]==0;
320       if( count >= use_inbandfec ) {
321           /* delay by one packet when using in-band FEC */
322           if( use_inbandfec  ) {
323               if( lost_prev ) {
324                   /* attempt to decode with in-band FEC from next packet */
325                   opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 1);
326               } else {
327                   /* regular decode */
328                   opus_decode(dec, data[1-toggle], len[1-toggle], out, frame_size, 0);
329               }
330           } else {
331               opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 0);
332           }
333           write_samples = frame_size-skip;
334           tot_written += write_samples*channels;
335           if (tot_written > tot_read)
336           {
337               write_samples -= (tot_written-tot_read)/channels;
338               stop = 1;
339           }
340           fwrite(out+skip, sizeof(short), write_samples*channels, fout);
341           skip = 0;
342       }
343
344 #if OPUS_TEST_RANGE_CODER_STATE
345       /* compare final range encoder rng values of encoder and decoder */
346       if( !lost && !lost_prev && opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) {
347           fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %d.\n", count);
348           return 0;
349       }
350 #endif
351
352       lost_prev = lost;
353
354       /* count bits */
355       bits += len[toggle]*8;
356       if( count >= use_inbandfec ) {
357           nrg = 0.0;
358           for ( k = 0; k < frame_size * channels; k++ ) {
359               nrg += in[ k ] * (double)in[ k ];
360           }
361           if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
362               bits_act += len[toggle]*8;
363               count_act++;
364           }
365               /* Variance */
366               bits2 += len[toggle]*len[toggle]*64;
367       }
368       count++;
369       toggle = (toggle + use_inbandfec) & 1;
370    }
371    fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
372    fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
373    fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
374    /* Close any files to which intermediate results were stored */
375    SILK_DEBUG_STORE_CLOSE_FILES
376    silk_TimerSave("opus_timing.txt");
377    opus_encoder_destroy(enc);
378    opus_decoder_destroy(dec);
379    free(data[0]);
380    if (use_inbandfec)
381            free(data[1]);
382    fclose(fin);
383    fclose(fout);
384    free(in);
385    free(out);
386    return 0;
387 }