Squashed commit of the following:
[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    opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
239    opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
240    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
241    opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
242    opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
243    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
244    opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
245    opus_encoder_ctl(enc, OPUS_SET_FORCE_MONO(forcemono));
246    opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx));
247    opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
248
249    skip = 5*sampling_rate/1000;
250    /* When SILK resamples, add 18 samples delay */
251    /*if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
252            skip += 18;*/
253
254    switch(bandwidth)
255    {
256    case BANDWIDTH_NARROWBAND:
257            bandwidth_string = "narrowband";
258            break;
259    case BANDWIDTH_MEDIUMBAND:
260            bandwidth_string = "mediumband";
261            break;
262    case BANDWIDTH_WIDEBAND:
263            bandwidth_string = "wideband";
264            break;
265    case BANDWIDTH_SUPERWIDEBAND:
266            bandwidth_string = "superwideband";
267            break;
268    case BANDWIDTH_FULLBAND:
269            bandwidth_string = "fullband";
270            break;
271    case BANDWIDTH_AUTO:
272            bandwidth_string = "auto";
273            break;
274    default:
275            bandwidth_string = "unknown";
276    }
277
278    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);
279
280    in = (short*)malloc(frame_size*channels*sizeof(short));
281    out = (short*)malloc(frame_size*channels*sizeof(short));
282    data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
283    if( use_inbandfec ) {
284        data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
285    }
286    while (!stop)
287    {
288
289       err = fread(in, sizeof(short), frame_size*channels, fin);
290       tot_read += err;
291       if (err < frame_size*channels)
292       {
293           int i;
294           for (i=err;i<frame_size*channels;i++)
295               in[i] = 0;
296       }
297
298       len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
299 #if OPUS_TEST_RANGE_CODER_STATE
300       enc_final_range[toggle] = opus_encoder_get_final_range( enc );
301 #endif
302       if (len[toggle] < 0)
303       {
304          fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
305          return 1;
306       }
307
308       lost = rand()%100 < packet_loss_perc || len[toggle]==0;
309       if( count >= use_inbandfec ) {
310           /* delay by one packet when using in-band FEC */
311           if( use_inbandfec  ) {
312               if( lost_prev ) {
313                   /* attempt to decode with in-band FEC from next packet */
314                   opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 1);
315               } else {
316                   /* regular decode */
317                   opus_decode(dec, data[1-toggle], len[1-toggle], out, frame_size, 0);
318               }
319           } else {
320               opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 0);
321           }
322           write_samples = frame_size-skip;
323           tot_written += write_samples*channels;
324           if (tot_written > tot_read)
325           {
326               write_samples -= (tot_written-tot_read)/channels;
327               stop = 1;
328           }
329           fwrite(out+skip, sizeof(short), write_samples*channels, fout);
330           skip = 0;
331       }
332
333 #if OPUS_TEST_RANGE_CODER_STATE
334       /* compare final range encoder rng values of encoder and decoder */
335       if( !lost && !lost_prev && opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) {
336           fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %d.\n", count);
337           return 0;
338       }
339 #endif
340
341       lost_prev = lost;
342
343       /* count bits */
344       bits += len[toggle]*8;
345       if( count >= use_inbandfec ) {
346           nrg = 0.0;
347           for ( k = 0; k < frame_size * channels; k++ ) {
348               nrg += in[ k ] * (double)in[ k ];
349           }
350           if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
351               bits_act += len[toggle]*8;
352               count_act++;
353           }
354               /* Variance */
355               bits2 += len[toggle]*len[toggle]*64;
356       }
357       count++;
358       toggle = (toggle + use_inbandfec) & 1;
359    }
360    fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
361    fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
362    fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
363    /* Close any files to which intermediate results were stored */
364    SILK_DEBUG_STORE_CLOSE_FILES
365    silk_TimerSave("opus_timing.txt");
366    opus_encoder_destroy(enc);
367    opus_decoder_destroy(dec);
368    free(data[0]);
369    if (use_inbandfec)
370            free(data[1]);
371    fclose(fin);
372    fclose(fout);
373    free(in);
374    free(out);
375    return 0;
376 }