add reference counting for preloaded sounds
This doesn't give full refcounting: loading a sound that isn't preloaded will still go through a full load (eg. initting Vorbis, etc). This handles the most expensive case, where the whole sound is loaded. This case is easy because we can make free copies, and track the number of copies remaining to handle cleanup.
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
#include "RageSound.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageTimer.h"
|
||||
#include "RageSoundReader_Preload.h"
|
||||
#include "Foreach.h"
|
||||
|
||||
#include "arch/Sound/RageSoundDriver.h"
|
||||
|
||||
@@ -97,8 +99,30 @@ void RageSoundManager::Update( float fDeltaTime )
|
||||
{
|
||||
FlushPosMapQueue();
|
||||
|
||||
/* Scan m_mapPreloadedSounds for sounds that are no longer loaded, and delete them. */
|
||||
g_SoundManMutex.Lock(); /* lock for access to m_mapPreloadedSounds, owned_sounds */
|
||||
{
|
||||
map<CString, RageSoundReader_Preload *>::iterator it, next;
|
||||
it = m_mapPreloadedSounds.begin();
|
||||
|
||||
while( it != m_mapPreloadedSounds.end() )
|
||||
{
|
||||
next = it; ++next;
|
||||
if( it->second->GetReferenceCount() == 1 )
|
||||
{
|
||||
LOG->Trace( "Deleted old sound \"%s\"", it->first.c_str() );
|
||||
delete it->second;
|
||||
m_mapPreloadedSounds.erase( it );
|
||||
}
|
||||
else
|
||||
LOG->Trace( "Kept sound \"%s\" (%i)", it->first.c_str(),
|
||||
it->second->GetReferenceCount() );
|
||||
|
||||
it = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan the owned_sounds list for sounds that are no longer playing, and delete them. */
|
||||
g_SoundManMutex.Lock(); /* lock for access to owned_sounds */
|
||||
set<RageSound *> ToDelete;
|
||||
for( set<RageSound *>::iterator it = owned_sounds.begin(); it != owned_sounds.end(); ++it )
|
||||
{
|
||||
@@ -256,6 +280,41 @@ void RageSoundManager::DeleteSoundWhenFinished( RageSound *pSound )
|
||||
g_SoundManMutex.Unlock(); /* finished with owned_sounds */
|
||||
}
|
||||
|
||||
/* If the given path is loaded, return a copy; otherwise return NULL.
|
||||
* It's the caller's responsibility to delete the result. */
|
||||
SoundReader *RageSoundManager::GetLoadedSound( const CString &sPath_ )
|
||||
{
|
||||
LockMut(g_SoundManMutex); /* lock for access to m_mapPreloadedSounds */
|
||||
|
||||
CString sPath(sPath_);
|
||||
sPath.MakeLower();
|
||||
map<CString, RageSoundReader_Preload *>::const_iterator it;
|
||||
it = m_mapPreloadedSounds.find( sPath );
|
||||
if( it == m_mapPreloadedSounds.end() )
|
||||
return NULL;
|
||||
|
||||
return it->second->Copy();
|
||||
}
|
||||
|
||||
/* Add the sound to the set of loaded sounds that can be copied for reuse.
|
||||
* The sound will be kept in memory as long as there are any other references
|
||||
* to it; once we hold the last one, we'll release it. */
|
||||
void RageSoundManager::AddLoadedSound( const CString &sPath_, RageSoundReader_Preload *pSound )
|
||||
{
|
||||
LockMut(g_SoundManMutex); /* lock for access to m_mapPreloadedSounds */
|
||||
|
||||
/* Don't AddLoadedSound a sound that's already registered. It should have been
|
||||
* used in GetLoadedSound. */
|
||||
CString sPath(sPath_);
|
||||
sPath.MakeLower();
|
||||
map<CString, RageSoundReader_Preload *>::const_iterator it;
|
||||
it = m_mapPreloadedSounds.find( sPath );
|
||||
ASSERT_M( it == m_mapPreloadedSounds.end(), sPath );
|
||||
|
||||
m_mapPreloadedSounds[sPath] = (RageSoundReader_Preload *) pSound->Copy();
|
||||
}
|
||||
|
||||
|
||||
/* Don't hold the lock when we don't have to. We call this function from other
|
||||
* threads, to avoid stalling the gameplay thread. */
|
||||
void RageSoundManager::PlayOnce( CString sPath )
|
||||
|
||||
@@ -11,6 +11,8 @@ class RageSound;
|
||||
class RageSoundBase;
|
||||
class RageSoundDriver;
|
||||
struct RageSoundParams;
|
||||
class SoundReader;
|
||||
class RageSoundReader_Preload;
|
||||
|
||||
class RageSoundManager
|
||||
{
|
||||
@@ -46,6 +48,9 @@ public:
|
||||
void DeleteSound( RageSound *pSound );
|
||||
void DeleteSoundWhenFinished( RageSound *pSound );
|
||||
|
||||
SoundReader *GetLoadedSound( const CString &sPath );
|
||||
void AddLoadedSound( const CString &sPath, RageSoundReader_Preload *pSound );
|
||||
|
||||
void PlayOnce( CString sPath );
|
||||
|
||||
RageSound *PlaySound( RageSound &snd, const RageSoundParams *params = NULL );
|
||||
@@ -60,7 +65,9 @@ private:
|
||||
|
||||
/* A list of all sounds that currently exist, by ID. */
|
||||
map<int,RageSound *> all_sounds;
|
||||
|
||||
|
||||
map<CString, RageSoundReader_Preload *> m_mapPreloadedSounds;
|
||||
|
||||
RageSoundDriver *m_pDriver;
|
||||
|
||||
/* Prefs: */
|
||||
|
||||
Reference in New Issue
Block a user