PS2 OPL SND TEST

Status
Not open for further replies.
@Krah: So... Does a secondary buffer and/or voice-channel work?


Edit: Btw.: It would be neat, if you could put your code into code-boxes (also in your previous post)! ;)

What about an SND-Test 4 for the masses?
 
Last edited:
I'll put up a new test when I get home, can still only use 2 different SFX but you can see how much smoother adpcm is at least..I "think" the issue is needing to clear the spu2 cache buffer flags etc .. I'll need to do research in order to try proceed.

 
  • Like
Reactions: TnA
I dont have time to remove the not working volume setting at the time of uploading this, not sure why it didn't work...first thing i tried was setting an integer with user defined values of 0-100 with the call
Code:
audsrv_set_volume(gSFXVolume);
since the arg is int vol i figured itd be that easy...didn't work so I did a big stupid inefficient volume function just to see if that would work heres a snippet
Code:
    if ((gSFXVolume != 0 && gSFXVolume <=4)){
       audsrv_set_volume(0x0096);
    }
    if ((gSFXVolume >4 && gSFXVolume <=8)){
       audsrv_set_volume(0x0190);
    }
    if ((gSFXVolume >8 && gSFXVolume <=12)){
       audsrv_set_volume(0x0230);
    }

didn't work either...really need to test individual shorts first to see if its an issue there or on my side but i'll do that later.
 

Attachments

Maybe you have to reinitialize the sound-library, or you have to make a new call after setting the volume...?!

Great progress! :)
 
I dont have time to remove the not working volume setting at the time of uploading this, not sure why it didn't work...first thing i tried was setting an integer with user defined values of 0-100 with the call
Code:
audsrv_set_volume(gSFXVolume);
since the arg is int vol i figured itd be that easy...didn't work so I did a big stupid inefficient volume function just to see if that would work heres a snippet
Code:
    if ((gSFXVolume != 0 && gSFXVolume <=4)){
       audsrv_set_volume(0x0096);
    }
    if ((gSFXVolume >4 && gSFXVolume <=8)){
       audsrv_set_volume(0x0190);
    }
    if ((gSFXVolume >8 && gSFXVolume <=12)){
       audsrv_set_volume(0x0230);
    }

didn't work either...really need to test individual shorts first to see if its an issue there or on my side but i'll do that later.
Based on the source code, the lowest possible volume value is 0 while max value is:

Code:
 #define MAX_VOLUME 0x3fff

So you should mess with that data range. Note that it's better to have bigger range while testing.
For example try:
0x1000 and 0x3000 to see for differences. If you try volumes like 0x1 and 0x3 , the differences in the output audio might be so small that the human ear can't tell the difference.
 
I tried 0x0096 and 0x3fff both sounded the same, max volume but it's a good suggestion anyway maybe I messed something up during the testing. I will try again when I get a chance.
 
I tried 0x0096 and 0x3fff both sounded the same, max volume but it's a good suggestion anyway maybe I messed something up during the testing. I will try again when I get a chance.
Try more extreme ranged values. When you day the same, the same as max volume?

gSFXVolume could be the getting it's value reset to the same value somewhere later in the code.
 
yea the same as max volume, good point though it is default to 100 (max_volume) in cfg so it could be an issue there or some where else related to the int itself.. got a few things to play with

EDIT: ok tested a few things, taking the int gSFXVolume out of the equation completely and just using a standard vol call
Code:
audsrv_set_volume(0x1000);
(as well as a few other lower values) it all sounds exactly the same to me as MAX_VOLUME.. perhaps the volume function for audsrv does not work as intended? or adpcm can only be one volume? im not sure exactly but sfx volume seems like a no go. other people are welcome to test it out and give results :)
 
Last edited:
I don't think there is a need to allow the sound effects to be changed.
While more options will offer greater flexibility, it also adds onto complexity (in terms of code and the user experience). The users of OPL are generally gamers, who will be more interested in games. So if you add any feature, you might want to consider whether anybody would use it.

I "think" the issue is needing to clear the spu2 cache buffer flags etc .. I'll need to do research in order to try proceed.
What's the SPU2 cache? It doesn't have one... right?

I dont have time to remove the not working volume setting at the time of uploading this, not sure why it didn't work...first thing i tried was setting an integer with user defined values of 0-100 with the call
Code:
audsrv_set_volume(gSFXVolume);
since the arg is int vol i figured itd be that easy...didn't work so I did a big stupid inefficient volume function just to see if that would work heres a snippet
Code:
    if ((gSFXVolume != 0 && gSFXVolume <=4)){
       audsrv_set_volume(0x0096);
    }
    if ((gSFXVolume >4 && gSFXVolume <=8)){
       audsrv_set_volume(0x0190);
    }
    if ((gSFXVolume >8 && gSFXVolume <=12)){
       audsrv_set_volume(0x0230);
    }

didn't work either...really need to test individual shorts first to see if its an issue there or on my side but i'll do that later.

I tried 0x0096 and 0x3fff both sounded the same, max volume but it's a good suggestion anyway maybe I messed something up during the testing. I will try again when I get a chance.

yea the same as max volume, good point though it is default to 100 (max_volume) in cfg so it could be an issue there or some where else related to the int itself.. got a few things to play with

EDIT: ok tested a few things, taking the int gSFXVolume out of the equation completely and just using a standard vol call
Code:
audsrv_set_volume(0x1000);
(as well as a few other lower values) it all sounds exactly the same to me as MAX_VOLUME.. perhaps the volume function for audsrv does not work as intended? or adpcm can only be one volume? im not sure exactly but sfx volume seems like a no go. other people are welcome to test it out and give results :)

By the definition of audsrv_set_volume on the EE, you are supposed to specify the volume level in percentage (i.e. 100 = maximum, 0 = muted).

It doesn't seem to have a function for changing the individual channel volume levels, after it is set once at initialization. The audsrv_set_volume() function adjusts the master volume level.
 
Awwwww... So if someone gets volume-changing (working), it is only a global value for all sounds and not separated? Hm... That's sad... :-|
 
What's the SPU2 cache? It doesn't have one... right?
you'd know better than me mate ;) a few months ago i was reading about the pcsx2 emulated spu2, i could be confusing some info from that?

The issues im having are
Code:
audsrv_adpcm_t sfx;
all the struct variables are related to sfx right? but i cant clear all variables after a sound call
Code:
    audsrv_load_adpcm(&sfx, snd1_buffer, snd1_size);
    audsrv_play_adpcm(&sfx);
i've tried a couple different things
Code:
memset(&sfx, 0, sizeof(sfx));

audsrv_adpcm_t sfx = {0};
also tried setting a standard default state like
Code:
sfx.buffer = NULL;
sfx.size = 0;
I couldn't get it to work which is why I did the dodgey double up of
Code:
struct audsrv_adpcm_t sfx;
struct audsrv_adpcm_t sfx2;
while inefficient it works for the mean time but it can't be done forever, trying to audsrv_load_adpcm() more than 2 struct pointers causes the console to freeze, so im just assuming i need to clear the spu2 buffers etc to load more sounds but this is also why I said i would need to research because im just making assumptions based off nothing really but trial and error.
Reading this part of the header
Code:
/** Initializes adpcm unit of audsrv
 * @returns zero on success, negative value on error
 *
 * Frees up all memory taken by samples, and stops all voices from
 * being played. This can be called multiple times
 */
int audsrv_adpcm_init();
I would think calling audsrv_adpcm_init() again would solve the issue, but it just freezes the console again. Maybe the lib needs to be deinit and reinit? Issue there is everytime i call audsrv_quit() it also freezes the console.

Obviously the biggest issue here is me and my lack of knowledge with the hardware etc as im just an end user trying to get a feature i personally wanted for my kids, nieces & nephews (bgm more so than sfx).
worst case scenario i cant get it working but at least i had a crack at it rather than just listing things as 'wishlist' and never trying to do anything about it. :biggrin2:

@sp193 I dont want to hassle you every time i run into an issue as i know you are trying to wrap up your ps2 projects for the meantime, but thanks for all your help so far it is appreciated.

I'll do my best to try get something use-able here
 
you'd know better than me mate ;) a few months ago i was reading about the pcsx2 emulated spu2, i could be confusing some info from that?

Nah, there isn't one. At least, not from what I remember.

The issues im having are
Code:
audsrv_adpcm_t sfx;
all the struct variables are related to sfx right? but i cant clear all variables after a sound call

Why must you clear them, after sound playback? Once you do this, you must never play that sound effect, until the structure is re-populated with audsrv_load_adpcm().
Once you do this, you must never the sound effect again, unless you use audsrv_load_adpcm() to populate the structure.

When you are done with the sound, you should stop all playback and free() snd*_buffer. You may clear the sfx structures then.

Code:
struct audsrv_adpcm_t sfx;
struct audsrv_adpcm_t sfx2;
while inefficient it works for the mean time but it can't be done forever, trying to audsrv_load_adpcm() more than 2 struct pointers causes the console to freeze, so im just assuming i need to clear the spu2 buffers etc to load more sounds but this is also why I said i would need to research because im just making assumptions based off nothing really but trial and error.

Can you paste your code here? So far, the problems you have faced probably aren't related to the SPU2, but coding with AUDSRV.

From what I can see, AUDSRV's RPC may be poorly designed for multi-thread use; if multiple threads try to use the RPC functions, they can overwrite each other's results. So for now, it is probably not a good idea to call its functions from multiple threads.

Reading this part of the header
Code:
/** Initializes adpcm unit of audsrv
 * @returns zero on success, negative value on error
 *
 * Frees up all memory taken by samples, and stops all voices from
 * being played. This can be called multiple times
 */
int audsrv_adpcm_init();
I would think calling audsrv_adpcm_init() again would solve the issue, but it just freezes the console again. Maybe the lib needs to be deinit and reinit? Issue there is everytime i call audsrv_quit() it also freezes the console.

I think you already crashed the IOP or the SIF implementation on the EE, hence why further calls to any RPC functions don't work...

@sp193 I dont want to hassle you every time i run into an issue as i know you are trying to wrap up your ps2 projects for the meantime, but thanks for all your help so far it is appreciated.

That is true, but it's only done when I can touch the PS2. So I'm fine with helping people like you, on every other day.

I'll do my best to try get something use-able here

All the best to you with this.
 
Have been trying to clean it up a bit, this is it so far seems to work fine for 2 sfx haven't tried a 3rd since tonights clean up.
header
Code:
struct audsrv_adpcm_t sfx;
struct audsrv_adpcm_t sfx2;

u8* snd_buffer;
int snd_size;
char device_path[128];
char snd1_path[256], snd2_path[256];
c
Code:
void getAudioDevice(void)
{
    if ((gAudioPath == 0))
       sprintf(device_path, "mc0:Sound/");
    if ((gAudioPath == 1))
       sprintf(device_path, "pfs0:Sound/");
    if ((gAudioPath == 2))
       sprintf(device_path, "mass0:Sound/");
}

void sfxInit(void)
{
    int ret;

    ret = audsrv_init();
    if (ret != 0)
    {
        printf("sfx: failed to initialize audsrv\n");
        printf("audsrv returned error string: %s\n", audsrv_get_error_string());
    }

    audsrv_adpcm_init();
    audsrv_set_volume(MAX_VOLUME);
}

int prep_sfx(char *snd_path)
{
    FILE* adpcm;

    getAudioDevice();

    sprintf(snd1_path, "%s/scrollV.adp", device_path);
    sprintf(snd2_path, "%s/scrollH.adp", device_path);

        adpcm = fopen(snd_path, "rb");

        fseek(adpcm, 0, SEEK_END);
        snd_size = ftell(adpcm);
        fseek(adpcm, 0, SEEK_SET);
        snd_buffer = malloc(snd_size);
        fread(snd_buffer, 1, snd_size, adpcm);
        fclose(adpcm);

    return 0;
}

void sfxEnd(void)
{
    audsrv_stop_audio(); // I think this only related to PCM audio? put it in anyway in case.
    free(snd_buffer);
   //memset(&sfx, 0, sizeof(sfx);
   //memset(&sfx2, 0, sizeof(sfx2);
}

with the call
Code:
        if (gEnableSFX){
            prep_sfx(snd*_path); //snd1_path or snd2_path
            audsrv_load_adpcm(&sfx*, snd_buffer, snd_size); //&sfx or &sfx2
            audsrv_play_adpcm(&sfx*); //&sfx or &sfx2
            sfxEnd();

I've used a struct per sfx, this may be inefficient? which is why i was trying to clear it at sfxEnd() so I can just use the same struct every time with different variables. couldnt get it working it just kept playing the same file so i removed it for now. Theres probably a bunch of issues here im unaware of?
 
Last edited:
AFAIK, it has 2MB...

However... Some buffers we are talking about, are possibly either running on the EE (or IOP) and are part of a task/thread, whereas it should be mixed and done on the SPU2 as it seems... I vaguely remember something about ADPCM and 'SPU2 plus' or so... 'Scalable channels' (in terms of volume, etc.) should be possible, but Audsrv seemingly doesn't support it...
 
When you are done with the sound, you should stop all playback and free() snd*_buffer. You may clear the sfx structures then.

Since it doesn't do anything about the EE buffer pointer after setting it, and neither is a way to re-upload a sound (i.e. no further use for it), you may consider freeing the buffer after calling audsrv_load_adpcm().

It doesn't seem to have a function for changing the individual channel volume levels, after it is set once at initialization. The audsrv_set_volume() function adjusts the master volume level.

You're probably right; there is no volume control for the sound effects, and the volume for the voice channels is fixed to the maximum.
The master volume control affects the input to core 1 and is muted by default. But yet you are able to play sound effects, so it cannot control the voice channels.

Code:
/** Initializes adpcm unit of audsrv
 * @returns zero on success, negative value on error
 *
 * Frees up all memory taken by samples, and stops all voices from
 * being played. This can be called multiple times
 */
int audsrv_adpcm_init();
I would think calling audsrv_adpcm_init() again would solve the issue

By design, it seems to allow the programmer to clear the SPU2 of all samples.


While this is currently done in OPL, please consider not putting globals into the header file for any other work that you might work on.
I think it's bad practice because it would result in a new declaration in each file that includes the header file, although nothing bad happens if the definition imported into each .c file ends up being the same.

For the PS2, it also has one more implication: we cannot use the mgpopt option with this, so the $gp register will always be left unused.

I might someday try to move the declarations in the header file into the .c files, but it's a lot of work to correct.

Code:
struct audsrv_adpcm_t sfx;
struct audsrv_adpcm_t sfx2;

u8* snd_buffer;
int snd_size;
char device_path[128];
char snd1_path[256], snd2_path[256];

For data (like the buffer for storing the paths) that is only needed once, you can consider declaring them as local variables. That will place them on the stack (rather than having permanent space, which exists throughout the whole runtime of the software), for use within the function's scope.

Code:
int prep_sfx(char *snd_path)
{
    FILE* adpcm;

    getAudioDevice();

    sprintf(snd1_path, "%s/scrollV.adp", device_path);
    sprintf(snd2_path, "%s/scrollH.adp", device_path);

        adpcm = fopen(snd_path, "rb");

        fseek(adpcm, 0, SEEK_END);
        snd_size = ftell(adpcm);
        fseek(adpcm, 0, SEEK_SET);
        snd_buffer = malloc(snd_size);
        fread(snd_buffer, 1, snd_size, adpcm);
        fclose(adpcm);

    return 0;
}

You might want to check the return values of fopen() and malloc().
If the file cannot be opened (fopen fails), then do not continue. If memory cannot be allocated, do not continue either.

Code:
void sfxEnd(void)
{
    audsrv_stop_audio(); // I think this only related to PCM audio? put it in anyway in case.
    free(snd_buffer);
   //memset(&sfx, 0, sizeof(sfx);
   //memset(&sfx2, 0, sizeof(sfx2);
}

Yes, it is not required to call audsrv_stop_audio(). In fact, that function only mutes PCM playback.

Code:
        if (gEnableSFX){
            prep_sfx(snd*_path); //snd1_path or snd2_path
            audsrv_load_adpcm(&sfx*, snd_buffer, snd_size); //&sfx or &sfx2
            audsrv_play_adpcm(&sfx*); //&sfx or &sfx2
            sfxEnd();

By the code of AUDSRV, the address of the audsrv_adpcm_t structure is used as an ID for identifying each sound effect, so you should not reuse the structures as it will refuse to have a sound loaded twice.

The ADPCM samples are transferred over to the IOP, before they are transferred to the SPU2. There is no sound data kept on the IOP, but all samples are always stored in SPU2 memory. Due to this and the fact that the structure is treated as the ID, you cannot unload a sound effect by just zero'ing the structure.

I've used a struct per sfx, this may be inefficient? which is why i was trying to clear it at sfxEnd() so I can just use the same struct every time with different variables.

No, I think it's intended for you to do that. I think it's even more inefficient to try to load each sound for each playback.
 
THX! That post deserves a 'gold-like'... It includes most needed info for Krah and also even teaches programming - in a bit subliminal way - to the readers (for those who start into the topic).

Sorry, if this is considered 'Spam' ^^6
 
On my phone so it's difficult to quote but you'll know what I'm referring to.
I previously had it reading each file and allocating the memory when SFX initiates at startup

https://github.com/KrahJohlito/Open-PS2-Loader/commit/2f15545a1df42f441efda9254aac6747d328ce04

If you get a chance to check this commit you'll see what I mean, are you saying this is more efficient? It just seemed code inefficient cause I had to double up a bunch of code per SFX file.. there are still mistakes in this commit going by your latest post but i just mean the way each file is read ahead of time rather than each sound call.
 
Yes, but you only need to call audsrv_load_adpcm() once. Do it when loading the sound.
Once it is loaded, you should be able to call audsrv_play_adpcm() many times.

To reduce the amount of code for loading the sound effect files, you may use a for loop and keep the filenames and their respective adpcm structures in arrays.

Regarding the new check on fopen(): simply calling audsrv_quit() is not sufficient to prevent trouble if the file cannot be opened. You need to abort the loading process for that file entirely and do not allow audsrv to play the sound that was not loaded. Otherwise, you may get some obscure crashes related to null and uninitialized data. But perhaps this can be worked on later.
 
A ton of useful info, thank you very much. this seems a lot better. I "think" I covered everything you mentioned.

Need to double check everything in your notes but at first glance it seems correct.

Edit: removed the code, spotted a few fixable stupid issues made at 2am.
Edit 2: fixed.
Code:
struct audsrv_adpcm_t sfx[6];
u8* snd_buffer[6];
int snd_size[6];
char snd_path[6][256];

char device_path[128];

void getAudioDevice(void)
{
    if ((gAudioPath == 0))
       sprintf(device_path, "mc0:Sound/");
    if ((gAudioPath == 1))
       sprintf(device_path, "pfs0:Sound/");
    if ((gAudioPath == 2))
       sprintf(device_path, "mass0:Sound/");
}

int sfxInit(void)
{
    FILE* adpcm;
    int ret, i;

    ret = audsrv_init();
    if (ret != 0)
    {
        printf("sfx: failed to initialize audsrv\n");
        printf("audsrv returned error string: %s\n", audsrv_get_error_string());
    }

    getAudioDevice();

    //sfx0
    sfx[0].buffer = snd_buffer[0];
    sfx[0].size = snd_size[0];
    sprintf(snd_path[0], "%s/scrollV.adp", device_path);
    //sfx1
    sfx[1].buffer = snd_buffer[1];
    sfx[1].size = snd_size[1];
    sprintf(snd_path[1], "%s/scrollH.adp", device_path);
    //sfx2
    sfx[2].buffer = snd_buffer[2];
    sfx[2].size = snd_size[2];
    sprintf(snd_path[2], "%s/page.adp", device_path);
    //sfx3
    sfx[3].buffer = snd_buffer[3];
    sfx[3].size = snd_size[3];
    sprintf(snd_path[3], "%s/cancel.adp", device_path);
    //sfx4
    sfx[4].buffer = snd_buffer[4];
    sfx[4].size = snd_size[4];
    sprintf(snd_path[4], "%s/transition.adp", device_path);
    //sfx5
    sfx[5].buffer = snd_buffer[5];
    sfx[5].size = snd_size[5];
    sprintf(snd_path[5], "%s/alert.adp", device_path);
    //sfx6
    sfx[6].buffer = snd_buffer[6];
    sfx[6].size = snd_size[6];
    sprintf(snd_path[6], "%s/confirm.adp", device_path);

    audsrv_adpcm_init();
    audsrv_set_volume(MAX_VOLUME);

    for(i=0; i<3; ++i) { //setting the loop higher than 3, freezes the console...?
        adpcm = fopen(snd_path[i], "rb");
        if (adpcm == NULL)
        {
        printf("failed to open adpcm file\n");
        audsrv_quit();
        break;
        }

        fseek(adpcm, 0, SEEK_END);
        sfx[i].size = ftell(adpcm);
        fseek(adpcm, 0, SEEK_SET);

        sfx[i].buffer = malloc(sfx[i].size);
        if (sfx[i].buffer == 0) //0 or NULL? I think 0 as its related to size
        {
        printf("memory allocation failed\n");
        break;
        }

        fread(sfx[i].buffer, 1, sfx[i].size, adpcm);
        fclose(adpcm);

        audsrv_load_adpcm(&sfx[i], sfx[i].buffer, sfx[i].size);
        free(sfx[i].buffer);
    }
    return i;
}

Can only get 3 sfx loaded, attempting more freezes the console but hey....its 1 more than before
 
Last edited:
Added buffer and size to the loop, makes more sense..less code. Anyone got any ideas why it'd only load 3 files? @TnA @NewFile files are well under 2mb total so I don't think it's filling the sram
 
  • Like
Reactions: TnA
Status
Not open for further replies.

Similar threads

Back
Top