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