Cort Stratton's latest updates adding cache limit support

This commit is contained in:
David Rose 2003-02-24 19:30:06 +00:00
parent 075d6addd6
commit 12de6f6b58
2 changed files with 135 additions and 19 deletions

View File

@ -53,8 +53,10 @@ FmodAudioManager() {
audio_debug(" audio_volume="<<audio_volume);
_active = audio_active;
_cache_limit = audio_cache_limit;
// Initialize FMOD, if this is the first manager created.
_is_valid = true;
if (_active_managers == 0) {
do {
audio_debug("Initializing FMOD for real.");
@ -65,14 +67,15 @@ FmodAudioManager() {
_is_valid = false;
break;
}
if (FSOUND_Init(44100, 32, 0) == 0) {
audio_error("Fmod initialization failure.");
_is_valid = false;
break;
}
}
while(0);
_is_valid = true;
}
// increment regardless of whether an error has occured -- the
@ -110,8 +113,22 @@ FmodAudioManager::
////////////////////////////////////////////////////////////////////
bool FmodAudioManager::
is_valid() {
// verify the cache and LRU list here.
return true;
bool check=true;
if (_sounds.size() != _lru.size()) {
audio_debug("--sizes--");
check=false;
} else {
LRU::const_iterator i=_lru.begin();
for (; i != _lru.end(); ++i) {
SoundMap::const_iterator smi=_sounds.find(*i);
if (smi == _sounds.end()) {
audio_debug("--"<<*i<<"--");
check=false;
break;
}
}
}
return _is_valid && check;
}
////////////////////////////////////////////////////////////////////
@ -159,6 +176,10 @@ get_sound(const string &file_name) {
new_entry.stale = true;
// Add to the cache
while (_sounds.size() >= (unsigned int)_cache_limit) {
uncache_a_sound();
}
si = _sounds.insert(SoundMap::value_type(path, new_entry)).first;
// It's important that we assign entry to the address of the entry
@ -193,6 +214,7 @@ get_sound(const string &file_name) {
return 0;
}
inc_refcount(path);
most_recently_used(path);
// determine length of sound
float length = (float)FSOUND_Stream_GetLengthMs(stream) * 0.001f;
@ -218,8 +240,16 @@ get_sound(const string &file_name) {
void FmodAudioManager::
uncache_sound(const string& file_name) {
audio_debug("FmodAudioManager::uncache_sound(\""<<file_name<<"\")");
Filename path = file_name;
assert(is_valid());
Filename path = file_name;
if (use_vfs) {
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
vfs->resolve_filename(path, get_sound_path());
} else {
path.resolve_filename(get_sound_path());
}
audio_debug(" path=\""<<path<<"\"");
SoundMap::iterator itor = _sounds.find(path);
if (itor == _sounds.end()) {
audio_error("FmodAudioManager::uncache_sound: no such entry "<<file_name);
@ -227,13 +257,20 @@ uncache_sound(const string& file_name) {
}
// Mark the entry as stale -- when its refcount reaches zero, it will
// be removed from the cache. If the refcount is already zero, it can be
// purged right now!
// be removed from the cache.
SoundCacheEntry *entry = &(*itor).second;
if (entry->refcount == 0) {
// If the refcount is already zero, it can be
// purged right now!
audio_debug("FmodAudioManager::uncache_sound: purging "<<path
<< " from the cache.");
delete [] entry->data;
// Erase the sound from the LRU list as well.
assert(_lru.size()>0);
LRU::iterator lru_i=find(_lru.begin(), _lru.end(), itor->first);
assert(lru_i != _lru.end());
_lru.erase(lru_i);
_sounds.erase(itor);
} else {
entry->stale = true;
@ -242,6 +279,48 @@ uncache_sound(const string& file_name) {
assert(is_valid());
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::uncache_a_sound
// Access: Public
// Description: Uncaches the least recently used sound.
////////////////////////////////////////////////////////////////////
void FmodAudioManager::
uncache_a_sound() {
audio_debug("FmodAudioManager::uncache_a_sound()");
assert(is_valid());
// uncache least recently used:
assert(_lru.size()>0);
LRU::reference path=_lru.front();
SoundMap::iterator i = _sounds.find(path);
assert(i != _sounds.end());
_lru.pop_front();
if (i != _sounds.end()) {
audio_debug(" uncaching \""<<i->first<<"\"");
uncache_sound(path);
}
assert(is_valid());
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::most_recently_used
// Access: Public
// Description: Indicates that the given sound was the most recently used.
////////////////////////////////////////////////////////////////////
void FmodAudioManager::
most_recently_used(const string& path) {
audio_debug("FmodAudioManager::most_recently_used(path=\""
<<path<<"\")");
LRU::iterator i=find(_lru.begin(), _lru.end(), path);
if (i != _lru.end()) {
_lru.erase(i);
}
// At this point, path should not exist in the _lru:
assert(find(_lru.begin(), _lru.end(), path) == _lru.end());
_lru.push_back(path);
assert(is_valid());
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::clear_cache
// Access: Public
@ -249,6 +328,7 @@ uncache_sound(const string& file_name) {
////////////////////////////////////////////////////////////////////
void FmodAudioManager::
clear_cache() {
audio_debug("FmodAudioManager::clear_cache()");
// Mark all cache entries as stale. Delete those which already have
// refcounts of zero.
@ -262,7 +342,14 @@ clear_cache() {
audio_debug("FmodAudioManager::clear_cache: purging "<< (*itor).first
<< " from the cache.");
delete [] entry->data;
// Erase the sound from the LRU list as well.
assert(_lru.size()>0);
LRU::iterator lru_i=find(_lru.begin(), _lru.end(), itor->first);
assert(lru_i != _lru.end());
_lru.erase(lru_i);
_sounds.erase(itor);
itor = _sounds.begin();
} else {
entry->stale = true;
@ -277,8 +364,17 @@ clear_cache() {
// Description:
////////////////////////////////////////////////////////////////////
void FmodAudioManager::
set_cache_limit(int) {
// intentionally blank.
set_cache_limit(int count) {
audio_debug("FmodAudioManager::set_cache_limit(count="
<<count<<")");
assert(is_valid());
while (_lru.size() > (unsigned int) count) {
uncache_a_sound();
}
_cache_limit = count;
assert(is_valid());
}
////////////////////////////////////////////////////////////////////
@ -288,8 +384,9 @@ set_cache_limit(int) {
////////////////////////////////////////////////////////////////////
int FmodAudioManager::
get_cache_limit() {
// intentionally blank.
return 0;
audio_debug("FmodAudioManager::get_cache_limit() returning "
<<_cache_limit);
return _cache_limit;
}
////////////////////////////////////////////////////////////////////
@ -377,16 +474,17 @@ stop_all_sounds(void) {
void FmodAudioManager::
inc_refcount(const string& file_name) {
Filename path = file_name;
SoundMap::iterator itor = _sounds.find(path.to_os_specific());
if (itor != _sounds.end()) {
SoundCacheEntry *entry = &(*itor).second;
entry->refcount++;
entry->stale = false; // definitely not stale!
audio_debug("FmodAudioManager: "<<path<<" has a refcount of "
<< entry->refcount);
} else {
SoundMap::iterator itor = _sounds.find(path);
if (itor == _sounds.end()) {
audio_debug("FmodAudioManager::inc_refcount: no such file "<<path);
return;
}
SoundCacheEntry *entry = &(*itor).second;
entry->refcount++;
entry->stale = false; // definitely not stale!
audio_debug("FmodAudioManager: "<<path<<" has a refcount of "
<< entry->refcount);
}
////////////////////////////////////////////////////////////////////
@ -399,7 +497,7 @@ inc_refcount(const string& file_name) {
void FmodAudioManager::
dec_refcount(const string& file_name) {
Filename path = file_name;
SoundMap::iterator itor = _sounds.find(path.to_os_specific());
SoundMap::iterator itor = _sounds.find(path);
if (itor != _sounds.end()) {
SoundCacheEntry *entry = &(*itor).second;
entry->refcount--;
@ -408,6 +506,12 @@ dec_refcount(const string& file_name) {
if (entry->refcount == 0 && entry->stale) {
audio_debug("FmodAudioManager::dec_refcount: purging "<<path<< " from the cache.");
delete [] entry->data;
// Erase the sound from the LRU list as well.
assert(_lru.size()>0);
LRU::iterator lru_i=find(_lru.begin(), _lru.end(), itor->first);
assert(lru_i != _lru.end());
_lru.erase(lru_i);
_sounds.erase(itor);
}
} else {

View File

@ -26,6 +26,7 @@
#include "audioManager.h"
class FmodAudioSound;
#include "filename.h"
#include "pdeque.h"
#include "pmap.h"
#include "pset.h"
@ -48,6 +49,12 @@ public:
virtual void set_cache_limit(int);
virtual int get_cache_limit();
// Indicates that the given sound was the most recently used.
void most_recently_used(const string& path);
// Uncaches the least recently used sound.
void uncache_a_sound();
virtual void set_volume(float);
virtual float get_volume();
@ -74,8 +81,13 @@ private:
// The offspring of this manager:
AudioSet _soundsOnLoan;
// The Least Recently Used mechanism:
typedef pdeque<string> LRU;
LRU _lru;
void release_sound(FmodAudioSound *audioSound);
int _cache_limit;
static int _active_managers;
bool _is_valid;
bool _active;