Initial revision
[flac.git] / src / flac / main.c
1 /* flac - Command-line FLAC encoder/decoder
2  * Copyright (C) 2000  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 "decode.h"
27 #include "encode.h"
28
29 static int usage(const char *message, ...);
30
31 int main(int argc, char *argv[])
32 {
33         int i;
34         bool verbose = true, lax = false, mode_decode = false, do_mid_side = true, do_exhaustive_model_search = false, do_qlp_coeff_prec_search = false;
35         unsigned max_lpc_order = 8;
36         unsigned qlp_coeff_precision = 0;
37         uint64 skip = 0;
38         int format_is_wave = -1, format_is_big_endian = -1, format_is_unsigned_samples = false;
39         int format_channels = -1, format_bps = -1, format_sample_rate = -1;
40         int blocksize = -1, rice_optimization_level = -1;
41
42         if(argc <= 1)
43                 return usage(0);
44
45         /* get the options */
46         for(i = 1; i < argc; i++) {
47                 if(argv[i][0] != '-' || argv[i][1] == 0)
48                         break;
49                 if(0 == strcmp(argv[i], "-d"))
50                         mode_decode = true;
51                 else if(0 == strcmp(argv[i], "-s"))
52                         verbose = false;
53                 else if(0 == strcmp(argv[i], "-s-"))
54                         verbose = true;
55                 else if(0 == strcmp(argv[i], "--skip"))
56                         skip = (uint64)atoi(argv[++i]); /* takes a pretty damn big file to overflow atoi() here, but it could happen */
57                 else if(0 == strcmp(argv[i], "--lax"))
58                         lax = true;
59                 else if(0 == strcmp(argv[i], "--lax-"))
60                         lax = false;
61                 else if(0 == strcmp(argv[i], "-b"))
62                         blocksize = atoi(argv[++i]);
63                 else if(0 == strcmp(argv[i], "-e"))
64                         do_exhaustive_model_search = true;
65                 else if(0 == strcmp(argv[i], "-e-"))
66                         do_exhaustive_model_search = false;
67                 else if(0 == strcmp(argv[i], "-l"))
68                         max_lpc_order = atoi(argv[++i]);
69                 else if(0 == strcmp(argv[i], "-m"))
70                         do_mid_side = true;
71                 else if(0 == strcmp(argv[i], "-m-"))
72                         do_mid_side = false;
73                 else if(0 == strcmp(argv[i], "-p"))
74                         do_qlp_coeff_prec_search = true;
75                 else if(0 == strcmp(argv[i], "-p-"))
76                         do_qlp_coeff_prec_search = false;
77                 else if(0 == strcmp(argv[i], "-q"))
78                         qlp_coeff_precision = atoi(argv[++i]);
79                 else if(0 == strcmp(argv[i], "-r"))
80                         rice_optimization_level = atoi(argv[++i]);
81                 else if(0 == strcmp(argv[i], "-fb"))
82                         format_is_big_endian = true;
83                 else if(0 == strcmp(argv[i], "-fl"))
84                         format_is_big_endian = false;
85                 else if(0 == strcmp(argv[i], "-fc"))
86                         format_channels = atoi(argv[++i]);
87                 else if(0 == strcmp(argv[i], "-fp"))
88                         format_bps = atoi(argv[++i]);
89                 else if(0 == strcmp(argv[i], "-fs"))
90                         format_sample_rate = atoi(argv[++i]);
91                 else if(0 == strcmp(argv[i], "-fu"))
92                         format_is_unsigned_samples = true;
93                 else if(0 == strcmp(argv[i], "-fr"))
94                         format_is_wave = false;
95                 else if(0 == strcmp(argv[i], "-fw"))
96                         format_is_wave = true;
97                 else if(0 == strcmp(argv[i], "-0")) {
98                         do_exhaustive_model_search = false;
99                         do_mid_side = false;
100                         qlp_coeff_precision = 0;
101                         rice_optimization_level = 0;
102                         max_lpc_order = 0;
103                 }
104                 else if(0 == strcmp(argv[i], "-1")) {
105                         do_exhaustive_model_search = false;
106                         do_mid_side = true;
107                         qlp_coeff_precision = 0;
108                         rice_optimization_level = 0;
109                         max_lpc_order = 0;
110                 }
111                 else if(0 == strcmp(argv[i], "-2")) {
112                         do_exhaustive_model_search = false;
113                         do_mid_side = true;
114                         qlp_coeff_precision = 0;
115                         max_lpc_order = 0;
116                 }
117                 else if(0 == strcmp(argv[i], "-4")) {
118                         do_exhaustive_model_search = false;
119                         do_mid_side = false;
120                         qlp_coeff_precision = 0;
121                         rice_optimization_level = 0;
122                         max_lpc_order = 8;
123                 }
124                 else if(0 == strcmp(argv[i], "-5")) {
125                         do_exhaustive_model_search = false;
126                         do_mid_side = true;
127                         qlp_coeff_precision = 0;
128                         rice_optimization_level = 0;
129                         max_lpc_order = 8;
130                 }
131                 else if(0 == strcmp(argv[i], "-6")) {
132                         do_exhaustive_model_search = false;
133                         do_mid_side = true;
134                         qlp_coeff_precision = 0;
135                         max_lpc_order = 8;
136                 }
137                 else if(0 == strcmp(argv[i], "-8")) {
138                         do_exhaustive_model_search = false;
139                         do_mid_side = true;
140                         qlp_coeff_precision = 0;
141                         max_lpc_order = 32;
142                 }
143                 else if(0 == strcmp(argv[i], "-9")) {
144                         do_exhaustive_model_search = true;
145                         do_mid_side = true;
146                         do_qlp_coeff_prec_search = true;
147                         rice_optimization_level = 99;
148                         max_lpc_order = 32;
149                 }
150                 else if(isdigit((int)(argv[i][1]))) {
151                         return usage("ERROR: compression level '%s' is still reserved\n", argv[i]);
152                 }
153                 else {
154                         return usage("ERROR: invalid option '%s'\n", argv[i]);
155                 }
156         }
157         if(i + 2 != argc)
158                 return usage("ERROR: invalid arguments (more/less than 2 filenames?)\n");
159
160         /* tweak options based on the filenames; validate the values */
161         if(!mode_decode) {
162                 if(format_is_wave < 0) {
163                         if(strstr(argv[i], ".wav") == argv[i] + (strlen(argv[i]) - strlen(".wav")))
164                                 format_is_wave = true;
165                         else
166                                 format_is_wave = false;
167                 }
168                 if(!format_is_wave) {
169                         if(format_is_big_endian < 0 || format_channels < 0 || format_bps < 0 || format_sample_rate < 0)
170                                 return usage("ERROR: for encoding a raw file you must specify { -fb or -fl }, -fc, -fp, and -fs\n");
171                 }
172                 if(blocksize < 0) {
173                         if(max_lpc_order == 0)
174                                 blocksize = 1152;
175                         else
176                                 blocksize = 4608;
177                 }
178                 if(rice_optimization_level < 0) {
179                         if(blocksize <= 1152)
180                                 rice_optimization_level = 4;
181                         else if(blocksize <= 2304)
182                                 rice_optimization_level = 4;
183                         else if(blocksize <= 4608)
184                                 rice_optimization_level = 4;
185                         else
186                                 rice_optimization_level = 5;
187                 }
188         }
189         else {
190                 if(format_is_wave < 0) {
191                         if(strstr(argv[i+1], ".wav") == argv[i+1] + (strlen(argv[i+1]) - strlen(".wav")))
192                                 format_is_wave = true;
193                         else
194                                 format_is_wave = false;
195                 }
196                 if(!format_is_wave) {
197                         if(format_is_big_endian < 0)
198                                 return usage("ERROR: for decoding to a raw file you must specify -fb or -fl\n");
199                 }
200         }
201
202         assert(blocksize >= 0 || mode_decode);
203
204         if(format_channels >= 0) {
205                 if(format_channels == 0 || (unsigned)format_channels > FLAC__MAX_CHANNELS)
206                         return usage("ERROR: invalid number of channels '%u', must be > 0 and <= %u\n", format_channels, FLAC__MAX_CHANNELS);
207         }
208         if(format_bps >= 0) {
209                 if(format_bps != 8 && format_bps != 16)
210                         return usage("ERROR: invalid bits per sample '%u' (must be 8 or 16)\n", format_bps);
211         }
212         if(format_sample_rate >= 0) {
213                 if(format_sample_rate == 0 || (unsigned)format_sample_rate > FLAC__MAX_SAMPLE_RATE)
214                         return usage("ERROR: invalid sample rate '%u', must be > 0 and <= %u\n", format_sample_rate, FLAC__MAX_SAMPLE_RATE);
215         }
216         if(!mode_decode && ((unsigned)blocksize < FLAC__MIN_BLOCK_SIZE || (unsigned)blocksize > FLAC__MAX_BLOCK_SIZE)) {
217                 return usage("ERROR: invalid blocksize '%u', must be >= %u and <= %u\n", (unsigned)blocksize, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE);
218         }
219         if(qlp_coeff_precision > 0 && qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION) {
220                 return usage("ERROR: invalid value for -q '%u', must be 0 or >= %u\n", qlp_coeff_precision, FLAC__MIN_QLP_COEFF_PRECISION);
221         }
222
223         /* turn off verbosity if the output stream is going to stdout */
224         if(0 == strcmp(argv[i+1], "-"))
225                 verbose = false;
226
227         if(verbose) {
228                 printf("\n");
229                 printf("flac v%u.%u, Copyright (C) 2000 Josh Coalson\n", FLAC__MAJOR_VERSION, FLAC__MINOR_VERSION);
230                 printf("flac comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are\n");
231                 printf("welcome to redistribute it under certain conditions.  Type `flac' for details.\n\n");
232
233                 if(!mode_decode) {
234                         printf("options:%s -b %u%s -l %u%s%s -q %u -r %u\n",
235                                 lax?" --lax":"", (unsigned)blocksize, do_mid_side?" -m":"", max_lpc_order,
236                                 do_exhaustive_model_search?" -e":"", do_qlp_coeff_prec_search?" -p":"",
237                                 qlp_coeff_precision, (unsigned)rice_optimization_level
238                         );
239                 }
240         }
241
242         if(mode_decode)
243                 if(format_is_wave)
244                         return decode_wav(argv[i], argv[i+1], verbose, skip);
245                 else
246                         return decode_raw(argv[i], argv[i+1], verbose, skip, format_is_big_endian, format_is_unsigned_samples);
247         else
248                 if(format_is_wave)
249                         return encode_wav(argv[i], argv[i+1], verbose, skip, lax, do_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision);
250                 else
251                         return encode_raw(argv[i], argv[i+1], verbose, skip, lax, do_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, format_is_big_endian, format_is_unsigned_samples, format_channels, format_bps, format_sample_rate);
252
253         return 0;
254 }
255
256 int usage(const char *message, ...)
257 {
258         va_list args;
259
260         if(message) {
261                 fprintf(stderr, message);
262                 fprintf(stderr, "\n");
263                 va_start(args, message);
264
265                 (void) vfprintf(stderr, message, args);
266
267                 va_end(args);
268
269         }
270         printf("==============================================================================\n");
271         printf("flac - Command-line FLAC encoder/decoder version %u.%u\n", FLAC__MAJOR_VERSION, FLAC__MINOR_VERSION);
272         printf("Copyright (C) 2000  Josh Coalson\n");
273         printf("\n");
274         printf("This program is free software; you can redistribute it and/or\n");
275         printf("modify it under the terms of the GNU General Public License\n");
276         printf("as published by the Free Software Foundation; either version 2\n");
277         printf("of the License, or (at your option) any later version.\n");
278         printf("\n");
279         printf("This program is distributed in the hope that it will be useful,\n");
280         printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
281         printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
282         printf("GNU General Public License for more details.\n");
283         printf("\n");
284         printf("You should have received a copy of the GNU General Public License\n");
285         printf("along with this program; if not, write to the Free Software\n");
286         printf("Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n");
287         printf("==============================================================================\n");
288         printf("Usage:\n");
289         printf("  flac [options] infile outfile\n");
290         printf("\n");
291         printf("For encoding:\n");
292         printf("  infile may be a PCM RIFF WAVE file or raw samples\n");
293         printf("  outfile will be in FLAC format\n");
294         printf("For decoding, the reverse will be true\n");
295         printf("\n");
296         printf("infile may be - for stdin, outfile may be - for stdout\n");
297         printf("\n");
298         printf("If the unencoded filename ends with '.wav' or -fw is used, it's assumed to be\n");
299         printf("RIFF WAVE.  Otherwise, it's assumed to be raw samples and you have to specify\n");
300         printf("all the format options.  You can force a .wav file to be treated as a raw file\n");
301         printf("using -fr.\n");
302         printf("\n");
303         printf("generic options:\n");
304         printf("  -d : decode (default behavior is encode)\n");
305         printf("  -s : silent (do not write runtime encode/decode statistics to stdout)\n");
306         printf("  --skip samples : can be used both for encoding and decoding\n");
307         printf("encoding options:\n");
308         printf("  --lax : allow encoder to generate non-Subset files\n");
309         printf("  -b blocksize : default is 1152 for -l 0, else 4608; should be 192/576/1152/2304/4608 (unless --lax is used)\n");
310         printf("  -m : try mid-side coding for each frame (stereo input only)\n");
311         printf("  -0 .. -9 : fastest compression .. highest compression, default is -6\n");
312         printf("             these are synonyms for other options:\n");
313         printf("  -0 : synonymous with -l 0\n");
314         printf("  -1 : synonymous with -l 0 -m\n");
315         printf("  -2 : synonymous with -l 0 -m -r # (# is automatically determined by the block size)\n");
316         printf("  -3 : reserved\n");
317         printf("  -4 : synonymous with -l 8\n");
318         printf("  -5 : synonymous with -l 8 -m\n");
319         printf("  -6 : synonymous with -l 8 -m -r # (# is automatically determined by the block size)\n");
320         printf("  -7 : reserved\n");
321         printf("  -8 : synonymous with -l 32 -m -r # (# is automatically determined by the block size)\n");
322         printf("  -9 : synonymous with -l 32 -m -e -r 99 -p (very slow!)\n");
323         printf("  -e : do exhaustive model search (expensive!)\n");
324         printf("  -l max_lpc_order : 0 => use only fixed predictors\n");
325         printf("  -p : do exhaustive search of LP coefficient quantization (expensive!); overrides -q\n");
326         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);
327         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");
328         printf("  -m-, -e-, -p-, --lax- can all be used to turn off a particular option\n");
329         printf("format options:\n");
330         printf("  -fb | -fl : big-endian | little-endian byte order\n");
331         printf("  -fc channels\n");
332         printf("  -fp bits_per_sample\n");
333         printf("  -fs sample_rate : in Hz\n");
334         printf("  -fu : unsigned samples (default is signed)\n");
335         printf("  -fr : force to raw format (even if filename ends in .wav)\n");
336         printf("  -fw : force to RIFF WAVE\n");
337         return 1;
338 }