1 /*
2  *      Command line frontend program
3  *
4  *      Copyright (c) 1999 Mark Taylor
5  *                    2000 Takehiro TOMINAGA
6  *                    2010-2017 Robert Hegemann
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23 
24 /* $Id$ */
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #include <assert.h>
31 #include <stdio.h>
32 
33 #ifdef STDC_HEADERS
34 # include <stdlib.h>
35 # include <string.h>
36 #else
37 # ifndef HAVE_STRCHR
38 #  define strchr index
39 #  define strrchr rindex
40 # endif
41 char   *strchr(), *strrchr();
42 # ifndef HAVE_MEMCPY
43 #  define memcpy(d, s, n) bcopy ((s), (d), (n))
44 #  define memmove(d, s, n) bcopy ((s), (d), (n))
45 # endif
46 #endif
47 
48 #ifdef HAVE_FCNTL_H
49 # include <fcntl.h>
50 #endif
51 
52 #ifdef __sun__
53 /* woraround for SunOS 4.x, it has SEEK_* defined here */
54 #include <unistd.h>
55 #endif
56 
57 #if defined(_WIN32)
58 # include <windows.h>
59 #endif
60 
61 
62 /*
63  main.c is example code for how to use libmp3lame.a.  To use this library,
64  you only need the library and lame.h.  All other .h files are private
65  to the library.
66 */
67 #include "lame.h"
68 
69 #include "console.h"
70 #include "parse.h"
71 #include "main.h"
72 #include "get_audio.h"
73 #include "timestatus.h"
74 
75 /* PLL 14/04/2000 */
76 #if macintosh
77 #include <console.h>
78 #endif
79 
80 #ifdef WITH_DMALLOC
81 #include <dmalloc.h>
82 #endif
83 
84 
85 
86 
87 /************************************************************************
88 *
89 * main
90 *
91 * PURPOSE:  MPEG-1,2 Layer III encoder with GPSYCHO
92 * psychoacoustic model.
93 *
94 ************************************************************************/
95 
96 
97 static FILE *
init_files(lame_global_flags * gf, char const *inPath, char const *outPath)98 init_files(lame_global_flags * gf, char const *inPath, char const *outPath)
99 {
100     FILE   *outf;
101     /* Mostly it is not useful to use the same input and output name.
102        This test is very easy and buggy and don't recognize different names
103        assigning the same file
104      */
105     if (0 != strcmp("-", outPath) && 0 == strcmp(inPath, outPath)) {
106         error_printf("Input file and Output file are the same. Abort.\n");
107         return NULL;
108     }
109 
110     /* open the wav/aiff/raw pcm or mp3 input file.  This call will
111      * open the file, try to parse the headers and
112      * set gf.samplerate, gf.num_channels, gf.num_samples.
113      * if you want to do your own file input, skip this call and set
114      * samplerate, num_channels and num_samples yourself.
115      */
116     if (init_infile(gf, inPath) < 0) {
117         error_printf("Can't init infile '%s'\n", inPath);
118         return NULL;
119     }
120     if ((outf = init_outfile(outPath, lame_get_decode_only(gf))) == NULL) {
121         error_printf("Can't init outfile '%s'\n", outPath);
122         return NULL;
123     }
124 
125     return outf;
126 }
127 
128 
129 static void
printInputFormat(lame_t gfp)130 printInputFormat(lame_t gfp)
131 {
132     int const v_main = 2 - lame_get_version(gfp);
133     char const *v_ex = lame_get_out_samplerate(gfp) < 16000 ? ".5" : "";
134     switch (global_reader.input_format) {
135     case sf_mp123:     /* FIXME: !!! */
136         break;
137     case sf_mp3:
138         console_printf("MPEG-%u%s Layer %s", v_main, v_ex, "III");
139         break;
140     case sf_mp2:
141         console_printf("MPEG-%u%s Layer %s", v_main, v_ex, "II");
142         break;
143     case sf_mp1:
144         console_printf("MPEG-%u%s Layer %s", v_main, v_ex, "I");
145         break;
146     case sf_raw:
147         console_printf("raw PCM data");
148         break;
149     case sf_wave:
150         console_printf("Microsoft WAVE");
151         break;
152     case sf_aiff:
153         console_printf("SGI/Apple AIFF");
154         break;
155     default:
156         console_printf("unknown");
157         break;
158     }
159 }
160 
161 /* the simple lame decoder */
162 /* After calling lame_init(), lame_init_params() and
163  * init_infile(), call this routine to read the input MP3 file
164  * and output .wav data to the specified file pointer*/
165 /* lame_decoder will ignore the first 528 samples, since these samples
166  * represent the mpglib delay (and are all 0).  skip = number of additional
167  * samples to skip, to (for example) compensate for the encoder delay */
168 
169 static int
lame_decoder_loop(lame_t gfp, FILE * outf, char *inPath, char *outPath)170 lame_decoder_loop(lame_t gfp, FILE * outf, char *inPath, char *outPath)
171 {
172     short int Buffer[2][1152];
173     int     i, iread;
174     double  wavsize;
175     int     tmp_num_channels = lame_get_num_channels(gfp);
176     int     skip_start = samples_to_skip_at_start();
177     int     skip_end = samples_to_skip_at_end();
178     DecoderProgress dp = 0;
179 
180     if (!(tmp_num_channels >= 1 && tmp_num_channels <= 2)) {
181         error_printf("Internal error.  Aborting.");
182         return -1;
183     }
184 
185     if (global_ui_config.silent < 9) {
186         console_printf("\rinput:  %s%s(%g kHz, %i channel%s, ",
187                        strcmp(inPath, "-") ? inPath : "<stdin>",
188                        strlen(inPath) > 26 ? "\n\t" : "  ",
189                        lame_get_in_samplerate(gfp) / 1.e3,
190                        tmp_num_channels, tmp_num_channels != 1 ? "s" : "");
191 
192         printInputFormat(gfp);
193 
194         console_printf(")\noutput: %s%s(16 bit, Microsoft WAVE)\n",
195                        strcmp(outPath, "-") ? outPath : "<stdout>",
196                        strlen(outPath) > 45 ? "\n\t" : "  ");
197 
198         if (skip_start > 0)
199             console_printf("skipping initial %i samples (encoder+decoder delay)\n", skip_start);
200         if (skip_end > 0)
201             console_printf("skipping final %i samples (encoder padding-decoder delay)\n", skip_end);
202 
203         switch (global_reader.input_format) {
204         case sf_mp3:
205         case sf_mp2:
206         case sf_mp1:
207             dp = decoder_progress_init(lame_get_num_samples(gfp),
208                                        global_decoder.mp3input_data.framesize);
209             break;
210         case sf_raw:
211         case sf_wave:
212         case sf_aiff:
213         default:
214             dp = decoder_progress_init(lame_get_num_samples(gfp),
215                                        lame_get_in_samplerate(gfp) < 32000 ? 576 : 1152);
216             break;
217         }
218     }
219 
220     if (0 == global_decoder.disable_wav_header)
221         WriteWaveHeader(outf, 0x7FFFFFFF, lame_get_in_samplerate(gfp), tmp_num_channels, 16);
222     /* unknown size, so write maximum 32 bit signed value */
223 
224     wavsize = 0;
225     do {
226         iread = get_audio16(gfp, Buffer); /* read in 'iread' samples */
227         if (iread >= 0) {
228             wavsize += iread;
229             if (dp != 0) {
230                 decoder_progress(dp, &global_decoder.mp3input_data, iread);
231             }
232             put_audio16(outf, Buffer, iread, tmp_num_channels);
233         }
234     } while (iread > 0);
235 
236     i = (16 / 8) * tmp_num_channels;
237     assert(i > 0);
238     if (wavsize <= 0) {
239         if (global_ui_config.silent < 10)
240             error_printf("WAVE file contains 0 PCM samples\n");
241         wavsize = 0;
242     }
243     else if (wavsize > 0xFFFFFFD0 / i) {
244         if (global_ui_config.silent < 10)
245             error_printf("Very huge WAVE file, can't set filesize accordingly\n");
246         wavsize = 0xFFFFFFD0;
247     }
248     else {
249         wavsize *= i;
250     }
251     /* if outf is seekable, rewind and adjust length */
252     if (!global_decoder.disable_wav_header && strcmp("-", outPath)
253         && !fseek(outf, 0l, SEEK_SET))
254         WriteWaveHeader(outf, (int) wavsize, lame_get_in_samplerate(gfp), tmp_num_channels, 16);
255 
256     if (dp != 0)
257         decoder_progress_finish(dp);
258     return 0;
259 }
260 
261 static int
lame_decoder(lame_t gfp, FILE * outf, char *inPath, char *outPath)262 lame_decoder(lame_t gfp, FILE * outf, char *inPath, char *outPath)
263 {
264     int     ret;
265 
266     ret = lame_decoder_loop(gfp, outf, inPath, outPath);
267     fclose(outf);       /* close the output file */
268     close_infile();     /* close the input file */
269     return ret;
270 }
271 
272 
273 static void
print_trailing_info(lame_global_flags * gf)274 print_trailing_info(lame_global_flags * gf)
275 {
276     if (lame_get_findReplayGain(gf)) {
277         int     RadioGain = lame_get_RadioGain(gf);
278         console_printf("ReplayGain: %s%.1fdB\n", RadioGain > 0 ? "+" : "",
279                        ((float) RadioGain) / 10.0);
280         if (RadioGain > 0x1FE || RadioGain < -0x1FE)
281             error_printf
282                 ("WARNING: ReplayGain exceeds the -51dB to +51dB range. Such a result is too\n"
283                  "         high to be stored in the header.\n");
284     }
285 
286     /* if (the user requested printing info about clipping) and (decoding
287        on the fly has actually been performed) */
288     if (global_ui_config.print_clipping_info && lame_get_decode_on_the_fly(gf)) {
289         float   noclipGainChange = (float) lame_get_noclipGainChange(gf) / 10.0f;
290         float   noclipScale = lame_get_noclipScale(gf);
291 
292         if (noclipGainChange > 0.0) { /* clipping occurs */
293             console_printf
294                 ("WARNING: clipping occurs at the current gain. Set your decoder to decrease\n"
295                  "         the  gain  by  at least %.1fdB or encode again ", noclipGainChange);
296 
297             /* advice the user on the scale factor */
298             if (noclipScale > 0) {
299                 console_printf("using  --scale %.2f\n", noclipScale * lame_get_scale(gf));
300                 console_printf("         or less (the value under --scale is approximate).\n");
301             }
302             else {
303                 /* the user specified his own scale factor. We could suggest
304                  * the scale factor of (32767.0/gfp->PeakSample)*(gfp->scale)
305                  * but it's usually very inaccurate. So we'd rather advice him to
306                  * disable scaling first and see our suggestion on the scale factor then. */
307                 console_printf("using --scale <arg>\n"
308                                "         (For   a   suggestion  on  the  optimal  value  of  <arg>  encode\n"
309                                "         with  --scale 1  first)\n");
310             }
311 
312         }
313         else {          /* no clipping */
314             if (noclipGainChange > -0.1)
315                 console_printf
316                     ("\nThe waveform does not clip and is less than 0.1dB away from full scale.\n");
317             else
318                 console_printf
319                     ("\nThe waveform does not clip and is at least %.1fdB away from full scale.\n",
320                      -noclipGainChange);
321         }
322     }
323 
324 }
325 
326 
327 static int
write_xing_frame(lame_global_flags * gf, FILE * outf, size_t offset)328 write_xing_frame(lame_global_flags * gf, FILE * outf, size_t offset)
329 {
330     unsigned char mp3buffer[LAME_MAXMP3BUFFER];
331     size_t  imp3, owrite;
332 
333     imp3 = lame_get_lametag_frame(gf, mp3buffer, sizeof(mp3buffer));
334     if (imp3 == 0) {
335         return 0;       /* nothing to do */
336     }
337     if (global_ui_config.silent <= 0) {
338         console_printf("Writing LAME Tag...");
339     }
340     if (imp3 > sizeof(mp3buffer)) {
341         error_printf
342             ("Error writing LAME-tag frame: buffer too small: buffer size=%d  frame size=%d\n",
343              sizeof(mp3buffer), imp3);
344         return -1;
345     }
346     assert( offset <= LONG_MAX );
347     if (fseek(outf, (long) offset, SEEK_SET) != 0) {
348         error_printf("fatal error: can't update LAME-tag frame!\n");
349         return -1;
350     }
351     owrite = fwrite(mp3buffer, 1, imp3, outf);
352     if (owrite != imp3) {
353         error_printf("Error writing LAME-tag \n");
354         return -1;
355     }
356     if (global_ui_config.silent <= 0) {
357         console_printf("done\n");
358     }
359     assert( imp3 <= INT_MAX );
360     return (int) imp3;
361 }
362 
363 
364 static int
write_id3v1_tag(lame_t gf, FILE * outf)365 write_id3v1_tag(lame_t gf, FILE * outf)
366 {
367     unsigned char mp3buffer[128];
368     size_t  imp3, owrite;
369 
370     imp3 = lame_get_id3v1_tag(gf, mp3buffer, sizeof(mp3buffer));
371     if (imp3 == 0) {
372         return 0;
373     }
374     if (imp3 > sizeof(mp3buffer)) {
375         error_printf("Error writing ID3v1 tag: buffer too small: buffer size=%d  ID3v1 size=%d\n",
376                      sizeof(mp3buffer), imp3);
377         return 0;       /* not critical */
378     }
379     owrite = fwrite(mp3buffer, 1, imp3, outf);
380     if (owrite != imp3) {
381         error_printf("Error writing ID3v1 tag \n");
382         return 1;
383     }
384     return 0;
385 }
386 
387 
388 static int
lame_encoder_loop(lame_global_flags * gf, FILE * outf, int nogap, char *inPath, char *outPath)389 lame_encoder_loop(lame_global_flags * gf, FILE * outf, int nogap, char *inPath, char *outPath)
390 {
391     unsigned char mp3buffer[LAME_MAXMP3BUFFER];
392     int     Buffer[2][1152];
393     int     iread, imp3, owrite, in_limit=0;
394     size_t  id3v2_size;
395 
396     encoder_progress_begin(gf, inPath, outPath);
397 
398     id3v2_size = lame_get_id3v2_tag(gf, 0, 0);
399     if (id3v2_size > 0) {
400         unsigned char *id3v2tag = malloc(id3v2_size);
401         if (id3v2tag != 0) {
402             size_t  n_bytes = lame_get_id3v2_tag(gf, id3v2tag, id3v2_size);
403             size_t  written = fwrite(id3v2tag, 1, n_bytes, outf);
404             free(id3v2tag);
405             if (written != n_bytes) {
406                 encoder_progress_end(gf);
407                 error_printf("Error writing ID3v2 tag \n");
408                 return 1;
409             }
410         }
411     }
412     else {
413         unsigned char* id3v2tag = getOldTag(gf);
414         id3v2_size = sizeOfOldTag(gf);
415         if ( id3v2_size > 0 ) {
416             size_t owrite = fwrite(id3v2tag, 1, id3v2_size, outf);
417             if (owrite != id3v2_size) {
418                 encoder_progress_end(gf);
419                 error_printf("Error writing ID3v2 tag \n");
420                 return 1;
421             }
422         }
423     }
424     if (global_writer.flush_write == 1) {
425         fflush(outf);
426     }
427 
428     /* do not feed more than in_limit PCM samples in one encode call
429        otherwise the mp3buffer is likely too small
430      */
431     in_limit = lame_get_maximum_number_of_samples(gf, sizeof(mp3buffer));
432     if (in_limit < 1)
433         in_limit = 1;
434 
435     /* encode until we hit eof */
436     do {
437         /* read in 'iread' samples */
438         iread = get_audio(gf, Buffer);
439 
440         if (iread >= 0) {
441             const int* buffer_l = Buffer[0];
442             const int* buffer_r = Buffer[1];
443             int     rest = iread;
444             do {
445                 int const chunk = rest < in_limit ? rest : in_limit;
446                 encoder_progress(gf);
447 
448                 /* encode */
449 
450                 imp3 = lame_encode_buffer_int(gf, buffer_l, buffer_r, chunk,
451                                               mp3buffer, sizeof(mp3buffer));
452                 buffer_l += chunk;
453                 buffer_r += chunk;
454                 rest -= chunk;
455 
456                 /* was our output buffer big enough? */
457                 if (imp3 < 0) {
458                     if (imp3 == -1)
459                         error_printf("mp3 buffer is not big enough... \n");
460                     else
461                         error_printf("mp3 internal error:  error code=%i\n", imp3);
462                     return 1;
463                 }
464                 owrite = (int) fwrite(mp3buffer, 1, imp3, outf);
465                 if (owrite != imp3) {
466                     error_printf("Error writing mp3 output \n");
467                     return 1;
468                 }
469             } while (rest > 0);
470         }
471         if (global_writer.flush_write == 1) {
472             fflush(outf);
473         }
474     } while (iread > 0);
475 
476     if (nogap)
477         imp3 = lame_encode_flush_nogap(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */
478     else
479         imp3 = lame_encode_flush(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */
480 
481     if (imp3 < 0) {
482         if (imp3 == -1)
483             error_printf("mp3 buffer is not big enough... \n");
484         else
485             error_printf("mp3 internal error:  error code=%i\n", imp3);
486         return 1;
487 
488     }
489 
490     encoder_progress_end(gf);
491 
492     owrite = (int) fwrite(mp3buffer, 1, imp3, outf);
493     if (owrite != imp3) {
494         error_printf("Error writing mp3 output \n");
495         return 1;
496     }
497     if (global_writer.flush_write == 1) {
498         fflush(outf);
499     }
500     imp3 = write_id3v1_tag(gf, outf);
501     if (global_writer.flush_write == 1) {
502         fflush(outf);
503     }
504     if (imp3) {
505         return 1;
506     }
507     write_xing_frame(gf, outf, id3v2_size);
508     if (global_writer.flush_write == 1) {
509         fflush(outf);
510     }
511     if (global_ui_config.silent <= 0) {
512         print_trailing_info(gf);
513     }
514     return 0;
515 }
516 
517 
518 static int
lame_encoder(lame_global_flags * gf, FILE * outf, int nogap, char *inPath, char *outPath)519 lame_encoder(lame_global_flags * gf, FILE * outf, int nogap, char *inPath, char *outPath)
520 {
521     int     ret;
522 
523     ret = lame_encoder_loop(gf, outf, nogap, inPath, outPath);
524     fclose(outf);       /* close the output file */
525     close_infile();     /* close the input file */
526     return ret;
527 }
528 
529 
530 int
lame_main(lame_t gf, int argc, char **argv)531 lame_main(lame_t gf, int argc, char **argv)
532 {
533     char    inPath[PATH_MAX + 1];
534     char    outPath[PATH_MAX + 1];
535     char    nogapdir[PATH_MAX + 1];
536     /* support for "nogap" encoding of up to 200 .wav files */
537 #define MAX_NOGAP 200
538     int     nogapout = 0;
539     int     max_nogap = MAX_NOGAP;
540     char    nogap_inPath_[MAX_NOGAP][PATH_MAX + 1];
541     char   *nogap_inPath[MAX_NOGAP];
542     char    nogap_outPath_[MAX_NOGAP][PATH_MAX + 1];
543     char   *nogap_outPath[MAX_NOGAP];
544 
545     int     ret;
546     int     i;
547     FILE   *outf = NULL;
548 
549     lame_set_msgf(gf, &frontend_msgf);
550     lame_set_errorf(gf, &frontend_errorf);
551     lame_set_debugf(gf, &frontend_debugf);
552     if (argc <= 1) {
553         usage(stderr, argv[0]); /* no command-line args, print usage, exit  */
554         return 1;
555     }
556 
557     memset(inPath, 0, sizeof(inPath));
558     memset(nogap_inPath_, 0, sizeof(nogap_inPath_));
559     for (i = 0; i < MAX_NOGAP; ++i) {
560         nogap_inPath[i] = &nogap_inPath_[i][0];
561     }
562     memset(nogap_outPath_, 0, sizeof(nogap_outPath_));
563     for (i = 0; i < MAX_NOGAP; ++i) {
564         nogap_outPath[i] = &nogap_outPath_[i][0];
565     }
566 
567     /* parse the command line arguments, setting various flags in the
568      * struct 'gf'.  If you want to parse your own arguments,
569      * or call libmp3lame from a program which uses a GUI to set arguments,
570      * skip this call and set the values of interest in the gf struct.
571      * (see the file API and lame.h for documentation about these parameters)
572      */
573     ret = parse_args(gf, argc, argv, inPath, outPath, nogap_inPath, &max_nogap);
574     if (ret < 0) {
575         return ret == -2 ? 0 : 1;
576     }
577     if (global_ui_config.update_interval < 0.)
578         global_ui_config.update_interval = 2.;
579 
580     if (outPath[0] != '\0' && max_nogap > 0) {
581         strncpy(nogapdir, outPath, PATH_MAX + 1);
582         nogapdir[PATH_MAX] = '\0';
583         nogapout = 1;
584     }
585 
586     /* initialize input file.  This also sets samplerate and as much
587        other data on the input file as available in the headers */
588     if (max_nogap > 0) {
589           /* for nogap encoding of multiple input files, it is not possible to
590            * specify the output file name, only an optional output directory. */
591           for (i = 0; i < max_nogap; ++i) {
592               char const* outdir = nogapout ? nogapdir : "";
593               if (generateOutPath(nogap_inPath[i], outdir, ".mp3", nogap_outPath[i]) != 0) {
594                   error_printf("processing nogap file %d: %s\n", i+1, nogap_inPath[i]);
595                   return -1;
596               }
597           }
598           outf = init_files(gf, nogap_inPath[0], nogap_outPath[0]);
599     }
600     else {
601         outf = init_files(gf, inPath, outPath);
602     }
603     if (outf == NULL) {
604         close_infile();
605         return -1;
606     }
607     /* turn off automatic writing of ID3 tag data into mp3 stream
608      * we have to call it before 'lame_init_params', because that
609      * function would spit out ID3v2 tag data.
610      */
611     lame_set_write_id3tag_automatic(gf, 0);
612 
613     /* Now that all the options are set, lame needs to analyze them and
614      * set some more internal options and check for problems
615      */
616     ret = lame_init_params(gf);
617     if (ret < 0) {
618         if (ret == -1) {
619             display_bitrates(stderr);
620         }
621         error_printf("fatal error during initialization\n");
622         fclose(outf);
623         close_infile();
624         return ret;
625     }
626 
627     if (global_ui_config.silent > 0) {
628         global_ui_config.brhist = 0; /* turn off VBR histogram */
629     }
630 
631     if (lame_get_decode_only(gf)) {
632         /* decode an mp3 file to a .wav */
633         ret = lame_decoder(gf, outf, inPath, outPath);
634     }
635     else if (max_nogap == 0) {
636         /* encode a single input file */
637         ret = lame_encoder(gf, outf, 0, inPath, outPath);
638     }
639     else {
640         /* encode multiple input files using nogap option */
641         for (i = 0; i < max_nogap; ++i) {
642             int     use_flush_nogap = (i != (max_nogap - 1));
643             if (i > 0) {
644                 /* note: if init_files changes anything, like
645                    samplerate, num_channels, etc, we are screwed */
646                 outf = init_files(gf, nogap_inPath[i], nogap_outPath[i]);
647                 if (outf == NULL) {
648                     close_infile();
649                     return -1;
650                 }
651                 /* reinitialize bitstream for next encoding.  this is normally done
652                  * by lame_init_params(), but we cannot call that routine twice */
653                 lame_init_bitstream(gf);
654             }
655             lame_set_nogap_total(gf, max_nogap);
656             lame_set_nogap_currentindex(gf, i);
657             ret = lame_encoder(gf, outf, use_flush_nogap, nogap_inPath[i], nogap_outPath[i]);
658         }
659     }
660     return ret;
661 }
662