mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-31 21:45:35 +00:00
Separate sound buffer pool from sound manager
This commit is contained in:
parent
2d61db555b
commit
944033db4e
7 changed files with 276 additions and 184 deletions
|
@ -58,6 +58,7 @@ add_openmw_dir (mwscript
|
|||
add_openmw_dir (mwsound
|
||||
soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output
|
||||
loudness movieaudiofactory alext efx efx-presets regionsoundselector watersoundupdater volumesettings
|
||||
sound_buffer
|
||||
)
|
||||
|
||||
add_openmw_dir (mwworld
|
||||
|
|
|
@ -7,6 +7,13 @@
|
|||
|
||||
namespace MWSound
|
||||
{
|
||||
// Extra play flags, not intended for caller use
|
||||
enum PlayModeEx
|
||||
{
|
||||
Play_2D = 0,
|
||||
Play_3D = 1 << 31,
|
||||
};
|
||||
|
||||
// For testing individual PlayMode flags
|
||||
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); }
|
||||
|
|
154
apps/openmw/mwsound/sound_buffer.cpp
Normal file
154
apps/openmw/mwsound/sound_buffer.cpp
Normal file
|
@ -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
|
||||
#define GAME_SOUND_SOUND_BUFFER_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "sound_output.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct Sound;
|
||||
}
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
class SoundBufferPool;
|
||||
|
||||
class Sound_Buffer
|
||||
{
|
||||
public:
|
||||
std::string mResourceName;
|
||||
public:
|
||||
Sound_Buffer(std::string resname, float volume, float mindist, float maxdist)
|
||||
: mResourceName(std::move(resname)), mVolume(volume), mMinDist(mindist), mMaxDist(maxdist)
|
||||
{}
|
||||
|
||||
float mVolume;
|
||||
float mMinDist, mMaxDist;
|
||||
const std::string& getResourceName() const noexcept { return mResourceName; }
|
||||
|
||||
Sound_Handle mHandle;
|
||||
Sound_Handle getHandle() const noexcept { return mHandle; }
|
||||
|
||||
size_t mUses;
|
||||
float getVolume() const noexcept { return mVolume; }
|
||||
|
||||
Sound_Buffer(std::string resname, float volume, float mindist, float maxdist)
|
||||
: mResourceName(resname), mVolume(volume), mMinDist(mindist), mMaxDist(maxdist), mHandle(nullptr), mUses(0)
|
||||
{ }
|
||||
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);
|
||||
}
|
||||
|
||||
void clear();
|
||||
|
||||
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;
|
||||
|
||||
inline Sound_Buffer* insertSound(const std::string& soundId, const ESM::Sound& sound);
|
||||
|
||||
inline void unloadUnused();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "soundmanagerimp.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
|
@ -25,6 +25,12 @@ namespace MWSound
|
|||
Auto
|
||||
};
|
||||
|
||||
enum Environment
|
||||
{
|
||||
Env_Normal,
|
||||
Env_Underwater
|
||||
};
|
||||
|
||||
class Sound_Output
|
||||
{
|
||||
SoundManager &mManager;
|
||||
|
@ -81,6 +87,7 @@ namespace MWSound
|
|||
|
||||
friend class OpenAL_Output;
|
||||
friend class SoundManager;
|
||||
friend class SoundBufferPool;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -56,8 +56,7 @@ namespace MWSound
|
|||
: mVFS(vfs)
|
||||
, mOutput(new DEFAULT_OUTPUT(*this))
|
||||
, mWaterSoundUpdater(makeWaterSoundUpdaterSettings())
|
||||
, mSoundBuffers(new SoundBufferList::element_type())
|
||||
, mBufferCacheSize(0)
|
||||
, mSoundBuffers(*vfs, *mOutput)
|
||||
, mListenerUnderwater(false)
|
||||
, mListenerPos(0,0,0)
|
||||
, mListenerDir(1,0,0)
|
||||
|
@ -69,11 +68,6 @@ namespace MWSound
|
|||
, mLastCell(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)
|
||||
{
|
||||
Log(Debug::Info) << "Sound disabled.";
|
||||
|
@ -116,13 +110,7 @@ namespace MWSound
|
|||
SoundManager::~SoundManager()
|
||||
{
|
||||
clear();
|
||||
for(Sound_Buffer &sfx : *mSoundBuffers)
|
||||
{
|
||||
if(sfx.mHandle)
|
||||
mOutput->unloadSound(sfx.mHandle);
|
||||
sfx.mHandle = nullptr;
|
||||
}
|
||||
mUnusedBuffers.clear();
|
||||
mSoundBuffers.clear();
|
||||
mOutput.reset();
|
||||
}
|
||||
|
||||
|
@ -132,112 +120,18 @@ namespace MWSound
|
|||
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,
|
||||
// minRange, and maxRange)
|
||||
Sound_Buffer *SoundManager::lookupSound(const std::string &soundId) const
|
||||
{
|
||||
NameBufferMap::const_iterator snd = mBufferNameMap.find(soundId);
|
||||
if(snd != mBufferNameMap.end())
|
||||
{
|
||||
Sound_Buffer *sfx = snd->second;
|
||||
if(sfx->mHandle) return sfx;
|
||||
}
|
||||
return nullptr;
|
||||
return mSoundBuffers.lookup(soundId);
|
||||
}
|
||||
|
||||
// Lookup a soundId for its sound data (resource name, local volume,
|
||||
// minRange, and maxRange), and ensure it's ready for use.
|
||||
Sound_Buffer *SoundManager::loadSound(const std::string &soundId)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
#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;
|
||||
return mSoundBuffers.load(soundId);
|
||||
}
|
||||
|
||||
DecoderPtr SoundManager::loadVoice(const std::string &voicefile)
|
||||
|
@ -624,23 +518,18 @@ namespace MWSound
|
|||
SoundPtr sound = getSoundRef();
|
||||
sound->init([&] {
|
||||
SoundParams params;
|
||||
params.mVolume = volume * sfx->mVolume;
|
||||
params.mVolume = volume * sfx->getVolume();
|
||||
params.mBaseVolume = volumeFromType(type);
|
||||
params.mPitch = pitch;
|
||||
params.mFlags = mode | type | Play_2D;
|
||||
return params;
|
||||
} ());
|
||||
if(!mOutput->playSound(sound.get(), sfx->mHandle, offset))
|
||||
if(!mOutput->playSound(sound.get(), sfx->getHandle(), offset))
|
||||
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();
|
||||
mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx);
|
||||
mSoundBuffers.use(*sfx);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -668,40 +557,35 @@ namespace MWSound
|
|||
{
|
||||
sound->init([&] {
|
||||
SoundParams params;
|
||||
params.mVolume = volume * sfx->mVolume;
|
||||
params.mVolume = volume * sfx->getVolume();
|
||||
params.mBaseVolume = volumeFromType(type);
|
||||
params.mPitch = pitch;
|
||||
params.mFlags = mode | type | Play_2D;
|
||||
return params;
|
||||
} ());
|
||||
played = mOutput->playSound(sound.get(), sfx->mHandle, offset);
|
||||
played = mOutput->playSound(sound.get(), sfx->getHandle(), offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
sound->init([&] {
|
||||
SoundParams params;
|
||||
params.mPos = objpos;
|
||||
params.mVolume = volume * sfx->mVolume;
|
||||
params.mVolume = volume * sfx->getVolume();
|
||||
params.mBaseVolume = volumeFromType(type);
|
||||
params.mPitch = pitch;
|
||||
params.mMinDistance = sfx->mMinDist;
|
||||
params.mMaxDistance = sfx->mMaxDist;
|
||||
params.mMinDistance = sfx->getMinDist();
|
||||
params.mMaxDistance = sfx->getMaxDist();
|
||||
params.mFlags = mode | type | Play_3D;
|
||||
return params;
|
||||
} ());
|
||||
played = mOutput->playSound3D(sound.get(), sfx->mHandle, offset);
|
||||
played = mOutput->playSound3D(sound.get(), sfx->getHandle(), offset);
|
||||
}
|
||||
if(!played)
|
||||
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();
|
||||
mActiveSounds[ptr].emplace_back(std::move(sound), sfx);
|
||||
mSoundBuffers.use(*sfx);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -720,25 +604,20 @@ namespace MWSound
|
|||
sound->init([&] {
|
||||
SoundParams params;
|
||||
params.mPos = initialPos;
|
||||
params.mVolume = volume * sfx->mVolume;
|
||||
params.mVolume = volume * sfx->getVolume();
|
||||
params.mBaseVolume = volumeFromType(type);
|
||||
params.mPitch = pitch;
|
||||
params.mMinDistance = sfx->mMinDist;
|
||||
params.mMaxDistance = sfx->mMaxDist;
|
||||
params.mMinDistance = sfx->getMinDist();
|
||||
params.mMaxDistance = sfx->getMaxDist();
|
||||
params.mFlags = mode | type | Play_3D;
|
||||
return params;
|
||||
} ());
|
||||
if(!mOutput->playSound3D(sound.get(), sfx->mHandle, offset))
|
||||
if(!mOutput->playSound3D(sound.get(), sfx->getHandle(), offset))
|
||||
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();
|
||||
mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx);
|
||||
mSoundBuffers.use(*sfx);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -921,7 +800,7 @@ namespace MWSound
|
|||
case WaterSoundAction::DoNothing:
|
||||
break;
|
||||
case WaterSoundAction::SetVolume:
|
||||
mNearWaterSound->setVolume(update.mVolume * sfx->mVolume);
|
||||
mNearWaterSound->setVolume(update.mVolume * sfx->getVolume());
|
||||
break;
|
||||
case WaterSoundAction::FinishSound:
|
||||
mOutput->finishSound(mNearWaterSound);
|
||||
|
@ -1028,7 +907,6 @@ namespace MWSound
|
|||
while(sndidx != snditer->second.end())
|
||||
{
|
||||
Sound *sound = sndidx->first.get();
|
||||
Sound_Buffer *sfx = sndidx->second;
|
||||
|
||||
if(!ptr.isEmpty() && sound->getIs3D())
|
||||
{
|
||||
|
@ -1050,8 +928,7 @@ namespace MWSound
|
|||
mUnderwaterSound = nullptr;
|
||||
if (sound == mNearWaterSound)
|
||||
mNearWaterSound = nullptr;
|
||||
if(sfx->mUses-- == 1)
|
||||
mUnusedBuffers.push_front(sfx);
|
||||
mSoundBuffers.release(*sndidx->second);
|
||||
sndidx = snditer->second.erase(sndidx);
|
||||
}
|
||||
else
|
||||
|
@ -1313,9 +1190,7 @@ namespace MWSound
|
|||
for(SoundBufferRefPair &sndbuf : snd.second)
|
||||
{
|
||||
mOutput->finishSound(sndbuf.first.get());
|
||||
Sound_Buffer *sfx = sndbuf.second;
|
||||
if(sfx->mUses-- == 1)
|
||||
mUnusedBuffers.push_front(sfx);
|
||||
mSoundBuffers.release(*sndbuf.second);
|
||||
}
|
||||
}
|
||||
mActiveSounds.clear();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
|
@ -18,6 +17,7 @@
|
|||
#include "watersoundupdater.hpp"
|
||||
#include "type.hpp"
|
||||
#include "volumesettings.hpp"
|
||||
#include "sound_buffer.hpp"
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
|
@ -36,17 +36,6 @@ namespace MWSound
|
|||
struct Sound_Decoder;
|
||||
class Sound;
|
||||
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 StreamPtr = Misc::ObjectPtr<Stream>;
|
||||
|
@ -66,21 +55,7 @@ namespace MWSound
|
|||
|
||||
WaterSoundUpdater mWaterSoundUpdater;
|
||||
|
||||
typedef std::unique_ptr<std::deque<Sound_Buffer> > SoundBufferList;
|
||||
// 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;
|
||||
SoundBufferPool mSoundBuffers;
|
||||
|
||||
Misc::ObjectPool<Sound> mSounds;
|
||||
|
||||
|
|
Loading…
Reference in a new issue