Fix test_opus args count
[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    - Neither the name of the Xiph.org Foundation nor the names of its
17    contributors may be used to endorse or promote products derived from
18    this software without specific prior written permission.
19
20    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
24    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <math.h>
40 #include <string.h>
41 #include "opus.h"
42 #include "SKP_debug.h"
43
44
45 #define MAX_PACKET 1024
46
47 void print_usage( char* argv[] ) 
48 {
49     fprintf(stderr, "Usage: %s <mode (0/1/2)> <sampling rate (Hz)> <channels> "
50         "<bits per second>  [options] <input> <output>\n\n", argv[0]);
51     fprintf(stderr, "mode: 0 for SILK, 1 for hybrid, 2 for CELT:\n" );
52     fprintf(stderr, "options:\n" );
53     fprintf(stderr, "-cbr                 : enable constant bitrate; default: VBR\n" );
54     fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB>  : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
55     fprintf(stderr, "-framesize <2.5|5|10|20|40|60>  : frame size in ms; default: 20 \n" );
56     fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
57     fprintf(stderr, "-complexity <comp>   : complexity, 0 (lowest) ... 10 (highest); default: 10\n" );
58     fprintf(stderr, "-inbandfec           : enable SILK inband FEC\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
70 int main(int argc, char *argv[])
71 {
72    int err;
73    char *inFile, *outFile;
74    FILE *fin, *fout;
75    OpusEncoder *enc;
76    OpusDecoder *dec;
77    int args;
78    int len;
79    int frame_size, channels;
80    int bitrate_bps;
81    unsigned char *data;
82    int sampling_rate;
83    int use_vbr;
84    int internal_sampling_rate_Hz;
85    int max_payload_bytes;
86    int complexity;
87    int use_inbandfec;
88    int use_dtx;
89    int packet_loss_perc;
90    int count=0, count_act=0, k;
91    int skip;
92    int stop=0;
93    int tot_read=0, tot_written=0;
94    short *in, *out;
95    int mode;
96    double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
97    int bandwidth=-1;
98    const char *bandwidth_string;
99
100    if (argc < 7 )
101    {
102       print_usage( argv );
103       return 1;
104    }
105
106    mode = atoi(argv[1]) + MODE_SILK_ONLY;
107    sampling_rate = atoi(argv[2]);
108    channels = atoi(argv[3]);
109    bitrate_bps = atoi(argv[4]);
110
111    frame_size = sampling_rate/50;
112
113    /* defaults: */
114    use_vbr = 1;
115    bandwidth=-1;
116    internal_sampling_rate_Hz = sampling_rate;
117    max_payload_bytes = MAX_PACKET;
118    complexity = 10;
119    use_inbandfec = 0;
120    use_dtx = 0;
121    packet_loss_perc = 0;
122
123    switch(sampling_rate)
124    {
125    case 8000:
126            bandwidth = BANDWIDTH_NARROWBAND;
127            break;
128    case 12000:
129            bandwidth = BANDWIDTH_MEDIUMBAND;
130            break;
131    case 16000:
132            bandwidth = BANDWIDTH_WIDEBAND;
133            break;
134    case 24000:
135            bandwidth = BANDWIDTH_SUPERWIDEBAND;
136            break;
137    case 48000:
138            bandwidth = BANDWIDTH_FULLBAND;
139            break;
140    }
141    args = 5;
142    while( args < argc - 2 ) {
143        /* process command line options */
144         if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cbr" ) == 0 ) {
145             use_vbr = 0;
146             args++;
147         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-bandwidth" ) == 0 ) {
148             if (strcmp(argv[ args + 1 ], "NB")==0)
149                 bandwidth = BANDWIDTH_NARROWBAND;
150             else if (strcmp(argv[ args + 1 ], "MB")==0)
151                 bandwidth = BANDWIDTH_MEDIUMBAND;
152             else if (strcmp(argv[ args + 1 ], "WB")==0)
153                 bandwidth = BANDWIDTH_WIDEBAND;
154             else if (strcmp(argv[ args + 1 ], "SWB")==0)
155                 bandwidth = BANDWIDTH_SUPERWIDEBAND;
156             else if (strcmp(argv[ args + 1 ], "FB")==0)
157                 bandwidth = BANDWIDTH_FULLBAND;
158             else {
159                 fprintf(stderr, "Unknown bandwidth %s. Supported are NB, MB, WB, SWB, FB.\n", argv[ args + 1 ]);
160                 return 1;
161             }
162             args += 2;
163         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-framesize" ) == 0 ) {
164             if (strcmp(argv[ args + 1 ], "2.5")==0)
165                 frame_size = sampling_rate/400;
166             else if (strcmp(argv[ args + 1 ], "5")==0)
167                 frame_size = sampling_rate/400;
168             else if (strcmp(argv[ args + 1 ], "10")==0)
169                 frame_size = sampling_rate/100;
170             else if (strcmp(argv[ args + 1 ], "20")==0)
171                 frame_size = sampling_rate/50;
172             else if (strcmp(argv[ args + 1 ], "40")==0)
173                 frame_size = sampling_rate/25;
174             else if (strcmp(argv[ args + 1 ], "60")==0)
175                 frame_size = 3*sampling_rate/50;
176             else {
177                 fprintf(stderr, "Unsupported frame size: %s ms. Supported are 2.5, 5, 10, 20, 40, 60.\n", argv[ args + 1 ]);
178                 return 1;
179             }
180             args += 2;
181         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-max_payload" ) == 0 ) {
182             max_payload_bytes = atoi( argv[ args + 1 ] );
183             args += 2;
184         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-complexity" ) == 0 ) {
185             complexity = atoi( argv[ args + 1 ] );
186             args += 2;
187         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandfec" ) == 0 ) {
188             use_inbandfec = 1;
189             args++;
190         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-dtx") == 0 ) {
191             use_dtx = 1;
192             args++;
193         } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
194             packet_loss_perc = atoi( argv[ args + 1 ] );
195             args += 2;
196         } else {
197             printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
198             print_usage( argv );
199             return 1;
200         }
201    }
202
203    if( mode < MODE_SILK_ONLY || mode > MODE_CELT_ONLY ) {
204       fprintf (stderr, "mode must be: 0, 1 or 2\n");
205       return 1;
206    }
207
208    if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
209    {
210       fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
211                         MAX_PACKET);
212       return 1;
213    }
214    if (bitrate_bps < 0 || bitrate_bps*frame_size/sampling_rate > max_payload_bytes*8)
215    {
216       fprintf (stderr, "bytes per packet must be between 0 and %d\n",
217                         max_payload_bytes);
218       return 1;
219    }
220
221    inFile = argv[argc-2];
222    fin = fopen(inFile, "rb");
223    if (!fin)
224    {
225       fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
226       return 1;
227    }
228    outFile = argv[argc-1];
229    fout = fopen(outFile, "wb+");
230    if (!fout)
231    {
232       fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
233       return 1;
234    }
235
236    if (mode==MODE_SILK_ONLY)
237    {
238        if (bandwidth == BANDWIDTH_SUPERWIDEBAND || bandwidth == BANDWIDTH_FULLBAND)
239        {
240            fprintf (stderr, "Predictive mode only supports up to wideband\n");
241            return 1;
242        }
243    }
244    if (mode==MODE_HYBRID)
245    {
246        if (bandwidth != BANDWIDTH_SUPERWIDEBAND && bandwidth != BANDWIDTH_FULLBAND)
247        {
248            fprintf (stderr, "Hybrid mode only supports superwideband and fullband\n");
249            return 1;
250        }
251    }
252    if (mode==MODE_CELT_ONLY)
253    {
254        if (bandwidth == BANDWIDTH_MEDIUMBAND)
255        {
256            fprintf (stderr, "Transform mode does not support mediumband\n");
257            return 1;
258        }
259    }
260
261    enc = opus_encoder_create(sampling_rate, channels);
262    dec = opus_decoder_create(sampling_rate, channels);
263
264    opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
265    opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
266
267    if (bandwidth == -1)
268    {
269        fprintf (stderr, "Please specify a bandwidth when the sampling rate does not match one exactly\n");
270        return 1;
271    }
272    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
273
274    opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
275    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
276    opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
277    opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx));
278
279    skip = 5*sampling_rate/1000;
280    /* When SILK resamples, add 18 samples delay */
281    if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
282            skip += 18;
283
284    switch(bandwidth)
285    {
286    case BANDWIDTH_NARROWBAND:
287            bandwidth_string = "narrowband";
288            break;
289    case BANDWIDTH_MEDIUMBAND:
290            bandwidth_string = "mediumband";
291            break;
292    case BANDWIDTH_WIDEBAND:
293            bandwidth_string = "wideband";
294            break;
295    case BANDWIDTH_SUPERWIDEBAND:
296            bandwidth_string = "superwideband";
297            break;
298    case BANDWIDTH_FULLBAND:
299            bandwidth_string = "fullband";
300            break;
301    default:
302            bandwidth_string = "unknown";
303    }
304
305    printf("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);
306
307    in = (short*)malloc(frame_size*channels*sizeof(short));
308    out = (short*)malloc(frame_size*channels*sizeof(short));
309    data = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
310    while (!stop)
311    {
312       int write_samples;
313       int lost;
314       err = fread(in, sizeof(short), frame_size*channels, fin);
315       tot_read += err;
316       if (err < frame_size*channels)
317       {
318           int i;
319           for (i=err;i<frame_size*channels;i++)
320               in[i] = 0;
321       }
322       len = opus_encode(enc, in, frame_size, data, max_payload_bytes);
323       if (len <= 0)
324       {
325          fprintf (stderr, "opus_encode() returned %d\n", len);
326          return 1;
327       }
328
329       lost = rand()%100<packet_loss_perc;
330       opus_decode(dec, lost ? NULL : data, len, out, frame_size);
331       count++;
332       tot_written += (frame_size-skip)*channels;
333       write_samples = frame_size;
334       if (tot_written > tot_read && skip==0)
335       {
336           write_samples -= (tot_written-tot_read)/channels;
337           stop = 1;
338       }
339       fwrite(out+skip, sizeof(short), (write_samples-skip)*channels, fout);
340       skip = 0;
341
342 #if OPUS_TEST_RANGE_CODER_STATE
343       /* compare final range encoder rng values of encoder and decoder */
344       if( !lost && opus_decoder_get_final_range( dec ) != opus_encoder_get_final_range( enc ) ) {
345           fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder.\n");
346           return 0;
347       }
348 #endif
349
350       /* count bits */
351       bits += len*8;
352       nrg = 0.0;
353       for ( k = 0; k < frame_size * channels; k++ ) {
354           nrg += out[ k ] * (double)out[ k ];
355       }
356       if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
357           bits_act += len*8;
358           count_act++;
359       }
360           /* Variance */
361           bits2 += len*len*64;
362    }
363    fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
364    fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
365    fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
366    DEBUG_STORE_CLOSE_FILES              /* Close any files to which intermediate results were stored */
367    opus_encoder_destroy(enc);
368    opus_decoder_destroy(dec);
369    fclose(fin);
370    fclose(fout);
371    free(in);
372    free(out);
373    return 0;
374 }