2 /* Ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */
4 #include <codecs/lib/codeclib.h>
5 #include "libgme/ay_emu.h"
9 /* Maximum number of bytes to process in one iteration */
10 #define CHUNK_SIZE (1024*2)
12 static int16_t samples
[CHUNK_SIZE
] IBSS_ATTR
;
13 static struct Ay_Emu ay_emu
;
15 /****************** rockbox interface ******************/
17 static void set_codec_track(int t
, int multitrack
) {
18 Ay_start_track(&ay_emu
, t
);
20 /* for loop mode we disable track limits */
21 if (!ci
->loop_track()) {
22 Track_set_fade(&ay_emu
, Track_get_length( &ay_emu
, t
) - 4000, 4000);
24 if (multitrack
) ci
->set_elapsed(t
*1000); /* t is track no to display */
25 else ci
->set_elapsed(0);
28 /* this is the codec entry point */
29 enum codec_status
codec_main(enum codec_entry_call_reason reason
)
31 if (reason
== CODEC_LOAD
) {
32 /* we only render 16 bits */
33 ci
->configure(DSP_SET_SAMPLE_DEPTH
, 16);
35 /* 44 Khz, Interleaved stereo */
36 ci
->configure(DSP_SET_FREQUENCY
, 44100);
37 ci
->configure(DSP_SET_STEREO_MODE
, STEREO_INTERLEAVED
);
40 Ay_set_sample_rate(&ay_emu
, 44100);
46 /* this is called for each file to process */
47 enum codec_status
codec_run(void)
52 int track
, is_multitrack
;
54 uint32_t elapsed_time
;
57 track
= is_multitrack
= 0;
60 DEBUGF("AY: next_track\n");
65 codec_set_replaygain(ci
->id3
);
67 /* Read the entire file */
68 DEBUGF("AY: request file\n");
70 buf
= ci
->request_buffer(&n
, ci
->filesize
);
71 if (!buf
|| n
< (size_t)ci
->filesize
) {
72 DEBUGF("AY: file load failed\n");
76 if ((err
= Ay_load_mem(&ay_emu
, buf
, ci
->filesize
))) {
77 DEBUGF("AY: Ay_load_mem failed (%s)\n", err
);
81 /* Update internal track count */
82 if (ay_emu
.m3u
.size
> 0)
83 ay_emu
.track_count
= ay_emu
.m3u
.size
;
85 /* Check if file has multiple tracks */
86 if (ay_emu
.track_count
> 1) {
91 set_codec_track(track
, is_multitrack
);
93 /* The main decoder loop */
95 enum codec_command_action action
= ci
->get_command(¶m
);
97 if (action
== CODEC_ACTION_HALT
)
100 if (action
== CODEC_ACTION_SEEK_TIME
) {
104 if (track
>= ay_emu
.track_count
) break;
108 ci
->set_elapsed(param
);
109 elapsed_time
= param
;
110 Track_seek(&ay_emu
, param
);
114 if (!ci
->loop_track()) {
115 Track_set_fade(&ay_emu
, Track_get_length( &ay_emu
, track
) - 4000, 4000);
119 /* Generate audio buffer */
120 err
= Ay_play(&ay_emu
, CHUNK_SIZE
, samples
);
121 if (err
|| Track_ended(&ay_emu
)) {
123 if (track
>= ay_emu
.track_count
) break;
127 ci
->pcmbuf_insert(samples
, NULL
, CHUNK_SIZE
>> 1);
129 /* Set elapsed time for one track files */
130 if (!is_multitrack
) {
131 elapsed_time
+= (CHUNK_SIZE
/ 2) * 10 / 441;
132 ci
->set_elapsed(elapsed_time
);