blob: 20bebba3331c83c37c5e3fc8fed71eab3162a936 [file] [log] [blame]
Jean-Marc Valinc8e37282010-06-30 14:44:20 -04001/* Copyright (c) 2007-2008 CSIRO
2 Copyright (c) 2007-2009 Xiph.Org Foundation
Jean-Marc Valin24af3032010-06-30 14:29:45 -04003 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
Jean-Marc Valin24af3032010-06-30 14:29:45 -040016 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
Jean-Marc Valincb05e7c2012-04-20 16:40:24 -040019 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Jean-Marc Valin24af3032010-06-30 14:29:45 -040021 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
Jean-Marc Valinc8e37282010-06-30 14:44:20 -040029#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
Jean-Marc Valin24af3032010-06-30 14:29:45 -040032
Jean-Marc Valinc8e37282010-06-30 14:44:20 -040033#include <stdio.h>
34#include <stdlib.h>
35#include <math.h>
36#include <string.h>
Jean-Marc Valin05dd36a2010-10-18 12:50:49 -040037#include "opus.h"
Jean-Marc Valin1c2f5632011-09-16 01:16:53 -070038#include "debug.h"
Jean-Marc Valind77d6a52011-07-29 17:33:06 -040039#include "opus_types.h"
Jean-Marc Valina05a3792011-10-30 22:49:35 -040040#include "opus_private.h"
Jean-Marc Valin24af3032010-06-30 14:29:45 -040041
Jean-Marc Valinbcdddb92011-03-17 06:51:58 -040042#define MAX_PACKET 1500
Jean-Marc Valinc8e37282010-06-30 14:44:20 -040043
Ralph Giles641eea82011-08-02 10:06:59 -070044void print_usage( char* argv[] )
Koen Vos9925d532011-02-01 10:44:48 -050045{
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -040046 fprintf(stderr, "Usage: %s [-e] <application> <sampling rate (Hz)> <channels (1/2)> "
47 "<bits per second> [options] <input> <output>\n", argv[0]);
48 fprintf(stderr, " %s -d <sampling rate (Hz)> <channels (1/2)> "
49 "[options] <input> <output>\n\n", argv[0]);
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -040050 fprintf(stderr, "mode: voip | audio | restricted-lowdelay\n" );
Koen Vos9925d532011-02-01 10:44:48 -050051 fprintf(stderr, "options:\n" );
Jean-Marc Valin46185622011-05-26 17:02:12 -040052 fprintf(stderr, "-e : only runs the encoder (output the bit-stream)\n" );
53 fprintf(stderr, "-d : only runs the decoder (reads the bit-stream as input)\n" );
Koen Vos479e18b2011-05-25 23:09:52 -040054 fprintf(stderr, "-cbr : enable constant bitrate; default: variable bitrate\n" );
Kat Walsh3269dce2011-08-15 22:43:51 -040055 fprintf(stderr, "-cvbr : enable constrained variable bitrate; default: unconstrained\n" );
Jean-Marc Valin46185622011-05-26 17:02:12 -040056 fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
57 fprintf(stderr, "-framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20 \n" );
Koen Vos9925d532011-02-01 10:44:48 -050058 fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
Koen Vos8f67b202011-02-03 09:31:12 -050059 fprintf(stderr, "-complexity <comp> : complexity, 0 (lowest) ... 10 (highest); default: 10\n" );
Koen Vos9925d532011-02-01 10:44:48 -050060 fprintf(stderr, "-inbandfec : enable SILK inband FEC\n" );
Jean-Marc Valin103302b2011-05-19 17:17:44 -040061 fprintf(stderr, "-forcemono : force mono encoding, even for stereo input\n" );
Koen Vos9925d532011-02-01 10:44:48 -050062 fprintf(stderr, "-dtx : enable SILK DTX\n" );
63 fprintf(stderr, "-loss <perc> : simulate packet loss, in percent (0-100); default: 0\n" );
64}
65
Jean-Marc Valind77d6a52011-07-29 17:33:06 -040066static void int_to_char(opus_uint32 i, unsigned char ch[4])
Jean-Marc Valin99126f42011-05-26 16:57:57 -040067{
68 ch[0] = i>>24;
69 ch[1] = (i>>16)&0xFF;
70 ch[2] = (i>>8)&0xFF;
71 ch[3] = i&0xFF;
72}
73
Jean-Marc Valind77d6a52011-07-29 17:33:06 -040074static opus_uint32 char_to_int(unsigned char ch[4])
Jean-Marc Valin99126f42011-05-26 16:57:57 -040075{
Jean-Marc Valind77d6a52011-07-29 17:33:06 -040076 return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16)
77 | ((opus_uint32)ch[2]<< 8) | (opus_uint32)ch[3];
Jean-Marc Valin99126f42011-05-26 16:57:57 -040078}
Koen Vos9925d532011-02-01 10:44:48 -050079
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -040080static void check_decoder_option(int encode_only, const char *opt)
81{
82 if (encode_only)
83 {
84 fprintf(stderr, "option %s is only for decoding\n", opt);
Gregory Maxwell72b9b342011-10-29 03:45:13 -040085 exit(EXIT_FAILURE);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -040086 }
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -040087}
88
89static void check_encoder_option(int decode_only, const char *opt)
90{
91 if (decode_only)
92 {
93 fprintf(stderr, "option %s is only for encoding\n", opt);
Gregory Maxwell72b9b342011-10-29 03:45:13 -040094 exit(EXIT_FAILURE);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -040095 }
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -040096}
97
Jean-Marc Valin17c59662012-02-17 16:09:21 -050098int silk8_test[][4] = {
99 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*3, 1},
100 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*2, 1},
101 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960, 1},
102 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480, 1},
103 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*3, 2},
104 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*2, 2},
105 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960, 2},
106 {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480, 2}
107};
108
109int silk12_test[][4] = {
110 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*3, 1},
111 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*2, 1},
112 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960, 1},
113 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 480, 1},
114 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*3, 2},
115 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*2, 2},
116 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960, 2},
117 {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 480, 2}
118};
119
120int silk16_test[][4] = {
121 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*3, 1},
122 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*2, 1},
123 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 1},
124 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480, 1},
125 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*3, 2},
126 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*2, 2},
127 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 2},
128 {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480, 2}
129};
130
131int hybrid24_test[][4] = {
132 {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 1},
133 {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 1},
134 {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 2},
135 {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 2}
136};
137
138int hybrid48_test[][4] = {
139 {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 1},
140 {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 1},
141 {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 2},
142 {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 2}
143};
144
145int celt_test[][4] = {
146 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 1},
147 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 1},
148 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 1},
149 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960, 1},
150
151 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 1},
152 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 1},
153 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480, 1},
154 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480, 1},
155
156 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 240, 1},
157 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 240, 1},
158 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 240, 1},
159 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 240, 1},
160
161 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 120, 1},
162 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 120, 1},
163 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 120, 1},
164 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 120, 1},
165
166 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 2},
167 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 2},
168 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 2},
169 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960, 2},
170
171 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 2},
172 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 2},
173 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480, 2},
174 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480, 2},
175
176 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 240, 2},
177 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 240, 2},
178 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 240, 2},
179 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 240, 2},
180
181 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 120, 2},
182 {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 120, 2},
183 {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 120, 2},
184 {MODE_CELT_ONLY, OPUS_BANDWIDTH_NARROWBAND, 120, 2},
185
186};
187
188int celt_hq_test[][4] = {
189 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 2},
190 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 2},
191 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 240, 2},
192 {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 120, 2},
193};
194
Jean-Marc Valinc8e37282010-06-30 14:44:20 -0400195int main(int argc, char *argv[])
196{
Ralph Giles641eea82011-08-02 10:06:59 -0700197 int err;
198 char *inFile, *outFile;
199 FILE *fin, *fout;
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400200 OpusEncoder *enc=NULL;
201 OpusDecoder *dec=NULL;
Ralph Giles641eea82011-08-02 10:06:59 -0700202 int args;
203 int len[2];
204 int frame_size, channels;
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400205 opus_int32 bitrate_bps=0;
Ralph Giles641eea82011-08-02 10:06:59 -0700206 unsigned char *data[2];
Gregory Maxwellb7034ec2012-04-30 10:22:03 -0400207 unsigned char *fbytes;
Gregory Maxwell64a35412011-09-02 10:31:17 -0400208 opus_int32 sampling_rate;
Ralph Giles641eea82011-08-02 10:06:59 -0700209 int use_vbr;
210 int max_payload_bytes;
211 int complexity;
212 int use_inbandfec;
213 int use_dtx;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400214 int forcechannels;
Ralph Giles641eea82011-08-02 10:06:59 -0700215 int cvbr = 0;
216 int packet_loss_perc;
Gregory Maxwell64a35412011-09-02 10:31:17 -0400217 opus_int32 count=0, count_act=0;
218 int k;
Jean-Marc Valin24ed4652012-05-18 15:14:17 -0400219 opus_int32 skip=0;
Ralph Giles641eea82011-08-02 10:06:59 -0700220 int stop=0;
Ralph Giles641eea82011-08-02 10:06:59 -0700221 short *in, *out;
Gregory Maxwell149754e2011-09-19 16:40:12 -0400222 int application=OPUS_APPLICATION_AUDIO;
Jean-Marc Valin294bfec2011-10-20 00:39:41 -0400223 double bits=0.0, bits_max=0.0, bits_act=0.0, bits2=0.0, nrg;
Ralph Giles641eea82011-08-02 10:06:59 -0700224 int bandwidth=-1;
225 const char *bandwidth_string;
Ralph Giles641eea82011-08-02 10:06:59 -0700226 int lost = 0, lost_prev = 1;
227 int toggle = 0;
Jean-Marc Valind4827732011-08-19 17:07:16 -0400228 opus_uint32 enc_final_range[2];
229 opus_uint32 dec_final_range;
Ralph Giles641eea82011-08-02 10:06:59 -0700230 int encode_only=0, decode_only=0;
Koen Vos4e1ce382011-08-25 13:50:21 -0400231 int max_frame_size = 960*6;
232 int curr_read=0;
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400233 int sweep_bps = 0;
Jean-Marc Valina05a3792011-10-30 22:49:35 -0400234 int random_framesize=0, newsize=0, delayed_celt=0;
235 int sweep_max=0, sweep_min=0;
Jean-Marc Valinabaa3482011-10-31 14:35:44 -0400236 int random_fec=0;
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500237 int (*mode_list)[4]=NULL;
238 int nb_modes_in_list=0;
239 int curr_mode=0;
240 int curr_mode_count=0;
241 int mode_switch_time = 48000;
Koen Vos9925d532011-02-01 10:44:48 -0500242
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400243 if (argc < 5 )
Ralph Giles641eea82011-08-02 10:06:59 -0700244 {
245 print_usage( argv );
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400246 return EXIT_FAILURE;
Ralph Giles641eea82011-08-02 10:06:59 -0700247 }
Jean-Marc Valinc8e37282010-06-30 14:44:20 -0400248
Ralph Gilesa57e0b92011-08-02 10:14:36 -0700249 fprintf(stderr, "%s\n", opus_get_version_string());
250
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400251 args = 1;
252 if (strcmp(argv[args], "-e")==0)
Ralph Giles641eea82011-08-02 10:06:59 -0700253 {
254 encode_only = 1;
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400255 args++;
256 } else if (strcmp(argv[args], "-d")==0)
Ralph Giles641eea82011-08-02 10:06:59 -0700257 {
258 decode_only = 1;
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400259 args++;
Ralph Giles641eea82011-08-02 10:06:59 -0700260 }
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400261 if (!decode_only && argc < 7 )
262 {
263 print_usage( argv );
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400264 return EXIT_FAILURE;
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -0400265 }
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400266
267 if (!decode_only)
268 {
269 if (strcmp(argv[args], "voip")==0)
270 application = OPUS_APPLICATION_VOIP;
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400271 else if (strcmp(argv[args], "restricted-lowdelay")==0)
272 application = OPUS_APPLICATION_RESTRICTED_LOWDELAY;
Gregory Maxwell149754e2011-09-19 16:40:12 -0400273 else if (strcmp(argv[args], "audio")!=0) {
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400274 fprintf(stderr, "unknown application: %s\n", argv[args]);
275 print_usage(argv);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400276 return EXIT_FAILURE;
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400277 }
278 args++;
279 }
280 sampling_rate = (opus_int32)atol(argv[args]);
281 args++;
282 channels = atoi(argv[args]);
283 args++;
284 if (!decode_only)
285 {
286 bitrate_bps = (opus_int32)atol(argv[args]);
287 args++;
288 }
Jean-Marc Valin769311f2010-07-20 13:28:00 -0400289
Ralph Gilesda025d52011-10-26 20:24:49 -0700290 if (sampling_rate != 8000 && sampling_rate != 12000
291 && sampling_rate != 16000 && sampling_rate != 24000
292 && sampling_rate != 48000)
Ralph Giles641eea82011-08-02 10:06:59 -0700293 {
Ralph Gilesda025d52011-10-26 20:24:49 -0700294 fprintf(stderr, "Supported sampling rates are 8000, 12000, "
295 "16000, 24000 and 48000.\n");
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400296 return EXIT_FAILURE;
Ralph Giles641eea82011-08-02 10:06:59 -0700297 }
298 frame_size = sampling_rate/50;
299
300 /* defaults: */
301 use_vbr = 1;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400302 bandwidth = OPUS_AUTO;
Ralph Giles641eea82011-08-02 10:06:59 -0700303 max_payload_bytes = MAX_PACKET;
304 complexity = 10;
305 use_inbandfec = 0;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400306 forcechannels = OPUS_AUTO;
Ralph Giles641eea82011-08-02 10:06:59 -0700307 use_dtx = 0;
308 packet_loss_perc = 0;
Koen Vos4e1ce382011-08-25 13:50:21 -0400309 max_frame_size = 960*6;
310 curr_read=0;
Ralph Giles641eea82011-08-02 10:06:59 -0700311
Ralph Giles641eea82011-08-02 10:06:59 -0700312 while( args < argc - 2 ) {
313 /* process command line options */
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400314 if( strcmp( argv[ args ], "-cbr" ) == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400315 check_encoder_option(decode_only, "-cbr");
Jean-Marc Valin99929d22011-02-04 00:54:00 -0500316 use_vbr = 0;
Koen Vos9925d532011-02-01 10:44:48 -0500317 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400318 } else if( strcmp( argv[ args ], "-bandwidth" ) == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400319 check_encoder_option(decode_only, "-bandwidth");
Jean-Marc Valina10e8792011-02-02 16:23:43 -0500320 if (strcmp(argv[ args + 1 ], "NB")==0)
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400321 bandwidth = OPUS_BANDWIDTH_NARROWBAND;
Jean-Marc Valina10e8792011-02-02 16:23:43 -0500322 else if (strcmp(argv[ args + 1 ], "MB")==0)
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400323 bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
Jean-Marc Valina10e8792011-02-02 16:23:43 -0500324 else if (strcmp(argv[ args + 1 ], "WB")==0)
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400325 bandwidth = OPUS_BANDWIDTH_WIDEBAND;
Jean-Marc Valina10e8792011-02-02 16:23:43 -0500326 else if (strcmp(argv[ args + 1 ], "SWB")==0)
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400327 bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
Jean-Marc Valina10e8792011-02-02 16:23:43 -0500328 else if (strcmp(argv[ args + 1 ], "FB")==0)
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400329 bandwidth = OPUS_BANDWIDTH_FULLBAND;
Jean-Marc Valina10e8792011-02-02 16:23:43 -0500330 else {
Ralph Gilesda025d52011-10-26 20:24:49 -0700331 fprintf(stderr, "Unknown bandwidth %s. "
332 "Supported are NB, MB, WB, SWB, FB.\n",
333 argv[ args + 1 ]);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400334 return EXIT_FAILURE;
Jean-Marc Valina10e8792011-02-02 16:23:43 -0500335 }
Koen Vos9925d532011-02-01 10:44:48 -0500336 args += 2;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400337 } else if( strcmp( argv[ args ], "-framesize" ) == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400338 check_encoder_option(decode_only, "-framesize");
Jean-Marc Valin356c9c42011-02-04 01:09:54 -0500339 if (strcmp(argv[ args + 1 ], "2.5")==0)
340 frame_size = sampling_rate/400;
341 else if (strcmp(argv[ args + 1 ], "5")==0)
Gregory Maxwellf919dd72011-02-08 23:06:01 -0500342 frame_size = sampling_rate/200;
Jean-Marc Valin356c9c42011-02-04 01:09:54 -0500343 else if (strcmp(argv[ args + 1 ], "10")==0)
344 frame_size = sampling_rate/100;
345 else if (strcmp(argv[ args + 1 ], "20")==0)
346 frame_size = sampling_rate/50;
347 else if (strcmp(argv[ args + 1 ], "40")==0)
348 frame_size = sampling_rate/25;
349 else if (strcmp(argv[ args + 1 ], "60")==0)
350 frame_size = 3*sampling_rate/50;
351 else {
Ralph Gilesda025d52011-10-26 20:24:49 -0700352 fprintf(stderr, "Unsupported frame size: %s ms. "
353 "Supported are 2.5, 5, 10, 20, 40, 60.\n",
354 argv[ args + 1 ]);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400355 return EXIT_FAILURE;
Jean-Marc Valin356c9c42011-02-04 01:09:54 -0500356 }
357 args += 2;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400358 } else if( strcmp( argv[ args ], "-max_payload" ) == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400359 check_encoder_option(decode_only, "-max_payload");
Koen Vos9925d532011-02-01 10:44:48 -0500360 max_payload_bytes = atoi( argv[ args + 1 ] );
361 args += 2;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400362 } else if( strcmp( argv[ args ], "-complexity" ) == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400363 check_encoder_option(decode_only, "-complexity");
Koen Vos9925d532011-02-01 10:44:48 -0500364 complexity = atoi( argv[ args + 1 ] );
365 args += 2;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400366 } else if( strcmp( argv[ args ], "-inbandfec" ) == 0 ) {
Koen Vos9925d532011-02-01 10:44:48 -0500367 use_inbandfec = 1;
368 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400369 } else if( strcmp( argv[ args ], "-forcemono" ) == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400370 check_encoder_option(decode_only, "-forcemono");
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400371 forcechannels = 1;
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400372 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400373 } else if( strcmp( argv[ args ], "-cvbr" ) == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400374 check_encoder_option(decode_only, "-cvbr");
Jean-Marc Valinb55b6612011-03-14 15:11:44 -0400375 cvbr = 1;
376 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400377 } else if( strcmp( argv[ args ], "-dtx") == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400378 check_encoder_option(decode_only, "-dtx");
Koen Vos9925d532011-02-01 10:44:48 -0500379 use_dtx = 1;
380 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400381 } else if( strcmp( argv[ args ], "-loss" ) == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400382 check_decoder_option(encode_only, "-loss");
Koen Vos9925d532011-02-01 10:44:48 -0500383 packet_loss_perc = atoi( argv[ args + 1 ] );
384 args += 2;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400385 } else if( strcmp( argv[ args ], "-sweep" ) == 0 ) {
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400386 check_encoder_option(decode_only, "-sweep");
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400387 sweep_bps = atoi( argv[ args + 1 ] );
388 args += 2;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400389 } else if( strcmp( argv[ args ], "-random_framesize" ) == 0 ) {
Jean-Marc Valina05a3792011-10-30 22:49:35 -0400390 check_encoder_option(decode_only, "-random_framesize");
391 random_framesize = 1;
392 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400393 } else if( strcmp( argv[ args ], "-sweep_max" ) == 0 ) {
Jean-Marc Valina05a3792011-10-30 22:49:35 -0400394 check_encoder_option(decode_only, "-sweep_max");
395 sweep_max = atoi( argv[ args + 1 ] );
396 args += 2;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400397 } else if( strcmp( argv[ args ], "-random_fec" ) == 0 ) {
Jean-Marc Valinabaa3482011-10-31 14:35:44 -0400398 check_encoder_option(decode_only, "-random_fec");
399 random_fec = 1;
400 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400401 } else if( strcmp( argv[ args ], "-silk8k_test" ) == 0 ) {
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500402 check_encoder_option(decode_only, "-silk8k_test");
403 mode_list = silk8_test;
404 nb_modes_in_list = 8;
405 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400406 } else if( strcmp( argv[ args ], "-silk12k_test" ) == 0 ) {
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500407 check_encoder_option(decode_only, "-silk12k_test");
408 mode_list = silk12_test;
409 nb_modes_in_list = 8;
410 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400411 } else if( strcmp( argv[ args ], "-silk16k_test" ) == 0 ) {
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500412 check_encoder_option(decode_only, "-silk16k_test");
413 mode_list = silk16_test;
414 nb_modes_in_list = 8;
415 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400416 } else if( strcmp( argv[ args ], "-hybrid24k_test" ) == 0 ) {
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500417 check_encoder_option(decode_only, "-hybrid24k_test");
418 mode_list = hybrid24_test;
419 nb_modes_in_list = 4;
420 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400421 } else if( strcmp( argv[ args ], "-hybrid48k_test" ) == 0 ) {
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500422 check_encoder_option(decode_only, "-hybrid48k_test");
423 mode_list = hybrid48_test;
424 nb_modes_in_list = 4;
425 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400426 } else if( strcmp( argv[ args ], "-celt_test" ) == 0 ) {
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500427 check_encoder_option(decode_only, "-celt_test");
428 mode_list = celt_test;
429 nb_modes_in_list = 32;
430 args++;
Gregory Maxwell2967d4e2012-05-17 20:04:42 -0400431 } else if( strcmp( argv[ args ], "-celt_hq_test" ) == 0 ) {
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500432 check_encoder_option(decode_only, "-celt_hq_test");
433 mode_list = celt_hq_test;
434 nb_modes_in_list = 4;
435 args++;
Koen Vos9925d532011-02-01 10:44:48 -0500436 } else {
437 printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
438 print_usage( argv );
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400439 return EXIT_FAILURE;
Koen Vos9925d532011-02-01 10:44:48 -0500440 }
Ralph Giles641eea82011-08-02 10:06:59 -0700441 }
Jean-Marc Valin769311f2010-07-20 13:28:00 -0400442
Jean-Marc Valina05a3792011-10-30 22:49:35 -0400443 if (sweep_max)
444 sweep_min = bitrate_bps;
445
Ralph Giles641eea82011-08-02 10:06:59 -0700446 if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
447 {
448 fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
449 MAX_PACKET);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400450 return EXIT_FAILURE;
Ralph Giles641eea82011-08-02 10:06:59 -0700451 }
Jean-Marc Valinc8e37282010-06-30 14:44:20 -0400452
Ralph Giles641eea82011-08-02 10:06:59 -0700453 inFile = argv[argc-2];
454 fin = fopen(inFile, "rb");
455 if (!fin)
456 {
457 fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400458 return EXIT_FAILURE;
Ralph Giles641eea82011-08-02 10:06:59 -0700459 }
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500460 if (mode_list)
461 {
462 int size;
463 fseek(fin, 0, SEEK_END);
464 size = ftell(fin);
465 fprintf(stderr, "File size is %d bytes\n", size);
466 fseek(fin, 0, SEEK_SET);
467 mode_switch_time = size/sizeof(short)/channels/nb_modes_in_list;
468 fprintf(stderr, "Switching mode every %d samples\n", mode_switch_time);
469 }
470
Ralph Giles641eea82011-08-02 10:06:59 -0700471 outFile = argv[argc-1];
472 fout = fopen(outFile, "wb+");
473 if (!fout)
474 {
475 fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
Gregory Maxwell38fc0d52011-10-29 23:54:45 -0400476 fclose(fin);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400477 return EXIT_FAILURE;
Ralph Giles641eea82011-08-02 10:06:59 -0700478 }
Jean-Marc Valinc8e37282010-06-30 14:44:20 -0400479
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400480 if (!decode_only)
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400481 {
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400482 enc = opus_encoder_create(sampling_rate, channels, application, &err);
483 if (err != OPUS_OK)
484 {
485 fprintf(stderr, "Cannot create encoder: %s\n", opus_strerror(err));
Gregory Maxwell38fc0d52011-10-29 23:54:45 -0400486 fclose(fin);
487 fclose(fout);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400488 return EXIT_FAILURE;
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400489 }
490 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
491 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
492 opus_encoder_ctl(enc, OPUS_SET_VBR(use_vbr));
493 opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
494 opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
495 opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(use_inbandfec));
496 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(forcechannels));
497 opus_encoder_ctl(enc, OPUS_SET_DTX(use_dtx));
498 opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
499
500 opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
Jean-Marc Valin1cd5d952012-07-11 02:54:47 -0400501 opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400502 }
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400503 if (!encode_only)
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400504 {
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400505 dec = opus_decoder_create(sampling_rate, channels, &err);
506 if (err != OPUS_OK)
507 {
508 fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
Gregory Maxwell38fc0d52011-10-29 23:54:45 -0400509 fclose(fin);
510 fclose(fout);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400511 return EXIT_FAILURE;
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400512 }
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400513 }
Jean-Marc Valinc8e37282010-06-30 14:44:20 -0400514
Jean-Marc Valin2c8b2982011-02-04 00:38:50 -0500515
Ralph Giles641eea82011-08-02 10:06:59 -0700516 switch(bandwidth)
517 {
518 case OPUS_BANDWIDTH_NARROWBAND:
519 bandwidth_string = "narrowband";
520 break;
521 case OPUS_BANDWIDTH_MEDIUMBAND:
522 bandwidth_string = "mediumband";
523 break;
524 case OPUS_BANDWIDTH_WIDEBAND:
525 bandwidth_string = "wideband";
526 break;
527 case OPUS_BANDWIDTH_SUPERWIDEBAND:
528 bandwidth_string = "superwideband";
529 break;
530 case OPUS_BANDWIDTH_FULLBAND:
531 bandwidth_string = "fullband";
532 break;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400533 case OPUS_AUTO:
Ralph Giles641eea82011-08-02 10:06:59 -0700534 bandwidth_string = "auto";
535 break;
536 default:
537 bandwidth_string = "unknown";
Jean-Marc Valinbe89c392011-08-30 12:39:51 -0400538 break;
Ralph Giles641eea82011-08-02 10:06:59 -0700539 }
Jean-Marc Valin2c8b2982011-02-04 00:38:50 -0500540
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400541 if (decode_only)
Ralph Gilesda025d52011-10-26 20:24:49 -0700542 fprintf(stderr, "Decoding with %ld Hz output (%d channels)\n",
543 (long)sampling_rate, channels);
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400544 else
Ralph Gilesda025d52011-10-26 20:24:49 -0700545 fprintf(stderr, "Encoding %ld Hz input at %.3f kb/s "
546 "in %s mode with %d-sample frames.\n",
547 (long)sampling_rate, bitrate_bps*0.001,
548 bandwidth_string, frame_size);
Jean-Marc Valin89e69502010-07-20 16:49:28 -0400549
Jean-Marc Valina05a3792011-10-30 22:49:35 -0400550 in = (short*)malloc(max_frame_size*channels*sizeof(short));
Ralph Giles641eea82011-08-02 10:06:59 -0700551 out = (short*)malloc(max_frame_size*channels*sizeof(short));
Gregory Maxwellb7034ec2012-04-30 10:22:03 -0400552 fbytes = (unsigned char*)malloc(max_frame_size*channels*sizeof(short));
Ralph Giles641eea82011-08-02 10:06:59 -0700553 data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
554 if ( use_inbandfec ) {
555 data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
556 }
557 while (!stop)
558 {
Jean-Marc Valina05a3792011-10-30 22:49:35 -0400559 if (delayed_celt)
560 {
561 frame_size = newsize;
562 delayed_celt = 0;
563 } else if (random_framesize && rand()%20==0)
564 {
565 newsize = rand()%6;
566 switch(newsize)
567 {
568 case 0: newsize=sampling_rate/400; break;
569 case 1: newsize=sampling_rate/200; break;
570 case 2: newsize=sampling_rate/100; break;
571 case 3: newsize=sampling_rate/50; break;
572 case 4: newsize=sampling_rate/25; break;
573 case 5: newsize=3*sampling_rate/50; break;
574 }
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500575 while (newsize < sampling_rate/25 && bitrate_bps-fabs(sweep_bps) <= 3*12*sampling_rate/newsize)
576 newsize*=2;
Jean-Marc Valina05a3792011-10-30 22:49:35 -0400577 if (newsize < sampling_rate/100 && frame_size >= sampling_rate/100)
578 {
579 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
580 delayed_celt=1;
581 } else {
582 frame_size = newsize;
583 }
584 }
Jean-Marc Valinabaa3482011-10-31 14:35:44 -0400585 if (random_fec && rand()%30==0)
586 {
587 opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(rand()%4==0));
588 }
Ralph Giles641eea82011-08-02 10:06:59 -0700589 if (decode_only)
590 {
591 unsigned char ch[4];
592 err = fread(ch, 1, 4, fin);
Gregory Maxwellbad313c2011-08-17 17:06:17 -0400593 if (feof(fin))
594 break;
Ralph Giles641eea82011-08-02 10:06:59 -0700595 len[toggle] = char_to_int(ch);
596 if (len[toggle]>max_payload_bytes || len[toggle]<0)
597 {
Gregory Maxwellbad313c2011-08-17 17:06:17 -0400598 fprintf(stderr, "Invalid payload length: %d\n",len[toggle]);
Ralph Giles641eea82011-08-02 10:06:59 -0700599 break;
600 }
601 err = fread(ch, 1, 4, fin);
602 enc_final_range[toggle] = char_to_int(ch);
603 err = fread(data[toggle], 1, len[toggle], fin);
Gregory Maxwellbad313c2011-08-17 17:06:17 -0400604 if (err<len[toggle])
605 {
Ralph Gilesda025d52011-10-26 20:24:49 -0700606 fprintf(stderr, "Ran out of input, "
607 "expecting %d bytes got %d\n",
608 len[toggle],err);
Ralph Giles641eea82011-08-02 10:06:59 -0700609 break;
Gregory Maxwellbad313c2011-08-17 17:06:17 -0400610 }
Ralph Giles641eea82011-08-02 10:06:59 -0700611 } else {
Gregory Maxwellb7034ec2012-04-30 10:22:03 -0400612 int i;
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500613 if (mode_list!=NULL)
614 {
615 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(mode_list[curr_mode][1]));
616 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(mode_list[curr_mode][0]));
617 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(mode_list[curr_mode][3]));
618 frame_size = mode_list[curr_mode][2];
619 }
Gregory Maxwellb7034ec2012-04-30 10:22:03 -0400620 err = fread(fbytes, sizeof(short)*channels, frame_size, fin);
Jean-Marc Valinc2d86f02011-08-10 14:17:55 -0400621 curr_read = err;
Gregory Maxwellb7034ec2012-04-30 10:22:03 -0400622 for(i=0;i<curr_read*channels;i++)
623 {
624 opus_int32 s;
625 s=fbytes[2*i+1]<<8|fbytes[2*i];
626 s=((s&0xFFFF)^0x8000)-0x8000;
627 in[i]=s;
628 }
Jean-Marc Valin0c08a992011-08-13 01:44:09 -0400629 if (curr_read < frame_size)
Ralph Giles641eea82011-08-02 10:06:59 -0700630 {
Jean-Marc Valinc2d86f02011-08-10 14:17:55 -0400631 for (i=curr_read*channels;i<frame_size*channels;i++)
632 in[i] = 0;
Ralph Giles641eea82011-08-02 10:06:59 -0700633 stop = 1;
634 }
Ralph Giles641eea82011-08-02 10:06:59 -0700635 len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400636 if (sweep_bps!=0)
637 {
638 bitrate_bps += sweep_bps;
Jean-Marc Valina05a3792011-10-30 22:49:35 -0400639 if (sweep_max)
640 {
641 if (bitrate_bps > sweep_max)
642 sweep_bps = -sweep_bps;
643 else if (bitrate_bps < sweep_min)
644 sweep_bps = -sweep_bps;
645 }
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400646 /* safety */
647 if (bitrate_bps<1000)
648 bitrate_bps = 1000;
649 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
650 }
Jean-Marc Valind4827732011-08-19 17:07:16 -0400651 opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range[toggle]));
Ralph Giles641eea82011-08-02 10:06:59 -0700652 if (len[toggle] < 0)
653 {
654 fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
Gregory Maxwell38fc0d52011-10-29 23:54:45 -0400655 fclose(fin);
656 fclose(fout);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400657 return EXIT_FAILURE;
Ralph Giles641eea82011-08-02 10:06:59 -0700658 }
Jean-Marc Valin17c59662012-02-17 16:09:21 -0500659 curr_mode_count += frame_size;
660 if (curr_mode_count > mode_switch_time && curr_mode < nb_modes_in_list-1)
661 {
662 curr_mode++;
663 curr_mode_count = 0;
664 }
Ralph Giles641eea82011-08-02 10:06:59 -0700665 }
Jean-Marc Valin99126f42011-05-26 16:57:57 -0400666
Ralph Giles641eea82011-08-02 10:06:59 -0700667 if (encode_only)
668 {
669 unsigned char int_field[4];
670 int_to_char(len[toggle], int_field);
Gregory Maxwell28b1d242012-04-23 13:51:23 -0400671 if (fwrite(int_field, 1, 4, fout) != 4) {
672 fprintf(stderr, "Error writing.\n");
673 return EXIT_FAILURE;
674 }
Ralph Giles641eea82011-08-02 10:06:59 -0700675 int_to_char(enc_final_range[toggle], int_field);
Gregory Maxwell28b1d242012-04-23 13:51:23 -0400676 if (fwrite(int_field, 1, 4, fout) != 4) {
677 fprintf(stderr, "Error writing.\n");
678 return EXIT_FAILURE;
679 }
680 if (fwrite(data[toggle], 1, len[toggle], fout) != (unsigned)len[toggle]) {
681 fprintf(stderr, "Error writing.\n");
682 return EXIT_FAILURE;
683 }
Ralph Giles641eea82011-08-02 10:06:59 -0700684 } else {
685 int output_samples;
Gregory Maxwellbad313c2011-08-17 17:06:17 -0400686 lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
Ralph Giles641eea82011-08-02 10:06:59 -0700687 if( count >= use_inbandfec ) {
688 /* delay by one packet when using in-band FEC */
689 if( use_inbandfec ) {
690 if( lost_prev ) {
691 /* attempt to decode with in-band FEC from next packet */
692 output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1);
693 } else {
694 /* regular decode */
695 output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0);
696 }
697 } else {
698 output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0);
699 }
700 if (output_samples>0)
701 {
Gregory Maxwell28b1d242012-04-23 13:51:23 -0400702 if (output_samples>skip) {
Gregory Maxwellb7034ec2012-04-30 10:22:03 -0400703 int i;
704 for(i=0;i<(output_samples-skip)*channels;i++)
705 {
706 short s;
707 s=out[i+(skip*channels)];
708 fbytes[2*i]=s&0xFF;
709 fbytes[2*i+1]=(s>>8)&0xFF;
710 }
711 if (fwrite(fbytes, sizeof(short)*channels, output_samples-skip, fout) != (unsigned)(output_samples-skip)){
Gregory Maxwell28b1d242012-04-23 13:51:23 -0400712 fprintf(stderr, "Error writing.\n");
713 return EXIT_FAILURE;
714 }
715 }
716 if (output_samples<skip) skip -= output_samples;
717 else skip = 0;
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400718 } else {
Ralph Gilesda025d52011-10-26 20:24:49 -0700719 fprintf(stderr, "error decoding frame: %s\n",
720 opus_strerror(output_samples));
Ralph Giles641eea82011-08-02 10:06:59 -0700721 }
722 }
723 }
Koen Vos9925d532011-02-01 10:44:48 -0500724
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400725 if (!encode_only)
726 opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
Ralph Giles641eea82011-08-02 10:06:59 -0700727 /* compare final range encoder rng values of encoder and decoder */
Ralph Gilesda025d52011-10-26 20:24:49 -0700728 if( enc_final_range[toggle^use_inbandfec]!=0 && !encode_only
729 && !lost && !lost_prev
730 && dec_final_range != enc_final_range[toggle^use_inbandfec] ) {
731 fprintf (stderr, "Error: Range coder state mismatch "
732 "between encoder and decoder "
733 "in frame %ld: 0x%8lx vs 0x%8lx\n",
734 (long)count,
735 (unsigned long)enc_final_range[toggle^use_inbandfec],
736 (unsigned long)dec_final_range);
Gregory Maxwell38fc0d52011-10-29 23:54:45 -0400737 fclose(fin);
738 fclose(fout);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400739 return EXIT_FAILURE;
Ralph Giles641eea82011-08-02 10:06:59 -0700740 }
Koen Vos8f67b202011-02-03 09:31:12 -0500741
Ralph Giles641eea82011-08-02 10:06:59 -0700742 lost_prev = lost;
Koen Vos1e1562c2011-02-14 15:04:59 -0500743
Ralph Giles641eea82011-08-02 10:06:59 -0700744 /* count bits */
745 bits += len[toggle]*8;
Jean-Marc Valin294bfec2011-10-20 00:39:41 -0400746 bits_max = ( len[toggle]*8 > bits_max ) ? len[toggle]*8 : bits_max;
Ralph Giles641eea82011-08-02 10:06:59 -0700747 if( count >= use_inbandfec ) {
748 nrg = 0.0;
749 if (!decode_only)
750 {
751 for ( k = 0; k < frame_size * channels; k++ ) {
752 nrg += in[ k ] * (double)in[ k ];
753 }
754 }
755 if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
756 bits_act += len[toggle]*8;
757 count_act++;
758 }
Ralph Gilesda025d52011-10-26 20:24:49 -0700759 /* Variance */
Ralph Giles641eea82011-08-02 10:06:59 -0700760 bits2 += len[toggle]*len[toggle]*64;
761 }
762 count++;
763 toggle = (toggle + use_inbandfec) & 1;
764 }
Ralph Gilesda025d52011-10-26 20:24:49 -0700765 fprintf (stderr, "average bitrate: %7.3f kb/s\n",
766 1e-3*bits*sampling_rate/(frame_size*(double)count));
Gregory Maxwell44666222012-07-27 00:37:19 -0400767 fprintf (stderr, "maximum bitrate: %7.3f kb/s\n",
Ralph Gilesda025d52011-10-26 20:24:49 -0700768 1e-3*bits_max*sampling_rate/frame_size);
Jean-Marc Valinf5ac8a62011-09-09 11:31:03 -0400769 if (!decode_only)
Ralph Gilesda025d52011-10-26 20:24:49 -0700770 fprintf (stderr, "active bitrate: %7.3f kb/s\n",
771 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
772 fprintf (stderr, "bitrate standard deviation: %7.3f kb/s\n",
773 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
Ralph Giles641eea82011-08-02 10:06:59 -0700774 /* Close any files to which intermediate results were stored */
775 SILK_DEBUG_STORE_CLOSE_FILES
776 silk_TimerSave("opus_timing.txt");
777 opus_encoder_destroy(enc);
778 opus_decoder_destroy(dec);
779 free(data[0]);
780 if (use_inbandfec)
781 free(data[1]);
782 fclose(fin);
783 fclose(fout);
784 free(in);
785 free(out);
Gregory Maxwellb7034ec2012-04-30 10:22:03 -0400786 free(fbytes);
Jean-Marc Valin9fb5cee2011-10-28 22:41:55 -0400787 return EXIT_SUCCESS;
Jean-Marc Valin24af3032010-06-30 14:29:45 -0400788}