forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

BUG in pspAudioLib

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
sakya



Joined: 28 Apr 2006
Posts: 190

PostPosted: Sat Jan 05, 2008 2:30 am    Post subject: BUG in pspAudioLib Reply with quote

Hi! :)

I think I found a bug in pspAudioLib.
This code just init and then end the audio lib but after two init-end the init fails (cannot create callback threads).

Code:
int main(){
    int count = 0;
   pspDebugScreenInit();
   SetupCallbacks();

    pspDebugScreenPrintf("Eboot test\n");
    pspDebugScreenPrintf("Press X to run pspAudioInit and pspAudioEnd\n");

    SceCtrlData pad;
    while(runningFlag){
        sceCtrlReadBufferPositive(&pad, 1);
        if (pad.Buttons & PSP_CTRL_CROSS){
            pspDebugScreenSetXY(0, 5);
            pspDebugScreenPrintf("Count: %i\n", ++count);
            if (pspAudioInit())
                pspDebugScreenPrintf("pspAudioInit ERROR!!!\n");
            else
                pspAudioEnd();
        }
        sceKernelDelayThread(200000);
    }
   sceKernelExitGame();
    return 0;
}


The problem (I think) is that pspAudioEnd isn't really deleting threads (so when the maximum is reached the init fails).

I fixed this by just adding a "flag" in this structure
Code:
typedef struct {
  int threadhandle;
  int threadactive;   <-- THIS
  int handle;
  int volumeleft;
  int volumeright;
  pspAudioCallback_t callback;
  void *pdata;
} psp_audio_channelinfo;


I changed the AudioChannelCallback to manage the new flag:
Code:
static int AudioChannelThread(int args, void *argp)
{
        volatile int bufidx=0;
        int channel=*(int *)argp;

        AudioStatus[channel].threadactive = 1;      <-- HERE
        while (audio_terminate==0) {
                void *bufptr=&audio_sndbuf[channel][bufidx];
                pspAudioCallback_t callback;
                callback=AudioStatus[channel].callback;
                if (callback) {
                        callback(bufptr, PSP_NUM_AUDIO_SAMPLES, AudioStatus[channel].pdata);
                } else {
                        unsigned int *ptr=bufptr;
                        int i;
                        for (i=0; i<PSP_NUM_AUDIO_SAMPLES; ++i) *(ptr++)=0;
                }
                pspAudioOutBlocking(channel,AudioStatus[channel].volumeleft,AudioStatus[channel].volumeright,bufptr);
                bufidx=(bufidx?0:1);
        }
        AudioStatus[channel].threadactive = 0;        <-- HERE
        sceKernelExitThread(0);
        return 0;
}


and waited for this flag in pspAudioEnd before sceKernelDeleteThread:
Code:
void pspAudioEnd()
{
        int i;
        audio_ready=0;
        audio_terminate=1;

        for (i=0; i<PSP_NUM_AUDIO_CHANNELS; i++) {
                if (AudioStatus[i].threadhandle != -1) {
                        //sceKernelWaitThreadEnd(AudioStatus[i].threadhandle,NULL);
                        while (AudioStatus[i].threadactive)    <-- HERE
                            sceKernelDelayThread(100000);
                        sceKernelDeleteThread(AudioStatus[i].threadhandle);
                }
                AudioStatus[i].threadhandle = -1;
        }

        for (i=0; i<PSP_NUM_AUDIO_CHANNELS; i++) {
                if (AudioStatus[i].handle != -1) {
                        sceAudioChRelease(AudioStatus[i].handle);
                        AudioStatus[i].handle = -1;
                }
        }
}


There's surely a more elegant way to fix this bug. :)

EDIT: I see now this commented line:
Code:
sceKernelWaitThreadEnd(AudioStatus[i].threadhandle,NULL);

If this does what I think (wait for the thread to end) it could fix the problem (maybe I'll try later).
Why is commented?
I dind't mention that I found the bug on 3.52M33-u4, with a kernel 3.x eboot.

Ciaooo
Sakya
Back to top
View user's profile Send private message Visit poster's website
NineByNine



Joined: 18 Jul 2008
Posts: 2

PostPosted: Fri Jul 18, 2008 8:47 am    Post subject: Reply with quote

Apologies for resurrection of this ancient thread, but I found the same behaviour recently. It's only likely to cause trouble if you start and stop the pspaudiolib stuff a couple times, but it does cause trouble in this case. Full explanation: the pspAudioEnd() code sets the flag that is supposed to allow the audio thread to terminate gracefully (audio_terminate), but doesn't actually wait for the audio threads to exit, so the calls to sceKernelDeleteThread() fail (silently; the returns aren't checked), and eventually, if you start and stop the lib a few times, the dead threads pile up and calls to create new threads start to fail.

I'm guessing the call to sceKernelWaitThreadEnd(...) was commented out because if someone supplies a buggy callback which would itself hang the audio thread(s), and then called pspAudioEnd() to shutdown, the thread calling pspAudioEnd() would hang in the call. But it's a nuisance that piles up dead threads if you leave the call out.

I note there's also a pspAudioEndPre() defined, presumably for this purpose. Calling this first, then sleeping the calling thread (to allow the audio threads slice time to terminate gracefully), and *then* calling pspAudioEnd() should also work... But note it's not quite guaranteed; you have to count on the audio threads actually getting scheduled, and getting out of the way in time for your call to pspAudioEnd(). The sceKernelWaitThreadEnd() from pspAudioEnd() is much safer from that point of view (tho', of course, a risk with regard to callbacks hanging).

My solution was to create a second call in the lib (pspAudioEnd_patient()) that does wait for the thread exit. Works fine for my app. Just a suggestion.
Back to top
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Fri Jul 18, 2008 10:26 am    Post subject: Reply with quote

Or you could just start the audio lib at the start of your app and stop it at the end... you know, like EVERYONE else does. ;)
Back to top
View user's profile Send private message AIM Address
NineByNine



Joined: 18 Jul 2008
Posts: 2

PostPosted: Fri Jul 18, 2008 11:02 am    Post subject: Reply with quote

J.F. wrote:
Or you could just start the audio lib at the start of your app and stop it at the end... you know, like EVERYONE else does. ;)


... Or, y'know, the SDK could contain code that cleans up after itself properly. Like anyone would expect.

Seriously, the reason I do it that way is only because attempts to reset the sample frequency (to use the built in rates the sce calls support) once the lib was up and running failed. So I modified the lib to allow me to set the sample frequency at init; that works; init with the rate you want, shut down, init again for another stream with a different rate; it's all good that way, provided you make sure those threads get put away properly. I do expect to revisit the issue, see what I can do about resetting the frequency without tearing down and restarting the thread; I don't like that either. But still, I did find that issue doing that. So here's yer notice, for what it's worth to you.
Back to top
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Fri Jul 18, 2008 11:07 am    Post subject: Reply with quote

NineByNine wrote:
J.F. wrote:
Or you could just start the audio lib at the start of your app and stop it at the end... you know, like EVERYONE else does. ;)


... Or, y'know, the SDK could contain code that cleans up after itself properly. Like anyone would expect.

Seriously, the reason I do it that way is only because attempts to reset the sample frequency (to use the built in rates the sce calls support) once the lib was up and running failed. So I modified the lib to allow me to set the sample frequency at init; that works; init with the rate you want, shut down, init again for another stream with a different rate; it's all good that way, provided you make sure those threads get put away properly. I do expect to revisit the issue, see what I can do about resetting the frequency without tearing down and restarting the thread; I don't like that either. But still, I did find that issue doing that. So here's yer notice, for what it's worth to you.


Or you can use the same method to set the sample rate that sakya uses in LightMP3. Seriously, it sounds like you should be using his code instead of the audiolib anyway. Too many people use the audiolib who don't really need to.
Back to top
View user's profile Send private message AIM Address
nemesis



Joined: 10 May 2009
Posts: 6

PostPosted: Sun Aug 02, 2009 4:09 pm    Post subject: Reply with quote

ok.. this crap took me hours of bugsearching where everything was fine.. thanks to sakya for this hint.. jeez why isn't this commited yet?
Back to top
View user's profile Send private message Visit poster's website
jimparis



Joined: 10 Jun 2005
Posts: 1179
Location: Boston

PostPosted: Tue Aug 11, 2009 12:56 pm    Post subject: Reply with quote

Because you haven't provided a proper patch in the "Patch Submissions" forum.
Back to top
View user's profile Send private message
willow :--)



Joined: 13 Jan 2007
Posts: 126

PostPosted: Sun Jul 18, 2010 10:57 pm    Post subject: Reply with quote

I ran into the issue this week while working on Half Byte Loader.
Even though half byte loader needs to clean up the mess after applications, it would be good if something was done for this issue.

In my specific case the "guilty" homebrew was my own, so I was able to replace the call to pspAudioEnd() with

pspAudioEndPre()
sceKernelDelayThread(100000)
pspAudioEnd()

as suggested by NineByNine (which, granted, does not give any guarantee, but seemed to do the trick for now), but nevertheless I have to find a long term solution for HBL.

Of course fixing the SDK now will not fix the homebrews that already have the bug, so I still have to find an HBL specific solution, but that's just an additional post to say that it's bad to assume that all homebrews have the same use case of "pspaudioinit" "pspaudioend" getting called only once at the beginning and end of the application respectively.

HBL is an example of homebrew that doesn't fit in the "usual" case.
_________________
Wagic. Play that card game against an AI on your PSP
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group