xref: /plan9-contrib/sys/src/games/mp3enc/parse.c (revision 8f5875f3e9b20916b4c52ad4336922bc8653eb7b)
1*8f5875f3SDavid du Colombier /*
2*8f5875f3SDavid du Colombier  *	Command line parsing related functions
3*8f5875f3SDavid du Colombier  *
4*8f5875f3SDavid du Colombier  *	Copyright (c) 1999 Mark Taylor
5*8f5875f3SDavid du Colombier  *
6*8f5875f3SDavid du Colombier  * This library is free software; you can redistribute it and/or
7*8f5875f3SDavid du Colombier  * modify it under the terms of the GNU Library General Public
8*8f5875f3SDavid du Colombier  * License as published by the Free Software Foundation; either
9*8f5875f3SDavid du Colombier  * version 2 of the License, or (at your option) any later version.
10*8f5875f3SDavid du Colombier  *
11*8f5875f3SDavid du Colombier  * This library is distributed in the hope that it will be useful,
12*8f5875f3SDavid du Colombier  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*8f5875f3SDavid du Colombier  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
14*8f5875f3SDavid du Colombier  * Library General Public License for more details.
15*8f5875f3SDavid du Colombier  *
16*8f5875f3SDavid du Colombier  * You should have received a copy of the GNU Library General Public
17*8f5875f3SDavid du Colombier  * License along with this library; if not, write to the
18*8f5875f3SDavid du Colombier  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19*8f5875f3SDavid du Colombier  * Boston, MA 02111-1307, USA.
20*8f5875f3SDavid du Colombier  */
21*8f5875f3SDavid du Colombier 
22*8f5875f3SDavid du Colombier /* $Id: parse.c,v 1.68 2001/03/11 11:24:25 aleidinger Exp $ */
23*8f5875f3SDavid du Colombier 
24*8f5875f3SDavid du Colombier #include <stdio.h>
25*8f5875f3SDavid du Colombier #include <stdlib.h>
26*8f5875f3SDavid du Colombier #include <string.h>
27*8f5875f3SDavid du Colombier #include <assert.h>
28*8f5875f3SDavid du Colombier #include <ctype.h>
29*8f5875f3SDavid du Colombier #ifdef HAVE_CONFIG_H
30*8f5875f3SDavid du Colombier # include <config.h>
31*8f5875f3SDavid du Colombier #endif
32*8f5875f3SDavid du Colombier 
33*8f5875f3SDavid du Colombier #include "lame.h"
34*8f5875f3SDavid du Colombier #include "brhist.h"
35*8f5875f3SDavid du Colombier #include "parse.h"
36*8f5875f3SDavid du Colombier #include "main.h"
37*8f5875f3SDavid du Colombier #include "get_audio.h"
38*8f5875f3SDavid du Colombier 
39*8f5875f3SDavid du Colombier /* GLOBAL VARIABLES.  set by parse_args() */
40*8f5875f3SDavid du Colombier /* we need to clean this up */
41*8f5875f3SDavid du Colombier sound_file_format input_format;
42*8f5875f3SDavid du Colombier int	swapbytes;		/* force byte swapping   default=0*/
43*8f5875f3SDavid du Colombier int	silent;
44*8f5875f3SDavid du Colombier int	brhist;
45*8f5875f3SDavid du Colombier float	update_interval;	/* to use Frank's time status display */
46*8f5875f3SDavid du Colombier int	mp3_delay;		/* to adjust the number of samples truncated
47*8f5875f3SDavid du Colombier                                during decode */
48*8f5875f3SDavid du Colombier int	mp3_delay_set;		/* user specified the value of the mp3 encoder
49*8f5875f3SDavid du Colombier                                delay to assume for decoding */
50*8f5875f3SDavid du Colombier 
51*8f5875f3SDavid du Colombier /*
52*8f5875f3SDavid du Colombier * license - Writes version and license to the file specified by fp
53*8f5875f3SDavid du Colombier */
54*8f5875f3SDavid du Colombier static int
lame_version_print(FILE * const fp)55*8f5875f3SDavid du Colombier lame_version_print(FILE*const fp)
56*8f5875f3SDavid du Colombier {
57*8f5875f3SDavid du Colombier 	const char *v = get_lame_version();
58*8f5875f3SDavid du Colombier 	const char *u = get_lame_url();
59*8f5875f3SDavid du Colombier 	const int lenv = strlen(v);
60*8f5875f3SDavid du Colombier 	const int lenu = strlen (u);
61*8f5875f3SDavid du Colombier 	const int lw = 80;	/* line width of terminal in characters */
62*8f5875f3SDavid du Colombier 	const int sw = 16;	/* static width of text */
63*8f5875f3SDavid du Colombier 
64*8f5875f3SDavid du Colombier 	if (lw >= lenv + lenu + sw || lw < lenu + 2)
65*8f5875f3SDavid du Colombier 		/* text fits in 80 chars/line, or line even too small for url */
66*8f5875f3SDavid du Colombier 		fprintf(fp, "mp3enc (from lame version %s (%s))\n\n", v, u);
67*8f5875f3SDavid du Colombier 	else
68*8f5875f3SDavid du Colombier 		/* text too long, wrap url into next line, right aligned */
69*8f5875f3SDavid du Colombier 		fprintf(fp, "mp3enc (from lame version %s)\n%*s(%s)\n\n",
70*8f5875f3SDavid du Colombier 			v, lw - 2 - lenu, "", u);
71*8f5875f3SDavid du Colombier 	return 0;
72*8f5875f3SDavid du Colombier }
73*8f5875f3SDavid du Colombier 
74*8f5875f3SDavid du Colombier /* print version & license */
75*8f5875f3SDavid du Colombier int
print_license(const lame_global_flags * gfp,FILE * const fp,const char * ProgramName)76*8f5875f3SDavid du Colombier print_license(const lame_global_flags*gfp, FILE*const fp, const char*ProgramName)
77*8f5875f3SDavid du Colombier {
78*8f5875f3SDavid du Colombier 	lame_version_print(fp);
79*8f5875f3SDavid du Colombier 	fprintf(fp, "Can I use LAME in my commercial program?\n\n"
80*8f5875f3SDavid du Colombier 		"Yes, you can, under the restrictions of the LGPL.  In particular, you\n"
81*8f5875f3SDavid du Colombier 		"can include a compiled version of the LAME library (for example,\n"
82*8f5875f3SDavid du Colombier 		"lame.dll) with a commercial program.  Some notable requirements of\n"
83*8f5875f3SDavid du Colombier 		"the LGPL:\n"
84*8f5875f3SDavid du Colombier 		"\n"
85*8f5875f3SDavid du Colombier 		"1. In your program, you cannot include any source code from LAME, with\n"
86*8f5875f3SDavid du Colombier 		"   the exception of files whose only purpose is to describe the library\n"
87*8f5875f3SDavid du Colombier 		"   interface (such as lame.h).\n"
88*8f5875f3SDavid du Colombier 		"\n"
89*8f5875f3SDavid du Colombier 		"2. Any modifications of LAME must be released under the LGPL.\n"
90*8f5875f3SDavid du Colombier 		"   The LAME project (www.mp3dev.org) would appreciate being\n"
91*8f5875f3SDavid du Colombier 		"   notified of any modifications.\n"
92*8f5875f3SDavid du Colombier 		"\n"
93*8f5875f3SDavid du Colombier 		"3. You must give prominent notice that your program is:\n"
94*8f5875f3SDavid du Colombier 		"      A. using LAME (including version number)\n"
95*8f5875f3SDavid du Colombier 		"      B. LAME is under the LGPL\n"
96*8f5875f3SDavid du Colombier 		"      C. Provide a copy of the LGPL.  (the file COPYING contains the LGPL)\n"
97*8f5875f3SDavid du Colombier 		"      D. Provide a copy of LAME source, or a pointer where the LAME\n"
98*8f5875f3SDavid du Colombier 		"         source can be obtained (such as www.mp3dev.org)\n"
99*8f5875f3SDavid du Colombier 		"   An example of prominent notice would be an \"About the LAME encoding engine\"\n"
100*8f5875f3SDavid du Colombier 		"   button in some pull down menu within the executable of your program.\n"
101*8f5875f3SDavid du Colombier 		"\n"
102*8f5875f3SDavid du Colombier 		"4. If you determine that distribution of LAME requires a patent license,\n"
103*8f5875f3SDavid du Colombier 		"   you must obtain such license.\n"
104*8f5875f3SDavid du Colombier 		"\n"
105*8f5875f3SDavid du Colombier 		"\n"
106*8f5875f3SDavid du Colombier 		"*** IMPORTANT NOTE ***\n"
107*8f5875f3SDavid du Colombier 		"\n"
108*8f5875f3SDavid du Colombier 		"The decoding functions provided in LAME use the mpglib decoding engine which\n"
109*8f5875f3SDavid du Colombier 		"is under the GPL.  They may not be used by any program not released under the\n"
110*8f5875f3SDavid du Colombier 		"GPL unless you obtain such permission from the MPG123 project (www.mpg123.de).\n"
111*8f5875f3SDavid du Colombier 		"\n");
112*8f5875f3SDavid du Colombier 	return 0;
113*8f5875f3SDavid du Colombier }
114*8f5875f3SDavid du Colombier 
115*8f5875f3SDavid du Colombier /*
116*8f5875f3SDavid du Colombier * usage - Writes command line syntax to the file specified by fp
117*8f5875f3SDavid du Colombier */
118*8f5875f3SDavid du Colombier /* print general syntax */
119*8f5875f3SDavid du Colombier int
usage(const lame_global_flags * gfp,FILE * const fp,const char * ProgramName)120*8f5875f3SDavid du Colombier usage(const lame_global_flags*gfp, FILE*const fp, const char*ProgramName)
121*8f5875f3SDavid du Colombier {
122*8f5875f3SDavid du Colombier 	lame_version_print(fp);
123*8f5875f3SDavid du Colombier 	fprintf(fp, "usage: %s [options] <infile> [outfile]\n\n"
124*8f5875f3SDavid du Colombier 		"    <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n"
125*8f5875f3SDavid du Colombier 		"\n"
126*8f5875f3SDavid du Colombier 		"Try  \"%s --help\"     for more information\n"
127*8f5875f3SDavid du Colombier 		"  or \"%s --longhelp\"\n"
128*8f5875f3SDavid du Colombier 		"  or \"%s -?\"         for a complete options list\n\n",
129*8f5875f3SDavid du Colombier 		ProgramName, ProgramName, ProgramName, ProgramName);
130*8f5875f3SDavid du Colombier 	return 0;
131*8f5875f3SDavid du Colombier }
132*8f5875f3SDavid du Colombier 
133*8f5875f3SDavid du Colombier /*
134*8f5875f3SDavid du Colombier * short_help - Writes command line syntax to the file specified by fp
135*8f5875f3SDavid du Colombier *           but only the most important ones, to fit on a vt100 terminal
136*8f5875f3SDavid du Colombier */
137*8f5875f3SDavid du Colombier /* print short syntax help */
138*8f5875f3SDavid du Colombier int
short_help(const lame_global_flags * gfp,FILE * const fp,const char * ProgramName)139*8f5875f3SDavid du Colombier short_help(const lame_global_flags*gfp, FILE*const fp, const char*ProgramName)
140*8f5875f3SDavid du Colombier {
141*8f5875f3SDavid du Colombier 	lame_version_print(fp);
142*8f5875f3SDavid du Colombier 	fprintf(fp, "usage: %s [options] <infile> [outfile]\n\n"
143*8f5875f3SDavid du Colombier 		"    <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n"
144*8f5875f3SDavid du Colombier 		"\n"
145*8f5875f3SDavid du Colombier 		"RECOMMENDED:\n"
146*8f5875f3SDavid du Colombier 		"    mp3enc -h input.wav output.mp3\n"
147*8f5875f3SDavid du Colombier 		"\n"
148*8f5875f3SDavid du Colombier 		"OPTIONS:\n"
149*8f5875f3SDavid du Colombier 		"    -b bitrate      set the bitrate, default 128 kbps\n"
150*8f5875f3SDavid du Colombier 		"    -f              fast mode (lower quality)\n"
151*8f5875f3SDavid du Colombier 		"    -h              higher quality, but a little slower.  Recommended.\n"
152*8f5875f3SDavid du Colombier 		"    -k              keep ALL frequencies (disables all filters)\n"
153*8f5875f3SDavid du Colombier 		"                    Can cause ringing and twinkling\n"
154*8f5875f3SDavid du Colombier 		"    -m mode         (s)tereo, (j)oint, (m)ono or (a)uto\n"
155*8f5875f3SDavid du Colombier 		"                    default is (j) or (s) depending on bitrate\n"
156*8f5875f3SDavid du Colombier 		"    -V n            quality setting for VBR.  default n=%i\n"
157*8f5875f3SDavid du Colombier 		"\n"
158*8f5875f3SDavid du Colombier 		"    --preset type   type must be phone, voice, fm, tape, hifi, cd or studio\n"
159*8f5875f3SDavid du Colombier 		"                    \"--preset help\" gives some more infos on these\n"
160*8f5875f3SDavid du Colombier 		"\n"
161*8f5875f3SDavid du Colombier 		"    --longhelp      full list of options\n"
162*8f5875f3SDavid du Colombier 		"\n",
163*8f5875f3SDavid du Colombier 		ProgramName, gfp->VBR_q);
164*8f5875f3SDavid du Colombier 	return 0;
165*8f5875f3SDavid du Colombier }
166*8f5875f3SDavid du Colombier 
167*8f5875f3SDavid du Colombier /*
168*8f5875f3SDavid du Colombier * wait_for - Writes command line syntax to the file specified by fp
169*8f5875f3SDavid du Colombier */
170*8f5875f3SDavid du Colombier static void
wait_for(FILE * const fp,int lessmode)171*8f5875f3SDavid du Colombier wait_for (FILE*const fp, int lessmode)
172*8f5875f3SDavid du Colombier {
173*8f5875f3SDavid du Colombier 	if (lessmode ) {
174*8f5875f3SDavid du Colombier 		fflush(fp);
175*8f5875f3SDavid du Colombier 		getchar ();
176*8f5875f3SDavid du Colombier 	} else
177*8f5875f3SDavid du Colombier 		fprintf(fp, "\n");
178*8f5875f3SDavid du Colombier 	fprintf(fp, "\n");
179*8f5875f3SDavid du Colombier }
180*8f5875f3SDavid du Colombier 
181*8f5875f3SDavid du Colombier /* print long syntax help */
182*8f5875f3SDavid du Colombier int
long_help(const lame_global_flags * gfp,FILE * const fp,const char * ProgramName,int lessmode)183*8f5875f3SDavid du Colombier long_help(const lame_global_flags*gfp, FILE*const fp, const char*ProgramName, int lessmode)
184*8f5875f3SDavid du Colombier {
185*8f5875f3SDavid du Colombier 	lame_version_print(fp);
186*8f5875f3SDavid du Colombier 	fprintf(fp, "usage: %s [options] <infile> [outfile]\n\n"
187*8f5875f3SDavid du Colombier 		"    <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n"
188*8f5875f3SDavid du Colombier 		"\n"
189*8f5875f3SDavid du Colombier 		"RECOMMENDED:\n"
190*8f5875f3SDavid du Colombier 		"    mp3enc -h input.wav output.mp3\n"
191*8f5875f3SDavid du Colombier 		"\n"
192*8f5875f3SDavid du Colombier 		"OPTIONS:\n"
193*8f5875f3SDavid du Colombier 		"  Input options:\n"
194*8f5875f3SDavid du Colombier 		"    -r              input is raw pcm\n"
195*8f5875f3SDavid du Colombier 		"    -x              force byte-swapping of input\n"
196*8f5875f3SDavid du Colombier 		"    -s sfreq        sampling frequency of input file (kHz) - default 44.1 kHz\n"
197*8f5875f3SDavid du Colombier 		"    --mp1input      input file is a MPEG Layer I   file\n"
198*8f5875f3SDavid du Colombier 		"    --mp2input      input file is a MPEG Layer II  file\n"
199*8f5875f3SDavid du Colombier 		"    --mp3input      input file is a MPEG Layer III file\n"
200*8f5875f3SDavid du Colombier 		"    --ogginput      input file is a Ogg Vorbis file",
201*8f5875f3SDavid du Colombier 		ProgramName);
202*8f5875f3SDavid du Colombier 	wait_for (fp, lessmode);
203*8f5875f3SDavid du Colombier 	fprintf(fp, "  Operational options:\n"
204*8f5875f3SDavid du Colombier 		"    -m <mode>       (s)tereo, (j)oint, (f)orce, (m)ono or (a)auto  \n"
205*8f5875f3SDavid du Colombier 		"                    default is (s) or (j) depending on bitrate\n"
206*8f5875f3SDavid du Colombier 		"                    force = force ms_stereo on all frames.\n"
207*8f5875f3SDavid du Colombier 		"                    auto = jstereo, with varialbe mid/side threshold\n"
208*8f5875f3SDavid du Colombier 		"    -a              downmix from stereo to mono file for mono encoding\n"
209*8f5875f3SDavid du Colombier 		"    -d              allow channels to have different blocktypes\n"
210*8f5875f3SDavid du Colombier 		"    --disptime <arg>print progress report every arg seconds\n"
211*8f5875f3SDavid du Colombier 		"    --ogg           encode to Ogg Vorbis instead of MP3\n"
212*8f5875f3SDavid du Colombier 		"    --freeformat    produce a free format bitstream\n"
213*8f5875f3SDavid du Colombier 		"    --decode        input=mp3 file, output=wav\n"
214*8f5875f3SDavid du Colombier 		"    -t              disable writing wav header when using --decode\n"
215*8f5875f3SDavid du Colombier 		"    --comp  <arg>   choose bitrate to achive a compression ratio of <arg>\n"
216*8f5875f3SDavid du Colombier 		"    --scale <arg>   scale input (multiply PCM data) by <arg>\n"
217*8f5875f3SDavid du Colombier 		"    --athonly       only use the ATH for masking\n"
218*8f5875f3SDavid du Colombier 		"    --noath         disable the ATH for masking\n"
219*8f5875f3SDavid du Colombier 		"    --athlower x    lower the ATH x dB\n"
220*8f5875f3SDavid du Colombier 		"    --notemp        disable temporal masking effect\n"
221*8f5875f3SDavid du Colombier 		"    --short         use short blocks\n"
222*8f5875f3SDavid du Colombier 		"    --noshort       do not use short blocks\n"
223*8f5875f3SDavid du Colombier 		"    --voice         experimental voice mode\n"
224*8f5875f3SDavid du Colombier 		"    --preset type   type must be phone, voice, fm, tape, hifi, cd or studio\n"
225*8f5875f3SDavid du Colombier 		"                    \"--preset help\" gives some more infos on these");
226*8f5875f3SDavid du Colombier 	wait_for (fp, lessmode);
227*8f5875f3SDavid du Colombier 	fprintf(fp, "  Verbosity:\n"
228*8f5875f3SDavid du Colombier 		"    -S              don't print progress report, VBR histograms\n"
229*8f5875f3SDavid du Colombier 		"    --silent        don't print anything on screen\n"
230*8f5875f3SDavid du Colombier 		"    --quiet         don't print anything on screen\n"
231*8f5875f3SDavid du Colombier 		"    --verbose       print a lot of useful information, default\n"
232*8f5875f3SDavid du Colombier 		"\n"
233*8f5875f3SDavid du Colombier 		"  Noise shaping & psycho acoustic algorithms:\n"
234*8f5875f3SDavid du Colombier 		"    -q <arg>        <arg> = 0...9.  Default  -q 5 \n"
235*8f5875f3SDavid du Colombier 		"                    -q 0:  Highest quality, very slow \n"
236*8f5875f3SDavid du Colombier 		"                    -q 9:  Poor quality, but fast \n"
237*8f5875f3SDavid du Colombier 		"    -h              Same as -q 2.   Recommended.\n"
238*8f5875f3SDavid du Colombier 		"    -f              Same as -q 7.   Fast, ok quality\n");
239*8f5875f3SDavid du Colombier 	wait_for (fp, lessmode);
240*8f5875f3SDavid du Colombier 	fprintf(fp, "  CBR (constant bitrate, the default) options:\n"
241*8f5875f3SDavid du Colombier 		"    -b <bitrate>    set the bitrate in kbps, default 128 kbps\n"
242*8f5875f3SDavid du Colombier 		"\n"
243*8f5875f3SDavid du Colombier 		"  ABR options:\n"
244*8f5875f3SDavid du Colombier 		"    --abr <bitrate> specify average bitrate desired (instead of quality)\n"
245*8f5875f3SDavid du Colombier 		"\n"
246*8f5875f3SDavid du Colombier 		"  VBR options:\n"
247*8f5875f3SDavid du Colombier 		"    -v              use variable bitrate (VBR) (--vbr-old)\n"
248*8f5875f3SDavid du Colombier 		"    --vbr-old       use old variable bitrate (VBR) routine\n"
249*8f5875f3SDavid du Colombier 		"    --vbr-new       use new variable bitrate (VBR) routine\n"
250*8f5875f3SDavid du Colombier 		"    --vbr-mtrh      a merger of old and new (VBR) routine\n"
251*8f5875f3SDavid du Colombier 		"    -V n            quality setting for VBR.  default n=%i\n"
252*8f5875f3SDavid du Colombier 		"                    0=high quality,bigger files. 9=smaller files\n"
253*8f5875f3SDavid du Colombier 		"    -b <bitrate>    specify minimum allowed bitrate, default  32 kbps\n"
254*8f5875f3SDavid du Colombier 		"    -B <bitrate>    specify maximum allowed bitrate, default 320 kbps\n"
255*8f5875f3SDavid du Colombier 		"    -F              strictly enforce the -b option, for use with players that\n"
256*8f5875f3SDavid du Colombier 		"                    do not support low bitrate mp3 (Apex AD600-A DVD/mp3 player)\n"
257*8f5875f3SDavid du Colombier 		"    -t              disable writing Xing VBR informational tag\n"
258*8f5875f3SDavid du Colombier 		"    --nohist        disable VBR histogram display", gfp->VBR_q);
259*8f5875f3SDavid du Colombier 
260*8f5875f3SDavid du Colombier 	wait_for (fp, lessmode);
261*8f5875f3SDavid du Colombier 	fprintf(fp, "  MP3 header/stream options:\n"
262*8f5875f3SDavid du Colombier 		"    -e <emp>        de-emphasis n/5/c  (obsolete)\n"
263*8f5875f3SDavid du Colombier 		"    -c              mark as copyright\n"
264*8f5875f3SDavid du Colombier 		"    -o              mark as non-original\n"
265*8f5875f3SDavid du Colombier 		"    -p              error protection.  adds 16 bit checksum to every frame\n"
266*8f5875f3SDavid du Colombier 		"                    (the checksum is computed correctly)\n"
267*8f5875f3SDavid du Colombier 		"    --nores         disable the bit reservoir\n"
268*8f5875f3SDavid du Colombier 		"    --strictly-enforce-ISO   comply as much as possible to ISO MPEG spec\n"
269*8f5875f3SDavid du Colombier 		"\n"
270*8f5875f3SDavid du Colombier 		"  Filter options:\n"
271*8f5875f3SDavid du Colombier 		"    -k              keep ALL frequencies (disables all filters),\n"
272*8f5875f3SDavid du Colombier 		"                    Can cause ringing and twinkling\n"
273*8f5875f3SDavid du Colombier 		"  --lowpass <freq>        frequency(kHz), lowpass filter cutoff above freq\n"
274*8f5875f3SDavid du Colombier 		"  --lowpass-width <freq>  frequency(kHz) - default 15%% of lowpass freq\n"
275*8f5875f3SDavid du Colombier 		"  --highpass <freq>       frequency(kHz), highpass filter cutoff below freq\n"
276*8f5875f3SDavid du Colombier 		"  --highpass-width <freq> frequency(kHz) - default 15%% of highpass freq\n"
277*8f5875f3SDavid du Colombier 		"  --resample <sfreq>  sampling frequency of output file(kHz)- default=automatic\n"
278*8f5875f3SDavid du Colombier 		"  --cwlimit <freq>    compute tonality up to freq (in kHz) default 8.8717");
279*8f5875f3SDavid du Colombier 
280*8f5875f3SDavid du Colombier 	wait_for (fp, lessmode);
281*8f5875f3SDavid du Colombier 	fprintf(fp,
282*8f5875f3SDavid du Colombier 		"  ID3 tag options:\n"
283*8f5875f3SDavid du Colombier 		"    --tt <title>    audio/song title (max 30 chars for version 1 tag)\n"
284*8f5875f3SDavid du Colombier 		"    --ta <artist>   audio/song artist (max 30 chars for version 1 tag)\n"
285*8f5875f3SDavid du Colombier 		"    --tl <album>    audio/song album (max 30 chars for version 1 tag)\n"
286*8f5875f3SDavid du Colombier 		"    --ty <year>     audio/song year of issue (1 to 9999)\n"
287*8f5875f3SDavid du Colombier 		"    --tc <comment>  user-defined text (max 30 chars for v1 tag, 28 for v1.1)\n"
288*8f5875f3SDavid du Colombier 		"    --tn <track>    audio/song track number (1 to 255, creates v1.1 tag)\n"
289*8f5875f3SDavid du Colombier 		"    --tg <genre>    audio/song genre (name or number in list)\n"
290*8f5875f3SDavid du Colombier 		"    --add-id3v2     force addition of version 2 tag\n"
291*8f5875f3SDavid du Colombier 		"    --id3v1-only    add only a version 1 tag\n"
292*8f5875f3SDavid du Colombier 		"    --id3v2-only    add only a version 2 tag\n"
293*8f5875f3SDavid du Colombier 		"    --space-id3v1   pad version 1 tag with spaces instead of nulls\n"
294*8f5875f3SDavid du Colombier 		"    --pad-id3v2     pad version 2 tag with extra 128 bytes\n"
295*8f5875f3SDavid du Colombier 		"    --genre-list    print alphabetically sorted ID3 genre list and exit\n"
296*8f5875f3SDavid du Colombier 		"\n"
297*8f5875f3SDavid du Colombier 		"    Note: A version 2 tag will NOT be added unless one of the input fields\n"
298*8f5875f3SDavid du Colombier 		"    won't fit in a version 1 tag (e.g. the title string is longer than 30\n"
299*8f5875f3SDavid du Colombier 		"    characters), or the '--add-id3v2' or '--id3v2-only' options are used,\n"
300*8f5875f3SDavid du Colombier 		"    or output is redirected to stdout."
301*8f5875f3SDavid du Colombier #if defined(HAVE_VORBIS)
302*8f5875f3SDavid du Colombier 		"\n\n"
303*8f5875f3SDavid du Colombier 		"    Note: All '--t*' options (except those for track and genre) work for Ogg\n"
304*8f5875f3SDavid du Colombier 		"    Vorbis output, but other ID3-specific options are ignored."
305*8f5875f3SDavid du Colombier #endif
306*8f5875f3SDavid du Colombier 		);
307*8f5875f3SDavid du Colombier 	wait_for (fp, lessmode);
308*8f5875f3SDavid du Colombier 	display_bitrates(fp);
309*8f5875f3SDavid du Colombier 	return 0;
310*8f5875f3SDavid du Colombier }
311*8f5875f3SDavid du Colombier 
312*8f5875f3SDavid du Colombier static void
display_bitrate(FILE * const fp,const char * const version,const int div,const int index)313*8f5875f3SDavid du Colombier display_bitrate(FILE*const fp, const char*const version, const int div, const int index)
314*8f5875f3SDavid du Colombier {
315*8f5875f3SDavid du Colombier 	int	i;
316*8f5875f3SDavid du Colombier 
317*8f5875f3SDavid du Colombier 	fprintf(fp, "\nMPEG-%-3s layer III sample frequencies (kHz):  %2d  %2d  %g\n"
318*8f5875f3SDavid du Colombier 		"bitrates (kbps):",
319*8f5875f3SDavid du Colombier 		version, 32 / div, 48 / div, 44.1 / div);
320*8f5875f3SDavid du Colombier 	for (i = 1; i <= 14; i++)
321*8f5875f3SDavid du Colombier 		fprintf(fp, " %2i", bitrate_table [index] [i]);
322*8f5875f3SDavid du Colombier 	fprintf(fp, "\n");
323*8f5875f3SDavid du Colombier }
324*8f5875f3SDavid du Colombier 
325*8f5875f3SDavid du Colombier int
display_bitrates(FILE * const fp)326*8f5875f3SDavid du Colombier display_bitrates(FILE*const fp)
327*8f5875f3SDavid du Colombier {
328*8f5875f3SDavid du Colombier 	display_bitrate(fp, "1"  , 1, 1);
329*8f5875f3SDavid du Colombier 	display_bitrate(fp, "2"  , 2, 0);
330*8f5875f3SDavid du Colombier 	display_bitrate(fp, "2.5", 4, 0);
331*8f5875f3SDavid du Colombier 	fprintf(fp, "\n");
332*8f5875f3SDavid du Colombier 	fflush(fp);
333*8f5875f3SDavid du Colombier 	return 0;
334*8f5875f3SDavid du Colombier }
335*8f5875f3SDavid du Colombier 
336*8f5875f3SDavid du Colombier typedef struct {
337*8f5875f3SDavid du Colombier 	const char*name;	/* name of preset */
338*8f5875f3SDavid du Colombier 	long	resample;	/* resample frequency in Hz, or -1 for no resampling */
339*8f5875f3SDavid du Colombier 	short	highpass_freq;	/* highpass frequency in Hz, or -1 for no highpass filtering */
340*8f5875f3SDavid du Colombier 	short	lowpass_freq;	/* lowpass frequency in Hz, or -1 for no lowpass filtering */
341*8f5875f3SDavid du Colombier 	short	lowpass_width;	/* lowpass width in Hz */
342*8f5875f3SDavid du Colombier 	signed char no_short_blocks;	/* use of short blocks, 1: no, 0: yes */
343*8f5875f3SDavid du Colombier 	signed char quality;	/* quality, the same as -f or -h */
344*8f5875f3SDavid du Colombier 	MPEG_mode mode;		/* channel mode (mono, stereo, joint) */
345*8f5875f3SDavid du Colombier 	short	cbr;		/* CBR data rate in kbps (8...320) */
346*8f5875f3SDavid du Colombier 	signed char xvbr_mode;	/* VBR mode (0...9) */
347*8f5875f3SDavid du Colombier 	short	vbr_min;	/* minimum VBR rate in kbps(8...256) */
348*8f5875f3SDavid du Colombier 	short	vbr_max;	/* maximum VBR rate in kbps (16...320) */
349*8f5875f3SDavid du Colombier } preset_t;
350*8f5875f3SDavid du Colombier 
351*8f5875f3SDavid du Colombier const preset_t Presets [] = {
352*8f5875f3SDavid du Colombier /* name       fs     fu    fo    dfo shrt qual  mode       cbr vbr_mode/min/max */
353*8f5875f3SDavid du Colombier { "phone" ,  8000, 125,  3400,    0,  1,  5, MONO        ,  16,  6,   8,  24 },	/* phone standard 300-3400 */
354*8f5875f3SDavid du Colombier { "phon+" , 11025, 100,  4000,    0,  1,  5, MONO        ,  24,  4,  16,  32 },	/* phone theoretical limits */
355*8f5875f3SDavid du Colombier { "lw"    , 11025,  -1,  4000,    0,  0,  5, MONO        ,  24,  3,  16,  56 },	/* LW */
356*8f5875f3SDavid du Colombier { "mw-eu" , 11025,  -1,  4000,    0,  0,  5, MONO        ,  24,  3,  16,  56 },	/* MW in europe */
357*8f5875f3SDavid du Colombier { "mw-us" , 16000,  -1,  7500,    0,  0,  5, MONO        ,  40,  3,  24, 112 },	/* MW in U.S.A. */
358*8f5875f3SDavid du Colombier { "sw"    , 11025,  -1,  4000,    0,  0,  5, MONO        ,  24,  3,  16,  56 },	/* SW */
359*8f5875f3SDavid du Colombier { "fm"    , 32000,  -1, 15000,    0,  0,  3, JOINT_STEREO, 112,  3,  80, 256 },
360*8f5875f3SDavid du Colombier { "voice" , 24000,  -1, 12000,    0,  1,  5, MONO        ,  56,  4,  40, 112 },
361*8f5875f3SDavid du Colombier { "radio" ,    -1,  -1, 15000,    0,  0,  3, JOINT_STEREO, 128,  3,  96, 256 },
362*8f5875f3SDavid du Colombier { "tape"  ,    -1,  -1, 18000,  900,  0,  3, JOINT_STEREO, 128,  3,  96, 256 },
363*8f5875f3SDavid du Colombier { "hifi"  ,    -1,  -1, 18000,  900,  0, -1, JOINT_STEREO, 160,  2, 112, 320 },
364*8f5875f3SDavid du Colombier { "cd"    ,    -1,  -1,    -1,   -1,  0, -1, STEREO      , 192,  1, 128, 320 },
365*8f5875f3SDavid du Colombier { "studio",    -1,  -1,    -1,   -1,  0, -1, STEREO      , 256,  0, 160, 320 },
366*8f5875f3SDavid du Colombier };
367*8f5875f3SDavid du Colombier 
368*8f5875f3SDavid du Colombier /*
369*8f5875f3SDavid du Colombier * Writes presetting info to #stdout#
370*8f5875f3SDavid du Colombier */
371*8f5875f3SDavid du Colombier 
372*8f5875f3SDavid du Colombier /* print possible combination */
373*8f5875f3SDavid du Colombier static int
presets_info(const lame_global_flags * gfp,FILE * const fp,const char * ProgramName)374*8f5875f3SDavid du Colombier presets_info(const lame_global_flags*gfp, FILE*const fp, const char*ProgramName)
375*8f5875f3SDavid du Colombier {
376*8f5875f3SDavid du Colombier 	int	i;
377*8f5875f3SDavid du Colombier 
378*8f5875f3SDavid du Colombier 	fprintf(fp, "\n");
379*8f5875f3SDavid du Colombier 	lame_version_print(fp);
380*8f5875f3SDavid du Colombier 
381*8f5875f3SDavid du Colombier 	fprintf(fp, "Presets are some shortcuts for common settings.\n");
382*8f5875f3SDavid du Colombier 	fprintf(fp, "They can be combined with -v if you want VBR MP3s.\n");
383*8f5875f3SDavid du Colombier 
384*8f5875f3SDavid du Colombier 	fprintf(fp, "\n                ");
385*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
386*8f5875f3SDavid du Colombier 		fprintf(fp,  strlen(Presets[i].name) <= 4? "%5s ": " %-5s",
387*8f5875f3SDavid du Colombier 			Presets[i].name);
388*8f5875f3SDavid du Colombier 	fprintf(fp, "\n=================");
389*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
390*8f5875f3SDavid du Colombier 		fprintf(fp,  "======");
391*8f5875f3SDavid du Colombier 	fprintf(fp, "\n--resample      ");
392*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
393*8f5875f3SDavid du Colombier 		if (Presets[i].resample < 0)
394*8f5875f3SDavid du Colombier 			fprintf(fp,  "      ");
395*8f5875f3SDavid du Colombier 		else
396*8f5875f3SDavid du Colombier 			fprintf(fp,  "%6.3g",  Presets[i].resample * 1.e-3);
397*8f5875f3SDavid du Colombier 	fprintf(fp, "\n--highpass      ");
398*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
399*8f5875f3SDavid du Colombier 		if (Presets[i].highpass_freq < 0)
400*8f5875f3SDavid du Colombier 			fprintf(fp,  "      ");
401*8f5875f3SDavid du Colombier 		else
402*8f5875f3SDavid du Colombier 			fprintf(fp,  "%6.3g",  Presets[i].highpass_freq * 1.e-3);
403*8f5875f3SDavid du Colombier 	fprintf(fp, "\n--lowpass       ");
404*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
405*8f5875f3SDavid du Colombier 		if (Presets[i].lowpass_freq < 0)
406*8f5875f3SDavid du Colombier 			fprintf(fp,  "      ");
407*8f5875f3SDavid du Colombier 		else
408*8f5875f3SDavid du Colombier 			fprintf(fp,  "%6.3g",  Presets[i].lowpass_freq * 1.e-3);
409*8f5875f3SDavid du Colombier 	fprintf(fp, "\n--lowpass-width ");
410*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
411*8f5875f3SDavid du Colombier 		if (Presets[i].lowpass_width < 0)
412*8f5875f3SDavid du Colombier 			fprintf(fp,  "      ");
413*8f5875f3SDavid du Colombier 		else
414*8f5875f3SDavid du Colombier 			fprintf(fp,  "%6.3g",  Presets[i].lowpass_width * 1.e-3);
415*8f5875f3SDavid du Colombier 	fprintf(fp, "\n--noshort       ");
416*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
417*8f5875f3SDavid du Colombier 		switch (Presets[i].no_short_blocks ) {
418*8f5875f3SDavid du Colombier 		case 1:
419*8f5875f3SDavid du Colombier 			fprintf(fp,  "   yes");
420*8f5875f3SDavid du Colombier 			break;
421*8f5875f3SDavid du Colombier 		case 0:
422*8f5875f3SDavid du Colombier 			fprintf(fp,  "    no");
423*8f5875f3SDavid du Colombier 			break;
424*8f5875f3SDavid du Colombier 		case -1:
425*8f5875f3SDavid du Colombier 			fprintf(fp,  "      ");
426*8f5875f3SDavid du Colombier 			break;
427*8f5875f3SDavid du Colombier 		default:
428*8f5875f3SDavid du Colombier 			assert (0);
429*8f5875f3SDavid du Colombier 			break;
430*8f5875f3SDavid du Colombier 		}
431*8f5875f3SDavid du Colombier 	fprintf(fp, "\n                ");
432*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
433*8f5875f3SDavid du Colombier 		switch (Presets[i].mode ) {
434*8f5875f3SDavid du Colombier 		case MONO:
435*8f5875f3SDavid du Colombier 			fprintf(fp, "   -mm");
436*8f5875f3SDavid du Colombier 			break;
437*8f5875f3SDavid du Colombier 		case JOINT_STEREO:
438*8f5875f3SDavid du Colombier 			fprintf(fp, "   -mj");
439*8f5875f3SDavid du Colombier 			break;
440*8f5875f3SDavid du Colombier 		case STEREO:
441*8f5875f3SDavid du Colombier 			fprintf(fp, "   -ms");
442*8f5875f3SDavid du Colombier 			break;
443*8f5875f3SDavid du Colombier 		case -1:
444*8f5875f3SDavid du Colombier 			fprintf(fp, "      ");
445*8f5875f3SDavid du Colombier 			break;
446*8f5875f3SDavid du Colombier 		default:
447*8f5875f3SDavid du Colombier 			assert (0);
448*8f5875f3SDavid du Colombier 			break;
449*8f5875f3SDavid du Colombier 		}
450*8f5875f3SDavid du Colombier 	fprintf(fp, "\n                ");
451*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
452*8f5875f3SDavid du Colombier 		switch (Presets[i].quality ) {
453*8f5875f3SDavid du Colombier 		case -1:
454*8f5875f3SDavid du Colombier 			fprintf(fp, "      ");
455*8f5875f3SDavid du Colombier 			break;
456*8f5875f3SDavid du Colombier 		case 2:
457*8f5875f3SDavid du Colombier 			fprintf(fp, "    -h");
458*8f5875f3SDavid du Colombier 			break;
459*8f5875f3SDavid du Colombier 		case 3:
460*8f5875f3SDavid du Colombier 			fprintf(fp, "   -q3");
461*8f5875f3SDavid du Colombier 			break;
462*8f5875f3SDavid du Colombier 		case 5:
463*8f5875f3SDavid du Colombier 			fprintf(fp, "      ");
464*8f5875f3SDavid du Colombier 			break;
465*8f5875f3SDavid du Colombier 		case 7:
466*8f5875f3SDavid du Colombier 			fprintf(fp, "    -f");
467*8f5875f3SDavid du Colombier 			break;
468*8f5875f3SDavid du Colombier 		default:
469*8f5875f3SDavid du Colombier 			assert (0);
470*8f5875f3SDavid du Colombier 			break;
471*8f5875f3SDavid du Colombier 		}
472*8f5875f3SDavid du Colombier 	fprintf(fp, "\n-b              ");
473*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
474*8f5875f3SDavid du Colombier 		fprintf(fp,  "%6u", Presets[i].cbr);
475*8f5875f3SDavid du Colombier 	fprintf(fp, "\n-- PLUS WITH -v ");
476*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
477*8f5875f3SDavid du Colombier 		fprintf(fp,  "------");
478*8f5875f3SDavid du Colombier 	fprintf(fp, "-\n-V              ");
479*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
480*8f5875f3SDavid du Colombier 		fprintf(fp,  "%6u", Presets[i].xvbr_mode);
481*8f5875f3SDavid du Colombier 	fprintf(fp, "\n-b              ");
482*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
483*8f5875f3SDavid du Colombier 		fprintf(fp,  "%6u", Presets[i].vbr_min);
484*8f5875f3SDavid du Colombier 	fprintf(fp, "\n-B              ");
485*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
486*8f5875f3SDavid du Colombier 		fprintf(fp,  "%6u", Presets[i].vbr_max);
487*8f5875f3SDavid du Colombier 	fprintf(fp, "\n----------------");
488*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof(Presets) / sizeof(*Presets); i++)
489*8f5875f3SDavid du Colombier 		fprintf(fp,  "------");
490*8f5875f3SDavid du Colombier 
491*8f5875f3SDavid du Colombier 	fprintf(fp, "-\nEXAMPLES:\n");
492*8f5875f3SDavid du Colombier 	fprintf(fp, " a) --preset fm\n");
493*8f5875f3SDavid du Colombier 	fprintf(fp, "    equal to: -mj -b112 --resample 32 --lowpass 15 --lowpass-width 0\n");
494*8f5875f3SDavid du Colombier 	fprintf(fp, " b) -v --preset studio\n");
495*8f5875f3SDavid du Colombier 	fprintf(fp, "    equals to: -h -ms -V0 -b160 -B320\n");
496*8f5875f3SDavid du Colombier 
497*8f5875f3SDavid du Colombier 	return 0;
498*8f5875f3SDavid du Colombier }
499*8f5875f3SDavid du Colombier 
500*8f5875f3SDavid du Colombier 
501*8f5875f3SDavid du Colombier static int
presets_setup(lame_global_flags * gfp,const char * preset_name,const char * ProgramName)502*8f5875f3SDavid du Colombier presets_setup(lame_global_flags*gfp, const char*preset_name, const char*ProgramName)
503*8f5875f3SDavid du Colombier {
504*8f5875f3SDavid du Colombier 	int	i;
505*8f5875f3SDavid du Colombier 
506*8f5875f3SDavid du Colombier 	for (i = 0; i < sizeof Presets / sizeof *Presets; i++)
507*8f5875f3SDavid du Colombier 		if (0 == strncmp(preset_name, Presets[i].name, strlen(preset_name))) {
508*8f5875f3SDavid du Colombier 			if (Presets[i].resample >= 0)
509*8f5875f3SDavid du Colombier 				(void) lame_set_out_samplerate(gfp,
510*8f5875f3SDavid du Colombier 					Presets[i].resample);
511*8f5875f3SDavid du Colombier 			if (Presets[i].highpass_freq >= 0)
512*8f5875f3SDavid du Colombier 				gfp ->highpassfreq = Presets[i].highpass_freq,
513*8f5875f3SDavid du Colombier 					gfp ->highpasswidth = 0;
514*8f5875f3SDavid du Colombier 			gfp ->lowpassfreq          = Presets[i].lowpass_freq;
515*8f5875f3SDavid du Colombier 			gfp ->lowpasswidth         = Presets[i].lowpass_width;
516*8f5875f3SDavid du Colombier 			gfp ->no_short_blocks      = Presets[i].no_short_blocks;
517*8f5875f3SDavid du Colombier 			(void) lame_set_quality(gfp, Presets[i].quality);
518*8f5875f3SDavid du Colombier 			(void) lame_set_mode(gfp, Presets[i].mode);
519*8f5875f3SDavid du Colombier 			gfp ->brate                = Presets[i].cbr;
520*8f5875f3SDavid du Colombier 			gfp ->VBR_q                = Presets[i].xvbr_mode;
521*8f5875f3SDavid du Colombier 			gfp ->VBR_min_bitrate_kbps = Presets[i].vbr_min;
522*8f5875f3SDavid du Colombier 			gfp ->VBR_max_bitrate_kbps = Presets[i].vbr_max;
523*8f5875f3SDavid du Colombier 			return 0;
524*8f5875f3SDavid du Colombier 		}
525*8f5875f3SDavid du Colombier 	presets_info(gfp, stderr, ProgramName);
526*8f5875f3SDavid du Colombier 	return -1;
527*8f5875f3SDavid du Colombier }
528*8f5875f3SDavid du Colombier 
529*8f5875f3SDavid du Colombier static void
genre_list_handler(int num,const char * name,void * cookie)530*8f5875f3SDavid du Colombier genre_list_handler(int num, const char *name, void *cookie)
531*8f5875f3SDavid du Colombier {
532*8f5875f3SDavid du Colombier 	printf("%3d %s\n", num, name);
533*8f5875f3SDavid du Colombier }
534*8f5875f3SDavid du Colombier 
535*8f5875f3SDavid du Colombier /*
536*8f5875f3SDavid du Colombier * parse_args - Sets encoding parameters to the specifications of the
537*8f5875f3SDavid du Colombier * command line.  Default settings are used for parameters
538*8f5875f3SDavid du Colombier * not specified in the command line.
539*8f5875f3SDavid du Colombier *
540*8f5875f3SDavid du Colombier * If the input file is in WAVE or AIFF format, the sampling frequency is read
541*8f5875f3SDavid du Colombier * from the AIFF header.
542*8f5875f3SDavid du Colombier *
543*8f5875f3SDavid du Colombier * The input and output filenames are read into #inpath# and #outpath#.
544*8f5875f3SDavid du Colombier */
545*8f5875f3SDavid du Colombier 
546*8f5875f3SDavid du Colombier /* would use real "strcasecmp" but it isn't portable */
547*8f5875f3SDavid du Colombier static int
local_strcasecmp(const char * s1,const char * s2)548*8f5875f3SDavid du Colombier local_strcasecmp(const char*s1, const char*s2)
549*8f5875f3SDavid du Colombier {
550*8f5875f3SDavid du Colombier 	unsigned char	c1, c2;
551*8f5875f3SDavid du Colombier 
552*8f5875f3SDavid du Colombier 	do {
553*8f5875f3SDavid du Colombier 		c1 = tolower(*s1);
554*8f5875f3SDavid du Colombier 		c2 = tolower(*s2);
555*8f5875f3SDavid du Colombier 		if (!c1)
556*8f5875f3SDavid du Colombier 			break;
557*8f5875f3SDavid du Colombier 		++s1;
558*8f5875f3SDavid du Colombier 		++s2;
559*8f5875f3SDavid du Colombier 	} while (c1 == c2);
560*8f5875f3SDavid du Colombier 	return c1 - c2;
561*8f5875f3SDavid du Colombier }
562*8f5875f3SDavid du Colombier 
563*8f5875f3SDavid du Colombier /*
564*8f5875f3SDavid du Colombier  * LAME is a simple frontend which just uses the file extension
565*8f5875f3SDavid du Colombier  * to determine the file type.  Trying to analyze the file
566*8f5875f3SDavid du Colombier  * contents is well beyond the scope of LAME and should not be added.
567*8f5875f3SDavid du Colombier  */
568*8f5875f3SDavid du Colombier static int
filename_to_type(const char * FileName)569*8f5875f3SDavid du Colombier filename_to_type(const char*FileName)
570*8f5875f3SDavid du Colombier {
571*8f5875f3SDavid du Colombier 	int	len = strlen(FileName);
572*8f5875f3SDavid du Colombier 
573*8f5875f3SDavid du Colombier 	if (len < 4)
574*8f5875f3SDavid du Colombier 		return sf_unknown;
575*8f5875f3SDavid du Colombier 
576*8f5875f3SDavid du Colombier 	FileName += len - 4;
577*8f5875f3SDavid du Colombier 	if (0 == local_strcasecmp(FileName, ".mpg" ))
578*8f5875f3SDavid du Colombier 		return sf_mp1;
579*8f5875f3SDavid du Colombier 	if (0 == local_strcasecmp(FileName, ".mp1" ))
580*8f5875f3SDavid du Colombier 		return sf_mp1;
581*8f5875f3SDavid du Colombier 	if (0 == local_strcasecmp(FileName, ".mp2" ))
582*8f5875f3SDavid du Colombier 		return sf_mp2;
583*8f5875f3SDavid du Colombier 	if (0 == local_strcasecmp(FileName, ".mp3" ))
584*8f5875f3SDavid du Colombier 		return sf_mp3;
585*8f5875f3SDavid du Colombier 	if (0 == local_strcasecmp(FileName, ".ogg" ))
586*8f5875f3SDavid du Colombier 		return sf_ogg;
587*8f5875f3SDavid du Colombier 	if (0 == local_strcasecmp(FileName, ".wav" ))
588*8f5875f3SDavid du Colombier 		return sf_wave;
589*8f5875f3SDavid du Colombier 	if (0 == local_strcasecmp(FileName, ".aif" ))
590*8f5875f3SDavid du Colombier 		return sf_aiff;
591*8f5875f3SDavid du Colombier 	if (0 == local_strcasecmp(FileName, ".raw" ))
592*8f5875f3SDavid du Colombier 		return sf_raw;
593*8f5875f3SDavid du Colombier 	return sf_unknown;
594*8f5875f3SDavid du Colombier }
595*8f5875f3SDavid du Colombier 
596*8f5875f3SDavid du Colombier static int
resample_rate(double freq)597*8f5875f3SDavid du Colombier resample_rate(double freq)
598*8f5875f3SDavid du Colombier {
599*8f5875f3SDavid du Colombier 	if (freq >= 1.e3)
600*8f5875f3SDavid du Colombier 		freq *= 1.e-3;
601*8f5875f3SDavid du Colombier 
602*8f5875f3SDavid du Colombier 	switch ((int)freq) {
603*8f5875f3SDavid du Colombier 	case 8:
604*8f5875f3SDavid du Colombier 		return  8000;
605*8f5875f3SDavid du Colombier 	case 11:
606*8f5875f3SDavid du Colombier 		return 11025;
607*8f5875f3SDavid du Colombier 	case 12:
608*8f5875f3SDavid du Colombier 		return 12000;
609*8f5875f3SDavid du Colombier 	case 16:
610*8f5875f3SDavid du Colombier 		return 16000;
611*8f5875f3SDavid du Colombier 	case 22:
612*8f5875f3SDavid du Colombier 		return 22050;
613*8f5875f3SDavid du Colombier 	case 24:
614*8f5875f3SDavid du Colombier 		return 24000;
615*8f5875f3SDavid du Colombier 	case 32:
616*8f5875f3SDavid du Colombier 		return 32000;
617*8f5875f3SDavid du Colombier 	case 44:
618*8f5875f3SDavid du Colombier 		return 44100;
619*8f5875f3SDavid du Colombier 	case 48:
620*8f5875f3SDavid du Colombier 		return 48000;
621*8f5875f3SDavid du Colombier 	default:
622*8f5875f3SDavid du Colombier 		fprintf(stderr, "Illegal resample frequency: %.3f kHz\n", freq);
623*8f5875f3SDavid du Colombier 		return 0;
624*8f5875f3SDavid du Colombier 	}
625*8f5875f3SDavid du Colombier }
626*8f5875f3SDavid du Colombier 
627*8f5875f3SDavid du Colombier /* Ugly, NOT final version */
628*8f5875f3SDavid du Colombier 
629*8f5875f3SDavid du Colombier #define T_IF(str)	if (0 == local_strcasecmp (token,str) ) {
630*8f5875f3SDavid du Colombier #define T_ELIF(str)	} else if (0 == local_strcasecmp (token,str) ) {
631*8f5875f3SDavid du Colombier #define T_ELIF2(str1,str2) } else if (0 == local_strcasecmp(token,str1) || \
632*8f5875f3SDavid du Colombier 			0 == local_strcasecmp(token,str2)) {
633*8f5875f3SDavid du Colombier #define T_ELSE		} else {
634*8f5875f3SDavid du Colombier #define T_END		}
635*8f5875f3SDavid du Colombier 
636*8f5875f3SDavid du Colombier int
parse_args(lame_global_flags * gfp,int argc,char ** argv)637*8f5875f3SDavid du Colombier parse_args(lame_global_flags*gfp, int argc, char **argv)
638*8f5875f3SDavid du Colombier {
639*8f5875f3SDavid du Colombier 	int err, i, autoconvert  = 0;
640*8f5875f3SDavid du Colombier 	double val;
641*8f5875f3SDavid du Colombier 	const char *ProgramName = argv[0];
642*8f5875f3SDavid du Colombier 
643*8f5875f3SDavid du Colombier 	/* turn on display options. user settings may turn them off below */
644*8f5875f3SDavid du Colombier 	silent   = 0;
645*8f5875f3SDavid du Colombier 	brhist   = 1;
646*8f5875f3SDavid du Colombier 	mp3_delay = 0;
647*8f5875f3SDavid du Colombier 	mp3_delay_set = 0;
648*8f5875f3SDavid du Colombier 	id3tag_init(gfp);
649*8f5875f3SDavid du Colombier 
650*8f5875f3SDavid du Colombier 	/* process args */
651*8f5875f3SDavid du Colombier 	for (i = 0, err = 0; ++i < argc && !err; ) {
652*8f5875f3SDavid du Colombier 		char	c;
653*8f5875f3SDavid du Colombier 		char *token, *arg, *nextArg;
654*8f5875f3SDavid du Colombier 		int	argUsed;
655*8f5875f3SDavid du Colombier 
656*8f5875f3SDavid du Colombier 		token = argv[i];
657*8f5875f3SDavid du Colombier 		if (*token++ == '-' ) {
658*8f5875f3SDavid du Colombier 			argUsed = 0;
659*8f5875f3SDavid du Colombier 			nextArg = i + 1 < argc? argv[i+1]: "";
660*8f5875f3SDavid du Colombier 
661*8f5875f3SDavid du Colombier 			if (*token == '-') {		/* GNU style */
662*8f5875f3SDavid du Colombier 				token++;
663*8f5875f3SDavid du Colombier 
664*8f5875f3SDavid du Colombier 				T_IF ("resample")
665*8f5875f3SDavid du Colombier 				argUsed = 1;
666*8f5875f3SDavid du Colombier 				(void) lame_set_out_samplerate(gfp,
667*8f5875f3SDavid du Colombier 					resample_rate(atof (nextArg) ));
668*8f5875f3SDavid du Colombier 
669*8f5875f3SDavid du Colombier 				T_ELIF ("vbr-old")
670*8f5875f3SDavid du Colombier 				gfp->VBR = vbr_rh;
671*8f5875f3SDavid du Colombier 
672*8f5875f3SDavid du Colombier 				T_ELIF ("vbr-new")
673*8f5875f3SDavid du Colombier 				gfp->VBR = vbr_mt;
674*8f5875f3SDavid du Colombier 
675*8f5875f3SDavid du Colombier 				T_ELIF ("vbr-mtrh")
676*8f5875f3SDavid du Colombier 				gfp->VBR = vbr_mtrh;
677*8f5875f3SDavid du Colombier 
678*8f5875f3SDavid du Colombier 				T_ELIF ("r3mix")
679*8f5875f3SDavid du Colombier 				gfp->VBR = vbr_rh;
680*8f5875f3SDavid du Colombier 				gfp->VBR_q = 1;
681*8f5875f3SDavid du Colombier 				(void) lame_set_quality(gfp, 2);
682*8f5875f3SDavid du Colombier 				gfp->lowpassfreq = 19500;
683*8f5875f3SDavid du Colombier 				(void) lame_set_mode(gfp, JOINT_STEREO);
684*8f5875f3SDavid du Colombier 				gfp->ATHtype = 3;
685*8f5875f3SDavid du Colombier 				gfp->VBR_min_bitrate_kbps = 64;
686*8f5875f3SDavid du Colombier 
687*8f5875f3SDavid du Colombier 				T_ELIF ("abr")
688*8f5875f3SDavid du Colombier 				argUsed = 1;
689*8f5875f3SDavid du Colombier 				gfp->VBR = vbr_abr;
690*8f5875f3SDavid du Colombier 				gfp->VBR_mean_bitrate_kbps = atoi(nextArg);
691*8f5875f3SDavid du Colombier 				/*
692*8f5875f3SDavid du Colombier 				 * values larger than 8000 are bps (like
693*8f5875f3SDavid du Colombier 				 * Fraunhofer), so it's strange to get 320000
694*8f5875f3SDavid du Colombier 				 * bps MP3 when specifying 8000 bps MP3.
695*8f5875f3SDavid du Colombier 				 */
696*8f5875f3SDavid du Colombier 				if (gfp ->VBR_mean_bitrate_kbps >= 8000)
697*8f5875f3SDavid du Colombier 					gfp->VBR_mean_bitrate_kbps = (gfp->VBR_mean_bitrate_kbps + 500 )/1000;
698*8f5875f3SDavid du Colombier 				gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 320);
699*8f5875f3SDavid du Colombier 				gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps,   8);
700*8f5875f3SDavid du Colombier 
701*8f5875f3SDavid du Colombier 				T_ELIF ("mp1input")
702*8f5875f3SDavid du Colombier 				input_format = sf_mp1;
703*8f5875f3SDavid du Colombier 
704*8f5875f3SDavid du Colombier 				T_ELIF ("mp2input")
705*8f5875f3SDavid du Colombier 				input_format = sf_mp2;
706*8f5875f3SDavid du Colombier 
707*8f5875f3SDavid du Colombier 				T_ELIF ("mp3input")
708*8f5875f3SDavid du Colombier 				input_format = sf_mp3;
709*8f5875f3SDavid du Colombier 
710*8f5875f3SDavid du Colombier 				T_ELIF ("ogginput")
711*8f5875f3SDavid du Colombier #if defined(HAVE_VORBIS)
712*8f5875f3SDavid du Colombier 				input_format = sf_ogg;
713*8f5875f3SDavid du Colombier #else
714*8f5875f3SDavid du Colombier 				fprintf(stderr, "Error: mp3enc not compiled with Vorbis support\n");
715*8f5875f3SDavid du Colombier 				return -1;
716*8f5875f3SDavid du Colombier #endif
717*8f5875f3SDavid du Colombier 				T_ELIF ("ogg")
718*8f5875f3SDavid du Colombier #if defined(HAVE_VORBIS)
719*8f5875f3SDavid du Colombier 				(void) lame_set_ogg(gfp, 1);
720*8f5875f3SDavid du Colombier #else
721*8f5875f3SDavid du Colombier 				fprintf(stderr, "Error: mp3enc not compiled with Vorbis support\n");
722*8f5875f3SDavid du Colombier 				return -1;
723*8f5875f3SDavid du Colombier #endif
724*8f5875f3SDavid du Colombier 				T_ELIF ("phone")
725*8f5875f3SDavid du Colombier 				if (presets_setup(gfp, token, ProgramName ) < 0)
726*8f5875f3SDavid du Colombier 					return -1;
727*8f5875f3SDavid du Colombier 
728*8f5875f3SDavid du Colombier 				T_ELIF ("voice")
729*8f5875f3SDavid du Colombier 				if (presets_setup(gfp, token, ProgramName ) < 0)
730*8f5875f3SDavid du Colombier 					return -1;
731*8f5875f3SDavid du Colombier 
732*8f5875f3SDavid du Colombier 				T_ELIF ("radio")
733*8f5875f3SDavid du Colombier 				if (presets_setup(gfp, token, ProgramName ) < 0)
734*8f5875f3SDavid du Colombier 					return -1;
735*8f5875f3SDavid du Colombier 
736*8f5875f3SDavid du Colombier 				T_ELIF ("tape")
737*8f5875f3SDavid du Colombier 				if (presets_setup(gfp, token, ProgramName ) < 0)
738*8f5875f3SDavid du Colombier 					return -1;
739*8f5875f3SDavid du Colombier 
740*8f5875f3SDavid du Colombier 				T_ELIF ("cd")
741*8f5875f3SDavid du Colombier 				if (presets_setup(gfp, token, ProgramName ) < 0)
742*8f5875f3SDavid du Colombier 					return -1;
743*8f5875f3SDavid du Colombier 
744*8f5875f3SDavid du Colombier 				T_ELIF ("studio")
745*8f5875f3SDavid du Colombier 				if (presets_setup(gfp, token, ProgramName ) < 0)
746*8f5875f3SDavid du Colombier 					return -1;
747*8f5875f3SDavid du Colombier 
748*8f5875f3SDavid du Colombier 				T_ELIF ("noshort")
749*8f5875f3SDavid du Colombier 				gfp->no_short_blocks = 1;
750*8f5875f3SDavid du Colombier 
751*8f5875f3SDavid du Colombier 				T_ELIF ("short")
752*8f5875f3SDavid du Colombier 				gfp->no_short_blocks = 0;
753*8f5875f3SDavid du Colombier 
754*8f5875f3SDavid du Colombier 				T_ELIF ("decode")
755*8f5875f3SDavid du Colombier 				(void) lame_set_decode_only(gfp, 1);
756*8f5875f3SDavid du Colombier 
757*8f5875f3SDavid du Colombier 				T_ELIF ("decode-mp3delay")
758*8f5875f3SDavid du Colombier 				mp3_delay = atoi(nextArg);
759*8f5875f3SDavid du Colombier 				mp3_delay_set = 1;
760*8f5875f3SDavid du Colombier 				argUsed = 1;
761*8f5875f3SDavid du Colombier 
762*8f5875f3SDavid du Colombier 				T_ELIF ("noath")
763*8f5875f3SDavid du Colombier 				gfp->noATH = 1;
764*8f5875f3SDavid du Colombier 
765*8f5875f3SDavid du Colombier 				T_ELIF ("nores")
766*8f5875f3SDavid du Colombier 				gfp->disable_reservoir = 1;
767*8f5875f3SDavid du Colombier 				gfp->padding_type = 0;
768*8f5875f3SDavid du Colombier 
769*8f5875f3SDavid du Colombier 				T_ELIF ("strictly-enforce-ISO")
770*8f5875f3SDavid du Colombier 				gfp->strict_ISO = 1;
771*8f5875f3SDavid du Colombier 
772*8f5875f3SDavid du Colombier 				T_ELIF ("athonly")
773*8f5875f3SDavid du Colombier 				gfp->ATHonly = 1;
774*8f5875f3SDavid du Colombier 
775*8f5875f3SDavid du Colombier 				T_ELIF ("athlower")
776*8f5875f3SDavid du Colombier 				argUsed = 1;
777*8f5875f3SDavid du Colombier 				gfp->ATHlower = atof(nextArg);
778*8f5875f3SDavid du Colombier 
779*8f5875f3SDavid du Colombier 				T_ELIF ("athtype")
780*8f5875f3SDavid du Colombier 				argUsed = 1;
781*8f5875f3SDavid du Colombier 				gfp->ATHtype = atoi(nextArg);
782*8f5875f3SDavid du Colombier 
783*8f5875f3SDavid du Colombier 				T_ELIF ("scale")
784*8f5875f3SDavid du Colombier 				argUsed = 1;
785*8f5875f3SDavid du Colombier 				(void) lame_set_scale(gfp, atof(nextArg));
786*8f5875f3SDavid du Colombier 
787*8f5875f3SDavid du Colombier 				T_ELIF ("freeformat")
788*8f5875f3SDavid du Colombier 				gfp->free_format = 1;
789*8f5875f3SDavid du Colombier 
790*8f5875f3SDavid du Colombier 				T_ELIF ("athshort")
791*8f5875f3SDavid du Colombier 				gfp->ATHshort = 1;
792*8f5875f3SDavid du Colombier 
793*8f5875f3SDavid du Colombier 				T_ELIF ("nohist")
794*8f5875f3SDavid du Colombier 				brhist = 0;
795*8f5875f3SDavid du Colombier 
796*8f5875f3SDavid du Colombier 				/* options for ID3 tag */
797*8f5875f3SDavid du Colombier 				T_ELIF ("tt")
798*8f5875f3SDavid du Colombier 				argUsed = 1;
799*8f5875f3SDavid du Colombier 				id3tag_set_title(gfp, nextArg);
800*8f5875f3SDavid du Colombier 
801*8f5875f3SDavid du Colombier 				T_ELIF ("ta")
802*8f5875f3SDavid du Colombier 				argUsed = 1;
803*8f5875f3SDavid du Colombier 				id3tag_set_artist(gfp, nextArg);
804*8f5875f3SDavid du Colombier 
805*8f5875f3SDavid du Colombier 				T_ELIF ("tl")
806*8f5875f3SDavid du Colombier 				argUsed = 1;
807*8f5875f3SDavid du Colombier 				id3tag_set_album(gfp, nextArg);
808*8f5875f3SDavid du Colombier 
809*8f5875f3SDavid du Colombier 				T_ELIF ("ty")
810*8f5875f3SDavid du Colombier 				argUsed = 1;
811*8f5875f3SDavid du Colombier 				id3tag_set_year(gfp, nextArg);
812*8f5875f3SDavid du Colombier 
813*8f5875f3SDavid du Colombier 				T_ELIF ("tc")
814*8f5875f3SDavid du Colombier 				argUsed = 1;
815*8f5875f3SDavid du Colombier 				id3tag_set_comment(gfp, nextArg);
816*8f5875f3SDavid du Colombier 
817*8f5875f3SDavid du Colombier 				T_ELIF ("tn")
818*8f5875f3SDavid du Colombier 				argUsed = 1;
819*8f5875f3SDavid du Colombier 				id3tag_set_track(gfp, nextArg);
820*8f5875f3SDavid du Colombier 
821*8f5875f3SDavid du Colombier 				T_ELIF ("tg")
822*8f5875f3SDavid du Colombier 				argUsed = 1;
823*8f5875f3SDavid du Colombier 				if (id3tag_set_genre(gfp, nextArg)) {
824*8f5875f3SDavid du Colombier 					fprintf(stderr, "Unknown genre: %s.  Specify genre name or number\n", nextArg);
825*8f5875f3SDavid du Colombier 					return -1;
826*8f5875f3SDavid du Colombier 				}
827*8f5875f3SDavid du Colombier 
828*8f5875f3SDavid du Colombier 				T_ELIF ("add-id3v2")
829*8f5875f3SDavid du Colombier 				id3tag_add_v2(gfp);
830*8f5875f3SDavid du Colombier 
831*8f5875f3SDavid du Colombier 				T_ELIF ("id3v1-only")
832*8f5875f3SDavid du Colombier 				id3tag_v1_only(gfp);
833*8f5875f3SDavid du Colombier 
834*8f5875f3SDavid du Colombier 				T_ELIF ("id3v2-only")
835*8f5875f3SDavid du Colombier 				id3tag_v2_only(gfp);
836*8f5875f3SDavid du Colombier 
837*8f5875f3SDavid du Colombier 				T_ELIF ("space-id3v1")
838*8f5875f3SDavid du Colombier 				id3tag_space_v1(gfp);
839*8f5875f3SDavid du Colombier 
840*8f5875f3SDavid du Colombier 				T_ELIF ("pad-id3v2")
841*8f5875f3SDavid du Colombier 				id3tag_pad_v2(gfp);
842*8f5875f3SDavid du Colombier 
843*8f5875f3SDavid du Colombier 				T_ELIF ("genre-list")
844*8f5875f3SDavid du Colombier 				id3tag_genre_list(genre_list_handler, NULL);
845*8f5875f3SDavid du Colombier 				return - 2;
846*8f5875f3SDavid du Colombier 
847*8f5875f3SDavid du Colombier 				T_ELIF ("lowpass")
848*8f5875f3SDavid du Colombier 				val     = atof(nextArg);
849*8f5875f3SDavid du Colombier 				argUsed = 1;
850*8f5875f3SDavid du Colombier 				/* useful are 0.001 kHz...50 kHz, 50 Hz...50000 Hz */
851*8f5875f3SDavid du Colombier 				gfp ->lowpassfreq = val * (val < 50. ? 1.e3 : 1.e0 ) + 0.5;
852*8f5875f3SDavid du Colombier 				if (val < 0.001 || val > 50000. ) {
853*8f5875f3SDavid du Colombier 					fprintf(stderr, "Must specify lowpass with --lowpass freq, freq >= 0.001 kHz\n");
854*8f5875f3SDavid du Colombier 					return -1;
855*8f5875f3SDavid du Colombier 				}
856*8f5875f3SDavid du Colombier 
857*8f5875f3SDavid du Colombier 				T_ELIF ("lowpass-width")
858*8f5875f3SDavid du Colombier 				argUsed = 1;
859*8f5875f3SDavid du Colombier 				gfp->lowpasswidth =  1000.0 * atof(nextArg ) + 0.5;
860*8f5875f3SDavid du Colombier 				if (gfp->lowpasswidth  < 0) {
861*8f5875f3SDavid du Colombier 					fprintf(stderr, "Must specify lowpass width with --lowpass-width freq, freq >= 0 kHz\n");
862*8f5875f3SDavid du Colombier 					return -1;
863*8f5875f3SDavid du Colombier 				}
864*8f5875f3SDavid du Colombier 
865*8f5875f3SDavid du Colombier 				T_ELIF ("highpass")
866*8f5875f3SDavid du Colombier 				val = atof(nextArg);
867*8f5875f3SDavid du Colombier 				argUsed = 1;
868*8f5875f3SDavid du Colombier 				/* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */
869*8f5875f3SDavid du Colombier 				gfp->highpassfreq =  val * (val < 16. ? 1.e3 : 1.e0 ) + 0.5;
870*8f5875f3SDavid du Colombier 				if (val < 0.001 || val > 50000. ) {
871*8f5875f3SDavid du Colombier 					fprintf(stderr, "Must specify highpass with --highpass freq, freq >= 0.001 kHz\n");
872*8f5875f3SDavid du Colombier 					return -1;
873*8f5875f3SDavid du Colombier 				}
874*8f5875f3SDavid du Colombier 
875*8f5875f3SDavid du Colombier 				T_ELIF ("highpass-width")
876*8f5875f3SDavid du Colombier 				argUsed = 1;
877*8f5875f3SDavid du Colombier 				gfp->highpasswidth =  1000.0 * atof(nextArg ) + 0.5;
878*8f5875f3SDavid du Colombier 				if (gfp->highpasswidth  < 0) {
879*8f5875f3SDavid du Colombier 					fprintf(stderr, "Must specify highpass width with --highpass-width freq, freq >= 0 kHz\n");
880*8f5875f3SDavid du Colombier 					return -1;
881*8f5875f3SDavid du Colombier 				}
882*8f5875f3SDavid du Colombier 
883*8f5875f3SDavid du Colombier 				T_ELIF ("cwlimit")
884*8f5875f3SDavid du Colombier 				val = atof (nextArg);
885*8f5875f3SDavid du Colombier 				argUsed = 1;
886*8f5875f3SDavid du Colombier 				/* useful are 0.001 kHz...50 kHz, 50 Hz...50000 Hz */
887*8f5875f3SDavid du Colombier 				gfp ->cwlimit = val *(val <= 50. ? 1.e3 : 1.e0);
888*8f5875f3SDavid du Colombier 				if (gfp->cwlimit <= 0 ) {
889*8f5875f3SDavid du Colombier 					fprintf(stderr, "Must specify cwlimit with --cwlimit freq, freq >= 0.001 kHz\n");
890*8f5875f3SDavid du Colombier 					return -1;
891*8f5875f3SDavid du Colombier 				}
892*8f5875f3SDavid du Colombier 
893*8f5875f3SDavid du Colombier 				T_ELIF ("comp")
894*8f5875f3SDavid du Colombier 				argUsed = 1;
895*8f5875f3SDavid du Colombier 				gfp->compression_ratio =  atof(nextArg);
896*8f5875f3SDavid du Colombier 				if (gfp->compression_ratio < 1.0 ) {
897*8f5875f3SDavid du Colombier 					fprintf(stderr, "Must specify compression ratio >= 1.0\n");
898*8f5875f3SDavid du Colombier 					return -1;
899*8f5875f3SDavid du Colombier 				}
900*8f5875f3SDavid du Colombier 
901*8f5875f3SDavid du Colombier 				T_ELIF ("notemp")
902*8f5875f3SDavid du Colombier 				gfp->useTemporal =  0;
903*8f5875f3SDavid du Colombier 
904*8f5875f3SDavid du Colombier 				T_ELIF ("nspsytune")
905*8f5875f3SDavid du Colombier 				gfp->exp_nspsytune |= 1;
906*8f5875f3SDavid du Colombier 				gfp->experimentalZ = 1;
907*8f5875f3SDavid du Colombier 				gfp->experimentalX = 1;
908*8f5875f3SDavid du Colombier 
909*8f5875f3SDavid du Colombier 				T_ELIF ("nssafejoint")
910*8f5875f3SDavid du Colombier 				gfp->exp_nspsytune |= 2;
911*8f5875f3SDavid du Colombier 
912*8f5875f3SDavid du Colombier 				T_ELIF ("ns-bass")
913*8f5875f3SDavid du Colombier 				argUsed = 1;
914*8f5875f3SDavid du Colombier 				 {
915*8f5875f3SDavid du Colombier 					double	d;
916*8f5875f3SDavid du Colombier 					int	k;
917*8f5875f3SDavid du Colombier 					d = atof(nextArg);
918*8f5875f3SDavid du Colombier 					k = (int)(d * 4);
919*8f5875f3SDavid du Colombier 					if (k < -32)
920*8f5875f3SDavid du Colombier 						k = -32;
921*8f5875f3SDavid du Colombier 					if (k >  31)
922*8f5875f3SDavid du Colombier 						k =  31;
923*8f5875f3SDavid du Colombier 					if (k < 0)
924*8f5875f3SDavid du Colombier 						k += 64;
925*8f5875f3SDavid du Colombier 					gfp->exp_nspsytune |= (k << 2);
926*8f5875f3SDavid du Colombier 				}
927*8f5875f3SDavid du Colombier 
928*8f5875f3SDavid du Colombier 				T_ELIF ("ns-alto")
929*8f5875f3SDavid du Colombier 				argUsed = 1;
930*8f5875f3SDavid du Colombier 				 {
931*8f5875f3SDavid du Colombier 					double	d;
932*8f5875f3SDavid du Colombier 					int	k;
933*8f5875f3SDavid du Colombier 					d = atof(nextArg);
934*8f5875f3SDavid du Colombier 					k = (int)(d * 4);
935*8f5875f3SDavid du Colombier 					if (k < -32)
936*8f5875f3SDavid du Colombier 						k = -32;
937*8f5875f3SDavid du Colombier 					if (k >  31)
938*8f5875f3SDavid du Colombier 						k =  31;
939*8f5875f3SDavid du Colombier 					if (k < 0)
940*8f5875f3SDavid du Colombier 						k += 64;
941*8f5875f3SDavid du Colombier 					gfp->exp_nspsytune |= (k << 8);
942*8f5875f3SDavid du Colombier 				}
943*8f5875f3SDavid du Colombier 
944*8f5875f3SDavid du Colombier 				T_ELIF ("ns-treble")
945*8f5875f3SDavid du Colombier 				argUsed = 1;
946*8f5875f3SDavid du Colombier 				 {
947*8f5875f3SDavid du Colombier 					double	d;
948*8f5875f3SDavid du Colombier 					int	k;
949*8f5875f3SDavid du Colombier 					d = atof(nextArg);
950*8f5875f3SDavid du Colombier 					k = (int)(d * 4);
951*8f5875f3SDavid du Colombier 					if (k < -32)
952*8f5875f3SDavid du Colombier 						k = -32;
953*8f5875f3SDavid du Colombier 					if (k >  31)
954*8f5875f3SDavid du Colombier 						k =  31;
955*8f5875f3SDavid du Colombier 					if (k < 0)
956*8f5875f3SDavid du Colombier 						k += 64;
957*8f5875f3SDavid du Colombier 					gfp->exp_nspsytune |= (k << 14);
958*8f5875f3SDavid du Colombier 				}
959*8f5875f3SDavid du Colombier 
960*8f5875f3SDavid du Colombier 				/* some more GNU-ish options could be added
961*8f5875f3SDavid du Colombier 		 * brief         => few messages on screen (name, status report)
962*8f5875f3SDavid du Colombier 		 * o/output file => specifies output filename
963*8f5875f3SDavid du Colombier 		 * O             => stdout
964*8f5875f3SDavid du Colombier 		 * i/input file  => specifies input filename
965*8f5875f3SDavid du Colombier 		 * I             => stdin
966*8f5875f3SDavid du Colombier 		 */
967*8f5875f3SDavid du Colombier 				T_ELIF2 ("quiet", "silent")
968*8f5875f3SDavid du Colombier 				silent = 10;    /* on a scale from 1 to 10 be very silent */
969*8f5875f3SDavid du Colombier 
970*8f5875f3SDavid du Colombier 				T_ELIF ("verbose")
971*8f5875f3SDavid du Colombier 				silent = 0;    /* print a lot on screen, the default */
972*8f5875f3SDavid du Colombier 
973*8f5875f3SDavid du Colombier 				T_ELIF2 ("version", "license")
974*8f5875f3SDavid du Colombier 				print_license(gfp, stdout, ProgramName);
975*8f5875f3SDavid du Colombier 				return - 2;
976*8f5875f3SDavid du Colombier 
977*8f5875f3SDavid du Colombier 				T_ELIF2 ("help", "usage")
978*8f5875f3SDavid du Colombier 				short_help(gfp, stdout, ProgramName);
979*8f5875f3SDavid du Colombier 				return - 2;
980*8f5875f3SDavid du Colombier 
981*8f5875f3SDavid du Colombier 				T_ELIF ("longhelp")
982*8f5875f3SDavid du Colombier 				long_help(gfp, stdout, ProgramName, 0 /* lessmode=NO */);
983*8f5875f3SDavid du Colombier 				return - 2;
984*8f5875f3SDavid du Colombier 
985*8f5875f3SDavid du Colombier 				T_ELIF ("?")
986*8f5875f3SDavid du Colombier 				long_help(gfp, stdout, ProgramName, 1 /* lessmode=YES */);
987*8f5875f3SDavid du Colombier 				return - 2;
988*8f5875f3SDavid du Colombier 
989*8f5875f3SDavid du Colombier 				T_ELIF ("preset")
990*8f5875f3SDavid du Colombier 				argUsed = 1;
991*8f5875f3SDavid du Colombier 				if (presets_setup(gfp, nextArg, ProgramName ) < 0)
992*8f5875f3SDavid du Colombier 					return -1;
993*8f5875f3SDavid du Colombier 
994*8f5875f3SDavid du Colombier 				T_ELIF ("disptime")
995*8f5875f3SDavid du Colombier 				argUsed = 1;
996*8f5875f3SDavid du Colombier 				update_interval = atof (nextArg);
997*8f5875f3SDavid du Colombier 
998*8f5875f3SDavid du Colombier 				T_ELSE
999*8f5875f3SDavid du Colombier 					fprintf(stderr, "%s: unrec option --%s\n", ProgramName, token);
1000*8f5875f3SDavid du Colombier 
1001*8f5875f3SDavid du Colombier 				T_END
1002*8f5875f3SDavid du Colombier 					i += argUsed;
1003*8f5875f3SDavid du Colombier 			} else {
1004*8f5875f3SDavid du Colombier 				while ((c = *token++) != '\0' ) {
1005*8f5875f3SDavid du Colombier 					arg = *token ? token : nextArg;
1006*8f5875f3SDavid du Colombier 					switch (c) {
1007*8f5875f3SDavid du Colombier 					case 'm':
1008*8f5875f3SDavid du Colombier 						argUsed = 1;
1009*8f5875f3SDavid du Colombier 
1010*8f5875f3SDavid du Colombier 						switch (*arg ) {
1011*8f5875f3SDavid du Colombier 						case 's':
1012*8f5875f3SDavid du Colombier 							(void) lame_set_mode(gfp, STEREO);
1013*8f5875f3SDavid du Colombier 							break;
1014*8f5875f3SDavid du Colombier 						case 'd':
1015*8f5875f3SDavid du Colombier 							(void) lame_set_mode(gfp, DUAL_CHANNEL);
1016*8f5875f3SDavid du Colombier 							fprintf(stderr,
1017*8f5875f3SDavid du Colombier 								"%s: dual channel is not supported yet, the result (perhaps stereo)\n"
1018*8f5875f3SDavid du Colombier 								"  may not be what you expect\n",
1019*8f5875f3SDavid du Colombier 								ProgramName);
1020*8f5875f3SDavid du Colombier 							break;
1021*8f5875f3SDavid du Colombier 						case 'f':
1022*8f5875f3SDavid du Colombier 							gfp->force_ms = 1;
1023*8f5875f3SDavid du Colombier 							/* FALLTHROUGH */
1024*8f5875f3SDavid du Colombier 						case 'j':
1025*8f5875f3SDavid du Colombier 							(void) lame_set_mode(gfp, JOINT_STEREO);
1026*8f5875f3SDavid du Colombier 							break;
1027*8f5875f3SDavid du Colombier 						case 'm':
1028*8f5875f3SDavid du Colombier 							(void) lame_set_mode(gfp, MONO);
1029*8f5875f3SDavid du Colombier 							break;
1030*8f5875f3SDavid du Colombier 						case 'a':
1031*8f5875f3SDavid du Colombier 							(void) lame_set_mode_automs(gfp, 1);
1032*8f5875f3SDavid du Colombier 							/* lame picks mode & uses variable MS threshold */
1033*8f5875f3SDavid du Colombier 							break;
1034*8f5875f3SDavid du Colombier 						default :
1035*8f5875f3SDavid du Colombier 							fprintf(stderr, "%s: -m mode must be s/d/j/f/m not %s\n", ProgramName, arg);
1036*8f5875f3SDavid du Colombier 							err = 1;
1037*8f5875f3SDavid du Colombier 							break;
1038*8f5875f3SDavid du Colombier 						}
1039*8f5875f3SDavid du Colombier 						break;
1040*8f5875f3SDavid du Colombier 
1041*8f5875f3SDavid du Colombier 					case 'V':
1042*8f5875f3SDavid du Colombier 						argUsed = 1;
1043*8f5875f3SDavid du Colombier 						/* to change VBR default look in lame.h */
1044*8f5875f3SDavid du Colombier 						if (gfp->VBR == vbr_off)
1045*8f5875f3SDavid du Colombier 							gfp->VBR = vbr_default;
1046*8f5875f3SDavid du Colombier 						gfp->VBR_q = atoi(arg);
1047*8f5875f3SDavid du Colombier 						if (gfp->VBR_q < 0)
1048*8f5875f3SDavid du Colombier 							gfp->VBR_q = 0;
1049*8f5875f3SDavid du Colombier 						if (gfp->VBR_q > 9)
1050*8f5875f3SDavid du Colombier 							gfp->VBR_q = 9;
1051*8f5875f3SDavid du Colombier 						break;
1052*8f5875f3SDavid du Colombier 					case 'v':
1053*8f5875f3SDavid du Colombier 						/* to change VBR default look in lame.h */
1054*8f5875f3SDavid du Colombier 						if (gfp->VBR == vbr_off)
1055*8f5875f3SDavid du Colombier 							gfp->VBR = vbr_default;
1056*8f5875f3SDavid du Colombier 						break;
1057*8f5875f3SDavid du Colombier 
1058*8f5875f3SDavid du Colombier 					case 'q':
1059*8f5875f3SDavid du Colombier 						argUsed = 1;
1060*8f5875f3SDavid du Colombier 						 {
1061*8f5875f3SDavid du Colombier 							int tmp_quality = atoi(arg);
1062*8f5875f3SDavid du Colombier 
1063*8f5875f3SDavid du Colombier 							/* XXX should we move this into lame_set_quality()? */
1064*8f5875f3SDavid du Colombier 							if (tmp_quality < 0)
1065*8f5875f3SDavid du Colombier 								tmp_quality = 0;
1066*8f5875f3SDavid du Colombier 							if (tmp_quality > 9)
1067*8f5875f3SDavid du Colombier 								tmp_quality = 9;
1068*8f5875f3SDavid du Colombier 
1069*8f5875f3SDavid du Colombier 							(void) lame_set_quality(gfp, tmp_quality);
1070*8f5875f3SDavid du Colombier 						}
1071*8f5875f3SDavid du Colombier 						break;
1072*8f5875f3SDavid du Colombier 					case 'f':
1073*8f5875f3SDavid du Colombier 						(void) lame_set_quality(gfp, 7);
1074*8f5875f3SDavid du Colombier 						break;
1075*8f5875f3SDavid du Colombier 					case 'h':
1076*8f5875f3SDavid du Colombier 						(void) lame_set_quality(gfp, 2);
1077*8f5875f3SDavid du Colombier 						break;
1078*8f5875f3SDavid du Colombier 
1079*8f5875f3SDavid du Colombier 					case 's':
1080*8f5875f3SDavid du Colombier 						argUsed = 1;
1081*8f5875f3SDavid du Colombier 						val = atof(arg);
1082*8f5875f3SDavid du Colombier 						(void) lame_set_in_samplerate(gfp,
1083*8f5875f3SDavid du Colombier 							val *(val <= 192 ? 1.e3 : 1.e0 ) + 0.5);
1084*8f5875f3SDavid du Colombier 						break;
1085*8f5875f3SDavid du Colombier 					case 'b':
1086*8f5875f3SDavid du Colombier 						argUsed = 1;
1087*8f5875f3SDavid du Colombier 						gfp->brate = atoi(arg);
1088*8f5875f3SDavid du Colombier 						gfp->VBR_min_bitrate_kbps = gfp->brate;
1089*8f5875f3SDavid du Colombier 						break;
1090*8f5875f3SDavid du Colombier 					case 'B':
1091*8f5875f3SDavid du Colombier 						argUsed = 1;
1092*8f5875f3SDavid du Colombier 						gfp->VBR_max_bitrate_kbps = atoi(arg);
1093*8f5875f3SDavid du Colombier 						break;
1094*8f5875f3SDavid du Colombier 					case 'F':
1095*8f5875f3SDavid du Colombier 						gfp->VBR_hard_min = 1;
1096*8f5875f3SDavid du Colombier 						break;
1097*8f5875f3SDavid du Colombier 					case 't':  /* dont write VBR tag */
1098*8f5875f3SDavid du Colombier 						(void) lame_set_bWriteVbrTag(gfp, 0);
1099*8f5875f3SDavid du Colombier 						(void) lame_set_disable_waveheader(gfp, 1);
1100*8f5875f3SDavid du Colombier 						break;
1101*8f5875f3SDavid du Colombier 					case 'r':  /* force raw pcm input file */
1102*8f5875f3SDavid du Colombier #if defined(LIBSNDFILE)
1103*8f5875f3SDavid du Colombier 						fprintf(stderr, "WARNING: libsndfile may ignore -r and perform fseek's on the input.\n"
1104*8f5875f3SDavid du Colombier 							"Compile without libsndfile if this is a problem.\n");
1105*8f5875f3SDavid du Colombier #endif
1106*8f5875f3SDavid du Colombier 						input_format = sf_raw;
1107*8f5875f3SDavid du Colombier 						break;
1108*8f5875f3SDavid du Colombier 					case 'x':  /* force byte swapping */
1109*8f5875f3SDavid du Colombier 						swapbytes = 1;
1110*8f5875f3SDavid du Colombier 						break;
1111*8f5875f3SDavid du Colombier 					case 'p': /* (jo) error_protection: add crc16 information to stream */
1112*8f5875f3SDavid du Colombier 						gfp->error_protection = 1;
1113*8f5875f3SDavid du Colombier 						break;
1114*8f5875f3SDavid du Colombier 					case 'a': /* autoconvert input file from stereo to mono - for mono mp3 encoding */
1115*8f5875f3SDavid du Colombier 						autoconvert = 1;
1116*8f5875f3SDavid du Colombier 						(void) lame_set_mode(gfp, MONO);
1117*8f5875f3SDavid du Colombier 						break;
1118*8f5875f3SDavid du Colombier 					case 'k':
1119*8f5875f3SDavid du Colombier 						gfp->lowpassfreq = -1;
1120*8f5875f3SDavid du Colombier 						gfp->highpassfreq = -1;
1121*8f5875f3SDavid du Colombier 						break;
1122*8f5875f3SDavid du Colombier 					case 'd':
1123*8f5875f3SDavid du Colombier 						gfp->allow_diff_short = 1;
1124*8f5875f3SDavid du Colombier 						break;
1125*8f5875f3SDavid du Colombier 					case 'S':
1126*8f5875f3SDavid du Colombier 						silent = 1;
1127*8f5875f3SDavid du Colombier 						break;
1128*8f5875f3SDavid du Colombier 					case 'X':
1129*8f5875f3SDavid du Colombier 						argUsed = 1;
1130*8f5875f3SDavid du Colombier 						gfp->experimentalX = atoi(arg);
1131*8f5875f3SDavid du Colombier 						break;
1132*8f5875f3SDavid du Colombier 					case 'Y':
1133*8f5875f3SDavid du Colombier 						gfp->experimentalY = 1;
1134*8f5875f3SDavid du Colombier 						break;
1135*8f5875f3SDavid du Colombier 					case 'Z':
1136*8f5875f3SDavid du Colombier 						gfp->experimentalZ = 1;
1137*8f5875f3SDavid du Colombier 						break;
1138*8f5875f3SDavid du Colombier #if defined(HAVE_GTK)
1139*8f5875f3SDavid du Colombier 					case 'g': /* turn on gtk analysis */
1140*8f5875f3SDavid du Colombier 						(void) lame_set_analysis(gfp, 1);
1141*8f5875f3SDavid du Colombier 						break;
1142*8f5875f3SDavid du Colombier #endif
1143*8f5875f3SDavid du Colombier 					case 'e':
1144*8f5875f3SDavid du Colombier 						argUsed = 1;
1145*8f5875f3SDavid du Colombier 
1146*8f5875f3SDavid du Colombier 						switch (*arg) {
1147*8f5875f3SDavid du Colombier 						case 'n':
1148*8f5875f3SDavid du Colombier 							gfp ->emphasis = 0;
1149*8f5875f3SDavid du Colombier 							break;
1150*8f5875f3SDavid du Colombier 						case '5':
1151*8f5875f3SDavid du Colombier 							gfp ->emphasis = 1;
1152*8f5875f3SDavid du Colombier 							break;
1153*8f5875f3SDavid du Colombier 						case 'c':
1154*8f5875f3SDavid du Colombier 							gfp ->emphasis = 3;
1155*8f5875f3SDavid du Colombier 							break;
1156*8f5875f3SDavid du Colombier 						default :
1157*8f5875f3SDavid du Colombier 							fprintf(stderr, "%s: -e emp must be n/5/c not %s\n", ProgramName, arg);
1158*8f5875f3SDavid du Colombier 							err = 1;
1159*8f5875f3SDavid du Colombier 							break;
1160*8f5875f3SDavid du Colombier 						}
1161*8f5875f3SDavid du Colombier 						break;
1162*8f5875f3SDavid du Colombier 					case 'c':
1163*8f5875f3SDavid du Colombier 						gfp->copyright = 1;
1164*8f5875f3SDavid du Colombier 						break;
1165*8f5875f3SDavid du Colombier 					case 'o':
1166*8f5875f3SDavid du Colombier 						gfp->original  = 0;
1167*8f5875f3SDavid du Colombier 						break;
1168*8f5875f3SDavid du Colombier 
1169*8f5875f3SDavid du Colombier 					case '?':
1170*8f5875f3SDavid du Colombier 						long_help(gfp, stderr, ProgramName, 0 /* LESSMODE=NO */);
1171*8f5875f3SDavid du Colombier 						return -1;
1172*8f5875f3SDavid du Colombier 
1173*8f5875f3SDavid du Colombier 					default:
1174*8f5875f3SDavid du Colombier 						fprintf(stderr, "%s: unrec option %c\n", ProgramName, c);
1175*8f5875f3SDavid du Colombier 						err = 1;
1176*8f5875f3SDavid du Colombier 						break;
1177*8f5875f3SDavid du Colombier 					}
1178*8f5875f3SDavid du Colombier 					if (argUsed) {
1179*8f5875f3SDavid du Colombier 						if (arg == token)
1180*8f5875f3SDavid du Colombier 							token = ""; /* no more from token */
1181*8f5875f3SDavid du Colombier 						else
1182*8f5875f3SDavid du Colombier 							++i; /* skip arg we used */
1183*8f5875f3SDavid du Colombier 						arg = "";
1184*8f5875f3SDavid du Colombier 						argUsed = 0;
1185*8f5875f3SDavid du Colombier 					}
1186*8f5875f3SDavid du Colombier 				}
1187*8f5875f3SDavid du Colombier 			}
1188*8f5875f3SDavid du Colombier 		} else {
1189*8f5875f3SDavid du Colombier 			fprintf(stderr, "%s: excess arg %s\n", ProgramName, argv[i]);
1190*8f5875f3SDavid du Colombier 			err = 1;
1191*8f5875f3SDavid du Colombier 		}
1192*8f5875f3SDavid du Colombier 	}
1193*8f5875f3SDavid du Colombier 
1194*8f5875f3SDavid du Colombier 	if (err) {
1195*8f5875f3SDavid du Colombier 		usage(gfp, stderr, ProgramName);
1196*8f5875f3SDavid du Colombier 		return -1;
1197*8f5875f3SDavid du Colombier 	}
1198*8f5875f3SDavid du Colombier 
1199*8f5875f3SDavid du Colombier //	if (inPath[0] == '-')
1200*8f5875f3SDavid du Colombier 	silent = 1;		/* turn off status - it's broken for stdin */
1201*8f5875f3SDavid du Colombier 
1202*8f5875f3SDavid du Colombier 	/* some file options not allowed with stdout */
1203*8f5875f3SDavid du Colombier //	if (outPath[0] == '-')
1204*8f5875f3SDavid du Colombier 	(void) lame_set_bWriteVbrTag(gfp, 0); /* turn off VBR tag */
1205*8f5875f3SDavid du Colombier 
1206*8f5875f3SDavid du Colombier #if !(defined HAVE_MPGLIB || defined AMIGA_MPEGA)
1207*8f5875f3SDavid du Colombier 	if (input_format == sf_mp1 ||
1208*8f5875f3SDavid du Colombier 		input_format == sf_mp2 ||
1209*8f5875f3SDavid du Colombier 		input_format == sf_mp3) {
1210*8f5875f3SDavid du Colombier 		fprintf(stderr, "Error: libmp3lame not compiled with mpg123 *decoding* support \n");
1211*8f5875f3SDavid du Colombier 		return -1;
1212*8f5875f3SDavid du Colombier 	}
1213*8f5875f3SDavid du Colombier #endif
1214*8f5875f3SDavid du Colombier 
1215*8f5875f3SDavid du Colombier #if !(defined HAVE_VORBIS)
1216*8f5875f3SDavid du Colombier 	if (input_format == sf_ogg) {
1217*8f5875f3SDavid du Colombier 		fprintf(stderr, "Error: mp3enc not compiled with Vorbis support\n");
1218*8f5875f3SDavid du Colombier 		return -1;
1219*8f5875f3SDavid du Colombier 	}
1220*8f5875f3SDavid du Colombier #endif
1221*8f5875f3SDavid du Colombier 	/* default guess for number of channels */
1222*8f5875f3SDavid du Colombier 	if (autoconvert)
1223*8f5875f3SDavid du Colombier 		(void) lame_set_num_channels(gfp, 2);
1224*8f5875f3SDavid du Colombier 	else if (MONO == lame_get_mode(gfp ))
1225*8f5875f3SDavid du Colombier 		(void) lame_set_num_channels(gfp, 1);
1226*8f5875f3SDavid du Colombier 	else
1227*8f5875f3SDavid du Colombier 		(void) lame_set_num_channels(gfp, 2);
1228*8f5875f3SDavid du Colombier 
1229*8f5875f3SDavid du Colombier 	if (gfp->free_format) {
1230*8f5875f3SDavid du Colombier 		if (gfp ->brate < 8  ||  gfp ->brate > 640) {
1231*8f5875f3SDavid du Colombier 			fprintf(stderr, "For free format, specify a bitrate between 8 and 640 kbps\n");
1232*8f5875f3SDavid du Colombier 			return -1;
1233*8f5875f3SDavid du Colombier 		}
1234*8f5875f3SDavid du Colombier 	}
1235*8f5875f3SDavid du Colombier 	return 0;
1236*8f5875f3SDavid du Colombier }
1237