xref: /third_party/lame/frontend/lame_main.c (revision 159b3361)
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
41char   *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
97static FILE *
98init_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
129static void
130printInputFormat(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
169static int
170lame_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
261static int
262lame_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
273static void
274print_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
327static int
328write_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
364static int
365write_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
388static int
389lame_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
518static int
519lame_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
530int
531lame_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