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