mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-18 20:53:50 -04:00
Cort Stratton's latest updates adding cache limit support
This commit is contained in:
parent
075d6addd6
commit
12de6f6b58
@ -53,8 +53,10 @@ FmodAudioManager() {
|
|||||||
audio_debug(" audio_volume="<<audio_volume);
|
audio_debug(" audio_volume="<<audio_volume);
|
||||||
|
|
||||||
_active = audio_active;
|
_active = audio_active;
|
||||||
|
_cache_limit = audio_cache_limit;
|
||||||
|
|
||||||
// Initialize FMOD, if this is the first manager created.
|
// Initialize FMOD, if this is the first manager created.
|
||||||
|
_is_valid = true;
|
||||||
if (_active_managers == 0) {
|
if (_active_managers == 0) {
|
||||||
do {
|
do {
|
||||||
audio_debug("Initializing FMOD for real.");
|
audio_debug("Initializing FMOD for real.");
|
||||||
@ -65,14 +67,15 @@ FmodAudioManager() {
|
|||||||
_is_valid = false;
|
_is_valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FSOUND_Init(44100, 32, 0) == 0) {
|
if (FSOUND_Init(44100, 32, 0) == 0) {
|
||||||
audio_error("Fmod initialization failure.");
|
audio_error("Fmod initialization failure.");
|
||||||
_is_valid = false;
|
_is_valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
while(0);
|
while(0);
|
||||||
_is_valid = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// increment regardless of whether an error has occured -- the
|
// increment regardless of whether an error has occured -- the
|
||||||
@ -110,8 +113,22 @@ FmodAudioManager::
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool FmodAudioManager::
|
bool FmodAudioManager::
|
||||||
is_valid() {
|
is_valid() {
|
||||||
// verify the cache and LRU list here.
|
bool check=true;
|
||||||
return 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;
|
new_entry.stale = true;
|
||||||
|
|
||||||
// Add to the cache
|
// Add to the cache
|
||||||
|
while (_sounds.size() >= (unsigned int)_cache_limit) {
|
||||||
|
uncache_a_sound();
|
||||||
|
}
|
||||||
|
|
||||||
si = _sounds.insert(SoundMap::value_type(path, new_entry)).first;
|
si = _sounds.insert(SoundMap::value_type(path, new_entry)).first;
|
||||||
|
|
||||||
// It's important that we assign entry to the address of the entry
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
inc_refcount(path);
|
inc_refcount(path);
|
||||||
|
most_recently_used(path);
|
||||||
|
|
||||||
// determine length of sound
|
// determine length of sound
|
||||||
float length = (float)FSOUND_Stream_GetLengthMs(stream) * 0.001f;
|
float length = (float)FSOUND_Stream_GetLengthMs(stream) * 0.001f;
|
||||||
@ -218,8 +240,16 @@ get_sound(const string &file_name) {
|
|||||||
void FmodAudioManager::
|
void FmodAudioManager::
|
||||||
uncache_sound(const string& file_name) {
|
uncache_sound(const string& file_name) {
|
||||||
audio_debug("FmodAudioManager::uncache_sound(\""<<file_name<<"\")");
|
audio_debug("FmodAudioManager::uncache_sound(\""<<file_name<<"\")");
|
||||||
Filename path = file_name;
|
|
||||||
assert(is_valid());
|
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);
|
SoundMap::iterator itor = _sounds.find(path);
|
||||||
if (itor == _sounds.end()) {
|
if (itor == _sounds.end()) {
|
||||||
audio_error("FmodAudioManager::uncache_sound: no such entry "<<file_name);
|
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
|
// 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
|
// be removed from the cache.
|
||||||
// purged right now!
|
|
||||||
SoundCacheEntry *entry = &(*itor).second;
|
SoundCacheEntry *entry = &(*itor).second;
|
||||||
if (entry->refcount == 0) {
|
if (entry->refcount == 0) {
|
||||||
|
// If the refcount is already zero, it can be
|
||||||
|
// purged right now!
|
||||||
audio_debug("FmodAudioManager::uncache_sound: purging "<<path
|
audio_debug("FmodAudioManager::uncache_sound: purging "<<path
|
||||||
<< " from the cache.");
|
<< " from the cache.");
|
||||||
delete [] entry->data;
|
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);
|
_sounds.erase(itor);
|
||||||
} else {
|
} else {
|
||||||
entry->stale = true;
|
entry->stale = true;
|
||||||
@ -242,6 +279,48 @@ uncache_sound(const string& file_name) {
|
|||||||
assert(is_valid());
|
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
|
// Function: FmodAudioManager::clear_cache
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -249,6 +328,7 @@ uncache_sound(const string& file_name) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void FmodAudioManager::
|
void FmodAudioManager::
|
||||||
clear_cache() {
|
clear_cache() {
|
||||||
|
audio_debug("FmodAudioManager::clear_cache()");
|
||||||
// Mark all cache entries as stale. Delete those which already have
|
// Mark all cache entries as stale. Delete those which already have
|
||||||
// refcounts of zero.
|
// refcounts of zero.
|
||||||
|
|
||||||
@ -262,7 +342,14 @@ clear_cache() {
|
|||||||
audio_debug("FmodAudioManager::clear_cache: purging "<< (*itor).first
|
audio_debug("FmodAudioManager::clear_cache: purging "<< (*itor).first
|
||||||
<< " from the cache.");
|
<< " from the cache.");
|
||||||
delete [] entry->data;
|
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);
|
_sounds.erase(itor);
|
||||||
|
|
||||||
itor = _sounds.begin();
|
itor = _sounds.begin();
|
||||||
} else {
|
} else {
|
||||||
entry->stale = true;
|
entry->stale = true;
|
||||||
@ -277,8 +364,17 @@ clear_cache() {
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void FmodAudioManager::
|
void FmodAudioManager::
|
||||||
set_cache_limit(int) {
|
set_cache_limit(int count) {
|
||||||
// intentionally blank.
|
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::
|
int FmodAudioManager::
|
||||||
get_cache_limit() {
|
get_cache_limit() {
|
||||||
// intentionally blank.
|
audio_debug("FmodAudioManager::get_cache_limit() returning "
|
||||||
return 0;
|
<<_cache_limit);
|
||||||
|
return _cache_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -377,16 +474,17 @@ stop_all_sounds(void) {
|
|||||||
void FmodAudioManager::
|
void FmodAudioManager::
|
||||||
inc_refcount(const string& file_name) {
|
inc_refcount(const string& file_name) {
|
||||||
Filename path = 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()) {
|
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 {
|
|
||||||
audio_debug("FmodAudioManager::inc_refcount: no such file "<<path);
|
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::
|
void FmodAudioManager::
|
||||||
dec_refcount(const string& file_name) {
|
dec_refcount(const string& file_name) {
|
||||||
Filename path = 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()) {
|
if (itor != _sounds.end()) {
|
||||||
SoundCacheEntry *entry = &(*itor).second;
|
SoundCacheEntry *entry = &(*itor).second;
|
||||||
entry->refcount--;
|
entry->refcount--;
|
||||||
@ -408,6 +506,12 @@ dec_refcount(const string& file_name) {
|
|||||||
if (entry->refcount == 0 && entry->stale) {
|
if (entry->refcount == 0 && entry->stale) {
|
||||||
audio_debug("FmodAudioManager::dec_refcount: purging "<<path<< " from the cache.");
|
audio_debug("FmodAudioManager::dec_refcount: purging "<<path<< " from the cache.");
|
||||||
delete [] entry->data;
|
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);
|
_sounds.erase(itor);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "audioManager.h"
|
#include "audioManager.h"
|
||||||
class FmodAudioSound;
|
class FmodAudioSound;
|
||||||
#include "filename.h"
|
#include "filename.h"
|
||||||
|
#include "pdeque.h"
|
||||||
#include "pmap.h"
|
#include "pmap.h"
|
||||||
#include "pset.h"
|
#include "pset.h"
|
||||||
|
|
||||||
@ -48,6 +49,12 @@ public:
|
|||||||
virtual void set_cache_limit(int);
|
virtual void set_cache_limit(int);
|
||||||
virtual int get_cache_limit();
|
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 void set_volume(float);
|
||||||
virtual float get_volume();
|
virtual float get_volume();
|
||||||
|
|
||||||
@ -74,8 +81,13 @@ private:
|
|||||||
// The offspring of this manager:
|
// The offspring of this manager:
|
||||||
AudioSet _soundsOnLoan;
|
AudioSet _soundsOnLoan;
|
||||||
|
|
||||||
|
// The Least Recently Used mechanism:
|
||||||
|
typedef pdeque<string> LRU;
|
||||||
|
LRU _lru;
|
||||||
|
|
||||||
void release_sound(FmodAudioSound *audioSound);
|
void release_sound(FmodAudioSound *audioSound);
|
||||||
|
|
||||||
|
int _cache_limit;
|
||||||
static int _active_managers;
|
static int _active_managers;
|
||||||
bool _is_valid;
|
bool _is_valid;
|
||||||
bool _active;
|
bool _active;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user