add --delete-input-file flag
[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 #include <unistd.h> /* for unlink() */
25 #include "FLAC/all.h"
26 #include "analyze.h"
27 #include "decode.h"
28 #include "encode.h"
29 #include "file.h"
30
31 static int usage(const char *message, ...);
32 static int encode_file(const char *infilename, const char *forced_outfilename);
33 static int decode_file(const char *infilename, const char *forced_outfilename);
34
35 bool verify = false, verbose = true, lax = false, test_only = false, analyze = false;
36 bool do_mid_side = true, loose_mid_side = false, do_exhaustive_model_search = false, do_qlp_coeff_prec_search = false;
37 bool force_to_stdout = false, delete_input = false;
38 analysis_options aopts = { false, false };
39 unsigned padding = 0;
40 unsigned max_lpc_order = 8;
41 unsigned qlp_coeff_precision = 0;
42 uint64 skip = 0;
43 int format_is_wave = -1, format_is_big_endian = -1, format_is_unsigned_samples = false;
44 int format_channels = -1, format_bps = -1, format_sample_rate = -1;
45 int blocksize = -1, min_residual_partition_order = -1, max_residual_partition_order = -1, rice_parameter_search_dist = -1;
46 char requested_seek_points[50000]; /* @@@ bad MAGIC NUMBER */
47 int num_requested_seek_points = -1; /* -1 => no -S options were given, 0 => -S- was given */
48
49 int main(int argc, char *argv[])
50 {
51         int i, retval = 0;
52         bool mode_decode = false;
53
54         if(argc <= 1)
55                 return usage(0);
56
57         /* get the options */
58         for(i = 1; i < argc; i++) {
59                 if(argv[i][0] != '-' || argv[i][1] == 0)
60                         break;
61                 if(0 == strcmp(argv[i], "-d"))
62                         mode_decode = true;
63                 else if(0 == strcmp(argv[i], "-a")) {
64                         mode_decode = true;
65                         analyze = true;
66                 }
67                 else if(0 == strcmp(argv[i], "-t")) {
68                         mode_decode = true;
69                         test_only = true;
70                 }
71                 else if(0 == strcmp(argv[i], "-c"))
72                         force_to_stdout = true;
73                 else if(0 == strcmp(argv[i], "-s"))
74                         verbose = false;
75                 else if(0 == strcmp(argv[i], "-s-"))
76                         verbose = true;
77                 else if(0 == strcmp(argv[i], "-S")) {
78                         if(num_requested_seek_points < 0)
79                                 num_requested_seek_points = 0;
80                         num_requested_seek_points++;
81                         strcat(requested_seek_points, argv[++i]);
82                         strcat(requested_seek_points, "<");
83                 }
84                 else if(0 == strcmp(argv[i], "-S-")) {
85                         num_requested_seek_points = 0;
86                         requested_seek_points[0] = '\0';
87                 }
88                 else if(0 == strcmp(argv[i], "--delete-input-file"))
89                         delete_input = true;
90                 else if(0 == strcmp(argv[i], "--delete-input-file-"))
91                         delete_input = false;
92                 else if(0 == strcmp(argv[i], "--skip"))
93                         skip = (uint64)atoi(argv[++i]); /* @@@ takes a pretty damn big file to overflow atoi() here, but it could happen */
94                 else if(0 == strcmp(argv[i], "--lax"))
95                         lax = true;
96                 else if(0 == strcmp(argv[i], "--lax-"))
97                         lax = false;
98                 else if(0 == strcmp(argv[i], "-b"))
99                         blocksize = atoi(argv[++i]);
100                 else if(0 == strcmp(argv[i], "-e"))
101                         do_exhaustive_model_search = true;
102                 else if(0 == strcmp(argv[i], "-e-"))
103                         do_exhaustive_model_search = false;
104                 else if(0 == strcmp(argv[i], "-l"))
105                         max_lpc_order = atoi(argv[++i]);
106                 else if(0 == strcmp(argv[i], "-m")) {
107                         do_mid_side = true;
108                         loose_mid_side = false;
109                 }
110                 else if(0 == strcmp(argv[i], "-m-"))
111                         do_mid_side = loose_mid_side = false;
112                 else if(0 == strcmp(argv[i], "-M"))
113                         loose_mid_side = do_mid_side = true;
114                 else if(0 == strcmp(argv[i], "-M-"))
115                         loose_mid_side = do_mid_side = false;
116                 else if(0 == strcmp(argv[i], "-p"))
117                         do_qlp_coeff_prec_search = true;
118                 else if(0 == strcmp(argv[i], "-p-"))
119                         do_qlp_coeff_prec_search = false;
120                 else if(0 == strcmp(argv[i], "-P"))
121                         padding = atoi(argv[++i]);
122                 else if(0 == strcmp(argv[i], "-q"))
123                         qlp_coeff_precision = atoi(argv[++i]);
124                 else if(0 == strcmp(argv[i], "-r")) {
125                         char *p = strchr(argv[++i], ',');
126                         if(0 == p) {
127                                 min_residual_partition_order = 0;
128                                 max_residual_partition_order = atoi(argv[i]);
129                         }
130                         else {
131                                 min_residual_partition_order = atoi(argv[i]);
132                                 max_residual_partition_order = atoi(++p);
133                         }
134                 }
135                 else if(0 == strcmp(argv[i], "-R"))
136                         rice_parameter_search_dist = atoi(argv[++i]);
137                 else if(0 == strcmp(argv[i], "-V"))
138                         verify = true;
139                 else if(0 == strcmp(argv[i], "-V-"))
140                         verify = false;
141                 else if(0 == strcmp(argv[i], "-fb"))
142                         format_is_big_endian = true;
143                 else if(0 == strcmp(argv[i], "-fl"))
144                         format_is_big_endian = false;
145                 else if(0 == strcmp(argv[i], "-fc"))
146                         format_channels = atoi(argv[++i]);
147                 else if(0 == strcmp(argv[i], "-fp"))
148                         format_bps = atoi(argv[++i]);
149                 else if(0 == strcmp(argv[i], "-fs"))
150                         format_sample_rate = atoi(argv[++i]);
151                 else if(0 == strcmp(argv[i], "-fu"))
152                         format_is_unsigned_samples = true;
153                 else if(0 == strcmp(argv[i], "-fr"))
154                         format_is_wave = false;
155                 else if(0 == strcmp(argv[i], "-fw"))
156                         format_is_wave = true;
157                 else if(0 == strcmp(argv[i], "--a-rgp"))
158                         aopts.do_residual_gnuplot = true;
159                 else if(0 == strcmp(argv[i], "--a-rgp-"))
160                         aopts.do_residual_gnuplot = false;
161                 else if(0 == strcmp(argv[i], "--a-rtext"))
162                         aopts.do_residual_text = true;
163                 else if(0 == strcmp(argv[i], "--a-rtext-"))
164                         aopts.do_residual_text = false;
165                 else if(0 == strcmp(argv[i], "-0")) {
166                         do_exhaustive_model_search = false;
167                         do_mid_side = false;
168                         loose_mid_side = false;
169                         qlp_coeff_precision = 0;
170                         min_residual_partition_order = max_residual_partition_order = 2;
171                         rice_parameter_search_dist = 0;
172                         max_lpc_order = 0;
173                 }
174                 else if(0 == strcmp(argv[i], "-1")) {
175                         do_exhaustive_model_search = false;
176                         do_mid_side = true;
177                         loose_mid_side = true;
178                         qlp_coeff_precision = 0;
179                         min_residual_partition_order = max_residual_partition_order = 2;
180                         rice_parameter_search_dist = 0;
181                         max_lpc_order = 0;
182                 }
183                 else if(0 == strcmp(argv[i], "-2")) {
184                         do_exhaustive_model_search = false;
185                         do_mid_side = true;
186                         loose_mid_side = false;
187                         qlp_coeff_precision = 0;
188                         min_residual_partition_order = 0;
189                         max_residual_partition_order = 3;
190                         rice_parameter_search_dist = 0;
191                         max_lpc_order = 0;
192                 }
193                 else if(0 == strcmp(argv[i], "-3")) {
194                         do_exhaustive_model_search = false;
195                         do_mid_side = false;
196                         loose_mid_side = false;
197                         qlp_coeff_precision = 0;
198                         min_residual_partition_order = max_residual_partition_order = 3;
199                         rice_parameter_search_dist = 0;
200                         max_lpc_order = 6;
201                 }
202                 else if(0 == strcmp(argv[i], "-4")) {
203                         do_exhaustive_model_search = false;
204                         do_mid_side = true;
205                         loose_mid_side = true;
206                         qlp_coeff_precision = 0;
207                         min_residual_partition_order = max_residual_partition_order = 3;
208                         rice_parameter_search_dist = 0;
209                         max_lpc_order = 8;
210                 }
211                 else if(0 == strcmp(argv[i], "-5")) {
212                         do_exhaustive_model_search = false;
213                         do_mid_side = true;
214                         loose_mid_side = false;
215                         qlp_coeff_precision = 0;
216                         min_residual_partition_order = max_residual_partition_order = 3;
217                         rice_parameter_search_dist = 0;
218                         max_lpc_order = 8;
219                 }
220                 else if(0 == strcmp(argv[i], "-6")) {
221                         do_exhaustive_model_search = false;
222                         do_mid_side = true;
223                         loose_mid_side = false;
224                         qlp_coeff_precision = 0;
225                         min_residual_partition_order = 0;
226                         max_residual_partition_order = 4;
227                         rice_parameter_search_dist = 0;
228                         max_lpc_order = 8;
229                 }
230                 else if(0 == strcmp(argv[i], "-7")) {
231                         do_exhaustive_model_search = true;
232                         do_mid_side = true;
233                         loose_mid_side = false;
234                         qlp_coeff_precision = 0;
235                         min_residual_partition_order = 0;
236                         max_residual_partition_order = 6;
237                         rice_parameter_search_dist = 0;
238                         max_lpc_order = 8;
239                 }
240                 else if(0 == strcmp(argv[i], "-8")) {
241                         do_exhaustive_model_search = true;
242                         do_mid_side = true;
243                         loose_mid_side = false;
244                         qlp_coeff_precision = 0;
245                         min_residual_partition_order = 0;
246                         max_residual_partition_order = 6;
247                         rice_parameter_search_dist = 0;
248                         max_lpc_order = 12;
249                 }
250                 else if(0 == strcmp(argv[i], "-9")) {
251                         do_exhaustive_model_search = true;
252                         do_mid_side = true;
253                         loose_mid_side = false;
254                         do_qlp_coeff_prec_search = true;
255                         min_residual_partition_order = 0;
256                         max_residual_partition_order = 16;
257                         rice_parameter_search_dist = 0;
258                         max_lpc_order = 32;
259                 }
260                 else if(isdigit((int)(argv[i][1]))) {
261                         return usage("ERROR: compression level '%s' is still reserved\n", argv[i]);
262                 }
263                 else {
264                         return usage("ERROR: invalid option '%s'\n", argv[i]);
265                 }
266         }
267
268         /* tweak options; validate the values */
269         if(!mode_decode) {
270                 if(blocksize < 0) {
271                         if(max_lpc_order == 0)
272                                 blocksize = 1152;
273                         else
274                                 blocksize = 4608;
275                 }
276                 if(max_residual_partition_order < 0) {
277                         if(blocksize <= 1152)
278                                 max_residual_partition_order = 2;
279                         else if(blocksize <= 2304)
280                                 max_residual_partition_order = 3;
281                         else if(blocksize <= 4608)
282                                 max_residual_partition_order = 3;
283                         else
284                                 max_residual_partition_order = 4;
285                         min_residual_partition_order = max_residual_partition_order;
286                 }
287                 if(rice_parameter_search_dist < 0) {
288                         rice_parameter_search_dist = 0;
289                 }
290         }
291         else {
292                 if(test_only) {
293                         if(skip > 0)
294                                 return usage("ERROR: --skip is not allowed in test mode\n");
295                 }
296         }
297
298         FLAC__ASSERT(blocksize >= 0 || mode_decode);
299
300         if(format_channels >= 0) {
301                 if(format_channels == 0 || (unsigned)format_channels > FLAC__MAX_CHANNELS)
302                         return usage("ERROR: invalid number of channels '%u', must be > 0 and <= %u\n", format_channels, FLAC__MAX_CHANNELS);
303         }
304         if(format_bps >= 0) {
305                 if(format_bps != 8 && format_bps != 16 && format_bps != 24)
306                         return usage("ERROR: invalid bits per sample '%u' (must be 8/16/24)\n", format_bps);
307         }
308         if(format_sample_rate >= 0) {
309                 if(format_sample_rate == 0 || (unsigned)format_sample_rate > FLAC__MAX_SAMPLE_RATE)
310                         return usage("ERROR: invalid sample rate '%u', must be > 0 and <= %u\n", format_sample_rate, FLAC__MAX_SAMPLE_RATE);
311         }
312         if(!mode_decode && ((unsigned)blocksize < FLAC__MIN_BLOCK_SIZE || (unsigned)blocksize > FLAC__MAX_BLOCK_SIZE)) {
313                 return usage("ERROR: invalid blocksize '%u', must be >= %u and <= %u\n", (unsigned)blocksize, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE);
314         }
315         if(qlp_coeff_precision > 0 && qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION) {
316                 return usage("ERROR: invalid value for -q '%u', must be 0 or >= %u\n", qlp_coeff_precision, FLAC__MIN_QLP_COEFF_PRECISION);
317         }
318
319         if(verbose) {
320                 fprintf(stderr, "\n");
321                 fprintf(stderr, "flac %s, Copyright (C) 2000,2001 Josh Coalson\n", FLAC__VERSION_STRING);
322                 fprintf(stderr, "flac comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are\n");
323                 fprintf(stderr, "welcome to redistribute it under certain conditions.  Type `flac' for details.\n\n");
324
325                 if(!mode_decode) {
326                         fprintf(stderr, "options:%s%s -P %u -b %u%s -l %u%s%s -q %u -r %u,%u -R %u%s\n",
327                                 delete_input?" --delete-input-file":"", lax?" --lax":"",
328                                 padding, (unsigned)blocksize, loose_mid_side?" -M":do_mid_side?" -m":"", max_lpc_order,
329                                 do_exhaustive_model_search?" -e":"", do_qlp_coeff_prec_search?" -p":"",
330                                 qlp_coeff_precision,
331                                 (unsigned)min_residual_partition_order, (unsigned)max_residual_partition_order, (unsigned)rice_parameter_search_dist,
332                                 verify? " -V":""
333                         );
334                 }
335         }
336
337         if(mode_decode) {
338                 bool first = true;
339                 int save_format;
340
341                 if(i == argc)
342                         retval = decode_file("-", 0);
343                 else if(i + 2 == argc && 0 == strcmp(argv[i], "-"))
344                         retval = decode_file("-", argv[i+1]);
345                 else {
346                         for(retval = 0; i < argc && retval == 0; i++) {
347                                 if(0 == strcmp(argv[i], "-") && !first)
348                                         continue;
349                                 save_format = format_is_wave;
350                                 retval = decode_file(argv[i], 0);
351                                 format_is_wave = save_format;
352                                 first = false;
353                         }
354                 }
355         }
356         else { /* encode */
357                 bool first = true;
358                 int save_format;
359
360                 if(i == argc)
361                         retval = encode_file("-", 0);
362                 else if(i + 2 == argc && 0 == strcmp(argv[i], "-"))
363                         retval = encode_file("-", argv[i+1]);
364                 else {
365                         for(retval = 0; i < argc && retval == 0; i++) {
366                                 if(0 == strcmp(argv[i], "-") && !first)
367                                         continue;
368                                 save_format = format_is_wave;
369                                 retval = encode_file(argv[i], 0);
370                                 format_is_wave = save_format;
371                                 first = false;
372                         }
373                 }
374         }
375
376         return retval;
377 }
378
379 int usage(const char *message, ...)
380 {
381         va_list args;
382
383         if(message) {
384                 va_start(args, message);
385
386                 (void) vfprintf(stderr, message, args);
387
388                 va_end(args);
389
390         }
391         fprintf(stderr, "===============================================================================\n");
392         fprintf(stderr, "flac - Command-line FLAC encoder/decoder version %s\n", FLAC__VERSION_STRING);
393         fprintf(stderr, "Copyright (C) 2000,2001  Josh Coalson\n");
394         fprintf(stderr, "\n");
395         fprintf(stderr, "This program is free software; you can redistribute it and/or\n");
396         fprintf(stderr, "modify it under the terms of the GNU General Public License\n");
397         fprintf(stderr, "as published by the Free Software Foundation; either version 2\n");
398         fprintf(stderr, "of the License, or (at your option) any later version.\n");
399         fprintf(stderr, "\n");
400         fprintf(stderr, "This program is distributed in the hope that it will be useful,\n");
401         fprintf(stderr, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
402         fprintf(stderr, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
403         fprintf(stderr, "GNU General Public License for more details.\n");
404         fprintf(stderr, "\n");
405         fprintf(stderr, "You should have received a copy of the GNU General Public License\n");
406         fprintf(stderr, "along with this program; if not, write to the Free Software\n");
407         fprintf(stderr, "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n");
408         fprintf(stderr, "===============================================================================\n");
409         fprintf(stderr, "Usage:\n");
410         fprintf(stderr, "  flac [options] [infile [...]]\n");
411         fprintf(stderr, "\n");
412         fprintf(stderr, "For encoding:\n");
413         fprintf(stderr, "  the input file(s) may be a PCM RIFF WAVE file or raw samples\n");
414         fprintf(stderr, "  the output file(s) will be in FLAC format\n");
415         fprintf(stderr, "For decoding, the reverse is true\n");
416         fprintf(stderr, "\n");
417         fprintf(stderr, "A single 'infile' may be - for stdin.  No 'infile' implies stdin.  Use of\n");
418         fprintf(stderr, "stdin implies -c (write to stdout).  However, flac allows the special\n");
419         fprintf(stderr, "encoding/decoding forms:\n");
420         fprintf(stderr, "   flac [options] - outfilename   or  flac -d [options] - outfilename\n");
421         fprintf(stderr, "which is better than:\n");
422         fprintf(stderr, "   flac [options] > outfilename   or  flac -d [options] > outfilename\n");
423         fprintf(stderr, "since the former allows flac to seek backwards to write the STREAMINFO or\n");
424         fprintf(stderr, "RIFF WAVE header contents when necessary.\n");
425         fprintf(stderr, "\n");
426         fprintf(stderr, "If the unencoded filename ends with '.wav' or -fw is used, it's assumed to be\n");
427         fprintf(stderr, "RIFF WAVE.  Otherwise, flac will check for the presence of a RIFF header.  If\n");
428         fprintf(stderr, "any infile is raw you must specify the format options {-fb|fl} -fc -fp and -fs,\n");
429         fprintf(stderr, "which will apply to all raw files.  You can force a .wav file to be treated as\n");
430         fprintf(stderr, "a raw file using -fr.\n");
431         fprintf(stderr, "\n");
432         fprintf(stderr, "generic options:\n");
433         fprintf(stderr, "  -d : decode (default behavior is encode)\n");
434         fprintf(stderr, "  -t : test (same as -d except no decoded file is written)\n");
435         fprintf(stderr, "  -a : analyze (same as -d except an analysis file is written)\n");
436         fprintf(stderr, "  -c : write output to stdout\n");
437         fprintf(stderr, "  -s : silent (do not write runtime encode/decode statistics)\n");
438         fprintf(stderr, "  --skip samples : can be used both for encoding and decoding\n");
439         fprintf(stderr, "  --delete-input-file : deletes the input file after a successful encode/decode\n");
440         fprintf(stderr, "analyze options:\n");
441         fprintf(stderr, "  --a-rtext : include residual signal in text output\n");
442         fprintf(stderr, "  --a-rgp : generate gnuplot files of residual distribution of each subframe\n");
443         fprintf(stderr, "encoding options:\n");
444         fprintf(stderr, "  --lax : allow encoder to generate non-Subset files\n");
445         fprintf(stderr, "  -S { # | X | #x } : include a point or points in a SEEKTABLE\n");
446         fprintf(stderr, "       #  : a specific sample number for a seek point\n");
447         fprintf(stderr, "       X  : a placeholder point (always goes at the end of the SEEKTABLE)\n");
448         fprintf(stderr, "       #x : # evenly spaced seekpoints, the first being at sample 0\n");
449         fprintf(stderr, "     You may use many -S options; the resulting SEEKTABLE will be the unique-\n");
450         fprintf(stderr, "           ified union of all such values.\n");
451         fprintf(stderr, "     With no -S options, flac defaults to '-S 100x'.  Use -S- for no SEEKTABLE.\n");
452         fprintf(stderr, "     Note: -S #x will not work if the encoder can't determine the input size\n");
453         fprintf(stderr, "           before starting.\n");
454         fprintf(stderr, "     Note: if you use -S # and # is >= samples in the input, there will be\n");
455         fprintf(stderr, "           either no seek point entered (if the input size is determinable\n");
456         fprintf(stderr, "           before encoding starts) or a placeholder point (if input size is not\n");
457         fprintf(stderr, "           determinable)\n");
458         fprintf(stderr, "  -P # : write a PADDING block of # bytes (goes after SEEKTABLE)\n");
459         fprintf(stderr, "         (0 => no PADDING block, default is -P 0)\n");
460         fprintf(stderr, "  -b # : specify blocksize in samples; default is 1152 for -l 0, else 4608;\n");
461         fprintf(stderr, "         must be 192/576/1152/2304/4608/256/512/1024/2048/4096/8192/16384/32768\n");
462         fprintf(stderr, "         (unless --lax is used)\n");
463         fprintf(stderr, "  -m   : try mid-side coding for each frame (stereo input only)\n");
464         fprintf(stderr, "  -M   : loose mid-side coding for all frames (stereo input only)\n");
465         fprintf(stderr, "  -0 .. -9 : fastest compression .. highest compression, default is -5\n");
466         fprintf(stderr, "             these are synonyms for other options:\n");
467         fprintf(stderr, "  -0   : synonymous with -l 0 -b 1152 -r 2,2\n");
468         fprintf(stderr, "  -1   : synonymous with -l 0 -b 1152 -M -r 2,2\n");
469         fprintf(stderr, "  -2   : synonymous with -l 0 -b 1152 -m -r 3\n");
470         fprintf(stderr, "  -3   : synonymous with -l 6 -b 4608 -r 3,3\n");
471         fprintf(stderr, "  -4   : synonymous with -l 8 -b 4608 -M -r 3,3\n");
472         fprintf(stderr, "  -5   : synonymous with -l 8 -b 4608 -m -r 3,3\n");
473         fprintf(stderr, "  -6   : synonymous with -l 8 -b 4608 -m -r 4\n");
474         fprintf(stderr, "  -7   : synonymous with -l 8 -b 4608 -m -e -r 6\n");
475         fprintf(stderr, "  -8   : synonymous with -l 12 -b 4608 -m -e -r 6\n");
476         fprintf(stderr, "  -9   : synonymous with -l 32 -b 4608 -m -e -r 16 -p (very slow!)\n");
477         fprintf(stderr, "  -e   : do exhaustive model search (expensive!)\n");
478         fprintf(stderr, "  -l # : specify max LPC order; 0 => use only fixed predictors\n");
479         fprintf(stderr, "  -p   : do exhaustive search of LP coefficient quantization (expensive!);\n");
480         fprintf(stderr, "         overrides -q, does nothing if using -l 0\n");
481         fprintf(stderr, "  -q # : specify precision in bits of quantized linear-predictor coefficients;\n");
482         fprintf(stderr, "         0 => let encoder decide (min is %u, default is -q 0)\n", FLAC__MIN_QLP_COEFF_PRECISION);
483         fprintf(stderr, "  -r [#,]# : [min,]max residual partition order (# is 0..16; min defaults to 0;\n");
484         fprintf(stderr, "         default is -r 0; above 4 doesn't usually help much)\n");
485         fprintf(stderr, "  -R # : Rice parameter search distance (# is 0..32; above 2 doesn't help much)\n");
486         fprintf(stderr, "  -V   : verify a correct encoding by decoding the output in parallel and\n");
487         fprintf(stderr, "         comparing to the original\n");
488         fprintf(stderr, "  -S-, -m-, -M-, -e-, -p-, -V-, --delete-input-file-, --lax- can all be used to\n");
489         fprintf(stderr, "  turn off a particular option\n");
490         fprintf(stderr, "format options:\n");
491         fprintf(stderr, "  -fb | -fl : big-endian | little-endian byte order\n");
492         fprintf(stderr, "  -fc channels\n");
493         fprintf(stderr, "  -fp bits_per_sample\n");
494         fprintf(stderr, "  -fs sample_rate : in Hz\n");
495         fprintf(stderr, "  -fu : unsigned samples (default is signed)\n");
496         fprintf(stderr, "  -fr : force to raw format (even if filename ends in .wav)\n");
497         fprintf(stderr, "  -fw : force to RIFF WAVE\n");
498         return 1;
499 }
500
501 int encode_file(const char *infilename, const char *forced_outfilename)
502 {
503         FILE *encode_infile;
504         char outfilename[4096]; /* @@@ bad MAGIC NUMBER */
505         char *p;
506         int retval;
507
508         if(0 == strcmp(infilename, "-")) {
509                 encode_infile = stdin;
510         }
511         else {
512                 if(0 == (encode_infile = fopen(infilename, "rb"))) {
513                         fprintf(stderr, "ERROR: can't open input file %s\n", infilename);
514                         return 1;
515                 }
516         }
517
518         if(verbose)
519                 fprintf(stderr, "%s:\n", infilename);
520
521         if(format_is_wave < 0) {
522                 /* lamely attempt to guess the file type based on the first 4 bytes (which is all ungetc will guarantee us) */
523                 char head[4];
524                 int h, n;
525                 /* first set format based on name */
526                 if(strstr(infilename, ".wav") == infilename + (strlen(infilename) - strlen(".wav")))
527                         format_is_wave = true;
528                 else
529                         format_is_wave = false;
530                 if((n = fread(head, 1, 4, encode_infile)) < 4) {
531                         if(format_is_wave)
532                                 fprintf(stderr, "WARNING: %s is not a WAVE file, treating as a raw file\n", infilename);
533                         format_is_wave = false;
534                 }
535                 else {
536                         if(strncmp(head, "RIFF", 4)) {
537                                 if(format_is_wave)
538                                         fprintf(stderr, "WARNING: %s is not a WAVE file, treating as a raw file\n", infilename);
539                                 format_is_wave = false;
540                         }
541                         else
542                                 format_is_wave = true;
543                 }
544                 for(h = n-1; h >= 0; h--)
545                         ungetc(head[h], encode_infile);
546         }
547
548         if(!format_is_wave) {
549                 if(format_is_big_endian < 0 || format_channels < 0 || format_bps < 0 || format_sample_rate < 0)
550                         return usage("ERROR: for encoding a raw file you must specify { -fb or -fl }, -fc, -fp, and -fs\n");
551         }
552
553         if(encode_infile == stdin || force_to_stdout)
554                 strcpy(outfilename, "-");
555         else {
556                 strcpy(outfilename, infilename);
557                 if(0 == (p = strrchr(outfilename, '.')))
558                         strcat(outfilename, ".flac");
559                 else {
560                         if(0 == strcmp(p, ".flac"))
561                                 strcpy(p, "_new.flac");
562                         else
563                                 strcpy(p, ".flac");
564                 }
565         }
566         if(0 == forced_outfilename)
567                 forced_outfilename = outfilename;
568
569         if(format_is_wave)
570                 retval = flac__encode_wav(encode_infile, infilename, forced_outfilename, verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding, requested_seek_points, num_requested_seek_points);
571         else
572                 retval = flac__encode_raw(encode_infile, infilename, forced_outfilename, verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding, requested_seek_points, num_requested_seek_points, format_is_big_endian, format_is_unsigned_samples, format_channels, format_bps, format_sample_rate);
573
574         if(retval == 0 && strcmp(infilename, "-")) {
575                 if(strcmp(forced_outfilename, "-"))
576                         flac__file_copy_metadata(infilename, forced_outfilename);
577                 if(delete_input)
578                         unlink(infilename);
579         }
580
581         return retval;
582 }
583
584 int decode_file(const char *infilename, const char *forced_outfilename)
585 {
586         static const char *suffixes[] = { ".wav", ".raw" };
587         char outfilename[4096]; /* @@@ bad MAGIC NUMBER */
588         char *p;
589         int retval;
590
591         if(!test_only && !analyze) {
592                 if(format_is_wave < 0) {
593                         format_is_wave = true;
594                 }
595                 if(!format_is_wave) {
596                         if(format_is_big_endian < 0)
597                                 return usage("ERROR: for decoding to a raw file you must specify -fb or -fl\n");
598                 }
599         }
600
601         if(0 == strcmp(infilename, "-") || force_to_stdout)
602                 strcpy(outfilename, "-");
603         else {
604                 const char *suffix = suffixes[format_is_wave? 0:1];
605                 strcpy(outfilename, infilename);
606                 if(0 == (p = strrchr(outfilename, '.')))
607                         strcat(outfilename, suffix);
608                 else {
609                         if(0 == strcmp(p, suffix)) {
610                                 strcpy(p, "_new");
611                                 strcat(p, suffix);
612                         }
613                         else
614                                 strcpy(p, suffix);
615                 }
616         }
617         if(0 == forced_outfilename)
618                 forced_outfilename = outfilename;
619
620         if(format_is_wave)
621                 retval = flac__decode_wav(infilename, test_only? 0 : forced_outfilename, analyze, aopts, verbose, skip);
622         else
623                 retval = flac__decode_raw(infilename, test_only? 0 : forced_outfilename, analyze, aopts, verbose, skip, format_is_big_endian, format_is_unsigned_samples);
624
625         if(retval == 0 && strcmp(infilename, "-")) {
626                 if(strcmp(forced_outfilename, "-"))
627                         flac__file_copy_metadata(infilename, forced_outfilename);
628                 if(delete_input)
629                         unlink(infilename);
630         }
631
632         return retval;
633 }