mp3test.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/mman.h>
  6. #include <sys/ioctl.h>
  7. #include <sys/time.h>
  8. #include <fcntl.h>
  9. #include <errno.h>
  10. #include "940shared.h"
  11. #include "../gp2x.h"
  12. //#include "emu.h"
  13. //#include "menu.h"
  14. #include "../asmutils.h"
  15. #include <platform/common/helix/pub/mp3dec.h>
  16. /* we will need some gp2x internals here */
  17. extern volatile unsigned short *gp2x_memregs; /* from minimal library rlyeh */
  18. extern volatile unsigned long *gp2x_memregl;
  19. static unsigned char *shared_mem = 0;
  20. static _940_data_t *shared_data = 0;
  21. static _940_ctl_t *shared_ctl = 0;
  22. static unsigned char *mp3_mem = 0;
  23. #define MP3_SIZE_MAX (0x1000000 - 4*640*480)
  24. int crashed_940 = 0;
  25. /***********************************************************/
  26. #define MAXOUT (+32767)
  27. #define MINOUT (-32768)
  28. /* limitter */
  29. #define Limit(val, max,min) { \
  30. if ( val > max ) val = max; \
  31. else if ( val < min ) val = min; \
  32. }
  33. void wait_busy_940(void)
  34. {
  35. int i;
  36. #if 0
  37. printf("940 busy, entering wait loop.. (cnt: %i, wc: %i, ve: ", shared_ctl->loopc, shared_ctl->waitc);
  38. for (i = 0; i < 8; i++)
  39. printf("%i ", shared_ctl->vstarts[i]);
  40. printf(")\n");
  41. for (i = 0; shared_ctl->busy; i++)
  42. {
  43. spend_cycles(1024); /* needs tuning */
  44. }
  45. printf("wait iterations: %i\n", i);
  46. #else
  47. for (i = 0; shared_ctl->busy && i < 0x10000; i++)
  48. spend_cycles(8*1024);
  49. if (i < 0x10000) return;
  50. /* 940 crashed */
  51. printf("940 crashed (cnt: %i, ve: ", shared_ctl->loopc);
  52. for (i = 0; i < 8; i++)
  53. printf("%i ", shared_ctl->vstarts[i]);
  54. printf(")\n");
  55. crashed_940 = 1;
  56. #endif
  57. }
  58. void add_job_940(int job0, int job1)
  59. {
  60. shared_ctl->jobs[0] = job0;
  61. shared_ctl->jobs[1] = job1;
  62. shared_ctl->busy = 1;
  63. gp2x_memregs[0x3B3E>>1] = 0xffff; // cause an IRQ for 940
  64. }
  65. static int read_to_upper(void *dest, void *tmpbuf, int tmpsize, FILE *f)
  66. {
  67. int nRead, nLen = 0;
  68. while(1)
  69. {
  70. nRead = fread(tmpbuf, 1, tmpsize, f);
  71. if(nRead <= 0)
  72. break;
  73. memcpy((unsigned char *)dest + nLen, tmpbuf, nRead);
  74. nLen += nRead;
  75. }
  76. return nLen;
  77. }
  78. static void simpleWait(int thissec, int lim_time)
  79. {
  80. struct timeval tval;
  81. spend_cycles(1024);
  82. gettimeofday(&tval, 0);
  83. if(thissec != tval.tv_sec) tval.tv_usec+=1000000;
  84. while(tval.tv_usec < lim_time)
  85. {
  86. spend_cycles(1024);
  87. gettimeofday(&tval, 0);
  88. if(thissec != tval.tv_sec) tval.tv_usec+=1000000;
  89. }
  90. }
  91. char **g_argv;
  92. /* none of the functions in this file should be called before this one */
  93. void YM2612Init_940(int baseclock, int rate)
  94. {
  95. printf("YM2612Init_940()\n");
  96. printf("Mem usage: shared_data: %i, shared_ctl: %i\n", sizeof(*shared_data), sizeof(*shared_ctl));
  97. Reset940(1, 2);
  98. Pause940(1);
  99. gp2x_memregs[0x3B46>>1] = 0xffff; // clear pending DUALCPU interrupts for 940
  100. gp2x_memregs[0x3B42>>1] = 0xffff; // enable DUALCPU interrupts for 940
  101. gp2x_memregl[0x4508>>2] = ~(1<<26); // unmask DUALCPU ints in the undocumented 940's interrupt controller
  102. if (shared_mem == NULL)
  103. {
  104. shared_mem = (unsigned char *) mmap(0, 0x210000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0x2000000);
  105. if(shared_mem == MAP_FAILED)
  106. {
  107. printf("mmap(shared_data) failed with %i\n", errno);
  108. exit(1);
  109. }
  110. shared_data = (_940_data_t *) (shared_mem+0x100000);
  111. /* this area must not get buffered on either side */
  112. shared_ctl = (_940_ctl_t *) (shared_mem+0x200000);
  113. mp3_mem = (unsigned char *) mmap(0, MP3_SIZE_MAX, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0x3000000);
  114. if (mp3_mem == MAP_FAILED)
  115. {
  116. printf("mmap(mp3_mem) failed with %i\n", errno);
  117. exit(1);
  118. }
  119. crashed_940 = 1;
  120. }
  121. if (crashed_940)
  122. {
  123. unsigned char ucData[1024];
  124. int i;
  125. char binpath[1024];
  126. FILE *fp;
  127. strncpy(binpath, g_argv[0], 1023);
  128. binpath[1023] = 0;
  129. for (i = strlen(binpath); i > 0; i--)
  130. if (binpath[i] == '/') { binpath[i] = 0; break; }
  131. strcat(binpath, "/code940.bin");
  132. fp = fopen(binpath, "rb");
  133. if(!fp)
  134. {
  135. printf("failed to open %s\n", binpath);
  136. exit(1);
  137. }
  138. read_to_upper(shared_mem, ucData, sizeof(ucData), fp);
  139. fclose(fp);
  140. crashed_940 = 0;
  141. }
  142. memset(shared_data, 0, sizeof(*shared_data));
  143. memset(shared_ctl, 0, sizeof(*shared_ctl));
  144. /* now cause 940 to init it's ym2612 stuff */
  145. shared_ctl->baseclock = baseclock;
  146. shared_ctl->rate = rate;
  147. shared_ctl->jobs[0] = JOB940_INITALL;
  148. shared_ctl->jobs[1] = 0;
  149. shared_ctl->busy = 1;
  150. /* start the 940 */
  151. Reset940(0, 2);
  152. Pause940(0);
  153. }
  154. unsigned char *mp3_data = 0;
  155. void local_decode(void)
  156. {
  157. int mp3_offs = shared_ctl->mp3_offs;
  158. unsigned char *readPtr = mp3_data + mp3_offs;
  159. int bytesLeft = shared_ctl->mp3_len - mp3_offs;
  160. int offset; // frame offset from readPtr
  161. int err = 0;
  162. if (bytesLeft <= 0) return; // EOF, nothing to do
  163. offset = MP3FindSyncWord(readPtr, bytesLeft);
  164. if (offset < 0) {
  165. shared_ctl->mp3_offs = shared_ctl->mp3_len;
  166. return; // EOF
  167. }
  168. readPtr += offset;
  169. bytesLeft -= offset;
  170. err = MP3Decode(shared_data->mp3dec, &readPtr, &bytesLeft,
  171. shared_data->mp3_buffer[shared_ctl->mp3_buffsel], 0);
  172. if (err) {
  173. if (err == ERR_MP3_INDATA_UNDERFLOW) {
  174. shared_ctl->mp3_offs = shared_ctl->mp3_len; // EOF
  175. return;
  176. } else if (err <= -6 && err >= -12) {
  177. // ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_*
  178. // just try to skip the offending frame..
  179. readPtr++;
  180. }
  181. shared_ctl->mp3_errors++;
  182. shared_ctl->mp3_lasterr = err;
  183. }
  184. shared_ctl->mp3_offs = readPtr - mp3_data;
  185. }
  186. void gp2x_sound_sync(void);
  187. #define USE_LOCAL 0
  188. #define BENCHMARK 0
  189. int main(int argc, char *argv[])
  190. {
  191. FILE *f;
  192. int size;
  193. struct timeval tval; // timing
  194. int thissec = 0, fps = 0;
  195. int target_frametime, frame_samples, samples_ready, mp3_buffer_offs, play_bufsel;
  196. unsigned char play_buffer[44100/50*2*2];
  197. if (argc != 2) {
  198. printf("usage: %s <mp3file>\n", argv[0]);
  199. return 1;
  200. }
  201. g_argv = argv;
  202. gp2x_init();
  203. YM2612Init_940(123, 44100);
  204. // load a mp3
  205. f = fopen(argv[1], "rb");
  206. if (!f) {
  207. printf("can't open %s\n", argv[1]);
  208. return 1;
  209. }
  210. fseek(f, 0, SEEK_END);
  211. size = (int) ftell(f);
  212. if (size > MP3_SIZE_MAX) {
  213. printf("size %i > %i\n", size, MP3_SIZE_MAX);
  214. size = MP3_SIZE_MAX;
  215. }
  216. fseek(f, 0, SEEK_SET);
  217. if (fread(mp3_mem, 1, size, f) != size) {
  218. printf("read failed, errno=%i\n", errno);
  219. fclose(f);
  220. exit(1);
  221. }
  222. fclose(f);
  223. shared_ctl->mp3_len = size;
  224. #if USE_LOCAL
  225. shared_data->mp3dec = MP3InitDecoder();
  226. mp3_data = malloc(size);
  227. printf("init: dec: %p ptr: %p\n", shared_data->mp3dec, mp3_data);
  228. if (!mp3_data) {
  229. printf("low mem\n");
  230. exit(1);
  231. }
  232. memcpy(mp3_data, mp3_mem, size);
  233. #else
  234. //printf("YM2612UpdateOne_940()\n");
  235. if (shared_ctl->busy) wait_busy_940();
  236. #endif
  237. gp2x_start_sound(44100, 16, 1);
  238. #define DESIRED_FPS 50
  239. target_frametime = 1000000/DESIRED_FPS;
  240. frame_samples = 44100/DESIRED_FPS;
  241. samples_ready = mp3_buffer_offs = 0;
  242. play_bufsel = 1;
  243. for (;; fps++)
  244. {
  245. int lim_time;
  246. gettimeofday(&tval, 0);
  247. if (tval.tv_sec != thissec)
  248. {
  249. printf("fps: %i\n", fps);
  250. thissec = tval.tv_sec;
  251. fps = 0;
  252. #if BENCHMARK
  253. shared_ctl->mp3_offs = 0;
  254. #endif
  255. }
  256. #if 0
  257. // decode
  258. #if USE_LOCAL
  259. shared_ctl->mp3_buffsel ^= 1;
  260. local_decode();
  261. #else
  262. wait_busy_940();
  263. shared_ctl->mp3_buffsel ^= 1;
  264. add_job_940(JOB940_MP3DECODE, 0);
  265. #endif
  266. if (shared_ctl->mp3_lasterr) {
  267. printf("mp3_lasterr #%i: %i size: %i offs: %i\n", shared_ctl->mp3_errors, shared_ctl->mp3_lasterr,
  268. shared_ctl->mp3_len, shared_ctl->mp3_offs);
  269. printf("loopc: %i bytes: %08x\n",
  270. shared_ctl->loopc, *(int *)(mp3_mem+shared_ctl->mp3_offs));
  271. shared_ctl->mp3_lasterr = 0;
  272. }
  273. #if !BENCHMARK
  274. // play
  275. gp2x_sound_sync();
  276. gp2x_sound_write(shared_data->mp3_buffer[shared_ctl->mp3_buffsel^1], 1152*2*2);
  277. #endif
  278. #else
  279. lim_time = (fps+1) * target_frametime;
  280. wait_busy_940();
  281. // decode, play
  282. if (samples_ready >= frame_samples) {
  283. if (1152 - mp3_buffer_offs >= frame_samples) {
  284. memcpy(play_buffer, shared_data->mp3_buffer[play_bufsel] + mp3_buffer_offs*2,
  285. frame_samples*2*2);
  286. mp3_buffer_offs += frame_samples;
  287. } else {
  288. // collect from both buffers..
  289. int left = 1152 - mp3_buffer_offs;
  290. memcpy(play_buffer, shared_data->mp3_buffer[play_bufsel] + mp3_buffer_offs*2,
  291. left*2*2);
  292. play_bufsel ^= 1;
  293. mp3_buffer_offs = frame_samples - left;
  294. memcpy(play_buffer + left*2*2, shared_data->mp3_buffer[play_bufsel],
  295. mp3_buffer_offs*2*2);
  296. }
  297. gp2x_sound_write(play_buffer, frame_samples*2*2);
  298. samples_ready -= frame_samples;
  299. }
  300. // make sure we will have enough samples next frame
  301. if (samples_ready < frame_samples) {
  302. // wait_busy_940();
  303. shared_ctl->mp3_buffsel ^= 1;
  304. add_job_940(JOB940_MP3DECODE, 0);
  305. samples_ready += 1152;
  306. }
  307. gettimeofday(&tval, 0);
  308. if(thissec != tval.tv_sec) tval.tv_usec+=1000000;
  309. if(tval.tv_usec < lim_time)
  310. {
  311. // we are too fast
  312. simpleWait(thissec, lim_time);
  313. }
  314. #endif
  315. }
  316. return 0;
  317. }