1 // Modified by Francisco Mu�oz 'Hermes' MAY 2008
10 //#define _GCMOD_DEBUG
12 #define STACKSIZE 8192
13 #define SNDBUFFERSIZE (3840<<2) //that's the maximum buffer size for one VBlank we need.
15 static BOOL thr_running
= FALSE
;
16 static BOOL sndPlaying
= FALSE
;
17 static MODSNDBUF sndBuffer
;
19 static s32 have_samples
= 0;
20 static s32 mod_freq
= 48000;
22 static u32 shiftVal
= 0;
23 static vu32 curr_audio
= 0;
24 static u32 curr_datalen
[2] = {0,0};
25 static u8 audioBuf
[2][SNDBUFFERSIZE
] ATTRIBUTE_ALIGN(32);
27 static lwpq_t player_queue
;
29 static u8 player_stack
[STACKSIZE
];
30 static void* player(void *);
33 extern long long gettime();
34 extern u32
diff_usec(unsigned long long start
,unsigned long long end
);
35 extern u32
diff_msec(unsigned long long start
,unsigned long long end
);
38 static void* player(void *arg
)
45 while(sndPlaying
==TRUE
) {
46 LWP_ThreadSleep(player_queue
);
48 if(curr_datalen
[curr_audio
]>0 && sndPlaying
==TRUE
) {
50 printf("player(run callback)\n\n");
53 sndBuffer
.callback(sndBuffer
.usr_data
,((u8
*)audioBuf
[curr_audio
]),curr_datalen
[curr_audio
]);
57 printf("player(end callback,%d - %d us)\n\n",curr_audio
,diff_usec(start
,end
));
63 printf("player stopped %d\n",thr_running
);
68 static void dmaCallback()
71 MODPlay
*mp
= (MODPlay
*)sndBuffer
.usr_data
;
76 static long long start
= 0,end
= 0;
79 if(start
) printf("dmaCallback(%p,%d,%d - after %d ms)\n",(void*)audioBuf
[curr_audio
],curr_datalen
,curr_audio
,diff_msec(start
,end
));
84 AUDIO_InitDMA((u32
)audioBuf
[curr_audio
],curr_datalen
[curr_audio
]);
88 curr_datalen
[curr_audio
] = (mod
->samplespertick
<<shiftVal
);
89 LWP_ThreadSignal(player_queue
);
93 LWP_ThreadSignal(player_queue
);
96 if(have_samples
==1) return;
98 if(SND_AddVoice(0,audioBuf
[curr_audio
], curr_datalen
[curr_audio
])!=0) return; // Sorry I am busy: try again
100 curr_datalen
[curr_audio
]=0;
103 curr_datalen
[curr_audio
]=SNDBUFFERSIZE
;
109 printf("dmaCallback(%p,%d,%d,%d us) leave\n",(void*)audioBuf
[curr_audio
],curr_datalen
,curr_audio
,diff_usec(end
,start
));
113 static void mixCallback(void *usrdata
,u8
*stream
,u32 len
)
116 MODPlay
*mp
= (MODPlay
*)usrdata
;
119 printf("mixCallback(%p,%p,%d) enter\n",stream
,usrdata
,len
);
121 if(mp
->manual_polling
)
122 mod
->notify
= &mp
->paused
;
126 mod
->mixingbuf
= stream
;
127 mod
->mixingbuflen
= len
;
130 for(i
=0;i
<(len
>>1);i
++)
131 ((u16
*)stream
)[i
] = 0;
135 DCFlushRange(stream
,len
);
137 printf("mixCallback(%p,%p,%d,%d) leave\n",stream
,usrdata
,len
,mp
->paused
);
141 static s32
SndBufStart(MODSNDBUF
*sndbuf
)
143 if(sndPlaying
) return -1;
145 printf("SndBufStart(%p) enter\n",sndbuf
);
147 memcpy(&sndBuffer
,sndbuf
,sizeof(MODSNDBUF
));
150 if(sndBuffer
.chans
==2)
152 if(sndBuffer
.fmt
==16)
155 memset(audioBuf
[0],0,SNDBUFFERSIZE
);
156 memset(audioBuf
[1],0,SNDBUFFERSIZE
);
158 DCFlushRange(audioBuf
[0],SNDBUFFERSIZE
);
159 DCFlushRange(audioBuf
[1],SNDBUFFERSIZE
);
165 curr_datalen
[0] = SNDBUFFERSIZE
;
166 curr_datalen
[1] = SNDBUFFERSIZE
;
167 if(LWP_CreateThread(&hplayer
,player
,NULL
,player_stack
,STACKSIZE
,80)!=-1) {
169 AUDIO_RegisterDMACallback(dmaCallback
);
170 AUDIO_InitDMA((u32
)audioBuf
[curr_audio
],curr_datalen
[curr_audio
]);
174 SND_SetVoice(0, VOICE_STEREO_16BIT
, mod_freq
,0, audioBuf
[curr_audio
], curr_datalen
[curr_audio
], 255, 255, dmaCallback
);
187 static void SndBufStop()
189 if(!sndPlaying
) return;
192 AUDIO_RegisterDMACallback(NULL
);
200 LWP_ThreadSignal(player_queue
);
201 LWP_JoinThread(hplayer
,NULL
);
204 static s32
updateWaveFormat(MODPlay
*mod
)
206 BOOL p
= mod
->playing
;
212 mod
->soundBuf
.chans
= 2;
213 mod
->mod
.channels
= 2;
215 mod
->soundBuf
.chans
= 1;
216 mod
->mod
.channels
= 1;
219 mod
->soundBuf
.freq
= mod
->playfreq
;
220 mod
->mod
.freq
= mod
->playfreq
;
224 mod
->mod
.samplescounter
= 0;
225 mod
->mod
.samplespertick
= mod
->mod
.bpmtab
[mod
->mod
.bpm
-32];
228 mod
->soundBuf
.fmt
= 16;
229 mod
->soundBuf
.usr_data
= mod
;
230 mod
->soundBuf
.callback
= mixCallback
;
231 mod
->soundBuf
.samples
= (f32
)mod
->playfreq
/50.0F
;
234 SndBufStart(&mod
->soundBuf
);
239 void MODPlay_Init(MODPlay
*mod
)
241 memset(mod
,0,sizeof(MODPlay
));
249 MODPlay_SetFrequency(mod
,48000);
250 MODPlay_SetStereo(mod
,TRUE
);
252 LWP_InitQueue(&player_queue
);
259 mod
->numSFXChans
= 0;
260 mod
->manual_polling
= FALSE
;
263 s32
MODPlay_SetFrequency(MODPlay
*mod
,u32 freq
)
265 if(freq
==mod
->playfreq
) return 0;
266 if(freq
==32000 || freq
==48000) {
269 AUDIO_SetDSPSampleRate(AI_SAMPLERATE_32KHZ
);
271 AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ
);
275 mod
->playfreq
= freq
;
276 updateWaveFormat(mod
);
282 void MODPlay_SetStereo(MODPlay
*mod
,BOOL stereo
)
284 if(stereo
==mod
->stereo
) return;
286 mod
->stereo
= stereo
;
287 updateWaveFormat(mod
);
290 void MODPlay_Unload(MODPlay
*mod
)
296 s32
MODPlay_SetMOD(MODPlay
*mod
,const void *mem
)
300 if(MOD_SetMOD(&mod
->mod
,(u8
*)mem
)==0) {
301 MODPlay_AllocSFXChannels(mod
,mod
->numSFXChans
);
307 s32
MODPlay_Start(MODPlay
*mod
)
309 if(mod
->playing
) return -1;
310 if(mod
->mod
.modraw
==NULL
) return -1;
312 updateWaveFormat(mod
);
313 MOD_Start(&mod
->mod
);
314 if(SndBufStart(&mod
->soundBuf
)<0) return -1;
319 s32
MODPlay_Stop(MODPlay
*mod
)
321 if(!mod
->playing
) return -1;
324 mod
->playing
= FALSE
;
328 s32
MODPlay_AllocSFXChannels(MODPlay
*mod
,u32 sfxchans
)
330 if(mod
->mod
.modraw
==NULL
) return -1;
332 if(MOD_AllocSFXChannels(&mod
->mod
,sfxchans
)==0) {
333 mod
->numSFXChans
= sfxchans
;
339 s32
MODPlay_Pause(MODPlay
*mod
,BOOL pause
)
341 if(!mod
->playing
) return -1;
346 s32
MODPlay_TriggerNote(MODPlay
*mod
,u32 chan
,u8 inst
,u16 freq
,u8 vol
)
348 if(mod
->mod
.modraw
==0) return -1;
349 return MOD_TriggerNote(&mod
->mod
,chan
,inst
,freq
,vol
);
354 /* void MODPlay_SetVolume(MODPlay *mod, s32 musicvolume, s32 sfxvolume)
356 Set the volume levels for the MOD music (call it after MODPlay_SetMOD())
358 mod: the MODPlay pointer
360 musicvolume: in range 0 to 64
361 sfxvolume: in range 0 to 64
365 void MODPlay_SetVolume(MODPlay
*mod
, s32 musicvolume
, s32 sfxvolume
)
367 if(musicvolume
<0) musicvolume
=0;
368 if(musicvolume
>64) musicvolume
=64;
370 if(sfxvolume
<0) sfxvolume
=0;
371 if(sfxvolume
>64) sfxvolume
=64;
373 mod
->mod
.musicvolume
= musicvolume
;
374 mod
->mod
.sfxvolume
= sfxvolume
;