lame_main.c 21 KB

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