mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 11:26:42 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master'
This commit is contained in:
		
						commit
						e0c9265148
					
				
					 10 changed files with 565 additions and 522 deletions
				
			
		| 
						 | 
				
			
			@ -15,6 +15,7 @@ namespace MWWorld
 | 
			
		|||
namespace MWSound
 | 
			
		||||
{
 | 
			
		||||
    class Sound;
 | 
			
		||||
    class Stream;
 | 
			
		||||
    struct Sound_Decoder;
 | 
			
		||||
    typedef boost::shared_ptr<Sound_Decoder> DecoderPtr;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +23,7 @@ namespace MWSound
 | 
			
		|||
namespace MWBase
 | 
			
		||||
{
 | 
			
		||||
    typedef boost::shared_ptr<MWSound::Sound> SoundPtr;
 | 
			
		||||
    typedef boost::shared_ptr<MWSound::Stream> SoundStreamPtr;
 | 
			
		||||
 | 
			
		||||
    /// \brief Interface for sound manager (implemented in MWSound)
 | 
			
		||||
    class SoundManager
 | 
			
		||||
| 
						 | 
				
			
			@ -104,9 +106,17 @@ 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(SoundStreamPtr stream) = 0;
 | 
			
		||||
            ///< Stop the given audio track from playing
 | 
			
		||||
 | 
			
		||||
            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.
 | 
			
		||||
 | 
			
		||||
            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 +133,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,
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -155,7 +168,7 @@ namespace MWBase
 | 
			
		|||
 | 
			
		||||
            virtual void setListenerPosDir(const osg::Vec3f &pos, const osg::Vec3f &dir, const osg::Vec3f &up, bool underwater) = 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;
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,11 +86,13 @@ namespace MWSound
 | 
			
		|||
    public:
 | 
			
		||||
        ~MovieAudioDecoder()
 | 
			
		||||
        {
 | 
			
		||||
            if(mAudioTrack.get())
 | 
			
		||||
                MWBase::Environment::get().getSoundManager()->stopTrack(mAudioTrack);
 | 
			
		||||
            mAudioTrack.reset();
 | 
			
		||||
            mDecoderBridge.reset();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MWBase::SoundPtr mAudioTrack;
 | 
			
		||||
        MWBase::SoundStreamPtr mAudioTrack;
 | 
			
		||||
        boost::shared_ptr<MWSoundDecoderBridge> mDecoderBridge;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +163,8 @@ namespace MWSound
 | 
			
		|||
        boost::shared_ptr<MWSound::MovieAudioDecoder> 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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<ALuint>(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<boost::mutex> lock(mOutput.mStreamThread->mMutex);
 | 
			
		||||
    alGetSourcei(mSource, AL_SOURCE_STATE, &state);
 | 
			
		||||
    throwALerror();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -420,33 +364,6 @@ bool OpenAL_SoundStream::isPlaying()
 | 
			
		|||
    return !mIsFinished;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double OpenAL_SoundStream::getTimeOffset()
 | 
			
		||||
{
 | 
			
		||||
    ALint state = AL_STOPPED;
 | 
			
		||||
    ALint offset;
 | 
			
		||||
    double t;
 | 
			
		||||
 | 
			
		||||
    boost::lock_guard<boost::mutex> lock(mOutput.mStreamThread->mMutex);
 | 
			
		||||
    alGetSourcei(mSource, AL_SAMPLE_OFFSET, &offset);
 | 
			
		||||
    alGetSourcei(mSource, AL_SOURCE_STATE, &state);
 | 
			
		||||
    if(state == AL_PLAYING || state == AL_PAUSED)
 | 
			
		||||
    {
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    throwALerror();
 | 
			
		||||
    return t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double OpenAL_SoundStream::getStreamDelay() const
 | 
			
		||||
{
 | 
			
		||||
    ALint state = AL_STOPPED;
 | 
			
		||||
| 
						 | 
				
			
			@ -467,41 +384,30 @@ double OpenAL_SoundStream::getStreamDelay() const
 | 
			
		|||
    return d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenAL_SoundStream::updateAll(bool local)
 | 
			
		||||
double OpenAL_SoundStream::getStreamOffset() const
 | 
			
		||||
{
 | 
			
		||||
    alSourcef(mSource, AL_REFERENCE_DISTANCE, mMinDistance);
 | 
			
		||||
    alSourcef(mSource, AL_MAX_DISTANCE, mMaxDistance);
 | 
			
		||||
    if(local)
 | 
			
		||||
    ALint state = AL_STOPPED;
 | 
			
		||||
    ALint offset;
 | 
			
		||||
    double t;
 | 
			
		||||
 | 
			
		||||
    alGetSourcei(mSource, AL_SAMPLE_OFFSET, &offset);
 | 
			
		||||
    alGetSourcei(mSource, AL_SOURCE_STATE, &state);
 | 
			
		||||
    if(state == AL_PLAYING || state == AL_PAUSED)
 | 
			
		||||
    {
 | 
			
		||||
        alSourcef(mSource, AL_ROLLOFF_FACTOR, 0.0f);
 | 
			
		||||
        alSourcei(mSource, AL_SOURCE_RELATIVE, AL_TRUE);
 | 
			
		||||
        ALint queued;
 | 
			
		||||
        alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
 | 
			
		||||
        ALint inqueue = mBufferSize/mFrameSize*queued - offset;
 | 
			
		||||
        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,121 +648,278 @@ 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::initCommon2D(ALuint source, const osg::Vec3f &pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv)
 | 
			
		||||
{
 | 
			
		||||
    boost::shared_ptr<OpenAL_Sound> sound;
 | 
			
		||||
    ALuint src;
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    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));
 | 
			
		||||
        initCommon2D(source, sound->getPosition(), sound->getRealVolume(), sound->getPitch(),
 | 
			
		||||
                     sound->getIsLooping(), sound->getUseEnv());
 | 
			
		||||
 | 
			
		||||
        alSourcef(source, AL_SEC_OFFSET, offset);
 | 
			
		||||
        throwALerror();
 | 
			
		||||
 | 
			
		||||
        alSourcei(source, AL_BUFFER, GET_PTRID(data));
 | 
			
		||||
        alSourcePlay(source);
 | 
			
		||||
        throwALerror();
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    sound->mHandle = MAKE_PTRID(source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
void OpenAL_Output::playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset)
 | 
			
		||||
{
 | 
			
		||||
    boost::shared_ptr<OpenAL_Sound> sound;
 | 
			
		||||
    ALuint src;
 | 
			
		||||
    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));
 | 
			
		||||
        initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(),
 | 
			
		||||
                     sound->getRealVolume(), sound->getPitch(), sound->getIsLooping(),
 | 
			
		||||
                     sound->getUseEnv());
 | 
			
		||||
 | 
			
		||||
        alSourcef(source, AL_SEC_OFFSET, offset);
 | 
			
		||||
        throwALerror();
 | 
			
		||||
 | 
			
		||||
        alSourcei(source, AL_BUFFER, GET_PTRID(data));
 | 
			
		||||
        alSourcePlay(source);
 | 
			
		||||
        throwALerror();
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
    sound->mHandle = MAKE_PTRID(source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    alSourcePlay(src);
 | 
			
		||||
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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenAL_Output::updateSound(MWBase::SoundPtr sound)
 | 
			
		||||
{
 | 
			
		||||
    if(!sound->mHandle) return;
 | 
			
		||||
    ALuint source = GET_PTRID(sound->mHandle);
 | 
			
		||||
 | 
			
		||||
    updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
 | 
			
		||||
                 sound->getPitch(), sound->getUseEnv(), sound->getIs3D());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float basevol, float pitch, int flags)
 | 
			
		||||
void OpenAL_Output::streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound)
 | 
			
		||||
{
 | 
			
		||||
    boost::shared_ptr<OpenAL_SoundStream> sound;
 | 
			
		||||
    ALuint src;
 | 
			
		||||
    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))
 | 
			
		||||
    if(sound->getIsLooping())
 | 
			
		||||
        std::cout <<"Warning: cannot loop stream \""<<decoder->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 {
 | 
			
		||||
        initCommon2D(source, sound->getPosition(), sound->getRealVolume(), sound->getPitch(),
 | 
			
		||||
                     false, sound->getUseEnv());
 | 
			
		||||
        throwALerror();
 | 
			
		||||
 | 
			
		||||
        stream = new OpenAL_SoundStream(source, decoder);
 | 
			
		||||
        mStreamThread->add(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;
 | 
			
		||||
    sound->mHandle = stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MWBase::SoundPtr OpenAL_Output::streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, float volume, float basevol, float pitch, float min, float max, int flags)
 | 
			
		||||
void OpenAL_Output::streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sound)
 | 
			
		||||
{
 | 
			
		||||
    boost::shared_ptr<OpenAL_SoundStream> sound;
 | 
			
		||||
    ALuint src;
 | 
			
		||||
    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))
 | 
			
		||||
    if(sound->getIsLooping())
 | 
			
		||||
        std::cout <<"Warning: cannot loop stream \""<<decoder->getName()<<"\""<< std::endl;
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        sound.reset(new OpenAL_SoundStream3D(*this, src, decoder, pos, volume, basevol, pitch, min, max, flags));
 | 
			
		||||
    try {
 | 
			
		||||
        initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(),
 | 
			
		||||
                     sound->getRealVolume(), sound->getPitch(), false, sound->getUseEnv());
 | 
			
		||||
        throwALerror();
 | 
			
		||||
 | 
			
		||||
        stream = new OpenAL_SoundStream(source, decoder);
 | 
			
		||||
        mStreamThread->add(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->mHandle = stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    sound->play();
 | 
			
		||||
    return sound;
 | 
			
		||||
void OpenAL_Output::stopStream(MWBase::SoundStreamPtr sound)
 | 
			
		||||
{
 | 
			
		||||
    if(!sound->mHandle) return;
 | 
			
		||||
    OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(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::SoundStreamPtr sound)
 | 
			
		||||
{
 | 
			
		||||
    if(!sound->mHandle) return 0.0;
 | 
			
		||||
    OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
 | 
			
		||||
    return stream->getStreamDelay();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double OpenAL_Output::getStreamOffset(MWBase::SoundStreamPtr sound)
 | 
			
		||||
{
 | 
			
		||||
    if(!sound->mHandle) return 0.0;
 | 
			
		||||
    OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
 | 
			
		||||
    boost::lock_guard<boost::mutex> lock(mStreamThread->mMutex);
 | 
			
		||||
    return stream->getStreamOffset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool OpenAL_Output::isStreamPlaying(MWBase::SoundStreamPtr sound)
 | 
			
		||||
{
 | 
			
		||||
    if(!sound->mHandle) return false;
 | 
			
		||||
    OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
 | 
			
		||||
    boost::lock_guard<boost::mutex> lock(mStreamThread->mMutex);
 | 
			
		||||
    return stream->isPlaying();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenAL_Output::updateStream(MWBase::SoundStreamPtr sound)
 | 
			
		||||
{
 | 
			
		||||
    if(!sound->mHandle) return;
 | 
			
		||||
    OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
 | 
			
		||||
    ALuint source = stream->mSource;
 | 
			
		||||
 | 
			
		||||
    updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
 | 
			
		||||
                 sound->getPitch(), sound->getUseEnv(), sound->getIs3D());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1038,19 +936,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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1060,14 +958,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<OpenAL_SoundStream*>((*stream)->mHandle);
 | 
			
		||||
            sources.push_back(strm->mSource);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if(!sources.empty())
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1082,14 +983,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<OpenAL_SoundStream*>((*stream)->mHandle);
 | 
			
		||||
            sources.push_back(strm->mSource);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if(!sources.empty())
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1106,8 +1010,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)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,13 +24,26 @@ namespace MWSound
 | 
			
		|||
        typedef std::deque<ALuint> IDDq;
 | 
			
		||||
        IDDq mFreeSources;
 | 
			
		||||
 | 
			
		||||
        typedef std::vector<OpenAL_Sound*> SoundVec;
 | 
			
		||||
        typedef std::vector<MWBase::SoundPtr> SoundVec;
 | 
			
		||||
        SoundVec mActiveSounds;
 | 
			
		||||
        typedef std::vector<OpenAL_SoundStream*> StreamVec;
 | 
			
		||||
        typedef std::vector<MWBase::SoundStreamPtr> StreamVec;
 | 
			
		||||
        StreamVec mActiveStreams;
 | 
			
		||||
 | 
			
		||||
        Environment mLastEnvironment;
 | 
			
		||||
        osg::Vec3f mListenerPos;
 | 
			
		||||
        Environment mListenerEnv;
 | 
			
		||||
 | 
			
		||||
        struct StreamThread;
 | 
			
		||||
        std::auto_ptr<StreamThread> 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);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        virtual std::vector<std::string> enumerate();
 | 
			
		||||
        virtual void init(const std::string &devname="");
 | 
			
		||||
        virtual void deinit();
 | 
			
		||||
| 
						 | 
				
			
			@ -42,12 +52,19 @@ 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 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 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);
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        virtual bool isStreamPlaying(MWBase::SoundStreamPtr sound);
 | 
			
		||||
        virtual void updateStream(MWBase::SoundStreamPtr sound);
 | 
			
		||||
 | 
			
		||||
        virtual void startUpdate();
 | 
			
		||||
        virtual void finishUpdate();
 | 
			
		||||
| 
						 | 
				
			
			@ -59,20 +76,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<StreamThread> 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))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +1,14 @@
 | 
			
		|||
#ifndef GAME_SOUND_SOUND_H
 | 
			
		||||
#define GAME_SOUND_SOUND_H
 | 
			
		||||
 | 
			
		||||
#include "soundmanagerimp.hpp"
 | 
			
		||||
#include "sound_output.hpp"
 | 
			
		||||
 | 
			
		||||
namespace MWSound
 | 
			
		||||
{
 | 
			
		||||
    class Sound
 | 
			
		||||
    {
 | 
			
		||||
    class Sound {
 | 
			
		||||
        Sound& operator=(const Sound &rhs);
 | 
			
		||||
        Sound(const Sound &rhs);
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        osg::Vec3f mPos;
 | 
			
		||||
        float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */
 | 
			
		||||
        float mBaseVolume;
 | 
			
		||||
| 
						 | 
				
			
			@ -21,12 +19,12 @@ namespace MWSound
 | 
			
		|||
 | 
			
		||||
        float mFadeOutTime;
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        Sound_Instance mHandle;
 | 
			
		||||
 | 
			
		||||
        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; }
 | 
			
		||||
| 
						 | 
				
			
			@ -41,22 +39,43 @@ 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; }
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
        { }
 | 
			
		||||
        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
 | 
			
		||||
    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)
 | 
			
		||||
        { }
 | 
			
		||||
        Stream(float vol, float basevol, float pitch, int flags)
 | 
			
		||||
          : Sound(vol, basevol, pitch, flags)
 | 
			
		||||
        { }
 | 
			
		||||
        virtual ~Sound() { }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,11 +3,10 @@
 | 
			
		|||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -30,14 +31,19 @@ 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 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 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;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
        virtual bool isStreamPlaying(MWBase::SoundStreamPtr sound) = 0;
 | 
			
		||||
        virtual void updateStream(MWBase::SoundStreamPtr sound) = 0;
 | 
			
		||||
 | 
			
		||||
        virtual void startUpdate() = 0;
 | 
			
		||||
        virtual void finishUpdate() = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -57,12 +63,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() { }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<ESM::GameSetting>().find("fAudioMinDistanceMult")->getFloat();
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -293,7 +298,7 @@ namespace MWSound
 | 
			
		|||
    void SoundManager::stopMusic()
 | 
			
		||||
    {
 | 
			
		||||
        if(mMusic)
 | 
			
		||||
            mMusic->stop();
 | 
			
		||||
            mOutput->stopStream(mMusic);
 | 
			
		||||
        mMusic.reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -303,19 +308,19 @@ namespace MWSound
 | 
			
		|||
            return;
 | 
			
		||||
        std::cout <<"Playing "<<filename<< std::endl;
 | 
			
		||||
        mLastPlayedMusic = filename;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
        try {
 | 
			
		||||
            stopMusic();
 | 
			
		||||
 | 
			
		||||
            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)
 | 
			
		||||
        {
 | 
			
		||||
        catch(std::exception &e) {
 | 
			
		||||
            std::cout << "Music Error: " << e.what() << "\n";
 | 
			
		||||
            mMusic.reset();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -366,7 +371,7 @@ namespace MWSound
 | 
			
		|||
 | 
			
		||||
    bool SoundManager::isMusicPlaying()
 | 
			
		||||
    {
 | 
			
		||||
        return mMusic && mMusic->isPlaying();
 | 
			
		||||
        return mMusic && mOutput->isStreamPlaying(mMusic);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SoundManager::playPlaylist(const std::string &playlist)
 | 
			
		||||
| 
						 | 
				
			
			@ -394,7 +399,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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -409,11 +414,10 @@ 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 = sound->getTimeOffset();
 | 
			
		||||
            if(sound->isPlaying())
 | 
			
		||||
                return loudness->getLoudnessAtTime(sec);
 | 
			
		||||
            float sec = mOutput->getStreamOffset(sound);
 | 
			
		||||
            return loudness->getLoudnessAtTime(sec);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0.0f;
 | 
			
		||||
| 
						 | 
				
			
			@ -435,7 +439,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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -450,7 +454,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,21 +466,25 @@ 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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
        {
 | 
			
		||||
            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);
 | 
			
		||||
        }
 | 
			
		||||
        catch(std::exception &e)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -485,6 +493,19 @@ namespace MWSound
 | 
			
		|||
        return track;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
    {
 | 
			
		||||
        return mOutput->getStreamDelay(stream);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    MWBase::SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, PlayType type, PlayMode mode, float offset)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -496,9 +517,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -510,6 +530,7 @@ namespace MWSound
 | 
			
		|||
        catch(std::exception&)
 | 
			
		||||
        {
 | 
			
		||||
            //std::cout <<"Sound Error: "<<e.what()<< std::endl;
 | 
			
		||||
            sound.reset();
 | 
			
		||||
        }
 | 
			
		||||
        return sound;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -532,14 +553,16 @@ namespace MWSound
 | 
			
		|||
                return MWBase::SoundPtr();
 | 
			
		||||
 | 
			
		||||
            if(!(mode&Play_NoPlayerLocal) && ptr == MWMechanics::getPlayer())
 | 
			
		||||
                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);
 | 
			
		||||
            }
 | 
			
		||||
            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);
 | 
			
		||||
| 
						 | 
				
			
			@ -551,6 +574,7 @@ namespace MWSound
 | 
			
		|||
        catch(std::exception&)
 | 
			
		||||
        {
 | 
			
		||||
            //std::cout <<"Sound Error: "<<e.what()<< std::endl;
 | 
			
		||||
            sound.reset();
 | 
			
		||||
        }
 | 
			
		||||
        return sound;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -567,10 +591,9 @@ namespace MWSound
 | 
			
		|||
            Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId));
 | 
			
		||||
            float basevol = volumeFromType(type);
 | 
			
		||||
 | 
			
		||||
            sound = mOutput->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);
 | 
			
		||||
| 
						 | 
				
			
			@ -582,10 +605,16 @@ namespace MWSound
 | 
			
		|||
        catch(std::exception &)
 | 
			
		||||
        {
 | 
			
		||||
            //std::cout <<"Sound Error: "<<e.what()<< std::endl;
 | 
			
		||||
            sound.reset();
 | 
			
		||||
        }
 | 
			
		||||
        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 +625,7 @@ namespace MWSound
 | 
			
		|||
            for(;sndidx != snditer->second.end();++sndidx)
 | 
			
		||||
            {
 | 
			
		||||
                if(sndidx->second == sfx)
 | 
			
		||||
                    sndidx->first->stop();
 | 
			
		||||
                    mOutput->stopSound(sndidx->first);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -608,7 +637,7 @@ namespace MWSound
 | 
			
		|||
        {
 | 
			
		||||
            SoundBufferRefPairList::iterator sndidx = snditer->second.begin();
 | 
			
		||||
            for(;sndidx != snditer->second.end();++sndidx)
 | 
			
		||||
                sndidx->first->stop();
 | 
			
		||||
                mOutput->stopSound(sndidx->first);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -623,7 +652,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 +663,7 @@ namespace MWSound
 | 
			
		|||
               sayiter->first != MWMechanics::getPlayer() &&
 | 
			
		||||
               sayiter->first.getCell() == cell)
 | 
			
		||||
            {
 | 
			
		||||
                sayiter->second.first->stop();
 | 
			
		||||
                mOutput->stopStream(sayiter->second.first);
 | 
			
		||||
            }
 | 
			
		||||
            ++sayiter;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -650,7 +679,7 @@ namespace MWSound
 | 
			
		|||
            for(;sndidx != snditer->second.end();++sndidx)
 | 
			
		||||
            {
 | 
			
		||||
                if(sndidx->second == sfx)
 | 
			
		||||
                    sndidx->first->stop();
 | 
			
		||||
                    mOutput->stopSound(sndidx->first);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -680,7 +709,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 +817,7 @@ namespace MWSound
 | 
			
		|||
            env = Env_Underwater;
 | 
			
		||||
        else if(mUnderwaterSound)
 | 
			
		||||
        {
 | 
			
		||||
            mUnderwaterSound->stop();
 | 
			
		||||
            mOutput->stopSound(mUnderwaterSound);
 | 
			
		||||
            mUnderwaterSound.reset();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -803,7 +832,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 +843,36 @@ 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);
 | 
			
		||||
 | 
			
		||||
                    mOutput->updateSound(sound);
 | 
			
		||||
                    ++sndidx;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if(snditer->second.empty())
 | 
			
		||||
                mActiveSounds.erase(snditer++);
 | 
			
		||||
| 
						 | 
				
			
			@ -840,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::SoundPtr 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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -862,36 +916,53 @@ 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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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())
 | 
			
		||||
            MWWorld::Ptr ptr = sayiter->first;
 | 
			
		||||
            MWBase::SoundStreamPtr sound = sayiter->second.first;
 | 
			
		||||
            if(!ptr.isEmpty() && sound->getIs3D())
 | 
			
		||||
            {
 | 
			
		||||
                if((mListenerPos - objpos).length2() > 2000*2000)
 | 
			
		||||
                    sound->stop();
 | 
			
		||||
                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(!mOutput->isStreamPlaying(sound))
 | 
			
		||||
            {
 | 
			
		||||
                mOutput->stopStream(sound);
 | 
			
		||||
                mActiveSaySounds.erase(sayiter++);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                sound->updateFade(duration);
 | 
			
		||||
 | 
			
		||||
                mOutput->updateStream(sound);
 | 
			
		||||
                ++sayiter;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!sound->isPlaying())
 | 
			
		||||
            return false;
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
        sound->updateFade(duration);
 | 
			
		||||
 | 
			
		||||
        sound->applyUpdates();
 | 
			
		||||
        return true;
 | 
			
		||||
                mOutput->updateStream(sound);
 | 
			
		||||
                ++trkiter;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        mOutput->finishUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -928,20 +999,27 @@ namespace MWSound
 | 
			
		|||
            {
 | 
			
		||||
                MWBase::SoundPtr sound = sndidx->first;
 | 
			
		||||
                sound->setBaseVolume(volumeFromType(sound->getPlayType()));
 | 
			
		||||
                sound->applyUpdates();
 | 
			
		||||
                mOutput->updateSound(sound);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        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()));
 | 
			
		||||
            sound->applyUpdates();
 | 
			
		||||
            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()));
 | 
			
		||||
            mMusic->applyUpdates();
 | 
			
		||||
            mOutput->updateStream(mMusic);
 | 
			
		||||
        }
 | 
			
		||||
        mOutput->finishUpdate();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1053,7 +1131,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -1062,8 +1140,12 @@ 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();
 | 
			
		||||
        TrackList::iterator trkiter = mActiveTracks.begin();
 | 
			
		||||
        for(;trkiter != mActiveTracks.end();++trkiter)
 | 
			
		||||
            mOutput->stopStream(*trkiter);
 | 
			
		||||
        mActiveTracks.clear();
 | 
			
		||||
        mPendingSaySounds.clear();
 | 
			
		||||
        mUnderwaterSound.reset();
 | 
			
		||||
        stopMusic();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,15 +79,12 @@ namespace MWSound
 | 
			
		|||
        typedef std::deque<Sound_Buffer*> SoundList;
 | 
			
		||||
        SoundList mUnusedBuffers;
 | 
			
		||||
 | 
			
		||||
        boost::shared_ptr<Sound> mMusic;
 | 
			
		||||
        std::string mCurrentPlaylist;
 | 
			
		||||
 | 
			
		||||
        typedef std::pair<MWBase::SoundPtr,Sound_Buffer*> SoundBufferRefPair;
 | 
			
		||||
        typedef std::vector<SoundBufferRefPair> SoundBufferRefPairList;
 | 
			
		||||
        typedef std::map<MWWorld::Ptr,SoundBufferRefPairList> SoundMap;
 | 
			
		||||
        SoundMap mActiveSounds;
 | 
			
		||||
 | 
			
		||||
        typedef std::pair<MWBase::SoundPtr,Sound_Loudness*> SoundLoudnessPair;
 | 
			
		||||
        typedef std::pair<MWBase::SoundStreamPtr,Sound_Loudness*> SoundLoudnessPair;
 | 
			
		||||
        typedef std::map<MWWorld::Ptr,SoundLoudnessPair> SaySoundMap;
 | 
			
		||||
        SaySoundMap mActiveSaySounds;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +92,11 @@ namespace MWSound
 | 
			
		|||
        typedef std::map<MWWorld::Ptr,DecoderLoudnessPair> SayDecoderMap;
 | 
			
		||||
        SayDecoderMap mPendingSaySounds;
 | 
			
		||||
 | 
			
		||||
        MWBase::SoundPtr mUnderwaterSound;
 | 
			
		||||
        typedef std::vector<MWBase::SoundStreamPtr> 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;
 | 
			
		||||
| 
						 | 
				
			
			@ -113,10 +116,9 @@ 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);
 | 
			
		||||
        bool updateSound(MWBase::SoundPtr sound, const MWWorld::Ptr &ptr, float duration);
 | 
			
		||||
        void updateSounds(float duration);
 | 
			
		||||
        void updateRegionSound(float duration);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -171,9 +173,17 @@ 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::SoundStreamPtr stream);
 | 
			
		||||
        ///< Stop the given audio track from playing
 | 
			
		||||
 | 
			
		||||
        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.
 | 
			
		||||
 | 
			
		||||
        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 +199,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,
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<MagicBoltState>::iterator it = mMagicBolts.begin(); it != mMagicBolts.end(); ++it)
 | 
			
		||||
        {
 | 
			
		||||
            mParent->removeChild(it->mNode);
 | 
			
		||||
            it->mSound->stop();
 | 
			
		||||
            MWBase::Environment::get().getSoundManager()->stopSound(it->mSound);
 | 
			
		||||
        }
 | 
			
		||||
        mMagicBolts.clear();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue