Independent SjPCM 2.1
Independent SjPCM 2.1
Based on a request by raizor, I've put together a version of SjPCM 2.1 which does NOT require libsd/freesd. Its a standalone module with spu2 code based on freesd source.
It requires the lastest ps2sdk cvs source to build and includes both ee and iop side code.
Its also possible to build the original SjPCM IRX by setting a define, but that and much more is documented in the readme, so I won't repeat myself here :)
The standalone version's size is about 8.31 kb when printfs aren't used :)
http://www.lukasz.dk/files/isjpcm-2.1.zip
Feedback is welcomed :)
It requires the lastest ps2sdk cvs source to build and includes both ee and iop side code.
Its also possible to build the original SjPCM IRX by setting a define, but that and much more is documented in the readme, so I won't repeat myself here :)
The standalone version's size is about 8.31 kb when printfs aren't used :)
http://www.lukasz.dk/files/isjpcm-2.1.zip
Feedback is welcomed :)
Last edited by Lukasz on Thu Aug 26, 2004 10:59 pm, edited 1 time in total.
Well, anyway: here is a small patch for this isjpcm thingy.
http://www.nobis-crew.org/isjpcm-callback.patch
It still keeps backward compatibility, and adds some new features, especially, callback, and buffer size. So, now, you have SjPCM_InitEx with a "num_blocks" argument (which SjPCM_Init defaults to 20, that is, 20 blocks of 960 samples), and SjPCM_SetCallback(threshold, callback), which sets up an EE callback which is called when there is at least "threshold" blocks available in the buffer. So, "typical" use could be:
Note that the callback is actually using the sif command 0x12. I am thinking about adding a piece of code into the ps2sdk in order to have multiple callbacks from IOP to EE multiplexed into a single sif command. Comments anyone ?
--edit--
Duh... sometime I feel dumb. The RPC system works both way... I'd better rework that out by installing a RPC server on the EE side, and using it as a callback thing.
http://www.nobis-crew.org/isjpcm-callback.patch
It still keeps backward compatibility, and adds some new features, especially, callback, and buffer size. So, now, you have SjPCM_InitEx with a "num_blocks" argument (which SjPCM_Init defaults to 20, that is, 20 blocks of 960 samples), and SjPCM_SetCallback(threshold, callback), which sets up an EE callback which is called when there is at least "threshold" blocks available in the buffer. So, "typical" use could be:
Code: Select all
void sound_init() {
SjPCM_InitEx(0, 12); // let's have a 12 blocks buffer.
SjPCM_Clearbuff();
SjPCM_Setvol(0x3fff);
SjPCM_SetCallback(2, sound_callback); // trigger the callback where there is at least 2 blocks available
// Sets up the sound_thread
}
void sound_callback(void) {
iWakeupThread(sound_thread_pid);
}
void sound_thread() {
int loops = 0, todo;
for (;;) {
SleepThread();
if (!(loops % 32)) {
// sometime, we might miss some callbacks, so, to avoid
// letting the core starving, let's feed it up completely
// from time to time.
todo = SjPCM_Available() / 960;
loops = 0;
} else {
// the rest of the time, let's just put what we know as the
// set threshold, sparing us some RPC.
todo = 2;
}
mix_up_some_sound(left, right, todo * 960);
SjPCM_Enqueue(left, right, todo * 960, 0);
loops++;
}
}
--edit--
Duh... sometime I feel dumb. The RPC system works both way... I'd better rework that out by installing a RPC server on the EE side, and using it as a callback thing.
pixel: A mischievous magical spirit associated with screen displays. The computer industry has frequently borrowed from mythology. Witness the sprites in computer graphics, the demons in artificial intelligence and the trolls in the marketing department.
You mean, creating a new module, right ? There's no iSjPCM module in CVS right now, huh ?
pixel: A mischievous magical spirit associated with screen displays. The computer industry has frequently borrowed from mythology. Witness the sprites in computer graphics, the demons in artificial intelligence and the trolls in the marketing department.
mrbrown: what raizor said, basicly demo people are obsessed with small sizes (...) which is why I did it. It's also a stripped version of freesd, only using block transfer, which is combined with SjPCM
pixel: No I didn't commit to cvs, dunno if you wanna commit it to ps2sdk since raizors ahx player is also in it. It was never my intention to commit it to cvs, just rather so show how to do a standalone spu2 module. But if you think its a good idea, go right ahead.
pixel: No I didn't commit to cvs, dunno if you wanna commit it to ps2sdk since raizors ahx player is also in it. It was never my intention to commit it to cvs, just rather so show how to do a standalone spu2 module. But if you think its a good idea, go right ahead.
well, while working on my different stuff, I also made a little modification to the original isjpcm to add some simple resampling code on the IOP side. I was tired to each time resample my buffer to 48Khz, and resampling it on the EE, first use some cpu cycles that I prefer to use for something else and second doesn't make sense (it's a job for the IOP).
Then I also removed freesd dependencies at compilation (just included a couple of defines in the source header).
the resampling algorithm is very basic (lazy guy, lazy code, but has the advantage of being fast) and is made based on the sample size passed to the SjPCM_Enqueue(..) function, BUT only works with the following sample size :
- 960 for 48Khz (PAL) > no resampling in this case
- 480 for 24Khz (PAL)
- 320 for 16Khz (PAL)
- 240 for 12Khz (PAL)
- 120 for 8Khz (PAL)
- 800 for 48Khz (NTSC) > no resampling in this case
- 400 for 24Khz (NTSC)
- 266 for 16Khz (NTSC)
- 200 for 12Khz (NTSC)
- 100 for 8Khz (NTSC)
I wanted first to add support for 11, 22 & 44Khz, but since It's a bit more tricky than 8Khz multiple frequency and since I don't have the time to work on it right now, I thought that it could already be usefull for someone. I'm currently using it in all my current works, and it's doing the job perfectly, and additional memory needed on the IOP is only 3840 bytes.
for those interested, you can find the updated code here :
neocd.ps2-scene.org/download/isjpcm2.2src.zip
I took the liberty to increase the version (now 2.2), but feel free to anybody to make whatever you want with it..
One more thing, with all theses changes, lukaz one with the original isjpcm, pixel with the callback and my 1 cent contribution, maybe adding it to cvs wouldn't be a bad thing.. uh ??
Then I also removed freesd dependencies at compilation (just included a couple of defines in the source header).
the resampling algorithm is very basic (lazy guy, lazy code, but has the advantage of being fast) and is made based on the sample size passed to the SjPCM_Enqueue(..) function, BUT only works with the following sample size :
- 960 for 48Khz (PAL) > no resampling in this case
- 480 for 24Khz (PAL)
- 320 for 16Khz (PAL)
- 240 for 12Khz (PAL)
- 120 for 8Khz (PAL)
- 800 for 48Khz (NTSC) > no resampling in this case
- 400 for 24Khz (NTSC)
- 266 for 16Khz (NTSC)
- 200 for 12Khz (NTSC)
- 100 for 8Khz (NTSC)
I wanted first to add support for 11, 22 & 44Khz, but since It's a bit more tricky than 8Khz multiple frequency and since I don't have the time to work on it right now, I thought that it could already be usefull for someone. I'm currently using it in all my current works, and it's doing the job perfectly, and additional memory needed on the IOP is only 3840 bytes.
for those interested, you can find the updated code here :
neocd.ps2-scene.org/download/isjpcm2.2src.zip
I took the liberty to increase the version (now 2.2), but feel free to anybody to make whatever you want with it..
One more thing, with all theses changes, lukaz one with the original isjpcm, pixel with the callback and my 1 cent contribution, maybe adding it to cvs wouldn't be a bad thing.. uh ??