blob: f8cdf0310863ce474ad8383367ba1f84ed6d70f7 [file] [log] [blame]
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +00001/* 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 COPYRIGHT OWNER
20 OR 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 "debug.h"
39#include "opus_types.h"
40#include "opus_private.h"
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +000041#include "opus_multistream.h"
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +000042
43#define MAX_PACKET 1500
44
45void print_usage( char* argv[] )
46{
47 fprintf(stderr, "Usage: %s [-e] <application> <sampling rate (Hz)> <channels (1/2)> "
48 "<bits per second> [options] <input> <output>\n", argv[0]);
49 fprintf(stderr, " %s -d <sampling rate (Hz)> <channels (1/2)> "
50 "[options] <input> <output>\n\n", argv[0]);
51 fprintf(stderr, "mode: voip | audio | restricted-lowdelay\n" );
52 fprintf(stderr, "options:\n" );
53 fprintf(stderr, "-e : only runs the encoder (output the bit-stream)\n" );
54 fprintf(stderr, "-d : only runs the decoder (reads the bit-stream as input)\n" );
55 fprintf(stderr, "-cbr : enable constant bitrate; default: variable bitrate\n" );
56 fprintf(stderr, "-cvbr : enable constrained variable bitrate; default: unconstrained\n" );
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +000057 fprintf(stderr, "-variable-duration : enable frames of variable duration (experts only); default: disabled\n" );
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +000058 fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
59 fprintf(stderr, "-framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20 \n" );
60 fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
61 fprintf(stderr, "-complexity <comp> : complexity, 0 (lowest) ... 10 (highest); default: 10\n" );
62 fprintf(stderr, "-inbandfec : enable SILK inband FEC\n" );
63 fprintf(stderr, "-forcemono : force mono encoding, even for stereo input\n" );
64 fprintf(stderr, "-dtx : enable SILK DTX\n" );
65 fprintf(stderr, "-loss <perc> : simulate packet loss, in percent (0-100); default: 0\n" );
66}
67
68static void int_to_char(opus_uint32 i, unsigned char ch[4])
69{
70 ch[0] = i>>24;
71 ch[1] = (i>>16)&0xFF;
72 ch[2] = (i>>8)&0xFF;
73 ch[3] = i&0xFF;
74}
75
76static opus_uint32 char_to_int(unsigned char ch[4])
77{
78 return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16)
79 | ((opus_uint32)ch[2]<< 8) | (opus_uint32)ch[3];
80}
81
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +000082static void check_encoder_option(int decode_only, const char *opt)
83{
84 if (decode_only)
85 {
86 fprintf(stderr, "option %s is only for encoding\n", opt);
87 exit(EXIT_FAILURE);
88 }
89}
90
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +000091static const int silk8_test[][4] = {
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +000092 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*3, 1},
93 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*2, 1},
94 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960, 1},
95 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480, 1},
96 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*3, 2},
97 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*2, 2},
98 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960, 2},
99 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480, 2}
100};
101
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000102static const int silk12_test[][4] = {
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000103 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*3, 1},
104 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*2, 1},
105 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960, 1},
106 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 480, 1},
107 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*3, 2},
108 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*2, 2},
109 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960, 2},
110 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 480, 2}
111};
112
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000113static const int silk16_test[][4] = {
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000114 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*3, 1},
115 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*2, 1},
116 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 1},
117 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480, 1},
118 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*3, 2},
119 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*2, 2},
120 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 2},
121 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480, 2}
122};
123
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000124static const int hybrid24_test[][4] = {
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000125 {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 1},
126 {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 1},
127 {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 2},
128 {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 2}
129};
130
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000131static const int hybrid48_test[][4] = {
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000132 {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 1},
133 {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 1},
134 {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 2},
135 {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 2}
136};
137
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000138static const int celt_test[][4] = {
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000139 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 1},
140 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 1},
141 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 1},
142 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960, 1},
143
144 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 1},
145 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 1},
146 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480, 1},
147 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480, 1},
148
149 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 240, 1},
150 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 240, 1},
151 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 240, 1},
152 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 240, 1},
153
154 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 120, 1},
155 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 120, 1},
156 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 120, 1},
157 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 120, 1},
158
159 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 2},
160 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 2},
161 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 2},
162 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960, 2},
163
164 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 2},
165 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 2},
166 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480, 2},
167 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480, 2},
168
169 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 240, 2},
170 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 240, 2},
171 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 240, 2},
172 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 240, 2},
173
174 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 120, 2},
175 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 120, 2},
176 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 120, 2},
177 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 120, 2},
178
179};
180
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000181static const int celt_hq_test[][4] = {
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000182 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 2},
183 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 2},
184 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 240, 2},
185 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 120, 2},
186};
187
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000188#if 0 /* This is a hack that replaces the normal encoder/decoder with the multistream version */
189#define OpusEncoder OpusMSEncoder
190#define OpusDecoder OpusMSDecoder
191#define opus_encode opus_multistream_encode
192#define opus_decode opus_multistream_decode
193#define opus_encoder_ctl opus_multistream_encoder_ctl
194#define opus_decoder_ctl opus_multistream_decoder_ctl
195#define opus_encoder_create ms_opus_encoder_create
196#define opus_decoder_create ms_opus_decoder_create
197#define opus_encoder_destroy opus_multistream_encoder_destroy
198#define opus_decoder_destroy opus_multistream_decoder_destroy
199
200static OpusEncoder *ms_opus_encoder_create(opus_int32 Fs, int channels, int application, int *error)
201{
202 int streams, coupled_streams;
203 unsigned char mapping[256];
204 return (OpusEncoder *)opus_multistream_surround_encoder_create(Fs, channels, 1, &streams, &coupled_streams, mapping, application, error);
205}
206static OpusDecoder *ms_opus_decoder_create(opus_int32 Fs, int channels, int *error)
207{
208 int streams;
209 int coupled_streams;
210 unsigned char mapping[256]={0,1};
211 streams = 1;
212 coupled_streams = channels==2;
213 return (OpusDecoder *)opus_multistream_decoder_create(Fs, channels, streams, coupled_streams, mapping, error);
214}
215#endif
216
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000217int main(int argc, char *argv[])
218{
219 int err;
220 char *inFile, *outFile;
221 FILE *fin, *fout;
222 OpusEncoder *enc=NULL;
223 OpusDecoder *dec=NULL;
224 int args;
225 int len[2];
226 int frame_size, channels;
227 opus_int32 bitrate_bps=0;
228 unsigned char *data[2];
229 unsigned char *fbytes;
230 opus_int32 sampling_rate;
231 int use_vbr;
232 int max_payload_bytes;
233 int complexity;
234 int use_inbandfec;
235 int use_dtx;
236 int forcechannels;
237 int cvbr = 0;
238 int packet_loss_perc;
239 opus_int32 count=0, count_act=0;
240 int k;
241 opus_int32 skip=0;
242 int stop=0;
243 short *in, *out;
244 int application=OPUS_APPLICATION_AUDIO;
245 double bits=0.0, bits_max=0.0, bits_act=0.0, bits2=0.0, nrg;
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000246 double tot_samples=0;
247 opus_uint64 tot_in, tot_out;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000248 int bandwidth=-1;
249 const char *bandwidth_string;
250 int lost = 0, lost_prev = 1;
251 int toggle = 0;
252 opus_uint32 enc_final_range[2];
253 opus_uint32 dec_final_range;
254 int encode_only=0, decode_only=0;
255 int max_frame_size = 960*6;
256 int curr_read=0;
257 int sweep_bps = 0;
258 int random_framesize=0, newsize=0, delayed_celt=0;
259 int sweep_max=0, sweep_min=0;
260 int random_fec=0;
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000261 const int (*mode_list)[4]=NULL;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000262 int nb_modes_in_list=0;
263 int curr_mode=0;
264 int curr_mode_count=0;
265 int mode_switch_time = 48000;
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000266 int nb_encoded=0;
267 int remaining=0;
268 int variable_duration=OPUS_FRAMESIZE_ARG;
269 int delayed_decision=0;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000270
271 if (argc < 5 )
272 {
273 print_usage( argv );
274 return EXIT_FAILURE;
275 }
276
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000277 tot_in=tot_out=0;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000278 fprintf(stderr, "%s\n", opus_get_version_string());
279
280 args = 1;
281 if (strcmp(argv[args], "-e")==0)
282 {
283 encode_only = 1;
284 args++;
285 } else if (strcmp(argv[args], "-d")==0)
286 {
287 decode_only = 1;
288 args++;
289 }
290 if (!decode_only && argc < 7 )
291 {
292 print_usage( argv );
293 return EXIT_FAILURE;
294 }
295
296 if (!decode_only)
297 {
298 if (strcmp(argv[args], "voip")==0)
299 application = OPUS_APPLICATION_VOIP;
300 else if (strcmp(argv[args], "restricted-lowdelay")==0)
301 application = OPUS_APPLICATION_RESTRICTED_LOWDELAY;
302 else if (strcmp(argv[args], "audio")!=0) {
303 fprintf(stderr, "unknown application: %s\n", argv[args]);
304 print_usage(argv);
305 return EXIT_FAILURE;
306 }
307 args++;
308 }
309 sampling_rate = (opus_int32)atol(argv[args]);
310 args++;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000311
312 if (sampling_rate != 8000 && sampling_rate != 12000
313 && sampling_rate != 16000 && sampling_rate != 24000
314 && sampling_rate != 48000)
315 {
316 fprintf(stderr, "Supported sampling rates are 8000, 12000, "
317 "16000, 24000 and 48000.\n");
318 return EXIT_FAILURE;
319 }
320 frame_size = sampling_rate/50;
321
tlegrand@google.com3c3902f2013-12-09 08:35:25 +0000322 channels = atoi(argv[args]);
323 args++;
324
325 if (channels < 1 || channels > 2)
326 {
327 fprintf(stderr, "Opus_demo supports only 1 or 2 channels.\n");
328 return EXIT_FAILURE;
329 }
330
331 if (!decode_only)
332 {
333 bitrate_bps = (opus_int32)atol(argv[args]);
334 args++;
335 }
336
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000337 /* defaults: */
338 use_vbr = 1;
339 bandwidth = OPUS_AUTO;
340 max_payload_bytes = MAX_PACKET;
341 complexity = 10;
342 use_inbandfec = 0;
343 forcechannels = OPUS_AUTO;
344 use_dtx = 0;
345 packet_loss_perc = 0;
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000346 max_frame_size = 2*48000;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000347 curr_read=0;
348
349 while( args < argc - 2 ) {
350 /* process command line options */
351 if( strcmp( argv[ args ], "-cbr" ) == 0 ) {
352 check_encoder_option(decode_only, "-cbr");
353 use_vbr = 0;
354 args++;
355 } else if( strcmp( argv[ args ], "-bandwidth" ) == 0 ) {
356 check_encoder_option(decode_only, "-bandwidth");
357 if (strcmp(argv[ args + 1 ], "NB")==0)
358 bandwidth = OPUS_BANDWIDTH_NARROWBAND;
359 else if (strcmp(argv[ args + 1 ], "MB")==0)
360 bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
361 else if (strcmp(argv[ args + 1 ], "WB")==0)
362 bandwidth = OPUS_BANDWIDTH_WIDEBAND;
363 else if (strcmp(argv[ args + 1 ], "SWB")==0)
364 bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
365 else if (strcmp(argv[ args + 1 ], "FB")==0)
366 bandwidth = OPUS_BANDWIDTH_FULLBAND;
367 else {
368 fprintf(stderr, "Unknown bandwidth %s. "
369 "Supported are NB, MB, WB, SWB, FB.\n",
370 argv[ args + 1 ]);
371 return EXIT_FAILURE;
372 }
373 args += 2;
374 } else if( strcmp( argv[ args ], "-framesize" ) == 0 ) {
375 check_encoder_option(decode_only, "-framesize");
376 if (strcmp(argv[ args + 1 ], "2.5")==0)
377 frame_size = sampling_rate/400;
378 else if (strcmp(argv[ args + 1 ], "5")==0)
379 frame_size = sampling_rate/200;
380 else if (strcmp(argv[ args + 1 ], "10")==0)
381 frame_size = sampling_rate/100;
382 else if (strcmp(argv[ args + 1 ], "20")==0)
383 frame_size = sampling_rate/50;
384 else if (strcmp(argv[ args + 1 ], "40")==0)
385 frame_size = sampling_rate/25;
386 else if (strcmp(argv[ args + 1 ], "60")==0)
387 frame_size = 3*sampling_rate/50;
388 else {
389 fprintf(stderr, "Unsupported frame size: %s ms. "
390 "Supported are 2.5, 5, 10, 20, 40, 60.\n",
391 argv[ args + 1 ]);
392 return EXIT_FAILURE;
393 }
394 args += 2;
395 } else if( strcmp( argv[ args ], "-max_payload" ) == 0 ) {
396 check_encoder_option(decode_only, "-max_payload");
397 max_payload_bytes = atoi( argv[ args + 1 ] );
398 args += 2;
399 } else if( strcmp( argv[ args ], "-complexity" ) == 0 ) {
400 check_encoder_option(decode_only, "-complexity");
401 complexity = atoi( argv[ args + 1 ] );
402 args += 2;
403 } else if( strcmp( argv[ args ], "-inbandfec" ) == 0 ) {
404 use_inbandfec = 1;
405 args++;
406 } else if( strcmp( argv[ args ], "-forcemono" ) == 0 ) {
407 check_encoder_option(decode_only, "-forcemono");
408 forcechannels = 1;
409 args++;
410 } else if( strcmp( argv[ args ], "-cvbr" ) == 0 ) {
411 check_encoder_option(decode_only, "-cvbr");
412 cvbr = 1;
413 args++;
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000414 } else if( strcmp( argv[ args ], "-variable-duration" ) == 0 ) {
415 check_encoder_option(decode_only, "-variable-duration");
416 variable_duration = OPUS_FRAMESIZE_VARIABLE;
417 args++;
418 } else if( strcmp( argv[ args ], "-delayed-decision" ) == 0 ) {
419 check_encoder_option(decode_only, "-delayed-decision");
420 delayed_decision = 1;
421 args++;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000422 } else if( strcmp( argv[ args ], "-dtx") == 0 ) {
423 check_encoder_option(decode_only, "-dtx");
424 use_dtx = 1;
425 args++;
426 } else if( strcmp( argv[ args ], "-loss" ) == 0 ) {
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000427 packet_loss_perc = atoi( argv[ args + 1 ] );
428 args += 2;
429 } else if( strcmp( argv[ args ], "-sweep" ) == 0 ) {
430 check_encoder_option(decode_only, "-sweep");
431 sweep_bps = atoi( argv[ args + 1 ] );
432 args += 2;
433 } else if( strcmp( argv[ args ], "-random_framesize" ) == 0 ) {
434 check_encoder_option(decode_only, "-random_framesize");
435 random_framesize = 1;
436 args++;
437 } else if( strcmp( argv[ args ], "-sweep_max" ) == 0 ) {
438 check_encoder_option(decode_only, "-sweep_max");
439 sweep_max = atoi( argv[ args + 1 ] );
440 args += 2;
441 } else if( strcmp( argv[ args ], "-random_fec" ) == 0 ) {
442 check_encoder_option(decode_only, "-random_fec");
443 random_fec = 1;
444 args++;
445 } else if( strcmp( argv[ args ], "-silk8k_test" ) == 0 ) {
446 check_encoder_option(decode_only, "-silk8k_test");
447 mode_list = silk8_test;
448 nb_modes_in_list = 8;
449 args++;
450 } else if( strcmp( argv[ args ], "-silk12k_test" ) == 0 ) {
451 check_encoder_option(decode_only, "-silk12k_test");
452 mode_list = silk12_test;
453 nb_modes_in_list = 8;
454 args++;
455 } else if( strcmp( argv[ args ], "-silk16k_test" ) == 0 ) {
456 check_encoder_option(decode_only, "-silk16k_test");
457 mode_list = silk16_test;
458 nb_modes_in_list = 8;
459 args++;
460 } else if( strcmp( argv[ args ], "-hybrid24k_test" ) == 0 ) {
461 check_encoder_option(decode_only, "-hybrid24k_test");
462 mode_list = hybrid24_test;
463 nb_modes_in_list = 4;
464 args++;
465 } else if( strcmp( argv[ args ], "-hybrid48k_test" ) == 0 ) {
466 check_encoder_option(decode_only, "-hybrid48k_test");
467 mode_list = hybrid48_test;
468 nb_modes_in_list = 4;
469 args++;
470 } else if( strcmp( argv[ args ], "-celt_test" ) == 0 ) {
471 check_encoder_option(decode_only, "-celt_test");
472 mode_list = celt_test;
473 nb_modes_in_list = 32;
474 args++;
475 } else if( strcmp( argv[ args ], "-celt_hq_test" ) == 0 ) {
476 check_encoder_option(decode_only, "-celt_hq_test");
477 mode_list = celt_hq_test;
478 nb_modes_in_list = 4;
479 args++;
480 } else {
481 printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
482 print_usage( argv );
483 return EXIT_FAILURE;
484 }
485 }
486
487 if (sweep_max)
488 sweep_min = bitrate_bps;
489
490 if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
491 {
492 fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
493 MAX_PACKET);
494 return EXIT_FAILURE;
495 }
496
497 inFile = argv[argc-2];
498 fin = fopen(inFile, "rb");
499 if (!fin)
500 {
501 fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
502 return EXIT_FAILURE;
503 }
504 if (mode_list)
505 {
506 int size;
507 fseek(fin, 0, SEEK_END);
508 size = ftell(fin);
509 fprintf(stderr, "File size is %d bytes\n", size);
510 fseek(fin, 0, SEEK_SET);
511 mode_switch_time = size/sizeof(short)/channels/nb_modes_in_list;
512 fprintf(stderr, "Switching mode every %d samples\n", mode_switch_time);
513 }
514
515 outFile = argv[argc-1];
516 fout = fopen(outFile, "wb+");
517 if (!fout)
518 {
519 fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
520 fclose(fin);
521 return EXIT_FAILURE;
522 }
523
524 if (!decode_only)
525 {
526 enc = opus_encoder_create(sampling_rate, channels, application, &err);
527 if (err != OPUS_OK)
528 {
529 fprintf(stderr, "Cannot create encoder: %s\n", opus_strerror(err));
530 fclose(fin);
531 fclose(fout);
532 return EXIT_FAILURE;
533 }
534 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
535 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
536 opus_encoder_ctl(enc, OPUS_SET_VBR(use_vbr));
537 opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
538 opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
539 opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(use_inbandfec));
540 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(forcechannels));
541 opus_encoder_ctl(enc, OPUS_SET_DTX(use_dtx));
542 opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
543
544 opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
545 opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000546 opus_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(variable_duration));
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000547 }
548 if (!encode_only)
549 {
550 dec = opus_decoder_create(sampling_rate, channels, &err);
551 if (err != OPUS_OK)
552 {
553 fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
554 fclose(fin);
555 fclose(fout);
556 return EXIT_FAILURE;
557 }
558 }
559
560
561 switch(bandwidth)
562 {
563 case OPUS_BANDWIDTH_NARROWBAND:
564 bandwidth_string = "narrowband";
565 break;
566 case OPUS_BANDWIDTH_MEDIUMBAND:
567 bandwidth_string = "mediumband";
568 break;
569 case OPUS_BANDWIDTH_WIDEBAND:
570 bandwidth_string = "wideband";
571 break;
572 case OPUS_BANDWIDTH_SUPERWIDEBAND:
573 bandwidth_string = "superwideband";
574 break;
575 case OPUS_BANDWIDTH_FULLBAND:
576 bandwidth_string = "fullband";
577 break;
578 case OPUS_AUTO:
579 bandwidth_string = "auto";
580 break;
581 default:
582 bandwidth_string = "unknown";
583 break;
584 }
585
586 if (decode_only)
587 fprintf(stderr, "Decoding with %ld Hz output (%d channels)\n",
588 (long)sampling_rate, channels);
589 else
590 fprintf(stderr, "Encoding %ld Hz input at %.3f kb/s "
591 "in %s mode with %d-sample frames.\n",
592 (long)sampling_rate, bitrate_bps*0.001,
593 bandwidth_string, frame_size);
594
595 in = (short*)malloc(max_frame_size*channels*sizeof(short));
596 out = (short*)malloc(max_frame_size*channels*sizeof(short));
597 fbytes = (unsigned char*)malloc(max_frame_size*channels*sizeof(short));
598 data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
599 if ( use_inbandfec ) {
600 data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
601 }
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000602 if(delayed_decision)
603 {
604 if (variable_duration!=OPUS_FRAMESIZE_VARIABLE)
605 {
606 if (frame_size==sampling_rate/400)
607 variable_duration = OPUS_FRAMESIZE_2_5_MS;
608 else if (frame_size==sampling_rate/200)
609 variable_duration = OPUS_FRAMESIZE_5_MS;
610 else if (frame_size==sampling_rate/100)
611 variable_duration = OPUS_FRAMESIZE_10_MS;
612 else if (frame_size==sampling_rate/50)
613 variable_duration = OPUS_FRAMESIZE_20_MS;
614 else if (frame_size==sampling_rate/25)
615 variable_duration = OPUS_FRAMESIZE_40_MS;
616 else
617 variable_duration = OPUS_FRAMESIZE_60_MS;
618 opus_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(variable_duration));
619 }
620 frame_size = 2*48000;
621 }
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000622 while (!stop)
623 {
624 if (delayed_celt)
625 {
626 frame_size = newsize;
627 delayed_celt = 0;
628 } else if (random_framesize && rand()%20==0)
629 {
630 newsize = rand()%6;
631 switch(newsize)
632 {
633 case 0: newsize=sampling_rate/400; break;
634 case 1: newsize=sampling_rate/200; break;
635 case 2: newsize=sampling_rate/100; break;
636 case 3: newsize=sampling_rate/50; break;
637 case 4: newsize=sampling_rate/25; break;
638 case 5: newsize=3*sampling_rate/50; break;
639 }
640 while (newsize < sampling_rate/25 && bitrate_bps-fabs(sweep_bps) <= 3*12*sampling_rate/newsize)
641 newsize*=2;
642 if (newsize < sampling_rate/100 && frame_size >= sampling_rate/100)
643 {
644 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
645 delayed_celt=1;
646 } else {
647 frame_size = newsize;
648 }
649 }
650 if (random_fec && rand()%30==0)
651 {
652 opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(rand()%4==0));
653 }
654 if (decode_only)
655 {
656 unsigned char ch[4];
657 err = fread(ch, 1, 4, fin);
658 if (feof(fin))
659 break;
660 len[toggle] = char_to_int(ch);
661 if (len[toggle]>max_payload_bytes || len[toggle]<0)
662 {
663 fprintf(stderr, "Invalid payload length: %d\n",len[toggle]);
664 break;
665 }
666 err = fread(ch, 1, 4, fin);
667 enc_final_range[toggle] = char_to_int(ch);
668 err = fread(data[toggle], 1, len[toggle], fin);
669 if (err<len[toggle])
670 {
671 fprintf(stderr, "Ran out of input, "
672 "expecting %d bytes got %d\n",
673 len[toggle],err);
674 break;
675 }
676 } else {
677 int i;
678 if (mode_list!=NULL)
679 {
680 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(mode_list[curr_mode][1]));
681 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(mode_list[curr_mode][0]));
682 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(mode_list[curr_mode][3]));
683 frame_size = mode_list[curr_mode][2];
684 }
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000685 err = fread(fbytes, sizeof(short)*channels, frame_size-remaining, fin);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000686 curr_read = err;
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000687 tot_in += curr_read;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000688 for(i=0;i<curr_read*channels;i++)
689 {
690 opus_int32 s;
691 s=fbytes[2*i+1]<<8|fbytes[2*i];
692 s=((s&0xFFFF)^0x8000)-0x8000;
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000693 in[i+remaining*channels]=s;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000694 }
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000695 if (curr_read+remaining < frame_size)
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000696 {
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000697 for (i=(curr_read+remaining)*channels;i<frame_size*channels;i++)
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000698 in[i] = 0;
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000699 if (encode_only || decode_only)
700 stop = 1;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000701 }
702 len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000703 nb_encoded = opus_packet_get_samples_per_frame(data[toggle], sampling_rate)*opus_packet_get_nb_frames(data[toggle], len[toggle]);
704 remaining = frame_size-nb_encoded;
705 for(i=0;i<remaining*channels;i++)
706 in[i] = in[nb_encoded*channels+i];
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000707 if (sweep_bps!=0)
708 {
709 bitrate_bps += sweep_bps;
710 if (sweep_max)
711 {
712 if (bitrate_bps > sweep_max)
713 sweep_bps = -sweep_bps;
714 else if (bitrate_bps < sweep_min)
715 sweep_bps = -sweep_bps;
716 }
717 /* safety */
718 if (bitrate_bps<1000)
719 bitrate_bps = 1000;
720 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
721 }
722 opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range[toggle]));
723 if (len[toggle] < 0)
724 {
725 fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
726 fclose(fin);
727 fclose(fout);
728 return EXIT_FAILURE;
729 }
730 curr_mode_count += frame_size;
731 if (curr_mode_count > mode_switch_time && curr_mode < nb_modes_in_list-1)
732 {
733 curr_mode++;
734 curr_mode_count = 0;
735 }
736 }
737
tlegrand@google.com3c3902f2013-12-09 08:35:25 +0000738#if 0 /* This is for testing the padding code, do not enable by default */
739 if (len[toggle]<1275)
740 {
741 int new_len = len[toggle]+rand()%(max_payload_bytes-len[toggle]);
742 if ((err = opus_packet_pad(data[toggle], len[toggle], new_len)) != OPUS_OK)
743 {
744 fprintf(stderr, "padding failed: %s\n", opus_strerror(err));
745 return EXIT_FAILURE;
746 }
747 len[toggle] = new_len;
748 }
749#endif
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000750 if (encode_only)
751 {
752 unsigned char int_field[4];
753 int_to_char(len[toggle], int_field);
754 if (fwrite(int_field, 1, 4, fout) != 4) {
755 fprintf(stderr, "Error writing.\n");
756 return EXIT_FAILURE;
757 }
758 int_to_char(enc_final_range[toggle], int_field);
759 if (fwrite(int_field, 1, 4, fout) != 4) {
760 fprintf(stderr, "Error writing.\n");
761 return EXIT_FAILURE;
762 }
763 if (fwrite(data[toggle], 1, len[toggle], fout) != (unsigned)len[toggle]) {
764 fprintf(stderr, "Error writing.\n");
765 return EXIT_FAILURE;
766 }
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000767 tot_samples += nb_encoded;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000768 } else {
769 int output_samples;
770 lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000771 if (lost)
772 opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
773 else
774 output_samples = max_frame_size;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000775 if( count >= use_inbandfec ) {
776 /* delay by one packet when using in-band FEC */
777 if( use_inbandfec ) {
778 if( lost_prev ) {
779 /* attempt to decode with in-band FEC from next packet */
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000780 opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000781 output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 1);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000782 } else {
783 /* regular decode */
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000784 output_samples = max_frame_size;
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000785 output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, output_samples, 0);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000786 }
787 } else {
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000788 output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 0);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000789 }
790 if (output_samples>0)
791 {
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000792 if (!decode_only && tot_out + output_samples > tot_in)
793 {
794 stop=1;
795 output_samples = tot_in-tot_out;
796 }
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000797 if (output_samples>skip) {
798 int i;
799 for(i=0;i<(output_samples-skip)*channels;i++)
800 {
801 short s;
802 s=out[i+(skip*channels)];
803 fbytes[2*i]=s&0xFF;
804 fbytes[2*i+1]=(s>>8)&0xFF;
805 }
806 if (fwrite(fbytes, sizeof(short)*channels, output_samples-skip, fout) != (unsigned)(output_samples-skip)){
807 fprintf(stderr, "Error writing.\n");
808 return EXIT_FAILURE;
809 }
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000810 tot_out += output_samples-skip;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000811 }
812 if (output_samples<skip) skip -= output_samples;
813 else skip = 0;
814 } else {
815 fprintf(stderr, "error decoding frame: %s\n",
816 opus_strerror(output_samples));
817 }
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000818 tot_samples += output_samples;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000819 }
820 }
821
822 if (!encode_only)
823 opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
824 /* compare final range encoder rng values of encoder and decoder */
825 if( enc_final_range[toggle^use_inbandfec]!=0 && !encode_only
826 && !lost && !lost_prev
827 && dec_final_range != enc_final_range[toggle^use_inbandfec] ) {
828 fprintf (stderr, "Error: Range coder state mismatch "
829 "between encoder and decoder "
830 "in frame %ld: 0x%8lx vs 0x%8lx\n",
831 (long)count,
832 (unsigned long)enc_final_range[toggle^use_inbandfec],
833 (unsigned long)dec_final_range);
834 fclose(fin);
835 fclose(fout);
836 return EXIT_FAILURE;
837 }
838
839 lost_prev = lost;
840
841 /* count bits */
842 bits += len[toggle]*8;
843 bits_max = ( len[toggle]*8 > bits_max ) ? len[toggle]*8 : bits_max;
844 if( count >= use_inbandfec ) {
845 nrg = 0.0;
846 if (!decode_only)
847 {
848 for ( k = 0; k < frame_size * channels; k++ ) {
849 nrg += in[ k ] * (double)in[ k ];
850 }
851 }
852 if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
853 bits_act += len[toggle]*8;
854 count_act++;
855 }
856 /* Variance */
857 bits2 += len[toggle]*len[toggle]*64;
858 }
859 count++;
860 toggle = (toggle + use_inbandfec) & 1;
861 }
862 fprintf (stderr, "average bitrate: %7.3f kb/s\n",
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000863 1e-3*bits*sampling_rate/tot_samples);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000864 fprintf (stderr, "maximum bitrate: %7.3f kb/s\n",
865 1e-3*bits_max*sampling_rate/frame_size);
866 if (!decode_only)
867 fprintf (stderr, "active bitrate: %7.3f kb/s\n",
868 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
869 fprintf (stderr, "bitrate standard deviation: %7.3f kb/s\n",
870 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
871 /* Close any files to which intermediate results were stored */
872 SILK_DEBUG_STORE_CLOSE_FILES
873 silk_TimerSave("opus_timing.txt");
874 opus_encoder_destroy(enc);
875 opus_decoder_destroy(dec);
876 free(data[0]);
877 if (use_inbandfec)
878 free(data[1]);
879 fclose(fin);
880 fclose(fout);
881 free(in);
882 free(out);
883 free(fbytes);
884 return EXIT_SUCCESS;
885}