Sega Saturn Development > General Jo Engine Help

Why is this skipping?

(1/4) > >>

ponut64:
If anyone bothers to look at this, that's cool.

If you are someone who is particularly short on time / has better things to do (like XL2), best to move on, because I have been fumbling around with an interruptible PCM playback system for more than a month now (and there are already better solutions, but I'm stubborn).
I thought I had it good, and I do have working concepts, but I've come to the conclusion that I need a buffer to give the Saturn time to switch files in the case I want to load something while the music is playing. Otherwise, the music has to halt. I have no experience with this kind of thing...


--- Code: ---
#define PCMRAM (631734272)
#define LWRAM (2097152)
#define HIMEM (100679680)
//HIMEM has 376 sectors (752 KB)
#define HIEND (101449728)
//Each buffer is 8 sectors / 16 KB, a total of 32 sectors / 64 KB
#define PCMBUF1 (101433344)
#define PCMBUF2 (101416960)
#define PCMBUF3 (101400576)
#define PCMWORK (101384192)

//THIS IS TESTED
#define M3072KHZ     (31118)
//


--- End code ---


--- Code: ---
/**MUSIC SYSTEM SETUP**/

Sint8* music = "SCARE.AIFF";
TESTLOOP:
    music_pcmfx.mode = JoSoundMono16Bit;
//This function is supposed to play a mono PCM sound effect constantly.
//Some HIMEM is consumed in the process (32 sectors / 64KB at the END OF HIMEM)
Sint32 fid_m = GFS_NameToId(music);
music_fs = GFS_Open(fid_m);
Sint32 msize;
Sint32 nsct_m;
Sint32 stat;
Sint32 rdsize;

Sint32 nsct_f;
Sint32 fsize;
//GFS Error Information
Sint32 a_stat;
//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(music_fs, NULL, &nsct_m, NULL);
GFS_GetFileInfo(music_fs, NULL, NULL, &msize, NULL);
//This determines playback time?
music_pcmfx.data_length = (msize);
_pcm[(int)0].mode = (Uint8)music_pcmfx.mode;
_pcm[(int)0].pitch = M3072KHZ;
//How many frames are we reading?
if(rt_step < msize){
music_sectors = (msize + (rt_step - 1))/(rt_step);
}
jo_printf(0, 18, "(%i)", msize);

GFS_SetReadPara(music_fs, rt_step);
GFS_SetTransPara(music_fs, rt_sector);
//music_fs should be SCU type since it's going to high memory.
GFS_SetTmode(music_fs, GFS_TMODE_SCU);
//Seek music to the desired location
GFS_Seek(music_fs, play_ref, GFS_SEEK_SET);
//MUSIC loading follows
GFS_NwCdRead(music_fs, (20 * 2048));


//Let's make a pre-playback loop to read from the CD to fill a series of buffers using a work buffer.
for( ; buffers_filled < 3 ; ){
if(buffers_filled == 0){
rd_pcmbuf = PCMBUF1;
}
if(buffers_filled == 1){
rd_pcmbuf = PCMBUF2;
}
if(buffers_filled == 2){
rd_pcmbuf = PCMBUF3;
}
if(music_frames == 4){
slDMACopy(PCMWORK, rd_pcmbuf, (8 * 2048));
slDMAWait();
buffers_filled += 1;
music_frames = 0;
}
if(music_frames < 4){
music_frames++;
GFS_NwFread(music_fs, rt_sector, PCMWORK  + (music_frames * rt_step), rt_step);
play_ref += 2;
}
do{
// game_code();
slSynch();
if(music_frames < 4){
GFS_NwExecOne(music_fs);
GFS_NwGetStat(music_fs, &stat, &rdsize);
}
jo_printf(0, 20, "(27)");
jo_printf(0, 7, "(%i)", music_frames);
jo_printf(7, 7, "(%i)", play_ref);
jo_printf(0, 10, "(%i)", stat);
jo_printf(0, 11, "(%i)", fetch_timer);
jo_printf(10, 11, "(fetched filesize)");
}while(stat != GFS_SVR_COMPLETED && rdsize < rt_step);
jo_printf(0, 22, "(%i)", buffers_filled);
}
GFS_Close(music_fs);
//Let's then make a test loop to playback in sequence the three playback buffers that have been filled.
for( ; buffers_filled > 0 ; ){
// game_code();
slSynch();
jo_printf(0, 20, "(49)");
jo_printf(0, 11, "(%i)", fetch_timer);
jo_printf(0, 22, "(%i)", buffers_filled);

fetch_timer++;

if(fetch_timer == 8){
buffers_filled -= 1;
fetch_timer = 0;
}
if(buffers_filled == 0){
curpcmbuf = PCMBUF3;
}
if(buffers_filled == 1){
curpcmbuf = PCMBUF2;
}
if(buffers_filled == 2){
curpcmbuf = PCMBUF1;
}
slSndFlush();

music_pcmfx.data = curpcmbuf; //this line does not matter
music_pcmfx.current_playing_channel = 0;

slSoundRequest("bbbbwbb", SND_PCM_START, 0, 0, 631767039, (0), 0, 0, 0);

slPCMOn(&_pcm[(int)0], music_pcmfx.data, music_pcmfx.data_length);
slPCMParmChange(&_pcm[(int)0]);
}
//buffers_filled = 0;
goto TESTLOOP;

--- End code ---

Actual transfer into PCMRAM to play is handled at Vblank with an interrupt:


--- Code: ---
void my_vlank(void){
//A new music buffer system is needed.
//A filled-by-request buffer of 4x8 sectors, 32 sectors, 64 KB, at the end of high memory...
//A system managed .. how? The core issue is the file system slows down the entire Saturn, causing skipping.
//Tenets: GFS Seek has a variable completion time (but does not halt the system). GFS_Close does not complete immediately.
//Management of the buffer system must never close or re-open the music file, unless the buffer is completely full.
//Copy memory from work area buffer directly into the PCM stream buffer
slDMACopy(curpcmbuf, PCMRAM, (8 * 2048));
slDMAWait();
    slGouraudTblCopy();
}

--- End code ---

ponut64:
Yes, you can ignore this, I have other problems to solve but I am making progress.

SaturnTeam:
I wish I could help, but I don't know enough about that.

ponut64:
Don't worry, I appreciate you reading though.
Buffers are more complicated than I would have expected. Which is good, I'm in it for the challenge

ponut64:
Maybe someone can give this a listen if they know a lot about audio and tell what's going on.
I'm not certain...
https://youtu.be/BdOBkLl8jFg

Navigation

[0] Message Index

[#] Next page

Sitemap 1 2 3 4 5 6 7 8 9 10 
Go to full version