From acd6d9cd72cc4c24d552403a324a5e34a43c887b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 15 Sep 2017 19:36:49 -0700 Subject: [PATCH 01/17] Try opening the default device fallback in OpenAL_Output --- apps/openmw/mwsound/openal_output.cpp | 36 +++++++++++++------------ apps/openmw/mwsound/soundmanagerimp.cpp | 19 +++---------- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 64aa1aff7..85a7d13ba 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -595,24 +595,24 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname deinit(); mDevice = alcOpenDevice(devname.c_str()); - if(!mDevice) + if(!mDevice && !devname.empty()) { - if(devname.empty()) - std::cerr<< "Failed to open default audio device" <removeAll(); - for(size_t i = 0;i < mFreeSources.size();i++) - alDeleteSources(1, &mFreeSources[i]); + std::for_each(mFreeSources.cbegin(), mFreeSources.cend(), + [](ALuint source) -> void + { alDeleteSources(1, &source); } + ); mFreeSources.clear(); if(mEffectSlot) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 0b6d8ff34..03bff89b4 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -26,11 +26,7 @@ #include "sound.hpp" #include "openal_output.hpp" -#define SOUND_OUT "OpenAL" #include "ffmpeg_decoder.hpp" -#ifndef SOUND_IN -#define SOUND_IN "FFmpeg" -#endif namespace MWSound @@ -60,6 +56,8 @@ namespace MWSound , mUnderwaterSound(nullptr) , mNearWaterSound(nullptr) { + std::cout<< "Initializing sound..." < 0 ? HrtfMode::Enable : HrtfMode::Disable; - std::cout << "Sound output: " << SOUND_OUT << std::endl; - std::cout << "Sound decoder: " << SOUND_IN << std::endl; - std::vector names = mOutput->enumerate(); std::cout <<"Enumerated output devices:\n"; std::for_each(names.cbegin(), names.cend(), @@ -103,15 +98,9 @@ namespace MWSound std::cout.flush(); std::string devname = Settings::Manager::getString("device", "Sound"); - bool inited = mOutput->init(devname, hrtfname, hrtfmode); - if(!inited && !devname.empty()) - { - std::cerr<< "Failed to initialize device \""<init(std::string(), hrtfname, hrtfmode); - } - if(!inited) + if(!mOutput->init(devname, hrtfname, hrtfmode)) { - std::cerr<< "Failed to initialize default audio device, sound disabled" < Date: Fri, 15 Sep 2017 21:21:49 -0700 Subject: [PATCH 02/17] Print a bit more information for sound initialization --- apps/openmw/mwsound/openal_output.cpp | 13 +++++++++++++ apps/openmw/mwsound/soundmanagerimp.cpp | 19 ++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 85a7d13ba..a6d3e4b12 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -594,6 +594,8 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname { deinit(); + std::cout<< "Initializing OpenAL..." < 0 ? HrtfMode::Enable : HrtfMode::Disable; + std::string devname = Settings::Manager::getString("device", "Sound"); + if(!mOutput->init(devname, hrtfname, hrtfmode)) + { + std::cerr<< "Failed to initialize audio output, sound disabled" < names = mOutput->enumerate(); std::cout <<"Enumerated output devices:\n"; std::for_each(names.cbegin(), names.cend(), @@ -97,13 +105,6 @@ namespace MWSound ); std::cout.flush(); - std::string devname = Settings::Manager::getString("device", "Sound"); - if(!mOutput->init(devname, hrtfname, hrtfmode)) - { - std::cerr<< "Failed to initialize audio output, sound disabled" <enumerateHrtf(); if(!names.empty()) { From 1e729e8da96b9ec08046c899aa25eccaf94beecf Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 16 Sep 2017 01:56:58 -0700 Subject: [PATCH 03/17] Avoid more explicit loops --- apps/openmw/mwsound/soundmanagerimp.cpp | 158 ++++++++++-------------- 1 file changed, 65 insertions(+), 93 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 2a65be737..f50b3f2fb 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -99,20 +99,16 @@ namespace MWSound std::vector names = mOutput->enumerate(); std::cout <<"Enumerated output devices:\n"; - std::for_each(names.cbegin(), names.cend(), - [](const std::string &name) -> void - { std::cout <<" "<enumerateHrtf(); if(!names.empty()) { std::cout<< "Enumerated HRTF names:\n"; - std::for_each(names.cbegin(), names.cend(), - [](const std::string &name) -> void - { std::cout<< " "<begin(); - for(;sfxiter != mSoundBuffers->end();++sfxiter) + for(Sound_Buffer &sfx : *mSoundBuffers) { - if(sfxiter->mHandle) - mOutput->unloadSound(sfxiter->mHandle); - sfxiter->mHandle = 0; + if(sfx.mHandle) + mOutput->unloadSound(sfx.mHandle); + sfx.mHandle = 0; } mUnusedBuffers.clear(); mOutput.reset(); @@ -668,11 +663,10 @@ namespace MWSound if(snditer != mActiveSounds.end()) { Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); - SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); - for(;sndidx != snditer->second.end();++sndidx) + for(SoundBufferRefPair &snd : snditer->second) { - if(sndidx->second == sfx) - mOutput->finishSound(sndidx->first); + if(snd.second == sfx) + mOutput->finishSound(snd.first); } } } @@ -682,33 +676,28 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.find(ptr); if(snditer != mActiveSounds.end()) { - SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); - for(;sndidx != snditer->second.end();++sndidx) - mOutput->finishSound(sndidx->first); + for(SoundBufferRefPair &snd : snditer->second) + mOutput->finishSound(snd.first); } + SaySoundMap::iterator sayiter = mActiveSaySounds.find(ptr); + if(sayiter != mActiveSaySounds.end()) + mOutput->finishStream(sayiter->second); } void SoundManager::stopSound(const MWWorld::CellStore *cell) { - SoundMap::iterator snditer = mActiveSounds.begin(); - for(;snditer != mActiveSounds.end();++snditer) + for(SoundMap::value_type &snd : mActiveSounds) { - if(snditer->first != MWWorld::ConstPtr() && - snditer->first != MWMechanics::getPlayer() && - snditer->first.getCell() == cell) + if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) { - SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); - for(;sndidx != snditer->second.end();++sndidx) - mOutput->finishSound(sndidx->first); + for(SoundBufferRefPair &sndbuf : snd.second) + mOutput->finishSound(sndbuf.first); } } - SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); - for(;sayiter != mActiveSaySounds.end();++sayiter) + for(SaySoundMap::value_type &snd : mActiveSaySounds) { - if(sayiter->first != MWWorld::ConstPtr() && - sayiter->first != MWMechanics::getPlayer() && - sayiter->first.getCell() == cell) - mOutput->finishStream(sayiter->second); + if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) + mOutput->finishStream(snd.second); } } @@ -718,11 +707,10 @@ namespace MWSound if(snditer != mActiveSounds.end()) { Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); - SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); - for(;sndidx != snditer->second.end();++sndidx) + for(SoundBufferRefPair &sndbuf : snditer->second) { - if(sndidx->second == sfx) - mOutput->finishSound(sndidx->first); + if(sndbuf.second == sfx) + mOutput->finishSound(sndbuf.first); } } } @@ -734,11 +722,10 @@ namespace MWSound if(snditer != mActiveSounds.end()) { Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); - SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); - for(;sndidx != snditer->second.end();++sndidx) + for(SoundBufferRefPair &sndbuf : snditer->second) { - if(sndidx->second == sfx) - sndidx->first->setFadeout(duration); + if(sndbuf.second == sfx) + sndbuf.first->setFadeout(duration); } } } @@ -749,12 +736,10 @@ namespace MWSound if(snditer != mActiveSounds.end()) { Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId)); - SoundBufferRefPairList::const_iterator sndidx = snditer->second.begin(); - for(;sndidx != snditer->second.end();++sndidx) - { - if(sndidx->second == sfx && mOutput->isSoundPlaying(sndidx->first)) - return true; - } + return std::find_if(snditer->second.cbegin(), snditer->second.cend(), + [this,sfx](const SoundBufferRefPair &snd) -> bool + { return snd.second == sfx && mOutput->isSoundPlaying(snd.first); } + ) != snditer->second.cend(); } return false; } @@ -813,10 +798,8 @@ namespace MWSound if(total == 0) { - std::for_each(regn->mSoundList.cbegin(), regn->mSoundList.cend(), - [](const ESM::Region::SoundRef &sndref) -> void - { total += (int)sndref.mChance; } - ); + for(const ESM::Region::SoundRef &sndref : regn->mSoundList) + total += (int)sndref.mChance; if(total == 0) return; } @@ -824,20 +807,15 @@ namespace MWSound int r = Misc::Rng::rollDice(total); int pos = 0; - std::find_if_not(regn->mSoundList.cbegin(), regn->mSoundList.cend(), - [&pos, r, this](const ESM::Region::SoundRef &sndref) -> bool + for(const ESM::Region::SoundRef &sndref : regn->mSoundList) + { + if(r - pos < sndref.mChance) { - if(r - pos < sndref.mChance) - { - 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; + playSound(sndref.mSound.toString(), 1.0f, 1.0f); + break; } - ); + pos += sndref.mChance; + } } void SoundManager::updateWaterSound(float /*duration*/) @@ -1125,28 +1103,23 @@ namespace MWSound if(!mOutput->isInitialized()) return; mOutput->startUpdate(); - SoundMap::iterator snditer = mActiveSounds.begin(); - for(;snditer != mActiveSounds.end();++snditer) + for(SoundMap::value_type &snd : mActiveSounds) { - SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); - for(;sndidx != snditer->second.end();++sndidx) + for(SoundBufferRefPair &sndbuf : snd.second) { - Sound *sound = sndidx->first; + Sound *sound = sndbuf.first; sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateSound(sound); } } - SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); - for(;sayiter != mActiveSaySounds.end();++sayiter) + for(SaySoundMap::value_type &snd : mActiveSaySounds) { - Stream *sound = sayiter->second; + Stream *sound = snd.second; sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateStream(sound); } - TrackList::iterator trkiter = mActiveTracks.begin(); - for(;trkiter != mActiveTracks.end();++trkiter) + for(Stream *sound : mActiveTracks) { - Stream *sound = *trkiter; sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateStream(sound); } @@ -1252,36 +1225,35 @@ namespace MWSound void SoundManager::clear() { - SoundMap::iterator snditer = mActiveSounds.begin(); - for(;snditer != mActiveSounds.end();++snditer) + stopMusic(); + + for(SoundMap::value_type &snd : mActiveSounds) { - SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); - for(;sndidx != snditer->second.end();++sndidx) + for(SoundBufferRefPair &sndbuf : snd.second) { - mOutput->finishSound(sndidx->first); - mUnusedSounds.push_back(sndidx->first); - Sound_Buffer *sfx = sndidx->second; + mOutput->finishSound(sndbuf.first); + mUnusedSounds.push_back(sndbuf.first); + Sound_Buffer *sfx = sndbuf.second; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); } } mActiveSounds.clear(); - SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); - for(;sayiter != mActiveSaySounds.end();++sayiter) + mUnderwaterSound = nullptr; + mNearWaterSound = nullptr; + + for(SaySoundMap::value_type &snd : mActiveSaySounds) { - mOutput->finishStream(sayiter->second); - mUnusedStreams.push_back(sayiter->second); + mOutput->finishStream(snd.second); + mUnusedStreams.push_back(snd.second); } mActiveSaySounds.clear(); - TrackList::iterator trkiter = mActiveTracks.begin(); - for(;trkiter != mActiveTracks.end();++trkiter) + + for(Stream *sound : mActiveTracks) { - mOutput->finishStream(*trkiter); - mUnusedStreams.push_back(*trkiter); + mOutput->finishStream(sound); + mUnusedStreams.push_back(sound); } mActiveTracks.clear(); - mUnderwaterSound = nullptr; - mNearWaterSound = nullptr; - stopMusic(); } } From 4b448c74d24023c9f43c952335829c3c287061f7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 16 Sep 2017 03:19:06 -0700 Subject: [PATCH 04/17] Use range-for loops instead of for_each --- apps/openmw/mwsound/openal_output.cpp | 152 +++++++++++--------------- 1 file changed, 66 insertions(+), 86 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index a6d3e4b12..77a14a398 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -192,12 +192,11 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type) { AL_FORMAT_STEREO8, ChannelConfig_Stereo, SampleType_UInt8 }, }}; - auto fmt = std::find_if(fmtlist.cbegin(), fmtlist.cend(), - [chans,type](const FormatEntry &fmt) -> bool - { return fmt.chans == chans && fmt.type == type; } - ); - if(fmt != fmtlist.cend()) - return fmt->format; + for(auto &fmt : fmtlist) + { + if(fmt.chans == chans && fmt.type == type) + return fmt.format; + } 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_71CHN8", ChannelConfig_7point1, SampleType_UInt8 }, }}; - ALenum format = AL_NONE; - std::find_if(mcfmtlist.cbegin(), mcfmtlist.cend(), - [&format,chans,type](const FormatEntryExt &fmt) -> bool + for(auto &fmt : mcfmtlist) + { + if(fmt.chans == chans && fmt.type == type) { - if(fmt.chans == chans && fmt.type == type) - format = alGetEnumValue(fmt.name); - return format != 0 && format != -1; + ALenum format = alGetEnumValue(fmt.name); + if(format != 0 && format != -1) + return format; } - ); - if(format != 0 && format != -1) - return format; + } } 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_STEREO_FLOAT32", ChannelConfig_Stereo, SampleType_Float32 }, }}; - ALenum format = AL_NONE; - std::find_if(fltfmtlist.cbegin(), fltfmtlist.cend(), - [&format,chans,type](const FormatEntryExt &fmt) -> bool + for(auto &fmt : fltfmtlist) + { + if(fmt.chans == chans && fmt.type == type) { - if(fmt.chans == chans && fmt.type == type) - format = alGetEnumValue(fmt.name); - return format != 0 && format != -1; + ALenum format = alGetEnumValue(fmt.name); + if(format != 0 && format != -1) + return format; } - ); - if(format != 0 && format != -1) - return format; + } if(alIsExtensionPresent("AL_EXT_MCFORMATS")) { @@ -249,16 +244,15 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type) { "AL_FORMAT_71CHN32", ChannelConfig_7point1, SampleType_Float32 }, }}; - std::find_if(fltmcfmtlist.cbegin(), fltmcfmtlist.cend(), - [&format,chans,type](const FormatEntryExt &fmt) -> bool + for(auto &fmt : fltmcfmtlist) + { + if(fmt.chans == chans && fmt.type == type) { - if(fmt.chans == chans && fmt.type == type) - format = alGetEnumValue(fmt.name); - return format != 0 && format != -1; + ALenum format = alGetEnumValue(fmt.name); + if(format != 0 && format != -1) + return format; } - ); - if(format != 0 && format != -1) - return format; + } } } @@ -547,11 +541,11 @@ ALint OpenAL_SoundStream::refillQueue() std::vector data(mBufferSize); 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()) { mIsFinished = true; - std::memset(&data[got], mSilence, data.size()-got); + std::fill(data.begin()+got, data.end(), mSilence); } if(got > 0) { @@ -559,7 +553,7 @@ ALint OpenAL_SoundStream::refillQueue() mLoudnessAnalyzer->analyzeLoudness(data); ALuint bufid = mBuffers[mCurrentBufIdx]; - alBufferData(bufid, mFormat, &data[0], data.size(), mSampleRate); + alBufferData(bufid, mFormat, data.data(), data.size(), mSampleRate); alSourceQueueBuffers(mSource, 1, &bufid); mCurrentBufIdx = (mCurrentBufIdx+1) % mBuffers.size(); } @@ -837,10 +831,8 @@ void OpenAL_Output::deinit() { mStreamThread->removeAll(); - std::for_each(mFreeSources.cbegin(), mFreeSources.cend(), - [](ALuint source) -> void - { alDeleteSources(1, &source); } - ); + for(ALuint source : mFreeSources) + alDeleteSources(1, &source); mFreeSources.clear(); if(mEffectSlot) @@ -1383,23 +1375,19 @@ void OpenAL_Output::updateListener(const osg::Vec3f &pos, const osg::Vec3f &atdi if(mWaterFilter) { ALuint filter = (env == Env_Underwater) ? mWaterFilter : AL_FILTER_NULL; - std::for_each(mActiveSounds.cbegin(), mActiveSounds.cend(), - [filter](const SoundVec::value_type &item) -> void - { - if(item->getUseEnv()) - alSourcei(GET_PTRID(item->mHandle), AL_DIRECT_FILTER, filter); - } - ); - std::for_each(mActiveStreams.cbegin(), mActiveStreams.cend(), - [filter](const StreamVec::value_type &item) -> void - { - if(item->getUseEnv()) - alSourcei( - reinterpret_cast(item->mHandle)->mSource, - AL_DIRECT_FILTER, filter - ); - } - ); + for(Sound *sound : mActiveSounds) + { + if(sound->getUseEnv()) + alSourcei(GET_PTRID(sound->mHandle), AL_DIRECT_FILTER, filter); + } + for(Stream *sound : mActiveStreams) + { + if(sound->getUseEnv()) + alSourcei( + reinterpret_cast(sound->mHandle)->mSource, + AL_DIRECT_FILTER, filter + ); + } } // Update the environment effect if(mEffectSlot) @@ -1418,23 +1406,19 @@ void OpenAL_Output::updateListener(const osg::Vec3f &pos, const osg::Vec3f &atdi void OpenAL_Output::pauseSounds(int types) { std::vector sources; - std::for_each(mActiveSounds.cbegin(), mActiveSounds.cend(), - [types,&sources](const SoundVec::value_type &sound) -> void - { - if(sound && sound->mHandle && (types&sound->getPlayType())) - sources.push_back(GET_PTRID(sound->mHandle)); - } - ); - std::for_each(mActiveStreams.cbegin(), mActiveStreams.cend(), - [types,&sources](const StreamVec::value_type &stream) -> void + for(Sound *sound : mActiveSounds) + { + if((types&sound->getPlayType())) + sources.push_back(GET_PTRID(sound->mHandle)); + } + for(Stream *sound : mActiveStreams) + { + if((types&sound->getPlayType())) { - if(stream && stream->mHandle && (types&stream->getPlayType())) - { - OpenAL_SoundStream *strm = reinterpret_cast(stream->mHandle); - sources.push_back(strm->mSource); - } + OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); + sources.push_back(stream->mSource); } - ); + } if(!sources.empty()) { alSourcePausev(sources.size(), sources.data()); @@ -1445,23 +1429,19 @@ void OpenAL_Output::pauseSounds(int types) void OpenAL_Output::resumeSounds(int types) { std::vector sources; - std::for_each(mActiveSounds.cbegin(), mActiveSounds.cend(), - [types,&sources](const SoundVec::value_type &sound) -> void - { - if(sound && sound->mHandle && (types&sound->getPlayType())) - sources.push_back(GET_PTRID(sound->mHandle)); - } - ); - std::for_each(mActiveStreams.cbegin(), mActiveStreams.cend(), - [types,&sources](const StreamVec::value_type &stream) -> void + for(Sound *sound : mActiveSounds) + { + if((types&sound->getPlayType())) + sources.push_back(GET_PTRID(sound->mHandle)); + } + for(Stream *sound : mActiveStreams) + { + if((types&sound->getPlayType())) { - if(stream && stream->mHandle && (types&stream->getPlayType())) - { - OpenAL_SoundStream *strm = reinterpret_cast(stream->mHandle); - sources.push_back(strm->mSource); - } + OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); + sources.push_back(stream->mSource); } - ); + } if(!sources.empty()) { alSourcePlayv(sources.size(), sources.data()); From 5c53ee42a10d8037420f442b65b2ac9e7045ad82 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 16 Sep 2017 03:48:41 -0700 Subject: [PATCH 05/17] Prepare all Sound_Buffers when retrieving the first one --- apps/openmw/mwsound/soundmanagerimp.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index f50b3f2fb..949b724f1 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -185,9 +185,23 @@ namespace MWSound // 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()) + insertSound(Misc::StringUtils::lowerCase(sound.mId), &sound); + } + Sound_Buffer *sfx; NameBufferMap::const_iterator snd = mBufferNameMap.find(soundId); - if(snd != mBufferNameMap.end()) + if(LIKELY(snd != mBufferNameMap.end())) sfx = snd->second; else { @@ -196,6 +210,8 @@ namespace MWSound if(!sound) return nullptr; sfx = insertSound(soundId, sound); } +#undef LIKELY +#undef UNLIKELY if(!sfx->mHandle) { From 41bb35655bf6da3de0b2bf8ff546dac2ce1dcec2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 16 Sep 2017 04:24:01 -0700 Subject: [PATCH 06/17] Avoid an extra call to get the buffer size --- apps/openmw/mwsound/openal_output.cpp | 28 +++++++++++-------------- apps/openmw/mwsound/openal_output.hpp | 5 ++--- apps/openmw/mwsound/sound_output.hpp | 5 ++--- apps/openmw/mwsound/soundmanagerimp.cpp | 9 ++++---- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 77a14a398..3fb1c1c13 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -941,7 +941,7 @@ void OpenAL_Output::setHrtf(const std::string &hrtfname, HrtfMode hrtfmode) } -Sound_Handle OpenAL_Output::loadSound(const std::string &fname) +std::pair OpenAL_Output::loadSound(const std::string &fname) { getALError(); @@ -966,27 +966,31 @@ Sound_Handle OpenAL_Output::loadSound(const std::string &fname) decoder->getInfo(&srate, &chans, &type); format = getALFormat(chans, type); - if(!format) return nullptr; + if(!format) return std::make_pair(nullptr, 0); decoder->readAll(data); decoder->close(); + ALint size; ALuint buf = 0; 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(buf && alIsBuffer(buf)) alDeleteBuffers(1, &buf); 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); + if(!buffer) return 0; + // Make sure no sources are playing this buffer before unloading it. SoundVec::const_iterator iter = mActiveSounds.begin(); for(;iter != mActiveSounds.end();++iter) @@ -1003,19 +1007,11 @@ void OpenAL_Output::unloadSound(Sound_Handle data) 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; - alGetBufferi(buffer, AL_SIZE, &size); + alDeleteBuffers(1, &buffer); getALError(); - - return (ALuint)size; + return size; } diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index 8a7b7b3b8..afc869733 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -66,9 +66,8 @@ namespace MWSound virtual std::vector enumerateHrtf(); virtual void setHrtf(const std::string &hrtfname, HrtfMode hrtfmode); - virtual Sound_Handle loadSound(const std::string &fname); - virtual void unloadSound(Sound_Handle data); - virtual size_t getSoundDataSize(Sound_Handle data) const; + virtual std::pair loadSound(const std::string &fname); + virtual size_t unloadSound(Sound_Handle data); virtual bool playSound(Sound *sound, Sound_Handle data, float offset); virtual bool playSound3D(Sound *sound, Sound_Handle data, float offset); diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index ad18e0d40..871562dc0 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -36,9 +36,8 @@ namespace MWSound virtual std::vector enumerateHrtf() = 0; virtual void setHrtf(const std::string &hrtfname, HrtfMode hrtfmode) = 0; - virtual Sound_Handle loadSound(const std::string &fname) = 0; - virtual void unloadSound(Sound_Handle data) = 0; - virtual size_t getSoundDataSize(Sound_Handle data) const = 0; + virtual std::pair loadSound(const std::string &fname) = 0; + virtual size_t unloadSound(Sound_Handle data) = 0; virtual bool playSound(Sound *sound, Sound_Handle data, float offset) = 0; virtual bool playSound3D(Sound *sound, Sound_Handle data, float offset) = 0; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 949b724f1..ac87a2f06 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -215,10 +215,11 @@ namespace MWSound 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; - mBufferCacheSize += mOutput->getSoundDataSize(sfx->mHandle); + mBufferCacheSize += size; if(mBufferCacheSize > mBufferCacheMax) { do { @@ -229,8 +230,8 @@ namespace MWSound } Sound_Buffer *unused = mUnusedBuffers.back(); - mBufferCacheSize -= mOutput->getSoundDataSize(unused->mHandle); - mOutput->unloadSound(unused->mHandle); + size = mOutput->unloadSound(unused->mHandle); + mBufferCacheSize -= size; unused->mHandle = 0; mUnusedBuffers.pop_back(); From 19d034f3705afb10064412f984a753af02085bc2 Mon Sep 17 00:00:00 2001 From: David Walley <31402617+loriel2@users.noreply.github.com> Date: Sun, 17 Sep 2017 07:43:26 +0100 Subject: [PATCH 07/17] Docs CS-Manual - tour - add ring to chest Extend the ring tutorial in the CS-Manual to put the ring in a chest. Images omitted pending decisions on style and where to store them --- docs/source/manuals/openmw-cs/tour.rst | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/source/manuals/openmw-cs/tour.rst b/docs/source/manuals/openmw-cs/tour.rst index fedd42462..923b1af36 100644 --- a/docs/source/manuals/openmw-cs/tour.rst +++ b/docs/source/manuals/openmw-cs/tour.rst @@ -304,3 +304,42 @@ already checked. Load a game and make your way to Seyda Neen - or start a new ga Check whether Arrille has one (or more) for sale, and whether Fargoth give you one when you return his healing ring. + +Placing in a chest +****************** + +For this example we will use the small chest intended for lockpick practice, +located in the Census and Excise Office in Seyda Neen. + +FIrst we need the ID of the chest - this can be obtained either by clicking on it in the console +in the game, or by applying a similar process in the CS - + +World/Cells + +Select "Seyda Neen, Census and Excise Office" + +Right-click and select "View" + +Use mouse wheel to zoon in/out, and mouse plus WASD keys to navigate + +Click on the small chest + +Either way, you should find the ID, which is "chest_small_02_lockprac". + +Open the Objects table (World/Objects) and scroll down to find this item. + +Alternatively use the Edit/Search facility, selecting ID rather than text, +enter "lockprac" (without the quotes) into the search box, press "Search", +which should return two rows, then select the "Container" one rather than the "Instance" + +Right-click and "Edit Record". + +Right-click the "Content" section and select "Add a row" + +Set the Item ID of the new row to be your new ring - simplest way is probably to open the Objects +table if it's not already open, sort on the "Modified" column which should bring the ring, +with its status of "Added" to the top, then drag and drop to the chest row. + +Increase the Count to 1. + +Save the addon, then test to ensure it works - e.g. start a new game and lockpick the chest. From 6b56f25f9ec5b7c58f055f0195ca4ff0397b3fc3 Mon Sep 17 00:00:00 2001 From: David Walley <31402617+loriel2@users.noreply.github.com> Date: Sun, 17 Sep 2017 07:47:27 +0100 Subject: [PATCH 08/17] Update tour.rst --- docs/source/manuals/openmw-cs/tour.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/manuals/openmw-cs/tour.rst b/docs/source/manuals/openmw-cs/tour.rst index 923b1af36..38915c95b 100644 --- a/docs/source/manuals/openmw-cs/tour.rst +++ b/docs/source/manuals/openmw-cs/tour.rst @@ -311,7 +311,7 @@ Placing in a chest For this example we will use the small chest intended for lockpick practice, located in the Census and Excise Office in Seyda Neen. -FIrst we need the ID of the chest - this can be obtained either by clicking on it in the console +First we need the ID of the chest - this can be obtained either by clicking on it in the console in the game, or by applying a similar process in the CS - World/Cells @@ -320,7 +320,7 @@ Select "Seyda Neen, Census and Excise Office" Right-click and select "View" -Use mouse wheel to zoon in/out, and mouse plus WASD keys to navigate +Use mouse wheel to zoom in/out, and mouse plus WASD keys to navigate Click on the small chest From 5e60fb7c10557864e06ab31f0f0de006f5f57f36 Mon Sep 17 00:00:00 2001 From: PlutonicOverkill Date: Sun, 17 Sep 2017 21:09:28 +1200 Subject: [PATCH 09/17] Fix preferences pane width --- apps/opencs/view/prefs/dialogue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/prefs/dialogue.cpp b/apps/opencs/view/prefs/dialogue.cpp index 7f901c470..960ca74bc 100644 --- a/apps/opencs/view/prefs/dialogue.cpp +++ b/apps/opencs/view/prefs/dialogue.cpp @@ -24,7 +24,7 @@ void CSVPrefs::Dialogue::buildCategorySelector (QSplitter *main) main->addWidget (list); - QFontMetrics metrics (QApplication::font()); + QFontMetrics metrics (QApplication::font(list)); int maxWidth = 1; From 3fb3c4c20f60e39903421f8b5aed0462192b994f Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 17 Sep 2017 14:06:01 +0400 Subject: [PATCH 10/17] Add scrollbar to a birth effect lists (bug #4105) --- apps/openmw/mwgui/birth.cpp | 8 +++++++- apps/openmw/mwgui/birth.hpp | 2 +- files/mygui/openmw_chargen_birth.layout | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 69fb2c462..ecc011fc1 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -244,6 +245,11 @@ namespace MWGui } } } - } + // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden + mSpellArea->setVisibleVScroll(false); + mSpellArea->setCanvasSize(MyGUI::IntSize(mSpellArea->getWidth(), std::max(mSpellArea->getHeight(), coord.top))); + mSpellArea->setVisibleVScroll(true); + mSpellArea->setViewOffset(MyGUI::IntPoint(0, 0)); + } } diff --git a/apps/openmw/mwgui/birth.hpp b/apps/openmw/mwgui/birth.hpp index 0a84bb4e9..c8ec9da09 100644 --- a/apps/openmw/mwgui/birth.hpp +++ b/apps/openmw/mwgui/birth.hpp @@ -47,7 +47,7 @@ namespace MWGui void updateSpells(); MyGUI::ListBox* mBirthList; - MyGUI::Widget* mSpellArea; + MyGUI::ScrollView* mSpellArea; MyGUI::ImageBox* mBirthImage; std::vector mSpellItems; diff --git a/files/mygui/openmw_chargen_birth.layout b/files/mygui/openmw_chargen_birth.layout index 2375e5277..d93249c03 100644 --- a/files/mygui/openmw_chargen_birth.layout +++ b/files/mygui/openmw_chargen_birth.layout @@ -11,7 +11,9 @@ - + + + > From 4bb349a5259d534c34ef2017d2f941c5be838045 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 17 Sep 2017 14:34:27 +0400 Subject: [PATCH 11/17] Use default 0 precision in the float formatting (bug #4096) --- components/misc/messageformatparser.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/components/misc/messageformatparser.cpp b/components/misc/messageformatparser.cpp index bfd8dd562..3a35c83ea 100644 --- a/components/misc/messageformatparser.cpp +++ b/components/misc/messageformatparser.cpp @@ -34,21 +34,19 @@ namespace Misc if (i < m.size()) { - int precision = 0; - bool precisionSet = false; + int precision = -1; if (m[i] == '.') { + precision = 0; while (++i < m.size() && m[i] >= '0' && m[i] <= '9') { precision = precision * 10 + (m[i] - '0'); - precisionSet = true; } } if (i < m.size()) { width = (widthSet) ? width : -1; - precision = (precisionSet) ? precision : -1; if (m[i] == 'S' || m[i] == 's') visitedPlaceholder(StringPlaceholder, pad, width, precision); From 5a5cb1a160d65b9b1d84a65bece4a7626daab3ec Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 17 Sep 2017 14:09:29 +0100 Subject: [PATCH 12/17] Check death counts are for valid actors before loading them --- apps/openmw/mwmechanics/actors.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index baa2470da..673304d30 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1767,9 +1767,12 @@ namespace MWMechanics while (reader.isNextSub("ID__")) { std::string id = reader.getHString(); - int count; - reader.getHNT (count, "COUN"); - mDeathCount[id] = count; + if (MWBase::Environment::get().getWorld()->getStore().find(id)) + { + int count; + reader.getHNT(count, "COUN"); + mDeathCount[id] = count; + } } } } From 10a0136b4aa561f1bba7bc42a24643523d364ce2 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 17 Sep 2017 17:04:30 +0400 Subject: [PATCH 13/17] Cycle only through weapons which can be equipped by player (bug #4104) --- apps/openmw/mwgui/inventorywindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 6a2d3ff83..6eb0c554e 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -717,7 +717,9 @@ namespace MWGui lastId = item.getCellRef().getRefId(); - if (item.getClass().getTypeName() == typeid(ESM::Weapon).name() && isRightHandWeapon(item)) + if (item.getClass().getTypeName() == typeid(ESM::Weapon).name() && + isRightHandWeapon(item) && + item.getClass().canBeEquipped(item, player).first) { found = true; break; From 0be7e2a5a574354ebe7dc14c05ca22becf934315 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 17 Sep 2017 14:16:17 +0100 Subject: [PATCH 14/17] Fix really obvious flaw with ignored records not being skipped that I missed --- apps/openmw/mwmechanics/actors.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 673304d30..0cb7619db 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1767,12 +1767,10 @@ namespace MWMechanics while (reader.isNextSub("ID__")) { std::string id = reader.getHString(); + int count; + reader.getHNT(count, "COUN"); if (MWBase::Environment::get().getWorld()->getStore().find(id)) - { - int count; - reader.getHNT(count, "COUN"); mDeathCount[id] = count; - } } } } From fcb815f2c70df2b15088cf89a748bab7fd8e7f9d Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 17 Sep 2017 23:03:02 +0000 Subject: [PATCH 15/17] Move fall height reset into PhysicsSystem (Fixes #4049) To avoid using onGround before it's actually set. --- apps/openmw/mwmechanics/character.cpp | 14 +------------- apps/openmw/mwphysics/physicssystem.cpp | 13 +++++++++---- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index bfe8812e6..75ecf00a8 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1704,20 +1704,11 @@ void CharacterController::update(float duration) if(sneak || inwater || flying) vec.z() = 0.0f; - if (inwater || flying) - cls.getCreatureStats(mPtr).land(); - bool inJump = true; if(!onground && !flying && !inwater) { // In the air (either getting up —ascending part of jump— or falling). - if (world->isSlowFalling(mPtr)) - { - // SlowFalling spell effect is active, do not keep previous fall height - cls.getCreatureStats(mPtr).land(); - } - forcestateupdate = (mJumpState != JumpState_InAir); jumpstate = JumpState_InAir; @@ -1763,7 +1754,7 @@ void CharacterController::update(float duration) } } } - else if(mJumpState == JumpState_InAir) + else if(mJumpState == JumpState_InAir && !inwater) { forcestateupdate = true; jumpstate = JumpState_Landing; @@ -1846,9 +1837,6 @@ void CharacterController::update(float duration) movestate = mMovementState; } - if (onground) - cls.getCreatureStats(mPtr).land(); - if(movestate != CharState_None && movestate != CharState_TurnLeft && movestate != CharState_TurnRight) clearAnimQueue(); diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 790ae2099..ee368ad24 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -1404,14 +1404,16 @@ namespace MWPhysics // Slow fall reduces fall speed by a factor of (effect magnitude / 200) float slowFall = 1.f - std::max(0.f, std::min(1.f, effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f)); + bool flying = world->isFlying(iter->first); + + bool wasOnGround = physicActor->getOnGround(); osg::Vec3f position = physicActor->getPosition(); float oldHeight = position.z(); bool positionChanged = false; for (int i=0; igetPtr(), physicActor, iter->second, physicsDt, - world->isFlying(iter->first), - waterlevel, slowFall, mCollisionWorld, mStandingCollisions); + flying, waterlevel, slowFall, mCollisionWorld, mStandingCollisions); if (position != physicActor->getPosition()) positionChanged = true; physicActor->setPosition(position); // always set even if unchanged to make sure interpolation is correct @@ -1424,8 +1426,11 @@ namespace MWPhysics float heightDiff = position.z() - oldHeight; - if (heightDiff < 0) - iter->first.getClass().getCreatureStats(iter->first).addToFallHeight(-heightDiff); + MWMechanics::CreatureStats& stats = iter->first.getClass().getCreatureStats(iter->first); + if ((wasOnGround && physicActor->getOnGround()) || flying || world->isSwimming(iter->first) || slowFall < 1) + stats.land(); + else if (heightDiff < 0) + stats.addToFallHeight(-heightDiff); mMovementResults.push_back(std::make_pair(iter->first, interpolated)); } From 00034192dca8adc4f3f71ca6c2dc877bc3f6f7ce Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 17 Sep 2017 23:07:17 +0000 Subject: [PATCH 16/17] Fix player Ptr in RenderingManager not being updated on cell changes Noticed that 'setpos' wasn't working in the console with the player selected. --- apps/openmw/mwrender/renderingmanager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 4d4a36f6c..5c22de12e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -530,8 +530,10 @@ namespace MWRender void RenderingManager::updatePlayerPtr(const MWWorld::Ptr &ptr) { if(mPlayerAnimation.get()) + { + setupPlayer(ptr); mPlayerAnimation->updatePtr(ptr); - + } mCamera->attachTo(ptr); } @@ -834,6 +836,7 @@ namespace MWRender player.getRefData().setBaseNode(mPlayerNode); + mWater->removeEmitter(player); mWater->addEmitter(player); } From d294d7e284b74e9c9f16600371cf87b163546b34 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 17 Sep 2017 23:16:49 +0000 Subject: [PATCH 17/17] Fix possible fall damage when switching from falling to flying --- apps/openmw/mwmechanics/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 75ecf00a8..cd14ec5a4 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1754,7 +1754,7 @@ void CharacterController::update(float duration) } } } - else if(mJumpState == JumpState_InAir && !inwater) + else if(mJumpState == JumpState_InAir && !inwater && !flying) { forcestateupdate = true; jumpstate = JumpState_Landing;