add more verbose status reporting; pass aopts to analyze_init/finish()
[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;
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, rice_optimization_level = -1;
45
46         aopts.do_residual_text = false;
47         aopts.do_residual_gnuplot = false;
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], "--skip"))
71                         skip = (uint64)atoi(argv[++i]); /* @@@ takes a pretty damn big file to overflow atoi() here, but it could happen */
72                 else if(0 == strcmp(argv[i], "--lax"))
73                         lax = true;
74                 else if(0 == strcmp(argv[i], "--lax-"))
75                         lax = false;
76                 else if(0 == strcmp(argv[i], "-b"))
77                         blocksize = atoi(argv[++i]);
78                 else if(0 == strcmp(argv[i], "-e"))
79                         do_exhaustive_model_search = true;
80                 else if(0 == strcmp(argv[i], "-e-"))
81                         do_exhaustive_model_search = false;
82                 else if(0 == strcmp(argv[i], "-l"))
83                         max_lpc_order = atoi(argv[++i]);
84                 else if(0 == strcmp(argv[i], "-m"))
85                         do_mid_side = true;
86                 else if(0 == strcmp(argv[i], "-m-"))
87                         do_mid_side = false;
88                 else if(0 == strcmp(argv[i], "-M"))
89                         loose_mid_side = do_mid_side = true;
90                 else if(0 == strcmp(argv[i], "-M-"))
91                         loose_mid_side = do_mid_side = false;
92                 else if(0 == strcmp(argv[i], "-p"))
93                         do_qlp_coeff_prec_search = true;
94                 else if(0 == strcmp(argv[i], "-p-"))
95                         do_qlp_coeff_prec_search = false;
96                 else if(0 == strcmp(argv[i], "-P"))
97                         padding = atoi(argv[++i]);
98                 else if(0 == strcmp(argv[i], "-q"))
99                         qlp_coeff_precision = atoi(argv[++i]);
100                 else if(0 == strcmp(argv[i], "-r"))
101                         rice_optimization_level = atoi(argv[++i]);
102                 else if(0 == strcmp(argv[i], "-V"))
103                         verify = true;
104                 else if(0 == strcmp(argv[i], "-V-"))
105                         verify = false;
106                 else if(0 == strcmp(argv[i], "-fb"))
107                         format_is_big_endian = true;
108                 else if(0 == strcmp(argv[i], "-fl"))
109                         format_is_big_endian = false;
110                 else if(0 == strcmp(argv[i], "-fc"))
111                         format_channels = atoi(argv[++i]);
112                 else if(0 == strcmp(argv[i], "-fp"))
113                         format_bps = atoi(argv[++i]);
114                 else if(0 == strcmp(argv[i], "-fs"))
115                         format_sample_rate = atoi(argv[++i]);
116                 else if(0 == strcmp(argv[i], "-fu"))
117                         format_is_unsigned_samples = true;
118                 else if(0 == strcmp(argv[i], "-fr"))
119                         format_is_wave = false;
120                 else if(0 == strcmp(argv[i], "-fw"))
121                         format_is_wave = true;
122                 else if(0 == strcmp(argv[i], "--a-rgp"))
123                         aopts.do_residual_gnuplot = true;
124                 else if(0 == strcmp(argv[i], "--a-rgp-"))
125                         aopts.do_residual_gnuplot = false;
126                 else if(0 == strcmp(argv[i], "-0")) {
127                         do_exhaustive_model_search = false;
128                         do_mid_side = false;
129                         loose_mid_side = false;
130                         qlp_coeff_precision = 0;
131                         rice_optimization_level = 0;
132                         max_lpc_order = 0;
133                 }
134                 else if(0 == strcmp(argv[i], "-1")) {
135                         do_exhaustive_model_search = false;
136                         do_mid_side = true;
137                         loose_mid_side = true;
138                         qlp_coeff_precision = 0;
139                         rice_optimization_level = 0;
140                         max_lpc_order = 0;
141                 }
142                 else if(0 == strcmp(argv[i], "-2")) {
143                         do_exhaustive_model_search = false;
144                         do_mid_side = true;
145                         loose_mid_side = false;
146                         qlp_coeff_precision = 0;
147                         max_lpc_order = 0;
148                 }
149                 else if(0 == strcmp(argv[i], "-4")) {
150                         do_exhaustive_model_search = false;
151                         do_mid_side = false;
152                         loose_mid_side = false;
153                         qlp_coeff_precision = 0;
154                         rice_optimization_level = 0;
155                         max_lpc_order = 8;
156                 }
157                 else if(0 == strcmp(argv[i], "-5")) {
158                         do_exhaustive_model_search = false;
159                         do_mid_side = true;
160                         loose_mid_side = true;
161                         qlp_coeff_precision = 0;
162                         rice_optimization_level = 0;
163                         max_lpc_order = 8;
164                 }
165                 else if(0 == strcmp(argv[i], "-6")) {
166                         do_exhaustive_model_search = false;
167                         do_mid_side = true;
168                         loose_mid_side = false;
169                         qlp_coeff_precision = 0;
170                         max_lpc_order = 8;
171                 }
172                 else if(0 == strcmp(argv[i], "-8")) {
173                         do_exhaustive_model_search = false;
174                         do_mid_side = true;
175                         loose_mid_side = false;
176                         qlp_coeff_precision = 0;
177                         max_lpc_order = 32;
178                 }
179                 else if(0 == strcmp(argv[i], "-9")) {
180                         do_exhaustive_model_search = true;
181                         do_mid_side = true;
182                         loose_mid_side = false;
183                         do_qlp_coeff_prec_search = true;
184                         rice_optimization_level = 99;
185                         max_lpc_order = 32;
186                 }
187                 else if(isdigit((int)(argv[i][1]))) {
188                         return usage("ERROR: compression level '%s' is still reserved\n", argv[i]);
189                 }
190                 else {
191                         return usage("ERROR: invalid option '%s'\n", argv[i]);
192                 }
193         }
194         if(i + (test_only? 1:2) != argc)
195                 return usage("ERROR: invalid arguments (more/less than %d filename%s?)\n", (test_only? 1:2), (test_only? "":"s"));
196
197         /* tweak options based on the filenames; validate the values */
198         if(!mode_decode) {
199                 if(format_is_wave < 0) {
200                         if(strstr(argv[i], ".wav") == argv[i] + (strlen(argv[i]) - strlen(".wav")))
201                                 format_is_wave = true;
202                         else
203                                 format_is_wave = false;
204                 }
205                 if(!format_is_wave) {
206                         if(format_is_big_endian < 0 || format_channels < 0 || format_bps < 0 || format_sample_rate < 0)
207                                 return usage("ERROR: for encoding a raw file you must specify { -fb or -fl }, -fc, -fp, and -fs\n");
208                 }
209                 if(blocksize < 0) {
210                         if(max_lpc_order == 0)
211                                 blocksize = 1152;
212                         else
213                                 blocksize = 4608;
214                 }
215                 if(rice_optimization_level < 0) {
216                         if(blocksize <= 1152)
217                                 rice_optimization_level = 4;
218                         else if(blocksize <= 2304)
219                                 rice_optimization_level = 4;
220                         else if(blocksize <= 4608)
221                                 rice_optimization_level = 4;
222                         else
223                                 rice_optimization_level = 5;
224                 }
225         }
226         else {
227                 if(test_only) {
228                         if(skip > 0)
229                                 return usage("ERROR: --skip is not allowed in test mode\n");
230                 }
231                 else if(!analyze) {
232                         if(format_is_wave < 0) {
233                                 if(strstr(argv[i+1], ".wav") == argv[i+1] + (strlen(argv[i+1]) - strlen(".wav")))
234                                         format_is_wave = true;
235                                 else
236                                         format_is_wave = false;
237                         }
238                         if(!format_is_wave) {
239                                 if(format_is_big_endian < 0)
240                                         return usage("ERROR: for decoding to a raw file you must specify -fb or -fl\n");
241                         }
242                 }
243         }
244
245         assert(blocksize >= 0 || mode_decode);
246
247         if(format_channels >= 0) {
248                 if(format_channels == 0 || (unsigned)format_channels > FLAC__MAX_CHANNELS)
249                         return usage("ERROR: invalid number of channels '%u', must be > 0 and <= %u\n", format_channels, FLAC__MAX_CHANNELS);
250         }
251         if(format_bps >= 0) {
252                 if(format_bps != 8 && format_bps != 16 && format_bps != 24)
253                         return usage("ERROR: invalid bits per sample '%u' (must be 8/16/24)\n", format_bps);
254         }
255         if(format_sample_rate >= 0) {
256                 if(format_sample_rate == 0 || (unsigned)format_sample_rate > FLAC__MAX_SAMPLE_RATE)
257                         return usage("ERROR: invalid sample rate '%u', must be > 0 and <= %u\n", format_sample_rate, FLAC__MAX_SAMPLE_RATE);
258         }
259         if(!mode_decode && ((unsigned)blocksize < FLAC__MIN_BLOCK_SIZE || (unsigned)blocksize > FLAC__MAX_BLOCK_SIZE)) {
260                 return usage("ERROR: invalid blocksize '%u', must be >= %u and <= %u\n", (unsigned)blocksize, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE);
261         }
262         if(qlp_coeff_precision > 0 && qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION) {
263                 return usage("ERROR: invalid value for -q '%u', must be 0 or >= %u\n", qlp_coeff_precision, FLAC__MIN_QLP_COEFF_PRECISION);
264         }
265
266         /* turn off verbosity if the output stream is going to stdout */
267         if(!test_only && 0 == strcmp(argv[i+1], "-"))
268                 verbose = false;
269
270         if(verbose) {
271                 printf("\n");
272                 printf("flac %s, Copyright (C) 2000,2001 Josh Coalson\n", FLAC__VERSION_STRING);
273                 printf("flac comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are\n");
274                 printf("welcome to redistribute it under certain conditions.  Type `flac' for details.\n\n");
275
276                 if(!mode_decode) {
277                         printf("options:%s -P %u -b %u%s -l %u%s%s -q %u -r %u%s\n",
278                                 lax?" --lax":"", padding, (unsigned)blocksize, loose_mid_side?" -M":do_mid_side?" -m":"", max_lpc_order,
279                                 do_exhaustive_model_search?" -e":"", do_qlp_coeff_prec_search?" -p":"",
280                                 qlp_coeff_precision, (unsigned)rice_optimization_level,
281                                 verify? " -V":""
282                         );
283                 }
284         }
285
286         if(mode_decode)
287                 if(format_is_wave)
288                         return decode_wav(argv[i], test_only? 0 : argv[i+1], analyze, aopts, verbose, skip);
289                 else
290                         return decode_raw(argv[i], test_only? 0 : argv[i+1], analyze, aopts, verbose, skip, format_is_big_endian, format_is_unsigned_samples);
291         else
292                 if(format_is_wave)
293                         return encode_wav(argv[i], argv[i+1], verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding);
294                 else
295                         return encode_raw(argv[i], argv[i+1], verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding, format_is_big_endian, format_is_unsigned_samples, format_channels, format_bps, format_sample_rate);
296
297         return 0;
298 }
299
300 int usage(const char *message, ...)
301 {
302         va_list args;
303
304         if(message) {
305                 va_start(args, message);
306
307                 (void) vfprintf(stderr, message, args);
308
309                 va_end(args);
310
311         }
312         printf("==============================================================================\n");
313         printf("flac - Command-line FLAC encoder/decoder version %s\n", FLAC__VERSION_STRING);
314         printf("Copyright (C) 2000,2001  Josh Coalson\n");
315         printf("\n");
316         printf("This program is free software; you can redistribute it and/or\n");
317         printf("modify it under the terms of the GNU General Public License\n");
318         printf("as published by the Free Software Foundation; either version 2\n");
319         printf("of the License, or (at your option) any later version.\n");
320         printf("\n");
321         printf("This program is distributed in the hope that it will be useful,\n");
322         printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
323         printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
324         printf("GNU General Public License for more details.\n");
325         printf("\n");
326         printf("You should have received a copy of the GNU General Public License\n");
327         printf("along with this program; if not, write to the Free Software\n");
328         printf("Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n");
329         printf("==============================================================================\n");
330         printf("Usage:\n");
331         printf("  flac [options] infile outfile\n");
332         printf("\n");
333         printf("For encoding:\n");
334         printf("  infile may be a PCM RIFF WAVE file or raw samples\n");
335         printf("  outfile will be in FLAC format\n");
336         printf("For decoding, the reverse is be true\n");
337         printf("\n");
338         printf("infile may be - for stdin, outfile may be - for stdout\n");
339         printf("\n");
340         printf("If the unencoded filename ends with '.wav' or -fw is used, it's assumed to be\n");
341         printf("RIFF WAVE.  Otherwise, it's assumed to be raw samples and you have to specify\n");
342         printf("all the format options.  You can force a .wav file to be treated as a raw file\n");
343         printf("using -fr.\n");
344         printf("\n");
345         printf("generic options:\n");
346         printf("  -d : decode (default behavior is encode)\n");
347         printf("  -t : test (same as -d except no decoded file is written)\n");
348         printf("  -a : analyze (same as -d except an analysis file is written)\n");
349         printf("  -s : silent (do not write runtime encode/decode statistics to stdout)\n");
350         printf("  --skip samples : can be used both for encoding and decoding\n");
351         printf("analyze options:\n");
352         printf("  --a-rtext : include residual signal in text output\n");
353         printf("  --a-rgp : generate gnuplot files of residual distribution of each subframe\n");
354         printf("encoding options:\n");
355         printf("  --lax : allow encoder to generate non-Subset files\n");
356         printf("  -P bytes : write a PADDING block of the given length (0 => no PADDING block, default is -P 0)\n");
357         printf("  -b blocksize : default is 1152 for -l 0, else 4608; should be 192/576/1152/2304/4608 (unless --lax is used)\n");
358         printf("  -m : try mid-side coding for each frame (stereo input only)\n");
359         printf("  -M : loose mid-side coding for all frames (stereo input only)\n");
360         printf("  -0 .. -9 : fastest compression .. highest compression, default is -6\n");
361         printf("             these are synonyms for other options:\n");
362         printf("  -0 : synonymous with -l 0\n");
363         printf("  -1 : synonymous with -l 0 -M\n");
364         printf("  -2 : synonymous with -l 0 -m -r # (# is automatically determined by the block size)\n");
365         printf("  -3 : reserved\n");
366         printf("  -4 : synonymous with -l 8\n");
367         printf("  -5 : synonymous with -l 8 -M\n");
368         printf("  -6 : synonymous with -l 8 -m -r # (# is automatically determined by the block size)\n");
369         printf("  -7 : reserved\n");
370         printf("  -8 : synonymous with -l 32 -m -r # (# is automatically determined by the block size)\n");
371         printf("  -9 : synonymous with -l 32 -m -e -r 99 -p (very slow!)\n");
372         printf("  -e : do exhaustive model search (expensive!)\n");
373         printf("  -l max_lpc_order : 0 => use only fixed predictors\n");
374         printf("  -p : do exhaustive search of LP coefficient quantization (expensive!); overrides -q, does nothing if using -l 0\n");
375         printf("  -q bits : precision of the quantized linear-predictor coefficients, 0 => let encoder decide (min is %u, default is -q 0)\n", FLAC__MIN_QLP_COEFF_PRECISION);
376         printf("  -r level : rice parameter optimization level (level is 0..99, 0 => none, default is -r 0, above 4 doesn't usually help much)\n");
377         printf("  -V : verify a correct encoding by decoding the output in parallel and comparing to the original\n");
378         printf("  -m-, -M-, -e-, -p-, -V-, --lax- can all be used to turn off a particular option\n");
379         printf("format options:\n");
380         printf("  -fb | -fl : big-endian | little-endian byte order\n");
381         printf("  -fc channels\n");
382         printf("  -fp bits_per_sample\n");
383         printf("  -fs sample_rate : in Hz\n");
384         printf("  -fu : unsigned samples (default is signed)\n");
385         printf("  -fr : force to raw format (even if filename ends in .wav)\n");
386         printf("  -fw : force to RIFF WAVE\n");
387         return 1;
388 }