1 /*
2 * Command line parsing related functions
3 *
4 * Copyright (c) 1999 Mark Taylor
5 * 2000-2012 Robert Hegemann
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23 /* $Id: parse.c,v 1.292.2.2 2012/02/07 13:40:37 robert Exp $ */
24
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28
29 #include <assert.h>
30 #include <ctype.h>
31
32 #ifdef STDC_HEADERS
33 # include <stdio.h>
34 # include <stdlib.h>
35 # include <string.h>
36 #else
37 # ifndef HAVE_STRCHR
38 # define strchr index
39 # define strrchr rindex
40 # endif
41 char *strchr(), *strrchr();
42 # ifndef HAVE_MEMCPY
43 # define memcpy(d, s, n) bcopy ((s), (d), (n))
44 # define memmove(d, s, n) bcopy ((s), (d), (n))
45 # endif
46 #endif
47
48
49 #ifdef HAVE_LIMITS_H
50 # include <limits.h>
51 #endif
52
53 #include "lame.h"
54
55 #include "parse.h"
56 #include "main.h"
57 #include "get_audio.h"
58 #include "version.h"
59 #include "console.h"
60
61 #undef dimension_of
62 #define dimension_of(array) (sizeof(array)/sizeof(array[0]))
63
64 #ifdef WITH_DMALLOC
65 #include <dmalloc.h>
66 #endif
67
68
69 #ifdef HAVE_ICONV
70 #include <iconv.h>
71 #include <errno.h>
72 #endif
73
74 #if defined _ALLOW_INTERNAL_OPTIONS
75 #define INTERNAL_OPTS 1
76 #else
77 #define INTERNAL_OPTS 0
78 #endif
79
80 #if (INTERNAL_OPTS!=0)
81 #include "set_get.h"
82 #define DEV_HELP(a) a
83 #else
84 #define DEV_HELP(a)
85 #endif
86
87 static int const lame_alpha_version_enabled = LAME_ALPHA_VERSION;
88 static int const internal_opts_enabled = INTERNAL_OPTS;
89
90 /* GLOBAL VARIABLES. set by parse_args() */
91 /* we need to clean this up */
92
93 ReaderConfig global_reader = { sf_unknown, 0, 0, 0 };
94 WriterConfig global_writer = { 0 };
95
96 UiConfig global_ui_config = {0,0,0,0};
97
98 DecoderConfig global_decoder;
99
100 RawPCMConfig global_raw_pcm =
101 { /* in_bitwidth */ 16
102 , /* in_signed */ -1
103 , /* in_endian */ ByteOrderLittleEndian
104 };
105
106
107
108 /* possible text encodings */
109 typedef enum TextEncoding
110 { TENC_RAW /* bytes will be stored as-is into ID3 tags, which are Latin1 per definition */
111 , TENC_LATIN1 /* text will be converted from local encoding to Latin1, as ID3 needs it */
112 , TENC_UTF16 /* text will be converted from local encoding to Unicode, as ID3v2 wants it */
113 } TextEncoding;
114
115 #ifdef HAVE_ICONV
116 #define ID3TAGS_EXTENDED
117 /* search for Zero termination in multi-byte strings */
118 static size_t
strlenMultiByte(char const * str,size_t w)119 strlenMultiByte(char const* str, size_t w)
120 {
121 size_t n = 0;
122 if (str != 0) {
123 size_t i, x = 0;
124 for (n = 0; ; ++n) {
125 x = 0;
126 for (i = 0; i < w; ++i) {
127 x += *str++ == 0 ? 1 : 0;
128 }
129 if (x == w) {
130 break;
131 }
132 }
133 }
134 return n;
135 }
136
137
138 static size_t
currCharCodeSize(void)139 currCharCodeSize(void)
140 {
141 size_t n = 1;
142 char dst[32];
143 char* src = "A";
144 char* env_lang = getenv("LANG");
145 char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
146 char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
147 iconv_t xiconv = iconv_open(cur_code, "ISO_8859-1");
148 if (xiconv != (iconv_t)-1) {
149 for (n = 0; n < 32; ++n) {
150 char* i_ptr = src;
151 char* o_ptr = dst;
152 size_t srcln = 1;
153 size_t avail = n;
154 size_t rc = iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
155 if (rc != (size_t)-1) {
156 break;
157 }
158 }
159 iconv_close(xiconv);
160 }
161 return n;
162 }
163
164 #if 0
165 static
166 char* fromLatin1( char* src )
167 {
168 char* dst = 0;
169 if (src != 0) {
170 size_t const l = strlen(src);
171 size_t const n = l*4;
172 dst = calloc(n+4, 4);
173 if (dst != 0) {
174 char* env_lang = getenv("LANG");
175 char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
176 char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
177 iconv_t xiconv = iconv_open(cur_code, "ISO_8859-1");
178 if (xiconv != (iconv_t)-1) {
179 char* i_ptr = src;
180 char* o_ptr = dst;
181 size_t srcln = l;
182 size_t avail = n;
183 iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
184 iconv_close(xiconv);
185 }
186 }
187 }
188 return dst;
189 }
190
191 static
192 char* fromUtf16( char* src )
193 {
194 char* dst = 0;
195 if (src != 0) {
196 size_t const l = strlenMultiByte(src, 2);
197 size_t const n = l*4;
198 dst = calloc(n+4, 4);
199 if (dst != 0) {
200 char* env_lang = getenv("LANG");
201 char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
202 char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
203 iconv_t xiconv = iconv_open(cur_code, "UTF-16LE");
204 if (xiconv != (iconv_t)-1) {
205 char* i_ptr = (char*)src;
206 char* o_ptr = dst;
207 size_t srcln = l*2;
208 size_t avail = n;
209 iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
210 iconv_close(xiconv);
211 }
212 }
213 }
214 return dst;
215 }
216 #endif
217
218 static
toLatin1(char * src)219 char* toLatin1( char* src )
220 {
221 size_t w = currCharCodeSize();
222 char* dst = 0;
223 if (src != 0) {
224 size_t const l = strlenMultiByte(src, w);
225 size_t const n = l*4;
226 dst = calloc(n+4, 4);
227 if (dst != 0) {
228 char* env_lang = getenv("LANG");
229 char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
230 char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
231 iconv_t xiconv = iconv_open("ISO_8859-1//TRANSLIT", cur_code);
232 if (xiconv != (iconv_t)-1) {
233 char* i_ptr = (char*)src;
234 char* o_ptr = dst;
235 size_t srcln = l*w;
236 size_t avail = n;
237 iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
238 iconv_close(xiconv);
239 }
240 }
241 }
242 return dst;
243 }
244
245
246 static
toUtf16(char * src)247 char* toUtf16( char* src )
248 {
249 size_t w = currCharCodeSize();
250 char* dst = 0;
251 if (src != 0) {
252 size_t const l = strlenMultiByte(src, w);
253 size_t const n = (l+1)*4;
254 dst = calloc(n+4, 4);
255 if (dst != 0) {
256 char* env_lang = getenv("LANG");
257 char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
258 char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
259 iconv_t xiconv = iconv_open("UTF-16LE//TRANSLIT", cur_code);
260 dst[0] = 0xff;
261 dst[1] = 0xfe;
262 if (xiconv != (iconv_t)-1) {
263 char* i_ptr = (char*)src;
264 char* o_ptr = &dst[2];
265 size_t srcln = l*w;
266 size_t avail = n;
267 iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
268 iconv_close(xiconv);
269 }
270 }
271 }
272 return dst;
273 }
274 #endif
275
276 #if defined( _WIN32 ) && !defined(__MINGW32__)
277 #define ID3TAGS_EXTENDED
278
toLatin1(char const * s)279 char* toLatin1(char const* s)
280 {
281 return utf8ToLatin1(s);
282 }
283
toUtf16(char const * s)284 unsigned short* toUtf16(char const* s)
285 {
286 return utf8ToUtf16(s);
287 }
288 #endif
289
290
291 static int
set_id3v2tag(lame_global_flags * gfp,int type,unsigned short const * str)292 set_id3v2tag(lame_global_flags* gfp, int type, unsigned short const* str)
293 {
294 switch (type)
295 {
296 case 'a': return id3tag_set_textinfo_utf16(gfp, "TPE1", str);
297 case 't': return id3tag_set_textinfo_utf16(gfp, "TIT2", str);
298 case 'l': return id3tag_set_textinfo_utf16(gfp, "TALB", str);
299 case 'g': return id3tag_set_textinfo_utf16(gfp, "TCON", str);
300 case 'c': return id3tag_set_comment_utf16(gfp, 0, 0, str);
301 case 'n': return id3tag_set_textinfo_utf16(gfp, "TRCK", str);
302 case 'y': return id3tag_set_textinfo_utf16(gfp, "TYER", str);
303 case 'v': return id3tag_set_fieldvalue_utf16(gfp, str);
304 }
305 return 0;
306 }
307
308
309 static int
set_id3tag(lame_global_flags * gfp,int type,char const * str)310 set_id3tag(lame_global_flags* gfp, int type, char const* str)
311 {
312 switch (type)
313 {
314 case 'a': return id3tag_set_artist(gfp, str), 0;
315 case 't': return id3tag_set_title(gfp, str), 0;
316 case 'l': return id3tag_set_album(gfp, str), 0;
317 case 'g': return id3tag_set_genre(gfp, str);
318 case 'c': return id3tag_set_comment(gfp, str), 0;
319 case 'n': return id3tag_set_track(gfp, str);
320 case 'y': return id3tag_set_year(gfp, str), 0;
321 case 'v': return id3tag_set_fieldvalue(gfp, str);
322 }
323 return 0;
324 }
325
326 static int
id3_tag(lame_global_flags * gfp,int type,TextEncoding enc,char * str)327 id3_tag(lame_global_flags* gfp, int type, TextEncoding enc, char* str)
328 {
329 void* x = 0;
330 int result;
331 if (enc == TENC_UTF16 && type != 'v' ) {
332 id3_tag(gfp, type, TENC_LATIN1, str); /* for id3v1 */
333 }
334 switch (enc)
335 {
336 default:
337 #ifdef ID3TAGS_EXTENDED
338 case TENC_LATIN1: x = toLatin1(str); break;
339 case TENC_UTF16: x = toUtf16(str); break;
340 #else
341 case TENC_RAW: x = strdup(str); break;
342 #endif
343 }
344 switch (enc)
345 {
346 default:
347 #ifdef ID3TAGS_EXTENDED
348 case TENC_LATIN1: result = set_id3tag(gfp, type, x); break;
349 case TENC_UTF16: result = set_id3v2tag(gfp, type, x); break;
350 #else
351 case TENC_RAW: result = set_id3tag(gfp, type, x); break;
352 #endif
353 }
354 free(x);
355 return result;
356 }
357
358
359
360
361 /************************************************************************
362 *
363 * license
364 *
365 * PURPOSE: Writes version and license to the file specified by fp
366 *
367 ************************************************************************/
368
369 static int
lame_version_print(FILE * const fp)370 lame_version_print(FILE * const fp)
371 {
372 const char *b = get_lame_os_bitness();
373 const char *v = get_lame_version();
374 const char *u = get_lame_url();
375 const size_t lenb = strlen(b);
376 const size_t lenv = strlen(v);
377 const size_t lenu = strlen(u);
378 const size_t lw = 80; /* line width of terminal in characters */
379 const size_t sw = 16; /* static width of text */
380
381 if (lw >= lenb + lenv + lenu + sw || lw < lenu + 2)
382 /* text fits in 80 chars per line, or line even too small for url */
383 if (lenb > 0)
384 fprintf(fp, "LAME %s version %s (%s)\n\n", b, v, u);
385 else
386 fprintf(fp, "LAME version %s (%s)\n\n", v, u);
387 else {
388 int const n_white_spaces = ((lenu+2) > lw ? 0 : lw-2-lenu);
389 /* text too long, wrap url into next line, right aligned */
390 if (lenb > 0)
391 fprintf(fp, "LAME %s version %s\n%*s(%s)\n\n", b, v, n_white_spaces, "", u);
392 else
393 fprintf(fp, "LAME version %s\n%*s(%s)\n\n", v, n_white_spaces, "", u);
394 }
395 if (lame_alpha_version_enabled)
396 fprintf(fp, "warning: alpha versions should be used for testing only\n\n");
397
398
399 return 0;
400 }
401
402 static int
print_license(FILE * const fp)403 print_license(FILE * const fp)
404 { /* print version & license */
405 lame_version_print(fp);
406 fprintf(fp,
407 "Copyright (c) 1999-2011 by The LAME Project\n"
408 "Copyright (c) 1999,2000,2001 by Mark Taylor\n"
409 "Copyright (c) 1998 by Michael Cheng\n"
410 "Copyright (c) 1995,1996,1997 by Michael Hipp: mpglib\n" "\n");
411 fprintf(fp,
412 "This library is free software; you can redistribute it and/or\n"
413 "modify it under the terms of the GNU Library General Public\n"
414 "License as published by the Free Software Foundation; either\n"
415 "version 2 of the License, or (at your option) any later version.\n"
416 "\n"
417 "This library is distributed in the hope that it will be useful,\n"
418 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
419 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
420 "Library General Public License for more details.\n"
421 "\n"
422 "You should have received a copy of the GNU Library General Public\n"
423 "License along with this program. If not, see\n"
424 "<http://www.gnu.org/licenses/>.\n");
425 return 0;
426 }
427
428
429 /************************************************************************
430 *
431 * usage
432 *
433 * PURPOSE: Writes command line syntax to the file specified by fp
434 *
435 ************************************************************************/
436
437 int
usage(FILE * const fp,const char * ProgramName)438 usage(FILE * const fp, const char *ProgramName)
439 { /* print general syntax */
440 lame_version_print(fp);
441 fprintf(fp,
442 "usage: %s [options] <infile> [outfile]\n"
443 "\n"
444 " <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n"
445 "\n"
446 "Try:\n"
447 " \"%s --help\" for general usage information\n"
448 " or:\n"
449 " \"%s --preset help\" for information on suggested predefined settings\n"
450 " or:\n"
451 " \"%s --longhelp\"\n"
452 " or \"%s -?\" for a complete options list\n\n",
453 ProgramName, ProgramName, ProgramName, ProgramName, ProgramName);
454 return 0;
455 }
456
457
458 /************************************************************************
459 *
460 * usage
461 *
462 * PURPOSE: Writes command line syntax to the file specified by fp
463 * but only the most important ones, to fit on a vt100 terminal
464 *
465 ************************************************************************/
466
467 int
short_help(const lame_global_flags * gfp,FILE * const fp,const char * ProgramName)468 short_help(const lame_global_flags * gfp, FILE * const fp, const char *ProgramName)
469 { /* print short syntax help */
470 lame_version_print(fp);
471 fprintf(fp,
472 "usage: %s [options] <infile> [outfile]\n"
473 "\n"
474 " <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n"
475 "\n" "RECOMMENDED:\n" " lame -V2 input.wav output.mp3\n" "\n", ProgramName);
476 fprintf(fp,
477 "OPTIONS:\n"
478 " -b bitrate set the bitrate, default 128 kbps\n"
479 " -h higher quality, but a little slower. Recommended.\n"
480 " -f fast mode (lower quality)\n"
481 " -V n quality setting for VBR. default n=%i\n"
482 " 0=high quality,bigger files. 9=smaller files\n",
483 lame_get_VBR_q(gfp));
484 fprintf(fp,
485 " --preset type type must be \"medium\", \"standard\", \"extreme\", \"insane\",\n"
486 " or a value for an average desired bitrate and depending\n"
487 " on the value specified, appropriate quality settings will\n"
488 " be used.\n"
489 " \"--preset help\" gives more info on these\n" "\n");
490 fprintf(fp,
491 #if defined(WIN32)
492 " --priority type sets the process priority\n"
493 " 0,1 = Low priority\n"
494 " 2 = normal priority\n"
495 " 3,4 = High priority\n" "\n"
496 #endif
497 #if defined(__OS2__)
498 " --priority type sets the process priority\n"
499 " 0 = Low priority\n"
500 " 1 = Medium priority\n"
501 " 2 = Regular priority\n"
502 " 3 = High priority\n"
503 " 4 = Maximum priority\n" "\n"
504 #endif
505 " --help id3 ID3 tagging related options\n" "\n"
506 DEV_HELP(
507 " --help dev developer options\n" "\n"
508 )
509 " --longhelp full list of options\n" "\n"
510 " --license print License information\n\n"
511 );
512
513 return 0;
514 }
515
516 /************************************************************************
517 *
518 * usage
519 *
520 * PURPOSE: Writes command line syntax to the file specified by fp
521 *
522 ************************************************************************/
523
524 static void
wait_for(FILE * const fp,int lessmode)525 wait_for(FILE * const fp, int lessmode)
526 {
527 if (lessmode) {
528 fflush(fp);
529 getchar();
530 }
531 else {
532 fprintf(fp, "\n");
533 }
534 fprintf(fp, "\n");
535 }
536
537 static void
help_id3tag(FILE * const fp)538 help_id3tag(FILE * const fp)
539 {
540 fprintf(fp,
541 " ID3 tag options:\n"
542 " --tt <title> audio/song title (max 30 chars for version 1 tag)\n"
543 " --ta <artist> audio/song artist (max 30 chars for version 1 tag)\n"
544 " --tl <album> audio/song album (max 30 chars for version 1 tag)\n"
545 " --ty <year> audio/song year of issue (1 to 9999)\n"
546 " --tc <comment> user-defined text (max 30 chars for v1 tag, 28 for v1.1)\n"
547 " --tn <track[/total]> audio/song track number and (optionally) the total\n"
548 " number of tracks on the original recording. (track\n"
549 " and total each 1 to 255. just the track number\n"
550 " creates v1.1 tag, providing a total forces v2.0).\n"
551 " --tg <genre> audio/song genre (name or number in list)\n"
552 " --ti <file> audio/song albumArt (jpeg/png/gif file, v2.3 tag)\n"
553 " --tv <id=value> user-defined frame specified by id and value (v2.3 tag)\n"
554 );
555 fprintf(fp,
556 " --add-id3v2 force addition of version 2 tag\n"
557 " --id3v1-only add only a version 1 tag\n"
558 " --id3v2-only add only a version 2 tag\n"
559 #ifdef ID3TAGS_EXTENDED
560 " --id3v2-utf16 add following options in unicode text encoding\n"
561 " --id3v2-latin1 add following options in latin-1 text encoding\n"
562 #endif
563 " --space-id3v1 pad version 1 tag with spaces instead of nulls\n"
564 " --pad-id3v2 same as '--pad-id3v2-size 128'\n"
565 " --pad-id3v2-size <value> adds version 2 tag, pad with extra <value> bytes\n"
566 " --genre-list print alphabetically sorted ID3 genre list and exit\n"
567 " --ignore-tag-errors ignore errors in values passed for tags\n" "\n"
568 );
569 fprintf(fp,
570 " Note: A version 2 tag will NOT be added unless one of the input fields\n"
571 " won't fit in a version 1 tag (e.g. the title string is longer than 30\n"
572 " characters), or the '--add-id3v2' or '--id3v2-only' options are used,\n"
573 " or output is redirected to stdout.\n"
574 );
575 }
576
577 static void
help_developer_switches(FILE * const fp)578 help_developer_switches(FILE * const fp)
579 {
580 if ( !internal_opts_enabled ) {
581 fprintf(fp,
582 " Note: Almost all of the following switches aren't available in this build!\n\n"
583 );
584 }
585 fprintf(fp,
586 " ATH related:\n"
587 " --noath turns ATH down to a flat noise floor\n"
588 " --athshort ignore GPSYCHO for short blocks, use ATH only\n"
589 " --athonly ignore GPSYCHO completely, use ATH only\n"
590 " --athtype n selects between different ATH types [0-4]\n"
591 " --athlower x lowers ATH by x dB\n"
592 );
593 fprintf(fp,
594 " --athaa-type n ATH auto adjust: 0 'no' else 'loudness based'\n"
595 /** OBSOLETE " --athaa-loudapprox n n=1 total energy or n=2 equal loudness curve\n"*/
596 " --athaa-sensitivity x activation offset in -/+ dB for ATH auto-adjustment\n"
597 "\n");
598 fprintf(fp,
599 " PSY related:\n"
600 " --short use short blocks when appropriate\n"
601 " --noshort do not use short blocks\n"
602 " --allshort use only short blocks\n"
603 );
604 fprintf(fp,
605 "(1) --temporal-masking x x=0 disables, x=1 enables temporal masking effect\n"
606 " --nssafejoint M/S switching criterion\n"
607 " --nsmsfix <arg> M/S switching tuning [effective 0-3.5]\n"
608 "(2) --interch x adjust inter-channel masking ratio\n"
609 " --ns-bass x adjust masking for sfbs 0 - 6 (long) 0 - 5 (short)\n"
610 " --ns-alto x adjust masking for sfbs 7 - 13 (long) 6 - 10 (short)\n"
611 " --ns-treble x adjust masking for sfbs 14 - 21 (long) 11 - 12 (short)\n"
612 );
613 fprintf(fp,
614 " --ns-sfb21 x change ns-treble by x dB for sfb21\n"
615 " --shortthreshold x,y short block switching threshold,\n"
616 " x for L/R/M channel, y for S channel\n"
617 " -Z [n] always do calculate short block maskings\n"
618 " Noise Shaping related:\n"
619 "(1) --substep n use pseudo substep noise shaping method types 0-2\n"
620 "(1) -X n[,m] selects between different noise measurements\n"
621 " n for long block, m for short. if m is omitted, m = n\n"
622 " 1: CBR, ABR and VBR-old encoding modes only\n"
623 " 2: ignored\n"
624 );
625 }
626
627 int
long_help(const lame_global_flags * gfp,FILE * const fp,const char * ProgramName,int lessmode)628 long_help(const lame_global_flags * gfp, FILE * const fp, const char *ProgramName, int lessmode)
629 { /* print long syntax help */
630 lame_version_print(fp);
631 fprintf(fp,
632 "usage: %s [options] <infile> [outfile]\n"
633 "\n"
634 " <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n"
635 "\n" "RECOMMENDED:\n" " lame -V2 input.wav output.mp3\n" "\n", ProgramName);
636 fprintf(fp,
637 "OPTIONS:\n"
638 " Input options:\n"
639 " --scale <arg> scale input (multiply PCM data) by <arg>\n"
640 " --scale-l <arg> scale channel 0 (left) input (multiply PCM data) by <arg>\n"
641 " --scale-r <arg> scale channel 1 (right) input (multiply PCM data) by <arg>\n"
642 #if (defined HAVE_MPGLIB || defined AMIGA_MPEGA)
643 " --mp1input input file is a MPEG Layer I file\n"
644 " --mp2input input file is a MPEG Layer II file\n"
645 " --mp3input input file is a MPEG Layer III file\n"
646 #endif
647 " --nogap <file1> <file2> <...>\n"
648 " gapless encoding for a set of contiguous files\n"
649 " --nogapout <dir>\n"
650 " output dir for gapless encoding (must precede --nogap)\n"
651 " --nogaptags allow the use of VBR tags in gapless encoding\n"
652 );
653 fprintf(fp,
654 "\n"
655 " Input options for RAW PCM:\n"
656 " -r input is raw pcm\n"
657 " -x force byte-swapping of input\n"
658 " -s sfreq sampling frequency of input file (kHz) - default 44.1 kHz\n"
659 " --bitwidth w input bit width is w (default 16)\n"
660 " --signed input is signed (default)\n"
661 " --unsigned input is unsigned\n"
662 " --little-endian input is little-endian (default)\n"
663 " --big-endian input is big-endian\n"
664 );
665
666 wait_for(fp, lessmode);
667 fprintf(fp,
668 " Operational options:\n"
669 " -a downmix from stereo to mono file for mono encoding\n"
670 " -m <mode> (j)oint, (s)imple, (f)orce, (d)ual-mono, (m)ono (l)eft (r)ight\n"
671 " default is (j) or (s) depending on bitrate\n"
672 " joint = joins the best possible of MS and LR stereo\n"
673 " simple = force LR stereo on all frames\n"
674 " force = force MS stereo on all frames.\n"
675 " --preset type type must be \"medium\", \"standard\", \"extreme\", \"insane\",\n"
676 " or a value for an average desired bitrate and depending\n"
677 " on the value specified, appropriate quality settings will\n"
678 " be used.\n"
679 " \"--preset help\" gives more info on these\n"
680 " --comp <arg> choose bitrate to achieve a compression ratio of <arg>\n");
681 fprintf(fp, " --replaygain-fast compute RG fast but slightly inaccurately (default)\n"
682 #ifdef DECODE_ON_THE_FLY
683 " --replaygain-accurate compute RG more accurately and find the peak sample\n"
684 #endif
685 " --noreplaygain disable ReplayGain analysis\n"
686 #ifdef DECODE_ON_THE_FLY
687 " --clipdetect enable --replaygain-accurate and print a message whether\n"
688 " clipping occurs and how far the waveform is from full scale\n"
689 #endif
690 );
691 fprintf(fp,
692 " --flush flush output stream as soon as possible\n"
693 " --freeformat produce a free format bitstream\n"
694 " --decode input=mp3 file, output=wav\n"
695 " --swap-channel swap L/R channels\n"
696 " -t disable writing wav header when using --decode\n");
697
698 wait_for(fp, lessmode);
699 fprintf(fp,
700 " Verbosity:\n"
701 " --disptime <arg>print progress report every arg seconds\n"
702 " -S don't print progress report, VBR histograms\n"
703 " --nohist disable VBR histogram display\n"
704 " --quiet don't print anything on screen\n"
705 " --silent don't print anything on screen, but fatal errors\n"
706 " --brief print more useful information\n"
707 " --verbose print a lot of useful information\n" "\n");
708 fprintf(fp,
709 " Noise shaping & psycho acoustic algorithms:\n"
710 " -q <arg> <arg> = 0...9. Default -q 5 \n"
711 " -q 0: Highest quality, very slow \n"
712 " -q 9: Poor quality, but fast \n"
713 " -h Same as -q 2. Recommended.\n"
714 " -f Same as -q 7. Fast, ok quality\n");
715
716 wait_for(fp, lessmode);
717 fprintf(fp,
718 " CBR (constant bitrate, the default) options:\n"
719 " -b <bitrate> set the bitrate in kbps, default 128 kbps\n"
720 " --cbr enforce use of constant bitrate\n"
721 "\n"
722 " ABR options:\n"
723 " --abr <bitrate> specify average bitrate desired (instead of quality)\n" "\n");
724 fprintf(fp,
725 " VBR options:\n"
726 " -V n quality setting for VBR. default n=%i\n"
727 " 0=high quality,bigger files. 9=smaller files\n"
728 " -v the same as -V 4\n"
729 " --vbr-old use old variable bitrate (VBR) routine\n"
730 " --vbr-new use new variable bitrate (VBR) routine (default)\n"
731 " -Y lets LAME ignore noise in sfb21, like in CBR\n"
732 ,
733 lame_get_VBR_q(gfp));
734 fprintf(fp,
735 " -b <bitrate> specify minimum allowed bitrate, default 32 kbps\n"
736 " -B <bitrate> specify maximum allowed bitrate, default 320 kbps\n"
737 " -F strictly enforce the -b option, for use with players that\n"
738 " do not support low bitrate mp3\n"
739 " -t disable writing LAME Tag\n"
740 " -T enable and force writing LAME Tag\n");
741
742 wait_for(fp, lessmode);
743 DEV_HELP(
744 help_developer_switches(fp);
745 wait_for(fp, lessmode);
746 )
747
748 fprintf(fp,
749 " MP3 header/stream options:\n"
750 " -e <emp> de-emphasis n/5/c (obsolete)\n"
751 " -c mark as copyright\n"
752 " -o mark as non-original\n"
753 " -p error protection. adds 16 bit checksum to every frame\n"
754 " (the checksum is computed correctly)\n"
755 " --nores disable the bit reservoir\n"
756 " --strictly-enforce-ISO comply as much as possible to ISO MPEG spec\n");
757 fprintf(fp,
758 " --buffer-constraint <constraint> available values for constraint:\n"
759 " default, strict, maximum\n"
760 "\n"
761 );
762 fprintf(fp,
763 " Filter options:\n"
764 " --lowpass <freq> frequency(kHz), lowpass filter cutoff above freq\n"
765 " --lowpass-width <freq> frequency(kHz) - default 15%% of lowpass freq\n"
766 " --highpass <freq> frequency(kHz), highpass filter cutoff below freq\n"
767 " --highpass-width <freq> frequency(kHz) - default 15%% of highpass freq\n");
768 fprintf(fp,
769 " --resample <sfreq> sampling frequency of output file(kHz)- default=automatic\n");
770
771 wait_for(fp, lessmode);
772 help_id3tag(fp);
773 fprintf(fp,
774 #if defined(WIN32)
775 "\n\nMS-Windows-specific options:\n"
776 " --priority <type> sets the process priority:\n"
777 " 0,1 = Low priority (IDLE_PRIORITY_CLASS)\n"
778 " 2 = normal priority (NORMAL_PRIORITY_CLASS, default)\n"
779 " 3,4 = High priority (HIGH_PRIORITY_CLASS))\n"
780 " Note: Calling '--priority' without a parameter will select priority 0.\n"
781 #endif
782 #if defined(__OS2__)
783 "\n\nOS/2-specific options:\n"
784 " --priority <type> sets the process priority:\n"
785 " 0 = Low priority (IDLE, delta = 0)\n"
786 " 1 = Medium priority (IDLE, delta = +31)\n"
787 " 2 = Regular priority (REGULAR, delta = -31)\n"
788 " 3 = High priority (REGULAR, delta = 0)\n"
789 " 4 = Maximum priority (REGULAR, delta = +31)\n"
790 " Note: Calling '--priority' without a parameter will select priority 0.\n"
791 #endif
792 "\nMisc:\n --license print License information\n\n"
793 );
794
795 #if defined(HAVE_NASM)
796 wait_for(fp, lessmode);
797 fprintf(fp,
798 " Platform specific:\n"
799 " --noasm <instructions> disable assembly optimizations for mmx/3dnow/sse\n");
800 wait_for(fp, lessmode);
801 #endif
802
803 display_bitrates(fp);
804
805 return 0;
806 }
807
808 static void
display_bitrate(FILE * const fp,const char * const version,const int d,const int indx)809 display_bitrate(FILE * const fp, const char *const version, const int d, const int indx)
810 {
811 int i;
812 int nBitrates = 14;
813 if (d == 4)
814 nBitrates = 8;
815
816
817 fprintf(fp,
818 "\nMPEG-%-3s layer III sample frequencies (kHz): %2d %2d %g\n"
819 "bitrates (kbps):", version, 32 / d, 48 / d, 44.1 / d);
820 for (i = 1; i <= nBitrates; i++)
821 fprintf(fp, " %2i", lame_get_bitrate(indx, i));
822 fprintf(fp, "\n");
823 }
824
825 int
display_bitrates(FILE * const fp)826 display_bitrates(FILE * const fp)
827 {
828 display_bitrate(fp, "1", 1, 1);
829 display_bitrate(fp, "2", 2, 0);
830 display_bitrate(fp, "2.5", 4, 0);
831 fprintf(fp, "\n");
832 fflush(fp);
833 return 0;
834 }
835
836
837 /* note: for presets it would be better to externalize them in a file.
838 suggestion: lame --preset <file-name> ...
839 or: lame --preset my-setting ... and my-setting is defined in lame.ini
840 */
841
842 /*
843 Note from GB on 08/25/2002:
844 I am merging --presets and --alt-presets. Old presets are now aliases for
845 corresponding abr values from old alt-presets. This way we now have a
846 unified preset system, and I hope than more people will use the new tuned
847 presets instead of the old unmaintained ones.
848 */
849
850
851
852 /************************************************************************
853 *
854 * usage
855 *
856 * PURPOSE: Writes presetting info to #stdout#
857 *
858 ************************************************************************/
859
860
861 static void
presets_longinfo_dm(FILE * msgfp)862 presets_longinfo_dm(FILE * msgfp)
863 {
864 fprintf(msgfp,
865 "\n"
866 "The --preset switches are aliases over LAME settings.\n"
867 "\n" "\n");
868 fprintf(msgfp,
869 "To activate these presets:\n"
870 "\n" " For VBR modes (generally highest quality):\n" "\n");
871 fprintf(msgfp,
872 " \"--preset medium\" This preset should provide near transparency\n"
873 " to most people on most music.\n"
874 "\n"
875 " \"--preset standard\" This preset should generally be transparent\n"
876 " to most people on most music and is already\n"
877 " quite high in quality.\n" "\n");
878 fprintf(msgfp,
879 " \"--preset extreme\" If you have extremely good hearing and similar\n"
880 " equipment, this preset will generally provide\n"
881 " slightly higher quality than the \"standard\"\n"
882 " mode.\n" "\n");
883 fprintf(msgfp,
884 " For CBR 320kbps (highest quality possible from the --preset switches):\n"
885 "\n"
886 " \"--preset insane\" This preset will usually be overkill for most\n"
887 " people and most situations, but if you must\n"
888 " have the absolute highest quality with no\n"
889 " regard to filesize, this is the way to go.\n" "\n");
890 fprintf(msgfp,
891 " For ABR modes (high quality per given bitrate but not as high as VBR):\n"
892 "\n"
893 " \"--preset <kbps>\" Using this preset will usually give you good\n"
894 " quality at a specified bitrate. Depending on the\n"
895 " bitrate entered, this preset will determine the\n");
896 fprintf(msgfp,
897 " optimal settings for that particular situation.\n"
898 " While this approach works, it is not nearly as\n"
899 " flexible as VBR, and usually will not attain the\n"
900 " same level of quality as VBR at higher bitrates.\n" "\n");
901 fprintf(msgfp,
902 "The following options are also available for the corresponding profiles:\n"
903 "\n"
904 " standard\n"
905 " extreme\n"
906 " insane\n"
907 " <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n"
908 " simply specify a bitrate. For example:\n"
909 " \"--preset 185\" activates this\n"
910 " preset and uses 185 as an average kbps.\n" "\n");
911 fprintf(msgfp,
912 " \"cbr\" - If you use the ABR mode (read above) with a significant\n"
913 " bitrate such as 80, 96, 112, 128, 160, 192, 224, 256, 320,\n"
914 " you can use the \"cbr\" option to force CBR mode encoding\n"
915 " instead of the standard abr mode. ABR does provide higher\n"
916 " quality but CBR may be useful in situations such as when\n"
917 " streaming an mp3 over the internet may be important.\n" "\n");
918 fprintf(msgfp,
919 " For example:\n"
920 "\n"
921 " \"--preset standard <input file> <output file>\"\n"
922 " or \"--preset cbr 192 <input file> <output file>\"\n"
923 " or \"--preset 172 <input file> <output file>\"\n"
924 " or \"--preset extreme <input file> <output file>\"\n" "\n" "\n");
925 fprintf(msgfp,
926 "A few aliases are also available for ABR mode:\n"
927 "phone => 16kbps/mono phon+/lw/mw-eu/sw => 24kbps/mono\n"
928 "mw-us => 40kbps/mono voice => 56kbps/mono\n"
929 "fm/radio/tape => 112kbps hifi => 160kbps\n"
930 "cd => 192kbps studio => 256kbps\n");
931 }
932
933
934 static int
presets_set(lame_t gfp,int fast,int cbr,const char * preset_name,const char * ProgramName)935 presets_set(lame_t gfp, int fast, int cbr, const char *preset_name, const char *ProgramName)
936 {
937 int mono = 0;
938
939 if ((strcmp(preset_name, "help") == 0) && (fast < 1)
940 && (cbr < 1)) {
941 lame_version_print(stdout);
942 presets_longinfo_dm(stdout);
943 return -1;
944 }
945
946 /*aliases for compatibility with old presets */
947
948 if (strcmp(preset_name, "phone") == 0) {
949 preset_name = "16";
950 mono = 1;
951 }
952 if ((strcmp(preset_name, "phon+") == 0) ||
953 (strcmp(preset_name, "lw") == 0) ||
954 (strcmp(preset_name, "mw-eu") == 0) || (strcmp(preset_name, "sw") == 0)) {
955 preset_name = "24";
956 mono = 1;
957 }
958 if (strcmp(preset_name, "mw-us") == 0) {
959 preset_name = "40";
960 mono = 1;
961 }
962 if (strcmp(preset_name, "voice") == 0) {
963 preset_name = "56";
964 mono = 1;
965 }
966 if (strcmp(preset_name, "fm") == 0) {
967 preset_name = "112";
968 }
969 if ((strcmp(preset_name, "radio") == 0) || (strcmp(preset_name, "tape") == 0)) {
970 preset_name = "112";
971 }
972 if (strcmp(preset_name, "hifi") == 0) {
973 preset_name = "160";
974 }
975 if (strcmp(preset_name, "cd") == 0) {
976 preset_name = "192";
977 }
978 if (strcmp(preset_name, "studio") == 0) {
979 preset_name = "256";
980 }
981
982 if (strcmp(preset_name, "medium") == 0) {
983 lame_set_VBR_q(gfp, 4);
984 lame_set_VBR(gfp, vbr_default);
985 return 0;
986 }
987
988 if (strcmp(preset_name, "standard") == 0) {
989 lame_set_VBR_q(gfp, 2);
990 lame_set_VBR(gfp, vbr_default);
991 return 0;
992 }
993
994 else if (strcmp(preset_name, "extreme") == 0) {
995 lame_set_VBR_q(gfp, 0);
996 lame_set_VBR(gfp, vbr_default);
997 return 0;
998 }
999
1000 else if ((strcmp(preset_name, "insane") == 0) && (fast < 1)) {
1001
1002 lame_set_preset(gfp, INSANE);
1003
1004 return 0;
1005 }
1006
1007 /* Generic ABR Preset */
1008 if (((atoi(preset_name)) > 0) && (fast < 1)) {
1009 if ((atoi(preset_name)) >= 8 && (atoi(preset_name)) <= 320) {
1010 lame_set_preset(gfp, atoi(preset_name));
1011
1012 if (cbr == 1)
1013 lame_set_VBR(gfp, vbr_off);
1014
1015 if (mono == 1) {
1016 lame_set_mode(gfp, MONO);
1017 }
1018
1019 return 0;
1020
1021 }
1022 else {
1023 lame_version_print(Console_IO.Error_fp);
1024 error_printf("Error: The bitrate specified is out of the valid range for this preset\n"
1025 "\n"
1026 "When using this mode you must enter a value between \"32\" and \"320\"\n"
1027 "\n" "For further information try: \"%s --preset help\"\n", ProgramName);
1028 return -1;
1029 }
1030 }
1031
1032 lame_version_print(Console_IO.Error_fp);
1033 error_printf("Error: You did not enter a valid profile and/or options with --preset\n"
1034 "\n"
1035 "Available profiles are:\n"
1036 "\n"
1037 " medium\n"
1038 " standard\n"
1039 " extreme\n"
1040 " insane\n"
1041 " <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n"
1042 " simply specify a bitrate. For example:\n"
1043 " \"--preset 185\" activates this\n"
1044 " preset and uses 185 as an average kbps.\n" "\n");
1045 error_printf(" Some examples:\n"
1046 "\n"
1047 " or \"%s --preset standard <input file> <output file>\"\n"
1048 " or \"%s --preset cbr 192 <input file> <output file>\"\n"
1049 " or \"%s --preset 172 <input file> <output file>\"\n"
1050 " or \"%s --preset extreme <input file> <output file>\"\n"
1051 "\n"
1052 "For further information try: \"%s --preset help\"\n", ProgramName, ProgramName,
1053 ProgramName, ProgramName, ProgramName);
1054 return -1;
1055 }
1056
1057 static void
genre_list_handler(int num,const char * name,void * cookie)1058 genre_list_handler(int num, const char *name, void *cookie)
1059 {
1060 (void) cookie;
1061 console_printf("%3d %s\n", num, name);
1062 }
1063
1064
1065 /************************************************************************
1066 *
1067 * parse_args
1068 *
1069 * PURPOSE: Sets encoding parameters to the specifications of the
1070 * command line. Default settings are used for parameters
1071 * not specified in the command line.
1072 *
1073 * If the input file is in WAVE or AIFF format, the sampling frequency is read
1074 * from the AIFF header.
1075 *
1076 * The input and output filenames are read into #inpath# and #outpath#.
1077 *
1078 ************************************************************************/
1079
1080 /* would use real "strcasecmp" but it isn't portable */
1081 static int
local_strcasecmp(const char * s1,const char * s2)1082 local_strcasecmp(const char *s1, const char *s2)
1083 {
1084 unsigned char c1;
1085 unsigned char c2;
1086
1087 do {
1088 c1 = (unsigned char) tolower(*s1);
1089 c2 = (unsigned char) tolower(*s2);
1090 if (!c1) {
1091 break;
1092 }
1093 ++s1;
1094 ++s2;
1095 } while (c1 == c2);
1096 return c1 - c2;
1097 }
1098
1099 static int
local_strncasecmp(const char * s1,const char * s2,int n)1100 local_strncasecmp(const char *s1, const char *s2, int n)
1101 {
1102 unsigned char c1 = 0;
1103 unsigned char c2 = 0;
1104 int cnt = 0;
1105
1106 do {
1107 if (cnt == n) {
1108 break;
1109 }
1110 c1 = (unsigned char) tolower(*s1);
1111 c2 = (unsigned char) tolower(*s2);
1112 if (!c1) {
1113 break;
1114 }
1115 ++s1;
1116 ++s2;
1117 ++cnt;
1118 } while (c1 == c2);
1119 return c1 - c2;
1120 }
1121
1122
1123
1124 /* LAME is a simple frontend which just uses the file extension */
1125 /* to determine the file type. Trying to analyze the file */
1126 /* contents is well beyond the scope of LAME and should not be added. */
1127 static int
filename_to_type(const char * FileName)1128 filename_to_type(const char *FileName)
1129 {
1130 size_t len = strlen(FileName);
1131
1132 if (len < 4)
1133 return sf_unknown;
1134
1135 FileName += len - 4;
1136 if (0 == local_strcasecmp(FileName, ".mpg"))
1137 return sf_mp123;
1138 if (0 == local_strcasecmp(FileName, ".mp1"))
1139 return sf_mp123;
1140 if (0 == local_strcasecmp(FileName, ".mp2"))
1141 return sf_mp123;
1142 if (0 == local_strcasecmp(FileName, ".mp3"))
1143 return sf_mp123;
1144 if (0 == local_strcasecmp(FileName, ".wav"))
1145 return sf_wave;
1146 if (0 == local_strcasecmp(FileName, ".aif"))
1147 return sf_aiff;
1148 if (0 == local_strcasecmp(FileName, ".raw"))
1149 return sf_raw;
1150 if (0 == local_strcasecmp(FileName, ".ogg"))
1151 return sf_ogg;
1152 return sf_unknown;
1153 }
1154
1155 static int
resample_rate(double freq)1156 resample_rate(double freq)
1157 {
1158 if (freq >= 1.e3)
1159 freq *= 1.e-3;
1160
1161 switch ((int) freq) {
1162 case 8:
1163 return 8000;
1164 case 11:
1165 return 11025;
1166 case 12:
1167 return 12000;
1168 case 16:
1169 return 16000;
1170 case 22:
1171 return 22050;
1172 case 24:
1173 return 24000;
1174 case 32:
1175 return 32000;
1176 case 44:
1177 return 44100;
1178 case 48:
1179 return 48000;
1180 default:
1181 error_printf("Illegal resample frequency: %.3f kHz\n", freq);
1182 return 0;
1183 }
1184 }
1185
1186 #ifdef _WIN32
1187 #define SLASH '\\'
1188 #elif __OS2__
1189 #define SLASH '\\'
1190 #else
1191 #define SLASH '/'
1192 #endif
1193
1194 static
scanPath(char const * s,char const ** a,char const ** b)1195 size_t scanPath(char const* s, char const** a, char const** b)
1196 {
1197 char const* s1 = s;
1198 char const* s2 = s;
1199 if (s != 0) {
1200 for (; *s; ++s) {
1201 switch (*s) {
1202 case SLASH:
1203 case ':':
1204 s2 = s;
1205 break;
1206 }
1207 }
1208 if (*s2 == ':') {
1209 ++s2;
1210 }
1211 }
1212 if (a) {
1213 *a = s1;
1214 }
1215 if (b) {
1216 *b = s2;
1217 }
1218 return s2-s1;
1219 }
1220
1221 static
scanBasename(char const * s,char const ** a,char const ** b)1222 size_t scanBasename(char const* s, char const** a, char const** b)
1223 {
1224 char const* s1 = s;
1225 char const* s2 = s;
1226 if (s != 0) {
1227 for (; *s; ++s) {
1228 switch (*s) {
1229 case SLASH:
1230 case ':':
1231 s1 = s2 = s;
1232 break;
1233 case '.':
1234 s2 = s;
1235 break;
1236 }
1237 }
1238 if (s2 == s1) {
1239 s2 = s;
1240 }
1241 if (*s1 == SLASH || *s1 == ':') {
1242 ++s1;
1243 }
1244 }
1245 if (a != 0) {
1246 *a = s1;
1247 }
1248 if (b != 0) {
1249 *b = s2;
1250 }
1251 return s2-s1;
1252 }
1253
1254 static
isCommonSuffix(char const * s_ext)1255 int isCommonSuffix(char const* s_ext)
1256 {
1257 char const* suffixes[] =
1258 { ".WAV", ".RAW", ".MP1", ".MP2"
1259 , ".MP3", ".MPG", ".MPA", ".CDA"
1260 , ".OGG", ".AIF", ".AIFF", ".AU"
1261 , ".SND", ".FLAC", ".WV", ".OFR"
1262 , ".TAK", ".MP4", ".M4A", ".PCM"
1263 , ".W64"
1264 };
1265 size_t i;
1266 for (i = 0; i < dimension_of(suffixes); ++i) {
1267 if (local_strcasecmp(s_ext, suffixes[i]) == 0) {
1268 return 1;
1269 }
1270 }
1271 return 0;
1272 }
1273
1274
1275 static
generateOutPath(lame_t gfp,char const * inPath,char const * outDir,char * outPath)1276 int generateOutPath(lame_t gfp, char const* inPath, char const* outDir, char* outPath)
1277 {
1278 size_t const max_path = PATH_MAX;
1279 char const* s_ext = lame_get_decode_only(gfp) ? ".wav" : ".mp3";
1280 #if 1
1281 size_t i = 0;
1282 int out_dir_used = 0;
1283
1284 if (outDir != 0 && outDir[0] != 0) {
1285 out_dir_used = 1;
1286 while (*outDir) {
1287 outPath[i++] = *outDir++;
1288 if (i >= max_path) {
1289 goto err_generateOutPath;
1290 }
1291 }
1292 if (i > 0 && outPath[i-1] != SLASH) {
1293 outPath[i++] = SLASH;
1294 if (i >= max_path) {
1295 goto err_generateOutPath;
1296 }
1297 }
1298 outPath[i] = 0;
1299 }
1300 else {
1301 char const* pa;
1302 char const* pb;
1303 size_t j, n = scanPath(inPath, &pa, &pb);
1304 if (i+n >= max_path) {
1305 goto err_generateOutPath;
1306 }
1307 for (j = 0; j < n; ++j) {
1308 outPath[i++] = pa[j];
1309 }
1310 if (n > 0) {
1311 outPath[i++] = SLASH;
1312 if (i >= max_path) {
1313 goto err_generateOutPath;
1314 }
1315 }
1316 outPath[i] = 0;
1317 }
1318 {
1319 int replace_suffix = 0;
1320 char const* na;
1321 char const* nb;
1322 size_t j, n = scanBasename(inPath, &na, &nb);
1323 if (i+n >= max_path) {
1324 goto err_generateOutPath;
1325 }
1326 for (j = 0; j < n; ++j) {
1327 outPath[i++] = na[j];
1328 }
1329 outPath[i] = 0;
1330 if (isCommonSuffix(nb) == 1) {
1331 replace_suffix = 1;
1332 if (out_dir_used == 0) {
1333 if (local_strcasecmp(nb, s_ext) == 0) {
1334 replace_suffix = 0;
1335 }
1336 }
1337 }
1338 if (replace_suffix == 0) {
1339 while (*nb) {
1340 outPath[i++] = *nb++;
1341 if (i >= max_path) {
1342 goto err_generateOutPath;
1343 }
1344 }
1345 outPath[i] = 0;
1346 }
1347 }
1348 if (i+5 >= max_path) {
1349 goto err_generateOutPath;
1350 }
1351 while (*s_ext) {
1352 outPath[i++] = *s_ext++;
1353 }
1354 outPath[i] = 0;
1355 return 0;
1356 err_generateOutPath:
1357 error_printf( "error: output file name too long" );
1358 return 1;
1359 #else
1360 strncpy(outPath, inPath, PATH_MAX + 1 - 4);
1361 strncat(outPath, s_ext, 4);
1362 return 0;
1363 #endif
1364 }
1365
1366
1367 static int
set_id3_albumart(lame_t gfp,char const * file_name)1368 set_id3_albumart(lame_t gfp, char const* file_name)
1369 {
1370 int ret = -1;
1371 FILE *fpi = 0;
1372 char *albumart = 0;
1373
1374 if (file_name == 0) {
1375 return 0;
1376 }
1377 fpi = lame_fopen(file_name, "rb");
1378 if (!fpi) {
1379 ret = 1;
1380 }
1381 else {
1382 size_t size;
1383
1384 fseek(fpi, 0, SEEK_END);
1385 size = ftell(fpi);
1386 fseek(fpi, 0, SEEK_SET);
1387 albumart = (char *)malloc(size);
1388 if (!albumart) {
1389 ret = 2;
1390 }
1391 else {
1392 if (fread(albumart, 1, size, fpi) != size) {
1393 ret = 3;
1394 }
1395 else {
1396 ret = id3tag_set_albumart(gfp, albumart, size) ? 4 : 0;
1397 }
1398 free(albumart);
1399 }
1400 fclose(fpi);
1401 }
1402 switch (ret) {
1403 case 1: error_printf("Could not find: '%s'.\n", file_name); break;
1404 case 2: error_printf("Insufficient memory for reading the albumart.\n"); break;
1405 case 3: error_printf("Read error: '%s'.\n", file_name); break;
1406 case 4: error_printf("Unsupported image: '%s'.\nSpecify JPEG/PNG/GIF image\n", file_name); break;
1407 default: break;
1408 }
1409 return ret;
1410 }
1411
1412
1413 enum ID3TAG_MODE
1414 { ID3TAG_MODE_DEFAULT
1415 , ID3TAG_MODE_V1_ONLY
1416 , ID3TAG_MODE_V2_ONLY
1417 };
1418
1419 /* Ugly, NOT final version */
1420
1421 #define T_IF(str) if ( 0 == local_strcasecmp (token,str) ) {
1422 #define T_ELIF(str) } else if ( 0 == local_strcasecmp (token,str) ) {
1423 #define T_ELIF_INTERNAL(str) } else if (internal_opts_enabled && (0 == local_strcasecmp (token,str)) ) {
1424 #define T_ELIF2(str1,str2) } else if ( 0 == local_strcasecmp (token,str1) || 0 == local_strcasecmp (token,str2) ) {
1425 #define T_ELSE } else {
1426 #define T_END }
1427
1428 int
parse_args(lame_global_flags * gfp,int argc,char ** argv,char * const inPath,char * const outPath,char ** nogap_inPath,int * num_nogap)1429 parse_args(lame_global_flags * gfp, int argc, char **argv,
1430 char *const inPath, char *const outPath, char **nogap_inPath, int *num_nogap)
1431 {
1432 char outDir[1024] = "";
1433 int input_file = 0; /* set to 1 if we parse an input file name */
1434 int i;
1435 int autoconvert = 0;
1436 double val;
1437 int nogap = 0;
1438 int nogap_tags = 0; /* set to 1 to use VBR tags in NOGAP mode */
1439 const char *ProgramName = argv[0];
1440 int count_nogap = 0;
1441 int noreplaygain = 0; /* is RG explicitly disabled by the user */
1442 int id3tag_mode = ID3TAG_MODE_DEFAULT;
1443 int ignore_tag_errors = 0; /* Ignore errors in values passed for tags */
1444 #ifdef ID3TAGS_EXTENDED
1445 enum TextEncoding id3_tenc = TENC_UTF16;
1446 #else
1447 enum TextEncoding id3_tenc = TENC_LATIN1;
1448 #endif
1449
1450 inPath[0] = '\0';
1451 outPath[0] = '\0';
1452 /* turn on display options. user settings may turn them off below */
1453 global_ui_config.silent = 0;
1454 global_ui_config.brhist = 1;
1455 global_decoder.mp3_delay = 0;
1456 global_decoder.mp3_delay_set = 0;
1457 global_decoder.disable_wav_header = 0;
1458 global_ui_config.print_clipping_info = 0;
1459 id3tag_init(gfp);
1460
1461 /* process args */
1462 for (i = 0; ++i < argc;) {
1463 char c;
1464 char *token;
1465 char *arg;
1466 char *nextArg;
1467 int argUsed;
1468
1469 token = argv[i];
1470 if (*token++ == '-') {
1471 argUsed = 0;
1472 nextArg = i + 1 < argc ? argv[i + 1] : "";
1473
1474 if (!*token) { /* The user wants to use stdin and/or stdout. */
1475 input_file = 1;
1476 if (inPath[0] == '\0')
1477 strncpy(inPath, argv[i], PATH_MAX + 1);
1478 else if (outPath[0] == '\0')
1479 strncpy(outPath, argv[i], PATH_MAX + 1);
1480 }
1481 if (*token == '-') { /* GNU style */
1482 token++;
1483
1484 T_IF("resample")
1485 argUsed = 1;
1486 (void) lame_set_out_samplerate(gfp, resample_rate(atof(nextArg)));
1487
1488 T_ELIF("vbr-old")
1489 lame_set_VBR(gfp, vbr_rh);
1490
1491 T_ELIF("vbr-new")
1492 lame_set_VBR(gfp, vbr_mt);
1493
1494 T_ELIF("vbr-mtrh")
1495 lame_set_VBR(gfp, vbr_mtrh);
1496
1497 T_ELIF("cbr")
1498 lame_set_VBR(gfp, vbr_off);
1499
1500 T_ELIF("abr")
1501 /* values larger than 8000 are bps (like Fraunhofer), so it's strange to get 320000 bps MP3 when specifying 8000 bps MP3 */
1502 int m = atoi(nextArg);
1503 argUsed = 1;
1504 if (m >= 8000) {
1505 m = (m + 500) / 1000;
1506 }
1507 if (m > 320) {
1508 m = 320;
1509 }
1510 if (m < 8) {
1511 m = 8;
1512 }
1513 lame_set_VBR(gfp, vbr_abr);
1514 lame_set_VBR_mean_bitrate_kbps(gfp, m);
1515
1516 T_ELIF("r3mix")
1517 lame_set_preset(gfp, R3MIX);
1518
1519 T_ELIF("bitwidth")
1520 argUsed = 1;
1521 global_raw_pcm.in_bitwidth = atoi(nextArg);
1522
1523 T_ELIF("signed")
1524 global_raw_pcm.in_signed = 1;
1525
1526 T_ELIF("unsigned")
1527 global_raw_pcm.in_signed = 0;
1528
1529 T_ELIF("little-endian")
1530 global_raw_pcm.in_endian = ByteOrderLittleEndian;
1531
1532 T_ELIF("big-endian")
1533 global_raw_pcm.in_endian = ByteOrderBigEndian;
1534
1535 T_ELIF("mp1input")
1536 global_reader.input_format = sf_mp1;
1537
1538 T_ELIF("mp2input")
1539 global_reader.input_format = sf_mp2;
1540
1541 T_ELIF("mp3input")
1542 global_reader.input_format = sf_mp3;
1543
1544 T_ELIF("ogginput")
1545 error_printf("sorry, vorbis support in LAME is deprecated.\n");
1546 return -1;
1547 #if INTERNAL_OPTS
1548 T_ELIF_INTERNAL("noshort")
1549 (void) lame_set_no_short_blocks(gfp, 1);
1550
1551 T_ELIF_INTERNAL("short")
1552 (void) lame_set_no_short_blocks(gfp, 0);
1553
1554 T_ELIF_INTERNAL("allshort")
1555 (void) lame_set_force_short_blocks(gfp, 1);
1556 #endif
1557
1558 T_ELIF("decode")
1559 (void) lame_set_decode_only(gfp, 1);
1560
1561 T_ELIF("flush")
1562 global_writer.flush_write = 1;
1563
1564 T_ELIF("decode-mp3delay")
1565 global_decoder.mp3_delay = atoi(nextArg);
1566 global_decoder.mp3_delay_set = 1;
1567 argUsed = 1;
1568
1569 T_ELIF("nores")
1570 lame_set_disable_reservoir(gfp, 1);
1571
1572 T_ELIF("strictly-enforce-ISO")
1573 lame_set_strict_ISO(gfp, MDB_STRICT_ISO);
1574
1575 T_ELIF("buffer-constraint")
1576 argUsed = 1;
1577 if (strcmp(nextArg, "default") == 0)
1578 (void) lame_set_strict_ISO(gfp, MDB_DEFAULT);
1579 else if (strcmp(nextArg, "strict") == 0)
1580 (void) lame_set_strict_ISO(gfp, MDB_STRICT_ISO);
1581 else if (strcmp(nextArg, "maximum") == 0)
1582 (void) lame_set_strict_ISO(gfp, MDB_MAXIMUM);
1583 else {
1584 error_printf("unknown buffer constraint '%s'\n", nextArg);
1585 return -1;
1586 }
1587
1588 T_ELIF("scale")
1589 argUsed = 1;
1590 (void) lame_set_scale(gfp, (float) atof(nextArg));
1591
1592 T_ELIF("scale-l")
1593 argUsed = 1;
1594 (void) lame_set_scale_left(gfp, (float) atof(nextArg));
1595
1596 T_ELIF("scale-r")
1597 argUsed = 1;
1598 (void) lame_set_scale_right(gfp, (float) atof(nextArg));
1599
1600 T_ELIF("noasm")
1601 argUsed = 1;
1602 if (!strcmp(nextArg, "mmx"))
1603 (void) lame_set_asm_optimizations(gfp, MMX, 0);
1604 if (!strcmp(nextArg, "3dnow"))
1605 (void) lame_set_asm_optimizations(gfp, AMD_3DNOW, 0);
1606 if (!strcmp(nextArg, "sse"))
1607 (void) lame_set_asm_optimizations(gfp, SSE, 0);
1608
1609 T_ELIF("freeformat")
1610 lame_set_free_format(gfp, 1);
1611
1612 T_ELIF("replaygain-fast")
1613 lame_set_findReplayGain(gfp, 1);
1614
1615 #ifdef DECODE_ON_THE_FLY
1616 T_ELIF("replaygain-accurate")
1617 lame_set_decode_on_the_fly(gfp, 1);
1618 lame_set_findReplayGain(gfp, 1);
1619 #endif
1620
1621 T_ELIF("noreplaygain")
1622 noreplaygain = 1;
1623 lame_set_findReplayGain(gfp, 0);
1624
1625
1626 #ifdef DECODE_ON_THE_FLY
1627 T_ELIF("clipdetect")
1628 global_ui_config.print_clipping_info = 1;
1629 lame_set_decode_on_the_fly(gfp, 1);
1630 #endif
1631
1632 T_ELIF("nohist")
1633 global_ui_config.brhist = 0;
1634
1635 #if defined(__OS2__) || defined(WIN32)
1636 T_ELIF("priority")
1637 char *endptr;
1638 int priority = (int) strtol(nextArg, &endptr, 10);
1639 if (endptr != nextArg) {
1640 argUsed = 1;
1641 }
1642 setProcessPriority(priority);
1643 #endif
1644
1645 /* options for ID3 tag */
1646 #ifdef ID3TAGS_EXTENDED
1647 T_ELIF2("id3v2-utf16","id3v2-ucs2") /* id3v2-ucs2 for compatibility only */
1648 id3_tenc = TENC_UTF16;
1649 id3tag_add_v2(gfp);
1650
1651 T_ELIF("id3v2-latin1")
1652 id3_tenc = TENC_LATIN1;
1653 id3tag_add_v2(gfp);
1654 #endif
1655
1656 T_ELIF("tt")
1657 argUsed = 1;
1658 id3_tag(gfp, 't', id3_tenc, nextArg);
1659
1660 T_ELIF("ta")
1661 argUsed = 1;
1662 id3_tag(gfp, 'a', id3_tenc, nextArg);
1663
1664 T_ELIF("tl")
1665 argUsed = 1;
1666 id3_tag(gfp, 'l', id3_tenc, nextArg);
1667
1668 T_ELIF("ty")
1669 argUsed = 1;
1670 id3_tag(gfp, 'y', id3_tenc, nextArg);
1671
1672 T_ELIF("tc")
1673 argUsed = 1;
1674 id3_tag(gfp, 'c', id3_tenc, nextArg);
1675
1676 T_ELIF("tn")
1677 int ret = id3_tag(gfp, 'n', id3_tenc, nextArg);
1678 argUsed = 1;
1679 if (ret != 0) {
1680 if (0 == ignore_tag_errors) {
1681 if (id3tag_mode == ID3TAG_MODE_V1_ONLY) {
1682 if (global_ui_config.silent < 9) {
1683 error_printf("The track number has to be between 1 and 255 for ID3v1.\n");
1684 }
1685 return -1;
1686 }
1687 else if (id3tag_mode == ID3TAG_MODE_V2_ONLY) {
1688 /* track will be stored as-is in ID3v2 case, so no problem here */
1689 }
1690 else {
1691 if (global_ui_config.silent < 9) {
1692 error_printf("The track number has to be between 1 and 255 for ID3v1, ignored for ID3v1.\n");
1693 }
1694 }
1695 }
1696 }
1697
1698 T_ELIF("tg")
1699 int ret = id3_tag(gfp, 'g', id3_tenc, nextArg);
1700 argUsed = 1;
1701 if (ret != 0) {
1702 if (0 == ignore_tag_errors) {
1703 if (ret == -1) {
1704 error_printf("Unknown ID3v1 genre number: '%s'.\n", nextArg);
1705 return -1;
1706 }
1707 else if (ret == -2) {
1708 if (id3tag_mode == ID3TAG_MODE_V1_ONLY) {
1709 error_printf("Unknown ID3v1 genre: '%s'.\n", nextArg);
1710 return -1;
1711 }
1712 else if (id3tag_mode == ID3TAG_MODE_V2_ONLY) {
1713 /* genre will be stored as-is in ID3v2 case, so no problem here */
1714 }
1715 else {
1716 if (global_ui_config.silent < 9) {
1717 error_printf("Unknown ID3v1 genre: '%s'. Setting ID3v1 genre to 'Other'\n", nextArg);
1718 }
1719 }
1720 }
1721 else {
1722 if (global_ui_config.silent < 10)
1723 error_printf("Internal error.\n");
1724 return -1;
1725 }
1726 }
1727 }
1728
1729 T_ELIF("tv")
1730 argUsed = 1;
1731 if (id3_tag(gfp, 'v', id3_tenc, nextArg)) {
1732 if (global_ui_config.silent < 9) {
1733 error_printf("Invalid field value: '%s'. Ignored\n", nextArg);
1734 }
1735 }
1736
1737 T_ELIF("ti")
1738 argUsed = 1;
1739 if (set_id3_albumart(gfp, nextArg) != 0) {
1740 if (! ignore_tag_errors) {
1741 return -1;
1742 }
1743 }
1744
1745 T_ELIF("ignore-tag-errors")
1746 ignore_tag_errors = 1;
1747
1748 T_ELIF("add-id3v2")
1749 id3tag_add_v2(gfp);
1750
1751 T_ELIF("id3v1-only")
1752 id3tag_v1_only(gfp);
1753 id3tag_mode = ID3TAG_MODE_V1_ONLY;
1754
1755 T_ELIF("id3v2-only")
1756 id3tag_v2_only(gfp);
1757 id3tag_mode = ID3TAG_MODE_V2_ONLY;
1758
1759 T_ELIF("space-id3v1")
1760 id3tag_space_v1(gfp);
1761
1762 T_ELIF("pad-id3v2")
1763 id3tag_pad_v2(gfp);
1764
1765 T_ELIF("pad-id3v2-size")
1766 int n = atoi(nextArg);
1767 n = n <= 128000 ? n : 128000;
1768 n = n >= 0 ? n : 0;
1769 id3tag_set_pad(gfp, n);
1770 argUsed = 1;
1771
1772
1773 T_ELIF("genre-list")
1774 id3tag_genre_list(genre_list_handler, NULL);
1775 return -2;
1776
1777
1778 T_ELIF("lowpass")
1779 val = atof(nextArg);
1780 argUsed = 1;
1781 if (val < 0) {
1782 lame_set_lowpassfreq(gfp, -1);
1783 }
1784 else {
1785 /* useful are 0.001 kHz...50 kHz, 50 Hz...50000 Hz */
1786 if (val < 0.001 || val > 50000.) {
1787 error_printf("Must specify lowpass with --lowpass freq, freq >= 0.001 kHz\n");
1788 return -1;
1789 }
1790 lame_set_lowpassfreq(gfp, (int) (val * (val < 50. ? 1.e3 : 1.e0) + 0.5));
1791 }
1792
1793 T_ELIF("lowpass-width")
1794 val = atof(nextArg);
1795 argUsed = 1;
1796 /* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */
1797 if (val < 0.001 || val > 50000.) {
1798 error_printf
1799 ("Must specify lowpass width with --lowpass-width freq, freq >= 0.001 kHz\n");
1800 return -1;
1801 }
1802 lame_set_lowpasswidth(gfp, (int) (val * (val < 16. ? 1.e3 : 1.e0) + 0.5));
1803
1804 T_ELIF("highpass")
1805 val = atof(nextArg);
1806 argUsed = 1;
1807 if (val < 0.0) {
1808 lame_set_highpassfreq(gfp, -1);
1809 }
1810 else {
1811 /* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */
1812 if (val < 0.001 || val > 50000.) {
1813 error_printf("Must specify highpass with --highpass freq, freq >= 0.001 kHz\n");
1814 return -1;
1815 }
1816 lame_set_highpassfreq(gfp, (int) (val * (val < 16. ? 1.e3 : 1.e0) + 0.5));
1817 }
1818
1819 T_ELIF("highpass-width")
1820 val = atof(nextArg);
1821 argUsed = 1;
1822 /* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */
1823 if (val < 0.001 || val > 50000.) {
1824 error_printf
1825 ("Must specify highpass width with --highpass-width freq, freq >= 0.001 kHz\n");
1826 return -1;
1827 }
1828 lame_set_highpasswidth(gfp, (int) val);
1829
1830 T_ELIF("comp")
1831 argUsed = 1;
1832 val = atof(nextArg);
1833 if (val < 1.0) {
1834 error_printf("Must specify compression ratio >= 1.0\n");
1835 return -1;
1836 }
1837 lame_set_compression_ratio(gfp, (float) val);
1838 #if INTERNAL_OPTS
1839 T_ELIF_INTERNAL("notemp")
1840 (void) lame_set_useTemporal(gfp, 0);
1841
1842 T_ELIF_INTERNAL("interch")
1843 argUsed = 1;
1844 (void) lame_set_interChRatio(gfp, (float) atof(nextArg));
1845
1846 T_ELIF_INTERNAL("temporal-masking")
1847 argUsed = 1;
1848 (void) lame_set_useTemporal(gfp, atoi(nextArg) ? 1 : 0);
1849
1850 T_ELIF_INTERNAL("nspsytune")
1851 ;
1852
1853 T_ELIF_INTERNAL("nssafejoint")
1854 lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2);
1855
1856 T_ELIF_INTERNAL("nsmsfix")
1857 argUsed = 1;
1858 (void) lame_set_msfix(gfp, atof(nextArg));
1859
1860 T_ELIF_INTERNAL("ns-bass")
1861 argUsed = 1;
1862 {
1863 double d;
1864 int k;
1865 d = atof(nextArg);
1866 k = (int) (d * 4);
1867 if (k < -32)
1868 k = -32;
1869 if (k > 31)
1870 k = 31;
1871 if (k < 0)
1872 k += 64;
1873 lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 2));
1874 }
1875
1876 T_ELIF_INTERNAL("ns-alto")
1877 argUsed = 1;
1878 {
1879 double d;
1880 int k;
1881 d = atof(nextArg);
1882 k = (int) (d * 4);
1883 if (k < -32)
1884 k = -32;
1885 if (k > 31)
1886 k = 31;
1887 if (k < 0)
1888 k += 64;
1889 lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 8));
1890 }
1891
1892 T_ELIF_INTERNAL("ns-treble")
1893 argUsed = 1;
1894 {
1895 double d;
1896 int k;
1897 d = atof(nextArg);
1898 k = (int) (d * 4);
1899 if (k < -32)
1900 k = -32;
1901 if (k > 31)
1902 k = 31;
1903 if (k < 0)
1904 k += 64;
1905 lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 14));
1906 }
1907
1908 T_ELIF_INTERNAL("ns-sfb21")
1909 /* to be compatible with Naoki's original code,
1910 * ns-sfb21 specifies how to change ns-treble for sfb21 */
1911 argUsed = 1;
1912 {
1913 double d;
1914 int k;
1915 d = atof(nextArg);
1916 k = (int) (d * 4);
1917 if (k < -32)
1918 k = -32;
1919 if (k > 31)
1920 k = 31;
1921 if (k < 0)
1922 k += 64;
1923 lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 20));
1924 }
1925 #endif
1926 /* some more GNU-ish options could be added
1927 * brief => few messages on screen (name, status report)
1928 * o/output file => specifies output filename
1929 * O => stdout
1930 * i/input file => specifies input filename
1931 * I => stdin
1932 */
1933 T_ELIF("quiet")
1934 global_ui_config.silent = 10; /* on a scale from 1 to 10 be very silent */
1935
1936 T_ELIF("silent")
1937 global_ui_config.silent = 9;
1938
1939 T_ELIF("brief")
1940 global_ui_config.silent = -5; /* print few info on screen */
1941
1942 T_ELIF("verbose")
1943 global_ui_config.silent = -10; /* print a lot on screen */
1944
1945 T_ELIF2("version", "license")
1946 print_license(stdout);
1947 return -2;
1948
1949 T_ELIF2("help", "usage")
1950 if (0 == local_strncasecmp(nextArg, "id3", 3)) {
1951 help_id3tag(stdout);
1952 }
1953 else if (0 == local_strncasecmp(nextArg, "dev", 3)) {
1954 help_developer_switches(stdout);
1955 }
1956 else {
1957 short_help(gfp, stdout, ProgramName);
1958 }
1959 return -2;
1960
1961 T_ELIF("longhelp")
1962 long_help(gfp, stdout, ProgramName, 0 /* lessmode=NO */ );
1963 return -2;
1964
1965 T_ELIF("?")
1966 #ifdef __unix__
1967 FILE *fp = popen("less -Mqc", "w");
1968 long_help(gfp, fp, ProgramName, 0 /* lessmode=NO */ );
1969 pclose(fp);
1970 #else
1971 long_help(gfp, stdout, ProgramName, 1 /* lessmode=YES */ );
1972 #endif
1973 return -2;
1974
1975 T_ELIF2("preset", "alt-preset")
1976 argUsed = 1;
1977 {
1978 int fast = 0, cbr = 0;
1979
1980 while ((strcmp(nextArg, "fast") == 0) || (strcmp(nextArg, "cbr") == 0)) {
1981
1982 if ((strcmp(nextArg, "fast") == 0) && (fast < 1))
1983 fast = 1;
1984 if ((strcmp(nextArg, "cbr") == 0) && (cbr < 1))
1985 cbr = 1;
1986
1987 argUsed++;
1988 nextArg = i + argUsed < argc ? argv[i + argUsed] : "";
1989 }
1990
1991 if (presets_set(gfp, fast, cbr, nextArg, ProgramName) < 0)
1992 return -1;
1993 }
1994
1995 T_ELIF("disptime")
1996 argUsed = 1;
1997 global_ui_config.update_interval = (float) atof(nextArg);
1998
1999 T_ELIF("nogaptags")
2000 nogap_tags = 1;
2001
2002 T_ELIF("nogapout")
2003 /* FIXME: replace strcpy by safer strncpy */
2004 strcpy(outPath, nextArg);
2005 argUsed = 1;
2006
2007 T_ELIF("out-dir")
2008 /* FIXME: replace strcpy by safer strncpy */
2009 strcpy(outDir, nextArg);
2010 argUsed = 1;
2011
2012 T_ELIF("nogap")
2013 nogap = 1;
2014
2015 T_ELIF("swap-channel")
2016 global_reader.swap_channel = 1;
2017 #if INTERNAL_OPTS
2018 T_ELIF_INTERNAL("tune") /*without helptext */
2019 argUsed = 1;
2020 lame_set_tune(gfp, (float) atof(nextArg));
2021
2022 T_ELIF_INTERNAL("shortthreshold") {
2023 float x, y;
2024 int n = sscanf(nextArg, "%f,%f", &x, &y);
2025 if (n == 1) {
2026 y = x;
2027 }
2028 argUsed = 1;
2029 (void) lame_set_short_threshold(gfp, x, y);
2030 }
2031
2032 T_ELIF_INTERNAL("maskingadjust") /*without helptext */
2033 argUsed = 1;
2034 (void) lame_set_maskingadjust(gfp, (float) atof(nextArg));
2035
2036 T_ELIF_INTERNAL("maskingadjustshort") /*without helptext */
2037 argUsed = 1;
2038 (void) lame_set_maskingadjust_short(gfp, (float) atof(nextArg));
2039
2040 T_ELIF_INTERNAL("athcurve") /*without helptext */
2041 argUsed = 1;
2042 (void) lame_set_ATHcurve(gfp, (float) atof(nextArg));
2043
2044 T_ELIF_INTERNAL("no-preset-tune") /*without helptext */
2045 (void) lame_set_preset_notune(gfp, 0);
2046
2047 T_ELIF_INTERNAL("substep")
2048 argUsed = 1;
2049 (void) lame_set_substep(gfp, atoi(nextArg));
2050
2051 T_ELIF_INTERNAL("sbgain") /*without helptext */
2052 argUsed = 1;
2053 (void) lame_set_subblock_gain(gfp, atoi(nextArg));
2054
2055 T_ELIF_INTERNAL("sfscale") /*without helptext */
2056 (void) lame_set_sfscale(gfp, 1);
2057
2058 T_ELIF_INTERNAL("noath")
2059 (void) lame_set_noATH(gfp, 1);
2060
2061 T_ELIF_INTERNAL("athonly")
2062 (void) lame_set_ATHonly(gfp, 1);
2063
2064 T_ELIF_INTERNAL("athshort")
2065 (void) lame_set_ATHshort(gfp, 1);
2066
2067 T_ELIF_INTERNAL("athlower")
2068 argUsed = 1;
2069 (void) lame_set_ATHlower(gfp, (float) atof(nextArg));
2070
2071 T_ELIF_INTERNAL("athtype")
2072 argUsed = 1;
2073 (void) lame_set_ATHtype(gfp, atoi(nextArg));
2074
2075 T_ELIF_INTERNAL("athaa-type") /* switch for developing, no DOCU */
2076 argUsed = 1; /* once was 1:Gaby, 2:Robert, 3:Jon, else:off */
2077 lame_set_athaa_type(gfp, atoi(nextArg)); /* now: 0:off else:Jon */
2078 #endif
2079 T_ELIF ("athaa-sensitivity")
2080 argUsed=1;
2081 lame_set_athaa_sensitivity(gfp, (float) atof(nextArg));
2082
2083 T_ELIF_INTERNAL("debug-file") /* switch for developing, no DOCU */
2084 argUsed = 1; /* file name to print debug info into */
2085 {
2086 set_debug_file(nextArg);
2087 }
2088
2089 T_ELSE {
2090 error_printf("%s: unrecognized option --%s\n", ProgramName, token);
2091 return -1;
2092 }
2093 T_END i += argUsed;
2094
2095 }
2096 else {
2097 while ((c = *token++) != '\0') {
2098 arg = *token ? token : nextArg;
2099 switch (c) {
2100 case 'm':
2101 argUsed = 1;
2102
2103 switch (*arg) {
2104 case 's':
2105 (void) lame_set_mode(gfp, STEREO);
2106 break;
2107 case 'd':
2108 (void) lame_set_mode(gfp, DUAL_CHANNEL);
2109 break;
2110 case 'f':
2111 lame_set_force_ms(gfp, 1);
2112 /* FALLTHROUGH */
2113 case 'j':
2114 (void) lame_set_mode(gfp, JOINT_STEREO);
2115 break;
2116 case 'm':
2117 (void) lame_set_mode(gfp, MONO);
2118 break;
2119 case 'l':
2120 (void) lame_set_mode(gfp, MONO);
2121 (void) lame_set_scale_left(gfp, 2);
2122 (void) lame_set_scale_right(gfp, 0);
2123 break;
2124 case 'r':
2125 (void) lame_set_mode(gfp, MONO);
2126 (void) lame_set_scale_left(gfp, 0);
2127 (void) lame_set_scale_right(gfp, 2);
2128 break;
2129 case 'a':
2130 (void) lame_set_mode(gfp, JOINT_STEREO);
2131 break;
2132 default:
2133 error_printf("%s: -m mode must be s/d/j/f/m not %s\n", ProgramName,
2134 arg);
2135 return -1;
2136 }
2137 break;
2138
2139 case 'V':
2140 argUsed = 1;
2141 /* to change VBR default look in lame.h */
2142 if (lame_get_VBR(gfp) == vbr_off)
2143 lame_set_VBR(gfp, vbr_default);
2144 lame_set_VBR_quality(gfp, (float)atof(arg));
2145 break;
2146 case 'v':
2147 /* to change VBR default look in lame.h */
2148 if (lame_get_VBR(gfp) == vbr_off)
2149 lame_set_VBR(gfp, vbr_default);
2150 break;
2151
2152 case 'q':
2153 argUsed = 1;
2154 (void) lame_set_quality(gfp, atoi(arg));
2155 break;
2156 case 'f':
2157 (void) lame_set_quality(gfp, 7);
2158 break;
2159 case 'h':
2160 (void) lame_set_quality(gfp, 2);
2161 break;
2162
2163 case 's':
2164 argUsed = 1;
2165 val = atof(arg);
2166 val = (int) (val * (val <= 192 ? 1.e3 : 1.e0) + 0.5);
2167 global_reader.input_samplerate = (int)val;
2168 (void) lame_set_in_samplerate(gfp, (int)val);
2169 break;
2170 case 'b':
2171 argUsed = 1;
2172 lame_set_brate(gfp, atoi(arg));
2173 lame_set_VBR_min_bitrate_kbps(gfp, lame_get_brate(gfp));
2174 break;
2175 case 'B':
2176 argUsed = 1;
2177 lame_set_VBR_max_bitrate_kbps(gfp, atoi(arg));
2178 break;
2179 case 'F':
2180 lame_set_VBR_hard_min(gfp, 1);
2181 break;
2182 case 't': /* dont write VBR tag */
2183 (void) lame_set_bWriteVbrTag(gfp, 0);
2184 global_decoder.disable_wav_header = 1;
2185 break;
2186 case 'T': /* do write VBR tag */
2187 (void) lame_set_bWriteVbrTag(gfp, 1);
2188 nogap_tags = 1;
2189 global_decoder.disable_wav_header = 0;
2190 break;
2191 case 'r': /* force raw pcm input file */
2192 #if defined(LIBSNDFILE)
2193 error_printf
2194 ("WARNING: libsndfile may ignore -r and perform fseek's on the input.\n"
2195 "Compile without libsndfile if this is a problem.\n");
2196 #endif
2197 global_reader.input_format = sf_raw;
2198 break;
2199 case 'x': /* force byte swapping */
2200 global_reader.swapbytes = 1;
2201 break;
2202 case 'p': /* (jo) error_protection: add crc16 information to stream */
2203 lame_set_error_protection(gfp, 1);
2204 break;
2205 case 'a': /* autoconvert input file from stereo to mono - for mono mp3 encoding */
2206 autoconvert = 1;
2207 (void) lame_set_mode(gfp, MONO);
2208 break;
2209 case 'd': /*(void) lame_set_allow_diff_short( gfp, 1 ); */
2210 case 'k': /*lame_set_lowpassfreq(gfp, -1);
2211 lame_set_highpassfreq(gfp, -1); */
2212 error_printf("WARNING: -%c is obsolete.\n", c);
2213 break;
2214 case 'S':
2215 global_ui_config.silent = 5;
2216 break;
2217 case 'X':
2218 /* experimental switch -X:
2219 the differnt types of quant compare are tough
2220 to communicate to endusers, so they shouldn't
2221 bother to toy around with them
2222 */
2223 {
2224 int x, y;
2225 int n = sscanf(arg, "%d,%d", &x, &y);
2226 if (n == 1) {
2227 y = x;
2228 }
2229 argUsed = 1;
2230 if (internal_opts_enabled) {
2231 lame_set_quant_comp(gfp, x);
2232 lame_set_quant_comp_short(gfp, y);
2233 }
2234 }
2235 break;
2236 case 'Y':
2237 lame_set_experimentalY(gfp, 1);
2238 break;
2239 case 'Z':
2240 /* experimental switch -Z:
2241 */
2242 {
2243 int n = 1;
2244 argUsed = sscanf(arg, "%d", &n);
2245 /*if (internal_opts_enabled)*/
2246 {
2247 lame_set_experimentalZ(gfp, n);
2248 }
2249 }
2250 break;
2251 case 'e':
2252 argUsed = 1;
2253
2254 switch (*arg) {
2255 case 'n':
2256 lame_set_emphasis(gfp, 0);
2257 break;
2258 case '5':
2259 lame_set_emphasis(gfp, 1);
2260 break;
2261 case 'c':
2262 lame_set_emphasis(gfp, 3);
2263 break;
2264 default:
2265 error_printf("%s: -e emp must be n/5/c not %s\n", ProgramName, arg);
2266 return -1;
2267 }
2268 break;
2269 case 'c':
2270 lame_set_copyright(gfp, 1);
2271 break;
2272 case 'o':
2273 lame_set_original(gfp, 0);
2274 break;
2275
2276 case '?':
2277 long_help(gfp, stdout, ProgramName, 0 /* LESSMODE=NO */ );
2278 return -1;
2279
2280 default:
2281 error_printf("%s: unrecognized option -%c\n", ProgramName, c);
2282 return -1;
2283 }
2284 if (argUsed) {
2285 if (arg == token)
2286 token = ""; /* no more from token */
2287 else
2288 ++i; /* skip arg we used */
2289 arg = "";
2290 argUsed = 0;
2291 }
2292 }
2293 }
2294 }
2295 else {
2296 if (nogap) {
2297 if ((num_nogap != NULL) && (count_nogap < *num_nogap)) {
2298 strncpy(nogap_inPath[count_nogap++], argv[i], PATH_MAX + 1);
2299 input_file = 1;
2300 }
2301 else {
2302 /* sorry, calling program did not allocate enough space */
2303 error_printf
2304 ("Error: 'nogap option'. Calling program does not allow nogap option, or\n"
2305 "you have exceeded maximum number of input files for the nogap option\n");
2306 *num_nogap = -1;
2307 return -1;
2308 }
2309 }
2310 else {
2311 /* normal options: inputfile [outputfile], and
2312 either one can be a '-' for stdin/stdout */
2313 if (inPath[0] == '\0') {
2314 strncpy(inPath, argv[i], PATH_MAX + 1);
2315 input_file = 1;
2316 }
2317 else {
2318 if (outPath[0] == '\0')
2319 strncpy(outPath, argv[i], PATH_MAX + 1);
2320 else {
2321 error_printf("%s: excess arg %s\n", ProgramName, argv[i]);
2322 return -1;
2323 }
2324 }
2325 }
2326 }
2327 } /* loop over args */
2328
2329 if (!input_file) {
2330 usage(Console_IO.Console_fp, ProgramName);
2331 return -1;
2332 }
2333
2334 if (inPath[0] == '-')
2335 global_ui_config.silent = (global_ui_config.silent <= 1 ? 1 : global_ui_config.silent);
2336 #ifdef WIN32
2337 else
2338 dosToLongFileName(inPath);
2339 #endif
2340
2341 if (outPath[0] == '\0' && count_nogap == 0) {
2342 if (inPath[0] == '-') {
2343 /* if input is stdin, default output is stdout */
2344 strcpy(outPath, "-");
2345 }
2346 else {
2347 if (generateOutPath(gfp, inPath, outDir, outPath) != 0) {
2348 return -1;
2349 }
2350 }
2351 }
2352
2353 /* RG is enabled by default */
2354 if (!noreplaygain)
2355 lame_set_findReplayGain(gfp, 1);
2356
2357 /* disable VBR tags with nogap unless the VBR tags are forced */
2358 if (nogap && lame_get_bWriteVbrTag(gfp) && nogap_tags == 0) {
2359 console_printf("Note: Disabling VBR Xing/Info tag since it interferes with --nogap\n");
2360 lame_set_bWriteVbrTag(gfp, 0);
2361 }
2362
2363 /* some file options not allowed with stdout */
2364 if (outPath[0] == '-') {
2365 (void) lame_set_bWriteVbrTag(gfp, 0); /* turn off VBR tag */
2366 }
2367
2368 /* if user did not explicitly specify input is mp3, check file name */
2369 if (global_reader.input_format == sf_unknown)
2370 global_reader.input_format = filename_to_type(inPath);
2371
2372 #if !(defined HAVE_MPGLIB || defined AMIGA_MPEGA)
2373 if (is_mpeg_file_format(global_reader.input_format)) {
2374 error_printf("Error: libmp3lame not compiled with mpg123 *decoding* support \n");
2375 return -1;
2376 }
2377 #endif
2378
2379 /* default guess for number of channels */
2380 if (autoconvert)
2381 (void) lame_set_num_channels(gfp, 2);
2382 else if (MONO == lame_get_mode(gfp))
2383 (void) lame_set_num_channels(gfp, 1);
2384 else
2385 (void) lame_set_num_channels(gfp, 2);
2386
2387 if (lame_get_free_format(gfp)) {
2388 if (lame_get_brate(gfp) < 8 || lame_get_brate(gfp) > 640) {
2389 error_printf("For free format, specify a bitrate between 8 and 640 kbps\n");
2390 error_printf("with the -b <bitrate> option\n");
2391 return -1;
2392 }
2393 }
2394 if (num_nogap != NULL)
2395 *num_nogap = count_nogap;
2396 return 0;
2397 }
2398
2399
2400 /* end of parse.c */
2401