main.c

Go to the documentation of this file.
00001 /*
00002  *      Command line frontend program
00003  *
00004  *      Copyright (c) 1999 Mark Taylor
00005  *                    2000 Takehiro TOMINAGA
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the
00019  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020  * Boston, MA 02111-1307, USA.
00021  */
00022 
00023 /* $Id: main.c,v 1.103 2007/07/24 17:46:09 bouvigne Exp $ */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #include <assert.h>
00030 #include <stdio.h>
00031 
00032 #ifdef STDC_HEADERS
00033 # include <stdlib.h>
00034 # include <string.h>
00035 #else
00036 # ifndef HAVE_STRCHR
00037 #  define strchr index
00038 #  define strrchr rindex
00039 # endif
00040 char   *strchr(), *strrchr();
00041 # ifndef HAVE_MEMCPY
00042 #  define memcpy(d, s, n) bcopy ((s), (d), (n))
00043 #  define memmove(d, s, n) bcopy ((s), (d), (n))
00044 # endif
00045 #endif
00046 
00047 #ifdef HAVE_FCNTL_H
00048 # include <fcntl.h>
00049 #endif
00050 
00051 #ifdef __sun__
00052 /* woraround for SunOS 4.x, it has SEEK_* defined here */
00053 #include <unistd.h>
00054 #endif
00055 
00056 #if defined(_WIN32)
00057 # include <windows.h>
00058 #endif
00059 
00060 
00061 /*
00062  main.c is example code for how to use libmp3lame.a.  To use this library,
00063  you only need the library and lame.h.  All other .h files are private
00064  to the library.
00065 */
00066 #include "lame.h"
00067 
00068 #include "console.h"
00069 #include "brhist.h"
00070 #include "parse.h"
00071 #include "main.h"
00072 #include "get_audio.h"
00073 #include "portableio.h"
00074 #include "timestatus.h"
00075 
00076 /* PLL 14/04/2000 */
00077 #if macintosh
00078 #include <console.h>
00079 #endif
00080 
00081 #ifdef WITH_DMALLOC
00082 #include <dmalloc.h>
00083 #endif
00084 
00085 
00086 
00087 
00088 /************************************************************************
00089 *
00090 * main
00091 *
00092 * PURPOSE:  MPEG-1,2 Layer III encoder with GPSYCHO
00093 * psychoacoustic model.
00094 *
00095 ************************************************************************/
00096 
00097 static int
00098 parse_args_from_string(lame_global_flags * const gfp, const char *p, char *inPath, char *outPath)
00099 {                       /* Quick & very Dirty */
00100     char   *q;
00101     char   *f;
00102     char   *r[128];
00103     int     c = 0;
00104     int     ret;
00105 
00106     if (p == NULL || *p == '\0')
00107         return 0;
00108 
00109     f = q = malloc(strlen(p) + 1);
00110     strcpy(q, p);
00111 
00112     r[c++] = "lhama";
00113     while (1) {
00114         r[c++] = q;
00115         while (*q != ' ' && *q != '\0')
00116             q++;
00117         if (*q == '\0')
00118             break;
00119         *q++ = '\0';
00120     }
00121     r[c] = NULL;
00122 
00123     ret = parse_args(gfp, c, r, inPath, outPath, NULL, NULL);
00124     free(f);
00125     return ret;
00126 }
00127 
00128 
00129 
00130 
00131 
00132 static FILE *
00133 init_files(lame_global_flags * gf, char *inPath, char *outPath, int *enc_delay, int *enc_padding)
00134 {
00135     FILE   *outf;
00136     /* Mostly it is not useful to use the same input and output name.
00137        This test is very easy and buggy and don't recognize different names
00138        assigning the same file
00139      */
00140     if (0 != strcmp("-", outPath) && 0 == strcmp(inPath, outPath)) {
00141         error_printf("Input file and Output file are the same. Abort.\n");
00142         return NULL;
00143     }
00144 
00145     /* open the wav/aiff/raw pcm or mp3 input file.  This call will
00146      * open the file, try to parse the headers and
00147      * set gf.samplerate, gf.num_channels, gf.num_samples.
00148      * if you want to do your own file input, skip this call and set
00149      * samplerate, num_channels and num_samples yourself.
00150      */
00151     init_infile(gf, inPath, enc_delay, enc_padding);
00152     if ((outf = init_outfile(outPath, lame_get_decode_only(gf))) == NULL) {
00153         error_printf("Can't init outfile '%s'\n", outPath);
00154         return NULL;
00155     }
00156 
00157     return outf;
00158 }
00159 
00160 
00161 
00162 
00163 
00164 
00165 /* the simple lame decoder */
00166 /* After calling lame_init(), lame_init_params() and
00167  * init_infile(), call this routine to read the input MP3 file
00168  * and output .wav data to the specified file pointer*/
00169 /* lame_decoder will ignore the first 528 samples, since these samples
00170  * represent the mpglib delay (and are all 0).  skip = number of additional
00171  * samples to skip, to (for example) compensate for the encoder delay */
00172 
00173 int
00174 lame_decoder(lame_global_flags * gfp, FILE * outf, int skip_start, char *inPath, char *outPath,
00175              int *enc_delay, int *enc_padding)
00176 {
00177     short int Buffer[2][1152];
00178     int     iread;
00179     int     skip_end = 0;
00180     double  wavsize;
00181     int     i;
00182     void    (*WriteFunction) (FILE * fp, char *p, int n);
00183     int     tmp_num_channels = lame_get_num_channels(gfp);
00184 
00185 
00186 
00187     if (silent < 10)
00188         console_printf("\rinput:  %s%s(%g kHz, %i channel%s, ",
00189                        strcmp(inPath, "-") ? inPath : "<stdin>",
00190                        strlen(inPath) > 26 ? "\n\t" : "  ",
00191                        lame_get_in_samplerate(gfp) / 1.e3,
00192                        tmp_num_channels, tmp_num_channels != 1 ? "s" : "");
00193 
00194     switch (input_format) {
00195     case sf_mp123: /* FIXME: !!! */
00196       error_printf("Internal error.  Aborting.");
00197       exit(-1);
00198 
00199     case sf_mp3:
00200         if (skip_start == 0) {
00201             if (*enc_delay > -1 || *enc_padding > -1) {
00202                 if (*enc_delay > -1)
00203                     skip_start = *enc_delay + 528 + 1;
00204                 if (*enc_padding > -1)
00205                     skip_end = *enc_padding - (528 + 1);
00206             }
00207             else
00208                 skip_start = lame_get_encoder_delay(gfp) + 528 + 1;
00209         }
00210         else {
00211             /* user specified a value of skip. just add for decoder */
00212             skip_start += 528 + 1; /* mp3 decoder has a 528 sample delay, plus user supplied "skip" */
00213         }
00214 
00215         if (silent < 10)
00216             console_printf("MPEG-%u%s Layer %s", 2 - lame_get_version(gfp),
00217                            lame_get_out_samplerate(gfp) < 16000 ? ".5" : "", "III");
00218         break;
00219     case sf_mp2:
00220         skip_start += 240 + 1;
00221         if (silent < 10)
00222             console_printf("MPEG-%u%s Layer %s", 2 - lame_get_version(gfp),
00223                            lame_get_out_samplerate(gfp) < 16000 ? ".5" : "", "II");
00224         break;
00225     case sf_mp1:
00226         skip_start += 240 + 1;
00227         if (silent < 10)
00228             console_printf("MPEG-%u%s Layer %s", 2 - lame_get_version(gfp),
00229                            lame_get_out_samplerate(gfp) < 16000 ? ".5" : "", "I");
00230         break;
00231     case sf_raw:
00232         if (silent < 10)
00233             console_printf("raw PCM data");
00234         mp3input_data.nsamp = lame_get_num_samples(gfp);
00235         mp3input_data.framesize = 1152;
00236         skip_start = 0; /* other formats have no delay *//* is += 0 not better ??? */
00237         break;
00238     case sf_wave:
00239         if (silent < 10)
00240             console_printf("Microsoft WAVE");
00241         mp3input_data.nsamp = lame_get_num_samples(gfp);
00242         mp3input_data.framesize = 1152;
00243         skip_start = 0; /* other formats have no delay *//* is += 0 not better ??? */
00244         break;
00245     case sf_aiff:
00246         if (silent < 10)
00247             console_printf("SGI/Apple AIFF");
00248         mp3input_data.nsamp = lame_get_num_samples(gfp);
00249         mp3input_data.framesize = 1152;
00250         skip_start = 0; /* other formats have no delay *//* is += 0 not better ??? */
00251         break;
00252     default:
00253         if (silent < 10)
00254             console_printf("unknown");
00255         mp3input_data.nsamp = lame_get_num_samples(gfp);
00256         mp3input_data.framesize = 1152;
00257         skip_start = 0; /* other formats have no delay *//* is += 0 not better ??? */
00258         assert(0);
00259         break;
00260     }
00261 
00262     if (silent < 10) {
00263         console_printf(")\noutput: %s%s(16 bit, Microsoft WAVE)\n",
00264                        strcmp(outPath, "-") ? outPath : "<stdout>",
00265                        strlen(outPath) > 45 ? "\n\t" : "  ");
00266 
00267         if (skip_start > 0)
00268             console_printf("skipping initial %i samples (encoder+decoder delay)\n", skip_start);
00269         if (skip_end > 0)
00270             console_printf("skipping final %i samples (encoder padding-decoder delay)\n", skip_end);
00271     }
00272 
00273     if (0 == disable_wav_header)
00274         WriteWaveHeader(outf, 0x7FFFFFFF, lame_get_in_samplerate(gfp), tmp_num_channels, 16);
00275     /* unknown size, so write maximum 32 bit signed value */
00276 
00277     wavsize = -(skip_start + skip_end);
00278     WriteFunction = swapbytes ? WriteBytesSwapped : WriteBytes;
00279     mp3input_data.totalframes = mp3input_data.nsamp / mp3input_data.framesize;
00280 
00281     assert(tmp_num_channels >= 1 && tmp_num_channels <= 2);
00282 
00283     do {
00284         iread = get_audio16(gfp, Buffer); /* read in 'iread' samples */
00285         if (iread >= 0) {
00286             mp3input_data.framenum += iread / mp3input_data.framesize;
00287             wavsize += iread;
00288 
00289             if (silent <= 0) {
00290                 decoder_progress(&mp3input_data);
00291                 console_flush();
00292             }
00293 
00294             skip_start -= (i = skip_start < iread ? skip_start : iread); /* 'i' samples are to skip in this frame */
00295 
00296             if (skip_end > 1152 && mp3input_data.framenum + 2 > mp3input_data.totalframes) {
00297                 iread -= (skip_end - 1152);
00298                 skip_end = 1152;
00299             }
00300             else if (mp3input_data.framenum == mp3input_data.totalframes && iread != 0)
00301                 iread -= skip_end;
00302 
00303             for (; i < iread; i++) {
00304                 if (disable_wav_header) {
00305                     WriteFunction(outf, (char *) &Buffer[0][i], sizeof(short));
00306                     if (tmp_num_channels == 2)
00307                         WriteFunction(outf, (char *) &Buffer[1][i], sizeof(short));
00308                 }
00309                 else {
00310                     Write16BitsLowHigh(outf, Buffer[0][i]);
00311                     if (tmp_num_channels == 2)
00312                         Write16BitsLowHigh(outf, Buffer[1][i]);
00313                 }
00314             }
00315             if (flush_write == 1) {
00316                 fflush(outf);
00317             }
00318         }
00319     } while (iread > 0);
00320 
00321     i = (16 / 8) * tmp_num_channels;
00322     assert(i > 0);
00323     if (wavsize <= 0) {
00324         if (silent < 10)
00325             error_printf("WAVE file contains 0 PCM samples\n");
00326         wavsize = 0;
00327     }
00328     else if (wavsize > 0xFFFFFFD0 / i) {
00329         if (silent < 10)
00330             error_printf("Very huge WAVE file, can't set filesize accordingly\n");
00331         wavsize = 0xFFFFFFD0;
00332     }
00333     else {
00334         wavsize *= i;
00335     }
00336 
00337     /* if outf is seekable, rewind and adjust length */
00338     if (!disable_wav_header && strcmp("-", outPath)
00339         && !fseek(outf, 0l, SEEK_SET))
00340         WriteWaveHeader(outf, (int) wavsize, lame_get_in_samplerate(gfp),
00341                         tmp_num_channels, 16);
00342     fclose(outf);
00343 
00344     if (silent <= 0)
00345         decoder_progress_finish();
00346     return 0;
00347 }
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 static int
00361 lame_encoder(lame_global_flags * gf, FILE * outf, int nogap, char *inPath, char *outPath)
00362 {
00363     unsigned char mp3buffer[LAME_MAXMP3BUFFER];
00364     int     Buffer[2][1152];
00365     int     iread, imp3, owrite;
00366 
00367     encoder_progress_begin(gf, inPath, outPath);
00368 
00369     /* encode until we hit eof */
00370     do {
00371         /* read in 'iread' samples */
00372         iread = get_audio(gf, Buffer);
00373 
00374         if (iread >= 0) {
00375             encoder_progress(gf);
00376 
00377             /* encode */
00378             imp3 = lame_encode_buffer_int(gf, Buffer[0], Buffer[1], iread,
00379                                           mp3buffer, sizeof(mp3buffer));
00380 
00381             /* was our output buffer big enough? */
00382             if (imp3 < 0) {
00383                 if (imp3 == -1)
00384                     error_printf("mp3 buffer is not big enough... \n");
00385                 else
00386                     error_printf("mp3 internal error:  error code=%i\n", imp3);
00387                 return 1;
00388             }
00389             owrite = (int) fwrite(mp3buffer, 1, imp3, outf);
00390             if (owrite != imp3) {
00391                 error_printf("Error writing mp3 output \n");
00392                 return 1;
00393             }
00394         }
00395         if (flush_write == 1) {
00396             fflush(outf);
00397         }
00398     } while (iread > 0);
00399 
00400     if (nogap)
00401         imp3 = lame_encode_flush_nogap(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */
00402     else
00403         imp3 = lame_encode_flush(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */
00404 
00405     if (imp3 < 0) {
00406         if (imp3 == -1)
00407             error_printf("mp3 buffer is not big enough... \n");
00408         else
00409             error_printf("mp3 internal error:  error code=%i\n", imp3);
00410         return 1;
00411 
00412     }
00413 
00414     encoder_progress_end(gf);
00415     
00416     owrite = (int) fwrite(mp3buffer, 1, imp3, outf);
00417     if (owrite != imp3) {
00418         error_printf("Error writing mp3 output \n");
00419         return 1;
00420     }
00421     if (flush_write == 1) {
00422         fflush(outf);
00423     }
00424 
00425     return 0;
00426 }
00427 
00428 
00429 
00430 
00431 
00432 
00433 static void
00434 brhist_init_package(lame_global_flags * gf)
00435 {
00436 #ifdef BRHIST
00437     if (brhist) {
00438         if (brhist_init(gf, lame_get_VBR_min_bitrate_kbps(gf), lame_get_VBR_max_bitrate_kbps(gf))) {
00439             /* fail to initialize */
00440             brhist = 0;
00441         }
00442     }
00443     else {
00444         brhist_init(gf, 128, 128); /* Dirty hack */
00445     }
00446 #endif
00447 }
00448 
00449 
00450 
00451 static
00452     void
00453 parse_nogap_filenames(int nogapout, char *inPath, char *outPath, char *outdir)
00454 {
00455 
00456     char   *slasher;
00457     size_t  n;
00458 
00459     strcpy(outPath, outdir);
00460     if (!nogapout) {
00461         strncpy(outPath, inPath, PATH_MAX + 1 - 4);
00462         n = strlen(outPath);
00463         /* nuke old extension, if one  */
00464         if (outPath[n - 3] == 'w'
00465             && outPath[n - 2] == 'a' && outPath[n - 1] == 'v' && outPath[n - 4] == '.') {
00466             outPath[n - 3] = 'm';
00467             outPath[n - 2] = 'p';
00468             outPath[n - 1] = '3';
00469         }
00470         else {
00471             outPath[n + 0] = '.';
00472             outPath[n + 1] = 'm';
00473             outPath[n + 2] = 'p';
00474             outPath[n + 3] = '3';
00475             outPath[n + 4] = 0;
00476         }
00477     }
00478     else {
00479         slasher = inPath;
00480         slasher += PATH_MAX + 1 - 4;
00481 
00482         /* backseek to last dir delemiter */
00483         while (*slasher != '/' && *slasher != '\\' && slasher != inPath && *slasher != ':') {
00484             slasher--;
00485         }
00486 
00487         /* skip one foward if needed */
00488         if (slasher != inPath
00489             && (outPath[strlen(outPath) - 1] == '/'
00490                 || outPath[strlen(outPath) - 1] == '\\' || outPath[strlen(outPath) - 1] == ':'))
00491             slasher++;
00492         else if (slasher == inPath
00493                  && (outPath[strlen(outPath) - 1] != '/'
00494                      &&
00495                      outPath[strlen(outPath) - 1] != '\\' && outPath[strlen(outPath) - 1] != ':'))
00496 #ifdef _WIN32
00497             strcat(outPath, "\\");
00498 #elif __OS2__
00499             strcat(outPath, "\\");
00500 #else
00501             strcat(outPath, "/");
00502 #endif
00503 
00504         strncat(outPath, slasher, PATH_MAX + 1 - 4);
00505         n = strlen(outPath);
00506         /* nuke old extension  */
00507         if (outPath[n - 3] == 'w'
00508             && outPath[n - 2] == 'a' && outPath[n - 1] == 'v' && outPath[n - 4] == '.') {
00509             outPath[n - 3] = 'm';
00510             outPath[n - 2] = 'p';
00511             outPath[n - 1] = '3';
00512         }
00513         else {
00514             outPath[n + 0] = '.';
00515             outPath[n + 1] = 'm';
00516             outPath[n + 2] = 'p';
00517             outPath[n + 3] = '3';
00518             outPath[n + 4] = 0;
00519         }
00520     }
00521 }
00522 
00523 
00524 
00525 
00526 static void
00527 print_lame_tag_leading_info(lame_global_flags * gf)
00528 {
00529     if (lame_get_bWriteVbrTag(gf))
00530         console_printf("Writing LAME Tag...");
00531 }
00532 
00533 static void
00534 print_trailing_info(lame_global_flags * gf)
00535 {
00536     if (lame_get_bWriteVbrTag(gf))
00537         console_printf("done\n");
00538 
00539     if (lame_get_findReplayGain(gf)) {
00540         int     RadioGain = lame_get_RadioGain(gf);
00541         console_printf("ReplayGain: %s%.1fdB\n", RadioGain > 0 ? "+" : "",
00542                        ((float) RadioGain) / 10.0);
00543         if (RadioGain > 0x1FE || RadioGain < -0x1FE)
00544             error_printf
00545                 ("WARNING: ReplayGain exceeds the -51dB to +51dB range. Such a result is too\n"
00546                  "         high to be stored in the header.\n");
00547     }
00548 
00549     /* if (the user requested printing info about clipping) and (decoding
00550        on the fly has actually been performed) */
00551     if (print_clipping_info && lame_get_decode_on_the_fly(gf)) {
00552         float   noclipGainChange = (float) lame_get_noclipGainChange(gf) / 10.0f;
00553         float   noclipScale = lame_get_noclipScale(gf);
00554 
00555         if (noclipGainChange > 0.0) { /* clipping occurs */
00556             console_printf
00557                 ("WARNING: clipping occurs at the current gain. Set your decoder to decrease\n"
00558                  "         the  gain  by  at least %.1fdB or encode again ", noclipGainChange);
00559 
00560             /* advice the user on the scale factor */
00561             if (noclipScale > 0) {
00562                 console_printf("using  --scale %.2f\n", noclipScale);
00563                 console_printf("         or less (the value under --scale is approximate).\n");
00564             }
00565             else {
00566                 /* the user specified his own scale factor. We could suggest
00567                  * the scale factor of (32767.0/gfp->PeakSample)*(gfp->scale)
00568                  * but it's usually very inaccurate. So we'd rather advice him to
00569                  * disable scaling first and see our suggestion on the scale factor then. */
00570                 console_printf("using --scale <arg>\n"
00571                                "         (For   a   suggestion  on  the  optimal  value  of  <arg>  encode\n"
00572                                "         with  --scale 1  first)\n");
00573             }
00574 
00575         }
00576         else {          /* no clipping */
00577             if (noclipGainChange > -0.1)
00578                 console_printf
00579                     ("\nThe waveform does not clip and is less than 0.1dB away from full scale.\n");
00580             else
00581                 console_printf
00582                     ("\nThe waveform does not clip and is at least %.1fdB away from full scale.\n",
00583                      -noclipGainChange);
00584         }
00585     }
00586 
00587 }
00588 
00589 
00590 /***********************************************************************
00591 *
00592 *  Message Output
00593 *
00594 ***********************************************************************/
00595 
00596 
00597 int
00598 main(int argc, char **argv)
00599 {
00600     int     ret;
00601     lame_global_flags *gf;
00602     char    outPath[PATH_MAX + 1];
00603     char    nogapdir[PATH_MAX + 1];
00604     char    inPath[PATH_MAX + 1];
00605 
00606     /* add variables for encoder delay/padding */
00607     int     enc_delay = -1;
00608     int     enc_padding = -1;
00609 
00610     /* support for "nogap" encoding of up to 200 .wav files */
00611 #define MAX_NOGAP 200
00612     int     nogapout = 0;
00613     int     max_nogap = MAX_NOGAP;
00614     char   *nogap_inPath[MAX_NOGAP];
00615 
00616     int     i;
00617     FILE   *outf;
00618 
00619 #if macintosh
00620     argc = ccommand(&argv);
00621 #endif
00622 #if 0
00623     /* rh 061207
00624        the following fix seems to be a workaround for a problem in the
00625        parent process calling LAME. It would be better to fix the broken
00626        application => code disabled.
00627      */
00628 #if defined(_WIN32)
00629     /* set affinity back to all CPUs.  Fix for EAC/lame on SMP systems from
00630        "Todd Richmond" <todd.richmond@openwave.com> */
00631     typedef BOOL(WINAPI * SPAMFunc) (HANDLE, DWORD_PTR);
00632     SPAMFunc func;
00633     SYSTEM_INFO si;
00634 
00635     if ((func = (SPAMFunc) GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"),
00636                                           "SetProcessAffinityMask")) != NULL) {
00637         GetSystemInfo(&si);
00638         func(GetCurrentProcess(), si.dwActiveProcessorMask);
00639     }
00640 #endif
00641 #endif
00642 
00643 #ifdef __EMX__
00644     /* This gives wildcard expansion on Non-POSIX shells with OS/2 */
00645     _wildcard(&argc, &argv);
00646 #endif
00647 
00648     for (i = 0; i < max_nogap; ++i) {
00649         nogap_inPath[i] = malloc(PATH_MAX + 1);
00650     }
00651 
00652     memset(inPath, 0, sizeof(inPath));
00653 
00654     frontend_open_console();
00655 
00656     /* initialize libmp3lame */
00657     input_format = sf_unknown;
00658     if (NULL == (gf = lame_init())) {
00659         error_printf("fatal error during initialization\n");
00660         frontend_close_console();
00661         return 1;
00662     }
00663     lame_set_errorf(gf, &frontend_errorf);
00664     lame_set_debugf(gf, &frontend_debugf);
00665     lame_set_msgf(gf, &frontend_msgf);
00666     if (argc <= 1) {
00667         usage(stderr, argv[0]); /* no command-line args, print usage, exit  */
00668         lame_close(gf);
00669         frontend_close_console();
00670         return 1;
00671     }
00672 
00673     /* parse the command line arguments, setting various flags in the
00674      * struct 'gf'.  If you want to parse your own arguments,
00675      * or call libmp3lame from a program which uses a GUI to set arguments,
00676      * skip this call and set the values of interest in the gf struct.
00677      * (see the file API and lame.h for documentation about these parameters)
00678      */
00679     parse_args_from_string(gf, getenv("LAMEOPT"), inPath, outPath);
00680     ret = parse_args(gf, argc, argv, inPath, outPath, nogap_inPath, &max_nogap);
00681     if (ret < 0) {
00682         lame_close(gf);
00683         frontend_close_console();
00684         return ret == -2 ? 0 : 1;
00685     }
00686     if (update_interval < 0.)
00687         update_interval = 2.;
00688 
00689     if (outPath[0] != '\0' && max_nogap > 0) {
00690         strncpy(nogapdir, outPath, PATH_MAX + 1);
00691         nogapout = 1;
00692     }
00693 
00694     /* initialize input file.  This also sets samplerate and as much
00695        other data on the input file as available in the headers */
00696     if (max_nogap > 0) {
00697         /* for nogap encoding of multiple input files, it is not possible to
00698          * specify the output file name, only an optional output directory. */
00699         parse_nogap_filenames(nogapout, nogap_inPath[0], outPath, nogapdir);
00700         outf = init_files(gf, nogap_inPath[0], outPath, &enc_delay, &enc_padding);
00701     }
00702     else {
00703         outf = init_files(gf, inPath, outPath, &enc_delay, &enc_padding);
00704     }
00705     if (outf == NULL) {
00706         lame_close(gf);
00707         frontend_close_console();
00708         return -1;
00709     }
00710 
00711     /* Now that all the options are set, lame needs to analyze them and
00712      * set some more internal options and check for problems
00713      */
00714     i = lame_init_params(gf);
00715     if (i < 0) {
00716         if (i == -1) {
00717             display_bitrates(stderr);
00718         }
00719         error_printf("fatal error during initialization\n");
00720         lame_close(gf);
00721         frontend_close_console();
00722         return i;
00723     }
00724 
00725     if (silent > 0
00726 #ifndef RH_HIST
00727         || lame_get_VBR(gf) == vbr_off
00728 #endif
00729         ) {
00730         brhist = 0;     /* turn off VBR histogram */
00731     }
00732 
00733 
00734     if (lame_get_decode_only(gf)) {
00735         /* decode an mp3 file to a .wav */
00736         if (mp3_delay_set)
00737             lame_decoder(gf, outf, mp3_delay, inPath, outPath, &enc_delay, &enc_padding);
00738         else
00739             lame_decoder(gf, outf, 0, inPath, outPath, &enc_delay, &enc_padding);
00740 
00741     }
00742     else {
00743         if (max_nogap > 0) {
00744             /*
00745              * encode multiple input files using nogap option
00746              */
00747             for (i = 0; i < max_nogap; ++i) {
00748                 int     use_flush_nogap = (i != (max_nogap - 1));
00749                 if (i > 0) {
00750                     parse_nogap_filenames(nogapout, nogap_inPath[i], outPath, nogapdir);
00751                     /* note: if init_files changes anything, like
00752                        samplerate, num_channels, etc, we are screwed */
00753                     outf = init_files(gf, nogap_inPath[i], outPath, &enc_delay, &enc_padding);
00754                 }
00755                 brhist_init_package(gf);
00756                 lame_set_nogap_total(gf, max_nogap);
00757                 lame_set_nogap_currentindex(gf, i);
00758                 ret = lame_encoder(gf, outf, use_flush_nogap, nogap_inPath[i], outPath);
00759 
00760                 if (silent <= 0)
00761                     print_lame_tag_leading_info(gf);
00762                 lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */
00763 
00764                 if (silent <= 0)
00765                     print_trailing_info(gf);
00766 
00767                 fclose(outf); /* close the output file */
00768                 close_infile(); /* close the input file */
00769 
00770                 /* reinitialize bitstream for next encoding.  this is normally done
00771                  * by lame_init_params(), but we cannot call that routine twice */
00772                 if (use_flush_nogap)
00773                     lame_init_bitstream(gf);
00774             }
00775             lame_close(gf);
00776 
00777         }
00778         else {
00779             /*
00780              * encode a single input file
00781              */
00782             brhist_init_package(gf);
00783             ret = lame_encoder(gf, outf, 0, inPath, outPath);
00784 
00785             if (silent <= 0)
00786                 print_lame_tag_leading_info(gf);
00787             lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */
00788 
00789             if (silent <= 0)
00790                 print_trailing_info(gf);
00791 
00792             fclose(outf); /* close the output file */
00793             close_infile(); /* close the input file */
00794             lame_close(gf);
00795         }
00796     }
00797     frontend_close_console();
00798     return ret;
00799 }

Generated on Sun Dec 2 11:34:18 2007 for LAME by  doxygen 1.5.2