From 2493236cea6623ab6059c5ec31310c871f61e697 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Mon, 18 Jul 2005 19:08:28 +0000 Subject: [PATCH] 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. --- stepmania/src/RageSoundManager.cpp | 61 +++++++++++++++++++++++++++++- stepmania/src/RageSoundManager.h | 9 ++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/stepmania/src/RageSoundManager.cpp b/stepmania/src/RageSoundManager.cpp index cf8015d8ea..0d91ec21f2 100644 --- a/stepmania/src/RageSoundManager.cpp +++ b/stepmania/src/RageSoundManager.cpp @@ -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::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 ToDelete; for( set::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::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::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 ) diff --git a/stepmania/src/RageSoundManager.h b/stepmania/src/RageSoundManager.h index 8131f03a36..7b5a242e34 100644 --- a/stepmania/src/RageSoundManager.h +++ b/stepmania/src/RageSoundManager.h @@ -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 all_sounds; - + + map m_mapPreloadedSounds; + RageSoundDriver *m_pDriver; /* Prefs: */