xref: /plan9/sys/src/games/mp3enc/main.c (revision 027288c8a8763d34db13dc89d8bcd6514dbc2163)
1 /* mp3enc - encode audio files in MP3 format */
2 
3 /*
4  *	Command line frontend program
5  *
6  *	Copyright (c) 1999 Mark Taylor
7  *                    2000 Takehiro TOMIANGA
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24 
25 /* $Id: main.c,v 1.46 2001/03/11 11:24:25 aleidinger Exp $ */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <assert.h>
33 #include <memory.h>
34 #ifdef HAVE_CONFIG_H
35 # include <config.h>
36 #endif
37 
38 /*
39  main.c is example code for how to use libmp3lame.a.  To use this library,
40  you only need the library and lame.h.  All other .h files are private
41  to the library.
42 */
43 #include "lame.h"
44 
45 #include "brhist.h"
46 #include "parse.h"
47 #include "main.h"
48 #include "get_audio.h"
49 #include "timestatus.h"
50 
51 /*
52 *
53 * main
54 *
55 * PURPOSE:  MPEG-1,2 Layer III encoder with GPSYCHO
56 * psychoacoustic model.
57 *
58 */
59 
60 int
parse_args_from_string(lame_global_flags * const gfp,const char * p)61 parse_args_from_string(lame_global_flags *const gfp, const char *p)
62 {
63 	/* Quick & very Dirty */
64 	int c = 0, ret;
65 	char *f, *q, *r[128];
66 
67 	if (p == NULL || *p == '\0')
68 		return 0;
69 
70 	f = q = malloc(strlen(p) + 1);
71 	strcpy (q, p);
72 
73 	r[c++] = "lhama";
74 	for (;;) {
75 		r[c++] = q;
76 		while (*q != ' ' && *q != '\0')
77 			q++;
78 		if (*q == '\0')
79 			break;
80 		*q++ = '\0';
81 	}
82 	r[c] = NULL;
83 
84 	ret = parse_args(gfp, c, r);
85 	free(f);
86 	return ret;
87 }
88 
89 int
main(int argc,char ** argv)90 main(int argc, char **argv)
91 {
92 	int i, iread, imp3, ret;
93 	short Buffer[2][1152];
94 	unsigned char mp3buffer[LAME_MAXMP3BUFFER];
95 	FILE *outf;
96 	lame_global_flags *gf;
97 	static char inPath[]  = "-";
98 	static char outPath[] = "-";
99 	static const char *mode_names[2][4] = {
100 		{ "stereo", "j-stereo", "dual-ch", "single-ch" },
101 		{ "stereo", "force-ms", "dual-ch", "single-ch" }
102 	};
103 
104 	/* initialize libmp3lame */
105 	input_format = sf_unknown;
106 	if (NULL == (gf = lame_init()) ) {
107 		fprintf(stderr, "mp3enc: fatal error during initialization\n");
108 		return 1;
109 	}
110 	/*
111 	 * parse the command line arguments, setting various flags in the
112 	 * struct 'gf'.  If you want to parse your own arguments,
113 	 * or call libmp3lame from a program which uses a GUI to set arguments,
114 	 * skip this call and set the values of interest in the gf struct.
115 	 * (see the file API & lame.h for documentation about these parameters)
116 	 */
117 	parse_args_from_string(gf, getenv("LAMEOPT"));
118 	ret = parse_args(gf, argc, argv);
119 	if (ret < 0)
120 		return ret == -2? 0: 1;
121 	if (update_interval < 0.)
122 		update_interval = 2.;
123 
124 	/*
125 	 * open the wav/aiff/raw pcm or mp3 input file.  This call will
126 	 * open the file, try to parse the headers and
127 	 * set gf.samplerate, gf.num_channels, gf.num_samples.
128 	 * if you want to do your own file input, skip this call and set
129 	 * samplerate, num_channels and num_samples yourself.
130 	 */
131 	init_infile(gf, inPath);
132 	if ((outf = init_outfile(outPath, lame_get_decode_only(gf))) == NULL) {
133 		fprintf(stderr, "Can't init outfile '%s'\n", outPath);
134 		return -42;
135 	}
136 
137 	/*
138 	 * Now that all the options are set, lame needs to analyze them and
139 	 * set some more internal options and check for problems
140 	 */
141 	i = lame_init_params(gf);
142 	if (i < 0) {
143 		if (i == -1)
144 			display_bitrates(stderr);
145 		fprintf(stderr, "fatal error during initialization\n");
146 		return 1;
147 	}
148 
149 	if (silent || gf->VBR == vbr_off)
150 		brhist = 0;			/* turn off VBR histogram */
151 
152 #ifdef BRHIST
153 	if (brhist) {
154 		if (brhist_init(gf, gf->VBR_min_bitrate_kbps,
155 		    gf->VBR_max_bitrate_kbps))
156 			/* fail to initialize */
157 			brhist = 0;
158 	} else
159 		brhist_init(gf, 128, 128);	/* Dirty hack */
160 #endif
161 
162 
163 #ifdef HAVE_VORBIS
164 	if (lame_get_ogg( gf ) ) {
165 		lame_encode_ogg_init(gf);
166 		gf->VBR = vbr_off;	/* ignore lame's various VBR modes */
167 	}
168 #endif
169 	if (0 == lame_get_decode_only( gf ) && silent < 10 ) {
170 		if (0)
171 			fprintf(stderr, "Encoding as %g kHz ",
172 				1.e-3 * lame_get_out_samplerate( gf ) );
173 
174 		if (lame_get_ogg(gf)) {
175 			if (0)
176 				fprintf(stderr, "VBR Ogg Vorbis\n" );
177 		} else {
178 			const char *appendix = "";
179 
180 			switch (gf->VBR ) {
181 			case vbr_mt:
182 			case vbr_rh:
183 			case vbr_mtrh:
184 				appendix = "ca. ";
185 				if (0)
186 					fprintf(stderr, "VBR(q=%i)", gf->VBR_q );
187 				break;
188 			case vbr_abr:
189 				if (0)
190 					fprintf(stderr, "average %d kbps",
191 						gf->VBR_mean_bitrate_kbps);
192 				break;
193 			default:
194 				if (0)
195 					fprintf(stderr, "%3d Kb/s", gf->brate);
196 				break;
197 			}
198 			if (0)
199 				fprintf(stderr, " %s MPEG-%u%s Layer III (%s%gx) qval=%i\n",
200 					mode_names[gf->force_ms][gf->mode],
201 					2 - gf->version,
202 					lame_get_out_samplerate(gf) < 16000?
203 					".5": "", appendix,
204 					0.1 * (int)(10.*gf->compression_ratio + 0.5),
205 					lame_get_quality(gf));
206 		}
207 		fflush(stderr);
208 	}
209 
210 	if (lame_get_decode_only(gf))
211 		/* decode an mp3 file to a .wav */
212 		if (mp3_delay_set)
213 			lame_decoder(gf, outf, mp3_delay, inPath, outPath);
214 		else
215 			lame_decoder(gf, outf, gf->encoder_delay, inPath, outPath);
216 	else {
217 		/* encode until we hit eof */
218 		do {
219 			/* read in 'iread' samples */
220 			iread = get_audio(gf, Buffer);
221 
222 			/* status display  */
223 			if (!silent)
224 				if (update_interval > 0)
225 					timestatus_klemm(gf);
226 				else {
227 					if (0 == gf->frameNum % 50) {
228 #ifdef BRHIST
229 						brhist_jump_back();
230 #endif
231 						timestatus(lame_get_out_samplerate(gf),
232 							gf->frameNum,
233 							gf->totalframes,
234 							gf->framesize );
235 #ifdef BRHIST
236 						if (brhist)
237 							brhist_disp(gf);
238 #endif
239 					}
240 				}
241 
242 			/* encode */
243 			imp3 = lame_encode_buffer(gf, Buffer[0], Buffer[1], iread,
244 				mp3buffer, sizeof(mp3buffer));
245 
246 			/* was our output buffer big enough? */
247 			if (imp3 < 0) {
248 				if (imp3 == -1)
249 					fprintf(stderr, "mp3 buffer is not big enough... \n");
250 				else
251 					fprintf(stderr, "mp3 internal error:  error code=%i\n", imp3);
252 				return 1;
253 			}
254 
255 			if (fwrite(mp3buffer, 1, imp3, outf) != imp3) {
256 				fprintf(stderr, "Error writing mp3 output \n");
257 				return 1;
258 			}
259 		} while (iread);
260 		/* may return one more mp3 frame */
261 		imp3 = lame_encode_flush(gf, mp3buffer, sizeof(mp3buffer));
262 		if (imp3 < 0) {
263 			if (imp3 == -1)
264 				fprintf(stderr, "mp3 buffer is not big enough... \n");
265 			else
266 				fprintf(stderr, "mp3 internal error:  error code=%i\n", imp3);
267 			return 1;
268 
269 		}
270 		if (!silent) {
271 #ifdef BRHIST
272 			brhist_jump_back();
273 #endif
274 			timestatus(lame_get_out_samplerate(gf),
275 				gf->frameNum,
276 				gf->totalframes,
277 				gf->framesize);
278 #ifdef BRHIST
279 			if (brhist)
280 				brhist_disp(gf);
281 			brhist_disp_total(gf);
282 #endif
283 			timestatus_finish();
284 		}
285 
286 		fwrite(mp3buffer, 1, imp3, outf);
287 		lame_mp3_tags_fid(gf, outf);	/* add VBR tags to mp3 file */
288 		lame_close(gf);
289 		fclose(outf);
290 	}
291 	close_infile();
292 	exit(0);
293 	return 0;
294 }
295