cff531af |
1 | /* |
2 | * Some mp3 related code for Sega/Mega CD. |
3 | * Uses the Helix Fixed-point MP3 decoder |
4 | * (C) notaz, 2007-2009 |
5 | * |
6 | * This work is licensed under the terms of MAME license. |
7 | * See COPYING file in the top-level directory. |
8 | */ |
da42200b |
9 | |
10 | #include <stdio.h> |
11 | #include <string.h> |
12 | |
7c34867a |
13 | #include <pico/pico_int.h> |
14 | #include <pico/sound/mix.h> |
da42200b |
15 | #include "helix/pub/mp3dec.h" |
7c34867a |
16 | #include "mp3.h" |
da42200b |
17 | #include "lprintf.h" |
18 | |
fc11dd05 |
19 | static HMP3Decoder mp3dec; |
20 | static unsigned char mp3_input_buffer[2 * 1024]; |
da42200b |
21 | |
7c34867a |
22 | #ifdef __GP2X__ |
23 | #define mp3_update mp3_update_local |
24 | #define mp3_start_play mp3_start_play_local |
25 | #endif |
da42200b |
26 | |
fc11dd05 |
27 | int mp3dec_decode(FILE *f, int *file_pos, int file_len) |
da42200b |
28 | { |
29 | unsigned char *readPtr; |
30 | int bytesLeft; |
31 | int offset; // mp3 frame offset from readPtr |
7c34867a |
32 | int had_err; |
33 | int err = 0; |
da42200b |
34 | |
35 | do |
36 | { |
fc11dd05 |
37 | if (*file_pos >= file_len) |
7c34867a |
38 | return 1; /* EOF, nothing to do */ |
da42200b |
39 | |
fc11dd05 |
40 | fseek(f, *file_pos, SEEK_SET); |
41 | bytesLeft = fread(mp3_input_buffer, 1, sizeof(mp3_input_buffer), f); |
da42200b |
42 | |
7c18e34a |
43 | offset = mp3_find_sync_word(mp3_input_buffer, bytesLeft); |
da42200b |
44 | if (offset < 0) { |
fc11dd05 |
45 | lprintf("find_sync_word (%i/%i) err %i\n", |
46 | *file_pos, file_len, offset); |
47 | *file_pos = file_len; |
da42200b |
48 | return 1; // EOF |
49 | } |
50 | readPtr = mp3_input_buffer + offset; |
51 | bytesLeft -= offset; |
52 | |
7c34867a |
53 | had_err = err; |
c9e1affc |
54 | err = MP3Decode(mp3dec, &readPtr, &bytesLeft, cdda_out_buffer, 0); |
da42200b |
55 | if (err) { |
7c34867a |
56 | if (err == ERR_MP3_MAINDATA_UNDERFLOW && !had_err) { |
57 | // just need another frame |
fc11dd05 |
58 | *file_pos += readPtr - mp3_input_buffer; |
7c34867a |
59 | continue; |
60 | } |
61 | if (err == ERR_MP3_INDATA_UNDERFLOW && !had_err) { |
da42200b |
62 | if (offset == 0) |
63 | // something's really wrong here, frame had to fit |
fc11dd05 |
64 | *file_pos = file_len; |
da42200b |
65 | else |
fc11dd05 |
66 | *file_pos += offset; |
da42200b |
67 | continue; |
7c34867a |
68 | } |
69 | if (-12 <= err && err <= -6) { |
da42200b |
70 | // ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_* |
71 | // just try to skip the offending frame.. |
fc11dd05 |
72 | *file_pos += offset + 1; |
da42200b |
73 | continue; |
74 | } |
fc11dd05 |
75 | lprintf("MP3Decode err (%i/%i) %i\n", |
76 | *file_pos, file_len, err); |
77 | *file_pos = file_len; |
da42200b |
78 | return 1; |
79 | } |
fc11dd05 |
80 | *file_pos += readPtr - mp3_input_buffer; |
da42200b |
81 | } |
82 | while (0); |
83 | |
84 | return 0; |
85 | } |
86 | |
75a30842 |
87 | int mp3dec_start(FILE *f, int fpos_start) |
da42200b |
88 | { |
7c34867a |
89 | // must re-init decoder for new track |
90 | if (mp3dec) |
91 | MP3FreeDecoder(mp3dec); |
92 | mp3dec = MP3InitDecoder(); |
da42200b |
93 | |
fc11dd05 |
94 | return (mp3dec == 0) ? -1 : 0; |
da42200b |
95 | } |