aboutsummaryrefslogtreecommitdiff
path: root/frontend/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/parse.c')
-rw-r--r--frontend/parse.c2341
1 files changed, 2341 insertions, 0 deletions
diff --git a/frontend/parse.c b/frontend/parse.c
new file mode 100644
index 0000000..2c6a10c
--- /dev/null
+++ b/frontend/parse.c
@@ -0,0 +1,2341 @@
+/*
+ * Command line parsing related functions
+ *
+ * Copyright (c) 1999 Mark Taylor
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* $Id: parse.c,v 1.247.2.8 2009/12/11 22:44:25 robert Exp $ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+
+#ifdef STDC_HEADERS
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+#else
+# ifndef HAVE_STRCHR
+# define strchr index
+# define strrchr rindex
+# endif
+char *strchr(), *strrchr();
+# ifndef HAVE_MEMCPY
+# define memcpy(d, s, n) bcopy ((s), (d), (n))
+# define memmove(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#ifdef __OS2__
+#include <os2.h>
+#define PRTYC_IDLE 1
+#define PRTYC_REGULAR 2
+#define PRTYD_MINIMUM -31
+#define PRTYD_MAXIMUM 31
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include "lame.h"
+#include "set_get.h"
+
+#include "brhist.h"
+#include "parse.h"
+#include "main.h"
+#include "get_audio.h"
+#include "version.h"
+#include "console.h"
+
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+#ifdef HAVE_ICONV
+#include <iconv.h>
+#include <errno.h>
+#endif
+
+#if defined DEBUG || _DEBUG || _ALLOW_INTERNAL_OPTIONS
+#define INTERNAL_OPTS 1
+#else
+#define INTERNAL_OPTS LAME_ALPHA_VERSION
+#endif
+
+#if (INTERNAL_OPTS!=0)
+#define DEV_HELP(a) a
+#else
+#define DEV_HELP(a)
+#endif
+
+
+
+/* GLOBAL VARIABLES. set by parse_args() */
+/* we need to clean this up */
+sound_file_format input_format;
+int swapbytes = 0; /* force byte swapping default=0 */
+int silent; /* Verbosity */
+int ignore_tag_errors; /* Ignore errors in values passed for tags */
+int brhist;
+float update_interval; /* to use Frank's time status display */
+int mp3_delay; /* to adjust the number of samples truncated
+ during decode */
+int mp3_delay_set; /* user specified the value of the mp3 encoder
+ delay to assume for decoding */
+
+int disable_wav_header;
+mp3data_struct mp3input_data; /* used by MP3 */
+int print_clipping_info; /* print info whether waveform clips */
+
+
+int in_signed = -1;
+
+enum ByteOrder in_endian = ByteOrderLittleEndian;
+
+int in_bitwidth = 16;
+
+int flush_write = 0;
+
+
+
+/**
+ * Long Filename support for the WIN32 platform
+ *
+ */
+#ifdef WIN32
+#include <winbase.h>
+static void
+dosToLongFileName(char *fn)
+{
+ const int MSIZE = PATH_MAX + 1 - 4; /* we wanna add ".mp3" later */
+ WIN32_FIND_DATAA lpFindFileData;
+ HANDLE h = FindFirstFileA(fn, &lpFindFileData);
+ if (h != INVALID_HANDLE_VALUE) {
+ int a;
+ char *q, *p;
+ FindClose(h);
+ for (a = 0; a < MSIZE; a++) {
+ if ('\0' == lpFindFileData.cFileName[a])
+ break;
+ }
+ if (a >= MSIZE || a == 0)
+ return;
+ q = strrchr(fn, '\\');
+ p = strrchr(fn, '/');
+ if (p - q > 0)
+ q = p;
+ if (q == NULL)
+ q = strrchr(fn, ':');
+ if (q == NULL)
+ strncpy(fn, lpFindFileData.cFileName, a);
+ else {
+ a += q - fn + 1;
+ if (a >= MSIZE)
+ return;
+ strncpy(++q, lpFindFileData.cFileName, MSIZE - a);
+ }
+ }
+}
+#endif
+#if defined(WIN32)
+#include <windows.h>
+BOOL
+SetPriorityClassMacro(DWORD p)
+{
+ HANDLE op = GetCurrentProcess();
+ return SetPriorityClass(op, p);
+}
+
+static void
+setWin32Priority(lame_global_flags * gfp, int Priority)
+{
+ switch (Priority) {
+ case 0:
+ case 1:
+ SetPriorityClassMacro(IDLE_PRIORITY_CLASS);
+ console_printf("==> Priority set to Low.\n");
+ break;
+ default:
+ case 2:
+ SetPriorityClassMacro(NORMAL_PRIORITY_CLASS);
+ console_printf("==> Priority set to Normal.\n");
+ break;
+ case 3:
+ case 4:
+ SetPriorityClassMacro(HIGH_PRIORITY_CLASS);
+ console_printf("==> Priority set to High.\n");
+ break;
+ }
+}
+#endif
+
+
+#if defined(__OS2__)
+/* OS/2 priority functions */
+static int
+setOS2Priority(lame_global_flags * gfp, int Priority)
+{
+ int rc;
+
+ switch (Priority) {
+
+ case 0:
+ rc = DosSetPriority(0, /* Scope: only one process */
+ PRTYC_IDLE, /* select priority class (idle, regular, etc) */
+ 0, /* set delta */
+ 0); /* Assume current process */
+ console_printf("==> Priority set to 0 (Low priority).\n");
+ break;
+
+ case 1:
+ rc = DosSetPriority(0, /* Scope: only one process */
+ PRTYC_IDLE, /* select priority class (idle, regular, etc) */
+ PRTYD_MAXIMUM, /* set delta */
+ 0); /* Assume current process */
+ console_printf("==> Priority set to 1 (Medium priority).\n");
+ break;
+
+ case 2:
+ rc = DosSetPriority(0, /* Scope: only one process */
+ PRTYC_REGULAR, /* select priority class (idle, regular, etc) */
+ PRTYD_MINIMUM, /* set delta */
+ 0); /* Assume current process */
+ console_printf("==> Priority set to 2 (Regular priority).\n");
+ break;
+
+ case 3:
+ rc = DosSetPriority(0, /* Scope: only one process */
+ PRTYC_REGULAR, /* select priority class (idle, regular, etc) */
+ 0, /* set delta */
+ 0); /* Assume current process */
+ console_printf("==> Priority set to 3 (High priority).\n");
+ break;
+
+ case 4:
+ rc = DosSetPriority(0, /* Scope: only one process */
+ PRTYC_REGULAR, /* select priority class (idle, regular, etc) */
+ PRTYD_MAXIMUM, /* set delta */
+ 0); /* Assume current process */
+ console_printf("==> Priority set to 4 (Maximum priority). I hope you enjoy it :)\n");
+ break;
+
+ default:
+ console_printf("==> Invalid priority specified! Assuming idle priority.\n");
+ }
+
+
+ return 0;
+}
+#endif
+
+
+extern int
+id3tag_set_textinfo_ucs2(lame_global_flags* gfp, char const* id, unsigned short const* text);
+
+extern int
+id3tag_set_comment_ucs2(lame_global_flags* gfp, char const* lng, unsigned short const* desc, unsigned short const* text);
+
+/* possible text encodings */
+typedef enum TextEncoding
+{ TENC_RAW /* bytes will be stored as-is into ID3 tags, which are Latin1/UCS2 per definition */
+, TENC_LATIN1 /* text will be converted from local encoding to Latin1, as ID3 needs it */
+, TENC_UCS2 /* text will be converted from local encoding to UCS-2, as ID3v2 wants it */
+} TextEncoding;
+
+#ifdef HAVE_ICONV
+
+/* search for Zero termination in multi-byte strings */
+static size_t
+strlenMultiByte(char const* str, size_t w)
+{
+ size_t n = 0;
+ if (str != 0) {
+ size_t i, x = 0;
+ for (n = 0; ; ++n) {
+ x = 0;
+ for (i = 0; i < w; ++i) {
+ x += *str++ == 0 ? 1 : 0;
+ }
+ if (x == w) {
+ break;
+ }
+ }
+ }
+ return n;
+}
+
+
+static size_t
+currCharCodeSize(void)
+{
+ size_t n = 1;
+ char dst[32];
+ char* src = "A";
+ char* env_lang = getenv("LANG");
+ char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
+ char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
+ iconv_t xiconv = iconv_open(cur_code, "ISO_8859-1");
+ if (xiconv != (iconv_t)-1) {
+ for (n = 0; n < 32; ++n) {
+ char* i_ptr = src;
+ char* o_ptr = dst;
+ size_t srcln = 1;
+ size_t avail = n;
+ size_t rc = iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
+ if (rc != (size_t)-1) {
+ break;
+ }
+ }
+ iconv_close(xiconv);
+ }
+ return n;
+}
+
+#if 0
+static
+char* fromLatin1( char* src )
+{
+ char* dst = 0;
+ if (src != 0) {
+ size_t const l = strlen(src);
+ size_t const n = l*4;
+ dst = calloc(n+4, 4);
+ if (dst != 0) {
+ char* env_lang = getenv("LANG");
+ char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
+ char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
+ iconv_t xiconv = iconv_open(cur_code, "ISO_8859-1");
+ if (xiconv != (iconv_t)-1) {
+ char* i_ptr = src;
+ char* o_ptr = dst;
+ size_t srcln = l;
+ size_t avail = n;
+ iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
+ iconv_close(xiconv);
+ }
+ }
+ }
+ return dst;
+}
+
+static
+char* fromUcs2( char* src )
+{
+ char* dst = 0;
+ if (src != 0) {
+ size_t const l = strlenMultiByte(src, 2);
+ size_t const n = l*4;
+ dst = calloc(n+4, 4);
+ if (dst != 0) {
+ char* env_lang = getenv("LANG");
+ char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
+ char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
+ iconv_t xiconv = iconv_open(cur_code, "UCS-2LE");
+ if (xiconv != (iconv_t)-1) {
+ char* i_ptr = (char*)src;
+ char* o_ptr = dst;
+ size_t srcln = l*2;
+ size_t avail = n;
+ iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
+ iconv_close(xiconv);
+ }
+ }
+ }
+ return dst;
+}
+#endif
+
+static
+char* toLatin1( char* src )
+{
+ size_t w = currCharCodeSize();
+ char* dst = 0;
+ if (src != 0) {
+ size_t const l = strlenMultiByte(src, w);
+ size_t const n = l*4;
+ dst = calloc(n+4, 4);
+ if (dst != 0) {
+ char* env_lang = getenv("LANG");
+ char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
+ char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
+ iconv_t xiconv = iconv_open("ISO_8859-1", cur_code);
+ if (xiconv != (iconv_t)-1) {
+ char* i_ptr = (char*)src;
+ char* o_ptr = dst;
+ size_t srcln = l*w;
+ size_t avail = n;
+ iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
+ iconv_close(xiconv);
+ }
+ }
+ }
+ return dst;
+}
+
+
+static
+char* toUcs2( char* src )
+{
+ size_t w = currCharCodeSize();
+ char* dst = 0;
+ if (src != 0) {
+ size_t const l = strlenMultiByte(src, w);
+ size_t const n = (l+1)*4;
+ dst = calloc(n+4, 4);
+ if (dst != 0) {
+ char* env_lang = getenv("LANG");
+ char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.');
+ char* cur_code = xxx_code == NULL ? "" : xxx_code+1;
+ iconv_t xiconv = iconv_open("UCS-2LE", cur_code);
+ dst[0] = 0xff;
+ dst[1] = 0xfe;
+ if (xiconv != (iconv_t)-1) {
+ char* i_ptr = (char*)src;
+ char* o_ptr = &dst[2];
+ size_t srcln = l*w;
+ size_t avail = n;
+ iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail);
+ iconv_close(xiconv);
+ }
+ }
+ }
+ return dst;
+}
+
+
+static int
+set_id3v2tag(lame_global_flags* gfp, int type, unsigned short const* str)
+{
+ switch (type)
+ {
+ case 'a': return id3tag_set_textinfo_ucs2(gfp, "TPE1", str);
+ case 't': return id3tag_set_textinfo_ucs2(gfp, "TIT2", str);
+ case 'l': return id3tag_set_textinfo_ucs2(gfp, "TALB", str);
+ case 'g': return id3tag_set_textinfo_ucs2(gfp, "TCON", str);
+ case 'c': return id3tag_set_comment_ucs2(gfp, 0, 0, str);
+ case 'n': return id3tag_set_textinfo_ucs2(gfp, "TRCK", str);
+ }
+ return 0;
+}
+#endif
+
+static int
+set_id3tag(lame_global_flags* gfp, int type, char const* str)
+{
+ switch (type)
+ {
+ case 'a': return id3tag_set_artist(gfp, str), 0;
+ case 't': return id3tag_set_title(gfp, str), 0;
+ case 'l': return id3tag_set_album(gfp, str), 0;
+ case 'g': return id3tag_set_genre(gfp, str);
+ case 'c': return id3tag_set_comment(gfp, str), 0;
+ case 'n': return id3tag_set_track(gfp, str);
+ case 'y': return id3tag_set_year(gfp, str), 0;
+ case 'v': return id3tag_set_fieldvalue(gfp, str);
+ }
+ return 0;
+}
+
+static int
+id3_tag(lame_global_flags* gfp, int type, TextEncoding enc, char* str)
+{
+ void* x = 0;
+ int result;
+ switch (enc)
+ {
+ default:
+ case TENC_RAW: x = strdup(str); break;
+#ifdef HAVE_ICONV
+ case TENC_LATIN1: x = toLatin1(str); break;
+ case TENC_UCS2: x = toUcs2(str); break;
+#endif
+ }
+ switch (enc)
+ {
+ default:
+ case TENC_RAW:
+ case TENC_LATIN1: result = set_id3tag(gfp, type, x); break;
+#ifdef HAVE_ICONV
+ case TENC_UCS2: result = set_id3v2tag(gfp, type, x); break;
+#endif
+ }
+ free(x);
+ return result;
+}
+
+
+
+
+/************************************************************************
+*
+* license
+*
+* PURPOSE: Writes version and license to the file specified by fp
+*
+************************************************************************/
+
+static int
+lame_version_print(FILE * const fp)
+{
+ const char *b = get_lame_os_bitness();
+ const char *v = get_lame_version();
+ const char *u = get_lame_url();
+ const size_t lenb = strlen(b);
+ const size_t lenv = strlen(v);
+ const size_t lenu = strlen(u);
+ const size_t lw = 80; /* line width of terminal in characters */
+ const size_t sw = 16; /* static width of text */
+
+ if (lw >= lenb + lenv + lenu + sw || lw < lenu + 2)
+ /* text fits in 80 chars per line, or line even too small for url */
+ if (lenb > 0)
+ fprintf(fp, "LAME %s version %s (%s)\n\n", b, v, u);
+ else
+ fprintf(fp, "LAME version %s (%s)\n\n", v, u);
+ else
+ /* text too long, wrap url into next line, right aligned */
+ if (lenb > 0)
+ fprintf(fp, "LAME %s version %s\n%*s(%s)\n\n", b, v, lw - 2 - lenu, "", u);
+ else
+ fprintf(fp, "LAME version %s\n%*s(%s)\n\n", v, lw - 2 - lenu, "", u);
+
+ if (LAME_ALPHA_VERSION)
+ fprintf(fp, "warning: alpha versions should be used for testing only\n\n");
+
+
+ return 0;
+}
+
+static int
+print_license(FILE * const fp)
+{ /* print version & license */
+ lame_version_print(fp);
+ fprintf(fp,
+ "Can I use LAME in my commercial program?\n"
+ "\n"
+ "Yes, you can, under the restrictions of the LGPL. In particular, you\n"
+ "can include a compiled version of the LAME library (for example,\n"
+ "lame.dll) with a commercial program. Some notable requirements of\n"
+ "the LGPL:\n" "\n");
+ fprintf(fp,
+ "1. In your program, you cannot include any source code from LAME, with\n"
+ " the exception of files whose only purpose is to describe the library\n"
+ " interface (such as lame.h).\n" "\n");
+ fprintf(fp,
+ "2. Any modifications of LAME must be released under the LGPL.\n"
+ " The LAME project (www.mp3dev.org) would appreciate being\n"
+ " notified of any modifications.\n" "\n");
+ fprintf(fp,
+ "3. You must give prominent notice that your program is:\n"
+ " A. using LAME (including version number)\n"
+ " B. LAME is under the LGPL\n"
+ " C. Provide a copy of the LGPL. (the file COPYING contains the LGPL)\n"
+ " D. Provide a copy of LAME source, or a pointer where the LAME\n"
+ " source can be obtained (such as www.mp3dev.org)\n"
+ " An example of prominent notice would be an \"About the LAME encoding engine\"\n"
+ " button in some pull down menu within the executable of your program.\n" "\n");
+ fprintf(fp,
+ "4. If you determine that distribution of LAME requires a patent license,\n"
+ " you must obtain such license.\n" "\n" "\n");
+ fprintf(fp,
+ "*** IMPORTANT NOTE ***\n"
+ "\n"
+ "The decoding functions provided in LAME use the mpglib decoding engine which\n"
+ "is under the GPL. They may not be used by any program not released under the\n"
+ "GPL unless you obtain such permission from the MPG123 project (www.mpg123.de).\n"
+ "\n");
+ return 0;
+}
+
+
+/************************************************************************
+*
+* usage
+*
+* PURPOSE: Writes command line syntax to the file specified by fp
+*
+************************************************************************/
+
+int
+usage(FILE * const fp, const char *ProgramName)
+{ /* print general syntax */
+ lame_version_print(fp);
+ fprintf(fp,
+ "usage: %s [options] <infile> [outfile]\n"
+ "\n"
+ " <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n"
+ "\n"
+ "Try:\n"
+ " \"%s --help\" for general usage information\n"
+ " or:\n"
+ " \"%s --preset help\" for information on suggested predefined settings\n"
+ " or:\n"
+ " \"%s --longhelp\"\n"
+ " or \"%s -?\" for a complete options list\n\n",
+ ProgramName, ProgramName, ProgramName, ProgramName, ProgramName);
+ return 0;
+}
+
+
+/************************************************************************
+*
+* usage
+*
+* PURPOSE: Writes command line syntax to the file specified by fp
+* but only the most important ones, to fit on a vt100 terminal
+*
+************************************************************************/
+
+int
+short_help(const lame_global_flags * gfp, FILE * const fp, const char *ProgramName)
+{ /* print short syntax help */
+ lame_version_print(fp);
+ fprintf(fp,
+ "usage: %s [options] <infile> [outfile]\n"
+ "\n"
+ " <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n"
+ "\n" "RECOMMENDED:\n" " lame -V2 input.wav output.mp3\n" "\n", ProgramName);
+ fprintf(fp,
+ "OPTIONS:\n"
+ " -b bitrate set the bitrate, default 128 kbps\n"
+ " -h higher quality, but a little slower. Recommended.\n"
+ " -f fast mode (lower quality)\n"
+ " -V n quality setting for VBR. default n=%i\n"
+ " 0=high quality,bigger files. 9=smaller files\n",
+ lame_get_VBR_q(gfp));
+ fprintf(fp,
+ " --preset type type must be \"medium\", \"standard\", \"extreme\", \"insane\",\n"
+ " or a value for an average desired bitrate and depending\n"
+ " on the value specified, appropriate quality settings will\n"
+ " be used.\n"
+ " \"--preset help\" gives more info on these\n" "\n");
+ fprintf(fp,
+#if defined(WIN32)
+ " --priority type sets the process priority\n"
+ " 0,1 = Low priority\n"
+ " 2 = normal priority\n"
+ " 3,4 = High priority\n" "\n"
+#endif
+#if defined(__OS2__)
+ " --priority type sets the process priority\n"
+ " 0 = Low priority\n"
+ " 1 = Medium priority\n"
+ " 2 = Regular priority\n"
+ " 3 = High priority\n"
+ " 4 = Maximum priority\n" "\n"
+#endif
+ " --longhelp full list of options\n" "\n"
+ " --license print License information\n\n"
+ );
+
+ return 0;
+}
+
+/************************************************************************
+*
+* usage
+*
+* PURPOSE: Writes command line syntax to the file specified by fp
+*
+************************************************************************/
+
+static void
+wait_for(FILE * const fp, int lessmode)
+{
+ if (lessmode) {
+ fflush(fp);
+ getchar();
+ }
+ else {
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, "\n");
+}
+
+int
+long_help(const lame_global_flags * gfp, FILE * const fp, const char *ProgramName, int lessmode)
+{ /* print long syntax help */
+ lame_version_print(fp);
+ fprintf(fp,
+ "usage: %s [options] <infile> [outfile]\n"
+ "\n"
+ " <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n"
+ "\n" "RECOMMENDED:\n" " lame -V2 input.wav output.mp3\n" "\n", ProgramName);
+ fprintf(fp,
+ "OPTIONS:\n"
+ " Input options:\n"
+ " --scale <arg> scale input (multiply PCM data) by <arg>\n"
+ " --scale-l <arg> scale channel 0 (left) input (multiply PCM data) by <arg>\n"
+ " --scale-r <arg> scale channel 1 (right) input (multiply PCM data) by <arg>\n"
+#if (defined HAVE_MPGLIB || defined AMIGA_MPEGA)
+ " --mp1input input file is a MPEG Layer I file\n"
+ " --mp2input input file is a MPEG Layer II file\n"
+ " --mp3input input file is a MPEG Layer III file\n"
+#endif
+ " --nogap <file1> <file2> <...>\n"
+ " gapless encoding for a set of contiguous files\n"
+ " --nogapout <dir>\n"
+ " output dir for gapless encoding (must precede --nogap)\n"
+ " --nogaptags allow the use of VBR tags in gapless encoding\n"
+ );
+ fprintf(fp,
+ "\n"
+ " Input options for RAW PCM:\n"
+ " -r input is raw pcm\n"
+ " -x force byte-swapping of input\n"
+ " -s sfreq sampling frequency of input file (kHz) - default 44.1 kHz\n"
+ " --bitwidth w input bit width is w (default 16)\n"
+ " --signed input is signed (default)\n"
+ " --unsigned input is unsigned\n"
+ " --little-endian input is little-endian (default)\n"
+ " --big-endian input is big-endian\n"
+ );
+
+ wait_for(fp, lessmode);
+ fprintf(fp,
+ " Operational options:\n"
+ " -a downmix from stereo to mono file for mono encoding\n"
+ " -m <mode> (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono\n"
+ " default is (j) or (s) depending on bitrate\n"
+ " joint = joins the best possible of MS and LR stereo\n"
+ " simple = force LR stereo on all frames\n"
+ " force = force MS stereo on all frames.\n"
+ " --preset type type must be \"medium\", \"standard\", \"extreme\", \"insane\",\n"
+ " or a value for an average desired bitrate and depending\n"
+ " on the value specified, appropriate quality settings will\n"
+ " be used.\n"
+ " \"--preset help\" gives more info on these\n"
+ " --comp <arg> choose bitrate to achive a compression ratio of <arg>\n");
+ fprintf(fp, " --replaygain-fast compute RG fast but slightly inaccurately (default)\n"
+#ifdef DECODE_ON_THE_FLY
+ " --replaygain-accurate compute RG more accurately and find the peak sample\n"
+#endif
+ " --noreplaygain disable ReplayGain analysis\n"
+#ifdef DECODE_ON_THE_FLY
+ " --clipdetect enable --replaygain-accurate and print a message whether\n"
+ " clipping occurs and how far the waveform is from full scale\n"
+#endif
+ );
+ fprintf(fp,
+ " --flush flush output stream as soon as possible\n"
+ " --freeformat produce a free format bitstream\n"
+ " --decode input=mp3 file, output=wav\n"
+ " -t disable writing wav header when using --decode\n");
+
+ wait_for(fp, lessmode);
+ fprintf(fp,
+ " Verbosity:\n"
+ " --disptime <arg>print progress report every arg seconds\n"
+ " -S don't print progress report, VBR histograms\n"
+ " --nohist disable VBR histogram display\n"
+ " --silent don't print anything on screen\n"
+ " --quiet don't print anything on screen\n"
+ " --brief print more useful information\n"
+ " --verbose print a lot of useful information\n" "\n");
+ fprintf(fp,
+ " Noise shaping & psycho acoustic algorithms:\n"
+ " -q <arg> <arg> = 0...9. Default -q 5 \n"
+ " -q 0: Highest quality, very slow \n"
+ " -q 9: Poor quality, but fast \n"
+ " -h Same as -q 2. Recommended.\n"
+ " -f Same as -q 7. Fast, ok quality\n");
+
+ wait_for(fp, lessmode);
+ fprintf(fp,
+ " CBR (constant bitrate, the default) options:\n"
+ " -b <bitrate> set the bitrate in kbps, default 128 kbps\n"
+ " --cbr enforce use of constant bitrate\n"
+ "\n"
+ " ABR options:\n"
+ " --abr <bitrate> specify average bitrate desired (instead of quality)\n" "\n");
+ fprintf(fp,
+ " VBR options:\n"
+ " -V n quality setting for VBR. default n=%i\n"
+ " 0=high quality,bigger files. 9=smaller files\n"
+ " -v the same as -V 4\n"
+ " --vbr-old use old variable bitrate (VBR) routine\n"
+ " --vbr-new use new variable bitrate (VBR) routine (default)\n"
+ ,
+ lame_get_VBR_q(gfp));
+ fprintf(fp,
+ " -b <bitrate> specify minimum allowed bitrate, default 32 kbps\n"
+ " -B <bitrate> specify maximum allowed bitrate, default 320 kbps\n"
+ " -F strictly enforce the -b option, for use with players that\n"
+ " do not support low bitrate mp3\n"
+ " -t disable writing LAME Tag\n"
+ " -T enable and force writing LAME Tag\n");
+
+ wait_for(fp, lessmode);
+ DEV_HELP(fprintf(fp,
+ " ATH related:\n"
+ " --noath turns ATH down to a flat noise floor\n"
+ " --athshort ignore GPSYCHO for short blocks, use ATH only\n"
+ " --athonly ignore GPSYCHO completely, use ATH only\n"
+ " --athtype n selects between different ATH types [0-4]\n"
+ " --athlower x lowers ATH by x dB\n");
+ fprintf(fp, " --athaa-type n ATH auto adjust: 0 'no' else 'loudness based'\n"
+/** OBSOLETE " --athaa-loudapprox n n=1 total energy or n=2 equal loudness curve\n"*/
+ " --athaa-sensitivity x activation offset in -/+ dB for ATH auto-adjustment\n"
+ "\n");
+ )
+ fprintf(fp,
+ " PSY related:\n"
+ DEV_HELP(
+ " --short use short blocks when appropriate\n"
+ " --noshort do not use short blocks\n"
+ " --allshort use only short blocks\n"
+ )
+ );
+ fprintf(fp,
+ " --temporal-masking x x=0 disables, x=1 enables temporal masking effect\n"
+ " --nssafejoint M/S switching criterion\n"
+ " --nsmsfix <arg> M/S switching tuning [effective 0-3.5]\n"
+ " --interch x adjust inter-channel masking ratio\n"
+ " --ns-bass x adjust masking for sfbs 0 - 6 (long) 0 - 5 (short)\n"
+ " --ns-alto x adjust masking for sfbs 7 - 13 (long) 6 - 10 (short)\n"
+ " --ns-treble x adjust masking for sfbs 14 - 21 (long) 11 - 12 (short)\n");
+ fprintf(fp,
+ " --ns-sfb21 x change ns-treble by x dB for sfb21\n"
+ DEV_HELP(" --shortthreshold x,y short block switching threshold,\n"
+ " x for L/R/M channel, y for S channel\n"
+ " Noise Shaping related:\n"
+ " --substep n use pseudo substep noise shaping method types 0-2\n")
+ );
+
+ wait_for(fp, lessmode);
+
+ fprintf(fp,
+ " experimental switches:\n"
+ DEV_HELP(
+ " -X n[,m] selects between different noise measurements\n"
+ " n for long block, m for short. if m is omitted, m = n\n"
+ )
+ " -Y lets LAME ignore noise in sfb21, like in CBR\n"
+ DEV_HELP(
+ " -Z [n] currently no effects\n"
+ )
+ );
+
+ wait_for(fp, lessmode);
+
+ fprintf(fp,
+ " MP3 header/stream options:\n"
+ " -e <emp> de-emphasis n/5/c (obsolete)\n"
+ " -c mark as copyright\n"
+ " -o mark as non-original\n"
+ " -p error protection. adds 16 bit checksum to every frame\n"
+ " (the checksum is computed correctly)\n"
+ " --nores disable the bit reservoir\n"
+ " --strictly-enforce-ISO comply as much as possible to ISO MPEG spec\n" "\n");
+ fprintf(fp,
+ " Filter options:\n"
+ " --lowpass <freq> frequency(kHz), lowpass filter cutoff above freq\n"
+ " --lowpass-width <freq> frequency(kHz) - default 15%% of lowpass freq\n"
+ " --highpass <freq> frequency(kHz), highpass filter cutoff below freq\n"
+ " --highpass-width <freq> frequency(kHz) - default 15%% of highpass freq\n");
+ fprintf(fp,
+ " --resample <sfreq> sampling frequency of output file(kHz)- default=automatic\n");
+
+ wait_for(fp, lessmode);
+ fprintf(fp,
+ " ID3 tag options:\n"
+ " --tt <title> audio/song title (max 30 chars for version 1 tag)\n"
+ " --ta <artist> audio/song artist (max 30 chars for version 1 tag)\n"
+ " --tl <album> audio/song album (max 30 chars for version 1 tag)\n"
+ " --ty <year> audio/song year of issue (1 to 9999)\n"
+ " --tc <comment> user-defined text (max 30 chars for v1 tag, 28 for v1.1)\n"
+ " --tn <track[/total]> audio/song track number and (optionally) the total\n"
+ " number of tracks on the original recording. (track\n"
+ " and total each 1 to 255. just the track number\n"
+ " creates v1.1 tag, providing a total forces v2.0).\n"
+ " --tg <genre> audio/song genre (name or number in list)\n"
+ " --ti <file> audio/song albumArt (jpeg/png/gif file, 128KB max, v2.3)\n"
+ " --tv <id=value> user-defined frame specified by id and value (v2.3 tag)\n");
+ fprintf(fp,
+ " --add-id3v2 force addition of version 2 tag\n"
+ " --id3v1-only add only a version 1 tag\n"
+ " --id3v2-only add only a version 2 tag\n"
+ " --space-id3v1 pad version 1 tag with spaces instead of nulls\n"
+ " --pad-id3v2 same as '--pad-id3v2-size 128'\n"
+ " --pad-id3v2-size <value> adds version 2 tag, pad with extra <value> bytes\n"
+ " --genre-list print alphabetically sorted ID3 genre list and exit\n"
+ " --ignore-tag-errors ignore errors in values passed for tags\n" "\n");
+ fprintf(fp,
+ " Note: A version 2 tag will NOT be added unless one of the input fields\n"
+ " won't fit in a version 1 tag (e.g. the title string is longer than 30\n"
+ " characters), or the '--add-id3v2' or '--id3v2-only' options are used,\n"
+ " or output is redirected to stdout.\n"
+#if defined(WIN32)
+ "\n\nMS-Windows-specific options:\n"
+ " --priority <type> sets the process priority:\n"
+ " 0,1 = Low priority (IDLE_PRIORITY_CLASS)\n"
+ " 2 = normal priority (NORMAL_PRIORITY_CLASS, default)\n"
+ " 3,4 = High priority (HIGH_PRIORITY_CLASS))\n"
+ " Note: Calling '--priority' without a parameter will select priority 0.\n"
+#endif
+#if defined(__OS2__)
+ "\n\nOS/2-specific options:\n"
+ " --priority <type> sets the process priority:\n"
+ " 0 = Low priority (IDLE, delta = 0)\n"
+ " 1 = Medium priority (IDLE, delta = +31)\n"
+ " 2 = Regular priority (REGULAR, delta = -31)\n"
+ " 3 = High priority (REGULAR, delta = 0)\n"
+ " 4 = Maximum priority (REGULAR, delta = +31)\n"
+ " Note: Calling '--priority' without a parameter will select priority 0.\n"
+#endif
+ "\nMisc:\n --license print License information\n\n"
+ );
+
+#if defined(HAVE_NASM)
+ wait_for(fp, lessmode);
+ fprintf(fp,
+ " Platform specific:\n"
+ " --noasm <instructions> disable assembly optimizations for mmx/3dnow/sse\n");
+ wait_for(fp, lessmode);
+#endif
+
+ display_bitrates(fp);
+
+ return 0;
+}
+
+static void
+display_bitrate(FILE * const fp, const char *const version, const int d, const int indx)
+{
+ int i;
+ int nBitrates = 14;
+ if (d == 4)
+ nBitrates = 8;
+
+
+ fprintf(fp,
+ "\nMPEG-%-3s layer III sample frequencies (kHz): %2d %2d %g\n"
+ "bitrates (kbps):", version, 32 / d, 48 / d, 44.1 / d);
+ for (i = 1; i <= nBitrates; i++)
+ fprintf(fp, " %2i", bitrate_table[indx][i]);
+ fprintf(fp, "\n");
+}
+
+int
+display_bitrates(FILE * const fp)
+{
+ display_bitrate(fp, "1", 1, 1);
+ display_bitrate(fp, "2", 2, 0);
+ display_bitrate(fp, "2.5", 4, 0);
+ fprintf(fp, "\n");
+ fflush(fp);
+ return 0;
+}
+
+
+/* note: for presets it would be better to externalize them in a file.
+ suggestion: lame --preset <file-name> ...
+ or: lame --preset my-setting ... and my-setting is defined in lame.ini
+ */
+
+/*
+Note from GB on 08/25/2002:
+I am merging --presets and --alt-presets. Old presets are now aliases for
+corresponding abr values from old alt-presets. This way we now have a
+unified preset system, and I hope than more people will use the new tuned
+presets instead of the old unmaintained ones.
+*/
+
+
+
+/************************************************************************
+*
+* usage
+*
+* PURPOSE: Writes presetting info to #stdout#
+*
+************************************************************************/
+
+
+static void
+presets_longinfo_dm(FILE * msgfp)
+{
+ fprintf(msgfp,
+ "\n"
+ "The --preset switches are aliases over LAME settings.\n"
+ "\n" "\n");
+ fprintf(msgfp,
+ "To activate these presets:\n"
+ "\n" " For VBR modes (generally highest quality):\n" "\n");
+ fprintf(msgfp,
+ " \"--preset medium\" This preset should provide near transparency\n"
+ " to most people on most music.\n"
+ "\n"
+ " \"--preset standard\" This preset should generally be transparent\n"
+ " to most people on most music and is already\n"
+ " quite high in quality.\n" "\n");
+ fprintf(msgfp,
+ " \"--preset extreme\" If you have extremely good hearing and similar\n"
+ " equipment, this preset will generally provide\n"
+ " slightly higher quality than the \"standard\"\n"
+ " mode.\n" "\n");
+ fprintf(msgfp,
+ " For CBR 320kbps (highest quality possible from the --preset switches):\n"
+ "\n"
+ " \"--preset insane\" This preset will usually be overkill for most\n"
+ " people and most situations, but if you must\n"
+ " have the absolute highest quality with no\n"
+ " regard to filesize, this is the way to go.\n" "\n");
+ fprintf(msgfp,
+ " For ABR modes (high quality per given bitrate but not as high as VBR):\n"
+ "\n"
+ " \"--preset <kbps>\" Using this preset will usually give you good\n"
+ " quality at a specified bitrate. Depending on the\n"
+ " bitrate entered, this preset will determine the\n");
+ fprintf(msgfp,
+ " optimal settings for that particular situation.\n"
+ " While this approach works, it is not nearly as\n"
+ " flexible as VBR, and usually will not attain the\n"
+ " same level of quality as VBR at higher bitrates.\n" "\n");
+ fprintf(msgfp,
+ "The following options are also available for the corresponding profiles:\n"
+ "\n"
+ " <fast> standard\n"
+ " <fast> extreme\n"
+ " insane\n"
+ " <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n"
+ " simply specify a bitrate. For example:\n"
+ " \"--preset 185\" activates this\n"
+ " preset and uses 185 as an average kbps.\n" "\n");
+ fprintf(msgfp,
+ " \"fast\" - Enables the fast VBR mode for a particular profile.\n" "\n");
+ fprintf(msgfp,
+ " \"cbr\" - If you use the ABR mode (read above) with a significant\n"
+ " bitrate such as 80, 96, 112, 128, 160, 192, 224, 256, 320,\n"
+ " you can use the \"cbr\" option to force CBR mode encoding\n"
+ " instead of the standard abr mode. ABR does provide higher\n"
+ " quality but CBR may be useful in situations such as when\n"
+ " streaming an mp3 over the internet may be important.\n" "\n");
+ fprintf(msgfp,
+ " For example:\n"
+ "\n"
+ " \"--preset fast standard <input file> <output file>\"\n"
+ " or \"--preset cbr 192 <input file> <output file>\"\n"
+ " or \"--preset 172 <input file> <output file>\"\n"
+ " or \"--preset extreme <input file> <output file>\"\n" "\n" "\n");
+ fprintf(msgfp,
+ "A few aliases are also available for ABR mode:\n"
+ "phone => 16kbps/mono phon+/lw/mw-eu/sw => 24kbps/mono\n"
+ "mw-us => 40kbps/mono voice => 56kbps/mono\n"
+ "fm/radio/tape => 112kbps hifi => 160kbps\n"
+ "cd => 192kbps studio => 256kbps\n");
+}
+
+
+extern void lame_set_msfix(lame_t gfp, double msfix);
+
+
+
+static int
+presets_set(lame_t gfp, int fast, int cbr, const char *preset_name, const char *ProgramName)
+{
+ int mono = 0;
+
+ if ((strcmp(preset_name, "help") == 0) && (fast < 1)
+ && (cbr < 1)) {
+ lame_version_print(stdout);
+ presets_longinfo_dm(stdout);
+ return -1;
+ }
+
+
+
+ /*aliases for compatibility with old presets */
+
+ if (strcmp(preset_name, "phone") == 0) {
+ preset_name = "16";
+ mono = 1;
+ }
+ if ((strcmp(preset_name, "phon+") == 0) ||
+ (strcmp(preset_name, "lw") == 0) ||
+ (strcmp(preset_name, "mw-eu") == 0) || (strcmp(preset_name, "sw") == 0)) {
+ preset_name = "24";
+ mono = 1;
+ }
+ if (strcmp(preset_name, "mw-us") == 0) {
+ preset_name = "40";
+ mono = 1;
+ }
+ if (strcmp(preset_name, "voice") == 0) {
+ preset_name = "56";
+ mono = 1;
+ }
+ if (strcmp(preset_name, "fm") == 0) {
+ preset_name = "112";
+ }
+ if ((strcmp(preset_name, "radio") == 0) || (strcmp(preset_name, "tape") == 0)) {
+ preset_name = "112";
+ }
+ if (strcmp(preset_name, "hifi") == 0) {
+ preset_name = "160";
+ }
+ if (strcmp(preset_name, "cd") == 0) {
+ preset_name = "192";
+ }
+ if (strcmp(preset_name, "studio") == 0) {
+ preset_name = "256";
+ }
+
+ if (strcmp(preset_name, "medium") == 0) {
+ lame_set_VBR_q(gfp, 4);
+ if (fast > 0) {
+ lame_set_VBR(gfp, vbr_mtrh);
+ }
+ else {
+ lame_set_VBR(gfp, vbr_rh);
+ }
+ return 0;
+ }
+
+ if (strcmp(preset_name, "standard") == 0) {
+ lame_set_VBR_q(gfp, 2);
+ if (fast > 0) {
+ lame_set_VBR(gfp, vbr_mtrh);
+ }
+ else {
+ lame_set_VBR(gfp, vbr_rh);
+ }
+ return 0;
+ }
+
+ else if (strcmp(preset_name, "extreme") == 0) {
+ lame_set_VBR_q(gfp, 0);
+ if (fast > 0) {
+ lame_set_VBR(gfp, vbr_mtrh);
+ }
+ else {
+ lame_set_VBR(gfp, vbr_rh);
+ }
+ return 0;
+ }
+
+ else if ((strcmp(preset_name, "insane") == 0) && (fast < 1)) {
+
+ lame_set_preset(gfp, INSANE);
+
+ return 0;
+ }
+
+ /* Generic ABR Preset */
+ if (((atoi(preset_name)) > 0) && (fast < 1)) {
+ if ((atoi(preset_name)) >= 8 && (atoi(preset_name)) <= 320) {
+ lame_set_preset(gfp, atoi(preset_name));
+
+ if (cbr == 1)
+ lame_set_VBR(gfp, vbr_off);
+
+ if (mono == 1) {
+ lame_set_mode(gfp, MONO);
+ }
+
+ return 0;
+
+ }
+ else {
+ lame_version_print(Console_IO.Error_fp);
+ error_printf("Error: The bitrate specified is out of the valid range for this preset\n"
+ "\n"
+ "When using this mode you must enter a value between \"32\" and \"320\"\n"
+ "\n" "For further information try: \"%s --preset help\"\n", ProgramName);
+ return -1;
+ }
+ }
+
+ lame_version_print(Console_IO.Error_fp);
+ error_printf("Error: You did not enter a valid profile and/or options with --preset\n"
+ "\n"
+ "Available profiles are:\n"
+ "\n"
+ " <fast> medium\n"
+ " <fast> standard\n"
+ " <fast> extreme\n"
+ " insane\n"
+ " <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n"
+ " simply specify a bitrate. For example:\n"
+ " \"--preset 185\" activates this\n"
+ " preset and uses 185 as an average kbps.\n" "\n");
+ error_printf(" Some examples:\n"
+ "\n"
+ " or \"%s --preset fast standard <input file> <output file>\"\n"
+ " or \"%s --preset cbr 192 <input file> <output file>\"\n"
+ " or \"%s --preset 172 <input file> <output file>\"\n"
+ " or \"%s --preset extreme <input file> <output file>\"\n"
+ "\n"
+ "For further information try: \"%s --preset help\"\n", ProgramName, ProgramName,
+ ProgramName, ProgramName, ProgramName);
+ return -1;
+}
+
+static void
+genre_list_handler(int num, const char *name, void *cookie)
+{
+ (void) cookie;
+ console_printf("%3d %s\n", num, name);
+}
+
+
+/************************************************************************
+*
+* parse_args
+*
+* PURPOSE: Sets encoding parameters to the specifications of the
+* command line. Default settings are used for parameters
+* not specified in the command line.
+*
+* If the input file is in WAVE or AIFF format, the sampling frequency is read
+* from the AIFF header.
+*
+* The input and output filenames are read into #inpath# and #outpath#.
+*
+************************************************************************/
+
+/* would use real "strcasecmp" but it isn't portable */
+static int
+local_strcasecmp(const char *s1, const char *s2)
+{
+ unsigned char c1;
+ unsigned char c2;
+
+ do {
+ c1 = tolower(*s1);
+ c2 = tolower(*s2);
+ if (!c1) {
+ break;
+ }
+ ++s1;
+ ++s2;
+ } while (c1 == c2);
+ return c1 - c2;
+}
+
+
+
+/* LAME is a simple frontend which just uses the file extension */
+/* to determine the file type. Trying to analyze the file */
+/* contents is well beyond the scope of LAME and should not be added. */
+static int
+filename_to_type(const char *FileName)
+{
+ size_t len = strlen(FileName);
+
+ if (len < 4)
+ return sf_unknown;
+
+ FileName += len - 4;
+ if (0 == local_strcasecmp(FileName, ".mpg"))
+ return sf_mp123;
+ if (0 == local_strcasecmp(FileName, ".mp1"))
+ return sf_mp123;
+ if (0 == local_strcasecmp(FileName, ".mp2"))
+ return sf_mp123;
+ if (0 == local_strcasecmp(FileName, ".mp3"))
+ return sf_mp123;
+ if (0 == local_strcasecmp(FileName, ".wav"))
+ return sf_wave;
+ if (0 == local_strcasecmp(FileName, ".aif"))
+ return sf_aiff;
+ if (0 == local_strcasecmp(FileName, ".raw"))
+ return sf_raw;
+ if (0 == local_strcasecmp(FileName, ".ogg"))
+ return sf_ogg;
+ return sf_unknown;
+}
+
+static int
+resample_rate(double freq)
+{
+ if (freq >= 1.e3)
+ freq *= 1.e-3;
+
+ switch ((int) freq) {
+ case 8:
+ return 8000;
+ case 11:
+ return 11025;
+ case 12:
+ return 12000;
+ case 16:
+ return 16000;
+ case 22:
+ return 22050;
+ case 24:
+ return 24000;
+ case 32:
+ return 32000;
+ case 44:
+ return 44100;
+ case 48:
+ return 48000;
+ default:
+ error_printf("Illegal resample frequency: %.3f kHz\n", freq);
+ return 0;
+ }
+}
+
+
+static int
+set_id3_albumart(lame_t gfp, char const* file_name)
+{
+ int ret = -1;
+ FILE *fpi = 0;
+ char *albumart = 0;
+
+ if (file_name == 0) {
+ return 0;
+ }
+ fpi = fopen(file_name, "rb");
+ if (!fpi) {
+ ret = 1;
+ }
+ else {
+ size_t size;
+
+ fseek(fpi, 0, SEEK_END);
+ size = ftell(fpi);
+ fseek(fpi, 0, SEEK_SET);
+ albumart = (char *)malloc(size);
+ if (!albumart) {
+ ret = 2;
+ }
+ else {
+ if (fread(albumart, 1, size, fpi) != size) {
+ ret = 3;
+ }
+ else {
+ ret = id3tag_set_albumart(gfp, albumart, size) ? 4 : 0;
+ }
+ free(albumart);
+ }
+ fclose(fpi);
+ }
+ switch (ret) {
+ case 1: error_printf("Could not find: '%s'.\n", file_name); break;
+ case 2: error_printf("Insufficient memory for reading the albumart.\n"); break;
+ case 3: error_printf("Read error: '%s'.\n", file_name); break;
+ case 4: error_printf("Unsupported image: '%s'.\nSpecify JPEG/PNG/GIF image (128KB maximum)\n", file_name); break;
+ default: break;
+ }
+ return ret;
+}
+
+
+enum ID3TAG_MODE
+{ ID3TAG_MODE_DEFAULT
+, ID3TAG_MODE_V1_ONLY
+, ID3TAG_MODE_V2_ONLY
+};
+
+/* Ugly, NOT final version */
+
+#define T_IF(str) if ( 0 == local_strcasecmp (token,str) ) {
+#define T_ELIF(str) } else if ( 0 == local_strcasecmp (token,str) ) {
+#define T_ELIF_INTERNAL(str) } else if (INTERNAL_OPTS && (0 == local_strcasecmp (token,str)) ) {
+#define T_ELIF2(str1,str2) } else if ( 0 == local_strcasecmp (token,str1) || 0 == local_strcasecmp (token,str2) ) {
+#define T_ELSE } else {
+#define T_END }
+
+int
+parse_args(lame_global_flags * gfp, int argc, char **argv,
+ char *const inPath, char *const outPath, char **nogap_inPath, int *num_nogap)
+{
+ int input_file = 0; /* set to 1 if we parse an input file name */
+ int i;
+ int autoconvert = 0;
+ double val;
+ int nogap = 0;
+ int nogap_tags = 0; /* set to 1 to use VBR tags in NOGAP mode */
+ const char *ProgramName = argv[0];
+ int count_nogap = 0;
+ int noreplaygain = 0; /* is RG explicitly disabled by the user */
+ int id3tag_mode = ID3TAG_MODE_DEFAULT;
+
+ inPath[0] = '\0';
+ outPath[0] = '\0';
+ /* turn on display options. user settings may turn them off below */
+ silent = 0;
+ ignore_tag_errors = 0;
+ brhist = 1;
+ mp3_delay = 0;
+ mp3_delay_set = 0;
+ print_clipping_info = 0;
+ disable_wav_header = 0;
+ id3tag_init(gfp);
+
+ /* process args */
+ for (i = 0; ++i < argc;) {
+ char c;
+ char *token;
+ char *arg;
+ char *nextArg;
+ int argUsed;
+
+ token = argv[i];
+ if (*token++ == '-') {
+ argUsed = 0;
+ nextArg = i + 1 < argc ? argv[i + 1] : "";
+
+ if (!*token) { /* The user wants to use stdin and/or stdout. */
+ input_file = 1;
+ if (inPath[0] == '\0')
+ strncpy(inPath, argv[i], PATH_MAX + 1);
+ else if (outPath[0] == '\0')
+ strncpy(outPath, argv[i], PATH_MAX + 1);
+ }
+ if (*token == '-') { /* GNU style */
+ token++;
+
+ T_IF("resample")
+ argUsed = 1;
+ (void) lame_set_out_samplerate(gfp, resample_rate(atof(nextArg)));
+
+ T_ELIF("vbr-old")
+ lame_set_VBR(gfp, vbr_rh);
+
+ T_ELIF("vbr-new")
+ lame_set_VBR(gfp, vbr_mtrh);
+
+ T_ELIF("vbr-mtrh")
+ lame_set_VBR(gfp, vbr_mtrh);
+
+ T_ELIF("cbr")
+ lame_set_VBR(gfp, vbr_off);
+
+ T_ELIF("abr")
+ argUsed = 1;
+ lame_set_VBR(gfp, vbr_abr);
+ lame_set_VBR_mean_bitrate_kbps(gfp, atoi(nextArg));
+ /* values larger than 8000 are bps (like Fraunhofer), so it's strange to get 320000 bps MP3 when specifying 8000 bps MP3 */
+ if (lame_get_VBR_mean_bitrate_kbps(gfp) >= 8000)
+ lame_set_VBR_mean_bitrate_kbps(gfp,
+ (lame_get_VBR_mean_bitrate_kbps(gfp) +
+ 500) / 1000);
+
+ lame_set_VBR_mean_bitrate_kbps(gfp, Min(lame_get_VBR_mean_bitrate_kbps(gfp), 320));
+ lame_set_VBR_mean_bitrate_kbps(gfp, Max(lame_get_VBR_mean_bitrate_kbps(gfp), 8));
+
+ T_ELIF("r3mix")
+ lame_set_preset(gfp, R3MIX);
+
+ T_ELIF("bitwidth")
+ argUsed = 1;
+ in_bitwidth = atoi(nextArg);
+
+ T_ELIF("signed")
+ in_signed = 1;
+
+ T_ELIF("unsigned")
+ in_signed = 0;
+
+ T_ELIF("little-endian")
+ in_endian = ByteOrderLittleEndian;
+
+ T_ELIF("big-endian")
+ in_endian = ByteOrderBigEndian;
+
+ T_ELIF("mp1input")
+ input_format = sf_mp1;
+
+ T_ELIF("mp2input")
+ input_format = sf_mp2;
+
+ T_ELIF("mp3input")
+ input_format = sf_mp3;
+
+ T_ELIF("ogginput")
+ error_printf("sorry, vorbis support in LAME is deprecated.\n");
+ return -1;
+
+ T_ELIF("phone")
+ if (presets_set(gfp, 0, 0, token, ProgramName) < 0)
+ return -1;
+ error_printf("Warning: --phone is deprecated, use --preset phone instead!");
+
+ T_ELIF("voice")
+ if (presets_set(gfp, 0, 0, token, ProgramName) < 0)
+ return -1;
+ error_printf("Warning: --voice is deprecated, use --preset voice instead!");
+
+ T_ELIF_INTERNAL("noshort")
+ (void) lame_set_no_short_blocks(gfp, 1);
+
+ T_ELIF_INTERNAL("short")
+ (void) lame_set_no_short_blocks(gfp, 0);
+
+ T_ELIF_INTERNAL("allshort")
+ (void) lame_set_force_short_blocks(gfp, 1);
+
+
+ T_ELIF("decode")
+ (void) lame_set_decode_only(gfp, 1);
+
+ T_ELIF("flush")
+ flush_write = 1;
+
+ T_ELIF("decode-mp3delay")
+ mp3_delay = atoi(nextArg);
+ mp3_delay_set = 1;
+ argUsed = 1;
+
+ T_ELIF("nores")
+ lame_set_disable_reservoir(gfp, 1);
+
+ T_ELIF("strictly-enforce-ISO")
+ lame_set_strict_ISO(gfp, 1);
+
+ T_ELIF("scale")
+ argUsed = 1;
+ (void) lame_set_scale(gfp, (float) atof(nextArg));
+
+ T_ELIF("scale-l")
+ argUsed = 1;
+ (void) lame_set_scale_left(gfp, (float) atof(nextArg));
+
+ T_ELIF("scale-r")
+ argUsed = 1;
+ (void) lame_set_scale_right(gfp, (float) atof(nextArg));
+
+ T_ELIF("noasm")
+ argUsed = 1;
+ if (!strcmp(nextArg, "mmx"))
+ (void) lame_set_asm_optimizations(gfp, MMX, 0);
+ if (!strcmp(nextArg, "3dnow"))
+ (void) lame_set_asm_optimizations(gfp, AMD_3DNOW, 0);
+ if (!strcmp(nextArg, "sse"))
+ (void) lame_set_asm_optimizations(gfp, SSE, 0);
+
+ T_ELIF("freeformat")
+ lame_set_free_format(gfp, 1);
+
+ T_ELIF("replaygain-fast")
+ lame_set_findReplayGain(gfp, 1);
+
+#ifdef DECODE_ON_THE_FLY
+ T_ELIF("replaygain-accurate")
+ lame_set_decode_on_the_fly(gfp, 1);
+ lame_set_findReplayGain(gfp, 1);
+#endif
+
+ T_ELIF("noreplaygain")
+ noreplaygain = 1;
+ lame_set_findReplayGain(gfp, 0);
+
+
+#ifdef DECODE_ON_THE_FLY
+ T_ELIF("clipdetect")
+ print_clipping_info = 1;
+ lame_set_decode_on_the_fly(gfp, 1);
+#endif
+
+ T_ELIF("nohist")
+ brhist = 0;
+
+#if defined(__OS2__) || defined(WIN32)
+ T_ELIF("priority")
+ char *endptr;
+ int priority = (int) strtol(nextArg, &endptr, 10);
+ if (endptr != nextArg) {
+ argUsed = 1;
+ }
+# if defined(__OS2__)
+ setOS2Priority(gfp, priority);
+# else /* WIN32 */
+ setWin32Priority(gfp, priority);
+# endif
+#endif
+
+ /* options for ID3 tag */
+ T_ELIF("tt")
+ argUsed = 1;
+ id3_tag(gfp, 't', TENC_RAW, nextArg);
+
+ T_ELIF("ta")
+ argUsed = 1;
+ id3_tag(gfp, 'a', TENC_RAW, nextArg);
+
+ T_ELIF("tl")
+ argUsed = 1;
+ id3_tag(gfp, 'l', TENC_RAW, nextArg);
+
+ T_ELIF("ty")
+ argUsed = 1;
+ id3_tag(gfp, 'y', TENC_RAW, nextArg);
+
+ T_ELIF("tc")
+ argUsed = 1;
+ id3_tag(gfp, 'c', TENC_RAW, nextArg);
+
+ T_ELIF("tn")
+ int ret = id3_tag(gfp, 'n', TENC_RAW, nextArg);
+ argUsed = 1;
+ if (ret != 0) {
+ if (0 == ignore_tag_errors) {
+ if (id3tag_mode == ID3TAG_MODE_V1_ONLY) {
+ error_printf("The track number has to be between 1 and 255 for ID3v1.\n");
+ return -1;
+ }
+ else if (id3tag_mode == ID3TAG_MODE_V2_ONLY) {
+ /* track will be stored as-is in ID3v2 case, so no problem here */
+ }
+ else {
+ if (silent < 10) {
+ error_printf("The track number has to be between 1 and 255 for ID3v1, ignored for ID3v1.\n");
+ }
+ }
+ }
+ }
+
+ T_ELIF("tg")
+ int ret = id3_tag(gfp, 'g', TENC_RAW, nextArg);
+ argUsed = 1;
+ if (ret != 0) {
+ if (0 == ignore_tag_errors) {
+ if (ret == -1) {
+ error_printf("Unknown ID3v1 genre number: '%s'.\n", nextArg);
+ return -1;
+ }
+ else if (ret == -2) {
+ if (id3tag_mode == ID3TAG_MODE_V1_ONLY) {
+ error_printf("Unknown ID3v1 genre: '%s'.\n", nextArg);
+ return -1;
+ }
+ else if (id3tag_mode == ID3TAG_MODE_V2_ONLY) {
+ /* genre will be stored as-is in ID3v2 case, so no problem here */
+ }
+ else {
+ if (silent < 10) {
+ error_printf("Unknown ID3v1 genre: '%s'. Setting ID3v1 genre to 'Other'\n", nextArg);
+ }
+ }
+ }
+ else {
+ error_printf("Internal error.\n");
+ return -1;
+ }
+ }
+ }
+
+ T_ELIF("tv")
+ argUsed = 1;
+ if (id3_tag(gfp, 'v', TENC_RAW, nextArg)) {
+ if (silent < 10) {
+ error_printf("Invalid field value: '%s'. Ignored\n", nextArg);
+ }
+ }
+
+ T_ELIF("ti")
+ argUsed = 1;
+ if (set_id3_albumart(gfp, nextArg) != 0) {
+ if (! ignore_tag_errors) {
+ return -1;
+ }
+ }
+
+ T_ELIF("ignore-tag-errors")
+ ignore_tag_errors = 1;
+
+ T_ELIF("add-id3v2")
+ id3tag_add_v2(gfp);
+
+ T_ELIF("id3v1-only")
+ id3tag_v1_only(gfp);
+ id3tag_mode = ID3TAG_MODE_V1_ONLY;
+
+ T_ELIF("id3v2-only")
+ id3tag_v2_only(gfp);
+ id3tag_mode = ID3TAG_MODE_V2_ONLY;
+
+ T_ELIF("space-id3v1")
+ id3tag_space_v1(gfp);
+
+ T_ELIF("pad-id3v2")
+ id3tag_pad_v2(gfp);
+
+ T_ELIF("pad-id3v2-size")
+ int n = atoi(nextArg);
+ n = n <= 128000 ? n : 128000;
+ n = n >= 0 ? n : 0;
+ id3tag_set_pad(gfp, n);
+ argUsed = 1;
+
+
+ T_ELIF("genre-list")
+ id3tag_genre_list(genre_list_handler, NULL);
+ return -2;
+
+#ifdef HAVE_ICONV
+ /* some experimental switches for setting ID3 tags
+ * with proper character encodings
+ */
+ T_ELIF("lTitle") argUsed = 1; id3_tag(gfp, 't', TENC_LATIN1, nextArg);
+ T_ELIF("lArtist") argUsed = 1; id3_tag(gfp, 'a', TENC_LATIN1, nextArg);
+ T_ELIF("lAlbum") argUsed = 1; id3_tag(gfp, 'l', TENC_LATIN1, nextArg);
+ T_ELIF("lGenre") argUsed = 1; id3_tag(gfp, 'g', TENC_LATIN1, nextArg);
+ T_ELIF("lComment")argUsed = 1; id3_tag(gfp, 'c', TENC_LATIN1, nextArg);
+ T_ELIF("lFieldvalue")
+ argUsed = 1;
+ if (id3_tag(gfp, 'v', TENC_LATIN1, nextArg)) {
+ if (silent < 10) {
+ error_printf("Invalid field value: '%s'. Ignored\n", nextArg);
+ }
+ }
+
+ T_ELIF("uTitle") argUsed = 1; id3_tag(gfp, 't', TENC_UCS2, nextArg);
+ T_ELIF("uArtist") argUsed = 1; id3_tag(gfp, 'a', TENC_UCS2, nextArg);
+ T_ELIF("uAlbum") argUsed = 1; id3_tag(gfp, 'l', TENC_UCS2, nextArg);
+ T_ELIF("uGenre") argUsed = 1; id3_tag(gfp, 'g', TENC_UCS2, nextArg);
+ T_ELIF("uComment")argUsed = 1; id3_tag(gfp, 'c', TENC_UCS2, nextArg);
+ /*
+ T_ELIF("uFieldvalue")
+ argUsed = 1;
+ if (id3_tag(gfp, 'v', TENC_UCS2, nextArg)) {
+ if (silent < 10) {
+ error_printf("Invalid field value: '%s'. Ignored\n", nextArg);
+ }
+ }
+ */
+#endif
+
+ T_ELIF("lowpass")
+ val = atof(nextArg);
+ argUsed = 1;
+ if (val < 0) {
+ lame_set_lowpassfreq(gfp, -1);
+ }
+ else {
+ /* useful are 0.001 kHz...50 kHz, 50 Hz...50000 Hz */
+ if (val < 0.001 || val > 50000.) {
+ error_printf("Must specify lowpass with --lowpass freq, freq >= 0.001 kHz\n");
+ return -1;
+ }
+ lame_set_lowpassfreq(gfp, (int) (val * (val < 50. ? 1.e3 : 1.e0) + 0.5));
+ }
+
+ T_ELIF("lowpass-width")
+ val = atof(nextArg);
+ argUsed = 1;
+ /* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */
+ if (val < 0.001 || val > 50000.) {
+ error_printf
+ ("Must specify lowpass width with --lowpass-width freq, freq >= 0.001 kHz\n");
+ return -1;
+ }
+ lame_set_lowpasswidth(gfp, (int) (val * (val < 16. ? 1.e3 : 1.e0) + 0.5));
+
+ T_ELIF("highpass")
+ val = atof(nextArg);
+ argUsed = 1;
+ if (val < 0.0) {
+ lame_set_highpassfreq(gfp, -1);
+ }
+ else {
+ /* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */
+ if (val < 0.001 || val > 50000.) {
+ error_printf("Must specify highpass with --highpass freq, freq >= 0.001 kHz\n");
+ return -1;
+ }
+ lame_set_highpassfreq(gfp, (int) (val * (val < 16. ? 1.e3 : 1.e0) + 0.5));
+ }
+
+ T_ELIF("highpass-width")
+ val = atof(nextArg);
+ argUsed = 1;
+ /* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */
+ if (val < 0.001 || val > 50000.) {
+ error_printf
+ ("Must specify highpass width with --highpass-width freq, freq >= 0.001 kHz\n");
+ return -1;
+ }
+ lame_set_highpasswidth(gfp, (int) val);
+
+ T_ELIF("comp")
+ argUsed = 1;
+ val = atof(nextArg);
+ if (val < 1.0) {
+ error_printf("Must specify compression ratio >= 1.0\n");
+ return -1;
+ }
+ lame_set_compression_ratio(gfp, (float) val);
+
+ T_ELIF("notemp")
+ (void) lame_set_useTemporal(gfp, 0);
+
+ T_ELIF("interch")
+ argUsed = 1;
+ (void) lame_set_interChRatio(gfp, (float) atof(nextArg));
+
+ T_ELIF("temporal-masking")
+ argUsed = 1;
+ (void) lame_set_useTemporal(gfp, atoi(nextArg) ? 1 : 0);
+
+ T_ELIF("nspsytune")
+ ;
+
+ T_ELIF("nssafejoint")
+ lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2);
+
+ T_ELIF("nsmsfix")
+ argUsed = 1;
+ (void) lame_set_msfix(gfp, atof(nextArg));
+
+ T_ELIF("ns-bass")
+ argUsed = 1;
+ {
+ double d;
+ int k;
+ d = atof(nextArg);
+ k = (int) (d * 4);
+ if (k < -32)
+ k = -32;
+ if (k > 31)
+ k = 31;
+ if (k < 0)
+ k += 64;
+ lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 2));
+ }
+
+ T_ELIF("ns-alto")
+ argUsed = 1;
+ {
+ double d;
+ int k;
+ d = atof(nextArg);
+ k = (int) (d * 4);
+ if (k < -32)
+ k = -32;
+ if (k > 31)
+ k = 31;
+ if (k < 0)
+ k += 64;
+ lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 8));
+ }
+
+ T_ELIF("ns-treble")
+ argUsed = 1;
+ {
+ double d;
+ int k;
+ d = atof(nextArg);
+ k = (int) (d * 4);
+ if (k < -32)
+ k = -32;
+ if (k > 31)
+ k = 31;
+ if (k < 0)
+ k += 64;
+ lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 14));
+ }
+
+ T_ELIF("ns-sfb21")
+ /* to be compatible with Naoki's original code,
+ * ns-sfb21 specifies how to change ns-treble for sfb21 */
+ argUsed = 1;
+ {
+ double d;
+ int k;
+ d = atof(nextArg);
+ k = (int) (d * 4);
+ if (k < -32)
+ k = -32;
+ if (k > 31)
+ k = 31;
+ if (k < 0)
+ k += 64;
+ lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 20));
+ }
+
+ T_ELIF("nspsytune2") {
+ }
+
+ /* some more GNU-ish options could be added
+ * brief => few messages on screen (name, status report)
+ * o/output file => specifies output filename
+ * O => stdout
+ * i/input file => specifies input filename
+ * I => stdin
+ */
+ T_ELIF2("quiet", "silent")
+ silent = 10; /* on a scale from 1 to 10 be very silent */
+
+ T_ELIF("brief")
+ silent = -5; /* print few info on screen */
+
+ T_ELIF("verbose")
+ silent = -10; /* print a lot on screen */
+
+ T_ELIF2("version", "license")
+ print_license(stdout);
+ return -2;
+
+ T_ELIF2("help", "usage")
+ short_help(gfp, stdout, ProgramName);
+ return -2;
+
+ T_ELIF("longhelp")
+ long_help(gfp, stdout, ProgramName, 0 /* lessmode=NO */ );
+ return -2;
+
+ T_ELIF("?")
+#ifdef __unix__
+ FILE *fp = popen("less -Mqc", "w");
+ long_help(gfp, fp, ProgramName, 0 /* lessmode=NO */ );
+ pclose(fp);
+#else
+ long_help(gfp, stdout, ProgramName, 1 /* lessmode=YES */ );
+#endif
+ return -2;
+
+ T_ELIF2("preset", "alt-preset")
+ argUsed = 1;
+ {
+ int fast = 0, cbr = 0;
+
+ while ((strcmp(nextArg, "fast") == 0) || (strcmp(nextArg, "cbr") == 0)) {
+
+ if ((strcmp(nextArg, "fast") == 0) && (fast < 1))
+ fast = 1;
+ if ((strcmp(nextArg, "cbr") == 0) && (cbr < 1))
+ cbr = 1;
+
+ argUsed++;
+ nextArg = i + argUsed < argc ? argv[i + argUsed] : "";
+ }
+
+ if (presets_set(gfp, fast, cbr, nextArg, ProgramName) < 0)
+ return -1;
+ }
+
+ T_ELIF("disptime")
+ argUsed = 1;
+ update_interval = (float) atof(nextArg);
+
+ T_ELIF("nogaptags")
+ nogap_tags = 1;
+
+ T_ELIF("nogapout")
+ strcpy(outPath, nextArg);
+ argUsed = 1;
+
+ T_ELIF("nogap")
+ nogap = 1;
+
+
+ T_ELIF_INTERNAL("tune") /*without helptext */
+ argUsed = 1;
+ {
+ extern void lame_set_tune(lame_t, float);
+ lame_set_tune(gfp, (float) atof(nextArg));
+ }
+
+ T_ELIF_INTERNAL("shortthreshold") {
+ float x, y;
+ int n = sscanf(nextArg, "%f,%f", &x, &y);
+ if (n == 1) {
+ y = x;
+ }
+ argUsed = 1;
+ (void) lame_set_short_threshold(gfp, x, y);
+ }
+
+ T_ELIF_INTERNAL("maskingadjust") /*without helptext */
+ argUsed = 1;
+ (void) lame_set_maskingadjust(gfp, (float) atof(nextArg));
+
+ T_ELIF_INTERNAL("maskingadjustshort") /*without helptext */
+ argUsed = 1;
+ (void) lame_set_maskingadjust_short(gfp, (float) atof(nextArg));
+
+ T_ELIF_INTERNAL("athcurve") /*without helptext */
+ argUsed = 1;
+ (void) lame_set_ATHcurve(gfp, (float) atof(nextArg));
+
+ T_ELIF_INTERNAL("no-preset-tune") /*without helptext */
+ (void) lame_set_preset_notune(gfp, 0);
+
+ T_ELIF_INTERNAL("substep")
+ argUsed = 1;
+ (void) lame_set_substep(gfp, atoi(nextArg));
+
+ T_ELIF_INTERNAL("sbgain") /*without helptext */
+ argUsed = 1;
+ (void) lame_set_subblock_gain(gfp, atoi(nextArg));
+
+ T_ELIF_INTERNAL("sfscale") /*without helptext */
+ (void) lame_set_sfscale(gfp, 1);
+
+ T_ELIF_INTERNAL("noath")
+ (void) lame_set_noATH(gfp, 1);
+
+ T_ELIF_INTERNAL("athonly")
+ (void) lame_set_ATHonly(gfp, 1);
+
+ T_ELIF_INTERNAL("athshort")
+ (void) lame_set_ATHshort(gfp, 1);
+
+ T_ELIF_INTERNAL("athlower")
+ argUsed = 1;
+ (void) lame_set_ATHlower(gfp, (float) atof(nextArg));
+
+ T_ELIF_INTERNAL("athtype")
+ argUsed = 1;
+ (void) lame_set_ATHtype(gfp, atoi(nextArg));
+
+ T_ELIF_INTERNAL("athaa-type") /* switch for developing, no DOCU */
+ argUsed = 1; /* once was 1:Gaby, 2:Robert, 3:Jon, else:off */
+ lame_set_athaa_type(gfp, atoi(nextArg)); /* now: 0:off else:Jon */
+
+ T_ELIF ("athaa-sensitivity")
+ argUsed=1;
+ lame_set_athaa_sensitivity(gfp, (float) atof(nextArg));
+
+ T_ELIF_INTERNAL("debug-file") /* switch for developing, no DOCU */
+ argUsed = 1; /* file name to print debug info into */
+ {
+ set_debug_file(nextArg);
+ }
+
+ T_ELSE {
+ error_printf("%s: unrecognized option --%s\n", ProgramName, token);
+ return -1;
+ }
+ T_END i += argUsed;
+
+ }
+ else {
+ while ((c = *token++) != '\0') {
+ arg = *token ? token : nextArg;
+ switch (c) {
+ case 'm':
+ argUsed = 1;
+
+ switch (*arg) {
+ case 's':
+ (void) lame_set_mode(gfp, STEREO);
+ break;
+ case 'd':
+ (void) lame_set_mode(gfp, DUAL_CHANNEL);
+ break;
+ case 'f':
+ lame_set_force_ms(gfp, 1);
+ /* FALLTHROUGH */
+ case 'j':
+ (void) lame_set_mode(gfp, JOINT_STEREO);
+ break;
+ case 'm':
+ (void) lame_set_mode(gfp, MONO);
+ break;
+ case 'a':
+ (void) lame_set_mode(gfp, JOINT_STEREO);
+ break;
+ default:
+ error_printf("%s: -m mode must be s/d/j/f/m not %s\n", ProgramName,
+ arg);
+ return -1;
+ }
+ break;
+
+ case 'V':
+ argUsed = 1;
+ /* to change VBR default look in lame.h */
+ if (lame_get_VBR(gfp) == vbr_off)
+ lame_set_VBR(gfp, vbr_default);
+ lame_set_VBR_quality(gfp, (float)atof(arg));
+ break;
+ case 'v':
+ /* to change VBR default look in lame.h */
+ if (lame_get_VBR(gfp) == vbr_off)
+ lame_set_VBR(gfp, vbr_default);
+ break;
+
+ case 'q':
+ argUsed = 1;
+ {
+ int tmp_quality = atoi(arg);
+
+ /* XXX should we move this into lame_set_quality()? */
+ if (tmp_quality < 0)
+ tmp_quality = 0;
+ if (tmp_quality > 9)
+ tmp_quality = 9;
+
+ (void) lame_set_quality(gfp, tmp_quality);
+ }
+ break;
+ case 'f':
+ (void) lame_set_quality(gfp, 7);
+ break;
+ case 'h':
+ (void) lame_set_quality(gfp, 2);
+ break;
+
+ case 's':
+ argUsed = 1;
+ val = atof(arg);
+ (void) lame_set_in_samplerate(gfp,
+ (int) (val * (val <= 192 ? 1.e3 : 1.e0) +
+ 0.5));
+ break;
+ case 'b':
+ argUsed = 1;
+ lame_set_brate(gfp, atoi(arg));
+ lame_set_VBR_min_bitrate_kbps(gfp, lame_get_brate(gfp));
+ break;
+ case 'B':
+ argUsed = 1;
+ lame_set_VBR_max_bitrate_kbps(gfp, atoi(arg));
+ break;
+ case 'F':
+ lame_set_VBR_hard_min(gfp, 1);
+ break;
+ case 't': /* dont write VBR tag */
+ (void) lame_set_bWriteVbrTag(gfp, 0);
+ disable_wav_header = 1;
+ break;
+ case 'T': /* do write VBR tag */
+ (void) lame_set_bWriteVbrTag(gfp, 1);
+ nogap_tags = 1;
+ disable_wav_header = 0;
+ break;
+ case 'r': /* force raw pcm input file */
+#if defined(LIBSNDFILE)
+ error_printf
+ ("WARNING: libsndfile may ignore -r and perform fseek's on the input.\n"
+ "Compile without libsndfile if this is a problem.\n");
+#endif
+ input_format = sf_raw;
+ break;
+ case 'x': /* force byte swapping */
+ swapbytes = 1;
+ break;
+ case 'p': /* (jo) error_protection: add crc16 information to stream */
+ lame_set_error_protection(gfp, 1);
+ break;
+ case 'a': /* autoconvert input file from stereo to mono - for mono mp3 encoding */
+ autoconvert = 1;
+ (void) lame_set_mode(gfp, MONO);
+ break;
+ case 'd': /*(void) lame_set_allow_diff_short( gfp, 1 ); */
+ case 'k': /*lame_set_lowpassfreq(gfp, -1);
+ lame_set_highpassfreq(gfp, -1); */
+ error_printf("WARNING: -%c is obsolete.\n", c);
+ break;
+ case 'S':
+ silent = 10;
+ break;
+ case 'X':
+ /* experimental switch -X:
+ the differnt types of quant compare are tough
+ to communicate to endusers, so they shouldn't
+ bother to toy around with them
+ */
+ {
+ int x, y;
+ int n = sscanf(arg, "%d,%d", &x, &y);
+ if (n == 1) {
+ y = x;
+ }
+ argUsed = 1;
+ if (INTERNAL_OPTS) {
+ lame_set_quant_comp(gfp, x);
+ lame_set_quant_comp_short(gfp, y);
+ }
+ }
+ break;
+ case 'Y':
+ lame_set_experimentalY(gfp, 1);
+ break;
+ case 'Z':
+ /* experimental switch -Z:
+ this switch is obsolete
+ */
+ {
+ int n = 1;
+ argUsed = sscanf(arg, "%d", &n);
+ if (INTERNAL_OPTS) {
+ lame_set_experimentalZ(gfp, n);
+ }
+ }
+ break;
+ case 'e':
+ argUsed = 1;
+
+ switch (*arg) {
+ case 'n':
+ lame_set_emphasis(gfp, 0);
+ break;
+ case '5':
+ lame_set_emphasis(gfp, 1);
+ break;
+ case 'c':
+ lame_set_emphasis(gfp, 3);
+ break;
+ default:
+ error_printf("%s: -e emp must be n/5/c not %s\n", ProgramName, arg);
+ return -1;
+ }
+ break;
+ case 'c':
+ lame_set_copyright(gfp, 1);
+ break;
+ case 'o':
+ lame_set_original(gfp, 0);
+ break;
+
+ case '?':
+ long_help(gfp, stdout, ProgramName, 0 /* LESSMODE=NO */ );
+ return -1;
+
+ default:
+ error_printf("%s: unrecognized option -%c\n", ProgramName, c);
+ return -1;
+ }
+ if (argUsed) {
+ if (arg == token)
+ token = ""; /* no more from token */
+ else
+ ++i; /* skip arg we used */
+ arg = "";
+ argUsed = 0;
+ }
+ }
+ }
+ }
+ else {
+ if (nogap) {
+ if ((num_nogap != NULL) && (count_nogap < *num_nogap)) {
+ strncpy(nogap_inPath[count_nogap++], argv[i], PATH_MAX + 1);
+ input_file = 1;
+ }
+ else {
+ /* sorry, calling program did not allocate enough space */
+ error_printf
+ ("Error: 'nogap option'. Calling program does not allow nogap option, or\n"
+ "you have exceeded maximum number of input files for the nogap option\n");
+ *num_nogap = -1;
+ return -1;
+ }
+ }
+ else {
+ /* normal options: inputfile [outputfile], and
+ either one can be a '-' for stdin/stdout */
+ if (inPath[0] == '\0') {
+ strncpy(inPath, argv[i], PATH_MAX + 1);
+ input_file = 1;
+ }
+ else {
+ if (outPath[0] == '\0')
+ strncpy(outPath, argv[i], PATH_MAX + 1);
+ else {
+ error_printf("%s: excess arg %s\n", ProgramName, argv[i]);
+ return -1;
+ }
+ }
+ }
+ }
+ } /* loop over args */
+
+ if (!input_file) {
+ usage(Console_IO.Console_fp, ProgramName);
+ return -1;
+ }
+
+ if (inPath[0] == '-')
+ silent = (silent <= 1 ? 1 : silent);
+#ifdef WIN32
+ else
+ dosToLongFileName(inPath);
+#endif
+
+ if (outPath[0] == '\0' && count_nogap == 0) {
+ if (inPath[0] == '-') {
+ /* if input is stdin, default output is stdout */
+ strcpy(outPath, "-");
+ }
+ else {
+ strncpy(outPath, inPath, PATH_MAX + 1 - 4);
+ if (lame_get_decode_only(gfp)) {
+ strncat(outPath, ".wav", 4);
+ }
+ else {
+ strncat(outPath, ".mp3", 4);
+ }
+ }
+ }
+
+ /* RG is enabled by default */
+ if (!noreplaygain)
+ lame_set_findReplayGain(gfp, 1);
+
+ /* disable VBR tags with nogap unless the VBR tags are forced */
+ if (nogap && lame_get_bWriteVbrTag(gfp) && nogap_tags == 0) {
+ console_printf("Note: Disabling VBR Xing/Info tag since it interferes with --nogap\n");
+ lame_set_bWriteVbrTag(gfp, 0);
+ }
+
+ /* some file options not allowed with stdout */
+ if (outPath[0] == '-') {
+ (void) lame_set_bWriteVbrTag(gfp, 0); /* turn off VBR tag */
+ }
+
+ /* if user did not explicitly specify input is mp3, check file name */
+ if (input_format == sf_unknown)
+ input_format = filename_to_type(inPath);
+
+#if !(defined HAVE_MPGLIB || defined AMIGA_MPEGA)
+ if (is_mpeg_file_format(input_format)) {
+ error_printf("Error: libmp3lame not compiled with mpg123 *decoding* support \n");
+ return -1;
+ }
+#endif
+
+
+ if (input_format == sf_ogg) {
+ error_printf("sorry, vorbis support in LAME is deprecated.\n");
+ return -1;
+ }
+ /* default guess for number of channels */
+ if (autoconvert)
+ (void) lame_set_num_channels(gfp, 2);
+ else if (MONO == lame_get_mode(gfp))
+ (void) lame_set_num_channels(gfp, 1);
+ else
+ (void) lame_set_num_channels(gfp, 2);
+
+ if (lame_get_free_format(gfp)) {
+ if (lame_get_brate(gfp) < 8 || lame_get_brate(gfp) > 640) {
+ error_printf("For free format, specify a bitrate between 8 and 640 kbps\n");
+ error_printf("with the -b <bitrate> option\n");
+ return -1;
+ }
+ }
+ if (num_nogap != NULL)
+ *num_nogap = count_nogap;
+ return 0;
+}
+
+
+/* end of parse.c */