Separate sound buffer pool from sound manager

pull/593/head
elsid 5 years ago
parent 2d61db555b
commit 944033db4e
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

@ -58,6 +58,7 @@ add_openmw_dir (mwscript
add_openmw_dir (mwsound add_openmw_dir (mwsound
soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output
loudness movieaudiofactory alext efx efx-presets regionsoundselector watersoundupdater volumesettings loudness movieaudiofactory alext efx efx-presets regionsoundselector watersoundupdater volumesettings
sound_buffer
) )
add_openmw_dir (mwworld add_openmw_dir (mwworld

@ -7,6 +7,13 @@
namespace MWSound namespace MWSound
{ {
// Extra play flags, not intended for caller use
enum PlayModeEx
{
Play_2D = 0,
Play_3D = 1 << 31,
};
// For testing individual PlayMode flags // For testing individual PlayMode flags
inline int operator&(int a, PlayMode b) { return a & static_cast<int>(b); } inline int operator&(int a, PlayMode b) { return a & static_cast<int>(b); }
inline int operator&(PlayMode a, PlayMode b) { return static_cast<int>(a) & static_cast<int>(b); } inline int operator&(PlayMode a, PlayMode b) { return static_cast<int>(a) & static_cast<int>(b); }

@ -0,0 +1,154 @@
#include "sound_buffer.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/esmstore.hpp"
#include <components/debug/debuglog.hpp>
#include <components/settings/settings.hpp>
#include <components/vfs/manager.hpp>
#include <algorithm>
#include <cmath>
namespace MWSound
{
namespace
{
struct AudioParams
{
float mAudioDefaultMinDistance;
float mAudioDefaultMaxDistance;
float mAudioMinDistanceMult;
float mAudioMaxDistanceMult;
};
AudioParams makeAudioParams(const MWBase::World& world)
{
const auto& settings = world.getStore().get<ESM::GameSetting>();
AudioParams params;
params.mAudioDefaultMinDistance = settings.find("fAudioDefaultMinDistance")->mValue.getFloat();
params.mAudioDefaultMaxDistance = settings.find("fAudioDefaultMaxDistance")->mValue.getFloat();
params.mAudioMinDistanceMult = settings.find("fAudioMinDistanceMult")->mValue.getFloat();
params.mAudioMaxDistanceMult = settings.find("fAudioMaxDistanceMult")->mValue.getFloat();
return params;
}
}
SoundBufferPool::SoundBufferPool(const VFS::Manager& vfs, Sound_Output& output) :
mVfs(&vfs),
mOutput(&output),
mBufferCacheMax(std::max(Settings::Manager::getInt("buffer cache max", "Sound"), 1) * 1024 * 1024),
mBufferCacheMin(std::min(static_cast<std::size_t>(std::max(Settings::Manager::getInt("buffer cache min", "Sound"), 1)) * 1024 * 1024, mBufferCacheMax))
{
}
SoundBufferPool::~SoundBufferPool()
{
clear();
}
Sound_Buffer* SoundBufferPool::lookup(const std::string& soundId) const
{
const auto it = mBufferNameMap.find(soundId);
if (it != mBufferNameMap.end())
{
Sound_Buffer* sfx = it->second;
if (sfx->getHandle() != nullptr)
return sfx;
}
return nullptr;
}
Sound_Buffer* SoundBufferPool::load(const std::string& soundId)
{
if (mBufferNameMap.empty())
{
for (const ESM::Sound& sound : MWBase::Environment::get().getWorld()->getStore().get<ESM::Sound>())
insertSound(Misc::StringUtils::lowerCase(sound.mId), sound);
}
Sound_Buffer* sfx;
const auto it = mBufferNameMap.find(soundId);
if (it != mBufferNameMap.end())
sfx = it->second;
else
{
const ESM::Sound *sound = MWBase::Environment::get().getWorld()->getStore().get<ESM::Sound>().search(soundId);
if (sound == nullptr)
return {};
sfx = insertSound(soundId, *sound);
}
if (sfx->getHandle() == nullptr)
{
Sound_Handle handle;
size_t size;
std::tie(handle, size) = mOutput->loadSound(sfx->getResourceName());
if (handle == nullptr)
return {};
sfx->mHandle = handle;
mBufferCacheSize += size;
if (mBufferCacheSize > mBufferCacheMax)
{
unloadUnused();
if (!mUnusedBuffers.empty() && mBufferCacheSize > mBufferCacheMax)
Log(Debug::Warning) << "No unused sound buffers to free, using " << mBufferCacheSize << " bytes!";
}
mUnusedBuffers.push_front(sfx);
}
return sfx;
}
void SoundBufferPool::clear()
{
for (auto &sfx : mSoundBuffers)
{
if(sfx.mHandle)
mOutput->unloadSound(sfx.mHandle);
sfx.mHandle = nullptr;
}
mUnusedBuffers.clear();
}
Sound_Buffer* SoundBufferPool::insertSound(const std::string& soundId, const ESM::Sound& sound)
{
static const AudioParams audioParams = makeAudioParams(*MWBase::Environment::get().getWorld());
float volume = static_cast<float>(std::pow(10.0, (sound.mData.mVolume / 255.0 * 3348.0 - 3348.0) / 2000.0));
float min = sound.mData.mMinRange;
float max = sound.mData.mMaxRange;
if (min == 0 && max == 0)
{
min = audioParams.mAudioDefaultMinDistance;
max = audioParams.mAudioDefaultMaxDistance;
}
min *= audioParams.mAudioMinDistanceMult;
max *= audioParams.mAudioMaxDistanceMult;
min = std::max(min, 1.0f);
max = std::max(min, max);
Sound_Buffer& sfx = mSoundBuffers.emplace_back("Sound/" + sound.mSound, volume, min, max);
mVfs->normalizeFilename(sfx.mResourceName);
mBufferNameMap.emplace(soundId, &sfx);
return &sfx;
}
void SoundBufferPool::unloadUnused()
{
while (!mUnusedBuffers.empty() && mBufferCacheSize > mBufferCacheMin)
{
Sound_Buffer* const unused = mUnusedBuffers.back();
mBufferCacheSize -= mOutput->unloadSound(unused->getHandle());
unused->mHandle = nullptr;
mUnusedBuffers.pop_back();
}
}
}

@ -1,27 +1,100 @@
#ifndef GAME_SOUND_SOUND_BUFFER_H #ifndef GAME_SOUND_SOUND_BUFFER_H
#define GAME_SOUND_SOUND_BUFFER_H #define GAME_SOUND_SOUND_BUFFER_H
#include <algorithm>
#include <string> #include <string>
#include <deque>
#include <unordered_map>
#include "sound_output.hpp" #include "sound_output.hpp"
namespace ESM
{
struct Sound;
}
namespace VFS
{
class Manager;
}
namespace MWSound namespace MWSound
{ {
class SoundBufferPool;
class Sound_Buffer class Sound_Buffer
{ {
public: public:
std::string mResourceName; Sound_Buffer(std::string resname, float volume, float mindist, float maxdist)
: mResourceName(std::move(resname)), mVolume(volume), mMinDist(mindist), mMaxDist(maxdist)
{}
const std::string& getResourceName() const noexcept { return mResourceName; }
Sound_Handle getHandle() const noexcept { return mHandle; }
float getVolume() const noexcept { return mVolume; }
float getMinDist() const noexcept { return mMinDist; }
float getMaxDist() const noexcept { return mMaxDist; }
private:
std::string mResourceName;
float mVolume = 0;
float mMinDist = 0;
float mMaxDist = 0;
Sound_Handle mHandle = nullptr;
std::size_t mUses = 0;
friend class SoundBufferPool;
};
class SoundBufferPool
{
public:
SoundBufferPool(const VFS::Manager& vfs, Sound_Output& output);
SoundBufferPool(const SoundBufferPool&) = delete;
~SoundBufferPool();
Sound_Buffer* lookup(const std::string& soundId) const;
Sound_Buffer* load(const std::string& soundId);
void use(Sound_Buffer& sfx)
{
if (sfx.mUses++ == 0)
{
const auto it = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), &sfx);
if (it != mUnusedBuffers.end())
mUnusedBuffers.erase(it);
}
}
void release(Sound_Buffer& sfx)
{
if (--sfx.mUses == 0)
mUnusedBuffers.push_front(&sfx);
}
float mVolume; void clear();
float mMinDist, mMaxDist;
Sound_Handle mHandle; private:
const VFS::Manager* const mVfs;
Sound_Output* mOutput;
std::deque<Sound_Buffer> mSoundBuffers;
std::unordered_map<std::string, Sound_Buffer*> mBufferNameMap;
std::size_t mBufferCacheMax;
std::size_t mBufferCacheMin;
std::size_t mBufferCacheSize = 0;
// NOTE: unused buffers are stored in front-newest order.
std::deque<Sound_Buffer*> mUnusedBuffers;
size_t mUses; inline Sound_Buffer* insertSound(const std::string& soundId, const ESM::Sound& sound);
Sound_Buffer(std::string resname, float volume, float mindist, float maxdist) inline void unloadUnused();
: mResourceName(resname), mVolume(volume), mMinDist(mindist), mMaxDist(maxdist), mHandle(nullptr), mUses(0)
{ }
}; };
} }

@ -5,7 +5,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "soundmanagerimp.hpp" #include "../mwbase/soundmanager.hpp"
namespace MWSound namespace MWSound
{ {
@ -25,6 +25,12 @@ namespace MWSound
Auto Auto
}; };
enum Environment
{
Env_Normal,
Env_Underwater
};
class Sound_Output class Sound_Output
{ {
SoundManager &mManager; SoundManager &mManager;
@ -81,6 +87,7 @@ namespace MWSound
friend class OpenAL_Output; friend class OpenAL_Output;
friend class SoundManager; friend class SoundManager;
friend class SoundBufferPool;
}; };
} }

@ -56,8 +56,7 @@ namespace MWSound
: mVFS(vfs) : mVFS(vfs)
, mOutput(new DEFAULT_OUTPUT(*this)) , mOutput(new DEFAULT_OUTPUT(*this))
, mWaterSoundUpdater(makeWaterSoundUpdaterSettings()) , mWaterSoundUpdater(makeWaterSoundUpdaterSettings())
, mSoundBuffers(new SoundBufferList::element_type()) , mSoundBuffers(*vfs, *mOutput)
, mBufferCacheSize(0)
, mListenerUnderwater(false) , mListenerUnderwater(false)
, mListenerPos(0,0,0) , mListenerPos(0,0,0)
, mListenerDir(1,0,0) , mListenerDir(1,0,0)
@ -69,11 +68,6 @@ namespace MWSound
, mLastCell(nullptr) , mLastCell(nullptr)
, mCurrentRegionSound(nullptr) , mCurrentRegionSound(nullptr)
{ {
mBufferCacheMin = std::max(Settings::Manager::getInt("buffer cache min", "Sound"), 1);
mBufferCacheMax = std::max(Settings::Manager::getInt("buffer cache max", "Sound"), 1);
mBufferCacheMax *= 1024*1024;
mBufferCacheMin = std::min(mBufferCacheMin*1024*1024, mBufferCacheMax);
if(!useSound) if(!useSound)
{ {
Log(Debug::Info) << "Sound disabled."; Log(Debug::Info) << "Sound disabled.";
@ -116,13 +110,7 @@ namespace MWSound
SoundManager::~SoundManager() SoundManager::~SoundManager()
{ {
clear(); clear();
for(Sound_Buffer &sfx : *mSoundBuffers) mSoundBuffers.clear();
{
if(sfx.mHandle)
mOutput->unloadSound(sfx.mHandle);
sfx.mHandle = nullptr;
}
mUnusedBuffers.clear();
mOutput.reset(); mOutput.reset();
} }
@ -132,112 +120,18 @@ namespace MWSound
return DecoderPtr(new DEFAULT_DECODER (mVFS)); return DecoderPtr(new DEFAULT_DECODER (mVFS));
} }
Sound_Buffer *SoundManager::insertSound(const std::string &soundId, const ESM::Sound *sound)
{
MWBase::World* world = MWBase::Environment::get().getWorld();
static const float fAudioDefaultMinDistance = world->getStore().get<ESM::GameSetting>().find("fAudioDefaultMinDistance")->mValue.getFloat();
static const float fAudioDefaultMaxDistance = world->getStore().get<ESM::GameSetting>().find("fAudioDefaultMaxDistance")->mValue.getFloat();
static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->mValue.getFloat();
static const float fAudioMaxDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMaxDistanceMult")->mValue.getFloat();
float volume, min, max;
volume = static_cast<float>(pow(10.0, (sound->mData.mVolume / 255.0*3348.0 - 3348.0) / 2000.0));
min = sound->mData.mMinRange;
max = sound->mData.mMaxRange;
if (min == 0 && max == 0)
{
min = fAudioDefaultMinDistance;
max = fAudioDefaultMaxDistance;
}
min *= fAudioMinDistanceMult;
max *= fAudioMaxDistanceMult;
min = std::max(min, 1.0f);
max = std::max(min, max);
Sound_Buffer *sfx = &*mSoundBuffers->insert(mSoundBuffers->end(),
Sound_Buffer("Sound/"+sound->mSound, volume, min, max)
);
mVFS->normalizeFilename(sfx->mResourceName);
mBufferNameMap.insert(std::make_pair(soundId, sfx));
return sfx;
}
// Lookup a soundId for its sound data (resource name, local volume, // Lookup a soundId for its sound data (resource name, local volume,
// minRange, and maxRange) // minRange, and maxRange)
Sound_Buffer *SoundManager::lookupSound(const std::string &soundId) const Sound_Buffer *SoundManager::lookupSound(const std::string &soundId) const
{ {
NameBufferMap::const_iterator snd = mBufferNameMap.find(soundId); return mSoundBuffers.lookup(soundId);
if(snd != mBufferNameMap.end())
{
Sound_Buffer *sfx = snd->second;
if(sfx->mHandle) return sfx;
}
return nullptr;
} }
// Lookup a soundId for its sound data (resource name, local volume, // Lookup a soundId for its sound data (resource name, local volume,
// minRange, and maxRange), and ensure it's ready for use. // minRange, and maxRange), and ensure it's ready for use.
Sound_Buffer *SoundManager::loadSound(const std::string &soundId) Sound_Buffer *SoundManager::loadSound(const std::string &soundId)
{ {
#ifdef __GNUC__ return mSoundBuffers.load(soundId);
#define LIKELY(x) __builtin_expect((bool)(x), true)
#define UNLIKELY(x) __builtin_expect((bool)(x), false)
#else
#define LIKELY(x) (bool)(x)
#define UNLIKELY(x) (bool)(x)
#endif
if(UNLIKELY(mBufferNameMap.empty()))
{
MWBase::World *world = MWBase::Environment::get().getWorld();
for(const ESM::Sound &sound : world->getStore().get<ESM::Sound>())
insertSound(Misc::StringUtils::lowerCase(sound.mId), &sound);
}
Sound_Buffer *sfx;
NameBufferMap::const_iterator snd = mBufferNameMap.find(soundId);
if(LIKELY(snd != mBufferNameMap.end()))
sfx = snd->second;
else
{
MWBase::World *world = MWBase::Environment::get().getWorld();
const ESM::Sound *sound = world->getStore().get<ESM::Sound>().search(soundId);
if(!sound) return nullptr;
sfx = insertSound(soundId, sound);
}
#undef LIKELY
#undef UNLIKELY
if(!sfx->mHandle)
{
size_t size;
std::tie(sfx->mHandle, size) = mOutput->loadSound(sfx->mResourceName);
if(!sfx->mHandle) return nullptr;
mBufferCacheSize += size;
if(mBufferCacheSize > mBufferCacheMax)
{
do {
if(mUnusedBuffers.empty())
{
Log(Debug::Warning) << "No unused sound buffers to free, using " << mBufferCacheSize << " bytes!";
break;
}
Sound_Buffer *unused = mUnusedBuffers.back();
size = mOutput->unloadSound(unused->mHandle);
mBufferCacheSize -= size;
unused->mHandle = nullptr;
mUnusedBuffers.pop_back();
} while(mBufferCacheSize > mBufferCacheMin);
}
mUnusedBuffers.push_front(sfx);
}
return sfx;
} }
DecoderPtr SoundManager::loadVoice(const std::string &voicefile) DecoderPtr SoundManager::loadVoice(const std::string &voicefile)
@ -624,23 +518,18 @@ namespace MWSound
SoundPtr sound = getSoundRef(); SoundPtr sound = getSoundRef();
sound->init([&] { sound->init([&] {
SoundParams params; SoundParams params;
params.mVolume = volume * sfx->mVolume; params.mVolume = volume * sfx->getVolume();
params.mBaseVolume = volumeFromType(type); params.mBaseVolume = volumeFromType(type);
params.mPitch = pitch; params.mPitch = pitch;
params.mFlags = mode | type | Play_2D; params.mFlags = mode | type | Play_2D;
return params; return params;
} ()); } ());
if(!mOutput->playSound(sound.get(), sfx->mHandle, offset)) if(!mOutput->playSound(sound.get(), sfx->getHandle(), offset))
return nullptr; return nullptr;
if(sfx->mUses++ == 0)
{
SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx);
if(iter != mUnusedBuffers.end())
mUnusedBuffers.erase(iter);
}
Sound* result = sound.get(); Sound* result = sound.get();
mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx); mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx);
mSoundBuffers.use(*sfx);
return result; return result;
} }
@ -668,40 +557,35 @@ namespace MWSound
{ {
sound->init([&] { sound->init([&] {
SoundParams params; SoundParams params;
params.mVolume = volume * sfx->mVolume; params.mVolume = volume * sfx->getVolume();
params.mBaseVolume = volumeFromType(type); params.mBaseVolume = volumeFromType(type);
params.mPitch = pitch; params.mPitch = pitch;
params.mFlags = mode | type | Play_2D; params.mFlags = mode | type | Play_2D;
return params; return params;
} ()); } ());
played = mOutput->playSound(sound.get(), sfx->mHandle, offset); played = mOutput->playSound(sound.get(), sfx->getHandle(), offset);
} }
else else
{ {
sound->init([&] { sound->init([&] {
SoundParams params; SoundParams params;
params.mPos = objpos; params.mPos = objpos;
params.mVolume = volume * sfx->mVolume; params.mVolume = volume * sfx->getVolume();
params.mBaseVolume = volumeFromType(type); params.mBaseVolume = volumeFromType(type);
params.mPitch = pitch; params.mPitch = pitch;
params.mMinDistance = sfx->mMinDist; params.mMinDistance = sfx->getMinDist();
params.mMaxDistance = sfx->mMaxDist; params.mMaxDistance = sfx->getMaxDist();
params.mFlags = mode | type | Play_3D; params.mFlags = mode | type | Play_3D;
return params; return params;
} ()); } ());
played = mOutput->playSound3D(sound.get(), sfx->mHandle, offset); played = mOutput->playSound3D(sound.get(), sfx->getHandle(), offset);
} }
if(!played) if(!played)
return nullptr; return nullptr;
if(sfx->mUses++ == 0)
{
SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx);
if(iter != mUnusedBuffers.end())
mUnusedBuffers.erase(iter);
}
Sound* result = sound.get(); Sound* result = sound.get();
mActiveSounds[ptr].emplace_back(std::move(sound), sfx); mActiveSounds[ptr].emplace_back(std::move(sound), sfx);
mSoundBuffers.use(*sfx);
return result; return result;
} }
@ -720,25 +604,20 @@ namespace MWSound
sound->init([&] { sound->init([&] {
SoundParams params; SoundParams params;
params.mPos = initialPos; params.mPos = initialPos;
params.mVolume = volume * sfx->mVolume; params.mVolume = volume * sfx->getVolume();
params.mBaseVolume = volumeFromType(type); params.mBaseVolume = volumeFromType(type);
params.mPitch = pitch; params.mPitch = pitch;
params.mMinDistance = sfx->mMinDist; params.mMinDistance = sfx->getMinDist();
params.mMaxDistance = sfx->mMaxDist; params.mMaxDistance = sfx->getMaxDist();
params.mFlags = mode | type | Play_3D; params.mFlags = mode | type | Play_3D;
return params; return params;
} ()); } ());
if(!mOutput->playSound3D(sound.get(), sfx->mHandle, offset)) if(!mOutput->playSound3D(sound.get(), sfx->getHandle(), offset))
return nullptr; return nullptr;
if(sfx->mUses++ == 0)
{
SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx);
if(iter != mUnusedBuffers.end())
mUnusedBuffers.erase(iter);
}
Sound* result = sound.get(); Sound* result = sound.get();
mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx); mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx);
mSoundBuffers.use(*sfx);
return result; return result;
} }
@ -921,7 +800,7 @@ namespace MWSound
case WaterSoundAction::DoNothing: case WaterSoundAction::DoNothing:
break; break;
case WaterSoundAction::SetVolume: case WaterSoundAction::SetVolume:
mNearWaterSound->setVolume(update.mVolume * sfx->mVolume); mNearWaterSound->setVolume(update.mVolume * sfx->getVolume());
break; break;
case WaterSoundAction::FinishSound: case WaterSoundAction::FinishSound:
mOutput->finishSound(mNearWaterSound); mOutput->finishSound(mNearWaterSound);
@ -1028,7 +907,6 @@ namespace MWSound
while(sndidx != snditer->second.end()) while(sndidx != snditer->second.end())
{ {
Sound *sound = sndidx->first.get(); Sound *sound = sndidx->first.get();
Sound_Buffer *sfx = sndidx->second;
if(!ptr.isEmpty() && sound->getIs3D()) if(!ptr.isEmpty() && sound->getIs3D())
{ {
@ -1050,8 +928,7 @@ namespace MWSound
mUnderwaterSound = nullptr; mUnderwaterSound = nullptr;
if (sound == mNearWaterSound) if (sound == mNearWaterSound)
mNearWaterSound = nullptr; mNearWaterSound = nullptr;
if(sfx->mUses-- == 1) mSoundBuffers.release(*sndidx->second);
mUnusedBuffers.push_front(sfx);
sndidx = snditer->second.erase(sndidx); sndidx = snditer->second.erase(sndidx);
} }
else else
@ -1313,9 +1190,7 @@ namespace MWSound
for(SoundBufferRefPair &sndbuf : snd.second) for(SoundBufferRefPair &sndbuf : snd.second)
{ {
mOutput->finishSound(sndbuf.first.get()); mOutput->finishSound(sndbuf.first.get());
Sound_Buffer *sfx = sndbuf.second; mSoundBuffers.release(*sndbuf.second);
if(sfx->mUses-- == 1)
mUnusedBuffers.push_front(sfx);
} }
} }
mActiveSounds.clear(); mActiveSounds.clear();

@ -4,7 +4,6 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <deque>
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
@ -18,6 +17,7 @@
#include "watersoundupdater.hpp" #include "watersoundupdater.hpp"
#include "type.hpp" #include "type.hpp"
#include "volumesettings.hpp" #include "volumesettings.hpp"
#include "sound_buffer.hpp"
namespace VFS namespace VFS
{ {
@ -36,17 +36,6 @@ namespace MWSound
struct Sound_Decoder; struct Sound_Decoder;
class Sound; class Sound;
class Stream; class Stream;
class Sound_Buffer;
enum Environment {
Env_Normal,
Env_Underwater
};
// Extra play flags, not intended for caller use
enum PlayModeEx {
Play_2D = 0,
Play_3D = 1<<31
};
using SoundPtr = Misc::ObjectPtr<Sound>; using SoundPtr = Misc::ObjectPtr<Sound>;
using StreamPtr = Misc::ObjectPtr<Stream>; using StreamPtr = Misc::ObjectPtr<Stream>;
@ -66,21 +55,7 @@ namespace MWSound
WaterSoundUpdater mWaterSoundUpdater; WaterSoundUpdater mWaterSoundUpdater;
typedef std::unique_ptr<std::deque<Sound_Buffer> > SoundBufferList; SoundBufferPool mSoundBuffers;
// List of sound buffers, grown as needed. New enties are added to the
// back, allowing existing Sound_Buffer references/pointers to remain
// valid.
SoundBufferList mSoundBuffers;
size_t mBufferCacheMin;
size_t mBufferCacheMax;
size_t mBufferCacheSize;
typedef std::unordered_map<std::string,Sound_Buffer*> NameBufferMap;
NameBufferMap mBufferNameMap;
// NOTE: unused buffers are stored in front-newest order.
typedef std::deque<Sound_Buffer*> SoundList;
SoundList mUnusedBuffers;
Misc::ObjectPool<Sound> mSounds; Misc::ObjectPool<Sound> mSounds;

Loading…
Cancel
Save