mpg123_to_out123.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. mpg123_to_wav.c
  3. copyright 2007-2016 by the mpg123 project - free software under the terms of the LGPL 2.1
  4. see COPYING and AUTHORS files in distribution or http://mpg123.org
  5. initially written by Nicholas Humfrey
  6. The most complicated part is about the choices to make about output format,
  7. and prepare for the unlikely case a bastard mp3 might file change it.
  8. */
  9. #include <out123.h>
  10. #include <mpg123.h>
  11. #include <stdio.h>
  12. #include <strings.h>
  13. void usage(const char *cmd)
  14. {
  15. printf("Usage: %s <input> [<driver> [<output> [encoding [buffersize]]]]\n"
  16. , cmd);
  17. printf( "\nPlay MPEG audio from intput file to output file/device using\n"
  18. "specified out123 driver, sample encoding and buffer size optional.\n\n" );
  19. exit(99);
  20. }
  21. void cleanup(mpg123_handle *mh, out123_handle *ao)
  22. {
  23. out123_del(ao);
  24. /* It's really to late for error checks here;-) */
  25. mpg123_close(mh);
  26. mpg123_delete(mh);
  27. mpg123_exit();
  28. }
  29. int main(int argc, char *argv[])
  30. {
  31. mpg123_handle *mh = NULL;
  32. out123_handle *ao = NULL;
  33. char *infile = NULL;
  34. char *driver = NULL;
  35. char *outfile = NULL;
  36. unsigned char* buffer = NULL;
  37. const char *encname;
  38. size_t buffer_size = 0;
  39. size_t done = 0;
  40. int channels = 0;
  41. int encoding = 0;
  42. int framesize = 1;
  43. long rate = 0;
  44. int err = MPG123_OK;
  45. off_t samples = 0;
  46. if(argc<2)
  47. usage(argv[0]);
  48. infile = argv[1];
  49. if(argc >= 3)
  50. driver = argv[2];
  51. if(argc >= 4)
  52. outfile = argv[3];
  53. printf("Input file: %s\n", infile);
  54. printf("Output driver: %s\n", driver ? driver : "<nil> (default)");
  55. printf("Output file: %s\n", outfile ? outfile : "<nil> (default)");
  56. err = mpg123_init();
  57. if(err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL)
  58. {
  59. fprintf(stderr, "Basic setup goes wrong: %s", mpg123_plain_strerror(err));
  60. cleanup(mh, ao);
  61. return -1;
  62. }
  63. ao = out123_new();
  64. if(!ao)
  65. {
  66. fprintf(stderr, "Cannot create output handle.\n");
  67. cleanup(mh, ao);
  68. return -1;
  69. }
  70. if(argc >= 5)
  71. { /* Make mpg123 support the desired encoding only for all rates. */
  72. const long *rates;
  73. size_t rate_count;
  74. size_t i;
  75. int enc;
  76. /* If that is zero, you'll get the error soon enough from mpg123. */
  77. enc = out123_enc_byname(argv[4]);
  78. mpg123_format_none(mh);
  79. mpg123_rates(&rates, &rate_count);
  80. for(i=0; i<rate_count; ++i)
  81. mpg123_format(mh, rates[i], MPG123_MONO|MPG123_STEREO, enc);
  82. }
  83. /* Let mpg123 work with the file, that excludes MPG123_NEED_MORE messages. */
  84. if( mpg123_open(mh, infile) != MPG123_OK
  85. /* Peek into track and get first output format. */
  86. || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK )
  87. {
  88. fprintf( stderr, "Trouble with mpg123: %s\n", mpg123_strerror(mh) );
  89. cleanup(mh, ao);
  90. return -1;
  91. }
  92. if(out123_open(ao, driver, outfile) != OUT123_OK)
  93. {
  94. fprintf(stderr, "Trouble with out123: %s\n", out123_strerror(ao));
  95. cleanup(mh, ao);
  96. return -1;
  97. }
  98. /* It makes no sense for that to give an error now. */
  99. out123_driver_info(ao, &driver, &outfile);
  100. printf("Effective output driver: %s\n", driver ? driver : "<nil> (default)");
  101. printf("Effective output file: %s\n", outfile ? outfile : "<nil> (default)");
  102. /* Ensure that this output format will not change
  103. (it might, when we allow it). */
  104. mpg123_format_none(mh);
  105. mpg123_format(mh, rate, channels, encoding);
  106. encname = out123_enc_name(encoding);
  107. printf( "Playing with %i channels and %li Hz, encoding %s.\n"
  108. , channels, rate, encname ? encname : "???" );
  109. if( out123_start(ao, rate, channels, encoding)
  110. || out123_getformat(ao, NULL, NULL, NULL, &framesize) )
  111. {
  112. fprintf(stderr, "Cannot start output / get framesize: %s\n"
  113. , out123_strerror(ao));
  114. cleanup(mh, ao);
  115. return -1;
  116. }
  117. /* Buffer could be almost any size here, mpg123_outblock() is just some
  118. recommendation. The size should be a multiple of the PCM frame size. */
  119. buffer_size = argc >= 6 ? atol(argv[5]) : mpg123_outblock(mh);
  120. buffer = malloc( buffer_size );
  121. do
  122. {
  123. size_t played;
  124. err = mpg123_read( mh, buffer, buffer_size, &done );
  125. played = out123_play(ao, buffer, done);
  126. if(played != done)
  127. {
  128. fprintf(stderr
  129. , "Warning: written less than gotten from libmpg123: %li != %li\n"
  130. , (long)played, (long)done);
  131. }
  132. samples += played/framesize;
  133. /* We are not in feeder mode, so MPG123_OK, MPG123_ERR and
  134. MPG123_NEW_FORMAT are the only possibilities.
  135. We do not handle a new format, MPG123_DONE is the end... so
  136. abort on anything not MPG123_OK. */
  137. } while (done && err==MPG123_OK);
  138. free(buffer);
  139. if(err != MPG123_DONE)
  140. fprintf( stderr, "Warning: Decoding ended prematurely because: %s\n",
  141. err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err) );
  142. printf("%li samples written.\n", (long)samples);
  143. cleanup(mh, ao);
  144. return 0;
  145. }