From 816015d6e668f57bf2c4fac32d7d74fee8c0e3c4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 30 Nov 2015 05:42:51 -0800 Subject: [PATCH 01/11] Avoid inheriting from Sound for sound types --- apps/openmw/mwbase/soundmanager.hpp | 11 + apps/openmw/mwsound/movieaudiofactory.cpp | 4 +- apps/openmw/mwsound/openal_output.cpp | 599 +++++++++------------- apps/openmw/mwsound/openal_output.hpp | 14 +- apps/openmw/mwsound/sound.hpp | 25 +- apps/openmw/mwsound/sound_output.hpp | 7 + apps/openmw/mwsound/soundmanagerimp.cpp | 127 +++-- apps/openmw/mwsound/soundmanagerimp.hpp | 12 +- apps/openmw/mwworld/projectilemanager.cpp | 4 +- apps/openmw/mwworld/weather.cpp | 2 +- 10 files changed, 383 insertions(+), 422 deletions(-) diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index a91149777..e75949a5b 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -107,6 +107,14 @@ namespace MWBase virtual SoundPtr playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0; ///< Play a 2D audio track, using a custom decoder + virtual void stopTrack(SoundPtr sound) = 0; + ///< Stop the given audio track from playing + + virtual double getTrackTimeDelay(SoundPtr sound) = 0; + ///< Retives the time delay, in seconds, of the audio track (must be a sound + /// returned by \ref playTrack). Only intended to be called by the track + /// decoder's read method. + virtual SoundPtr playSound(const std::string& soundId, float volume, float pitch, PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal, float offset=0) = 0; @@ -123,6 +131,9 @@ namespace MWBase float volume, float pitch, PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal, float offset=0) = 0; ///< Play a 3D sound at \a initialPos. If the sound should be moving, it must be updated using Sound::setPosition. + virtual void stopSound(SoundPtr sound) = 0; + ///< Stop the given sound from playing + virtual void stopSound3D(const MWWorld::Ptr &reference, const std::string& soundId) = 0; ///< Stop the given object from playing the given sound, diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 925c966da..1f7b8a515 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -61,7 +61,7 @@ namespace MWSound virtual double getAudioClock() { return (double)getSampleOffset()/(double)mAVStream->codec->sample_rate - - mAudioTrack->getStreamDelay(); + MWBase::Environment::get().getSoundManager()->getTrackTimeDelay(mAudioTrack); } virtual void adjustAudioSettings(AVSampleFormat& sampleFormat, uint64_t& channelLayout, int& sampleRate) @@ -86,6 +86,8 @@ namespace MWSound public: ~MovieAudioDecoder() { + if(mAudioTrack.get()) + MWBase::Environment::get().getSoundManager()->stopTrack(mAudioTrack); mAudioTrack.reset(); mDecoderBridge.reset(); } diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index d4c890cee..3607f71a4 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -157,17 +157,14 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type) // // A streaming OpenAL sound. // -class OpenAL_SoundStream : public Sound +class OpenAL_SoundStream { static const ALuint sNumBuffers = 6; static const ALfloat sBufferLength; -protected: - OpenAL_Output &mOutput; - +private: ALuint mSource; -private: ALuint mBuffers[sNumBuffers]; ALint mCurrentBufIdx; @@ -189,34 +186,18 @@ private: friend class OpenAL_Output; public: - OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder, const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags); - virtual ~OpenAL_SoundStream(); + OpenAL_SoundStream(ALuint src, DecoderPtr decoder); + ~OpenAL_SoundStream(); - virtual void stop(); - virtual bool isPlaying(); - virtual double getTimeOffset(); - virtual double getStreamDelay() const; - virtual void applyUpdates(); + bool isPlaying(); + double getStreamDelay() const; + double getStreamOffset() const; - void play(); bool process(); ALint refillQueue(); }; const ALfloat OpenAL_SoundStream::sBufferLength = 0.125f; -class OpenAL_SoundStream3D : public OpenAL_SoundStream -{ - OpenAL_SoundStream3D(const OpenAL_SoundStream3D &rhs); - OpenAL_SoundStream3D& operator=(const OpenAL_SoundStream3D &rhs); - -public: - OpenAL_SoundStream3D(OpenAL_Output &output, ALuint src, DecoderPtr decoder, const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) - : OpenAL_SoundStream(output, src, decoder, pos, vol, basevol, pitch, mindist, maxdist, flags) - { } - - virtual void applyUpdates(); -}; - // // A background streaming thread (keeps active streams processed) @@ -329,13 +310,9 @@ private: }; -OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder, const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) - : Sound(pos, vol, basevol, pitch, mindist, maxdist, flags) - , mOutput(output), mSource(src), mCurrentBufIdx(0), mFrameSize(0), mSilence(0) - , mDecoder(decoder), mIsFinished(true) +OpenAL_SoundStream::OpenAL_SoundStream(ALuint src, DecoderPtr decoder) + : mSource(src), mCurrentBufIdx(0), mFrameSize(0), mSilence(0), mDecoder(decoder), mIsFinished(false) { - throwALerror(); - alGenBuffers(sNumBuffers, mBuffers); throwALerror(); try @@ -358,8 +335,6 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode mFrameSize = framesToBytes(1, chans, type); mBufferSize = static_cast(sBufferLength*srate); mBufferSize *= mFrameSize; - - mOutput.mActiveStreams.push_back(this); } catch(std::exception&) { @@ -367,51 +342,20 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode alGetError(); throw; } + mIsFinished = false; } OpenAL_SoundStream::~OpenAL_SoundStream() { - mOutput.mStreamThread->remove(this); - - alSourceStop(mSource); - alSourcei(mSource, AL_BUFFER, 0); - - mOutput.mFreeSources.push_back(mSource); alDeleteBuffers(sNumBuffers, mBuffers); alGetError(); mDecoder->close(); - - mOutput.mActiveStreams.erase(std::find(mOutput.mActiveStreams.begin(), - mOutput.mActiveStreams.end(), this)); -} - -void OpenAL_SoundStream::play() -{ - alSourceStop(mSource); - alSourcei(mSource, AL_BUFFER, 0); - throwALerror(); - - mIsFinished = false; - mOutput.mStreamThread->add(this); -} - -void OpenAL_SoundStream::stop() -{ - mOutput.mStreamThread->remove(this); - mIsFinished = true; - - alSourceStop(mSource); - alSourcei(mSource, AL_BUFFER, 0); - throwALerror(); - - mDecoder->rewind(); } bool OpenAL_SoundStream::isPlaying() { ALint state; - boost::lock_guard lock(mOutput.mStreamThread->mMutex); alGetSourcei(mSource, AL_SOURCE_STATE, &state); throwALerror(); @@ -420,13 +364,12 @@ bool OpenAL_SoundStream::isPlaying() return !mIsFinished; } -double OpenAL_SoundStream::getTimeOffset() +double OpenAL_SoundStream::getStreamDelay() const { ALint state = AL_STOPPED; + double d = 0.0; ALint offset; - double t; - boost::lock_guard lock(mOutput.mStreamThread->mMutex); alGetSourcei(mSource, AL_SAMPLE_OFFSET, &offset); alGetSourcei(mSource, AL_SOURCE_STATE, &state); if(state == AL_PLAYING || state == AL_PAUSED) @@ -434,24 +377,18 @@ double OpenAL_SoundStream::getTimeOffset() ALint queued; alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued); ALint inqueue = mBufferSize/mFrameSize*queued - offset; - t = (double)(mDecoder->getSampleOffset() - inqueue) / (double)mSampleRate; - } - else - { - /* Underrun, or not started yet. The decoder offset is where we'll play - * next. */ - t = (double)mDecoder->getSampleOffset() / (double)mSampleRate; + d = (double)inqueue / (double)mSampleRate; } throwALerror(); - return t; + return d; } -double OpenAL_SoundStream::getStreamDelay() const +double OpenAL_SoundStream::getStreamOffset() const { ALint state = AL_STOPPED; - double d = 0.0; ALint offset; + double t; alGetSourcei(mSource, AL_SAMPLE_OFFSET, &offset); alGetSourcei(mSource, AL_SOURCE_STATE, &state); @@ -460,48 +397,17 @@ double OpenAL_SoundStream::getStreamDelay() const ALint queued; alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued); ALint inqueue = mBufferSize/mFrameSize*queued - offset; - d = (double)inqueue / (double)mSampleRate; - } - - throwALerror(); - return d; -} - -void OpenAL_SoundStream::updateAll(bool local) -{ - alSourcef(mSource, AL_REFERENCE_DISTANCE, mMinDistance); - alSourcef(mSource, AL_MAX_DISTANCE, mMaxDistance); - if(local) - { - alSourcef(mSource, AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(mSource, AL_SOURCE_RELATIVE, AL_TRUE); + t = (double)(mDecoder->getSampleOffset() - inqueue) / (double)mSampleRate; } else { - alSourcef(mSource, AL_ROLLOFF_FACTOR, 1.0f); - alSourcei(mSource, AL_SOURCE_RELATIVE, AL_FALSE); - } - alSourcei(mSource, AL_LOOPING, AL_FALSE); - - applyUpdates(); -} - -void OpenAL_SoundStream::applyUpdates() -{ - ALfloat gain = mVolume*mBaseVolume; - ALfloat pitch = mPitch; - if(!(mFlags&MWBase::SoundManager::Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; + /* Underrun, or not started yet. The decoder offset is where we'll play + * next. */ + t = (double)mDecoder->getSampleOffset() / (double)mSampleRate; } - alSourcef(mSource, AL_GAIN, gain); - alSourcef(mSource, AL_PITCH, pitch); - alSource3f(mSource, AL_POSITION, mPos[0], mPos[1], mPos[2]); - alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f); throwALerror(); + return t; } bool OpenAL_SoundStream::process() @@ -562,172 +468,6 @@ ALint OpenAL_SoundStream::refillQueue() return queued; } -void OpenAL_SoundStream3D::applyUpdates() -{ - ALfloat gain = mVolume*mBaseVolume; - ALfloat pitch = mPitch; - if((mPos - mOutput.mPos).length2() > mMaxDistance*mMaxDistance) - gain = 0.0f; - else if(!(mFlags&MWBase::SoundManager::Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; - } - - alSourcef(mSource, AL_GAIN, gain); - alSourcef(mSource, AL_PITCH, pitch); - alSource3f(mSource, AL_POSITION, mPos[0], mPos[1], mPos[2]); - alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f); - throwALerror(); -} - - -// -// A regular 2D OpenAL sound -// -class OpenAL_Sound : public Sound -{ -protected: - OpenAL_Output &mOutput; - - ALuint mSource; - - friend class OpenAL_Output; - - void updateAll(bool local); - -private: - OpenAL_Sound(const OpenAL_Sound &rhs); - OpenAL_Sound& operator=(const OpenAL_Sound &rhs); - -public: - OpenAL_Sound(OpenAL_Output &output, ALuint src, const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags); - virtual ~OpenAL_Sound(); - - virtual void stop(); - virtual bool isPlaying(); - virtual double getTimeOffset(); - virtual void applyUpdates(); -}; - -// -// A regular 3D OpenAL sound -// -class OpenAL_Sound3D : public OpenAL_Sound -{ - OpenAL_Sound3D(const OpenAL_Sound &rhs); - OpenAL_Sound3D& operator=(const OpenAL_Sound &rhs); - -public: - OpenAL_Sound3D(OpenAL_Output &output, ALuint src, const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) - : OpenAL_Sound(output, src, pos, vol, basevol, pitch, mindist, maxdist, flags) - { } - - virtual void applyUpdates(); -}; - -OpenAL_Sound::OpenAL_Sound(OpenAL_Output &output, ALuint src, const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) - : Sound(pos, vol, basevol, pitch, mindist, maxdist, flags) - , mOutput(output), mSource(src) -{ - mOutput.mActiveSounds.push_back(this); -} -OpenAL_Sound::~OpenAL_Sound() -{ - alSourceStop(mSource); - alSourcei(mSource, AL_BUFFER, 0); - - mOutput.mFreeSources.push_back(mSource); - - mOutput.mActiveSounds.erase(std::find(mOutput.mActiveSounds.begin(), - mOutput.mActiveSounds.end(), this)); -} - -void OpenAL_Sound::stop() -{ - alSourceStop(mSource); - throwALerror(); -} - -bool OpenAL_Sound::isPlaying() -{ - ALint state; - - alGetSourcei(mSource, AL_SOURCE_STATE, &state); - throwALerror(); - - return state==AL_PLAYING || state==AL_PAUSED; -} - -double OpenAL_Sound::getTimeOffset() -{ - ALfloat t; - - alGetSourcef(mSource, AL_SEC_OFFSET, &t); - throwALerror(); - - return t; -} - -void OpenAL_Sound::updateAll(bool local) -{ - alSourcef(mSource, AL_REFERENCE_DISTANCE, mMinDistance); - alSourcef(mSource, AL_MAX_DISTANCE, mMaxDistance); - if(local) - { - alSourcef(mSource, AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(mSource, AL_SOURCE_RELATIVE, AL_TRUE); - } - else - { - alSourcef(mSource, AL_ROLLOFF_FACTOR, 1.0f); - alSourcei(mSource, AL_SOURCE_RELATIVE, AL_FALSE); - } - alSourcei(mSource, AL_LOOPING, (mFlags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE); - - applyUpdates(); -} - -void OpenAL_Sound::applyUpdates() -{ - ALfloat gain = mVolume*mBaseVolume; - ALfloat pitch = mPitch; - - if(!(mFlags&MWBase::SoundManager::Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; - } - - alSourcef(mSource, AL_GAIN, gain); - alSourcef(mSource, AL_PITCH, pitch); - alSource3f(mSource, AL_POSITION, mPos[0], mPos[1], mPos[2]); - alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f); - throwALerror(); -} - -void OpenAL_Sound3D::applyUpdates() -{ - ALfloat gain = mVolume*mBaseVolume; - ALfloat pitch = mPitch; - if((mPos - mOutput.mPos).length2() > mMaxDistance*mMaxDistance) - gain = 0.0f; - else if(!(mFlags&MWBase::SoundManager::Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; - } - - alSourcef(mSource, AL_GAIN, gain); - alSourcef(mSource, AL_PITCH, pitch); - alSource3f(mSource, AL_POSITION, mPos[0], mPos[1], mPos[2]); - alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f); - throwALerror(); -} - // // An OpenAL output device @@ -881,15 +621,16 @@ void OpenAL_Output::unloadSound(Sound_Handle data) SoundVec::const_iterator iter = mActiveSounds.begin(); for(;iter != mActiveSounds.end();++iter) { - if(!(*iter)->mSource) + if(!(*iter)->mHandle) continue; + ALuint source = GET_PTRID((*iter)->mHandle); ALint srcbuf; - alGetSourcei((*iter)->mSource, AL_BUFFER, &srcbuf); + alGetSourcei(source, AL_BUFFER, &srcbuf); if((ALuint)srcbuf == buffer) { - alSourceStop((*iter)->mSource); - alSourcei((*iter)->mSource, AL_BUFFER, 0); + alSourceStop(source); + alSourcei(source, AL_BUFFER, 0); } } alDeleteBuffers(1, &buffer); @@ -907,123 +648,281 @@ size_t OpenAL_Output::getSoundDataSize(Sound_Handle data) const } -MWBase::SoundPtr OpenAL_Output::playSound(Sound_Handle data, float vol, float basevol, float pitch, int flags,float offset) +MWBase::SoundPtr OpenAL_Output::playSound(Sound_Handle data, float vol, float basevol, float pitch, int flags, float offset) { - boost::shared_ptr sound; - ALuint src; + boost::shared_ptr sound; + ALuint source; if(mFreeSources.empty()) fail("No free sources"); - src = mFreeSources.front(); + source = mFreeSources.front(); mFreeSources.pop_front(); try { - sound.reset(new OpenAL_Sound(*this, src, osg::Vec3f(0.f, 0.f, 0.f), vol, basevol, pitch, 1.0f, 1000.0f, flags)); + alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); + alSourcef(source, AL_MAX_DISTANCE, 1000.0f); + alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f); + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + alSourcei(source, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE); + + ALfloat gain = vol*basevol; + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSource3f(source, AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + + alSourcef(source, AL_SEC_OFFSET, offset/pitch); + alSourcei(source, AL_BUFFER, GET_PTRID(data)); + + alSourcePlay(source); + throwALerror(); + + sound.reset(new Sound(osg::Vec3f(0.f, 0.f, 0.f), vol, basevol, pitch, 1.0f, 1000.0f, flags)); + sound->mHandle = MAKE_PTRID(source); + mActiveSounds.push_back(sound); } - catch(std::exception&) - { - mFreeSources.push_back(src); + catch(std::exception&) { + mFreeSources.push_back(source); throw; } - sound->updateAll(true); - alSourcei(src, AL_BUFFER, GET_PTRID(data)); - alSourcef(src, AL_SEC_OFFSET, offset/pitch); - - alSourcePlay(src); - throwALerror(); - return sound; } MWBase::SoundPtr OpenAL_Output::playSound3D(Sound_Handle data, const osg::Vec3f &pos, float vol, float basevol, float pitch, - float min, float max, int flags, float offset) + float mindist, float maxdist, int flags, float offset) { - boost::shared_ptr sound; - ALuint src; + boost::shared_ptr sound; + ALuint source; if(mFreeSources.empty()) fail("No free sources"); - src = mFreeSources.front(); + source = mFreeSources.front(); mFreeSources.pop_front(); try { - sound.reset(new OpenAL_Sound3D(*this, src, pos, vol, basevol, pitch, min, max, flags)); + alSourcef(source, AL_REFERENCE_DISTANCE, mindist); + alSourcef(source, AL_MAX_DISTANCE, maxdist); + alSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); + alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); + alSourcei(source, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE); + + ALfloat gain = vol*basevol; + if((pos - mPos).length2() > maxdist*maxdist) + gain = 0.0f; + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSourcefv(source, AL_POSITION, pos.ptr()); + alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + + alSourcef(source, AL_SEC_OFFSET, offset/pitch); + alSourcei(source, AL_BUFFER, GET_PTRID(data)); + + alSourcePlay(source); + throwALerror(); + + sound.reset(new Sound(pos, vol, basevol, pitch, mindist, maxdist, flags)); + sound->mHandle = MAKE_PTRID(source); + mActiveSounds.push_back(sound); } - catch(std::exception&) - { - mFreeSources.push_back(src); + catch(std::exception&) { + mFreeSources.push_back(source); throw; } - sound->updateAll(false); - alSourcei(src, AL_BUFFER, GET_PTRID(data)); - alSourcef(src, AL_SEC_OFFSET, offset/pitch); + return sound; +} + +void OpenAL_Output::stopSound(MWBase::SoundPtr sound) +{ + if(!sound->mHandle) + return; + + ALuint source = GET_PTRID(sound->mHandle); + sound->mHandle = 0; + + alSourceStop(source); + alSourcei(source, AL_BUFFER, 0); + + mFreeSources.push_back(source); + mActiveSounds.erase(std::find(mActiveSounds.begin(), mActiveSounds.end(), sound)); +} - alSourcePlay(src); +bool OpenAL_Output::isSoundPlaying(MWBase::SoundPtr sound) +{ + if(!sound->mHandle) + return false; + ALuint source = GET_PTRID(sound->mHandle); + ALint state; + + alGetSourcei(source, AL_SOURCE_STATE, &state); throwALerror(); - return sound; + return state == AL_PLAYING || state == AL_PAUSED; } MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) { - boost::shared_ptr sound; - ALuint src; + boost::shared_ptr sound; + OpenAL_SoundStream *stream = 0; + ALuint source; if(mFreeSources.empty()) fail("No free sources"); - src = mFreeSources.front(); + source = mFreeSources.front(); mFreeSources.pop_front(); if((flags&MWBase::SoundManager::Play_Loop)) std::cout <<"Warning: cannot loop stream \""<getName()<<"\""<< std::endl; - try - { - sound.reset(new OpenAL_SoundStream(*this, src, decoder, osg::Vec3f(0.0f, 0.0f, 0.0f), 1.0f, basevol, pitch, 1.0f, 1000.0f, flags)); + try { + alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); + alSourcef(source, AL_MAX_DISTANCE, 1000.0f); + alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f); + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + alSourcei(source, AL_LOOPING, AL_FALSE); + + ALfloat gain = basevol; + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSource3f(source, AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + throwALerror(); + + sound.reset(new Sound(osg::Vec3f(0.0f, 0.0f, 0.0f), 1.0f, basevol, pitch, 1.0f, 1000.0f, flags)); + stream = new OpenAL_SoundStream(source, decoder); + mStreamThread->add(stream); + sound->mHandle = stream; + mActiveStreams.push_back(sound); } - catch(std::exception&) - { - mFreeSources.push_back(src); + catch(std::exception&) { + mStreamThread->remove(stream); + delete stream; + mFreeSources.push_back(source); throw; } - sound->updateAll(true); - - sound->play(); return sound; } - -MWBase::SoundPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, float volume, float basevol, float pitch, float min, float max, int flags) +MWBase::SoundPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, float volume, float basevol, float pitch, float mindist, float maxdist, int flags) { - boost::shared_ptr sound; - ALuint src; + boost::shared_ptr sound; + OpenAL_SoundStream *stream = 0; + ALuint source; if(mFreeSources.empty()) fail("No free sources"); - src = mFreeSources.front(); + source = mFreeSources.front(); mFreeSources.pop_front(); if((flags&MWBase::SoundManager::Play_Loop)) std::cout <<"Warning: cannot loop stream \""<getName()<<"\""<< std::endl; - try - { - sound.reset(new OpenAL_SoundStream3D(*this, src, decoder, pos, volume, basevol, pitch, min, max, flags)); + try { + alSourcef(source, AL_REFERENCE_DISTANCE, mindist); + alSourcef(source, AL_MAX_DISTANCE, maxdist); + alSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); + alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); + alSourcei(source, AL_LOOPING, AL_FALSE); + + ALfloat gain = volume*basevol; + if((pos - mPos).length2() > maxdist*maxdist) + gain = 0.0f; + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSourcefv(source, AL_POSITION, pos.ptr()); + alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + throwALerror(); + + sound.reset(new Sound(pos, volume, basevol, pitch, mindist, maxdist, flags)); + stream = new OpenAL_SoundStream(source, decoder); + mStreamThread->add(stream); + sound->mHandle = stream; + mActiveStreams.push_back(sound); } - catch(std::exception&) - { - mFreeSources.push_back(src); + catch(std::exception&) { + mStreamThread->remove(stream); + delete stream; + mFreeSources.push_back(source); throw; } - sound->updateAll(false); - - sound->play(); return sound; } +void OpenAL_Output::stopStream(MWBase::SoundPtr sound) +{ + if(!sound->mHandle) + return; + OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); + ALuint source = stream->mSource; + + sound->mHandle = 0; + mStreamThread->remove(stream); + + alSourceStop(source); + alSourcei(source, AL_BUFFER, 0); + + mFreeSources.push_back(source); + mActiveStreams.erase(std::find(mActiveStreams.begin(), mActiveStreams.end(), sound)); + + delete stream; +} + +double OpenAL_Output::getStreamDelay(MWBase::SoundPtr sound) +{ + if(!sound->mHandle) + return 0.0; + OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); + return stream->getStreamDelay(); +} + +double OpenAL_Output::getStreamOffset(MWBase::SoundPtr sound) +{ + if(!sound->mHandle) + return 0.0; + OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); + boost::lock_guard lock(mStreamThread->mMutex); + return stream->getStreamOffset(); +} + +bool OpenAL_Output::isStreamPlaying(MWBase::SoundPtr sound) +{ + if(!sound->mHandle) + return false; + OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); + boost::lock_guard lock(mStreamThread->mMutex); + return stream->isPlaying(); +} + void OpenAL_Output::startUpdate() { @@ -1060,14 +959,17 @@ void OpenAL_Output::pauseSounds(int types) SoundVec::const_iterator sound = mActiveSounds.begin(); for(;sound != mActiveSounds.end();++sound) { - if(*sound && (*sound)->mSource && ((*sound)->getPlayType()&types)) - sources.push_back((*sound)->mSource); + if(*sound && (*sound)->mHandle && ((*sound)->getPlayType()&types)) + sources.push_back(GET_PTRID((*sound)->mHandle)); } StreamVec::const_iterator stream = mActiveStreams.begin(); for(;stream != mActiveStreams.end();++stream) { - if(*stream && (*stream)->mSource && ((*stream)->getPlayType()&types)) - sources.push_back((*stream)->mSource); + if(*stream && (*stream)->mHandle && ((*stream)->getPlayType()&types)) + { + OpenAL_SoundStream *strm = reinterpret_cast((*stream)->mHandle); + sources.push_back(strm->mSource); + } } if(!sources.empty()) { @@ -1082,14 +984,17 @@ void OpenAL_Output::resumeSounds(int types) SoundVec::const_iterator sound = mActiveSounds.begin(); for(;sound != mActiveSounds.end();++sound) { - if(*sound && (*sound)->mSource && ((*sound)->getPlayType()&types)) - sources.push_back((*sound)->mSource); + if(*sound && (*sound)->mHandle && ((*sound)->getPlayType()&types)) + sources.push_back(GET_PTRID((*sound)->mHandle)); } StreamVec::const_iterator stream = mActiveStreams.begin(); for(;stream != mActiveStreams.end();++stream) { - if(*stream && (*stream)->mSource && ((*stream)->getPlayType()&types)) - sources.push_back((*stream)->mSource); + if(*stream && (*stream)->mHandle && ((*stream)->getPlayType()&types)) + { + OpenAL_SoundStream *strm = reinterpret_cast((*stream)->mHandle); + sources.push_back(strm->mSource); + } } if(!sources.empty()) { diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index 751ec4fd2..b7c3603c6 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -16,9 +16,6 @@ namespace MWSound class SoundManager; class Sound; - class OpenAL_Sound; - class OpenAL_SoundStream; - class OpenAL_Output : public Sound_Output { ALCdevice *mDevice; @@ -27,9 +24,9 @@ namespace MWSound typedef std::deque IDDq; IDDq mFreeSources; - typedef std::vector SoundVec; + typedef std::vector SoundVec; SoundVec mActiveSounds; - typedef std::vector StreamVec; + typedef std::vector StreamVec; StreamVec mActiveStreams; Environment mLastEnvironment; @@ -45,9 +42,16 @@ namespace MWSound virtual MWBase::SoundPtr playSound(Sound_Handle data, float vol, float basevol, float pitch, int flags, float offset); virtual MWBase::SoundPtr playSound3D(Sound_Handle data, const osg::Vec3f &pos, float vol, float basevol, float pitch, float min, float max, int flags, float offset); + virtual void stopSound(MWBase::SoundPtr sound); + virtual bool isSoundPlaying(MWBase::SoundPtr sound); + virtual MWBase::SoundPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags); virtual MWBase::SoundPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, float vol, float basevol, float pitch, float min, float max, int flags); + virtual void stopStream(MWBase::SoundPtr sound); + virtual double getStreamDelay(MWBase::SoundPtr sound); + virtual double getStreamOffset(MWBase::SoundPtr sound); + virtual bool isStreamPlaying(MWBase::SoundPtr sound); virtual void startUpdate(); virtual void finishUpdate(); diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index f95ff169d..f467ba121 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -10,7 +10,6 @@ namespace MWSound Sound& operator=(const Sound &rhs); Sound(const Sound &rhs); - protected: osg::Vec3f mPos; float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */ float mBaseVolume; @@ -21,12 +20,13 @@ namespace MWSound float mFadeOutTime; + protected: + void *mHandle; + + friend class Sound_Output; + friend class OpenAL_Output; + public: - virtual void stop() = 0; - virtual bool isPlaying() = 0; - virtual double getTimeOffset() = 0; - virtual double getStreamDelay() const { return 0.0; } - virtual void applyUpdates() = 0; void setPosition(const osg::Vec3f &pos) { mPos = pos; } void setVolume(float volume) { mVolume = volume; } void setBaseVolume(float volume) { mBaseVolume = volume; } @@ -47,16 +47,11 @@ namespace MWSound bool getIs3D() const { return mFlags&Play_3D; } Sound(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) - : mPos(pos) - , mVolume(vol) - , mBaseVolume(basevol) - , mPitch(pitch) - , mMinDistance(mindist) - , mMaxDistance(maxdist) - , mFlags(flags) - , mFadeOutTime(0.0f) + : mPos(pos), mVolume(vol), mBaseVolume(basevol), mPitch(pitch) + , mMinDistance(mindist), mMaxDistance(maxdist), mFlags(flags) + , mFadeOutTime(0.0f), mHandle(0) { } - virtual ~Sound() { } + ~Sound() { } }; } diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index 0f69498aa..bdf40bf44 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -35,9 +35,16 @@ namespace MWSound /// @param offset Number of seconds into the sound to start playback. virtual MWBase::SoundPtr playSound3D(Sound_Handle data, const osg::Vec3f &pos, float vol, float basevol, float pitch, float min, float max, int flags, float offset) = 0; + virtual void stopSound(MWBase::SoundPtr sound) = 0; + virtual bool isSoundPlaying(MWBase::SoundPtr sound) = 0; + virtual MWBase::SoundPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) = 0; virtual MWBase::SoundPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, float vol, float basevol, float pitch, float min, float max, int flags) = 0; + virtual void stopStream(MWBase::SoundPtr sound) = 0; + virtual double getStreamDelay(MWBase::SoundPtr sound) = 0; + virtual double getStreamOffset(MWBase::SoundPtr sound) = 0; + virtual bool isStreamPlaying(MWBase::SoundPtr sound) = 0; virtual void startUpdate() = 0; virtual void finishUpdate() = 0; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index ceff1a619..82dd49f32 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -293,7 +293,7 @@ namespace MWSound void SoundManager::stopMusic() { if(mMusic) - mMusic->stop(); + mOutput->stopStream(mMusic); mMusic.reset(); } @@ -303,8 +303,7 @@ namespace MWSound return; std::cout <<"Playing "<streamSound(decoder, volumeFromType(Play_TypeMusic), 1.0f, Play_NoEnv|Play_TypeMusic|Play_2D); } - catch(std::exception &e) - { + catch(std::exception &e) { std::cout << "Music Error: " << e.what() << "\n"; } } @@ -366,7 +364,7 @@ namespace MWSound bool SoundManager::isMusicPlaying() { - return mMusic && mMusic->isPlaying(); + return mMusic && mOutput->isStreamPlaying(mMusic); } void SoundManager::playPlaylist(const std::string &playlist) @@ -411,9 +409,8 @@ namespace MWSound { MWBase::SoundPtr sound = snditer->second.first; Sound_Loudness *loudness = snditer->second.second; - float sec = sound->getTimeOffset(); - if(sound->isPlaying()) - return loudness->getLoudnessAtTime(sec); + float sec = mOutput->getStreamOffset(sound); + return loudness->getLoudnessAtTime(sec); } return 0.0f; @@ -450,7 +447,7 @@ namespace MWSound SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - if(snditer->second.first->isPlaying()) + if(mOutput->isStreamPlaying(snditer->second.first)) return false; return true; } @@ -462,7 +459,7 @@ namespace MWSound SaySoundMap::iterator snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - snditer->second.first->stop(); + mOutput->stopStream(snditer->second.first); mActiveSaySounds.erase(snditer); } mPendingSaySounds.erase(ptr); @@ -485,6 +482,16 @@ namespace MWSound return track; } + void SoundManager::stopTrack(MWBase::SoundPtr sound) + { + mOutput->stopStream(sound); + } + + double SoundManager::getTrackTimeDelay(MWBase::SoundPtr sound) + { + return mOutput->getStreamDelay(sound); + } + MWBase::SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, PlayType type, PlayMode mode, float offset) { @@ -586,6 +593,11 @@ namespace MWSound return sound; } + void SoundManager::stopSound(MWBase::SoundPtr sound) + { + mOutput->stopSound(sound); + } + void SoundManager::stopSound3D(const MWWorld::Ptr &ptr, const std::string& soundId) { SoundMap::iterator snditer = mActiveSounds.find(ptr); @@ -596,7 +608,7 @@ namespace MWSound for(;sndidx != snditer->second.end();++sndidx) { if(sndidx->second == sfx) - sndidx->first->stop(); + mOutput->stopSound(sndidx->first); } } } @@ -608,7 +620,7 @@ namespace MWSound { SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) - sndidx->first->stop(); + mOutput->stopSound(sndidx->first); } } @@ -623,7 +635,7 @@ namespace MWSound { SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) - sndidx->first->stop(); + mOutput->stopSound(sndidx->first); } ++snditer; } @@ -634,7 +646,7 @@ namespace MWSound sayiter->first != MWMechanics::getPlayer() && sayiter->first.getCell() == cell) { - sayiter->second.first->stop(); + mOutput->stopStream(sayiter->second.first); } ++sayiter; } @@ -650,7 +662,7 @@ namespace MWSound for(;sndidx != snditer->second.end();++sndidx) { if(sndidx->second == sfx) - sndidx->first->stop(); + mOutput->stopSound(sndidx->first); } } } @@ -680,7 +692,7 @@ namespace MWSound SoundBufferRefPairList::const_iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) { - if(sndidx->second == sfx && sndidx->first->isPlaying()) + if(sndidx->second == sfx && mOutput->isSoundPlaying(sndidx->first)) return true; } } @@ -788,7 +800,7 @@ namespace MWSound env = Env_Underwater; else if(mUnderwaterSound) { - mUnderwaterSound->stop(); + mOutput->stopSound(mUnderwaterSound); mUnderwaterSound.reset(); } @@ -803,7 +815,7 @@ namespace MWSound if(mListenerUnderwater) { // Play underwater sound (after updating listener) - if(!(mUnderwaterSound && mUnderwaterSound->isPlaying())) + if(!(mUnderwaterSound && mOutput->isSoundPlaying(mUnderwaterSound))) mUnderwaterSound = playSound("Underwater", 1.0f, 1.0f, Play_TypeSfx, Play_LoopNoEnv); } @@ -814,15 +826,35 @@ namespace MWSound SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); while(sndidx != snditer->second.end()) { - if(!updateSound(sndidx->first, snditer->first, duration)) + MWWorld::Ptr ptr = snditer->first; + MWBase::SoundPtr sound = sndidx->first; + if(!ptr.isEmpty() && sound->getIs3D()) + { + const ESM::Position &pos = ptr.getRefData().getPosition(); + const osg::Vec3f objpos(pos.asVec3()); + sound->setPosition(objpos); + + if(sound->getDistanceCull()) + { + if((mListenerPos - objpos).length2() > 2000*2000) + mOutput->stopSound(sound); + } + } + + if(!mOutput->isSoundPlaying(sound)) { + mOutput->stopSound(sound); Sound_Buffer *sfx = sndidx->second; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); sndidx = snditer->second.erase(sndidx); } else + { + sound->updateFade(duration); + ++sndidx; + } } if(snditer->second.empty()) mActiveSounds.erase(snditer++); @@ -862,36 +894,34 @@ namespace MWSound SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); while(sayiter != mActiveSaySounds.end()) { - if(!updateSound(sayiter->second.first, sayiter->first, duration)) - mActiveSaySounds.erase(sayiter++); - else - ++sayiter; - } - mOutput->finishUpdate(); - } + MWWorld::Ptr ptr = sayiter->first; + MWBase::SoundPtr sound = sayiter->second.first; + if(!ptr.isEmpty() && sound->getIs3D()) + { + const ESM::Position &pos = ptr.getRefData().getPosition(); + const osg::Vec3f objpos(pos.asVec3()); + sound->setPosition(objpos); - bool SoundManager::updateSound(MWBase::SoundPtr sound, const MWWorld::Ptr& ptr, float duration) - { - if(!ptr.isEmpty() && sound->getIs3D()) - { - const ESM::Position &pos = ptr.getRefData().getPosition(); - const osg::Vec3f objpos(pos.asVec3()); - sound->setPosition(objpos); + if(sound->getDistanceCull()) + { + if((mListenerPos - objpos).length2() > 2000*2000) + mOutput->stopStream(sound); + } + } - if(sound->getDistanceCull()) + if(!mOutput->isStreamPlaying(sound)) { - if((mListenerPos - objpos).length2() > 2000*2000) - sound->stop(); + mOutput->stopStream(sound); + mActiveSaySounds.erase(sayiter++); } - } - - if(!sound->isPlaying()) - return false; - - sound->updateFade(duration); + else + { + sound->updateFade(duration); - sound->applyUpdates(); - return true; + ++sayiter; + } + } + mOutput->finishUpdate(); } @@ -928,7 +958,6 @@ namespace MWSound { MWBase::SoundPtr sound = sndidx->first; sound->setBaseVolume(volumeFromType(sound->getPlayType())); - sound->applyUpdates(); } } SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); @@ -936,12 +965,10 @@ namespace MWSound { MWBase::SoundPtr sound = sayiter->second.first; sound->setBaseVolume(volumeFromType(sound->getPlayType())); - sound->applyUpdates(); } if(mMusic) { mMusic->setBaseVolume(volumeFromType(mMusic->getPlayType())); - mMusic->applyUpdates(); } mOutput->finishUpdate(); } @@ -1056,7 +1083,7 @@ namespace MWSound SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) { - sndidx->first->stop(); + mOutput->stopSound(sndidx->first); Sound_Buffer *sfx = sndidx->second; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); @@ -1065,7 +1092,7 @@ namespace MWSound mActiveSounds.clear(); SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); for(;sayiter != mActiveSaySounds.end();++sayiter) - sayiter->second.first->stop(); + mOutput->stopStream(sayiter->second.first); mActiveSaySounds.clear(); mPendingSaySounds.clear(); mUnderwaterSound.reset(); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 9c090585b..5f4cf6ebc 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -116,7 +116,6 @@ namespace MWSound MWBase::SoundPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal); void streamMusicFull(const std::string& filename); - bool updateSound(MWBase::SoundPtr sound, const MWWorld::Ptr &ptr, float duration); void updateSounds(float duration); void updateRegionSound(float duration); @@ -174,6 +173,14 @@ namespace MWSound virtual MWBase::SoundPtr playTrack(const DecoderPtr& decoder, PlayType type); ///< Play a 2D audio track, using a custom decoder + virtual void stopTrack(MWBase::SoundPtr sound); + ///< Stop the given audio track from playing + + virtual double getTrackTimeDelay(MWBase::SoundPtr sound); + ///< Retives the time delay, in seconds, of the audio track (must be a sound + /// returned by \ref playTrack). Only intended to be called by the track + /// decoder's read method. + virtual MWBase::SoundPtr playSound(const std::string& soundId, float volume, float pitch, PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal, float offset=0); ///< Play a sound, independently of 3D-position ///< @param offset Number of seconds into the sound to start playback. @@ -189,6 +196,9 @@ namespace MWSound ///< Play a 3D sound at \a initialPos. If the sound should be moving, it must be updated using Sound::setPosition. ///< @param offset Number of seconds into the sound to start playback. + virtual void stopSound(MWBase::SoundPtr sound); + ///< Stop the given sound from playing + virtual void stopSound3D(const MWWorld::Ptr &reference, const std::string& soundId); ///< Stop the given object from playing the given sound, diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 4ec4d1432..08ae6f2b0 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -190,7 +190,7 @@ namespace MWWorld { MWBase::Environment::get().getWorld()->explodeSpell(pos, it->mEffects, caster, ESM::RT_Target, it->mSpellId, it->mSourceName); - it->mSound->stop(); + MWBase::Environment::get().getSoundManager()->stopSound(it->mSound); mParent->removeChild(it->mNode); it = mMagicBolts.erase(it); @@ -264,7 +264,7 @@ namespace MWWorld for (std::vector::iterator it = mMagicBolts.begin(); it != mMagicBolts.end(); ++it) { mParent->removeChild(it->mNode); - it->mSound->stop(); + MWBase::Environment::get().getSoundManager()->stopSound(it->mSound); } mMagicBolts.clear(); } diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index afa819121..9a93f3827 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -738,7 +738,7 @@ void WeatherManager::update(float duration, bool paused) void WeatherManager::stopSounds() { if (mAmbientSound.get()) - mAmbientSound->stop(); + MWBase::Environment::get().getSoundManager()->stopSound(mAmbientSound); mAmbientSound.reset(); mPlayingSoundID.clear(); } From 1ce3e7f5b999e95829205c4c2f93b7df00716194 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 30 Nov 2015 07:32:42 -0800 Subject: [PATCH 02/11] Use a separate type for streams They're basically the same, but it's to help avoid accidents with passing non- streaming sounds to the stream functions, or vice-versa. --- apps/openmw/mwbase/soundmanager.hpp | 10 +++++---- apps/openmw/mwsound/movieaudiofactory.cpp | 5 +++-- apps/openmw/mwsound/openal_output.cpp | 20 ++++++++--------- apps/openmw/mwsound/openal_output.hpp | 16 +++++++------- apps/openmw/mwsound/sound.hpp | 15 ++++++++++--- apps/openmw/mwsound/sound_output.hpp | 14 ++++++------ apps/openmw/mwsound/soundmanagerimp.cpp | 26 +++++++++++------------ apps/openmw/mwsound/soundmanagerimp.hpp | 12 +++++------ 8 files changed, 65 insertions(+), 53 deletions(-) diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index e75949a5b..46f245c46 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -15,6 +15,7 @@ namespace MWWorld namespace MWSound { class Sound; + class Stream; struct Sound_Decoder; typedef boost::shared_ptr DecoderPtr; } @@ -22,6 +23,7 @@ namespace MWSound namespace MWBase { typedef boost::shared_ptr SoundPtr; + typedef boost::shared_ptr SoundStreamPtr; /// \brief Interface for sound manager (implemented in MWSound) class SoundManager @@ -104,13 +106,13 @@ namespace MWBase /// and get an average loudness value (scale [0,1]) at the current time position. /// If the actor is not saying anything, returns 0. - virtual SoundPtr playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0; + virtual SoundStreamPtr playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0; ///< Play a 2D audio track, using a custom decoder - virtual void stopTrack(SoundPtr sound) = 0; + virtual void stopTrack(SoundStreamPtr stream) = 0; ///< Stop the given audio track from playing - virtual double getTrackTimeDelay(SoundPtr sound) = 0; + virtual double getTrackTimeDelay(SoundStreamPtr stream) = 0; ///< Retives the time delay, in seconds, of the audio track (must be a sound /// returned by \ref playTrack). Only intended to be called by the track /// decoder's read method. @@ -166,7 +168,7 @@ namespace MWBase virtual void setListenerPosDir(const osg::Vec3f &pos, const osg::Vec3f &dir, const osg::Vec3f &up) = 0; - virtual void updatePtr (const MWWorld::Ptr& old, const MWWorld::Ptr& updated) = 0; + virtual void updatePtr(const MWWorld::Ptr& old, const MWWorld::Ptr& updated) = 0; virtual void clear() = 0; }; diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 1f7b8a515..554b62d26 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -92,7 +92,7 @@ namespace MWSound mDecoderBridge.reset(); } - MWBase::SoundPtr mAudioTrack; + MWBase::SoundStreamPtr mAudioTrack; boost::shared_ptr mDecoderBridge; }; @@ -163,7 +163,8 @@ namespace MWSound boost::shared_ptr decoder(new MWSound::MovieAudioDecoder(videoState)); decoder->setupFormat(); - MWBase::SoundPtr sound = MWBase::Environment::get().getSoundManager()->playTrack(decoder->mDecoderBridge, MWBase::SoundManager::Play_TypeMovie); + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); + MWBase::SoundStreamPtr sound = sndMgr->playTrack(decoder->mDecoderBridge, MWBase::SoundManager::Play_TypeMovie); if (!sound.get()) { decoder.reset(); diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 3607f71a4..5757e92cf 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -776,9 +776,9 @@ bool OpenAL_Output::isSoundPlaying(MWBase::SoundPtr sound) } -MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) +MWBase::SoundStreamPtr OpenAL_Output::streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) { - boost::shared_ptr sound; + MWBase::SoundStreamPtr sound; OpenAL_SoundStream *stream = 0; ALuint source; @@ -810,7 +810,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float basevol, f alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); throwALerror(); - sound.reset(new Sound(osg::Vec3f(0.0f, 0.0f, 0.0f), 1.0f, basevol, pitch, 1.0f, 1000.0f, flags)); + sound.reset(new Stream(osg::Vec3f(0.0f, 0.0f, 0.0f), 1.0f, basevol, pitch, 1.0f, 1000.0f, flags)); stream = new OpenAL_SoundStream(source, decoder); mStreamThread->add(stream); sound->mHandle = stream; @@ -826,9 +826,9 @@ MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float basevol, f return sound; } -MWBase::SoundPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, float volume, float basevol, float pitch, float mindist, float maxdist, int flags) +MWBase::SoundStreamPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, float volume, float basevol, float pitch, float mindist, float maxdist, int flags) { - boost::shared_ptr sound; + MWBase::SoundStreamPtr sound; OpenAL_SoundStream *stream = 0; ALuint source; @@ -862,7 +862,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const osg::Vec alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); throwALerror(); - sound.reset(new Sound(pos, volume, basevol, pitch, mindist, maxdist, flags)); + sound.reset(new Stream(pos, volume, basevol, pitch, mindist, maxdist, flags)); stream = new OpenAL_SoundStream(source, decoder); mStreamThread->add(stream); sound->mHandle = stream; @@ -878,7 +878,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const osg::Vec return sound; } -void OpenAL_Output::stopStream(MWBase::SoundPtr sound) +void OpenAL_Output::stopStream(MWBase::SoundStreamPtr sound) { if(!sound->mHandle) return; @@ -897,7 +897,7 @@ void OpenAL_Output::stopStream(MWBase::SoundPtr sound) delete stream; } -double OpenAL_Output::getStreamDelay(MWBase::SoundPtr sound) +double OpenAL_Output::getStreamDelay(MWBase::SoundStreamPtr sound) { if(!sound->mHandle) return 0.0; @@ -905,7 +905,7 @@ double OpenAL_Output::getStreamDelay(MWBase::SoundPtr sound) return stream->getStreamDelay(); } -double OpenAL_Output::getStreamOffset(MWBase::SoundPtr sound) +double OpenAL_Output::getStreamOffset(MWBase::SoundStreamPtr sound) { if(!sound->mHandle) return 0.0; @@ -914,7 +914,7 @@ double OpenAL_Output::getStreamOffset(MWBase::SoundPtr sound) return stream->getStreamOffset(); } -bool OpenAL_Output::isStreamPlaying(MWBase::SoundPtr sound) +bool OpenAL_Output::isStreamPlaying(MWBase::SoundStreamPtr sound) { if(!sound->mHandle) return false; diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index b7c3603c6..0c074b126 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -26,7 +26,7 @@ namespace MWSound typedef std::vector SoundVec; SoundVec mActiveSounds; - typedef std::vector StreamVec; + typedef std::vector StreamVec; StreamVec mActiveStreams; Environment mLastEnvironment; @@ -45,13 +45,13 @@ namespace MWSound virtual void stopSound(MWBase::SoundPtr sound); virtual bool isSoundPlaying(MWBase::SoundPtr sound); - virtual MWBase::SoundPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags); - virtual MWBase::SoundPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, - float vol, float basevol, float pitch, float min, float max, int flags); - virtual void stopStream(MWBase::SoundPtr sound); - virtual double getStreamDelay(MWBase::SoundPtr sound); - virtual double getStreamOffset(MWBase::SoundPtr sound); - virtual bool isStreamPlaying(MWBase::SoundPtr sound); + virtual MWBase::SoundStreamPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags); + virtual MWBase::SoundStreamPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, + float vol, float basevol, float pitch, float min, float max, int flags); + virtual void stopStream(MWBase::SoundStreamPtr sound); + virtual double getStreamDelay(MWBase::SoundStreamPtr sound); + virtual double getStreamOffset(MWBase::SoundStreamPtr sound); + virtual bool isStreamPlaying(MWBase::SoundStreamPtr sound); virtual void startUpdate(); virtual void finishUpdate(); diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index f467ba121..b76e4d6eb 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -5,8 +5,7 @@ namespace MWSound { - class Sound - { + class Sound { Sound& operator=(const Sound &rhs); Sound(const Sound &rhs); @@ -51,7 +50,17 @@ namespace MWSound , mMinDistance(mindist), mMaxDistance(maxdist), mFlags(flags) , mFadeOutTime(0.0f), mHandle(0) { } - ~Sound() { } + }; + + // Same as above, but it's a different type since the output handles them differently + class Stream : public Sound { + Stream& operator=(const Stream &rhs); + Stream(const Stream &rhs); + + public: + Stream(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) + : Sound(pos, vol, basevol, pitch, mindist, maxdist, flags) + { } }; } diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index bdf40bf44..061fcdf07 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -38,13 +38,13 @@ namespace MWSound virtual void stopSound(MWBase::SoundPtr sound) = 0; virtual bool isSoundPlaying(MWBase::SoundPtr sound) = 0; - virtual MWBase::SoundPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) = 0; - virtual MWBase::SoundPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, - float vol, float basevol, float pitch, float min, float max, int flags) = 0; - virtual void stopStream(MWBase::SoundPtr sound) = 0; - virtual double getStreamDelay(MWBase::SoundPtr sound) = 0; - virtual double getStreamOffset(MWBase::SoundPtr sound) = 0; - virtual bool isStreamPlaying(MWBase::SoundPtr sound) = 0; + virtual MWBase::SoundStreamPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) = 0; + virtual MWBase::SoundStreamPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, + float vol, float basevol, float pitch, float min, float max, int flags) = 0; + virtual void stopStream(MWBase::SoundStreamPtr sound) = 0; + virtual double getStreamDelay(MWBase::SoundStreamPtr sound) = 0; + virtual double getStreamOffset(MWBase::SoundStreamPtr sound) = 0; + virtual bool isStreamPlaying(MWBase::SoundStreamPtr sound) = 0; virtual void startUpdate() = 0; virtual void finishUpdate() = 0; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 82dd49f32..c40d2cd3e 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -241,7 +241,7 @@ namespace MWSound return decoder; } - MWBase::SoundPtr SoundManager::playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal) + MWBase::SoundStreamPtr SoundManager::playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal) { MWBase::World* world = MWBase::Environment::get().getWorld(); static const float fAudioMinDistanceMult = world->getStore().get().find("fAudioMinDistanceMult")->getFloat(); @@ -392,7 +392,7 @@ namespace MWSound mPendingSaySounds[ptr] = std::make_pair(decoder, loudness); else { - MWBase::SoundPtr sound = playVoice(decoder, objpos, (ptr == MWMechanics::getPlayer())); + MWBase::SoundStreamPtr sound = playVoice(decoder, objpos, (ptr == MWMechanics::getPlayer())); mActiveSaySounds[ptr] = std::make_pair(sound, loudness); } } @@ -407,7 +407,7 @@ namespace MWSound SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - MWBase::SoundPtr sound = snditer->second.first; + MWBase::SoundStreamPtr sound = snditer->second.first; Sound_Loudness *loudness = snditer->second.second; float sec = mOutput->getStreamOffset(sound); return loudness->getLoudnessAtTime(sec); @@ -432,7 +432,7 @@ namespace MWSound mPendingSaySounds[MWWorld::Ptr()] = std::make_pair(decoder, loudness); else { - MWBase::SoundPtr sound = playVoice(decoder, osg::Vec3f(), true); + MWBase::SoundStreamPtr sound = playVoice(decoder, osg::Vec3f(), true); mActiveSaySounds[MWWorld::Ptr()] = std::make_pair(sound, loudness); } } @@ -466,9 +466,9 @@ namespace MWSound } - MWBase::SoundPtr SoundManager::playTrack(const DecoderPtr& decoder, PlayType type) + MWBase::SoundStreamPtr SoundManager::playTrack(const DecoderPtr& decoder, PlayType type) { - MWBase::SoundPtr track; + MWBase::SoundStreamPtr track; if(!mOutput->isInitialized()) return track; try @@ -482,14 +482,14 @@ namespace MWSound return track; } - void SoundManager::stopTrack(MWBase::SoundPtr sound) + void SoundManager::stopTrack(MWBase::SoundStreamPtr stream) { - mOutput->stopStream(sound); + mOutput->stopStream(stream); } - double SoundManager::getTrackTimeDelay(MWBase::SoundPtr sound) + double SoundManager::getTrackTimeDelay(MWBase::SoundStreamPtr stream) { - return mOutput->getStreamDelay(sound); + return mOutput->getStreamDelay(stream); } @@ -876,7 +876,7 @@ namespace MWSound const ESM::Position &pos = ptr.getRefData().getPosition(); const osg::Vec3f objpos(pos.asVec3()); - MWBase::SoundPtr sound = playVoice(decoder, + MWBase::SoundStreamPtr sound = playVoice(decoder, objpos, (ptr == MWMechanics::getPlayer()) ); mActiveSaySounds[ptr] = std::make_pair(sound, loudness); @@ -895,7 +895,7 @@ namespace MWSound while(sayiter != mActiveSaySounds.end()) { MWWorld::Ptr ptr = sayiter->first; - MWBase::SoundPtr sound = sayiter->second.first; + MWBase::SoundStreamPtr sound = sayiter->second.first; if(!ptr.isEmpty() && sound->getIs3D()) { const ESM::Position &pos = ptr.getRefData().getPosition(); @@ -963,7 +963,7 @@ namespace MWSound SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); for(;sayiter != mActiveSaySounds.end();++sayiter) { - MWBase::SoundPtr sound = sayiter->second.first; + MWBase::SoundStreamPtr sound = sayiter->second.first; sound->setBaseVolume(volumeFromType(sound->getPlayType())); } if(mMusic) diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 5f4cf6ebc..e0214e091 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -79,7 +79,7 @@ namespace MWSound typedef std::deque SoundList; SoundList mUnusedBuffers; - boost::shared_ptr mMusic; + MWBase::SoundStreamPtr mMusic; std::string mCurrentPlaylist; typedef std::pair SoundBufferRefPair; @@ -87,7 +87,7 @@ namespace MWSound typedef std::map SoundMap; SoundMap mActiveSounds; - typedef std::pair SoundLoudnessPair; + typedef std::pair SoundLoudnessPair; typedef std::map SaySoundMap; SaySoundMap mActiveSaySounds; @@ -113,7 +113,7 @@ namespace MWSound // to start streaming DecoderPtr loadVoice(const std::string &voicefile, Sound_Loudness **lipdata); - MWBase::SoundPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal); + MWBase::SoundStreamPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal); void streamMusicFull(const std::string& filename); void updateSounds(float duration); @@ -170,13 +170,13 @@ namespace MWSound /// and get an average loudness value (scale [0,1]) at the current time position. /// If the actor is not saying anything, returns 0. - virtual MWBase::SoundPtr playTrack(const DecoderPtr& decoder, PlayType type); + virtual MWBase::SoundStreamPtr playTrack(const DecoderPtr& decoder, PlayType type); ///< Play a 2D audio track, using a custom decoder - virtual void stopTrack(MWBase::SoundPtr sound); + virtual void stopTrack(MWBase::SoundStreamPtr stream); ///< Stop the given audio track from playing - virtual double getTrackTimeDelay(MWBase::SoundPtr sound); + virtual double getTrackTimeDelay(MWBase::SoundStreamPtr stream); ///< Retives the time delay, in seconds, of the audio track (must be a sound /// returned by \ref playTrack). Only intended to be called by the track /// decoder's read method. From 4bd235284b20c7dd7728ee31cb258391ddcc14e2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 30 Nov 2015 08:00:02 -0800 Subject: [PATCH 03/11] Rename a couple members to avoid confusion --- apps/openmw/mwsound/openal_output.cpp | 25 +++++++++++++------------ apps/openmw/mwsound/openal_output.hpp | 22 +++++++++------------- apps/openmw/mwsound/sound_output.hpp | 5 +---- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 5757e92cf..3d5a97095 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -666,7 +666,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(Sound_Handle data, float vol, float ba alSourcei(source, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE); ALfloat gain = vol*basevol; - if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mListenerEnv == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -715,9 +715,9 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(Sound_Handle data, const osg::Vec3f alSourcei(source, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE); ALfloat gain = vol*basevol; - if((pos - mPos).length2() > maxdist*maxdist) + if((pos - mListenerPos).length2() > maxdist*maxdist) gain = 0.0f; - if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mListenerEnv == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -797,7 +797,7 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound(DecoderPtr decoder, float base alSourcei(source, AL_LOOPING, AL_FALSE); ALfloat gain = basevol; - if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mListenerEnv == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -847,9 +847,9 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const os alSourcei(source, AL_LOOPING, AL_FALSE); ALfloat gain = volume*basevol; - if((pos - mPos).length2() > maxdist*maxdist) + if((pos - mListenerPos).length2() > maxdist*maxdist) gain = 0.0f; - if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mListenerEnv == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -937,19 +937,19 @@ void OpenAL_Output::finishUpdate() void OpenAL_Output::updateListener(const osg::Vec3f &pos, const osg::Vec3f &atdir, const osg::Vec3f &updir, Environment env) { - mPos = pos; - mLastEnvironment = env; - if(mContext) { ALfloat orient[6] = { atdir.x(), atdir.y(), atdir.z(), updir.x(), updir.y(), updir.z() }; - alListener3f(AL_POSITION, mPos.x(), mPos.y(), mPos.z()); + alListenerfv(AL_POSITION, pos.ptr()); alListenerfv(AL_ORIENTATION, orient); throwALerror(); } + + mListenerPos = pos; + mListenerEnv = env; } @@ -1011,8 +1011,9 @@ void OpenAL_Output::loadLoudnessAsync(DecoderPtr decoder, Sound_Loudness *loudne OpenAL_Output::OpenAL_Output(SoundManager &mgr) - : Sound_Output(mgr), mDevice(0), mContext(0), mLastEnvironment(Env_Normal), - mStreamThread(new StreamThread) + : Sound_Output(mgr), mDevice(0), mContext(0) + , mListenerPos(0.0f, 0.0f, 0.0f), mListenerEnv(Env_Normal) + , mStreamThread(new StreamThread) { } diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index 0c074b126..c49bd3dbb 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -29,8 +29,16 @@ namespace MWSound typedef std::vector StreamVec; StreamVec mActiveStreams; - Environment mLastEnvironment; + osg::Vec3f mListenerPos; + Environment mListenerEnv; + struct StreamThread; + std::auto_ptr mStreamThread; + + OpenAL_Output& operator=(const OpenAL_Output &rhs); + OpenAL_Output(const OpenAL_Output &rhs); + + public: virtual std::vector enumerate(); virtual void init(const std::string &devname=""); virtual void deinit(); @@ -63,20 +71,8 @@ namespace MWSound virtual void loadLoudnessAsync(DecoderPtr decoder, Sound_Loudness *loudness); - OpenAL_Output& operator=(const OpenAL_Output &rhs); - OpenAL_Output(const OpenAL_Output &rhs); - OpenAL_Output(SoundManager &mgr); virtual ~OpenAL_Output(); - - struct StreamThread; - std::auto_ptr mStreamThread; - - friend class OpenAL_Sound; - friend class OpenAL_Sound3D; - friend class OpenAL_SoundStream; - friend class OpenAL_SoundStream3D; - friend class SoundManager; }; #ifndef DEFAULT_OUTPUT #define DEFAULT_OUTPUT(x) ::MWSound::OpenAL_Output((x)) diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index 061fcdf07..fcb992f58 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -64,12 +64,9 @@ namespace MWSound protected: bool mInitialized; - osg::Vec3f mPos; Sound_Output(SoundManager &mgr) - : mManager(mgr) - , mInitialized(false) - , mPos(0.0f, 0.0f, 0.0f) + : mManager(mgr), mInitialized(false) { } public: virtual ~Sound_Output() { } From a6db96b2d8defa2bd8c683438663625cd28058c2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 30 Nov 2015 14:34:14 -0800 Subject: [PATCH 04/11] Update sound and stream parameters --- apps/openmw/mwsound/openal_output.cpp | 55 +++++++++++++++++++++++++ apps/openmw/mwsound/openal_output.hpp | 2 + apps/openmw/mwsound/sound.hpp | 6 +++ apps/openmw/mwsound/sound_output.hpp | 2 + apps/openmw/mwsound/soundmanagerimp.cpp | 5 +++ 5 files changed, 70 insertions(+) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 3d5a97095..f93829ae5 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -775,6 +775,33 @@ bool OpenAL_Output::isSoundPlaying(MWBase::SoundPtr sound) return state == AL_PLAYING || state == AL_PAUSED; } +void OpenAL_Output::updateSound(MWBase::SoundPtr sound) +{ + if(!sound->mHandle) return; + ALuint source = GET_PTRID(sound->mHandle); + + const osg::Vec3f &pos = sound->getPosition(); + ALfloat gain = sound->getRealVolume(); + ALfloat pitch = sound->getPitch(); + if(sound->getIs3D()) + { + ALfloat maxdist = sound->getMaxDistance(); + if((pos - mListenerPos).length2() > maxdist*maxdist) + gain = 0.0f; + } + if(sound->getUseEnv() && mListenerEnv == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSourcefv(source, AL_POSITION, pos.ptr()); + alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); +} + MWBase::SoundStreamPtr OpenAL_Output::streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) { @@ -923,6 +950,34 @@ bool OpenAL_Output::isStreamPlaying(MWBase::SoundStreamPtr sound) return stream->isPlaying(); } +void OpenAL_Output::updateStream(MWBase::SoundStreamPtr sound) +{ + if(!sound->mHandle) return; + OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); + ALuint source = stream->mSource; + + const osg::Vec3f &pos = sound->getPosition(); + ALfloat gain = sound->getRealVolume(); + ALfloat pitch = sound->getPitch(); + if(sound->getIs3D()) + { + ALfloat maxdist = sound->getMaxDistance(); + if((pos - mListenerPos).length2() > maxdist*maxdist) + gain = 0.0f; + } + if(sound->getUseEnv() && mListenerEnv == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSourcefv(source, AL_POSITION, pos.ptr()); + alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); +} + void OpenAL_Output::startUpdate() { diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index c49bd3dbb..24b9c855f 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -52,6 +52,7 @@ namespace MWSound float vol, float basevol, float pitch, float min, float max, int flags, float offset); virtual void stopSound(MWBase::SoundPtr sound); virtual bool isSoundPlaying(MWBase::SoundPtr sound); + virtual void updateSound(MWBase::SoundPtr sound); virtual MWBase::SoundStreamPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags); virtual MWBase::SoundStreamPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, @@ -60,6 +61,7 @@ namespace MWSound virtual double getStreamDelay(MWBase::SoundStreamPtr sound); virtual double getStreamOffset(MWBase::SoundStreamPtr sound); virtual bool isStreamPlaying(MWBase::SoundStreamPtr sound); + virtual void updateStream(MWBase::SoundStreamPtr sound); virtual void startUpdate(); virtual void finishUpdate(); diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index b76e4d6eb..ec55db580 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -40,8 +40,14 @@ namespace MWSound } } + const osg::Vec3f &getPosition() const { return mPos; } + float getRealVolume() const { return mVolume * mBaseVolume; } + float getPitch() const { return mPitch; } + float getMaxDistance() const { return mMaxDistance; } + MWBase::SoundManager::PlayType getPlayType() const { return (MWBase::SoundManager::PlayType)(mFlags&MWBase::SoundManager::Play_TypeMask); } + bool getUseEnv() const { return !(mFlags&MWBase::SoundManager::Play_NoEnv); } bool getDistanceCull() const { return mFlags&MWBase::SoundManager::Play_RemoveAtDistance; } bool getIs3D() const { return mFlags&Play_3D; } diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index fcb992f58..9cc02160b 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -37,6 +37,7 @@ namespace MWSound float vol, float basevol, float pitch, float min, float max, int flags, float offset) = 0; virtual void stopSound(MWBase::SoundPtr sound) = 0; virtual bool isSoundPlaying(MWBase::SoundPtr sound) = 0; + virtual void updateSound(MWBase::SoundPtr sound) = 0; virtual MWBase::SoundStreamPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) = 0; virtual MWBase::SoundStreamPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, @@ -45,6 +46,7 @@ namespace MWSound virtual double getStreamDelay(MWBase::SoundStreamPtr sound) = 0; virtual double getStreamOffset(MWBase::SoundStreamPtr sound) = 0; virtual bool isStreamPlaying(MWBase::SoundStreamPtr sound) = 0; + virtual void updateStream(MWBase::SoundStreamPtr sound) = 0; virtual void startUpdate() = 0; virtual void finishUpdate() = 0; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index c40d2cd3e..0263c5751 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -853,6 +853,7 @@ namespace MWSound { sound->updateFade(duration); + mOutput->updateSound(sound); ++sndidx; } } @@ -918,6 +919,7 @@ namespace MWSound { sound->updateFade(duration); + mOutput->updateStream(sound); ++sayiter; } } @@ -958,6 +960,7 @@ namespace MWSound { MWBase::SoundPtr sound = sndidx->first; sound->setBaseVolume(volumeFromType(sound->getPlayType())); + mOutput->updateSound(sound); } } SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); @@ -965,10 +968,12 @@ namespace MWSound { MWBase::SoundStreamPtr sound = sayiter->second.first; sound->setBaseVolume(volumeFromType(sound->getPlayType())); + mOutput->updateStream(sound); } if(mMusic) { mMusic->setBaseVolume(volumeFromType(mMusic->getPlayType())); + mOutput->updateStream(mMusic); } mOutput->finishUpdate(); } From 2883cdba5c6b3b55e35ec0b127ce5098108ce591 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 30 Nov 2015 14:51:41 -0800 Subject: [PATCH 05/11] Initialize the Sound object before modifying the pitch variable --- apps/openmw/mwsound/openal_output.cpp | 12 ++++++++---- apps/openmw/mwsound/sound.hpp | 8 ++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index f93829ae5..552e5bc28 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -659,6 +659,8 @@ MWBase::SoundPtr OpenAL_Output::playSound(Sound_Handle data, float vol, float ba mFreeSources.pop_front(); try { + sound.reset(new Sound(vol, basevol, pitch, flags)); + alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); alSourcef(source, AL_MAX_DISTANCE, 1000.0f); alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f); @@ -684,7 +686,6 @@ MWBase::SoundPtr OpenAL_Output::playSound(Sound_Handle data, float vol, float ba alSourcePlay(source); throwALerror(); - sound.reset(new Sound(osg::Vec3f(0.f, 0.f, 0.f), vol, basevol, pitch, 1.0f, 1000.0f, flags)); sound->mHandle = MAKE_PTRID(source); mActiveSounds.push_back(sound); } @@ -708,6 +709,8 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(Sound_Handle data, const osg::Vec3f mFreeSources.pop_front(); try { + sound.reset(new Sound(pos, vol, basevol, pitch, mindist, maxdist, flags)); + alSourcef(source, AL_REFERENCE_DISTANCE, mindist); alSourcef(source, AL_MAX_DISTANCE, maxdist); alSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); @@ -735,7 +738,6 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(Sound_Handle data, const osg::Vec3f alSourcePlay(source); throwALerror(); - sound.reset(new Sound(pos, vol, basevol, pitch, mindist, maxdist, flags)); sound->mHandle = MAKE_PTRID(source); mActiveSounds.push_back(sound); } @@ -817,6 +819,8 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound(DecoderPtr decoder, float base if((flags&MWBase::SoundManager::Play_Loop)) std::cout <<"Warning: cannot loop stream \""<getName()<<"\""<< std::endl; try { + sound.reset(new Stream(1.0f, basevol, pitch, flags)); + alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); alSourcef(source, AL_MAX_DISTANCE, 1000.0f); alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f); @@ -837,7 +841,6 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound(DecoderPtr decoder, float base alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); throwALerror(); - sound.reset(new Stream(osg::Vec3f(0.0f, 0.0f, 0.0f), 1.0f, basevol, pitch, 1.0f, 1000.0f, flags)); stream = new OpenAL_SoundStream(source, decoder); mStreamThread->add(stream); sound->mHandle = stream; @@ -867,6 +870,8 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const os if((flags&MWBase::SoundManager::Play_Loop)) std::cout <<"Warning: cannot loop stream \""<getName()<<"\""<< std::endl; try { + sound.reset(new Stream(pos, volume, basevol, pitch, mindist, maxdist, flags)); + alSourcef(source, AL_REFERENCE_DISTANCE, mindist); alSourcef(source, AL_MAX_DISTANCE, maxdist); alSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); @@ -889,7 +894,6 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const os alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); throwALerror(); - sound.reset(new Stream(pos, volume, basevol, pitch, mindist, maxdist, flags)); stream = new OpenAL_SoundStream(source, decoder); mStreamThread->add(stream); sound->mHandle = stream; diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index ec55db580..0ae465cfb 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -56,6 +56,11 @@ namespace MWSound , mMinDistance(mindist), mMaxDistance(maxdist), mFlags(flags) , mFadeOutTime(0.0f), mHandle(0) { } + Sound(float vol, float basevol, float pitch, int flags) + : mPos(0.0f, 0.0f, 0.0f), mVolume(vol), mBaseVolume(basevol), mPitch(pitch) + , mMinDistance(1.0f), mMaxDistance(1000.0f), mFlags(flags) + , mFadeOutTime(0.0f), mHandle(0) + { } }; // Same as above, but it's a different type since the output handles them differently @@ -67,6 +72,9 @@ namespace MWSound Stream(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) : Sound(pos, vol, basevol, pitch, mindist, maxdist, flags) { } + Stream(float vol, float basevol, float pitch, int flags) + : Sound(vol, basevol, pitch, flags) + { } }; } From 3a39a92b93e2ab3989d6e835c581f05b5fc7c4f1 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 1 Dec 2015 11:28:37 -0800 Subject: [PATCH 06/11] Keep track of audio tracks --- apps/openmw/mwsound/soundmanagerimp.cpp | 34 +++++++++++++++++++++++++ apps/openmw/mwsound/soundmanagerimp.hpp | 11 +++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 0263c5751..157426564 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -474,6 +474,8 @@ namespace MWSound try { track = mOutput->streamSound(decoder, volumeFromType(type), 1.0f, Play_NoEnv|type); + TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), track); + mActiveTracks.insert(iter, track); } catch(std::exception &e) { @@ -485,6 +487,9 @@ namespace MWSound void SoundManager::stopTrack(MWBase::SoundStreamPtr stream) { mOutput->stopStream(stream); + TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), stream); + if(iter != mActiveTracks.end() && *iter == stream) + mActiveTracks.erase(iter); } double SoundManager::getTrackTimeDelay(MWBase::SoundStreamPtr stream) @@ -923,6 +928,24 @@ namespace MWSound ++sayiter; } } + + TrackList::iterator trkiter = mActiveTracks.begin(); + for(;trkiter != mActiveTracks.end();++trkiter) + { + MWBase::SoundStreamPtr sound = *trkiter; + if(!mOutput->isStreamPlaying(sound)) + { + mOutput->stopStream(sound); + trkiter = mActiveTracks.erase(trkiter); + } + else + { + sound->updateFade(duration); + + mOutput->updateStream(sound); + ++trkiter; + } + } mOutput->finishUpdate(); } @@ -970,6 +993,13 @@ namespace MWSound sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateStream(sound); } + TrackList::iterator trkiter = mActiveTracks.begin(); + for(;trkiter != mActiveTracks.end();++trkiter) + { + MWBase::SoundStreamPtr sound = *trkiter; + sound->setBaseVolume(volumeFromType(sound->getPlayType())); + mOutput->updateStream(sound); + } if(mMusic) { mMusic->setBaseVolume(volumeFromType(mMusic->getPlayType())); @@ -1099,6 +1129,10 @@ namespace MWSound for(;sayiter != mActiveSaySounds.end();++sayiter) mOutput->stopStream(sayiter->second.first); mActiveSaySounds.clear(); + TrackList::iterator trkiter = mActiveTracks.begin(); + for(;trkiter != mActiveTracks.end();++trkiter) + mOutput->stopStream(*trkiter); + mActiveTracks.clear(); mPendingSaySounds.clear(); mUnderwaterSound.reset(); stopMusic(); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index e0214e091..8ec46bd73 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -79,9 +79,6 @@ namespace MWSound typedef std::deque SoundList; SoundList mUnusedBuffers; - MWBase::SoundStreamPtr mMusic; - std::string mCurrentPlaylist; - typedef std::pair SoundBufferRefPair; typedef std::vector SoundBufferRefPairList; typedef std::map SoundMap; @@ -95,7 +92,11 @@ namespace MWSound typedef std::map SayDecoderMap; SayDecoderMap mPendingSaySounds; - MWBase::SoundPtr mUnderwaterSound; + typedef std::vector TrackList; + TrackList mActiveTracks; + + MWBase::SoundStreamPtr mMusic; + std::string mCurrentPlaylist; bool mListenerUnderwater; osg::Vec3f mListenerPos; @@ -104,6 +105,8 @@ namespace MWSound int mPausedSoundTypes; + MWBase::SoundPtr mUnderwaterSound; + Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound); Sound_Buffer *lookupSound(const std::string &soundId) const; From 53718a5ca00f95150f1c0700efa949d19d83410a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 2 Dec 2015 05:18:43 -0800 Subject: [PATCH 07/11] Use a typedef for the sound instance handle --- apps/openmw/mwsound/sound.hpp | 4 ++-- apps/openmw/mwsound/sound_output.hpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index 0ae465cfb..878384b43 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -1,7 +1,7 @@ #ifndef GAME_SOUND_SOUND_H #define GAME_SOUND_SOUND_H -#include "soundmanagerimp.hpp" +#include "sound_output.hpp" namespace MWSound { @@ -20,7 +20,7 @@ namespace MWSound float mFadeOutTime; protected: - void *mHandle; + Sound_Instance mHandle; friend class Sound_Output; friend class OpenAL_Output; diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index 9cc02160b..d879dbf44 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -3,11 +3,10 @@ #include #include +#include #include "soundmanagerimp.hpp" -#include "../mwworld/ptr.hpp" - namespace MWSound { class SoundManager; @@ -17,6 +16,8 @@ namespace MWSound // An opaque handle for the implementation's sound buffers. typedef void *Sound_Handle; + // An opaque handle for the implementation's sound instances. + typedef void *Sound_Instance; class Sound_Output { From 2ee3265b66466786d81d6c7c124dc1cc2421d359 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 2 Dec 2015 06:35:35 -0800 Subject: [PATCH 08/11] Use a premade Sound object for the output's playSound functions --- apps/openmw/mwsound/openal_output.cpp | 62 +++++++++++-------------- apps/openmw/mwsound/openal_output.hpp | 5 +- apps/openmw/mwsound/sound.hpp | 3 +- apps/openmw/mwsound/sound_output.hpp | 7 +-- apps/openmw/mwsound/soundmanagerimp.cpp | 31 +++++++------ 5 files changed, 49 insertions(+), 59 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 552e5bc28..8932c1b55 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -648,9 +648,8 @@ size_t OpenAL_Output::getSoundDataSize(Sound_Handle data) const } -MWBase::SoundPtr OpenAL_Output::playSound(Sound_Handle data, float vol, float basevol, float pitch, int flags, float offset) +void OpenAL_Output::playSound(MWBase::SoundPtr sound, Sound_Handle data, float offset) { - boost::shared_ptr sound; ALuint source; if(mFreeSources.empty()) @@ -659,16 +658,15 @@ MWBase::SoundPtr OpenAL_Output::playSound(Sound_Handle data, float vol, float ba mFreeSources.pop_front(); try { - sound.reset(new Sound(vol, basevol, pitch, flags)); - alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); alSourcef(source, AL_MAX_DISTANCE, 1000.0f); alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f); alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); - alSourcei(source, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE); + alSourcei(source, AL_LOOPING, sound->getIsLooping() ? AL_TRUE : AL_FALSE); - ALfloat gain = vol*basevol; - if(!(flags&MWBase::SoundManager::Play_NoEnv) && mListenerEnv == Env_Underwater) + ALfloat gain = sound->getRealVolume(); + ALfloat pitch = sound->getPitch(); + if(sound->getUseEnv() && mListenerEnv == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -681,12 +679,12 @@ MWBase::SoundPtr OpenAL_Output::playSound(Sound_Handle data, float vol, float ba alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); alSourcef(source, AL_SEC_OFFSET, offset/pitch); - alSourcei(source, AL_BUFFER, GET_PTRID(data)); + throwALerror(); + alSourcei(source, AL_BUFFER, GET_PTRID(data)); alSourcePlay(source); throwALerror(); - sound->mHandle = MAKE_PTRID(source); mActiveSounds.push_back(sound); } catch(std::exception&) { @@ -694,13 +692,11 @@ MWBase::SoundPtr OpenAL_Output::playSound(Sound_Handle data, float vol, float ba throw; } - return sound; + sound->mHandle = MAKE_PTRID(source); } -MWBase::SoundPtr OpenAL_Output::playSound3D(Sound_Handle data, const osg::Vec3f &pos, float vol, float basevol, float pitch, - float mindist, float maxdist, int flags, float offset) +void OpenAL_Output::playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset) { - boost::shared_ptr sound; ALuint source; if(mFreeSources.empty()) @@ -709,18 +705,19 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(Sound_Handle data, const osg::Vec3f mFreeSources.pop_front(); try { - sound.reset(new Sound(pos, vol, basevol, pitch, mindist, maxdist, flags)); - - alSourcef(source, AL_REFERENCE_DISTANCE, mindist); - alSourcef(source, AL_MAX_DISTANCE, maxdist); + alSourcef(source, AL_REFERENCE_DISTANCE, sound->getMinDistance()); + alSourcef(source, AL_MAX_DISTANCE, sound->getMaxDistance()); alSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSourcei(source, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE); + alSourcei(source, AL_LOOPING, sound->getIsLooping() ? AL_TRUE : AL_FALSE); - ALfloat gain = vol*basevol; + const osg::Vec3f &pos = sound->getPosition(); + ALfloat maxdist = sound->getMaxDistance(); + ALfloat gain = sound->getRealVolume(); + ALfloat pitch = sound->getPitch(); if((pos - mListenerPos).length2() > maxdist*maxdist) gain = 0.0f; - if(!(flags&MWBase::SoundManager::Play_NoEnv) && mListenerEnv == Env_Underwater) + if(sound->getUseEnv() && mListenerEnv == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -733,12 +730,12 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(Sound_Handle data, const osg::Vec3f alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); alSourcef(source, AL_SEC_OFFSET, offset/pitch); - alSourcei(source, AL_BUFFER, GET_PTRID(data)); + throwALerror(); + alSourcei(source, AL_BUFFER, GET_PTRID(data)); alSourcePlay(source); throwALerror(); - sound->mHandle = MAKE_PTRID(source); mActiveSounds.push_back(sound); } catch(std::exception&) { @@ -746,14 +743,12 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(Sound_Handle data, const osg::Vec3f throw; } - return sound; + sound->mHandle = MAKE_PTRID(source); } void OpenAL_Output::stopSound(MWBase::SoundPtr sound) { - if(!sound->mHandle) - return; - + if(!sound->mHandle) return; ALuint source = GET_PTRID(sound->mHandle); sound->mHandle = 0; @@ -766,8 +761,7 @@ void OpenAL_Output::stopSound(MWBase::SoundPtr sound) bool OpenAL_Output::isSoundPlaying(MWBase::SoundPtr sound) { - if(!sound->mHandle) - return false; + if(!sound->mHandle) return false; ALuint source = GET_PTRID(sound->mHandle); ALint state; @@ -911,8 +905,7 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const os void OpenAL_Output::stopStream(MWBase::SoundStreamPtr sound) { - if(!sound->mHandle) - return; + if(!sound->mHandle) return; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); ALuint source = stream->mSource; @@ -930,16 +923,14 @@ void OpenAL_Output::stopStream(MWBase::SoundStreamPtr sound) double OpenAL_Output::getStreamDelay(MWBase::SoundStreamPtr sound) { - if(!sound->mHandle) - return 0.0; + if(!sound->mHandle) return 0.0; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); return stream->getStreamDelay(); } double OpenAL_Output::getStreamOffset(MWBase::SoundStreamPtr sound) { - if(!sound->mHandle) - return 0.0; + if(!sound->mHandle) return 0.0; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); boost::lock_guard lock(mStreamThread->mMutex); return stream->getStreamOffset(); @@ -947,8 +938,7 @@ double OpenAL_Output::getStreamOffset(MWBase::SoundStreamPtr sound) bool OpenAL_Output::isStreamPlaying(MWBase::SoundStreamPtr sound) { - if(!sound->mHandle) - return false; + if(!sound->mHandle) return false; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); boost::lock_guard lock(mStreamThread->mMutex); return stream->isPlaying(); diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index 24b9c855f..934cb2d9d 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -47,9 +47,8 @@ namespace MWSound virtual void unloadSound(Sound_Handle data); virtual size_t getSoundDataSize(Sound_Handle data) const; - virtual MWBase::SoundPtr playSound(Sound_Handle data, float vol, float basevol, float pitch, int flags, float offset); - virtual MWBase::SoundPtr playSound3D(Sound_Handle data, const osg::Vec3f &pos, - float vol, float basevol, float pitch, float min, float max, int flags, float offset); + virtual void playSound(MWBase::SoundPtr sound, Sound_Handle data, float offset); + virtual void playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset); virtual void stopSound(MWBase::SoundPtr sound); virtual bool isSoundPlaying(MWBase::SoundPtr sound); virtual void updateSound(MWBase::SoundPtr sound); diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index 878384b43..a59027fc1 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -22,7 +22,6 @@ namespace MWSound protected: Sound_Instance mHandle; - friend class Sound_Output; friend class OpenAL_Output; public: @@ -43,11 +42,13 @@ namespace MWSound const osg::Vec3f &getPosition() const { return mPos; } float getRealVolume() const { return mVolume * mBaseVolume; } float getPitch() const { return mPitch; } + float getMinDistance() const { return mMinDistance; } float getMaxDistance() const { return mMaxDistance; } MWBase::SoundManager::PlayType getPlayType() const { return (MWBase::SoundManager::PlayType)(mFlags&MWBase::SoundManager::Play_TypeMask); } bool getUseEnv() const { return !(mFlags&MWBase::SoundManager::Play_NoEnv); } + bool getIsLooping() const { return mFlags&MWBase::SoundManager::Play_Loop; } bool getDistanceCull() const { return mFlags&MWBase::SoundManager::Play_RemoveAtDistance; } bool getIs3D() const { return mFlags&Play_3D; } diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index d879dbf44..01009c5a3 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -31,11 +31,8 @@ namespace MWSound virtual void unloadSound(Sound_Handle data) = 0; virtual size_t getSoundDataSize(Sound_Handle data) const = 0; - /// @param offset Number of seconds into the sound to start playback. - virtual MWBase::SoundPtr playSound(Sound_Handle data, float vol, float basevol, float pitch, int flags, float offset) = 0; - /// @param offset Number of seconds into the sound to start playback. - virtual MWBase::SoundPtr playSound3D(Sound_Handle data, const osg::Vec3f &pos, - float vol, float basevol, float pitch, float min, float max, int flags, float offset) = 0; + virtual void playSound(MWBase::SoundPtr sound, Sound_Handle data, float offset) = 0; + virtual void playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset) = 0; virtual void stopSound(MWBase::SoundPtr sound) = 0; virtual bool isSoundPlaying(MWBase::SoundPtr sound) = 0; virtual void updateSound(MWBase::SoundPtr sound) = 0; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 157426564..9ab86ef57 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -508,9 +508,8 @@ namespace MWSound Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); float basevol = volumeFromType(type); - sound = mOutput->playSound(sfx->mHandle, - volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D, offset - ); + sound.reset(new Sound(volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D)); + mOutput->playSound(sound, sfx->mHandle, offset); if(sfx->mUses++ == 0) { SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx); @@ -522,6 +521,7 @@ namespace MWSound catch(std::exception&) { //std::cout <<"Sound Error: "<playSound(sfx->mHandle, - volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D, offset - ); + { + sound.reset(new Sound(volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D)); + mOutput->playSound(sound, sfx->mHandle, offset); + } else - sound = mOutput->playSound3D(sfx->mHandle, - objpos, volume * sfx->mVolume, basevol, pitch, sfx->mMinDist, sfx->mMaxDist, - mode|type|Play_3D, offset - ); + { + sound.reset(new Sound(objpos, volume * sfx->mVolume, basevol, pitch, + sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D)); + mOutput->playSound3D(sound, sfx->mHandle, offset); + } if(sfx->mUses++ == 0) { SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx); @@ -563,6 +565,7 @@ namespace MWSound catch(std::exception&) { //std::cout <<"Sound Error: "<playSound3D(sfx->mHandle, - initialPos, volume * sfx->mVolume, basevol, pitch, sfx->mMinDist, sfx->mMaxDist, - mode|type|Play_3D, offset - ); + sound.reset(new Sound(initialPos, volume * sfx->mVolume, basevol, pitch, + sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D)); + mOutput->playSound3D(sound, sfx->mHandle, offset); if(sfx->mUses++ == 0) { SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx); @@ -594,6 +596,7 @@ namespace MWSound catch(std::exception &) { //std::cout <<"Sound Error: "< Date: Wed, 2 Dec 2015 08:04:30 -0800 Subject: [PATCH 09/11] Use a premade SoundStream object for the output's streamSound functions --- apps/openmw/mwsound/openal_output.cpp | 36 +++++++++++-------------- apps/openmw/mwsound/openal_output.hpp | 5 ++-- apps/openmw/mwsound/sound_output.hpp | 5 ++-- apps/openmw/mwsound/soundmanagerimp.cpp | 29 +++++++++++++------- 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 8932c1b55..839ae45ad 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -799,9 +799,8 @@ void OpenAL_Output::updateSound(MWBase::SoundPtr sound) } -MWBase::SoundStreamPtr OpenAL_Output::streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) +void OpenAL_Output::streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound) { - MWBase::SoundStreamPtr sound; OpenAL_SoundStream *stream = 0; ALuint source; @@ -810,19 +809,18 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound(DecoderPtr decoder, float base source = mFreeSources.front(); mFreeSources.pop_front(); - if((flags&MWBase::SoundManager::Play_Loop)) + if(sound->getIsLooping()) std::cout <<"Warning: cannot loop stream \""<getName()<<"\""<< std::endl; try { - sound.reset(new Stream(1.0f, basevol, pitch, flags)); - alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); alSourcef(source, AL_MAX_DISTANCE, 1000.0f); alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f); alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(source, AL_LOOPING, AL_FALSE); - ALfloat gain = basevol; - if(!(flags&MWBase::SoundManager::Play_NoEnv) && mListenerEnv == Env_Underwater) + ALfloat gain = sound->getRealVolume(); + ALfloat pitch = sound->getPitch(); + if(sound->getUseEnv() && mListenerEnv == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -837,7 +835,6 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound(DecoderPtr decoder, float base stream = new OpenAL_SoundStream(source, decoder); mStreamThread->add(stream); - sound->mHandle = stream; mActiveStreams.push_back(sound); } catch(std::exception&) { @@ -847,12 +844,11 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound(DecoderPtr decoder, float base throw; } - return sound; + sound->mHandle = stream; } -MWBase::SoundStreamPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, float volume, float basevol, float pitch, float mindist, float maxdist, int flags) +void OpenAL_Output::streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sound) { - MWBase::SoundStreamPtr sound; OpenAL_SoundStream *stream = 0; ALuint source; @@ -861,21 +857,22 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const os source = mFreeSources.front(); mFreeSources.pop_front(); - if((flags&MWBase::SoundManager::Play_Loop)) + if(sound->getIsLooping()) std::cout <<"Warning: cannot loop stream \""<getName()<<"\""<< std::endl; try { - sound.reset(new Stream(pos, volume, basevol, pitch, mindist, maxdist, flags)); - - alSourcef(source, AL_REFERENCE_DISTANCE, mindist); - alSourcef(source, AL_MAX_DISTANCE, maxdist); + alSourcef(source, AL_REFERENCE_DISTANCE, sound->getMinDistance()); + alSourcef(source, AL_MAX_DISTANCE, sound->getMaxDistance()); alSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); alSourcei(source, AL_LOOPING, AL_FALSE); - ALfloat gain = volume*basevol; + const osg::Vec3f &pos = sound->getPosition(); + ALfloat maxdist = sound->getMaxDistance(); + ALfloat gain = sound->getRealVolume(); + ALfloat pitch = sound->getPitch(); if((pos - mListenerPos).length2() > maxdist*maxdist) gain = 0.0f; - if(!(flags&MWBase::SoundManager::Play_NoEnv) && mListenerEnv == Env_Underwater) + if(sound->getUseEnv() && mListenerEnv == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -890,7 +887,6 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const os stream = new OpenAL_SoundStream(source, decoder); mStreamThread->add(stream); - sound->mHandle = stream; mActiveStreams.push_back(sound); } catch(std::exception&) { @@ -900,7 +896,7 @@ MWBase::SoundStreamPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const os throw; } - return sound; + sound->mHandle = stream; } void OpenAL_Output::stopStream(MWBase::SoundStreamPtr sound) diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index 934cb2d9d..1c2a991cf 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -53,9 +53,8 @@ namespace MWSound virtual bool isSoundPlaying(MWBase::SoundPtr sound); virtual void updateSound(MWBase::SoundPtr sound); - virtual MWBase::SoundStreamPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags); - virtual MWBase::SoundStreamPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, - float vol, float basevol, float pitch, float min, float max, int flags); + virtual void streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound); + virtual void streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sound); virtual void stopStream(MWBase::SoundStreamPtr sound); virtual double getStreamDelay(MWBase::SoundStreamPtr sound); virtual double getStreamOffset(MWBase::SoundStreamPtr sound); diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index 01009c5a3..2f459d09b 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -37,9 +37,8 @@ namespace MWSound virtual bool isSoundPlaying(MWBase::SoundPtr sound) = 0; virtual void updateSound(MWBase::SoundPtr sound) = 0; - virtual MWBase::SoundStreamPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) = 0; - virtual MWBase::SoundStreamPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, - float vol, float basevol, float pitch, float min, float max, int flags) = 0; + virtual void streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound) = 0; + virtual void streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sound) = 0; virtual void stopStream(MWBase::SoundStreamPtr sound) = 0; virtual double getStreamDelay(MWBase::SoundStreamPtr sound) = 0; virtual double getStreamOffset(MWBase::SoundStreamPtr sound) = 0; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 9ab86ef57..f814e4d19 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -251,15 +251,20 @@ namespace MWSound static float minDistance = std::max(fAudioVoiceDefaultMinDistance * fAudioMinDistanceMult, 1.0f); static float maxDistance = std::max(fAudioVoiceDefaultMaxDistance * fAudioMaxDistanceMult, minDistance); + MWBase::SoundStreamPtr sound; float basevol = volumeFromType(Play_TypeVoice); if(playlocal) - return mOutput->streamSound(decoder, - basevol, 1.0f, Play_Normal|Play_TypeVoice|Play_2D - ); - return mOutput->streamSound3D(decoder, - pos, 1.0f, basevol, 1.0f, minDistance, maxDistance, - Play_Normal|Play_TypeVoice|Play_3D - ); + { + sound.reset(new Stream(1.0f, basevol, 1.0f, Play_Normal|Play_TypeVoice|Play_2D)); + mOutput->streamSound(decoder, sound); + } + else + { + sound.reset(new Stream(pos, 1.0f, basevol, 1.0f, minDistance, maxDistance, + Play_Normal|Play_TypeVoice|Play_3D)); + mOutput->streamSound3D(decoder, sound); + } + return sound; } @@ -309,11 +314,13 @@ namespace MWSound DecoderPtr decoder = getDecoder(); decoder->open(filename); - mMusic = mOutput->streamSound(decoder, volumeFromType(Play_TypeMusic), - 1.0f, Play_NoEnv|Play_TypeMusic|Play_2D); + mMusic.reset(new Stream(1.0f, volumeFromType(Play_TypeMusic), 1.0f, + Play_NoEnv|Play_TypeMusic|Play_2D)); + mOutput->streamSound(decoder, mMusic); } catch(std::exception &e) { std::cout << "Music Error: " << e.what() << "\n"; + mMusic.reset(); } } @@ -473,7 +480,9 @@ namespace MWSound return track; try { - track = mOutput->streamSound(decoder, volumeFromType(type), 1.0f, Play_NoEnv|type); + track.reset(new Stream(1.0f, volumeFromType(type), 1.0f, Play_NoEnv|type|Play_2D)); + mOutput->streamSound(decoder, track); + TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), track); mActiveTracks.insert(iter, track); } From 2face3d0a9ca6d9a81ec62936820aff6a5bc2408 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 2 Dec 2015 09:55:51 -0800 Subject: [PATCH 10/11] Combine duplicate code --- apps/openmw/mwsound/openal_output.cpp | 206 ++++++++++---------------- apps/openmw/mwsound/openal_output.hpp | 5 + 2 files changed, 85 insertions(+), 126 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 839ae45ad..54a5efb68 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -648,6 +648,71 @@ size_t OpenAL_Output::getSoundDataSize(Sound_Handle data) const } +void OpenAL_Output::initCommon2D(ALuint source, const osg::Vec3f &pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv) +{ + alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); + alSourcef(source, AL_MAX_DISTANCE, 1000.0f); + alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f); + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + alSourcei(source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); + + if(useenv && mListenerEnv == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSourcefv(source, AL_POSITION, pos.ptr()); + alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); +} + +void OpenAL_Output::initCommon3D(ALuint source, const osg::Vec3f &pos, ALfloat mindist, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool loop, bool useenv) +{ + alSourcef(source, AL_REFERENCE_DISTANCE, mindist); + alSourcef(source, AL_MAX_DISTANCE, maxdist); + alSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); + alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); + alSourcei(source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); + + if((pos - mListenerPos).length2() > maxdist*maxdist) + gain = 0.0f; + if(useenv && mListenerEnv == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSourcefv(source, AL_POSITION, pos.ptr()); + alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); +} + +void OpenAL_Output::updateCommon(ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv, bool is3d) +{ + if(is3d) + { + if((pos - mListenerPos).length2() > maxdist*maxdist) + gain = 0.0f; + } + if(useenv && mListenerEnv == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSourcefv(source, AL_POSITION, pos.ptr()); + alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); +} + + void OpenAL_Output::playSound(MWBase::SoundPtr sound, Sound_Handle data, float offset) { ALuint source; @@ -658,27 +723,10 @@ void OpenAL_Output::playSound(MWBase::SoundPtr sound, Sound_Handle data, float o mFreeSources.pop_front(); try { - alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); - alSourcef(source, AL_MAX_DISTANCE, 1000.0f); - alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); - alSourcei(source, AL_LOOPING, sound->getIsLooping() ? AL_TRUE : AL_FALSE); - - ALfloat gain = sound->getRealVolume(); - ALfloat pitch = sound->getPitch(); - if(sound->getUseEnv() && mListenerEnv == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; - } - - alSourcef(source, AL_GAIN, gain); - alSourcef(source, AL_PITCH, pitch); - alSource3f(source, AL_POSITION, 0.0f, 0.0f, 0.0f); - alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + initCommon2D(source, sound->getPosition(), sound->getRealVolume(), sound->getPitch(), + sound->getIsLooping(), sound->getUseEnv()); - alSourcef(source, AL_SEC_OFFSET, offset/pitch); + alSourcef(source, AL_SEC_OFFSET, offset); throwALerror(); alSourcei(source, AL_BUFFER, GET_PTRID(data)); @@ -705,31 +753,11 @@ void OpenAL_Output::playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float mFreeSources.pop_front(); try { - alSourcef(source, AL_REFERENCE_DISTANCE, sound->getMinDistance()); - alSourcef(source, AL_MAX_DISTANCE, sound->getMaxDistance()); - alSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); - alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSourcei(source, AL_LOOPING, sound->getIsLooping() ? AL_TRUE : AL_FALSE); - - const osg::Vec3f &pos = sound->getPosition(); - ALfloat maxdist = sound->getMaxDistance(); - ALfloat gain = sound->getRealVolume(); - ALfloat pitch = sound->getPitch(); - if((pos - mListenerPos).length2() > maxdist*maxdist) - gain = 0.0f; - if(sound->getUseEnv() && mListenerEnv == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; - } - - alSourcef(source, AL_GAIN, gain); - alSourcef(source, AL_PITCH, pitch); - alSourcefv(source, AL_POSITION, pos.ptr()); - alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(), + sound->getRealVolume(), sound->getPitch(), sound->getIsLooping(), + sound->getUseEnv()); - alSourcef(source, AL_SEC_OFFSET, offset/pitch); + alSourcef(source, AL_SEC_OFFSET, offset); throwALerror(); alSourcei(source, AL_BUFFER, GET_PTRID(data)); @@ -776,26 +804,8 @@ void OpenAL_Output::updateSound(MWBase::SoundPtr sound) if(!sound->mHandle) return; ALuint source = GET_PTRID(sound->mHandle); - const osg::Vec3f &pos = sound->getPosition(); - ALfloat gain = sound->getRealVolume(); - ALfloat pitch = sound->getPitch(); - if(sound->getIs3D()) - { - ALfloat maxdist = sound->getMaxDistance(); - if((pos - mListenerPos).length2() > maxdist*maxdist) - gain = 0.0f; - } - if(sound->getUseEnv() && mListenerEnv == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; - } - - alSourcef(source, AL_GAIN, gain); - alSourcef(source, AL_PITCH, pitch); - alSourcefv(source, AL_POSITION, pos.ptr()); - alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(), + sound->getPitch(), sound->getUseEnv(), sound->getIs3D()); } @@ -812,25 +822,8 @@ void OpenAL_Output::streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound if(sound->getIsLooping()) std::cout <<"Warning: cannot loop stream \""<getName()<<"\""<< std::endl; try { - alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); - alSourcef(source, AL_MAX_DISTANCE, 1000.0f); - alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); - alSourcei(source, AL_LOOPING, AL_FALSE); - - ALfloat gain = sound->getRealVolume(); - ALfloat pitch = sound->getPitch(); - if(sound->getUseEnv() && mListenerEnv == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; - } - - alSourcef(source, AL_GAIN, gain); - alSourcef(source, AL_PITCH, pitch); - alSource3f(source, AL_POSITION, 0.0f, 0.0f, 0.0f); - alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + initCommon2D(source, sound->getPosition(), sound->getRealVolume(), sound->getPitch(), + false, sound->getUseEnv()); throwALerror(); stream = new OpenAL_SoundStream(source, decoder); @@ -860,29 +853,8 @@ void OpenAL_Output::streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sou if(sound->getIsLooping()) std::cout <<"Warning: cannot loop stream \""<getName()<<"\""<< std::endl; try { - alSourcef(source, AL_REFERENCE_DISTANCE, sound->getMinDistance()); - alSourcef(source, AL_MAX_DISTANCE, sound->getMaxDistance()); - alSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); - alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSourcei(source, AL_LOOPING, AL_FALSE); - - const osg::Vec3f &pos = sound->getPosition(); - ALfloat maxdist = sound->getMaxDistance(); - ALfloat gain = sound->getRealVolume(); - ALfloat pitch = sound->getPitch(); - if((pos - mListenerPos).length2() > maxdist*maxdist) - gain = 0.0f; - if(sound->getUseEnv() && mListenerEnv == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; - } - - alSourcef(source, AL_GAIN, gain); - alSourcef(source, AL_PITCH, pitch); - alSourcefv(source, AL_POSITION, pos.ptr()); - alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(), + sound->getRealVolume(), sound->getPitch(), false, sound->getUseEnv()); throwALerror(); stream = new OpenAL_SoundStream(source, decoder); @@ -946,26 +918,8 @@ void OpenAL_Output::updateStream(MWBase::SoundStreamPtr sound) OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); ALuint source = stream->mSource; - const osg::Vec3f &pos = sound->getPosition(); - ALfloat gain = sound->getRealVolume(); - ALfloat pitch = sound->getPitch(); - if(sound->getIs3D()) - { - ALfloat maxdist = sound->getMaxDistance(); - if((pos - mListenerPos).length2() > maxdist*maxdist) - gain = 0.0f; - } - if(sound->getUseEnv() && mListenerEnv == Env_Underwater) - { - gain *= 0.9f; - pitch *= 0.7f; - } - - alSourcef(source, AL_GAIN, gain); - alSourcef(source, AL_PITCH, pitch); - alSourcefv(source, AL_POSITION, pos.ptr()); - alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(), + sound->getPitch(), sound->getUseEnv(), sound->getIs3D()); } diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index 1c2a991cf..d00e8cd67 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -35,6 +35,11 @@ namespace MWSound struct StreamThread; std::auto_ptr mStreamThread; + void initCommon2D(ALuint source, const osg::Vec3f &pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv); + void initCommon3D(ALuint source, const osg::Vec3f &pos, ALfloat mindist, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool loop, bool useenv); + + void updateCommon(ALuint source, const osg::Vec3f &pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv, bool is3d); + OpenAL_Output& operator=(const OpenAL_Output &rhs); OpenAL_Output(const OpenAL_Output &rhs); From f19f1c47c8f0895e6d56234fd3551cb0f3cc321d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 2 Dec 2015 16:07:19 -0800 Subject: [PATCH 11/11] Fix playing pending voices without a Ptr --- apps/openmw/mwsound/soundmanagerimp.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index f814e4d19..044a8ba48 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -890,13 +890,17 @@ namespace MWSound DecoderPtr decoder = penditer->second.first; decoder->rewind(); + MWBase::SoundStreamPtr sound; MWWorld::Ptr ptr = penditer->first; - const ESM::Position &pos = ptr.getRefData().getPosition(); - const osg::Vec3f objpos(pos.asVec3()); + if(ptr == MWWorld::Ptr()) + sound = playVoice(decoder, osg::Vec3f(), true); + else + { + const ESM::Position &pos = ptr.getRefData().getPosition(); + const osg::Vec3f objpos(pos.asVec3()); - MWBase::SoundStreamPtr sound = playVoice(decoder, - objpos, (ptr == MWMechanics::getPlayer()) - ); + sound = playVoice(decoder, objpos, (ptr == MWMechanics::getPlayer())); + } mActiveSaySounds[ptr] = std::make_pair(sound, loudness); } catch(std::exception &e) {