Browse Source

Use hsThread for SoundBuffer preloading.

Darryl Pogue 13 years ago
parent
commit
c699ae8ab6
  1. 117
      Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.cpp
  2. 38
      Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.h

117
Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.cpp

@ -40,11 +40,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plStatusLog/plStatusLog.h" #include "plStatusLog/plStatusLog.h"
#include "hsTimer.h" #include "hsTimer.h"
static bool s_running;
static LISTDECL(plSoundBuffer, link) s_loading;
static CCritSect s_critsect;
static CEvent s_event(kEventAutoReset);
static void GetFullPath( const char filename[], char *destStr ) static void GetFullPath( const char filename[], char *destStr )
{ {
char path[ kFolderIterator_MaxPath ]; char path[ kFolderIterator_MaxPath ];
@ -79,73 +74,74 @@ static plAudioFileReader *CreateReader( hsBool fullpath, const char filename[],
return reader; return reader;
} }
// our loading thread hsError plSoundPreloader::Run()
static void LoadCallback(void *)
{ {
LISTDECL(plSoundBuffer, link) templist; hsTArray<plSoundBuffer*> templist;
while(s_running)
{ while (fRunning)
s_critsect.Enter(); {
{ fCritSect.Lock();
while(plSoundBuffer *buffer = s_loading.Head()) for (int i = fBuffers.GetCount(); i > 0; i--)
{ {
templist.Link(buffer); templist.Append(fBuffers.Pop());
} }
} fCritSect.Unlock();
s_critsect.Leave();
if (templist.GetCount() == 0)
if(!templist.Head()) {
{ fEvent.Wait();
s_event.Wait(kEventWaitForever); }
} else
else {
{
plAudioFileReader *reader = nil; plAudioFileReader *reader = nil;
while(plSoundBuffer *buffer = templist.Head()) for (int i = templist.GetCount(); i > 0; i--)
{ {
if(buffer->GetData()) plSoundBuffer* buf = templist.Pop();
{
reader = CreateReader(true, buffer->GetFileName(), buffer->GetAudioReaderType(), buffer->GetReaderSelect()); if (buf->GetData())
{
reader = CreateReader(true, buf->GetFileName(), buf->GetAudioReaderType(), buf->GetReaderSelect());
if( reader ) if( reader )
{ {
unsigned readLen = buffer->GetAsyncLoadLength() ? buffer->GetAsyncLoadLength() : buffer->GetDataLength(); unsigned readLen = buf->GetAsyncLoadLength() ? buf->GetAsyncLoadLength() : buf->GetDataLength();
reader->Read( readLen, buffer->GetData() ); reader->Read( readLen, buf->GetData() );
buffer->SetAudioReader(reader); // give sound buffer reader, since we may need it later buf->SetAudioReader(reader); // give sound buffer reader, since we may need it later
} }
else else
buffer->SetError(); {
} buf->SetError();
}
templist.Unlink(buffer); }
buffer->SetLoaded(true);
} buf->SetLoaded(true);
} }
} }
}
// we need to be sure that all buffers are removed from our load list when shutting this thread down or we will hang, // we need to be sure that all buffers are removed from our load list when shutting this thread down or we will hang,
// since the sound buffer will wait to be destroyed until it is marked as loaded // since the sound buffer will wait to be destroyed until it is marked as loaded
s_critsect.Enter(); fCritSect.Lock();
{ for (int i = fBuffers.GetCount(); i > 0; i--)
while(plSoundBuffer *buffer = s_loading.Head()) {
{ plSoundBuffer* buf = fBuffers.Pop();
buffer->SetLoaded(true); buf->SetLoaded(true);
s_loading.Unlink(buffer); }
} fCritSect.Unlock();
}
s_critsect.Leave(); return hsOK;
} }
static plSoundPreloader gLoaderThread;
void plSoundBuffer::Init() void plSoundBuffer::Init()
{ {
s_running = true; gLoaderThread.Start();
_beginthread(LoadCallback, 0, 0);
} }
void plSoundBuffer::Shutdown() void plSoundBuffer::Shutdown()
{ {
s_running = false; gLoaderThread.Stop();
s_event.Signal();
} }
//// Constructor/Destructor ////////////////////////////////////////////////// //// Constructor/Destructor //////////////////////////////////////////////////
@ -175,7 +171,6 @@ plSoundBuffer::~plSoundBuffer()
} }
} }
ASSERT(!link.IsLinked());
delete [] fFileName; delete [] fFileName;
UnLoad(); UnLoad();
} }
@ -342,7 +337,7 @@ void plSoundBuffer::IGetFullPath( char *destStr )
// While a file is loading(fLoading == true, and fLoaded == false) a buffer, no paremeters of the buffer should be modified. // While a file is loading(fLoading == true, and fLoaded == false) a buffer, no paremeters of the buffer should be modified.
plSoundBuffer::ELoadReturnVal plSoundBuffer::AsyncLoad(plAudioFileReader::StreamType type, unsigned length /* = 0 */ ) plSoundBuffer::ELoadReturnVal plSoundBuffer::AsyncLoad(plAudioFileReader::StreamType type, unsigned length /* = 0 */ )
{ {
if(!s_running) if(!gLoaderThread.IsRunning())
return kError; // we cannot load the data since the load thread is no longer running return kError; // we cannot load the data since the load thread is no longer running
if(!fLoading && !fLoaded) if(!fLoading && !fLoaded)
{ {
@ -354,13 +349,9 @@ plSoundBuffer::ELoadReturnVal plSoundBuffer::AsyncLoad(plAudioFileReader::Stream
if( fData == nil ) if( fData == nil )
return kError; return kError;
} }
s_critsect.Enter();
{ gLoaderThread.AddBuffer(this);
fLoading = true; fLoading = true;
s_loading.Link(this);
}
s_critsect.Leave();
s_event.Signal();
} }
if(fLoaded) if(fLoaded)
{ {

38
Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.h

@ -39,7 +39,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "pnKeyedObject/hsKeyedObject.h" #include "pnKeyedObject/hsKeyedObject.h"
#include "plAudioCore.h" #include "plAudioCore.h"
#include "plAudioFileReader.h" #include "plAudioFileReader.h"
#include "pnUtils/pnUtils.h" #include "hsThread.h"
//// Class Definition //////////////////////////////////////////////////////// //// Class Definition ////////////////////////////////////////////////////////
@ -55,8 +55,6 @@ public:
CLASSNAME_REGISTER( plSoundBuffer ); CLASSNAME_REGISTER( plSoundBuffer );
GETINTERFACE_ANY( plSoundBuffer, hsKeyedObject ); GETINTERFACE_ANY( plSoundBuffer, hsKeyedObject );
LINK(plSoundBuffer) link;
enum Flags enum Flags
{ {
kIsExternal = 0x0001, kIsExternal = 0x0001,
@ -143,4 +141,38 @@ protected:
plAudioFileReader *IGetReader( hsBool fullpath ); plAudioFileReader *IGetReader( hsBool fullpath );
}; };
class plSoundPreloader : public hsThread
{
protected:
hsTArray<plSoundBuffer*> fBuffers;
hsEvent fEvent;
bool fRunning;
hsMutex fCritSect;
public:
virtual hsError Run();
virtual void Start() {
fRunning = true;
hsThread::Start();
}
virtual void Stop() {
fRunning = false;
fEvent.Signal();
hsThread::Stop();
}
bool IsRunning() const { return fRunning; }
void AddBuffer(plSoundBuffer* buffer) {
fCritSect.Lock();
fBuffers.Push(buffer);
fCritSect.Unlock();
fEvent.Signal();
}
};
#endif //_plSoundBuffer_h #endif //_plSoundBuffer_h

Loading…
Cancel
Save