feedseek.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. feedseek: test program for libmpg123, showing how to use fuzzy seeking in feeder mode
  3. copyright 2008 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. */
  6. #include <mpg123.h>
  7. #include <stdio.h>
  8. #define INBUFF 16384 * 2 * 2
  9. #define WAVE_FORMAT_PCM 0x0001
  10. #define WAVE_FORMAT_IEEE_FLOAT 0x0003
  11. FILE *out;
  12. size_t totaloffset, dataoffset;
  13. long rate;
  14. int channels, enc;
  15. unsigned short bitspersample, wavformat;
  16. // write wav header
  17. void initwav()
  18. {
  19. unsigned int tmp32 = 0;
  20. unsigned short tmp16 = 0;
  21. fwrite("RIFF", 1, 4, out);
  22. totaloffset = ftell(out);
  23. fwrite(&tmp32, 1, 4, out); // total size
  24. fwrite("WAVE", 1, 4, out);
  25. fwrite("fmt ", 1, 4, out);
  26. tmp32 = 16;
  27. fwrite(&tmp32, 1, 4, out); // format length
  28. tmp16 = wavformat;
  29. fwrite(&tmp16, 1, 2, out); // format
  30. tmp16 = channels;
  31. fwrite(&tmp16, 1, 2, out); // channels
  32. tmp32 = rate;
  33. fwrite(&tmp32, 1, 4, out); // sample rate
  34. tmp32 = rate * bitspersample/8 * channels;
  35. fwrite(&tmp32, 1, 4, out); // bytes / second
  36. tmp16 = bitspersample/8 * channels; // float 16 or signed int 16
  37. fwrite(&tmp16, 1, 2, out); // block align
  38. tmp16 = bitspersample;
  39. fwrite(&tmp16, 1, 2, out); // bits per sample
  40. fwrite("data ", 1, 4, out);
  41. tmp32 = 0;
  42. dataoffset = ftell(out);
  43. fwrite(&tmp32, 1, 4, out); // data length
  44. }
  45. // rewrite wav header with final length infos
  46. void closewav()
  47. {
  48. unsigned int tmp32 = 0;
  49. unsigned short tmp16 = 0;
  50. long total = ftell(out);
  51. fseek(out, totaloffset, SEEK_SET);
  52. tmp32 = total - (totaloffset + 4);
  53. fwrite(&tmp32, 1, 4, out);
  54. fseek(out, dataoffset, SEEK_SET);
  55. tmp32 = total - (dataoffset + 4);
  56. fwrite(&tmp32, 1, 4, out);
  57. }
  58. // determine correct wav format and bits per sample
  59. // from mpg123 enc value
  60. void initwavformat()
  61. {
  62. if(enc & MPG123_ENC_FLOAT_64)
  63. {
  64. bitspersample = 64;
  65. wavformat = WAVE_FORMAT_IEEE_FLOAT;
  66. }
  67. else if(enc & MPG123_ENC_FLOAT_32)
  68. {
  69. bitspersample = 32;
  70. wavformat = WAVE_FORMAT_IEEE_FLOAT;
  71. }
  72. else if(enc & MPG123_ENC_16)
  73. {
  74. bitspersample = 16;
  75. wavformat = WAVE_FORMAT_PCM;
  76. }
  77. else
  78. {
  79. bitspersample = 8;
  80. wavformat = WAVE_FORMAT_PCM;
  81. }
  82. }
  83. int main(int argc, char **argv)
  84. {
  85. unsigned char buf[INBUFF];
  86. unsigned char *audio;
  87. FILE *in;
  88. mpg123_handle *m;
  89. int ret, state;
  90. size_t inc, outc;
  91. off_t len, num;
  92. size_t bytes;
  93. off_t inoffset;
  94. inc = outc = 0;
  95. if(argc < 3)
  96. {
  97. fprintf(stderr,"Please supply in and out filenames\n");
  98. return -1;
  99. }
  100. mpg123_init();
  101. m = mpg123_new(NULL, &ret);
  102. if(m == NULL)
  103. {
  104. fprintf(stderr,"Unable to create mpg123 handle: %s\n", mpg123_plain_strerror(ret));
  105. return -1;
  106. }
  107. mpg123_param(m, MPG123_VERBOSE, 2, 0);
  108. ret = mpg123_param(m, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0);
  109. if(ret != MPG123_OK)
  110. {
  111. fprintf(stderr,"Unable to set library options: %s\n", mpg123_plain_strerror(ret));
  112. return -1;
  113. }
  114. // Let the seek index auto-grow and contain an entry for every frame
  115. ret = mpg123_param(m, MPG123_INDEX_SIZE, -1, 0);
  116. if(ret != MPG123_OK)
  117. {
  118. fprintf(stderr,"Unable to set index size: %s\n", mpg123_plain_strerror(ret));
  119. return -1;
  120. }
  121. ret = mpg123_format_none(m);
  122. if(ret != MPG123_OK)
  123. {
  124. fprintf(stderr,"Unable to disable all output formats: %s\n", mpg123_plain_strerror(ret));
  125. return -1;
  126. }
  127. // Use float output
  128. ret = mpg123_format(m, 44100, MPG123_MONO | MPG123_STEREO, MPG123_ENC_FLOAT_32);
  129. if(ret != MPG123_OK)
  130. {
  131. fprintf(stderr,"Unable to set float output formats: %s\n", mpg123_plain_strerror(ret));
  132. return -1;
  133. }
  134. ret = mpg123_open_feed(m);
  135. if(ret != MPG123_OK)
  136. {
  137. fprintf(stderr,"Unable open feed: %s\n", mpg123_plain_strerror(ret));
  138. return -1;
  139. }
  140. in = fopen(argv[1], "rb");
  141. if(in == NULL)
  142. {
  143. fprintf(stderr,"Unable to open input file %s\n", argv[1]);
  144. return -1;
  145. }
  146. out = fopen(argv[2], "wb");
  147. if(out == NULL)
  148. {
  149. fclose(in);
  150. fprintf(stderr,"Unable to open output file %s\n", argv[2]);
  151. return -1;
  152. }
  153. fprintf(stderr, "Seeking...\n");
  154. /* That condition is tricky... parentheses are crucial... */
  155. while((ret = mpg123_feedseek(m, 95000, SEEK_SET, &inoffset)) == MPG123_NEED_MORE)
  156. {
  157. len = fread(buf, sizeof(unsigned char), INBUFF, in);
  158. if(len <= 0)
  159. break;
  160. inc += len;
  161. state = mpg123_feed(m, buf, len);
  162. if(state == MPG123_ERR)
  163. {
  164. fprintf(stderr, "Error: %s", mpg123_strerror(m));
  165. return -1;
  166. }
  167. }
  168. if(ret == MPG123_ERR)
  169. {
  170. fprintf(stderr, "Feedseek failed: %s\n", mpg123_strerror(m));
  171. return -1;
  172. }
  173. fseek(in, inoffset, SEEK_SET);
  174. fprintf(stderr, "Starting decode...\n");
  175. while(1)
  176. {
  177. len = fread(buf, sizeof(unsigned char), INBUFF, in);
  178. if(len <= 0)
  179. break;
  180. inc += len;
  181. ret = mpg123_feed(m, buf, len);
  182. while(ret != MPG123_ERR && ret != MPG123_NEED_MORE)
  183. {
  184. ret = mpg123_decode_frame(m, &num, &audio, &bytes);
  185. if(ret == MPG123_NEW_FORMAT)
  186. {
  187. mpg123_getformat(m, &rate, &channels, &enc);
  188. initwavformat();
  189. initwav();
  190. fprintf(stderr, "New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
  191. }
  192. fwrite(audio, sizeof(unsigned char), bytes, out);
  193. outc += bytes;
  194. }
  195. if(ret == MPG123_ERR)
  196. {
  197. fprintf(stderr, "Error: %s", mpg123_strerror(m));
  198. break;
  199. }
  200. }
  201. fprintf(stderr, "Finished\n", (unsigned long)inc, (unsigned long)outc);
  202. closewav();
  203. fclose(out);
  204. fclose(in);
  205. mpg123_delete(m);
  206. mpg123_exit();
  207. return 0;
  208. }