home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Sound / LAME / WarpOS / src / frontend / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-06-25  |  17.5 KB  |  616 lines

  1. /*
  2.  *    Command line frontend program
  3.  *
  4.  *    Copyright (c) 1999 Mark Taylor
  5.  *                    2000 Takehiro TOMIANGA
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Library General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the GNU
  15.  * Library General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Library General Public
  18.  * License along with this library; if not, write to the
  19.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20.  * Boston, MA 02111-1307, USA.
  21.  */
  22.  
  23. /* $Id: main.c,v 1.57 2001/06/25 02:14:00 cisc Exp $ */
  24.  
  25. #ifdef HAVE_CONFIG_H
  26. # include <config.h>
  27. #endif
  28.  
  29. #include <assert.h>
  30. #include <stdio.h>
  31.  
  32. #ifdef STDC_HEADERS
  33. # include <stdlib.h>
  34. # include <string.h>
  35. #else
  36. # ifndef HAVE_STRCHR
  37. #  define strchr index
  38. #  define strrchr rindex
  39. # endif
  40. char   *strchr(), *strrchr();
  41. # ifndef HAVE_MEMCPY
  42. #  define memcpy(d, s, n) bcopy ((s), (d), (n))
  43. #  define memmove(d, s, n) bcopy ((s), (d), (n))
  44. # endif
  45. #endif
  46.  
  47. #ifdef HAVE_FCNTL_H
  48. # include <fcntl.h>
  49. #endif
  50.  
  51.  
  52. /*
  53.  main.c is example code for how to use libmp3lame.a.  To use this library,
  54.  you only need the library and lame.h.  All other .h files are private
  55.  to the library.
  56. */
  57. #include "lame.h"
  58.  
  59. #include "brhist.h"
  60. #include "parse.h"
  61. #include "main.h"
  62. #include "get_audio.h"
  63. #include "portableio.h"
  64. #include "timestatus.h"
  65.  
  66. /* PLL 14/04/2000 */
  67. #if macintosh
  68. #include <console.h>
  69. #endif
  70.  
  71. #ifdef WITH_DMALLOC
  72. #include <dmalloc.h>
  73. #endif
  74.  
  75.  
  76.  
  77.  
  78. /************************************************************************
  79. *
  80. * main
  81. *
  82. * PURPOSE:  MPEG-1,2 Layer III encoder with GPSYCHO
  83. * psychoacoustic model.
  84. *
  85. ************************************************************************/
  86.  
  87. int
  88. parse_args_from_string(lame_global_flags * const gfp, const char *p,
  89.                        char *inPath, char *outPath)
  90. {                       /* Quick & very Dirty */
  91.     char   *q;
  92.     char   *f;
  93.     char   *r[128];
  94.     int     c = 0;
  95.     int     ret;
  96.  
  97.     if (p == NULL || *p == '\0')
  98.         return 0;
  99.  
  100.     f = q = malloc(strlen(p) + 1);
  101.     strcpy(q, p);
  102.  
  103.     r[c++] = "lhama";
  104.     while (1) {
  105.         r[c++] = q;
  106.         while (*q != ' ' && *q != '\0')
  107.             q++;
  108.         if (*q == '\0')
  109.             break;
  110.         *q++ = '\0';
  111.     }
  112.     r[c] = NULL;
  113.  
  114.     ret = parse_args(gfp, c, r, inPath, outPath, NULL, NULL);
  115.     free(f);
  116.     return ret;
  117. }
  118.  
  119.  
  120.  
  121.  
  122.  
  123. FILE   *
  124. init_files(lame_global_flags * gf, char *inPath, char *outPath)
  125. {
  126.     FILE   *outf;
  127.     /* Mostly it is not useful to use the same input and output name.
  128.        This test is very easy and buggy and don't recognize different names
  129.        assigning the same file
  130.      */
  131.     if (0 != strcmp("-", outPath) && 0 == strcmp(inPath, outPath)) {
  132.         fprintf(stderr, "Input file and Output file are the same. Abort.\n");
  133.         return NULL;
  134.     }
  135.  
  136.     /* open the wav/aiff/raw pcm or mp3 input file.  This call will
  137.      * open the file, try to parse the headers and
  138.      * set gf.samplerate, gf.num_channels, gf.num_samples.
  139.      * if you want to do your own file input, skip this call and set
  140.      * samplerate, num_channels and num_samples yourself.
  141.      */
  142.     init_infile(gf, inPath);
  143.     if ((outf = init_outfile(outPath, lame_get_decode_only(gf))) == NULL) {
  144.         fprintf(stderr, "Can't init outfile '%s'\n", outPath);
  145.         return NULL;
  146.     }
  147.  
  148.     return outf;
  149. }
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156. /* the simple lame decoder */
  157. /* After calling lame_init(), lame_init_params() and
  158.  * init_infile(), call this routine to read the input MP3 file
  159.  * and output .wav data to the specified file pointer*/
  160. /* lame_decoder will ignore the first 528 samples, since these samples
  161.  * represent the mpglib delay (and are all 0).  skip = number of additional
  162.  * samples to skip, to (for example) compensate for the encoder delay */
  163.  
  164. int
  165. lame_decoder(lame_global_flags * gfp, FILE * outf, int skip, char *inPath,
  166.              char *outPath)
  167. {
  168.     short int Buffer[2][1152];
  169.     int     iread;
  170.     double  wavsize;
  171.     int     i;
  172.     void    (*WriteFunction) (FILE * fp, char *p, int n);
  173.     int tmp_num_channels = lame_get_num_channels( gfp );
  174.  
  175.  
  176.  
  177.     fprintf(stderr, "\rinput:  %s%s(%g kHz, %i channel%s, ",
  178.             strcmp(inPath, "-") ? inPath : "<stdin>",
  179.             strlen(inPath) > 26 ? "\n\t" : "  ",
  180.             lame_get_in_samplerate( gfp ) / 1.e3,
  181.             tmp_num_channels, tmp_num_channels != 1 ? "s" : "");
  182.  
  183.     switch (input_format) {
  184.     case sf_mp3:
  185.         skip += 528 + 1; /* mp3 decoder has a 528 sample delay, plus user supplied "skip" */
  186.         fprintf(stderr, "MPEG-%u%s Layer %s", 2 - lame_get_version(gfp),
  187.                 lame_get_out_samplerate( gfp ) < 16000 ? ".5" : "", "III");
  188.         break;
  189.     case sf_mp2:
  190.         skip += 240 + 1;
  191.         fprintf(stderr, "MPEG-%u%s Layer %s", 2 - lame_get_version(gfp),
  192.                 lame_get_out_samplerate( gfp ) < 16000 ? ".5" : "", "II");
  193.         break;
  194.     case sf_mp1:
  195.         skip += 240 + 1;
  196.         fprintf(stderr, "MPEG-%u%s Layer %s", 2 - lame_get_version(gfp),
  197.                 lame_get_out_samplerate( gfp ) < 16000 ? ".5" : "", "I");
  198.         break;
  199.     case sf_ogg:
  200.         fprintf(stderr, "Ogg Vorbis");
  201.         skip = 0;       /* other formats have no delay *//* is += 0 not better ??? */
  202.         break;
  203.     case sf_raw:
  204.         fprintf(stderr, "raw PCM data");
  205.         mp3input_data.nsamp = lame_get_num_samples( gfp );
  206.         mp3input_data.framesize = 1152;
  207.         skip = 0;       /* other formats have no delay *//* is += 0 not better ??? */
  208.         break;
  209.     case sf_wave:
  210.         fprintf(stderr, "Microsoft WAVE");
  211.         mp3input_data.nsamp = lame_get_num_samples( gfp );
  212.         mp3input_data.framesize = 1152;
  213.         skip = 0;       /* other formats have no delay *//* is += 0 not better ??? */
  214.         break;
  215.     case sf_aiff:
  216.         fprintf(stderr, "SGI/Apple AIFF");
  217.         mp3input_data.nsamp = lame_get_num_samples( gfp );
  218.         mp3input_data.framesize = 1152;
  219.         skip = 0;       /* other formats have no delay *//* is += 0 not better ??? */
  220.         break;
  221.     default:
  222.         fprintf(stderr, "unknown");
  223.         mp3input_data.nsamp = lame_get_num_samples( gfp );
  224.         mp3input_data.framesize = 1152;
  225.         skip = 0;       /* other formats have no delay *//* is += 0 not better ??? */
  226.         assert(0);
  227.         break;
  228.     }
  229.  
  230.     fprintf(stderr, ")\noutput: %s%s(16 bit, Microsoft WAVE)\n",
  231.             strcmp(outPath, "-") ? outPath : "<stdout>",
  232.             strlen(outPath) > 45 ? "\n\t" : "  ");
  233.  
  234.     if (skip > 0)
  235.         fprintf(stderr, "skipping initial %i samples (encoder+decoder delay)\n",
  236.                 skip);
  237.  
  238.     if ( 0 == disable_wav_header )
  239.         WriteWaveHeader(outf, 0x7FFFFFFF, lame_get_in_samplerate( gfp ),
  240.                         tmp_num_channels,
  241.                         16);
  242.     /* unknown size, so write maximum 32 bit signed value */
  243.  
  244.     wavsize = -skip;
  245.     WriteFunction = swapbytes ? WriteBytesSwapped : WriteBytes;
  246.     mp3input_data.totalframes = mp3input_data.nsamp / mp3input_data.framesize;
  247.  
  248.     assert(tmp_num_channels >= 1 && tmp_num_channels <= 2);
  249.  
  250.     do {
  251.         iread = get_audio16(gfp, Buffer); /* read in 'iread' samples */
  252.         mp3input_data.framenum += iread / mp3input_data.framesize;
  253.         wavsize += iread;
  254.  
  255.         if (silent <= 0)
  256.             decoder_progress(gfp, &mp3input_data);
  257.  
  258.         skip -= (i = skip < iread ? skip : iread); /* 'i' samples are to skip in this frame */
  259.  
  260.         for (; i < iread; i++) {
  261.             if ( disable_wav_header ) {
  262.                 WriteFunction(outf, (char *) &Buffer[0][i], sizeof(short));
  263.                 if (tmp_num_channels == 2)
  264.                     WriteFunction(outf, (char *) &Buffer[1][i], sizeof(short));
  265.             }
  266.             else {
  267.                 Write16BitsLowHigh(outf, Buffer[0][i]);
  268.                 if (tmp_num_channels == 2)
  269.                     Write16BitsLowHigh(outf, Buffer[1][i]);
  270.             }
  271.         }
  272.     } while (iread);
  273.  
  274.     i = (16 / 8) * tmp_num_channels;
  275.     assert(i > 0);
  276.     if (wavsize <= 0) {
  277.         fprintf(stderr, "WAVE file contains 0 PCM samples\n");
  278.         wavsize = 0;
  279.     }
  280.     else if (wavsize > 0xFFFFFFD0 / i) {
  281.         fprintf(stderr,
  282.                 "Very huge WAVE file, can't set filesize accordingly\n");
  283.         wavsize = 0xFFFFFFD0;
  284.     }
  285.     else {
  286.         wavsize *= i;
  287.     }
  288.  
  289.     if ( 0 == disable_wav_header )
  290.         if (!fseek(outf, 0l, SEEK_SET)) /* if outf is seekable, rewind and adjust length */
  291.             WriteWaveHeader(outf, wavsize, lame_get_in_samplerate( gfp ),
  292.                             tmp_num_channels, 16);
  293.     fclose(outf);
  294.  
  295.     decoder_progress_finish(gfp);
  296.     return 0;
  297. }
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314. int
  315. lame_encoder(lame_global_flags * gf, FILE * outf, int nogap, char *inPath,
  316.              char *outPath)
  317. {
  318.     unsigned char mp3buffer[LAME_MAXMP3BUFFER];
  319.     int     Buffer[2][1152];
  320.     int     iread, imp3;
  321.     static const char *mode_names[2][4] = {
  322.         {"stereo", "j-stereo", "dual-ch", "single-ch"},
  323.         {"stereo", "force-ms", "dual-ch", "single-ch"}
  324.     };
  325.     int     frames;
  326.  
  327.     if (silent < 10) {
  328.         lame_print_config(gf); /* print useful information about options being used */
  329.  
  330.         fprintf(stderr, "Encoding %s%s to %s\n",
  331.                 strcmp(inPath, "-") ? inPath : "<stdin>",
  332.                 strlen(inPath) + strlen(outPath) < 66 ? "" : "\n     ",
  333.                 strcmp(outPath, "-") ? outPath : "<stdout>");
  334.  
  335.         fprintf(stderr,
  336.                 "Encoding as %g kHz ", 1.e-3 * lame_get_out_samplerate(gf));
  337.  
  338.         if (lame_get_ogg(gf)) {
  339.             fprintf(stderr, "VBR Ogg Vorbis\n");
  340.         }
  341.         else {
  342.             const char *appendix = "";
  343.  
  344.             switch (lame_get_VBR(gf)) {
  345.             case vbr_mt:
  346.             case vbr_rh:
  347.             case vbr_mtrh:
  348.                 appendix = "ca. ";
  349.                 fprintf(stderr, "VBR(q=%i)", lame_get_VBR_q(gf));
  350.                 break;
  351.             case vbr_abr:
  352.                 fprintf(stderr, "average %d kbps",
  353.                         lame_get_VBR_mean_bitrate_kbps(gf));
  354.                 break;
  355.             default:
  356.                 fprintf(stderr, "%3d kbps", lame_get_brate(gf));
  357.                 break;
  358.             }
  359.             fprintf(stderr, " %s MPEG-%u%s Layer III (%s%gx) qval=%i\n",
  360.                     mode_names[lame_get_force_ms(gf)][lame_get_mode(gf)],
  361.                     2 - lame_get_version(gf),
  362.                     lame_get_out_samplerate(gf) < 16000 ? ".5" : "",
  363.                     appendix,
  364.                     0.1 * (int) (10. * lame_get_compression_ratio(gf) + 0.5),
  365.                     lame_get_quality(gf));
  366.         }
  367.  
  368.         if (silent <= -10)
  369.             lame_print_internals(gf);
  370.  
  371.         fflush(stderr);
  372.     }
  373.  
  374.  
  375.     /* encode until we hit eof */
  376.     do {
  377.         /* read in 'iread' samples */
  378.         iread = get_audio(gf, Buffer);
  379.         frames = lame_get_frameNum(gf);
  380.  
  381.  
  382.  /********************** status display  *****************************/
  383.         if (silent <= 0) {
  384.             if (update_interval > 0) {
  385.                 timestatus_klemm(gf);
  386.             }
  387.             else {
  388.                 if (0 == frames % 50) {
  389. #ifdef BRHIST
  390.                     brhist_jump_back();
  391. #endif
  392.                     timestatus(lame_get_out_samplerate(gf),
  393.                                frames,
  394.                                lame_get_totalframes(gf),
  395.                                lame_get_framesize(gf));
  396. #ifdef BRHIST
  397.                     if (brhist)
  398.                         brhist_disp(gf);
  399. #endif
  400.                 }
  401.             }
  402.         }
  403.  
  404.         /* encode */
  405.         imp3 = lame_encode_buffer_int(gf, Buffer[0], Buffer[1], iread,
  406.                                       mp3buffer, sizeof(mp3buffer));
  407.  
  408.         /* was our output buffer big enough? */
  409.         if (imp3 < 0) {
  410.             if (imp3 == -1)
  411.                 fprintf(stderr, "mp3 buffer is not big enough... \n");
  412.             else
  413.                 fprintf(stderr, "mp3 internal error:  error code=%i\n", imp3);
  414.             return 1;
  415.         }
  416.  
  417.         if (fwrite(mp3buffer, 1, imp3, outf) != imp3) {
  418.             fprintf(stderr, "Error writing mp3 output \n");
  419.             return 1;
  420.         }
  421.  
  422.     } while (iread);
  423.  
  424.     if (nogap) {
  425.         imp3 = lame_encode_flush_nogap(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */
  426.     /* reinitialize bitstream for next encoding.  this is normally done
  427.      * by lame_init_params(), but we cannot call that routine twice */ 
  428.     lame_init_bitstream(gf);
  429.     } else {
  430.         imp3 = lame_encode_flush(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */
  431.     }
  432.  
  433.     if (imp3 < 0) {
  434.         if (imp3 == -1)
  435.             fprintf(stderr, "mp3 buffer is not big enough... \n");
  436.         else
  437.             fprintf(stderr, "mp3 internal error:  error code=%i\n", imp3);
  438.         return 1;
  439.  
  440.     }
  441.  
  442.     if (silent <= 0) {
  443. #ifdef BRHIST
  444.         brhist_jump_back();
  445. #endif
  446.         timestatus(lame_get_out_samplerate(gf),
  447.                    frames, lame_get_totalframes(gf), lame_get_framesize(gf));
  448. #ifdef BRHIST
  449.         if (brhist) {
  450.             brhist_disp(gf);
  451.         }
  452.         brhist_disp_total(gf);
  453. #endif
  454.         timestatus_finish();
  455.     }
  456.  
  457.     fwrite(mp3buffer, 1, imp3, outf);
  458.  
  459.     return 0;
  460. }
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467. void
  468. brhist_init_package(lame_global_flags * gf)
  469. {
  470. #ifdef BRHIST
  471.     if (brhist) {
  472.         if (brhist_init
  473.             (gf, lame_get_VBR_min_bitrate_kbps(gf),
  474.              lame_get_VBR_max_bitrate_kbps(gf))) {
  475.             /* fail to initialize */
  476.             brhist = 0;
  477.         }
  478.     }
  479.     else {
  480.         brhist_init(gf, 128, 128); // Dirty hack
  481.     }
  482. #endif
  483. }
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491. int
  492. main(int argc, char **argv)
  493. {
  494.     int     ret;
  495.     lame_global_flags *gf;
  496.     char    outPath[MAX_NAME_SIZE];
  497.     char    inPath[MAX_NAME_SIZE];
  498. #define MAX_NOGAP 20
  499.     int     max_nogap = MAX_NOGAP;
  500.     char   *nogap_inPath[MAX_NOGAP];
  501.     int     i;
  502.     FILE   *outf;
  503.  
  504. #if macintosh
  505.     argc = ccommand(&argv);
  506. #endif
  507.     for (i = 0; i < max_nogap; ++i) {
  508.         nogap_inPath[i] = malloc(MAX_NAME_SIZE);
  509.     }
  510.  
  511.     /* initialize libmp3lame */
  512.     input_format = sf_unknown;
  513.     if (NULL == (gf = lame_init())) {
  514.         fprintf(stderr, "fatal error during initialization\n");
  515.         return 1;
  516.     }
  517.     if (argc <= 1) {
  518.         usage(gf, stderr, argv[0]); /* no command-line args, print usage, exit  */
  519.         return 1;
  520.     }
  521.  
  522.     /* parse the command line arguments, setting various flags in the
  523.      * struct 'gf'.  If you want to parse your own arguments,
  524.      * or call libmp3lame from a program which uses a GUI to set arguments,
  525.      * skip this call and set the values of interest in the gf struct.
  526.      * (see the file API and lame.h for documentation about these parameters)
  527.      */
  528.     parse_args_from_string(gf, getenv("LAMEOPT"), inPath, outPath);
  529.     ret = parse_args(gf, argc, argv, inPath, outPath, nogap_inPath, &max_nogap);
  530.     if (ret < 0)
  531.         return ret == -2 ? 0 : 1;
  532.  
  533.     if (update_interval < 0.)
  534.         update_interval = 2.;
  535.  
  536.     /* initialize input file.  This also sets samplerate and as much
  537.        other data on the input file as available in the headers */
  538.     if (max_nogap > 0) {
  539.         strncpy(outPath, nogap_inPath[0], MAX_NAME_SIZE - 4);
  540.         strncat(outPath, ".mp3", 4);
  541.         outf = init_files(gf, nogap_inPath[0], outPath);
  542.     }
  543.     else {
  544.         outf = init_files(gf, inPath, outPath);
  545.     }
  546.     if (outf == NULL) {
  547.         return -1;
  548.     }
  549.  
  550.     /* Now that all the options are set, lame needs to analyze them and
  551.      * set some more internal options and check for problems
  552.      */
  553.     i = lame_init_params(gf);
  554.     if (i < 0) {
  555.         if (i == -1) {
  556.             display_bitrates(stderr);
  557.         }
  558.         fprintf(stderr, "fatal error during initialization\n");
  559.         return i;
  560.     }
  561.  
  562.     if (silent > 0 || lame_get_VBR(gf) == vbr_off) {
  563.         brhist = 0;     /* turn off VBR histogram */
  564.     }
  565.  
  566.  
  567. #ifdef HAVE_VORBIS
  568.     if (lame_get_ogg(gf)) {
  569.         lame_encode_ogg_init(gf);
  570.         lame_set_VBR(gf, vbr_off); /* ignore lame's various VBR modes */
  571.     }
  572. #endif
  573.  
  574.  
  575.     if (lame_get_decode_only(gf)) {
  576.         /* decode an mp3 file to a .wav */
  577.         if (mp3_delay_set)
  578.             lame_decoder(gf, outf, mp3_delay, inPath, outPath);
  579.         else
  580.             lame_decoder(gf, outf, lame_get_encoder_delay(gf), inPath, outPath);
  581.  
  582.     }
  583.     else {
  584.         if (max_nogap > 0) {
  585.             for (i = 0; i < max_nogap; ++i) {
  586.                 int     use_flush_nogap = (i != (max_nogap - 1));
  587.                 if (i > 0) {
  588.                     strncpy(outPath, nogap_inPath[i], MAX_NAME_SIZE - 4);
  589.                     strncat(outPath, ".mp3", 4);
  590.                     /* note: if init_files changes anything, like
  591.                        samplerate, num_channels, etc, we are screwed */
  592.                     outf = init_files(gf, nogap_inPath[i], outPath);
  593.                 }
  594.                 brhist_init_package(gf);
  595.                 ret =
  596.                     lame_encoder(gf, outf, use_flush_nogap, nogap_inPath[i],
  597.                                  outPath);
  598.                 lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */
  599.                 fclose(outf); /* close the output file */
  600.                 close_infile(); /* close the input file */
  601.             }
  602.             lame_close(gf);
  603.  
  604.         }
  605.         else {
  606.             brhist_init_package(gf);
  607.             ret = lame_encoder(gf, outf, 0, inPath, outPath);
  608.             lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */
  609.             fclose(outf); /* close the output file */
  610.             close_infile(); /* close the input file */
  611.             lame_close(gf);
  612.         }
  613.     }
  614.     return ret;
  615. }
  616.