#ifndef __AUDIO_H__
#define __AUDIO_H__
#define SECTOR_SIZE (2048)
#define RING_BUF_SIZE (2048*10)
#define PCM_ADDR ((void*)0x25a20000)
#define PCM_SIZE (4096*2)
#define SMP_1TASK_SAMPLE (1024)
#define SMP_TR_MODE_CD (PCM_TRMODE_CPU)
#define SMP_LOAD_NUM (10)
#define PCMRAM (631734272)
#define LWRAM (2097152)
#define HIMEM (100679680)
//(31122)
#define S4410KHZ (0)
#define S3780KHZ (31451)
//THIS IS TESTED
#define M3072KHZ (31118)
//
#define S2205KHZ (30720)
#define S1920KHZ (29431)
#define S18900HZ (29404)
#define S1600KHZ (29134)
#define S1536KHZ (29074)
#define S1100KHZ (27643)
#define S0800KHZ (27086)
extern jo_sound main_pcmfx;
extern jo_sound music_pcmfx;
//Functions go here
void pcm_music_play(void(*sysframe)(void));
void* load_pcm(Sint8* filename, const jo_sound_mode mode, jo_sound *sound, void * workAddress);
void sound_on_channel(jo_sound * const sound, const unsigned char channel);
#endif
//Modified Jo Engine functions
jo_sound music_pcmfx;
jo_sound main_pcmfx;
static PCM _pcm[JO_SOUND_MAX_CHANNEL] =
{
{(_Stereo | _PCM16Bit), 0, 127, 0, 0x0, 0, 0, 0, 0},
{(_Stereo | _PCM16Bit), 2, 127, 0, 0x0, 0, 0, 0, 0},
{(_Stereo | _PCM16Bit), 4, 127, 0, 0x0, 0, 0, 0, 0},
{(_Stereo | _PCM16Bit), 6, 127, 0, 0x0, 0, 0, 0, 0},
{(_Stereo | _PCM16Bit), 8, 127, 0, 0x0, 0, 0, 0, 0},
{(_Stereo | _PCM16Bit), 10, 127, 0, 0x0, 0, 0, 0, 0},
};
static Sint16 music_frames = 0;
static Sint16 music_sectors = 0;
void pcm_music_play(void(*sysframe)(void))
{
//DEBUG INFORMATION
Sint8* filename = "B.PCM";
music_pcmfx.mode = JoSoundMono16Bit;
//This function is supposed to play a mono PCM sound effect constantly.
//Some LWRAM is consumed in the process (10 sectors / 20KB).
void* pcm = LWRAM;
void* write_buffer = LWRAM;
Sint32 fid = GFS_NameToId(filename);
GfsHn gfsm = GFS_Open(fid);
Sint8 fetch_timer = 0;
Sint32 fsize;
Sint32 nsct;
Sint32 stat;
Sint32 rdsize;
//Rate of data reading
Sint16 rt_step = (2 * 2048);
Sint16 rt_sector = 2;
//Get sectors
//HEY! SBL DOCUMENTATION IS WRONG! THIRD ITEM nzect IS GFS SECTOR COUNT. SECOND ITEM IS CD SECTOR SIZE.
//TIP: MEMORY MUST BE MANAGED IN SECTORS (2KB)
GFS_GetFileSize(gfsm, NULL, &nsct, NULL);
GFS_GetFileInfo(gfsm, NULL, NULL, &fsize, NULL);
//This determines playback time?
music_pcmfx.data_length = (fsize);
_pcm[(int)0].mode = (Uint8)music_pcmfx.mode;
_pcm[(int)0].pitch = M3072KHZ;
//How many frames are we reading?
if(rt_step < fsize){
music_sectors = (fsize + (rt_step - 1))/(rt_step);
}
jo_printf(0, 18, "(%i)", fsize);
GFS_SetReadPara(gfsm, rt_step);
GFS_SetTransPara(gfsm, rt_sector);
GFS_SetTmode(gfsm, GFS_TMODE_CPU);
//Loading follows
GFS_NwCdRead(gfsm, (10 * 2048));
for( ; music_frames <= music_sectors ; ){
//Copy memory from work area buffer directly into the PCM stream buffer
slDMACopy(write_buffer, PCMRAM, (8 * 2048));
slDMAWait();
//Very tightly timed! Not even timed right! Saturn appears to playback sounds faster than advertised; check pitch?
fetch_timer++;
if(music_frames < 4){
GFS_NwFread(gfsm, rt_sector, write_buffer + (music_frames * rt_step), rt_step);
}
do{
sysframe();
slSynch();
if(music_frames < 4){
GFS_NwExecOne(gfsm);
GFS_NwGetStat(gfsm, &stat, &rdsize);
}
jo_printf(0, 7, "(%i)", music_frames);
jo_printf(7, 7, "(%i)", music_sectors);
jo_printf(0, 11, "(%i)", rdsize);
jo_printf(10, 11, "(fetched filesize)");
}while(stat != GFS_SVR_COMPLETED && rdsize < rt_step);
if(music_frames < 4){
music_frames++;
}
if(music_frames == 4 && fetch_timer == 8){
music_frames = 0; fetch_timer = 0;
}
slSndFlush();
music_pcmfx.data = pcm;
jo_printf(0, 0, "(%i)", pcm);
music_pcmfx.current_playing_channel = 0;
//HEY! slPCMOn does -NOT- accept changes to the data address during playback. IT WILL DO NOTHING.
slPCMOn(&_pcm[(int)0], music_pcmfx.data, music_pcmfx.data_length);
slPCMParmChange(&_pcm[(int)0]);
}
GFS_Close(gfsm);
}