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