add -F, remove -R
[flac.git] / src / flac / main.c
1 /* flac - Command-line FLAC encoder/decoder
2  * Copyright (C) 2000,2001,2002  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 #include <ctype.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #if !defined _MSC_VER && !defined __MINGW32__
25 /* unlink is in stdio.h in VC++ */
26 #include <unistd.h> /* for unlink() */
27 #else
28 #define strcasecmp stricmp
29 #endif
30 #include "FLAC/all.h"
31 #include "analyze.h"
32 #include "decode.h"
33 #include "encode.h"
34 #include "file.h"
35
36 static int short_usage(const char *message, ...);
37 static int long_usage(const char *message, ...);
38 static int encode_file(const char *infilename, const char *forced_outfilename, FLAC__bool is_last_file);
39 static int decode_file(const char *infilename, const char *forced_outfilename);
40
41 FLAC__bool verify = false, verbose = true, continue_through_decode_errors = false, lax = false, test_only = false, analyze = false, use_ogg = false;
42 FLAC__bool do_mid_side = true, loose_mid_side = false, do_exhaustive_model_search = false, do_escape_coding = false, do_qlp_coeff_prec_search = false;
43 FLAC__bool force_to_stdout = false, force_raw_format = false, delete_input = false, sector_align = false;
44 const char *cmdline_forced_outfilename = 0, *output_prefix = 0;
45 analysis_options aopts = { false, false };
46 int padding = -1;
47 unsigned max_lpc_order = 8;
48 unsigned qlp_coeff_precision = 0;
49 FLAC__uint64 skip = 0;
50 int format_is_big_endian = -1, format_is_unsigned_samples = false;
51 int format_channels = -1, format_bps = -1, format_sample_rate = -1;
52 int blocksize = -1, min_residual_partition_order = -1, max_residual_partition_order = -1, rice_parameter_search_dist = -1;
53 char requested_seek_points[50000]; /* @@@ bad MAGIC NUMBER */
54 int num_requested_seek_points = -1; /* -1 => no -S options were given, 0 => -S- was given */
55 FLAC__int32 align_reservoir_0[588], align_reservoir_1[588]; /* for carrying over samples from --sector-align */
56 FLAC__int32 *align_reservoir[2] = { align_reservoir_0, align_reservoir_1 };
57 unsigned align_reservoir_samples = 0; /* 0 .. 587 */
58
59 static const char *flac_suffix = ".flac", *ogg_suffix = ".ogg";
60
61 int main(int argc, char *argv[])
62 {
63         int i, retval = 0;
64         FLAC__bool mode_decode = false;
65
66         if(argc <= 1)
67                 return short_usage(0);
68
69         /* get the options */
70         for(i = 1; i < argc; i++) {
71                 if(argv[i][0] != '-' || argv[i][1] == 0)
72                         break;
73                 if(0 == strcmp(argv[i], "-H") || 0 == strcmp(argv[i], "--help"))
74                         return long_usage(0);
75                 else if(0 == strcmp(argv[i], "-d"))
76                         mode_decode = true;
77                 else if(0 == strcmp(argv[i], "-a")) {
78                         mode_decode = true;
79                         analyze = true;
80                 }
81                 else if(0 == strcmp(argv[i], "-t")) {
82                         mode_decode = true;
83                         test_only = true;
84                 }
85                 else if(0 == strcmp(argv[i], "-c"))
86                         force_to_stdout = true;
87                 else if(0 == strcmp(argv[i], "-F"))
88                         continue_through_decode_errors = true;
89                 else if(0 == strcmp(argv[i], "-F-"))
90                         continue_through_decode_errors = false;
91                 else if(0 == strcmp(argv[i], "-s"))
92                         verbose = false;
93                 else if(0 == strcmp(argv[i], "-s-"))
94                         verbose = true;
95                 else if(0 == strcmp(argv[i], "-S")) {
96                         if(++i >= argc)
97                                 return long_usage("ERROR: must specify a value with -S\n");
98                         if(num_requested_seek_points < 0)
99                                 num_requested_seek_points = 0;
100                         num_requested_seek_points++;
101                         strcat(requested_seek_points, argv[i]);
102                         strcat(requested_seek_points, "<");
103                 }
104                 else if(0 == strcmp(argv[i], "-S-")) {
105                         num_requested_seek_points = 0;
106                         requested_seek_points[0] = '\0';
107                 }
108                 else if(0 == strcmp(argv[i], "--delete-input-file"))
109                         delete_input = true;
110                 else if(0 == strcmp(argv[i], "--delete-input-file-"))
111                         delete_input = false;
112                 else if(0 == strcmp(argv[i], "--output-prefix")) {
113                         if(++i >= argc)
114                                 return long_usage("ERROR: must specify a value with --output-prefix\n");
115                         output_prefix = argv[i];
116                 }
117                 else if(0 == strcmp(argv[i], "--sector-align"))
118                         sector_align = true;
119                 else if(0 == strcmp(argv[i], "--sector-align-"))
120                         sector_align = false;
121                 else if(0 == strcmp(argv[i], "--skip")) {
122                         if(++i >= argc)
123                                 return long_usage("ERROR: must specify a value with --skip\n");
124                         skip = (FLAC__uint64)atoi(argv[i]); /* @@@ takes a pretty damn big file to overflow atoi() here, but it could happen */
125                 }
126                 else if(0 == strcmp(argv[i], "--lax"))
127                         lax = true;
128                 else if(0 == strcmp(argv[i], "--lax-"))
129                         lax = false;
130 #ifdef FLAC__HAS_OGG
131                 else if(0 == strcmp(argv[i], "--ogg"))
132                         use_ogg = true;
133                 else if(0 == strcmp(argv[i], "--ogg-"))
134                         use_ogg = false;
135 #endif
136                 else if(0 == strcmp(argv[i], "-b")) {
137                         if(++i >= argc)
138                                 return long_usage("ERROR: must specify a value with -b\n");
139                         blocksize = atoi(argv[i]);
140                 }
141                 else if(0 == strcmp(argv[i], "-e"))
142                         do_exhaustive_model_search = true;
143                 else if(0 == strcmp(argv[i], "-e-"))
144                         do_exhaustive_model_search = false;
145                 else if(0 == strcmp(argv[i], "-E"))
146                         do_escape_coding = true;
147                 else if(0 == strcmp(argv[i], "-E-"))
148                         do_escape_coding = false;
149                 else if(0 == strcmp(argv[i], "-l")) {
150                         if(++i >= argc)
151                                 return long_usage("ERROR: must specify a value with -l\n");
152                         max_lpc_order = atoi(argv[i]);
153                 }
154                 else if(0 == strcmp(argv[i], "-m")) {
155                         do_mid_side = true;
156                         loose_mid_side = false;
157                 }
158                 else if(0 == strcmp(argv[i], "-m-"))
159                         do_mid_side = loose_mid_side = false;
160                 else if(0 == strcmp(argv[i], "-M"))
161                         loose_mid_side = do_mid_side = true;
162                 else if(0 == strcmp(argv[i], "-M-"))
163                         loose_mid_side = do_mid_side = false;
164                 else if(0 == strcmp(argv[i], "-o")) {
165                         if(++i >= argc)
166                                 return long_usage("ERROR: must specify a value with -o\n");
167                         cmdline_forced_outfilename = argv[i];
168                 }
169                 else if(0 == strcmp(argv[i], "-p"))
170                         do_qlp_coeff_prec_search = true;
171                 else if(0 == strcmp(argv[i], "-p-"))
172                         do_qlp_coeff_prec_search = false;
173                 else if(0 == strcmp(argv[i], "-P")) {
174                         if(++i >= argc)
175                                 return long_usage("ERROR: must specify a value with -P\n");
176                         padding = atoi(argv[i]);
177                         if(padding < 0)
178                                 return long_usage("ERROR: argument to -P must be >= 0\n");
179                 }
180                 else if(0 == strcmp(argv[i], "-P-"))
181                         padding = -1;
182                 else if(0 == strcmp(argv[i], "-q")) {
183                         if(++i >= argc)
184                                 return long_usage("ERROR: must specify a value with -q\n");
185                         qlp_coeff_precision = atoi(argv[i]);
186                 }
187                 else if(0 == strcmp(argv[i], "-r")) {
188                         char *p;
189                         if(++i >= argc)
190                                 return long_usage("ERROR: must specify a value with -r\n");
191                         p = strchr(argv[i], ',');
192                         if(0 == p) {
193                                 min_residual_partition_order = 0;
194                                 max_residual_partition_order = atoi(argv[i]);
195                         }
196                         else {
197                                 min_residual_partition_order = atoi(argv[i]);
198                                 max_residual_partition_order = atoi(++p);
199                         }
200                 }
201                 else if(0 == strcmp(argv[i], "--old-unworking-do-not-use-R")) {
202                         if(++i >= argc)
203                                 return long_usage("ERROR: must specify a value with -R\n");
204                         rice_parameter_search_dist = atoi(argv[i]);
205                 }
206                 else if(0 == strcmp(argv[i], "-V"))
207                         verify = true;
208                 else if(0 == strcmp(argv[i], "-V-"))
209                         verify = false;
210                 else if(0 == strcmp(argv[i], "-fb"))
211                         format_is_big_endian = true;
212                 else if(0 == strcmp(argv[i], "-fl"))
213                         format_is_big_endian = false;
214                 else if(0 == strcmp(argv[i], "-fc")) {
215                         if(++i >= argc)
216                                 return long_usage("ERROR: must specify a value with -fc\n");
217                         format_channels = atoi(argv[i]);
218                 }
219                 else if(0 == strcmp(argv[i], "-fp")) {
220                         if(++i >= argc)
221                                 return long_usage("ERROR: must specify a value with -fp\n");
222                         format_bps = atoi(argv[i]);
223                 }
224                 else if(0 == strcmp(argv[i], "-fs")) {
225                         if(++i >= argc)
226                                 return long_usage("ERROR: must specify a value with -fs\n");
227                         format_sample_rate = atoi(argv[i]);
228                 }
229                 else if(0 == strcmp(argv[i], "-fu"))
230                         format_is_unsigned_samples = true;
231                 else if(0 == strcmp(argv[i], "-fr"))
232                         force_raw_format = true;
233                 else if(0 == strcmp(argv[i], "--a-rgp"))
234                         aopts.do_residual_gnuplot = true;
235                 else if(0 == strcmp(argv[i], "--a-rgp-"))
236                         aopts.do_residual_gnuplot = false;
237                 else if(0 == strcmp(argv[i], "--a-rtext"))
238                         aopts.do_residual_text = true;
239                 else if(0 == strcmp(argv[i], "--a-rtext-"))
240                         aopts.do_residual_text = false;
241                 else if(0 == strcmp(argv[i], "-0") || 0 == strcmp(argv[i], "--fast")) {
242                         do_exhaustive_model_search = false;
243                         do_escape_coding = false;
244                         do_mid_side = false;
245                         loose_mid_side = false;
246                         qlp_coeff_precision = 0;
247                         min_residual_partition_order = max_residual_partition_order = 2;
248                         rice_parameter_search_dist = 0;
249                         max_lpc_order = 0;
250                 }
251                 else if(0 == strcmp(argv[i], "-1")) {
252                         do_exhaustive_model_search = false;
253                         do_escape_coding = false;
254                         do_mid_side = true;
255                         loose_mid_side = true;
256                         qlp_coeff_precision = 0;
257                         min_residual_partition_order = max_residual_partition_order = 2;
258                         rice_parameter_search_dist = 0;
259                         max_lpc_order = 0;
260                 }
261                 else if(0 == strcmp(argv[i], "-2")) {
262                         do_exhaustive_model_search = false;
263                         do_escape_coding = false;
264                         do_mid_side = true;
265                         loose_mid_side = false;
266                         qlp_coeff_precision = 0;
267                         min_residual_partition_order = 0;
268                         max_residual_partition_order = 3;
269                         rice_parameter_search_dist = 0;
270                         max_lpc_order = 0;
271                 }
272                 else if(0 == strcmp(argv[i], "-3")) {
273                         do_exhaustive_model_search = false;
274                         do_escape_coding = false;
275                         do_mid_side = false;
276                         loose_mid_side = false;
277                         qlp_coeff_precision = 0;
278                         min_residual_partition_order = max_residual_partition_order = 3;
279                         rice_parameter_search_dist = 0;
280                         max_lpc_order = 6;
281                 }
282                 else if(0 == strcmp(argv[i], "-4")) {
283                         do_exhaustive_model_search = false;
284                         do_escape_coding = false;
285                         do_mid_side = true;
286                         loose_mid_side = true;
287                         qlp_coeff_precision = 0;
288                         min_residual_partition_order = max_residual_partition_order = 3;
289                         rice_parameter_search_dist = 0;
290                         max_lpc_order = 8;
291                 }
292                 else if(0 == strcmp(argv[i], "-5")) {
293                         do_exhaustive_model_search = false;
294                         do_escape_coding = false;
295                         do_mid_side = true;
296                         loose_mid_side = false;
297                         qlp_coeff_precision = 0;
298                         min_residual_partition_order = max_residual_partition_order = 3;
299                         rice_parameter_search_dist = 0;
300                         max_lpc_order = 8;
301                 }
302                 else if(0 == strcmp(argv[i], "-6")) {
303                         do_exhaustive_model_search = false;
304                         do_escape_coding = false;
305                         do_mid_side = true;
306                         loose_mid_side = false;
307                         qlp_coeff_precision = 0;
308                         min_residual_partition_order = 0;
309                         max_residual_partition_order = 4;
310                         rice_parameter_search_dist = 0;
311                         max_lpc_order = 8;
312                 }
313                 else if(0 == strcmp(argv[i], "-7")) {
314                         do_exhaustive_model_search = true;
315                         do_escape_coding = false;
316                         do_mid_side = true;
317                         loose_mid_side = false;
318                         qlp_coeff_precision = 0;
319                         min_residual_partition_order = 0;
320                         max_residual_partition_order = 6;
321                         rice_parameter_search_dist = 0;
322                         max_lpc_order = 8;
323                 }
324                 else if(0 == strcmp(argv[i], "-8") || 0 == strcmp(argv[i], "--best")) {
325                         do_exhaustive_model_search = true;
326                         do_escape_coding = false;
327                         do_mid_side = true;
328                         loose_mid_side = false;
329                         qlp_coeff_precision = 0;
330                         min_residual_partition_order = 0;
331                         max_residual_partition_order = 6;
332                         rice_parameter_search_dist = 0;
333                         max_lpc_order = 12;
334                 }
335                 else if(0 == strcmp(argv[i], "--super-secret-impractical-compression-level")) {
336                         do_exhaustive_model_search = true;
337                         do_escape_coding = true;
338                         do_mid_side = true;
339                         loose_mid_side = false;
340                         do_qlp_coeff_prec_search = true;
341                         min_residual_partition_order = 0;
342                         max_residual_partition_order = 16;
343                         rice_parameter_search_dist = 0;
344                         max_lpc_order = 32;
345                 }
346                 else if(isdigit((int)(argv[i][1]))) {
347                         return long_usage("ERROR: compression level '%s' is reserved\n", argv[i]);
348                 }
349                 else {
350                         return long_usage("ERROR: invalid option '%s'\n", argv[i]);
351                 }
352         }
353
354         /* tweak options; validate the values */
355         if(!mode_decode) {
356                 if(blocksize < 0) {
357                         if(max_lpc_order == 0)
358                                 blocksize = 1152;
359                         else
360                                 blocksize = 4608;
361                 }
362                 if(max_residual_partition_order < 0) {
363                         if(blocksize <= 1152)
364                                 max_residual_partition_order = 2;
365                         else if(blocksize <= 2304)
366                                 max_residual_partition_order = 3;
367                         else if(blocksize <= 4608)
368                                 max_residual_partition_order = 3;
369                         else
370                                 max_residual_partition_order = 4;
371                         min_residual_partition_order = max_residual_partition_order;
372                 }
373                 if(rice_parameter_search_dist < 0) {
374                         rice_parameter_search_dist = 0;
375                 }
376         }
377         else {
378                 if(test_only) {
379                         if(skip > 0)
380                                 return long_usage("ERROR: --skip is not allowed in test mode\n");
381                 }
382         }
383
384         FLAC__ASSERT(blocksize >= 0 || mode_decode);
385
386         if(format_channels >= 0) {
387                 if(format_channels == 0 || (unsigned)format_channels > FLAC__MAX_CHANNELS)
388                         return long_usage("ERROR: invalid number of channels '%u', must be > 0 and <= %u\n", format_channels, FLAC__MAX_CHANNELS);
389         }
390         if(format_bps >= 0) {
391                 if(format_bps != 8 && format_bps != 16 && format_bps != 24)
392                         return long_usage("ERROR: invalid bits per sample '%u' (must be 8/16/24)\n", format_bps);
393         }
394         if(format_sample_rate >= 0) {
395                 if(!FLAC__format_is_valid_sample_rate(format_sample_rate))
396                         return long_usage("ERROR: invalid sample rate '%u', must be > 0 and <= %u\n", format_sample_rate, FLAC__MAX_SAMPLE_RATE);
397         }
398         if(!mode_decode && ((unsigned)blocksize < FLAC__MIN_BLOCK_SIZE || (unsigned)blocksize > FLAC__MAX_BLOCK_SIZE)) {
399                 return long_usage("ERROR: invalid blocksize '%u', must be >= %u and <= %u\n", (unsigned)blocksize, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE);
400         }
401         if(qlp_coeff_precision > 0 && qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION) {
402                 return long_usage("ERROR: invalid value for -q '%u', must be 0 or >= %u\n", qlp_coeff_precision, FLAC__MIN_QLP_COEFF_PRECISION);
403         }
404
405         if(sector_align) {
406                 if(mode_decode)
407                         return long_usage("ERROR: --sector-align only allowed for encoding\n");
408                 else if(skip > 0)
409                         return long_usage("ERROR: --sector-align not allowed with --skip\n");
410                 else if(format_channels >= 0 && format_channels != 2)
411                         return long_usage("ERROR: --sector-align can only be done with stereo input\n");
412                 else if(format_sample_rate >= 0 && format_sample_rate != 2)
413                         return long_usage("ERROR: --sector-align can only be done with sample rate of 44100\n");
414         }
415         if(argc - i > 1 && cmdline_forced_outfilename) {
416                 return long_usage("ERROR: -o cannot be used with multiple files\n");
417         }
418         if(cmdline_forced_outfilename && output_prefix) {
419                 return long_usage("ERROR: --output-prefix conflicts with -o\n");
420         }
421
422         if(verbose) {
423                 fprintf(stderr, "\n");
424                 fprintf(stderr, "flac %s, Copyright (C) 2000,2001,2002 Josh Coalson\n", FLAC__VERSION_STRING);
425                 fprintf(stderr, "flac comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are\n");
426                 fprintf(stderr, "welcome to redistribute it under certain conditions.  Type `flac' for details.\n\n");
427
428                 if(!mode_decode) {
429                         char padopt[16];
430                         if(padding < 0)
431                                 strcpy(padopt, "-");
432                         else
433                                 sprintf(padopt, " %d", padding);
434                         fprintf(stderr,
435                                 "options:%s%s"
436 #ifdef FLAC__HAS_OGG
437                                 "%s"
438 #endif
439                                 "%s -P%s -b %u%s -l %u%s%s%s -q %u -r %u,%u -R %u%s\n",
440                                 delete_input?" --delete-input-file":"", sector_align?" --sector-align":"",
441 #ifdef FLAC__HAS_OGG
442                                 use_ogg?" --ogg":"",
443 #endif
444                                 lax?" --lax":"",
445                                 padopt, (unsigned)blocksize, loose_mid_side?" -M":do_mid_side?" -m":"", max_lpc_order,
446                                 do_exhaustive_model_search?" -e":"", do_escape_coding?" -E":"", do_qlp_coeff_prec_search?" -p":"",
447                                 qlp_coeff_precision,
448                                 (unsigned)min_residual_partition_order, (unsigned)max_residual_partition_order, (unsigned)rice_parameter_search_dist,
449                                 verify? " -V":""
450                         );
451                 }
452         }
453
454         if(mode_decode) {
455                 FLAC__bool first = true;
456
457                 if(i == argc) {
458                         retval = decode_file("-", 0);
459                 }
460                 else {
461                         if(i + 1 != argc)
462                                 cmdline_forced_outfilename = 0;
463                         for(retval = 0; i < argc && retval == 0; i++) {
464                                 if(0 == strcmp(argv[i], "-") && !first)
465                                         continue;
466                                 retval = decode_file(argv[i], 0);
467                                 first = false;
468                         }
469                 }
470         }
471         else { /* encode */
472                 FLAC__bool first = true;
473
474                 if(i == argc) {
475                         retval = encode_file("-", 0, true);
476                 }
477                 else {
478                         if(i + 1 != argc)
479                                 cmdline_forced_outfilename = 0;
480                         for(retval = 0; i < argc && retval == 0; i++) {
481                                 if(0 == strcmp(argv[i], "-") && !first)
482                                         continue;
483                                 retval = encode_file(argv[i], 0, i == (argc-1));
484                                 first = false;
485                         }
486                 }
487         }
488
489         return retval;
490 }
491
492 static void usage_header()
493 {
494         fprintf(stderr, "===============================================================================\n");
495         fprintf(stderr, "flac - Command-line FLAC encoder/decoder version %s\n", FLAC__VERSION_STRING);
496         fprintf(stderr, "Copyright (C) 2000,2001,2002  Josh Coalson\n");
497         fprintf(stderr, "\n");
498         fprintf(stderr, "This program is free software; you can redistribute it and/or\n");
499         fprintf(stderr, "modify it under the terms of the GNU General Public License\n");
500         fprintf(stderr, "as published by the Free Software Foundation; either version 2\n");
501         fprintf(stderr, "of the License, or (at your option) any later version.\n");
502         fprintf(stderr, "\n");
503         fprintf(stderr, "This program is distributed in the hope that it will be useful,\n");
504         fprintf(stderr, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
505         fprintf(stderr, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
506         fprintf(stderr, "GNU General Public License for more details.\n");
507         fprintf(stderr, "\n");
508         fprintf(stderr, "You should have received a copy of the GNU General Public License\n");
509         fprintf(stderr, "along with this program; if not, write to the Free Software\n");
510         fprintf(stderr, "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n");
511         fprintf(stderr, "===============================================================================\n");
512 }
513
514 int short_usage(const char *message, ...)
515 {
516         va_list args;
517
518         if(message) {
519                 va_start(args, message);
520
521                 (void) vfprintf(stderr, message, args);
522
523                 va_end(args);
524
525         }
526         usage_header();
527         fprintf(stderr, "\n");
528         fprintf(stderr, "This is the short help; for full help use 'flac --help'\n");
529         fprintf(stderr, "\n");
530         fprintf(stderr, "To encode:\n");
531         fprintf(stderr, "  flac [-#] [infile [...]]\n");
532         fprintf(stderr, "\n");
533         fprintf(stderr, "  -# is -0 (fastest compression) to -8 (highest compression); -5 is the default\n");
534         fprintf(stderr, "\n");
535         fprintf(stderr, "To decode:\n");
536         fprintf(stderr, "  flac -d [infile [...]]\n");
537         fprintf(stderr, "\n");
538         fprintf(stderr, "To test:\n");
539         fprintf(stderr, "  flac -t [infile [...]]\n");
540
541         return message? 1 : 0;
542 }
543
544 int long_usage(const char *message, ...)
545 {
546         FILE *out = (message? stderr : stdout);
547         va_list args;
548
549         if(message) {
550                 va_start(args, message);
551
552                 (void) vfprintf(stderr, message, args);
553
554                 va_end(args);
555
556         }
557         usage_header();
558         fprintf(out, "Usage:\n");
559         fprintf(out, "  flac [options] [infile [...]]\n");
560         fprintf(out, "\n");
561         fprintf(out, "For encoding:\n");
562         fprintf(out, "  the input file(s) may be a PCM RIFF WAVE file or raw samples\n");
563         fprintf(out, "  the output file(s) will be in FLAC format\n");
564         fprintf(out, "For decoding, the reverse is true\n");
565         fprintf(out, "\n");
566         fprintf(out, "A single 'infile' may be - for stdin.  No 'infile' implies stdin.  Use of\n");
567         fprintf(out, "stdin implies -c (write to stdout).  Normally you should use:\n");
568         fprintf(out, "   flac [options] -o outfilename  or  flac -d [options] -o outfilename\n");
569         fprintf(out, "instead of:\n");
570         fprintf(out, "   flac [options] > outfilename   or  flac -d [options] > outfilename\n");
571         fprintf(out, "since the former allows flac to seek backwards to write the STREAMINFO or\n");
572         fprintf(out, "RIFF WAVE header contents when necessary.\n");
573         fprintf(out, "\n");
574         fprintf(out, "flac checks for the presence of a RIFF WAVE header to decide whether or not\n");
575         fprintf(out, "to treat an input file as WAVE format or raw samples.  If any infile is raw\n");
576         fprintf(out, "you must specify the format options {-fb|fl} -fc -fp and -fs, which will\n");
577         fprintf(out, "apply to all raw files.  You can force WAVE files to be treated as a raw files\n");
578         fprintf(out, "using -fr.\n");
579         fprintf(out, "\n");
580         fprintf(out, "generic options:\n");
581         fprintf(out, "  -d : decode (default behavior is encode)\n");
582         fprintf(out, "  -t : test (same as -d except no decoded file is written)\n");
583         fprintf(out, "  -a : analyze (same as -d except an analysis file is written)\n");
584         fprintf(out, "  -c : write output to stdout\n");
585         fprintf(out, "  -s : silent (do not write runtime encode/decode statistics)\n");
586         fprintf(out, "  -o filename : force the output file name (usually flac just changes the\n");
587         fprintf(out, "                extension)\n");
588         fprintf(out, "  --output-prefix string : prefix each output file name with the given string.\n");
589         fprintf(out, "    This can be useful for encoding/decoding files to a different directory.\n");
590         fprintf(out, "    Make sure if your string is a path name that it ends with a '/' slash.\n");
591         fprintf(out, "  --delete-input-file : deletes the input file after a successful encode/decode\n");
592         fprintf(out, "  --skip samples : can be used both for encoding and decoding\n");
593         fprintf(out, "analyze options:\n");
594         fprintf(out, "  --a-rtext : include residual signal in text output\n");
595         fprintf(out, "  --a-rgp : generate gnuplot files of residual distribution of each subframe\n");
596         fprintf(out, "decoding options:\n");
597         fprintf(out, "  -F : force decoder to continue decoding through stream errors\n");
598         fprintf(out, "encoding options:\n");
599 #ifdef FLAC__HAS_OGG
600         fprintf(out, "  --ogg : output Ogg-FLAC stream instead of native FLAC\n");
601 #endif
602         fprintf(out, "  --lax : allow encoder to generate non-Subset files\n");
603         fprintf(out, "  --sector-align : align encoding of multiple files on sector boundaries\n");
604         fprintf(out, "  -S { # | X | #x } : include a point or points in a SEEKTABLE\n");
605         fprintf(out, "       #  : a specific sample number for a seek point\n");
606         fprintf(out, "       X  : a placeholder point (always goes at the end of the SEEKTABLE)\n");
607         fprintf(out, "       #x : # evenly spaced seekpoints, the first being at sample 0\n");
608         fprintf(out, "     You may use many -S options; the resulting SEEKTABLE will be the unique-\n");
609         fprintf(out, "           ified union of all such values.\n");
610         fprintf(out, "     With no -S options, flac defaults to '-S 100x'.  Use -S- for no SEEKTABLE.\n");
611         fprintf(out, "     Note: -S #x will not work if the encoder can't determine the input size\n");
612         fprintf(out, "           before starting.\n");
613         fprintf(out, "     Note: if you use -S # and # is >= samples in the input, there will be\n");
614         fprintf(out, "           either no seek point entered (if the input size is determinable\n");
615         fprintf(out, "           before encoding starts) or a placeholder point (if input size is not\n");
616         fprintf(out, "           determinable)\n");
617         fprintf(out, "  -P # : write a PADDING block of length # (goes after SEEKTABLE)\n");
618         fprintf(out, "         (# must be >= 0; default is -P-).  Note that the overall size in bytes\n");
619         fprintf(out, "         of the PADDING block will be # + 4 because of the metadata header.\n");
620         fprintf(out, "  -b # : specify blocksize in samples; default is 1152 for -l 0, else 4608;\n");
621         fprintf(out, "         must be 192/576/1152/2304/4608/256/512/1024/2048/4096/8192/16384/32768\n");
622         fprintf(out, "         (unless --lax is used)\n");
623         fprintf(out, "  -m   : try mid-side coding for each frame (stereo input only)\n");
624         fprintf(out, "  -M   : adaptive mid-side coding for all frames (stereo input only)\n");
625         fprintf(out, "  -0 .. -8 : fastest compression .. highest compression, default is -5\n");
626         fprintf(out, "             these are synonyms for other options:\n");
627         fprintf(out, "  -0   : synonymous with -l 0 -b 1152 -r 2,2\n");
628         fprintf(out, "  -1   : synonymous with -l 0 -b 1152 -M -r 2,2\n");
629         fprintf(out, "  -2   : synonymous with -l 0 -b 1152 -m -r 3\n");
630         fprintf(out, "  -3   : synonymous with -l 6 -b 4608 -r 3,3\n");
631         fprintf(out, "  -4   : synonymous with -l 8 -b 4608 -M -r 3,3\n");
632         fprintf(out, "  -5   : synonymous with -l 8 -b 4608 -m -r 3,3\n");
633         fprintf(out, "  -6   : synonymous with -l 8 -b 4608 -m -r 4\n");
634         fprintf(out, "  -7   : synonymous with -l 8 -b 4608 -m -e -r 6\n");
635         fprintf(out, "  -8   : synonymous with -l 12 -b 4608 -m -e -r 6\n");
636         fprintf(out, "  --fast, --best : synonymous with -0 and -8 respectively\n");
637         fprintf(out, "  -e   : do exhaustive model search (expensive!)\n");
638         fprintf(out, "  -E   : include escape coding in the entropy coder\n");
639         fprintf(out, "  -l # : specify max LPC order; 0 => use only fixed predictors\n");
640         fprintf(out, "  -p   : do exhaustive search of LP coefficient quantization (expensive!);\n");
641         fprintf(out, "         overrides -q, does nothing if using -l 0\n");
642         fprintf(out, "  -q # : specify precision in bits of quantized linear-predictor coefficients;\n");
643         fprintf(out, "         0 => let encoder decide (min is %u, default is -q 0)\n", FLAC__MIN_QLP_COEFF_PRECISION);
644         fprintf(out, "  -r [#,]# : [min,]max residual partition order (# is 0..16; min defaults to 0;\n");
645         fprintf(out, "         default is -r 0; above 4 doesn't usually help much)\n");
646 #if 0
647 @@@ removed because it doesnt work yet and is too dangerous for users
648         fprintf(out, "  -R # : Rice parameter search distance (# is 0..32; above 2 doesn't help much)\n");
649 #endif
650         fprintf(out, "  -V   : verify a correct encoding by decoding the output in parallel and\n");
651         fprintf(out, "         comparing to the original\n");
652         fprintf(out, "  -S-, -P-, -m-, -M-, -e-, -E-, -p-, -V-, --delete-input-file-,%s --lax-,\n",
653 #ifdef FLAC__HAS_OGG
654                 " --ogg-,"
655 #else
656                 ""
657 #endif
658         );
659         fprintf(out, "  --sector-align- can all be used to turn off a particular option\n");
660         fprintf(out, "format options:\n");
661         fprintf(out, "  -fb | -fl : big-endian | little-endian byte order\n");
662         fprintf(out, "  -fc channels\n");
663         fprintf(out, "  -fp bits_per_sample\n");
664         fprintf(out, "  -fs sample_rate : in Hz\n");
665         fprintf(out, "  -fu : unsigned samples (default is signed)\n");
666         fprintf(out, "  -fr : force input to be treated as raw samples\n");
667
668         return message? 1 : 0;
669 }
670
671 int encode_file(const char *infilename, const char *forced_outfilename, FLAC__bool is_last_file)
672 {
673         FILE *encode_infile;
674         char outfilename[4096]; /* @@@ bad MAGIC NUMBER */
675         char *p;
676         FLAC__byte lookahead[12];
677         unsigned lookahead_length = 0;
678         FLAC__bool treat_as_wave = false;
679         int retval;
680         long infilesize;
681         encode_options_t common_options;
682
683         if(0 == strcmp(infilename, "-")) {
684                 infilesize = -1;
685                 encode_infile = file__get_binary_stdin();
686         }
687         else {
688                 infilesize = flac__file_get_filesize(infilename);
689                 if(0 == (encode_infile = fopen(infilename, "rb"))) {
690                         fprintf(stderr, "ERROR: can't open input file %s\n", infilename);
691                         return 1;
692                 }
693         }
694
695         if(!force_raw_format) {
696                 /* first set format based on name */
697                 if(0 == strcasecmp(infilename+(strlen(infilename)-4), ".wav"))
698                         treat_as_wave = true;
699                 else
700                         treat_as_wave = false;
701
702                 /* attempt to guess the file type based on the first 12 bytes */
703                 if((lookahead_length = fread(lookahead, 1, 12, encode_infile)) < 12) {
704                         if(treat_as_wave)
705                                 fprintf(stderr, "WARNING: %s is not a WAVE file, treating as a raw file\n", infilename);
706                         treat_as_wave = false;
707                 }
708                 else {
709                         if(strncmp(lookahead, "RIFF", 4) || strncmp(lookahead+8, "WAVE", 4)) {
710                                 if(treat_as_wave)
711                                         fprintf(stderr, "WARNING: %s is not a WAVE file, treating as a raw file\n", infilename);
712                                 treat_as_wave = false;
713                         }
714                         else
715                                 treat_as_wave = true;
716                 }
717         }
718
719         if(sector_align && !treat_as_wave && infilesize < 0) {
720                 fprintf(stderr, "ERROR: can't --sector-align when the input size is unknown\n");
721                 return 1;
722         }
723
724         if(!treat_as_wave) {
725                 if(format_is_big_endian < 0 || format_channels < 0 || format_bps < 0 || format_sample_rate < 0)
726                         return long_usage("ERROR: for encoding a raw file you must specify { -fb or -fl }, -fc, -fp, and -fs\n");
727         }
728
729         if(encode_infile == stdin || force_to_stdout)
730                 strcpy(outfilename, "-");
731         else {
732                 const char *suffix = (use_ogg? ogg_suffix : flac_suffix);
733                 strcpy(outfilename, output_prefix? output_prefix : "");
734                 strcat(outfilename, infilename);
735                 if(0 == (p = strrchr(outfilename, '.')))
736                         strcat(outfilename, suffix);
737                 else {
738                         if(0 == strcmp(p, suffix)) {
739                                 strcpy(p, "_new");
740                                 strcat(p, suffix);
741                         }
742                         else
743                                 strcpy(p, suffix);
744                 }
745         }
746         if(0 == forced_outfilename)
747                 forced_outfilename = outfilename;
748         if(0 != cmdline_forced_outfilename)
749                 forced_outfilename = cmdline_forced_outfilename;
750
751         common_options.verbose = verbose;
752         common_options.skip = skip;
753         common_options.verify = verify;
754 #ifdef FLAC__HAS_OGG
755         common_options.use_ogg = use_ogg;
756 #endif
757         common_options.lax = lax;
758         common_options.do_mid_side = do_mid_side;
759         common_options.loose_mid_side = loose_mid_side;
760         common_options.do_exhaustive_model_search = do_exhaustive_model_search;
761         common_options.do_escape_coding = do_escape_coding;
762         common_options.do_qlp_coeff_prec_search = do_qlp_coeff_prec_search;
763         common_options.min_residual_partition_order = min_residual_partition_order;
764         common_options.max_residual_partition_order = max_residual_partition_order;
765         common_options.rice_parameter_search_dist = rice_parameter_search_dist;
766         common_options.max_lpc_order = max_lpc_order;
767         common_options.blocksize = (unsigned)blocksize;
768         common_options.qlp_coeff_precision = qlp_coeff_precision;
769         common_options.padding = padding;
770         common_options.requested_seek_points = requested_seek_points;
771         common_options.num_requested_seek_points = num_requested_seek_points;
772
773         if(treat_as_wave) {
774                 wav_encode_options_t options;
775
776                 options.common = common_options;
777                 options.is_last_file = is_last_file;
778                 options.align_reservoir = align_reservoir;
779                 options.align_reservoir_samples = &align_reservoir_samples;
780                 options.sector_align = sector_align;
781
782                 retval = flac__encode_wav(encode_infile, infilesize, infilename, forced_outfilename, lookahead, lookahead_length, options);
783         }
784         else {
785                 raw_encode_options_t options;
786
787                 options.common = common_options;
788                 options.is_big_endian = format_is_big_endian;
789                 options.is_unsigned_samples = format_is_unsigned_samples;
790                 options.channels = format_channels;
791                 options.bps = format_bps;
792                 options.sample_rate = format_sample_rate;
793
794                 retval = flac__encode_raw(encode_infile, infilesize, infilename, forced_outfilename, lookahead, lookahead_length, options);
795         }
796
797         if(retval == 0 && strcmp(infilename, "-")) {
798                 if(strcmp(forced_outfilename, "-"))
799                         flac__file_copy_metadata(infilename, forced_outfilename);
800                 if(delete_input)
801                         unlink(infilename);
802         }
803
804         return 0;
805 }
806
807 int decode_file(const char *infilename, const char *forced_outfilename)
808 {
809         static const char *suffixes[] = { ".wav", ".raw", ".ana" };
810         char outfilename[4096]; /* @@@ bad MAGIC NUMBER */
811         char *p;
812         int retval;
813         FLAC__bool treat_as_ogg = false;
814         decode_options_t common_options;
815
816         if(!test_only && !analyze) {
817                 if(force_raw_format && format_is_big_endian < 0)
818                         return long_usage("ERROR: for decoding to a raw file you must specify -fb or -fl\n");
819         }
820
821         if(0 == strcmp(infilename, "-") || force_to_stdout)
822                 strcpy(outfilename, "-");
823         else {
824                 const char *suffix = suffixes[analyze? 2 : force_raw_format? 1 : 0];
825                 strcpy(outfilename, output_prefix? output_prefix : "");
826                 strcat(outfilename, infilename);
827                 if(0 == (p = strrchr(outfilename, '.')))
828                         strcat(outfilename, suffix);
829                 else {
830                         if(0 == strcmp(p, suffix)) {
831                                 strcpy(p, "_new");
832                                 strcat(p, suffix);
833                         }
834                         else
835                                 strcpy(p, suffix);
836                 }
837         }
838         if(0 == forced_outfilename)
839                 forced_outfilename = outfilename;
840         if(0 != cmdline_forced_outfilename)
841                 forced_outfilename = cmdline_forced_outfilename;
842
843         if(use_ogg)
844                 treat_as_ogg = true;
845         else if(0 == strcasecmp(infilename+(strlen(infilename)-4), ".ogg"))
846                 treat_as_ogg = true;
847         else
848                 treat_as_ogg = false;
849
850 #ifndef FLAC__HAS_OGG
851         if(treat_as_ogg) {
852                 fprintf(stderr, "%s: Ogg support has not been built into this copy of flac\n", infilename);
853                 return 1;
854         }
855 #endif
856
857         common_options.verbose = verbose;
858         common_options.continue_through_decode_errors = continue_through_decode_errors;
859 #ifdef FLAC__HAS_OGG
860         common_options.is_ogg = treat_as_ogg;
861 #endif
862         common_options.skip = skip;
863
864         if(!force_raw_format) {
865                 wav_decode_options_t options;
866
867                 options.common = common_options;
868
869                 retval = flac__decode_wav(infilename, test_only? 0 : forced_outfilename, analyze, aopts, options);
870         }
871         else {
872                 raw_decode_options_t options;
873
874                 options.common = common_options;
875                 options.is_big_endian = format_is_big_endian;
876                 options.is_unsigned_samples = format_is_unsigned_samples;
877
878                 retval = flac__decode_raw(infilename, test_only? 0 : forced_outfilename, analyze, aopts, options);
879         }
880
881         if(retval == 0 && strcmp(infilename, "-")) {
882                 if(strcmp(forced_outfilename, "-"))
883                         flac__file_copy_metadata(infilename, forced_outfilename);
884                 if(delete_input)
885                         unlink(infilename);
886         }
887
888         return 0;
889 }