Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* mp3enc - encode audio files in MP3 format */

/*
 *      Command line frontend program
 *
 *      Copyright (c) 1999 Mark Taylor
 *                    2000 Takehiro TOMIANGA
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/* $Id: main.c,v 1.46 2001/03/11 11:24:25 aleidinger Exp $ */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <memory.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

/*
 main.c is example code for how to use libmp3lame.a.  To use this library,
 you only need the library and lame.h.  All other .h files are private
 to the library.
*/
#include "lame.h"

#include "brhist.h"
#include "parse.h"
#include "main.h"
#include "get_audio.h"
#include "timestatus.h"

/*
*
* main
*
* PURPOSE:  MPEG-1,2 Layer III encoder with GPSYCHO
* psychoacoustic model.
*
*/

int
parse_args_from_string(lame_global_flags *const gfp, const char *p)
{
        /* Quick & very Dirty */
        int c = 0, ret;
        char *f, *q, *r[128];

        if (p == NULL || *p == '\0')
                return 0;

        f = q = malloc(strlen(p) + 1);
        strcpy (q, p);

        r[c++] = "lhama";
        for (;;) {
                r[c++] = q;
                while (*q != ' ' && *q != '\0')
                        q++;
                if (*q == '\0')
                        break;
                *q++ = '\0';
        }
        r[c] = NULL;

        ret = parse_args(gfp, c, r);
        free(f);
        return ret;
}

int
main(int argc, char **argv)
{
        int i, iread, imp3, ret;
        short Buffer[2][1152];
        unsigned char mp3buffer[LAME_MAXMP3BUFFER];
        FILE *outf;
        lame_global_flags *gf;
        static char inPath[]  = "-";
        static char outPath[] = "-";
        static const char *mode_names[2][4] = {
                { "stereo", "j-stereo", "dual-ch", "single-ch" },
                { "stereo", "force-ms", "dual-ch", "single-ch" }
        };

        /* initialize libmp3lame */
        input_format = sf_unknown;
        if (NULL == (gf = lame_init()) ) {
                fprintf(stderr, "mp3enc: fatal error during initialization\n");
                return 1;
        }
        /*
         * parse the command line arguments, setting various flags in the
         * struct 'gf'.  If you want to parse your own arguments,
         * or call libmp3lame from a program which uses a GUI to set arguments,
         * skip this call and set the values of interest in the gf struct.
         * (see the file API & lame.h for documentation about these parameters)
         */
        parse_args_from_string(gf, getenv("LAMEOPT"));
        ret = parse_args(gf, argc, argv);
        if (ret < 0)
                return ret == -2? 0: 1;
        if (update_interval < 0.)
                update_interval = 2.;

        /*
         * open the wav/aiff/raw pcm or mp3 input file.  This call will
         * open the file, try to parse the headers and
         * set gf.samplerate, gf.num_channels, gf.num_samples.
         * if you want to do your own file input, skip this call and set
         * samplerate, num_channels and num_samples yourself.
         */
        init_infile(gf, inPath);
        if ((outf = init_outfile(outPath, lame_get_decode_only(gf))) == NULL) {
                fprintf(stderr, "Can't init outfile '%s'\n", outPath);
                return -42;
        }

        /*
         * Now that all the options are set, lame needs to analyze them and
         * set some more internal options and check for problems
         */
        i = lame_init_params(gf);
        if (i < 0) {
                if (i == -1)
                        display_bitrates(stderr);
                fprintf(stderr, "fatal error during initialization\n");
                return 1;
        }

        if (silent || gf->VBR == vbr_off)
                brhist = 0;                     /* turn off VBR histogram */

#ifdef BRHIST
        if (brhist) {
                if (brhist_init(gf, gf->VBR_min_bitrate_kbps,
                    gf->VBR_max_bitrate_kbps))
                        /* fail to initialize */
                        brhist = 0;
        } else
                brhist_init(gf, 128, 128);      /* Dirty hack */
#endif


#ifdef HAVE_VORBIS
        if (lame_get_ogg( gf ) ) {
                lame_encode_ogg_init(gf);
                gf->VBR = vbr_off;      /* ignore lame's various VBR modes */
        }
#endif
        if (0 == lame_get_decode_only( gf ) && silent < 10 ) {
                if (0)
                        fprintf(stderr, "Encoding as %g kHz ",
                                1.e-3 * lame_get_out_samplerate( gf ) );

                if (lame_get_ogg(gf)) {
                        if (0)
                                fprintf(stderr, "VBR Ogg Vorbis\n" );
                } else {
                        const char *appendix = "";

                        switch (gf->VBR ) {
                        case vbr_mt:
                        case vbr_rh:
                        case vbr_mtrh:
                                appendix = "ca. ";
                                if (0)
                                        fprintf(stderr, "VBR(q=%i)", gf->VBR_q );
                                break;
                        case vbr_abr:
                                if (0)
                                        fprintf(stderr, "average %d kbps",
                                                gf->VBR_mean_bitrate_kbps);
                                break;
                        default:
                                if (0)
                                        fprintf(stderr, "%3d Kb/s", gf->brate);
                                break;
                        }
                        if (0)
                                fprintf(stderr, " %s MPEG-%u%s Layer III (%s%gx) qval=%i\n",
                                        mode_names[gf->force_ms][gf->mode],
                                        2 - gf->version,
                                        lame_get_out_samplerate(gf) < 16000?
                                        ".5": "", appendix,
                                        0.1 * (int)(10.*gf->compression_ratio + 0.5),
                                        lame_get_quality(gf));
                }
                fflush(stderr);
        }

        if (lame_get_decode_only(gf))
                /* decode an mp3 file to a .wav */
                if (mp3_delay_set)
                        lame_decoder(gf, outf, mp3_delay, inPath, outPath);
                else
                        lame_decoder(gf, outf, gf->encoder_delay, inPath, outPath);
        else {
                /* encode until we hit eof */
                do {
                        /* read in 'iread' samples */
                        iread = get_audio(gf, Buffer);

                        /* status display  */
                        if (!silent)
                                if (update_interval > 0)
                                        timestatus_klemm(gf);
                                else {
                                        if (0 == gf->frameNum % 50) {
#ifdef BRHIST
                                                brhist_jump_back();
#endif
                                                timestatus(lame_get_out_samplerate(gf),
                                                        gf->frameNum,
                                                        gf->totalframes,
                                                        gf->framesize );
#ifdef BRHIST
                                                if (brhist)
                                                        brhist_disp(gf);
#endif
                                        }
                                }

                        /* encode */
                        imp3 = lame_encode_buffer(gf, Buffer[0], Buffer[1], iread,
                                mp3buffer, sizeof(mp3buffer));

                        /* was our output buffer big enough? */
                        if (imp3 < 0) {
                                if (imp3 == -1)
                                        fprintf(stderr, "mp3 buffer is not big enough... \n");
                                else
                                        fprintf(stderr, "mp3 internal error:  error code=%i\n", imp3);
                                return 1;
                        }

                        if (fwrite(mp3buffer, 1, imp3, outf) != imp3) {
                                fprintf(stderr, "Error writing mp3 output \n");
                                return 1;
                        }
                } while (iread);
                /* may return one more mp3 frame */
                imp3 = lame_encode_flush(gf, mp3buffer, sizeof(mp3buffer));
                if (imp3 < 0) {
                        if (imp3 == -1)
                                fprintf(stderr, "mp3 buffer is not big enough... \n");
                        else
                                fprintf(stderr, "mp3 internal error:  error code=%i\n", imp3);
                        return 1;

                }
                if (!silent) {
#ifdef BRHIST
                        brhist_jump_back();
#endif
                        timestatus(lame_get_out_samplerate(gf),
                                gf->frameNum,
                                gf->totalframes,
                                gf->framesize);
#ifdef BRHIST
                        if (brhist)
                                brhist_disp(gf);
                        brhist_disp_total(gf);
#endif
                        timestatus_finish();
                }

                fwrite(mp3buffer, 1, imp3, outf);
                lame_mp3_tags_fid(gf, outf);    /* add VBR tags to mp3 file */
                lame_close(gf);
                fclose(outf);
        }
        close_infile();
        exit(0);
        return 0;
}