Page 1 of 1

Independent SjPCM 2.1

Posted: Thu Aug 26, 2004 7:14 pm
by Lukasz
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 :)

Posted: Thu Aug 26, 2004 7:24 pm
by Raizor
r0x0r

Posted: Thu Aug 26, 2004 11:52 pm
by ooPo
You didn't just embed a copy of libsd into sjpcm, did you? :)

Posted: Fri Aug 27, 2004 3:14 am
by Lukasz
ooPo wrote:You didn't just embed a copy of libsd into sjpcm, did you? :)
More or less :)

Posted: Mon Aug 30, 2004 10:04 am
by pixel
Why not having it in the CVS ?

Posted: Sat Sep 04, 2004 9:44 am
by pixel
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:

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++;
    }
}
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.

Posted: Sun Sep 05, 2004 7:09 am
by Lukasz
Feel free to commit it all to the cvs if you want.

Posted: Sun Sep 05, 2004 10:04 am
by pixel
You mean, creating a new module, right ? There's no iSjPCM module in CVS right now, huh ?

Posted: Sun Sep 05, 2004 10:56 am
by mrbrown
Just curious, because it's my nature to ask such things:

What exactly was the point of combining freesd and sjpcm?

Posted: Sun Sep 05, 2004 11:30 am
by Raizor
I think one of the reasons was to provide a nice example for anyone wishing to make a standalone iop based sound system, like my AHX player etc...

Posted: Sun Sep 05, 2004 11:11 pm
by Lukasz
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.

Posted: Sat Feb 12, 2005 6:50 am
by evilo
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 ??

Posted: Sat Feb 12, 2005 7:55 am
by Raizor
Nice work evilo ;o)