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