mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-03 16:45:34 +00:00
Merge pull request #836 from kcat/master
More audio cleanups and crash fix
This commit is contained in:
commit
6234fba16d
10 changed files with 565 additions and 522 deletions
|
@ -15,6 +15,7 @@ namespace MWWorld
|
||||||
namespace MWSound
|
namespace MWSound
|
||||||
{
|
{
|
||||||
class Sound;
|
class Sound;
|
||||||
|
class Stream;
|
||||||
struct Sound_Decoder;
|
struct Sound_Decoder;
|
||||||
typedef boost::shared_ptr<Sound_Decoder> DecoderPtr;
|
typedef boost::shared_ptr<Sound_Decoder> DecoderPtr;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +23,7 @@ namespace MWSound
|
||||||
namespace MWBase
|
namespace MWBase
|
||||||
{
|
{
|
||||||
typedef boost::shared_ptr<MWSound::Sound> SoundPtr;
|
typedef boost::shared_ptr<MWSound::Sound> SoundPtr;
|
||||||
|
typedef boost::shared_ptr<MWSound::Stream> SoundStreamPtr;
|
||||||
|
|
||||||
/// \brief Interface for sound manager (implemented in MWSound)
|
/// \brief Interface for sound manager (implemented in MWSound)
|
||||||
class SoundManager
|
class SoundManager
|
||||||
|
@ -104,9 +106,17 @@ namespace MWBase
|
||||||
/// and get an average loudness value (scale [0,1]) at the current time position.
|
/// and get an average loudness value (scale [0,1]) at the current time position.
|
||||||
/// If the actor is not saying anything, returns 0.
|
/// 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
|
///< 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,
|
virtual SoundPtr playSound(const std::string& soundId, float volume, float pitch,
|
||||||
PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal,
|
PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal,
|
||||||
float offset=0) = 0;
|
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;
|
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.
|
///< 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;
|
virtual void stopSound3D(const MWWorld::Ptr &reference, const std::string& soundId) = 0;
|
||||||
///< Stop the given object from playing the given sound,
|
///< 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) = 0;
|
virtual void setListenerPosDir(const osg::Vec3f &pos, const osg::Vec3f &dir, const osg::Vec3f &up) = 0;
|
||||||
|
|
||||||
virtual void updatePtr (const MWWorld::Ptr& old, const MWWorld::Ptr& updated) = 0;
|
virtual void updatePtr(const MWWorld::Ptr& old, const MWWorld::Ptr& updated) = 0;
|
||||||
|
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace MWSound
|
||||||
virtual double getAudioClock()
|
virtual double getAudioClock()
|
||||||
{
|
{
|
||||||
return (double)getSampleOffset()/(double)mAVStream->codec->sample_rate -
|
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)
|
virtual void adjustAudioSettings(AVSampleFormat& sampleFormat, uint64_t& channelLayout, int& sampleRate)
|
||||||
|
@ -86,11 +86,13 @@ namespace MWSound
|
||||||
public:
|
public:
|
||||||
~MovieAudioDecoder()
|
~MovieAudioDecoder()
|
||||||
{
|
{
|
||||||
|
if(mAudioTrack.get())
|
||||||
|
MWBase::Environment::get().getSoundManager()->stopTrack(mAudioTrack);
|
||||||
mAudioTrack.reset();
|
mAudioTrack.reset();
|
||||||
mDecoderBridge.reset();
|
mDecoderBridge.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
MWBase::SoundPtr mAudioTrack;
|
MWBase::SoundStreamPtr mAudioTrack;
|
||||||
boost::shared_ptr<MWSoundDecoderBridge> mDecoderBridge;
|
boost::shared_ptr<MWSoundDecoderBridge> mDecoderBridge;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -161,7 +163,8 @@ namespace MWSound
|
||||||
boost::shared_ptr<MWSound::MovieAudioDecoder> decoder(new MWSound::MovieAudioDecoder(videoState));
|
boost::shared_ptr<MWSound::MovieAudioDecoder> decoder(new MWSound::MovieAudioDecoder(videoState));
|
||||||
decoder->setupFormat();
|
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())
|
if (!sound.get())
|
||||||
{
|
{
|
||||||
decoder.reset();
|
decoder.reset();
|
||||||
|
|
|
@ -157,17 +157,14 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type)
|
||||||
//
|
//
|
||||||
// A streaming OpenAL sound.
|
// A streaming OpenAL sound.
|
||||||
//
|
//
|
||||||
class OpenAL_SoundStream : public Sound
|
class OpenAL_SoundStream
|
||||||
{
|
{
|
||||||
static const ALuint sNumBuffers = 6;
|
static const ALuint sNumBuffers = 6;
|
||||||
static const ALfloat sBufferLength;
|
static const ALfloat sBufferLength;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
OpenAL_Output &mOutput;
|
|
||||||
|
|
||||||
ALuint mSource;
|
ALuint mSource;
|
||||||
|
|
||||||
private:
|
|
||||||
ALuint mBuffers[sNumBuffers];
|
ALuint mBuffers[sNumBuffers];
|
||||||
ALint mCurrentBufIdx;
|
ALint mCurrentBufIdx;
|
||||||
|
|
||||||
|
@ -189,34 +186,18 @@ private:
|
||||||
friend class OpenAL_Output;
|
friend class OpenAL_Output;
|
||||||
|
|
||||||
public:
|
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);
|
OpenAL_SoundStream(ALuint src, DecoderPtr decoder);
|
||||||
virtual ~OpenAL_SoundStream();
|
~OpenAL_SoundStream();
|
||||||
|
|
||||||
virtual void stop();
|
bool isPlaying();
|
||||||
virtual bool isPlaying();
|
double getStreamDelay() const;
|
||||||
virtual double getTimeOffset();
|
double getStreamOffset() const;
|
||||||
virtual double getStreamDelay() const;
|
|
||||||
virtual void applyUpdates();
|
|
||||||
|
|
||||||
void play();
|
|
||||||
bool process();
|
bool process();
|
||||||
ALint refillQueue();
|
ALint refillQueue();
|
||||||
};
|
};
|
||||||
const ALfloat OpenAL_SoundStream::sBufferLength = 0.125f;
|
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)
|
// 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)
|
OpenAL_SoundStream::OpenAL_SoundStream(ALuint src, DecoderPtr decoder)
|
||||||
: Sound(pos, vol, basevol, pitch, mindist, maxdist, flags)
|
: mSource(src), mCurrentBufIdx(0), mFrameSize(0), mSilence(0), mDecoder(decoder), mIsFinished(false)
|
||||||
, mOutput(output), mSource(src), mCurrentBufIdx(0), mFrameSize(0), mSilence(0)
|
|
||||||
, mDecoder(decoder), mIsFinished(true)
|
|
||||||
{
|
{
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
alGenBuffers(sNumBuffers, mBuffers);
|
alGenBuffers(sNumBuffers, mBuffers);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
try
|
try
|
||||||
|
@ -358,8 +335,6 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode
|
||||||
mFrameSize = framesToBytes(1, chans, type);
|
mFrameSize = framesToBytes(1, chans, type);
|
||||||
mBufferSize = static_cast<ALuint>(sBufferLength*srate);
|
mBufferSize = static_cast<ALuint>(sBufferLength*srate);
|
||||||
mBufferSize *= mFrameSize;
|
mBufferSize *= mFrameSize;
|
||||||
|
|
||||||
mOutput.mActiveStreams.push_back(this);
|
|
||||||
}
|
}
|
||||||
catch(std::exception&)
|
catch(std::exception&)
|
||||||
{
|
{
|
||||||
|
@ -367,51 +342,20 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode
|
||||||
alGetError();
|
alGetError();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
mIsFinished = false;
|
||||||
}
|
}
|
||||||
OpenAL_SoundStream::~OpenAL_SoundStream()
|
OpenAL_SoundStream::~OpenAL_SoundStream()
|
||||||
{
|
{
|
||||||
mOutput.mStreamThread->remove(this);
|
|
||||||
|
|
||||||
alSourceStop(mSource);
|
|
||||||
alSourcei(mSource, AL_BUFFER, 0);
|
|
||||||
|
|
||||||
mOutput.mFreeSources.push_back(mSource);
|
|
||||||
alDeleteBuffers(sNumBuffers, mBuffers);
|
alDeleteBuffers(sNumBuffers, mBuffers);
|
||||||
alGetError();
|
alGetError();
|
||||||
|
|
||||||
mDecoder->close();
|
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()
|
bool OpenAL_SoundStream::isPlaying()
|
||||||
{
|
{
|
||||||
ALint state;
|
ALint state;
|
||||||
|
|
||||||
boost::lock_guard<boost::mutex> lock(mOutput.mStreamThread->mMutex);
|
|
||||||
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
|
||||||
|
@ -420,33 +364,6 @@ bool OpenAL_SoundStream::isPlaying()
|
||||||
return !mIsFinished;
|
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
|
double OpenAL_SoundStream::getStreamDelay() const
|
||||||
{
|
{
|
||||||
ALint state = AL_STOPPED;
|
ALint state = AL_STOPPED;
|
||||||
|
@ -467,41 +384,30 @@ double OpenAL_SoundStream::getStreamDelay() const
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenAL_SoundStream::updateAll(bool local)
|
double OpenAL_SoundStream::getStreamOffset() const
|
||||||
{
|
{
|
||||||
alSourcef(mSource, AL_REFERENCE_DISTANCE, mMinDistance);
|
ALint state = AL_STOPPED;
|
||||||
alSourcef(mSource, AL_MAX_DISTANCE, mMaxDistance);
|
ALint offset;
|
||||||
if(local)
|
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);
|
ALint queued;
|
||||||
alSourcei(mSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
|
||||||
|
ALint inqueue = mBufferSize/mFrameSize*queued - offset;
|
||||||
|
t = (double)(mDecoder->getSampleOffset() - inqueue) / (double)mSampleRate;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alSourcef(mSource, AL_ROLLOFF_FACTOR, 1.0f);
|
/* Underrun, or not started yet. The decoder offset is where we'll play
|
||||||
alSourcei(mSource, AL_SOURCE_RELATIVE, AL_FALSE);
|
* next. */
|
||||||
}
|
t = (double)mDecoder->getSampleOffset() / (double)mSampleRate;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
throwALerror();
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenAL_SoundStream::process()
|
bool OpenAL_SoundStream::process()
|
||||||
|
@ -562,172 +468,6 @@ ALint OpenAL_SoundStream::refillQueue()
|
||||||
return queued;
|
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
|
// An OpenAL output device
|
||||||
|
@ -881,15 +621,16 @@ void OpenAL_Output::unloadSound(Sound_Handle data)
|
||||||
SoundVec::const_iterator iter = mActiveSounds.begin();
|
SoundVec::const_iterator iter = mActiveSounds.begin();
|
||||||
for(;iter != mActiveSounds.end();++iter)
|
for(;iter != mActiveSounds.end();++iter)
|
||||||
{
|
{
|
||||||
if(!(*iter)->mSource)
|
if(!(*iter)->mHandle)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
ALuint source = GET_PTRID((*iter)->mHandle);
|
||||||
ALint srcbuf;
|
ALint srcbuf;
|
||||||
alGetSourcei((*iter)->mSource, AL_BUFFER, &srcbuf);
|
alGetSourcei(source, AL_BUFFER, &srcbuf);
|
||||||
if((ALuint)srcbuf == buffer)
|
if((ALuint)srcbuf == buffer)
|
||||||
{
|
{
|
||||||
alSourceStop((*iter)->mSource);
|
alSourceStop(source);
|
||||||
alSourcei((*iter)->mSource, AL_BUFFER, 0);
|
alSourcei(source, AL_BUFFER, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
alDeleteBuffers(1, &buffer);
|
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;
|
alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f);
|
||||||
ALuint src;
|
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())
|
if(mFreeSources.empty())
|
||||||
fail("No free sources");
|
fail("No free sources");
|
||||||
src = mFreeSources.front();
|
source = mFreeSources.front();
|
||||||
mFreeSources.pop_front();
|
mFreeSources.pop_front();
|
||||||
|
|
||||||
try {
|
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&)
|
catch(std::exception&) {
|
||||||
{
|
mFreeSources.push_back(source);
|
||||||
mFreeSources.push_back(src);
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
sound->updateAll(true);
|
sound->mHandle = MAKE_PTRID(source);
|
||||||
alSourcei(src, AL_BUFFER, GET_PTRID(data));
|
|
||||||
alSourcef(src, AL_SEC_OFFSET, offset/pitch);
|
|
||||||
|
|
||||||
alSourcePlay(src);
|
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
return sound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MWBase::SoundPtr OpenAL_Output::playSound3D(Sound_Handle data, const osg::Vec3f &pos, float vol, float basevol, float pitch,
|
void OpenAL_Output::playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset)
|
||||||
float min, float max, int flags, float offset)
|
|
||||||
{
|
{
|
||||||
boost::shared_ptr<OpenAL_Sound> sound;
|
ALuint source;
|
||||||
ALuint src;
|
|
||||||
|
|
||||||
if(mFreeSources.empty())
|
if(mFreeSources.empty())
|
||||||
fail("No free sources");
|
fail("No free sources");
|
||||||
src = mFreeSources.front();
|
source = mFreeSources.front();
|
||||||
mFreeSources.pop_front();
|
mFreeSources.pop_front();
|
||||||
|
|
||||||
try {
|
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(),
|
||||||
catch(std::exception&)
|
sound->getUseEnv());
|
||||||
{
|
|
||||||
mFreeSources.push_back(src);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
sound->updateAll(false);
|
alSourcef(source, AL_SEC_OFFSET, offset);
|
||||||
alSourcei(src, AL_BUFFER, GET_PTRID(data));
|
|
||||||
alSourcef(src, AL_SEC_OFFSET, offset/pitch);
|
|
||||||
|
|
||||||
alSourcePlay(src);
|
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
|
||||||
return sound;
|
alSourcei(source, AL_BUFFER, GET_PTRID(data));
|
||||||
}
|
alSourcePlay(source);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
mActiveSounds.push_back(sound);
|
||||||
MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float basevol, float pitch, int flags)
|
|
||||||
{
|
|
||||||
boost::shared_ptr<OpenAL_SoundStream> sound;
|
|
||||||
ALuint src;
|
|
||||||
|
|
||||||
if(mFreeSources.empty())
|
|
||||||
fail("No free sources");
|
|
||||||
src = mFreeSources.front();
|
|
||||||
mFreeSources.pop_front();
|
|
||||||
|
|
||||||
if((flags&MWBase::SoundManager::Play_Loop))
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
catch(std::exception&)
|
catch(std::exception&) {
|
||||||
{
|
mFreeSources.push_back(source);
|
||||||
mFreeSources.push_back(src);
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
sound->updateAll(true);
|
sound->mHandle = MAKE_PTRID(source);
|
||||||
|
}
|
||||||
|
|
||||||
sound->play();
|
void OpenAL_Output::stopSound(MWBase::SoundPtr sound)
|
||||||
return 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 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::streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos, float volume, float basevol, float pitch, float min, float max, int flags)
|
void OpenAL_Output::streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<OpenAL_SoundStream> sound;
|
OpenAL_SoundStream *stream = 0;
|
||||||
ALuint src;
|
ALuint source;
|
||||||
|
|
||||||
if(mFreeSources.empty())
|
if(mFreeSources.empty())
|
||||||
fail("No free sources");
|
fail("No free sources");
|
||||||
src = mFreeSources.front();
|
source = mFreeSources.front();
|
||||||
mFreeSources.pop_front();
|
mFreeSources.pop_front();
|
||||||
|
|
||||||
if((flags&MWBase::SoundManager::Play_Loop))
|
if(sound->getIsLooping())
|
||||||
std::cout <<"Warning: cannot loop stream \""<<decoder->getName()<<"\""<< std::endl;
|
std::cout <<"Warning: cannot loop stream \""<<decoder->getName()<<"\""<< std::endl;
|
||||||
try
|
try {
|
||||||
{
|
initCommon2D(source, sound->getPosition(), sound->getRealVolume(), sound->getPitch(),
|
||||||
sound.reset(new OpenAL_SoundStream3D(*this, src, decoder, pos, volume, basevol, pitch, min, max, flags));
|
false, sound->getUseEnv());
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
stream = new OpenAL_SoundStream(source, decoder);
|
||||||
|
mStreamThread->add(stream);
|
||||||
|
mActiveStreams.push_back(sound);
|
||||||
}
|
}
|
||||||
catch(std::exception&)
|
catch(std::exception&) {
|
||||||
{
|
mStreamThread->remove(stream);
|
||||||
mFreeSources.push_back(src);
|
delete stream;
|
||||||
|
mFreeSources.push_back(source);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
sound->updateAll(false);
|
sound->mHandle = stream;
|
||||||
|
}
|
||||||
|
|
||||||
sound->play();
|
void OpenAL_Output::streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sound)
|
||||||
return sound;
|
{
|
||||||
|
OpenAL_SoundStream *stream = 0;
|
||||||
|
ALuint source;
|
||||||
|
|
||||||
|
if(mFreeSources.empty())
|
||||||
|
fail("No free sources");
|
||||||
|
source = mFreeSources.front();
|
||||||
|
mFreeSources.pop_front();
|
||||||
|
|
||||||
|
if(sound->getIsLooping())
|
||||||
|
std::cout <<"Warning: cannot loop stream \""<<decoder->getName()<<"\""<< std::endl;
|
||||||
|
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&) {
|
||||||
|
mStreamThread->remove(stream);
|
||||||
|
delete stream;
|
||||||
|
mFreeSources.push_back(source);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
sound->mHandle = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
void OpenAL_Output::updateListener(const osg::Vec3f &pos, const osg::Vec3f &atdir, const osg::Vec3f &updir, Environment env)
|
||||||
{
|
{
|
||||||
mPos = pos;
|
|
||||||
mLastEnvironment = env;
|
|
||||||
|
|
||||||
if(mContext)
|
if(mContext)
|
||||||
{
|
{
|
||||||
ALfloat orient[6] = {
|
ALfloat orient[6] = {
|
||||||
atdir.x(), atdir.y(), atdir.z(),
|
atdir.x(), atdir.y(), atdir.z(),
|
||||||
updir.x(), updir.y(), updir.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);
|
alListenerfv(AL_ORIENTATION, orient);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mListenerPos = pos;
|
||||||
|
mListenerEnv = env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1060,14 +958,17 @@ void OpenAL_Output::pauseSounds(int types)
|
||||||
SoundVec::const_iterator sound = mActiveSounds.begin();
|
SoundVec::const_iterator sound = mActiveSounds.begin();
|
||||||
for(;sound != mActiveSounds.end();++sound)
|
for(;sound != mActiveSounds.end();++sound)
|
||||||
{
|
{
|
||||||
if(*sound && (*sound)->mSource && ((*sound)->getPlayType()&types))
|
if(*sound && (*sound)->mHandle && ((*sound)->getPlayType()&types))
|
||||||
sources.push_back((*sound)->mSource);
|
sources.push_back(GET_PTRID((*sound)->mHandle));
|
||||||
}
|
}
|
||||||
StreamVec::const_iterator stream = mActiveStreams.begin();
|
StreamVec::const_iterator stream = mActiveStreams.begin();
|
||||||
for(;stream != mActiveStreams.end();++stream)
|
for(;stream != mActiveStreams.end();++stream)
|
||||||
{
|
{
|
||||||
if(*stream && (*stream)->mSource && ((*stream)->getPlayType()&types))
|
if(*stream && (*stream)->mHandle && ((*stream)->getPlayType()&types))
|
||||||
sources.push_back((*stream)->mSource);
|
{
|
||||||
|
OpenAL_SoundStream *strm = reinterpret_cast<OpenAL_SoundStream*>((*stream)->mHandle);
|
||||||
|
sources.push_back(strm->mSource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(!sources.empty())
|
if(!sources.empty())
|
||||||
{
|
{
|
||||||
|
@ -1082,14 +983,17 @@ void OpenAL_Output::resumeSounds(int types)
|
||||||
SoundVec::const_iterator sound = mActiveSounds.begin();
|
SoundVec::const_iterator sound = mActiveSounds.begin();
|
||||||
for(;sound != mActiveSounds.end();++sound)
|
for(;sound != mActiveSounds.end();++sound)
|
||||||
{
|
{
|
||||||
if(*sound && (*sound)->mSource && ((*sound)->getPlayType()&types))
|
if(*sound && (*sound)->mHandle && ((*sound)->getPlayType()&types))
|
||||||
sources.push_back((*sound)->mSource);
|
sources.push_back(GET_PTRID((*sound)->mHandle));
|
||||||
}
|
}
|
||||||
StreamVec::const_iterator stream = mActiveStreams.begin();
|
StreamVec::const_iterator stream = mActiveStreams.begin();
|
||||||
for(;stream != mActiveStreams.end();++stream)
|
for(;stream != mActiveStreams.end();++stream)
|
||||||
{
|
{
|
||||||
if(*stream && (*stream)->mSource && ((*stream)->getPlayType()&types))
|
if(*stream && (*stream)->mHandle && ((*stream)->getPlayType()&types))
|
||||||
sources.push_back((*stream)->mSource);
|
{
|
||||||
|
OpenAL_SoundStream *strm = reinterpret_cast<OpenAL_SoundStream*>((*stream)->mHandle);
|
||||||
|
sources.push_back(strm->mSource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(!sources.empty())
|
if(!sources.empty())
|
||||||
{
|
{
|
||||||
|
@ -1106,8 +1010,9 @@ void OpenAL_Output::loadLoudnessAsync(DecoderPtr decoder, Sound_Loudness *loudne
|
||||||
|
|
||||||
|
|
||||||
OpenAL_Output::OpenAL_Output(SoundManager &mgr)
|
OpenAL_Output::OpenAL_Output(SoundManager &mgr)
|
||||||
: Sound_Output(mgr), mDevice(0), mContext(0), mLastEnvironment(Env_Normal),
|
: Sound_Output(mgr), mDevice(0), mContext(0)
|
||||||
mStreamThread(new StreamThread)
|
, mListenerPos(0.0f, 0.0f, 0.0f), mListenerEnv(Env_Normal)
|
||||||
|
, mStreamThread(new StreamThread)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,6 @@ namespace MWSound
|
||||||
class SoundManager;
|
class SoundManager;
|
||||||
class Sound;
|
class Sound;
|
||||||
|
|
||||||
class OpenAL_Sound;
|
|
||||||
class OpenAL_SoundStream;
|
|
||||||
|
|
||||||
class OpenAL_Output : public Sound_Output
|
class OpenAL_Output : public Sound_Output
|
||||||
{
|
{
|
||||||
ALCdevice *mDevice;
|
ALCdevice *mDevice;
|
||||||
|
@ -27,13 +24,26 @@ namespace MWSound
|
||||||
typedef std::deque<ALuint> IDDq;
|
typedef std::deque<ALuint> IDDq;
|
||||||
IDDq mFreeSources;
|
IDDq mFreeSources;
|
||||||
|
|
||||||
typedef std::vector<OpenAL_Sound*> SoundVec;
|
typedef std::vector<MWBase::SoundPtr> SoundVec;
|
||||||
SoundVec mActiveSounds;
|
SoundVec mActiveSounds;
|
||||||
typedef std::vector<OpenAL_SoundStream*> StreamVec;
|
typedef std::vector<MWBase::SoundStreamPtr> StreamVec;
|
||||||
StreamVec mActiveStreams;
|
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 std::vector<std::string> enumerate();
|
||||||
virtual void init(const std::string &devname="");
|
virtual void init(const std::string &devname="");
|
||||||
virtual void deinit();
|
virtual void deinit();
|
||||||
|
@ -42,12 +52,19 @@ namespace MWSound
|
||||||
virtual void unloadSound(Sound_Handle data);
|
virtual void unloadSound(Sound_Handle data);
|
||||||
virtual size_t getSoundDataSize(Sound_Handle data) const;
|
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 void playSound(MWBase::SoundPtr sound, Sound_Handle data, float offset);
|
||||||
virtual MWBase::SoundPtr playSound3D(Sound_Handle data, const osg::Vec3f &pos,
|
virtual void playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset);
|
||||||
float vol, float basevol, float pitch, float min, float max, int flags, float offset);
|
virtual void stopSound(MWBase::SoundPtr sound);
|
||||||
virtual MWBase::SoundPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags);
|
virtual bool isSoundPlaying(MWBase::SoundPtr sound);
|
||||||
virtual MWBase::SoundPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos,
|
virtual void updateSound(MWBase::SoundPtr sound);
|
||||||
float vol, float basevol, float pitch, float min, float max, int flags);
|
|
||||||
|
virtual void streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound);
|
||||||
|
virtual void streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sound);
|
||||||
|
virtual void stopStream(MWBase::SoundStreamPtr sound);
|
||||||
|
virtual double getStreamDelay(MWBase::SoundStreamPtr sound);
|
||||||
|
virtual double getStreamOffset(MWBase::SoundStreamPtr sound);
|
||||||
|
virtual bool isStreamPlaying(MWBase::SoundStreamPtr sound);
|
||||||
|
virtual void updateStream(MWBase::SoundStreamPtr sound);
|
||||||
|
|
||||||
virtual void startUpdate();
|
virtual void startUpdate();
|
||||||
virtual void finishUpdate();
|
virtual void finishUpdate();
|
||||||
|
@ -59,20 +76,8 @@ namespace MWSound
|
||||||
|
|
||||||
virtual void loadLoudnessAsync(DecoderPtr decoder, Sound_Loudness *loudness);
|
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);
|
OpenAL_Output(SoundManager &mgr);
|
||||||
virtual ~OpenAL_Output();
|
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
|
#ifndef DEFAULT_OUTPUT
|
||||||
#define DEFAULT_OUTPUT(x) ::MWSound::OpenAL_Output((x))
|
#define DEFAULT_OUTPUT(x) ::MWSound::OpenAL_Output((x))
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
#ifndef GAME_SOUND_SOUND_H
|
#ifndef GAME_SOUND_SOUND_H
|
||||||
#define GAME_SOUND_SOUND_H
|
#define GAME_SOUND_SOUND_H
|
||||||
|
|
||||||
#include "soundmanagerimp.hpp"
|
#include "sound_output.hpp"
|
||||||
|
|
||||||
namespace MWSound
|
namespace MWSound
|
||||||
{
|
{
|
||||||
class Sound
|
class Sound {
|
||||||
{
|
|
||||||
Sound& operator=(const Sound &rhs);
|
Sound& operator=(const Sound &rhs);
|
||||||
Sound(const Sound &rhs);
|
Sound(const Sound &rhs);
|
||||||
|
|
||||||
protected:
|
|
||||||
osg::Vec3f mPos;
|
osg::Vec3f mPos;
|
||||||
float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */
|
float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */
|
||||||
float mBaseVolume;
|
float mBaseVolume;
|
||||||
|
@ -21,12 +19,12 @@ namespace MWSound
|
||||||
|
|
||||||
float mFadeOutTime;
|
float mFadeOutTime;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Sound_Instance mHandle;
|
||||||
|
|
||||||
|
friend class OpenAL_Output;
|
||||||
|
|
||||||
public:
|
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 setPosition(const osg::Vec3f &pos) { mPos = pos; }
|
||||||
void setVolume(float volume) { mVolume = volume; }
|
void setVolume(float volume) { mVolume = volume; }
|
||||||
void setBaseVolume(float volume) { mBaseVolume = 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
|
MWBase::SoundManager::PlayType getPlayType() const
|
||||||
{ return (MWBase::SoundManager::PlayType)(mFlags&MWBase::SoundManager::Play_TypeMask); }
|
{ 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 getDistanceCull() const { return mFlags&MWBase::SoundManager::Play_RemoveAtDistance; }
|
||||||
bool getIs3D() const { return mFlags&Play_3D; }
|
bool getIs3D() const { return mFlags&Play_3D; }
|
||||||
|
|
||||||
Sound(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags)
|
Sound(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags)
|
||||||
: mPos(pos)
|
: mPos(pos), mVolume(vol), mBaseVolume(basevol), mPitch(pitch)
|
||||||
, mVolume(vol)
|
, mMinDistance(mindist), mMaxDistance(maxdist), mFlags(flags)
|
||||||
, mBaseVolume(basevol)
|
, mFadeOutTime(0.0f), mHandle(0)
|
||||||
, mPitch(pitch)
|
{ }
|
||||||
, mMinDistance(mindist)
|
Sound(float vol, float basevol, float pitch, int flags)
|
||||||
, mMaxDistance(maxdist)
|
: mPos(0.0f, 0.0f, 0.0f), mVolume(vol), mBaseVolume(basevol), mPitch(pitch)
|
||||||
, mFlags(flags)
|
, mMinDistance(1.0f), mMaxDistance(1000.0f), mFlags(flags)
|
||||||
, mFadeOutTime(0.0f)
|
, 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 <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "soundmanagerimp.hpp"
|
#include "soundmanagerimp.hpp"
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
|
||||||
|
|
||||||
namespace MWSound
|
namespace MWSound
|
||||||
{
|
{
|
||||||
class SoundManager;
|
class SoundManager;
|
||||||
|
@ -17,6 +16,8 @@ namespace MWSound
|
||||||
|
|
||||||
// An opaque handle for the implementation's sound buffers.
|
// An opaque handle for the implementation's sound buffers.
|
||||||
typedef void *Sound_Handle;
|
typedef void *Sound_Handle;
|
||||||
|
// An opaque handle for the implementation's sound instances.
|
||||||
|
typedef void *Sound_Instance;
|
||||||
|
|
||||||
class Sound_Output
|
class Sound_Output
|
||||||
{
|
{
|
||||||
|
@ -30,14 +31,19 @@ namespace MWSound
|
||||||
virtual void unloadSound(Sound_Handle data) = 0;
|
virtual void unloadSound(Sound_Handle data) = 0;
|
||||||
virtual size_t getSoundDataSize(Sound_Handle data) const = 0;
|
virtual size_t getSoundDataSize(Sound_Handle data) const = 0;
|
||||||
|
|
||||||
/// @param offset Number of seconds into the sound to start playback.
|
virtual void playSound(MWBase::SoundPtr sound, Sound_Handle data, float offset) = 0;
|
||||||
virtual MWBase::SoundPtr playSound(Sound_Handle data, float vol, float basevol, float pitch, int flags, float offset) = 0;
|
virtual void playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset) = 0;
|
||||||
/// @param offset Number of seconds into the sound to start playback.
|
virtual void stopSound(MWBase::SoundPtr sound) = 0;
|
||||||
virtual MWBase::SoundPtr playSound3D(Sound_Handle data, const osg::Vec3f &pos,
|
virtual bool isSoundPlaying(MWBase::SoundPtr sound) = 0;
|
||||||
float vol, float basevol, float pitch, float min, float max, int flags, float offset) = 0;
|
virtual void updateSound(MWBase::SoundPtr sound) = 0;
|
||||||
virtual MWBase::SoundPtr streamSound(DecoderPtr decoder, float basevol, float pitch, int flags) = 0;
|
|
||||||
virtual MWBase::SoundPtr streamSound3D(DecoderPtr decoder, const osg::Vec3f &pos,
|
virtual void streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound) = 0;
|
||||||
float vol, float basevol, float pitch, float min, float max, int flags) = 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 startUpdate() = 0;
|
||||||
virtual void finishUpdate() = 0;
|
virtual void finishUpdate() = 0;
|
||||||
|
@ -57,12 +63,9 @@ namespace MWSound
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool mInitialized;
|
bool mInitialized;
|
||||||
osg::Vec3f mPos;
|
|
||||||
|
|
||||||
Sound_Output(SoundManager &mgr)
|
Sound_Output(SoundManager &mgr)
|
||||||
: mManager(mgr)
|
: mManager(mgr), mInitialized(false)
|
||||||
, mInitialized(false)
|
|
||||||
, mPos(0.0f, 0.0f, 0.0f)
|
|
||||||
{ }
|
{ }
|
||||||
public:
|
public:
|
||||||
virtual ~Sound_Output() { }
|
virtual ~Sound_Output() { }
|
||||||
|
|
|
@ -241,7 +241,7 @@ namespace MWSound
|
||||||
return decoder;
|
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();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->getFloat();
|
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 minDistance = std::max(fAudioVoiceDefaultMinDistance * fAudioMinDistanceMult, 1.0f);
|
||||||
static float maxDistance = std::max(fAudioVoiceDefaultMaxDistance * fAudioMaxDistanceMult, minDistance);
|
static float maxDistance = std::max(fAudioVoiceDefaultMaxDistance * fAudioMaxDistanceMult, minDistance);
|
||||||
|
|
||||||
|
MWBase::SoundStreamPtr sound;
|
||||||
float basevol = volumeFromType(Play_TypeVoice);
|
float basevol = volumeFromType(Play_TypeVoice);
|
||||||
if(playlocal)
|
if(playlocal)
|
||||||
return mOutput->streamSound(decoder,
|
{
|
||||||
basevol, 1.0f, Play_Normal|Play_TypeVoice|Play_2D
|
sound.reset(new Stream(1.0f, basevol, 1.0f, Play_Normal|Play_TypeVoice|Play_2D));
|
||||||
);
|
mOutput->streamSound(decoder, sound);
|
||||||
return mOutput->streamSound3D(decoder,
|
}
|
||||||
pos, 1.0f, basevol, 1.0f, minDistance, maxDistance,
|
else
|
||||||
Play_Normal|Play_TypeVoice|Play_3D
|
{
|
||||||
);
|
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()
|
void SoundManager::stopMusic()
|
||||||
{
|
{
|
||||||
if(mMusic)
|
if(mMusic)
|
||||||
mMusic->stop();
|
mOutput->stopStream(mMusic);
|
||||||
mMusic.reset();
|
mMusic.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,19 +308,19 @@ namespace MWSound
|
||||||
return;
|
return;
|
||||||
std::cout <<"Playing "<<filename<< std::endl;
|
std::cout <<"Playing "<<filename<< std::endl;
|
||||||
mLastPlayedMusic = filename;
|
mLastPlayedMusic = filename;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
stopMusic();
|
stopMusic();
|
||||||
|
|
||||||
DecoderPtr decoder = getDecoder();
|
DecoderPtr decoder = getDecoder();
|
||||||
decoder->open(filename);
|
decoder->open(filename);
|
||||||
|
|
||||||
mMusic = mOutput->streamSound(decoder, volumeFromType(Play_TypeMusic),
|
mMusic.reset(new Stream(1.0f, volumeFromType(Play_TypeMusic), 1.0f,
|
||||||
1.0f, Play_NoEnv|Play_TypeMusic|Play_2D);
|
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";
|
std::cout << "Music Error: " << e.what() << "\n";
|
||||||
|
mMusic.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +371,7 @@ namespace MWSound
|
||||||
|
|
||||||
bool SoundManager::isMusicPlaying()
|
bool SoundManager::isMusicPlaying()
|
||||||
{
|
{
|
||||||
return mMusic && mMusic->isPlaying();
|
return mMusic && mOutput->isStreamPlaying(mMusic);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundManager::playPlaylist(const std::string &playlist)
|
void SoundManager::playPlaylist(const std::string &playlist)
|
||||||
|
@ -394,7 +399,7 @@ namespace MWSound
|
||||||
mPendingSaySounds[ptr] = std::make_pair(decoder, loudness);
|
mPendingSaySounds[ptr] = std::make_pair(decoder, loudness);
|
||||||
else
|
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);
|
mActiveSaySounds[ptr] = std::make_pair(sound, loudness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,10 +414,9 @@ namespace MWSound
|
||||||
SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr);
|
SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr);
|
||||||
if(snditer != mActiveSaySounds.end())
|
if(snditer != mActiveSaySounds.end())
|
||||||
{
|
{
|
||||||
MWBase::SoundPtr sound = snditer->second.first;
|
MWBase::SoundStreamPtr sound = snditer->second.first;
|
||||||
Sound_Loudness *loudness = snditer->second.second;
|
Sound_Loudness *loudness = snditer->second.second;
|
||||||
float sec = sound->getTimeOffset();
|
float sec = mOutput->getStreamOffset(sound);
|
||||||
if(sound->isPlaying())
|
|
||||||
return loudness->getLoudnessAtTime(sec);
|
return loudness->getLoudnessAtTime(sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +439,7 @@ namespace MWSound
|
||||||
mPendingSaySounds[MWWorld::Ptr()] = std::make_pair(decoder, loudness);
|
mPendingSaySounds[MWWorld::Ptr()] = std::make_pair(decoder, loudness);
|
||||||
else
|
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);
|
mActiveSaySounds[MWWorld::Ptr()] = std::make_pair(sound, loudness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,7 +454,7 @@ namespace MWSound
|
||||||
SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr);
|
SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr);
|
||||||
if(snditer != mActiveSaySounds.end())
|
if(snditer != mActiveSaySounds.end())
|
||||||
{
|
{
|
||||||
if(snditer->second.first->isPlaying())
|
if(mOutput->isStreamPlaying(snditer->second.first))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -462,21 +466,25 @@ namespace MWSound
|
||||||
SaySoundMap::iterator snditer = mActiveSaySounds.find(ptr);
|
SaySoundMap::iterator snditer = mActiveSaySounds.find(ptr);
|
||||||
if(snditer != mActiveSaySounds.end())
|
if(snditer != mActiveSaySounds.end())
|
||||||
{
|
{
|
||||||
snditer->second.first->stop();
|
mOutput->stopStream(snditer->second.first);
|
||||||
mActiveSaySounds.erase(snditer);
|
mActiveSaySounds.erase(snditer);
|
||||||
}
|
}
|
||||||
mPendingSaySounds.erase(ptr);
|
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())
|
if(!mOutput->isInitialized())
|
||||||
return track;
|
return track;
|
||||||
try
|
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)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
|
@ -485,6 +493,19 @@ namespace MWSound
|
||||||
return track;
|
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)
|
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));
|
Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId));
|
||||||
float basevol = volumeFromType(type);
|
float basevol = volumeFromType(type);
|
||||||
|
|
||||||
sound = mOutput->playSound(sfx->mHandle,
|
sound.reset(new Sound(volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D));
|
||||||
volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D, offset
|
mOutput->playSound(sound, sfx->mHandle, offset);
|
||||||
);
|
|
||||||
if(sfx->mUses++ == 0)
|
if(sfx->mUses++ == 0)
|
||||||
{
|
{
|
||||||
SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx);
|
SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx);
|
||||||
|
@ -510,6 +530,7 @@ namespace MWSound
|
||||||
catch(std::exception&)
|
catch(std::exception&)
|
||||||
{
|
{
|
||||||
//std::cout <<"Sound Error: "<<e.what()<< std::endl;
|
//std::cout <<"Sound Error: "<<e.what()<< std::endl;
|
||||||
|
sound.reset();
|
||||||
}
|
}
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
@ -532,14 +553,16 @@ namespace MWSound
|
||||||
return MWBase::SoundPtr();
|
return MWBase::SoundPtr();
|
||||||
|
|
||||||
if(!(mode&Play_NoPlayerLocal) && ptr == MWMechanics::getPlayer())
|
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
|
else
|
||||||
sound = mOutput->playSound3D(sfx->mHandle,
|
{
|
||||||
objpos, volume * sfx->mVolume, basevol, pitch, sfx->mMinDist, sfx->mMaxDist,
|
sound.reset(new Sound(objpos, volume * sfx->mVolume, basevol, pitch,
|
||||||
mode|type|Play_3D, offset
|
sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D));
|
||||||
);
|
mOutput->playSound3D(sound, sfx->mHandle, offset);
|
||||||
|
}
|
||||||
if(sfx->mUses++ == 0)
|
if(sfx->mUses++ == 0)
|
||||||
{
|
{
|
||||||
SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx);
|
SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx);
|
||||||
|
@ -551,6 +574,7 @@ namespace MWSound
|
||||||
catch(std::exception&)
|
catch(std::exception&)
|
||||||
{
|
{
|
||||||
//std::cout <<"Sound Error: "<<e.what()<< std::endl;
|
//std::cout <<"Sound Error: "<<e.what()<< std::endl;
|
||||||
|
sound.reset();
|
||||||
}
|
}
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
@ -567,10 +591,9 @@ namespace MWSound
|
||||||
Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId));
|
Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId));
|
||||||
float basevol = volumeFromType(type);
|
float basevol = volumeFromType(type);
|
||||||
|
|
||||||
sound = mOutput->playSound3D(sfx->mHandle,
|
sound.reset(new Sound(initialPos, volume * sfx->mVolume, basevol, pitch,
|
||||||
initialPos, volume * sfx->mVolume, basevol, pitch, sfx->mMinDist, sfx->mMaxDist,
|
sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D));
|
||||||
mode|type|Play_3D, offset
|
mOutput->playSound3D(sound, sfx->mHandle, offset);
|
||||||
);
|
|
||||||
if(sfx->mUses++ == 0)
|
if(sfx->mUses++ == 0)
|
||||||
{
|
{
|
||||||
SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx);
|
SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx);
|
||||||
|
@ -582,10 +605,16 @@ namespace MWSound
|
||||||
catch(std::exception &)
|
catch(std::exception &)
|
||||||
{
|
{
|
||||||
//std::cout <<"Sound Error: "<<e.what()<< std::endl;
|
//std::cout <<"Sound Error: "<<e.what()<< std::endl;
|
||||||
|
sound.reset();
|
||||||
}
|
}
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoundManager::stopSound(MWBase::SoundPtr sound)
|
||||||
|
{
|
||||||
|
mOutput->stopSound(sound);
|
||||||
|
}
|
||||||
|
|
||||||
void SoundManager::stopSound3D(const MWWorld::Ptr &ptr, const std::string& soundId)
|
void SoundManager::stopSound3D(const MWWorld::Ptr &ptr, const std::string& soundId)
|
||||||
{
|
{
|
||||||
SoundMap::iterator snditer = mActiveSounds.find(ptr);
|
SoundMap::iterator snditer = mActiveSounds.find(ptr);
|
||||||
|
@ -596,7 +625,7 @@ namespace MWSound
|
||||||
for(;sndidx != snditer->second.end();++sndidx)
|
for(;sndidx != snditer->second.end();++sndidx)
|
||||||
{
|
{
|
||||||
if(sndidx->second == sfx)
|
if(sndidx->second == sfx)
|
||||||
sndidx->first->stop();
|
mOutput->stopSound(sndidx->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,7 +637,7 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
SoundBufferRefPairList::iterator sndidx = snditer->second.begin();
|
SoundBufferRefPairList::iterator sndidx = snditer->second.begin();
|
||||||
for(;sndidx != snditer->second.end();++sndidx)
|
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();
|
SoundBufferRefPairList::iterator sndidx = snditer->second.begin();
|
||||||
for(;sndidx != snditer->second.end();++sndidx)
|
for(;sndidx != snditer->second.end();++sndidx)
|
||||||
sndidx->first->stop();
|
mOutput->stopSound(sndidx->first);
|
||||||
}
|
}
|
||||||
++snditer;
|
++snditer;
|
||||||
}
|
}
|
||||||
|
@ -634,7 +663,7 @@ namespace MWSound
|
||||||
sayiter->first != MWMechanics::getPlayer() &&
|
sayiter->first != MWMechanics::getPlayer() &&
|
||||||
sayiter->first.getCell() == cell)
|
sayiter->first.getCell() == cell)
|
||||||
{
|
{
|
||||||
sayiter->second.first->stop();
|
mOutput->stopStream(sayiter->second.first);
|
||||||
}
|
}
|
||||||
++sayiter;
|
++sayiter;
|
||||||
}
|
}
|
||||||
|
@ -650,7 +679,7 @@ namespace MWSound
|
||||||
for(;sndidx != snditer->second.end();++sndidx)
|
for(;sndidx != snditer->second.end();++sndidx)
|
||||||
{
|
{
|
||||||
if(sndidx->second == sfx)
|
if(sndidx->second == sfx)
|
||||||
sndidx->first->stop();
|
mOutput->stopSound(sndidx->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -680,7 +709,7 @@ namespace MWSound
|
||||||
SoundBufferRefPairList::const_iterator sndidx = snditer->second.begin();
|
SoundBufferRefPairList::const_iterator sndidx = snditer->second.begin();
|
||||||
for(;sndidx != snditer->second.end();++sndidx)
|
for(;sndidx != snditer->second.end();++sndidx)
|
||||||
{
|
{
|
||||||
if(sndidx->second == sfx && sndidx->first->isPlaying())
|
if(sndidx->second == sfx && mOutput->isSoundPlaying(sndidx->first))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -788,7 +817,7 @@ namespace MWSound
|
||||||
env = Env_Underwater;
|
env = Env_Underwater;
|
||||||
else if(mUnderwaterSound)
|
else if(mUnderwaterSound)
|
||||||
{
|
{
|
||||||
mUnderwaterSound->stop();
|
mOutput->stopSound(mUnderwaterSound);
|
||||||
mUnderwaterSound.reset();
|
mUnderwaterSound.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,7 +832,7 @@ namespace MWSound
|
||||||
if(mListenerUnderwater)
|
if(mListenerUnderwater)
|
||||||
{
|
{
|
||||||
// Play underwater sound (after updating listener)
|
// 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);
|
mUnderwaterSound = playSound("Underwater", 1.0f, 1.0f, Play_TypeSfx, Play_LoopNoEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,16 +843,37 @@ namespace MWSound
|
||||||
SoundBufferRefPairList::iterator sndidx = snditer->second.begin();
|
SoundBufferRefPairList::iterator sndidx = snditer->second.begin();
|
||||||
while(sndidx != snditer->second.end())
|
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;
|
Sound_Buffer *sfx = sndidx->second;
|
||||||
if(sfx->mUses-- == 1)
|
if(sfx->mUses-- == 1)
|
||||||
mUnusedBuffers.push_front(sfx);
|
mUnusedBuffers.push_front(sfx);
|
||||||
sndidx = snditer->second.erase(sndidx);
|
sndidx = snditer->second.erase(sndidx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
sound->updateFade(duration);
|
||||||
|
|
||||||
|
mOutput->updateSound(sound);
|
||||||
++sndidx;
|
++sndidx;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(snditer->second.empty())
|
if(snditer->second.empty())
|
||||||
mActiveSounds.erase(snditer++);
|
mActiveSounds.erase(snditer++);
|
||||||
else
|
else
|
||||||
|
@ -840,13 +890,17 @@ namespace MWSound
|
||||||
DecoderPtr decoder = penditer->second.first;
|
DecoderPtr decoder = penditer->second.first;
|
||||||
decoder->rewind();
|
decoder->rewind();
|
||||||
|
|
||||||
|
MWBase::SoundStreamPtr sound;
|
||||||
MWWorld::Ptr ptr = penditer->first;
|
MWWorld::Ptr ptr = penditer->first;
|
||||||
|
if(ptr == MWWorld::Ptr())
|
||||||
|
sound = playVoice(decoder, osg::Vec3f(), true);
|
||||||
|
else
|
||||||
|
{
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||||
const osg::Vec3f objpos(pos.asVec3());
|
const osg::Vec3f objpos(pos.asVec3());
|
||||||
|
|
||||||
MWBase::SoundPtr sound = playVoice(decoder,
|
sound = playVoice(decoder, objpos, (ptr == MWMechanics::getPlayer()));
|
||||||
objpos, (ptr == MWMechanics::getPlayer())
|
}
|
||||||
);
|
|
||||||
mActiveSaySounds[ptr] = std::make_pair(sound, loudness);
|
mActiveSaySounds[ptr] = std::make_pair(sound, loudness);
|
||||||
}
|
}
|
||||||
catch(std::exception &e) {
|
catch(std::exception &e) {
|
||||||
|
@ -862,16 +916,8 @@ namespace MWSound
|
||||||
SaySoundMap::iterator sayiter = mActiveSaySounds.begin();
|
SaySoundMap::iterator sayiter = mActiveSaySounds.begin();
|
||||||
while(sayiter != mActiveSaySounds.end())
|
while(sayiter != mActiveSaySounds.end())
|
||||||
{
|
{
|
||||||
if(!updateSound(sayiter->second.first, sayiter->first, duration))
|
MWWorld::Ptr ptr = sayiter->first;
|
||||||
mActiveSaySounds.erase(sayiter++);
|
MWBase::SoundStreamPtr sound = sayiter->second.first;
|
||||||
else
|
|
||||||
++sayiter;
|
|
||||||
}
|
|
||||||
mOutput->finishUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SoundManager::updateSound(MWBase::SoundPtr sound, const MWWorld::Ptr& ptr, float duration)
|
|
||||||
{
|
|
||||||
if(!ptr.isEmpty() && sound->getIs3D())
|
if(!ptr.isEmpty() && sound->getIs3D())
|
||||||
{
|
{
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||||
|
@ -881,17 +927,42 @@ namespace MWSound
|
||||||
if(sound->getDistanceCull())
|
if(sound->getDistanceCull())
|
||||||
{
|
{
|
||||||
if((mListenerPos - objpos).length2() > 2000*2000)
|
if((mListenerPos - objpos).length2() > 2000*2000)
|
||||||
sound->stop();
|
mOutput->stopStream(sound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!sound->isPlaying())
|
if(!mOutput->isStreamPlaying(sound))
|
||||||
return false;
|
{
|
||||||
|
mOutput->stopStream(sound);
|
||||||
|
mActiveSaySounds.erase(sayiter++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
sound->updateFade(duration);
|
sound->updateFade(duration);
|
||||||
|
|
||||||
sound->applyUpdates();
|
mOutput->updateStream(sound);
|
||||||
return true;
|
++sayiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackList::iterator trkiter = mActiveTracks.begin();
|
||||||
|
for(;trkiter != mActiveTracks.end();++trkiter)
|
||||||
|
{
|
||||||
|
MWBase::SoundStreamPtr sound = *trkiter;
|
||||||
|
if(!mOutput->isStreamPlaying(sound))
|
||||||
|
{
|
||||||
|
mOutput->stopStream(sound);
|
||||||
|
trkiter = mActiveTracks.erase(trkiter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sound->updateFade(duration);
|
||||||
|
|
||||||
|
mOutput->updateStream(sound);
|
||||||
|
++trkiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mOutput->finishUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -928,20 +999,27 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
MWBase::SoundPtr sound = sndidx->first;
|
MWBase::SoundPtr sound = sndidx->first;
|
||||||
sound->setBaseVolume(volumeFromType(sound->getPlayType()));
|
sound->setBaseVolume(volumeFromType(sound->getPlayType()));
|
||||||
sound->applyUpdates();
|
mOutput->updateSound(sound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SaySoundMap::iterator sayiter = mActiveSaySounds.begin();
|
SaySoundMap::iterator sayiter = mActiveSaySounds.begin();
|
||||||
for(;sayiter != mActiveSaySounds.end();++sayiter)
|
for(;sayiter != mActiveSaySounds.end();++sayiter)
|
||||||
{
|
{
|
||||||
MWBase::SoundPtr sound = sayiter->second.first;
|
MWBase::SoundStreamPtr sound = sayiter->second.first;
|
||||||
sound->setBaseVolume(volumeFromType(sound->getPlayType()));
|
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)
|
if(mMusic)
|
||||||
{
|
{
|
||||||
mMusic->setBaseVolume(volumeFromType(mMusic->getPlayType()));
|
mMusic->setBaseVolume(volumeFromType(mMusic->getPlayType()));
|
||||||
mMusic->applyUpdates();
|
mOutput->updateStream(mMusic);
|
||||||
}
|
}
|
||||||
mOutput->finishUpdate();
|
mOutput->finishUpdate();
|
||||||
}
|
}
|
||||||
|
@ -1056,7 +1134,7 @@ namespace MWSound
|
||||||
SoundBufferRefPairList::iterator sndidx = snditer->second.begin();
|
SoundBufferRefPairList::iterator sndidx = snditer->second.begin();
|
||||||
for(;sndidx != snditer->second.end();++sndidx)
|
for(;sndidx != snditer->second.end();++sndidx)
|
||||||
{
|
{
|
||||||
sndidx->first->stop();
|
mOutput->stopSound(sndidx->first);
|
||||||
Sound_Buffer *sfx = sndidx->second;
|
Sound_Buffer *sfx = sndidx->second;
|
||||||
if(sfx->mUses-- == 1)
|
if(sfx->mUses-- == 1)
|
||||||
mUnusedBuffers.push_front(sfx);
|
mUnusedBuffers.push_front(sfx);
|
||||||
|
@ -1065,8 +1143,12 @@ namespace MWSound
|
||||||
mActiveSounds.clear();
|
mActiveSounds.clear();
|
||||||
SaySoundMap::iterator sayiter = mActiveSaySounds.begin();
|
SaySoundMap::iterator sayiter = mActiveSaySounds.begin();
|
||||||
for(;sayiter != mActiveSaySounds.end();++sayiter)
|
for(;sayiter != mActiveSaySounds.end();++sayiter)
|
||||||
sayiter->second.first->stop();
|
mOutput->stopStream(sayiter->second.first);
|
||||||
mActiveSaySounds.clear();
|
mActiveSaySounds.clear();
|
||||||
|
TrackList::iterator trkiter = mActiveTracks.begin();
|
||||||
|
for(;trkiter != mActiveTracks.end();++trkiter)
|
||||||
|
mOutput->stopStream(*trkiter);
|
||||||
|
mActiveTracks.clear();
|
||||||
mPendingSaySounds.clear();
|
mPendingSaySounds.clear();
|
||||||
mUnderwaterSound.reset();
|
mUnderwaterSound.reset();
|
||||||
stopMusic();
|
stopMusic();
|
||||||
|
|
|
@ -79,15 +79,12 @@ namespace MWSound
|
||||||
typedef std::deque<Sound_Buffer*> SoundList;
|
typedef std::deque<Sound_Buffer*> SoundList;
|
||||||
SoundList mUnusedBuffers;
|
SoundList mUnusedBuffers;
|
||||||
|
|
||||||
boost::shared_ptr<Sound> mMusic;
|
|
||||||
std::string mCurrentPlaylist;
|
|
||||||
|
|
||||||
typedef std::pair<MWBase::SoundPtr,Sound_Buffer*> SoundBufferRefPair;
|
typedef std::pair<MWBase::SoundPtr,Sound_Buffer*> SoundBufferRefPair;
|
||||||
typedef std::vector<SoundBufferRefPair> SoundBufferRefPairList;
|
typedef std::vector<SoundBufferRefPair> SoundBufferRefPairList;
|
||||||
typedef std::map<MWWorld::Ptr,SoundBufferRefPairList> SoundMap;
|
typedef std::map<MWWorld::Ptr,SoundBufferRefPairList> SoundMap;
|
||||||
SoundMap mActiveSounds;
|
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;
|
typedef std::map<MWWorld::Ptr,SoundLoudnessPair> SaySoundMap;
|
||||||
SaySoundMap mActiveSaySounds;
|
SaySoundMap mActiveSaySounds;
|
||||||
|
|
||||||
|
@ -95,7 +92,11 @@ namespace MWSound
|
||||||
typedef std::map<MWWorld::Ptr,DecoderLoudnessPair> SayDecoderMap;
|
typedef std::map<MWWorld::Ptr,DecoderLoudnessPair> SayDecoderMap;
|
||||||
SayDecoderMap mPendingSaySounds;
|
SayDecoderMap mPendingSaySounds;
|
||||||
|
|
||||||
MWBase::SoundPtr mUnderwaterSound;
|
typedef std::vector<MWBase::SoundStreamPtr> TrackList;
|
||||||
|
TrackList mActiveTracks;
|
||||||
|
|
||||||
|
MWBase::SoundStreamPtr mMusic;
|
||||||
|
std::string mCurrentPlaylist;
|
||||||
|
|
||||||
bool mListenerUnderwater;
|
bool mListenerUnderwater;
|
||||||
osg::Vec3f mListenerPos;
|
osg::Vec3f mListenerPos;
|
||||||
|
@ -104,6 +105,8 @@ namespace MWSound
|
||||||
|
|
||||||
int mPausedSoundTypes;
|
int mPausedSoundTypes;
|
||||||
|
|
||||||
|
MWBase::SoundPtr mUnderwaterSound;
|
||||||
|
|
||||||
Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound);
|
Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound);
|
||||||
|
|
||||||
Sound_Buffer *lookupSound(const std::string &soundId) const;
|
Sound_Buffer *lookupSound(const std::string &soundId) const;
|
||||||
|
@ -113,10 +116,9 @@ namespace MWSound
|
||||||
// to start streaming
|
// to start streaming
|
||||||
DecoderPtr loadVoice(const std::string &voicefile, Sound_Loudness **lipdata);
|
DecoderPtr loadVoice(const std::string &voicefile, Sound_Loudness **lipdata);
|
||||||
|
|
||||||
MWBase::SoundPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal);
|
MWBase::SoundStreamPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal);
|
||||||
|
|
||||||
void streamMusicFull(const std::string& filename);
|
void streamMusicFull(const std::string& filename);
|
||||||
bool updateSound(MWBase::SoundPtr sound, const MWWorld::Ptr &ptr, float duration);
|
|
||||||
void updateSounds(float duration);
|
void updateSounds(float duration);
|
||||||
void updateRegionSound(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.
|
/// and get an average loudness value (scale [0,1]) at the current time position.
|
||||||
/// If the actor is not saying anything, returns 0.
|
/// 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
|
///< 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);
|
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
|
///< Play a sound, independently of 3D-position
|
||||||
///< @param offset Number of seconds into the sound to start playback.
|
///< @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.
|
///< 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.
|
///< @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);
|
virtual void stopSound3D(const MWWorld::Ptr &reference, const std::string& soundId);
|
||||||
///< Stop the given object from playing the given sound,
|
///< 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);
|
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);
|
mParent->removeChild(it->mNode);
|
||||||
|
|
||||||
it = mMagicBolts.erase(it);
|
it = mMagicBolts.erase(it);
|
||||||
|
@ -264,7 +264,7 @@ namespace MWWorld
|
||||||
for (std::vector<MagicBoltState>::iterator it = mMagicBolts.begin(); it != mMagicBolts.end(); ++it)
|
for (std::vector<MagicBoltState>::iterator it = mMagicBolts.begin(); it != mMagicBolts.end(); ++it)
|
||||||
{
|
{
|
||||||
mParent->removeChild(it->mNode);
|
mParent->removeChild(it->mNode);
|
||||||
it->mSound->stop();
|
MWBase::Environment::get().getSoundManager()->stopSound(it->mSound);
|
||||||
}
|
}
|
||||||
mMagicBolts.clear();
|
mMagicBolts.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -738,7 +738,7 @@ void WeatherManager::update(float duration, bool paused)
|
||||||
void WeatherManager::stopSounds()
|
void WeatherManager::stopSounds()
|
||||||
{
|
{
|
||||||
if (mAmbientSound.get())
|
if (mAmbientSound.get())
|
||||||
mAmbientSound->stop();
|
MWBase::Environment::get().getSoundManager()->stopSound(mAmbientSound);
|
||||||
mAmbientSound.reset();
|
mAmbientSound.reset();
|
||||||
mPlayingSoundID.clear();
|
mPlayingSoundID.clear();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue