Merge pull request #1455 from kcat/master

Print sound init info and preload sound buffer info
pull/292/head
scrawl 7 years ago committed by GitHub
commit 242d085da0

@ -192,12 +192,11 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type)
{ AL_FORMAT_STEREO8, ChannelConfig_Stereo, SampleType_UInt8 }, { AL_FORMAT_STEREO8, ChannelConfig_Stereo, SampleType_UInt8 },
}}; }};
auto fmt = std::find_if(fmtlist.cbegin(), fmtlist.cend(), for(auto &fmt : fmtlist)
[chans,type](const FormatEntry &fmt) -> bool {
{ return fmt.chans == chans && fmt.type == type; } if(fmt.chans == chans && fmt.type == type)
); return fmt.format;
if(fmt != fmtlist.cend()) }
return fmt->format;
if(alIsExtensionPresent("AL_EXT_MCFORMATS")) if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
{ {
@ -209,18 +208,16 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type)
{ "AL_FORMAT_71CHN16", ChannelConfig_7point1, SampleType_Int16 }, { "AL_FORMAT_71CHN16", ChannelConfig_7point1, SampleType_Int16 },
{ "AL_FORMAT_71CHN8", ChannelConfig_7point1, SampleType_UInt8 }, { "AL_FORMAT_71CHN8", ChannelConfig_7point1, SampleType_UInt8 },
}}; }};
ALenum format = AL_NONE;
std::find_if(mcfmtlist.cbegin(), mcfmtlist.cend(), for(auto &fmt : mcfmtlist)
[&format,chans,type](const FormatEntryExt &fmt) -> bool {
if(fmt.chans == chans && fmt.type == type)
{ {
if(fmt.chans == chans && fmt.type == type) ALenum format = alGetEnumValue(fmt.name);
format = alGetEnumValue(fmt.name); if(format != 0 && format != -1)
return format != 0 && format != -1; return format;
} }
); }
if(format != 0 && format != -1)
return format;
} }
if(alIsExtensionPresent("AL_EXT_FLOAT32")) if(alIsExtensionPresent("AL_EXT_FLOAT32"))
{ {
@ -228,18 +225,16 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type)
{ "AL_FORMAT_MONO_FLOAT32", ChannelConfig_Mono, SampleType_Float32 }, { "AL_FORMAT_MONO_FLOAT32", ChannelConfig_Mono, SampleType_Float32 },
{ "AL_FORMAT_STEREO_FLOAT32", ChannelConfig_Stereo, SampleType_Float32 }, { "AL_FORMAT_STEREO_FLOAT32", ChannelConfig_Stereo, SampleType_Float32 },
}}; }};
ALenum format = AL_NONE;
std::find_if(fltfmtlist.cbegin(), fltfmtlist.cend(), for(auto &fmt : fltfmtlist)
[&format,chans,type](const FormatEntryExt &fmt) -> bool {
if(fmt.chans == chans && fmt.type == type)
{ {
if(fmt.chans == chans && fmt.type == type) ALenum format = alGetEnumValue(fmt.name);
format = alGetEnumValue(fmt.name); if(format != 0 && format != -1)
return format != 0 && format != -1; return format;
} }
); }
if(format != 0 && format != -1)
return format;
if(alIsExtensionPresent("AL_EXT_MCFORMATS")) if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
{ {
@ -249,16 +244,15 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type)
{ "AL_FORMAT_71CHN32", ChannelConfig_7point1, SampleType_Float32 }, { "AL_FORMAT_71CHN32", ChannelConfig_7point1, SampleType_Float32 },
}}; }};
std::find_if(fltmcfmtlist.cbegin(), fltmcfmtlist.cend(), for(auto &fmt : fltmcfmtlist)
[&format,chans,type](const FormatEntryExt &fmt) -> bool {
if(fmt.chans == chans && fmt.type == type)
{ {
if(fmt.chans == chans && fmt.type == type) ALenum format = alGetEnumValue(fmt.name);
format = alGetEnumValue(fmt.name); if(format != 0 && format != -1)
return format != 0 && format != -1; return format;
} }
); }
if(format != 0 && format != -1)
return format;
} }
} }
@ -547,11 +541,11 @@ ALint OpenAL_SoundStream::refillQueue()
std::vector<char> data(mBufferSize); std::vector<char> data(mBufferSize);
for(;!mIsFinished && (ALuint)queued < mBuffers.size();++queued) for(;!mIsFinished && (ALuint)queued < mBuffers.size();++queued)
{ {
size_t got = mDecoder->read(&data[0], data.size()); size_t got = mDecoder->read(data.data(), data.size());
if(got < data.size()) if(got < data.size())
{ {
mIsFinished = true; mIsFinished = true;
std::memset(&data[got], mSilence, data.size()-got); std::fill(data.begin()+got, data.end(), mSilence);
} }
if(got > 0) if(got > 0)
{ {
@ -559,7 +553,7 @@ ALint OpenAL_SoundStream::refillQueue()
mLoudnessAnalyzer->analyzeLoudness(data); mLoudnessAnalyzer->analyzeLoudness(data);
ALuint bufid = mBuffers[mCurrentBufIdx]; ALuint bufid = mBuffers[mCurrentBufIdx];
alBufferData(bufid, mFormat, &data[0], data.size(), mSampleRate); alBufferData(bufid, mFormat, data.data(), data.size(), mSampleRate);
alSourceQueueBuffers(mSource, 1, &bufid); alSourceQueueBuffers(mSource, 1, &bufid);
mCurrentBufIdx = (mCurrentBufIdx+1) % mBuffers.size(); mCurrentBufIdx = (mCurrentBufIdx+1) % mBuffers.size();
} }
@ -594,25 +588,33 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
{ {
deinit(); deinit();
std::cout<< "Initializing OpenAL..." <<std::endl;
mDevice = alcOpenDevice(devname.c_str()); mDevice = alcOpenDevice(devname.c_str());
if(!mDevice) if(!mDevice && !devname.empty())
{ {
if(devname.empty()) std::cerr<< "Failed to open \""<<devname<<"\", trying default" <<std::endl;
std::cerr<< "Failed to open default audio device" <<std::endl; mDevice = alcOpenDevice(nullptr);
else
std::cerr<< "Failed to open \""<<devname<<"\"" <<std::endl;
return false;
} }
else if(!mDevice)
{ {
const ALCchar *name = NULL; std::cerr<< "Failed to open default audio device" <<std::endl;
if(alcIsExtensionPresent(mDevice, "ALC_ENUMERATE_ALL_EXT")) return false;
name = alcGetString(mDevice, ALC_ALL_DEVICES_SPECIFIER);
if(alcGetError(mDevice) != AL_NO_ERROR || !name)
name = alcGetString(mDevice, ALC_DEVICE_SPECIFIER);
std::cout << "Opened \""<<name<<"\"" << std::endl;
} }
const ALCchar *name = nullptr;
if(alcIsExtensionPresent(mDevice, "ALC_ENUMERATE_ALL_EXT"))
name = alcGetString(mDevice, ALC_ALL_DEVICES_SPECIFIER);
if(alcGetError(mDevice) != AL_NO_ERROR || !name)
name = alcGetString(mDevice, ALC_DEVICE_SPECIFIER);
std::cout<< "Opened \""<<name<<"\"" <<std::endl;
ALCint major=0, minor=0;
alcGetIntegerv(mDevice, ALC_MAJOR_VERSION, 1, &major);
alcGetIntegerv(mDevice, ALC_MINOR_VERSION, 1, &minor);
std::cout<< " ALC Version: "<<major<<"."<<minor<<"\n"<<
" ALC Extensions: "<<alcGetString(mDevice, ALC_EXTENSIONS) <<std::endl;
ALC.EXT_EFX = alcIsExtensionPresent(mDevice, "ALC_EXT_EFX"); ALC.EXT_EFX = alcIsExtensionPresent(mDevice, "ALC_EXT_EFX");
ALC.SOFT_HRTF = alcIsExtensionPresent(mDevice, "ALC_SOFT_HRTF"); ALC.SOFT_HRTF = alcIsExtensionPresent(mDevice, "ALC_SOFT_HRTF");
@ -643,7 +645,7 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
} }
if(index < 0) if(index < 0)
std::cerr<< "Failed to find HRTF name \""<<hrtfname<<"\", using default" <<std::endl; std::cerr<< "Failed to find HRTF \""<<hrtfname<<"\", using default" <<std::endl;
else else
{ {
attrs.push_back(ALC_HRTF_ID_SOFT); attrs.push_back(ALC_HRTF_ID_SOFT);
@ -665,6 +667,11 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
return false; return false;
} }
std::cout<< " Vendor: "<<alGetString(AL_VENDOR)<<"\n"<<
" Renderer: "<<alGetString(AL_RENDERER)<<"\n"<<
" Version: "<<alGetString(AL_VERSION)<<"\n"<<
" Extensions: "<<alGetString(AL_EXTENSIONS)<<std::endl;
if(!ALC.SOFT_HRTF) if(!ALC.SOFT_HRTF)
std::cout<< "HRTF status unavailable" <<std::endl; std::cout<< "HRTF status unavailable" <<std::endl;
else else
@ -698,7 +705,7 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
{ {
ALuint src = 0; ALuint src = 0;
alGenSources(1, &src); alGenSources(1, &src);
if(getALError() != AL_NO_ERROR) if(alGetError() != AL_NO_ERROR)
break; break;
mFreeSources.push_back(src); mFreeSources.push_back(src);
} }
@ -824,8 +831,8 @@ void OpenAL_Output::deinit()
{ {
mStreamThread->removeAll(); mStreamThread->removeAll();
for(size_t i = 0;i < mFreeSources.size();i++) for(ALuint source : mFreeSources)
alDeleteSources(1, &mFreeSources[i]); alDeleteSources(1, &source);
mFreeSources.clear(); mFreeSources.clear();
if(mEffectSlot) if(mEffectSlot)
@ -934,7 +941,7 @@ void OpenAL_Output::setHrtf(const std::string &hrtfname, HrtfMode hrtfmode)
} }
Sound_Handle OpenAL_Output::loadSound(const std::string &fname) std::pair<Sound_Handle,size_t> OpenAL_Output::loadSound(const std::string &fname)
{ {
getALError(); getALError();
@ -959,27 +966,31 @@ Sound_Handle OpenAL_Output::loadSound(const std::string &fname)
decoder->getInfo(&srate, &chans, &type); decoder->getInfo(&srate, &chans, &type);
format = getALFormat(chans, type); format = getALFormat(chans, type);
if(!format) return nullptr; if(!format) return std::make_pair(nullptr, 0);
decoder->readAll(data); decoder->readAll(data);
decoder->close(); decoder->close();
ALint size;
ALuint buf = 0; ALuint buf = 0;
alGenBuffers(1, &buf); alGenBuffers(1, &buf);
alBufferData(buf, format, &data[0], data.size(), srate); alBufferData(buf, format, data.data(), data.size(), srate);
alGetBufferi(buf, AL_SIZE, &size);
if(getALError() != AL_NO_ERROR) if(getALError() != AL_NO_ERROR)
{ {
if(buf && alIsBuffer(buf)) if(buf && alIsBuffer(buf))
alDeleteBuffers(1, &buf); alDeleteBuffers(1, &buf);
getALError(); getALError();
return nullptr; return std::make_pair(nullptr, 0);
} }
return MAKE_PTRID(buf); return std::make_pair(MAKE_PTRID(buf), size);
} }
void OpenAL_Output::unloadSound(Sound_Handle data) size_t OpenAL_Output::unloadSound(Sound_Handle data)
{ {
ALuint buffer = GET_PTRID(data); ALuint buffer = GET_PTRID(data);
if(!buffer) return 0;
// Make sure no sources are playing this buffer before unloading it. // Make sure no sources are playing this buffer before unloading it.
SoundVec::const_iterator iter = mActiveSounds.begin(); SoundVec::const_iterator iter = mActiveSounds.begin();
for(;iter != mActiveSounds.end();++iter) for(;iter != mActiveSounds.end();++iter)
@ -996,19 +1007,11 @@ void OpenAL_Output::unloadSound(Sound_Handle data)
alSourcei(source, AL_BUFFER, 0); alSourcei(source, AL_BUFFER, 0);
} }
} }
alDeleteBuffers(1, &buffer);
getALError();
}
size_t OpenAL_Output::getSoundDataSize(Sound_Handle data) const
{
ALuint buffer = GET_PTRID(data);
ALint size = 0; ALint size = 0;
alGetBufferi(buffer, AL_SIZE, &size); alGetBufferi(buffer, AL_SIZE, &size);
alDeleteBuffers(1, &buffer);
getALError(); getALError();
return size;
return (ALuint)size;
} }
@ -1368,23 +1371,19 @@ void OpenAL_Output::updateListener(const osg::Vec3f &pos, const osg::Vec3f &atdi
if(mWaterFilter) if(mWaterFilter)
{ {
ALuint filter = (env == Env_Underwater) ? mWaterFilter : AL_FILTER_NULL; ALuint filter = (env == Env_Underwater) ? mWaterFilter : AL_FILTER_NULL;
std::for_each(mActiveSounds.cbegin(), mActiveSounds.cend(), for(Sound *sound : mActiveSounds)
[filter](const SoundVec::value_type &item) -> void {
{ if(sound->getUseEnv())
if(item->getUseEnv()) alSourcei(GET_PTRID(sound->mHandle), AL_DIRECT_FILTER, filter);
alSourcei(GET_PTRID(item->mHandle), AL_DIRECT_FILTER, filter); }
} for(Stream *sound : mActiveStreams)
); {
std::for_each(mActiveStreams.cbegin(), mActiveStreams.cend(), if(sound->getUseEnv())
[filter](const StreamVec::value_type &item) -> void alSourcei(
{ reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle)->mSource,
if(item->getUseEnv()) AL_DIRECT_FILTER, filter
alSourcei( );
reinterpret_cast<OpenAL_SoundStream*>(item->mHandle)->mSource, }
AL_DIRECT_FILTER, filter
);
}
);
} }
// Update the environment effect // Update the environment effect
if(mEffectSlot) if(mEffectSlot)
@ -1403,23 +1402,19 @@ void OpenAL_Output::updateListener(const osg::Vec3f &pos, const osg::Vec3f &atdi
void OpenAL_Output::pauseSounds(int types) void OpenAL_Output::pauseSounds(int types)
{ {
std::vector<ALuint> sources; std::vector<ALuint> sources;
std::for_each(mActiveSounds.cbegin(), mActiveSounds.cend(), for(Sound *sound : mActiveSounds)
[types,&sources](const SoundVec::value_type &sound) -> void {
{ if((types&sound->getPlayType()))
if(sound && sound->mHandle && (types&sound->getPlayType())) sources.push_back(GET_PTRID(sound->mHandle));
sources.push_back(GET_PTRID(sound->mHandle)); }
} for(Stream *sound : mActiveStreams)
); {
std::for_each(mActiveStreams.cbegin(), mActiveStreams.cend(), if((types&sound->getPlayType()))
[types,&sources](const StreamVec::value_type &stream) -> void
{ {
if(stream && stream->mHandle && (types&stream->getPlayType())) OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
{ sources.push_back(stream->mSource);
OpenAL_SoundStream *strm = reinterpret_cast<OpenAL_SoundStream*>(stream->mHandle);
sources.push_back(strm->mSource);
}
} }
); }
if(!sources.empty()) if(!sources.empty())
{ {
alSourcePausev(sources.size(), sources.data()); alSourcePausev(sources.size(), sources.data());
@ -1430,23 +1425,19 @@ void OpenAL_Output::pauseSounds(int types)
void OpenAL_Output::resumeSounds(int types) void OpenAL_Output::resumeSounds(int types)
{ {
std::vector<ALuint> sources; std::vector<ALuint> sources;
std::for_each(mActiveSounds.cbegin(), mActiveSounds.cend(), for(Sound *sound : mActiveSounds)
[types,&sources](const SoundVec::value_type &sound) -> void {
{ if((types&sound->getPlayType()))
if(sound && sound->mHandle && (types&sound->getPlayType())) sources.push_back(GET_PTRID(sound->mHandle));
sources.push_back(GET_PTRID(sound->mHandle)); }
} for(Stream *sound : mActiveStreams)
); {
std::for_each(mActiveStreams.cbegin(), mActiveStreams.cend(), if((types&sound->getPlayType()))
[types,&sources](const StreamVec::value_type &stream) -> void
{ {
if(stream && stream->mHandle && (types&stream->getPlayType())) OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
{ sources.push_back(stream->mSource);
OpenAL_SoundStream *strm = reinterpret_cast<OpenAL_SoundStream*>(stream->mHandle);
sources.push_back(strm->mSource);
}
} }
); }
if(!sources.empty()) if(!sources.empty())
{ {
alSourcePlayv(sources.size(), sources.data()); alSourcePlayv(sources.size(), sources.data());

@ -66,9 +66,8 @@ namespace MWSound
virtual std::vector<std::string> enumerateHrtf(); virtual std::vector<std::string> enumerateHrtf();
virtual void setHrtf(const std::string &hrtfname, HrtfMode hrtfmode); virtual void setHrtf(const std::string &hrtfname, HrtfMode hrtfmode);
virtual Sound_Handle loadSound(const std::string &fname); virtual std::pair<Sound_Handle,size_t> loadSound(const std::string &fname);
virtual void unloadSound(Sound_Handle data); virtual size_t unloadSound(Sound_Handle data);
virtual size_t getSoundDataSize(Sound_Handle data) const;
virtual bool playSound(Sound *sound, Sound_Handle data, float offset); virtual bool playSound(Sound *sound, Sound_Handle data, float offset);
virtual bool playSound3D(Sound *sound, Sound_Handle data, float offset); virtual bool playSound3D(Sound *sound, Sound_Handle data, float offset);

@ -36,9 +36,8 @@ namespace MWSound
virtual std::vector<std::string> enumerateHrtf() = 0; virtual std::vector<std::string> enumerateHrtf() = 0;
virtual void setHrtf(const std::string &hrtfname, HrtfMode hrtfmode) = 0; virtual void setHrtf(const std::string &hrtfname, HrtfMode hrtfmode) = 0;
virtual Sound_Handle loadSound(const std::string &fname) = 0; virtual std::pair<Sound_Handle,size_t> loadSound(const std::string &fname) = 0;
virtual void unloadSound(Sound_Handle data) = 0; virtual size_t unloadSound(Sound_Handle data) = 0;
virtual size_t getSoundDataSize(Sound_Handle data) const = 0;
virtual bool playSound(Sound *sound, Sound_Handle data, float offset) = 0; virtual bool playSound(Sound *sound, Sound_Handle data, float offset) = 0;
virtual bool playSound3D(Sound *sound, Sound_Handle data, float offset) = 0; virtual bool playSound3D(Sound *sound, Sound_Handle data, float offset) = 0;

@ -26,11 +26,7 @@
#include "sound.hpp" #include "sound.hpp"
#include "openal_output.hpp" #include "openal_output.hpp"
#define SOUND_OUT "OpenAL"
#include "ffmpeg_decoder.hpp" #include "ffmpeg_decoder.hpp"
#ifndef SOUND_IN
#define SOUND_IN "FFmpeg"
#endif
namespace MWSound namespace MWSound
@ -84,45 +80,35 @@ namespace MWSound
mBufferCacheMin = std::min(mBufferCacheMin*1024*1024, mBufferCacheMax); mBufferCacheMin = std::min(mBufferCacheMin*1024*1024, mBufferCacheMax);
if(!useSound) if(!useSound)
{
std::cout<< "Sound disabled." <<std::endl;
return; return;
}
std::string hrtfname = Settings::Manager::getString("hrtf", "Sound"); std::string hrtfname = Settings::Manager::getString("hrtf", "Sound");
int hrtfstate = Settings::Manager::getInt("hrtf enable", "Sound"); int hrtfstate = Settings::Manager::getInt("hrtf enable", "Sound");
HrtfMode hrtfmode = hrtfstate < 0 ? HrtfMode::Auto : HrtfMode hrtfmode = hrtfstate < 0 ? HrtfMode::Auto :
hrtfstate > 0 ? HrtfMode::Enable : HrtfMode::Disable; hrtfstate > 0 ? HrtfMode::Enable : HrtfMode::Disable;
std::cout << "Sound output: " << SOUND_OUT << std::endl;
std::cout << "Sound decoder: " << SOUND_IN << std::endl;
std::vector<std::string> names = mOutput->enumerate();
std::cout <<"Enumerated output devices:\n";
std::for_each(names.cbegin(), names.cend(),
[](const std::string &name) -> void
{ std::cout <<" "<<name<<"\n"; }
);
std::cout.flush();
std::string devname = Settings::Manager::getString("device", "Sound"); std::string devname = Settings::Manager::getString("device", "Sound");
bool inited = mOutput->init(devname, hrtfname, hrtfmode); if(!mOutput->init(devname, hrtfname, hrtfmode))
if(!inited && !devname.empty())
{
std::cerr<< "Failed to initialize device \""<<devname<<"\", trying default" <<std::endl;
inited = mOutput->init(std::string(), hrtfname, hrtfmode);
}
if(!inited)
{ {
std::cerr<< "Failed to initialize default audio device, sound disabled" <<std::endl; std::cerr<< "Failed to initialize audio output, sound disabled" <<std::endl;
return; return;
} }
std::vector<std::string> names = mOutput->enumerate();
std::cout <<"Enumerated output devices:\n";
for(const std::string &name : names)
std::cout <<" "<<name<<"\n";
std::cout.flush();
names = mOutput->enumerateHrtf(); names = mOutput->enumerateHrtf();
if(!names.empty()) if(!names.empty())
{ {
std::cout<< "Enumerated HRTF names:\n"; std::cout<< "Enumerated HRTF names:\n";
std::for_each(names.cbegin(), names.cend(), for(const std::string &name : names)
[](const std::string &name) -> void std::cout <<" "<<name<<"\n";
{ std::cout<< " "<<name<<"\n"; }
);
std::cout.flush(); std::cout.flush();
} }
} }
@ -130,12 +116,11 @@ namespace MWSound
SoundManager::~SoundManager() SoundManager::~SoundManager()
{ {
clear(); clear();
SoundBufferList::element_type::iterator sfxiter = mSoundBuffers->begin(); for(Sound_Buffer &sfx : *mSoundBuffers)
for(;sfxiter != mSoundBuffers->end();++sfxiter)
{ {
if(sfxiter->mHandle) if(sfx.mHandle)
mOutput->unloadSound(sfxiter->mHandle); mOutput->unloadSound(sfx.mHandle);
sfxiter->mHandle = 0; sfx.mHandle = 0;
} }
mUnusedBuffers.clear(); mUnusedBuffers.clear();
mOutput.reset(); mOutput.reset();
@ -200,9 +185,23 @@ namespace MWSound
// 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__
#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; Sound_Buffer *sfx;
NameBufferMap::const_iterator snd = mBufferNameMap.find(soundId); NameBufferMap::const_iterator snd = mBufferNameMap.find(soundId);
if(snd != mBufferNameMap.end()) if(LIKELY(snd != mBufferNameMap.end()))
sfx = snd->second; sfx = snd->second;
else else
{ {
@ -211,13 +210,16 @@ namespace MWSound
if(!sound) return nullptr; if(!sound) return nullptr;
sfx = insertSound(soundId, sound); sfx = insertSound(soundId, sound);
} }
#undef LIKELY
#undef UNLIKELY
if(!sfx->mHandle) if(!sfx->mHandle)
{ {
sfx->mHandle = mOutput->loadSound(sfx->mResourceName); size_t size;
std::tie(sfx->mHandle, size) = mOutput->loadSound(sfx->mResourceName);
if(!sfx->mHandle) return nullptr; if(!sfx->mHandle) return nullptr;
mBufferCacheSize += mOutput->getSoundDataSize(sfx->mHandle); mBufferCacheSize += size;
if(mBufferCacheSize > mBufferCacheMax) if(mBufferCacheSize > mBufferCacheMax)
{ {
do { do {
@ -228,8 +230,8 @@ namespace MWSound
} }
Sound_Buffer *unused = mUnusedBuffers.back(); Sound_Buffer *unused = mUnusedBuffers.back();
mBufferCacheSize -= mOutput->getSoundDataSize(unused->mHandle); size = mOutput->unloadSound(unused->mHandle);
mOutput->unloadSound(unused->mHandle); mBufferCacheSize -= size;
unused->mHandle = 0; unused->mHandle = 0;
mUnusedBuffers.pop_back(); mUnusedBuffers.pop_back();
@ -678,11 +680,10 @@ namespace MWSound
if(snditer != mActiveSounds.end()) if(snditer != mActiveSounds.end())
{ {
Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId));
SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(SoundBufferRefPair &snd : snditer->second)
for(;sndidx != snditer->second.end();++sndidx)
{ {
if(sndidx->second == sfx) if(snd.second == sfx)
mOutput->finishSound(sndidx->first); mOutput->finishSound(snd.first);
} }
} }
} }
@ -692,33 +693,28 @@ namespace MWSound
SoundMap::iterator snditer = mActiveSounds.find(ptr); SoundMap::iterator snditer = mActiveSounds.find(ptr);
if(snditer != mActiveSounds.end()) if(snditer != mActiveSounds.end())
{ {
SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(SoundBufferRefPair &snd : snditer->second)
for(;sndidx != snditer->second.end();++sndidx) mOutput->finishSound(snd.first);
mOutput->finishSound(sndidx->first);
} }
SaySoundMap::iterator sayiter = mActiveSaySounds.find(ptr);
if(sayiter != mActiveSaySounds.end())
mOutput->finishStream(sayiter->second);
} }
void SoundManager::stopSound(const MWWorld::CellStore *cell) void SoundManager::stopSound(const MWWorld::CellStore *cell)
{ {
SoundMap::iterator snditer = mActiveSounds.begin(); for(SoundMap::value_type &snd : mActiveSounds)
for(;snditer != mActiveSounds.end();++snditer)
{ {
if(snditer->first != MWWorld::ConstPtr() && if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell)
snditer->first != MWMechanics::getPlayer() &&
snditer->first.getCell() == cell)
{ {
SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(SoundBufferRefPair &sndbuf : snd.second)
for(;sndidx != snditer->second.end();++sndidx) mOutput->finishSound(sndbuf.first);
mOutput->finishSound(sndidx->first);
} }
} }
SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); for(SaySoundMap::value_type &snd : mActiveSaySounds)
for(;sayiter != mActiveSaySounds.end();++sayiter)
{ {
if(sayiter->first != MWWorld::ConstPtr() && if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell)
sayiter->first != MWMechanics::getPlayer() && mOutput->finishStream(snd.second);
sayiter->first.getCell() == cell)
mOutput->finishStream(sayiter->second);
} }
} }
@ -728,11 +724,10 @@ namespace MWSound
if(snditer != mActiveSounds.end()) if(snditer != mActiveSounds.end())
{ {
Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId));
SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(SoundBufferRefPair &sndbuf : snditer->second)
for(;sndidx != snditer->second.end();++sndidx)
{ {
if(sndidx->second == sfx) if(sndbuf.second == sfx)
mOutput->finishSound(sndidx->first); mOutput->finishSound(sndbuf.first);
} }
} }
} }
@ -744,11 +739,10 @@ namespace MWSound
if(snditer != mActiveSounds.end()) if(snditer != mActiveSounds.end())
{ {
Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId));
SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(SoundBufferRefPair &sndbuf : snditer->second)
for(;sndidx != snditer->second.end();++sndidx)
{ {
if(sndidx->second == sfx) if(sndbuf.second == sfx)
sndidx->first->setFadeout(duration); sndbuf.first->setFadeout(duration);
} }
} }
} }
@ -759,12 +753,10 @@ namespace MWSound
if(snditer != mActiveSounds.end()) if(snditer != mActiveSounds.end())
{ {
Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId)); Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId));
SoundBufferRefPairList::const_iterator sndidx = snditer->second.begin(); return std::find_if(snditer->second.cbegin(), snditer->second.cend(),
for(;sndidx != snditer->second.end();++sndidx) [this,sfx](const SoundBufferRefPair &snd) -> bool
{ { return snd.second == sfx && mOutput->isSoundPlaying(snd.first); }
if(sndidx->second == sfx && mOutput->isSoundPlaying(sndidx->first)) ) != snditer->second.cend();
return true;
}
} }
return false; return false;
} }
@ -823,10 +815,8 @@ namespace MWSound
if(total == 0) if(total == 0)
{ {
std::for_each(regn->mSoundList.cbegin(), regn->mSoundList.cend(), for(const ESM::Region::SoundRef &sndref : regn->mSoundList)
[](const ESM::Region::SoundRef &sndref) -> void total += (int)sndref.mChance;
{ total += (int)sndref.mChance; }
);
if(total == 0) if(total == 0)
return; return;
} }
@ -834,20 +824,15 @@ namespace MWSound
int r = Misc::Rng::rollDice(total); int r = Misc::Rng::rollDice(total);
int pos = 0; int pos = 0;
std::find_if_not(regn->mSoundList.cbegin(), regn->mSoundList.cend(), for(const ESM::Region::SoundRef &sndref : regn->mSoundList)
[&pos, r, this](const ESM::Region::SoundRef &sndref) -> bool {
if(r - pos < sndref.mChance)
{ {
if(r - pos < sndref.mChance) playSound(sndref.mSound.toString(), 1.0f, 1.0f);
{ break;
playSound(sndref.mSound.toString(), 1.0f, 1.0f);
// Played this sound, stop iterating
return false;
}
pos += sndref.mChance;
// Not this sound, keep iterating
return true;
} }
); pos += sndref.mChance;
}
} }
void SoundManager::updateWaterSound(float /*duration*/) void SoundManager::updateWaterSound(float /*duration*/)
@ -1135,28 +1120,23 @@ namespace MWSound
if(!mOutput->isInitialized()) if(!mOutput->isInitialized())
return; return;
mOutput->startUpdate(); mOutput->startUpdate();
SoundMap::iterator snditer = mActiveSounds.begin(); for(SoundMap::value_type &snd : mActiveSounds)
for(;snditer != mActiveSounds.end();++snditer)
{ {
SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(SoundBufferRefPair &sndbuf : snd.second)
for(;sndidx != snditer->second.end();++sndidx)
{ {
Sound *sound = sndidx->first; Sound *sound = sndbuf.first;
sound->setBaseVolume(volumeFromType(sound->getPlayType())); sound->setBaseVolume(volumeFromType(sound->getPlayType()));
mOutput->updateSound(sound); mOutput->updateSound(sound);
} }
} }
SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); for(SaySoundMap::value_type &snd : mActiveSaySounds)
for(;sayiter != mActiveSaySounds.end();++sayiter)
{ {
Stream *sound = sayiter->second; Stream *sound = snd.second;
sound->setBaseVolume(volumeFromType(sound->getPlayType())); sound->setBaseVolume(volumeFromType(sound->getPlayType()));
mOutput->updateStream(sound); mOutput->updateStream(sound);
} }
TrackList::iterator trkiter = mActiveTracks.begin(); for(Stream *sound : mActiveTracks)
for(;trkiter != mActiveTracks.end();++trkiter)
{ {
Stream *sound = *trkiter;
sound->setBaseVolume(volumeFromType(sound->getPlayType())); sound->setBaseVolume(volumeFromType(sound->getPlayType()));
mOutput->updateStream(sound); mOutput->updateStream(sound);
} }
@ -1262,36 +1242,35 @@ namespace MWSound
void SoundManager::clear() void SoundManager::clear()
{ {
SoundMap::iterator snditer = mActiveSounds.begin(); stopMusic();
for(;snditer != mActiveSounds.end();++snditer)
for(SoundMap::value_type &snd : mActiveSounds)
{ {
SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(SoundBufferRefPair &sndbuf : snd.second)
for(;sndidx != snditer->second.end();++sndidx)
{ {
mOutput->finishSound(sndidx->first); mOutput->finishSound(sndbuf.first);
mUnusedSounds.push_back(sndidx->first); mUnusedSounds.push_back(sndbuf.first);
Sound_Buffer *sfx = sndidx->second; Sound_Buffer *sfx = sndbuf.second;
if(sfx->mUses-- == 1) if(sfx->mUses-- == 1)
mUnusedBuffers.push_front(sfx); mUnusedBuffers.push_front(sfx);
} }
} }
mActiveSounds.clear(); mActiveSounds.clear();
SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); mUnderwaterSound = nullptr;
for(;sayiter != mActiveSaySounds.end();++sayiter) mNearWaterSound = nullptr;
for(SaySoundMap::value_type &snd : mActiveSaySounds)
{ {
mOutput->finishStream(sayiter->second); mOutput->finishStream(snd.second);
mUnusedStreams.push_back(sayiter->second); mUnusedStreams.push_back(snd.second);
} }
mActiveSaySounds.clear(); mActiveSaySounds.clear();
TrackList::iterator trkiter = mActiveTracks.begin();
for(;trkiter != mActiveTracks.end();++trkiter) for(Stream *sound : mActiveTracks)
{ {
mOutput->finishStream(*trkiter); mOutput->finishStream(sound);
mUnusedStreams.push_back(*trkiter); mUnusedStreams.push_back(sound);
} }
mActiveTracks.clear(); mActiveTracks.clear();
mUnderwaterSound = nullptr;
mNearWaterSound = nullptr;
stopMusic();
} }
} }

Loading…
Cancel
Save