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