Use separate lists for the sound name and its buffer

This should make sound lookup a bit more efficient, especially when an integer
ID can be used.
openmw-38
Chris Robinson 9 years ago
parent fbfcc4050f
commit 6c3953766e

@ -101,12 +101,12 @@ namespace MWSound
clear(); clear();
if(mOutput->isInitialized()) if(mOutput->isInitialized())
{ {
NameBufferMap::iterator sfxiter = mSoundBuffers.begin(); SoundBufferList::iterator sfxiter = mSoundBuffers.begin();
for(;sfxiter != mSoundBuffers.end();++sfxiter) for(;sfxiter != mSoundBuffers.end();++sfxiter)
{ {
if(sfxiter->second.mHandle) if(sfxiter->mHandle)
mOutput->unloadSound(sfxiter->second.mHandle); mOutput->unloadSound(sfxiter->mHandle);
sfxiter->second.mHandle = 0; sfxiter->mHandle = 0;
} }
} }
mOutput.reset(); mOutput.reset();
@ -122,11 +122,11 @@ namespace MWSound
// minRange and maxRange. The returned pointer is only valid temporarily. // minRange and maxRange. The returned pointer is only valid temporarily.
Sound_Buffer *SoundManager::lookup(const std::string &soundId) Sound_Buffer *SoundManager::lookup(const std::string &soundId)
{ {
NameBufferMap::iterator sfxiter = mSoundBuffers.find(soundId); Sound_Buffer *sfx;
if(sfxiter != mSoundBuffers.end() && sfxiter->second.mHandle) BufferKeyList::iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), soundId);
return &sfxiter->second; if(bufkey != mBufferKeys.end() && *bufkey == soundId)
sfx = &mSoundBuffers[std::distance(mBufferKeys.begin(), bufkey)];
if(sfxiter == mSoundBuffers.end()) else
{ {
// TODO: We could process all available ESM::Sound records on init // TODO: We could process all available ESM::Sound records on init
// to pre-fill a non-resizing list, which would allow subsystems to // to pre-fill a non-resizing list, which would allow subsystems to
@ -157,31 +157,45 @@ namespace MWSound
min = std::max(min, 1.0f); min = std::max(min, 1.0f);
max = std::max(min, max); max = std::max(min, max);
sfxiter = mSoundBuffers.insert(std::make_pair( bufkey = mBufferKeys.insert(bufkey, soundId);
soundId, Sound_Buffer("Sound/"+snd->mSound, volume, min, max) try {
)).first; BufferKeyList::difference_type id;
mVFS->normalizeFilename(sfxiter->second.mResourceName); id = std::distance(mBufferKeys.begin(), bufkey);
} mSoundBuffers.insert(mSoundBuffers.begin()+id,
Sound_Buffer("Sound/"+snd->mSound, volume, min, max)
);
sfx = &mSoundBuffers[id];
}
catch(...) {
mBufferKeys.erase(bufkey);
throw;
}
Sound_Buffer *sfx = &sfxiter->second; mVFS->normalizeFilename(sfx->mResourceName);
sfx->mHandle = mOutput->loadSound(sfx->mResourceName); }
mBufferCacheSize += mOutput->getSoundDataSize(sfx->mHandle);
// NOTE: Max sound buffer cache size is 15MB. Make configurable? if(!sfx->mHandle)
while(mBufferCacheSize > 15*1024*1024)
{ {
if(mUnusedBuffers.empty()) sfx->mHandle = mOutput->loadSound(sfx->mResourceName);
mBufferCacheSize += mOutput->getSoundDataSize(sfx->mHandle);
// NOTE: Max sound buffer cache size is 15MB. Make configurable?
while(mBufferCacheSize > 15*1024*1024)
{ {
std::cerr<< "No unused sound buffers to free, using "<<mBufferCacheSize<<" bytes!" <<std::endl; if(mUnusedBuffers.empty())
break; {
std::cerr<< "No unused sound buffers to free, using "<<mBufferCacheSize<<" bytes!" <<std::endl;
break;
}
SoundSet::iterator iter = mUnusedBuffers.begin();
bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), *iter);
Sound_Buffer *unused = &mSoundBuffers[std::distance(mBufferKeys.begin(), bufkey)];
mBufferCacheSize -= mOutput->getSoundDataSize(unused->mHandle);
mOutput->unloadSound(unused->mHandle);
mUnusedBuffers.erase(iter);
} }
SoundSet::iterator iter = mUnusedBuffers.begin(); mUnusedBuffers.insert(soundId);
sfxiter = mSoundBuffers.find(*iter);
mBufferCacheSize -= mOutput->getSoundDataSize(sfxiter->second.mHandle);
mOutput->unloadSound(sfxiter->second.mHandle);
mUnusedBuffers.erase(iter);
} }
mUnusedBuffers.insert(soundId);
return sfx; return sfx;
} }
@ -773,8 +787,10 @@ namespace MWSound
{ {
if(!updateSound(sndname->first, snditer->first, duration)) if(!updateSound(sndname->first, snditer->first, duration))
{ {
NameBufferMap::iterator sfxiter = mSoundBuffers.find(sndname->second); BufferKeyList::iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(),
if(sfxiter->second.mReferences-- == 1) sndname->second);
Sound_Buffer *sfx = &mSoundBuffers[std::distance(mBufferKeys.begin(), bufkey)];
if(sfx->mReferences-- == 1)
mUnusedBuffers.insert(sndname->second); mUnusedBuffers.insert(sndname->second);
sndname = snditer->second.erase(sndname); sndname = snditer->second.erase(sndname);
} }
@ -981,8 +997,10 @@ namespace MWSound
for(;sndname != snditer->second.end();++sndname) for(;sndname != snditer->second.end();++sndname)
{ {
sndname->first->stop(); sndname->first->stop();
NameBufferMap::iterator sfxiter = mSoundBuffers.find(sndname->second); BufferKeyList::iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(),
if(sfxiter->second.mReferences-- == 1) sndname->second);
Sound_Buffer *sfx = &mSoundBuffers[std::distance(mBufferKeys.begin(), bufkey)];
if(sfx->mReferences-- == 1)
mUnusedBuffers.insert(sndname->second); mUnusedBuffers.insert(sndname->second);
} }
} }

@ -45,8 +45,13 @@ namespace MWSound
float mVoiceVolume; float mVoiceVolume;
float mFootstepsVolume; float mFootstepsVolume;
typedef std::map<std::string,Sound_Buffer> NameBufferMap; typedef std::vector<std::string> BufferKeyList;
NameBufferMap mSoundBuffers; typedef std::vector<Sound_Buffer> SoundBufferList;
// Each mBufferKeys index has a corresponding entry in mSoundBuffers.
// That is, if string "foo" is at index 10 in mBufferKeys, index 10 in
// mSoundBuffers contains the Sound_Buffer for "foo".
BufferKeyList mBufferKeys;
SoundBufferList mSoundBuffers;
size_t mBufferCacheSize; size_t mBufferCacheSize;
typedef std::map<std::string,Sound_Loudness> NameLoudnessMap; typedef std::map<std::string,Sound_Loudness> NameLoudnessMap;

Loading…
Cancel
Save