1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-20 15:53:54 +00:00

Make the sound stream thread object per-device

This commit is contained in:
Chris Robinson 2012-03-19 02:15:08 -07:00
parent 2c27827e4f
commit 4698e8c0a2
2 changed files with 52 additions and 40 deletions

View file

@ -3,6 +3,8 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <boost/thread.hpp>
#include "openal_output.hpp" #include "openal_output.hpp"
#include "sound_decoder.hpp" #include "sound_decoder.hpp"
#include "sound.hpp" #include "sound.hpp"
@ -54,6 +56,8 @@ class OpenAL_SoundStream : public Sound
static const ALuint sNumBuffers = 4; static const ALuint sNumBuffers = 4;
static const ALuint sBufferSize = 32768; static const ALuint sBufferSize = 32768;
OpenAL_Output &mOutput;
ALuint mSource; ALuint mSource;
ALuint mBuffers[sNumBuffers]; ALuint mBuffers[sNumBuffers];
@ -65,7 +69,7 @@ class OpenAL_SoundStream : public Sound
volatile bool mIsFinished; volatile bool mIsFinished;
public: public:
OpenAL_SoundStream(DecoderPtr decoder); OpenAL_SoundStream(OpenAL_Output &output, DecoderPtr decoder);
virtual ~OpenAL_SoundStream(); virtual ~OpenAL_SoundStream();
virtual void stop(); virtual void stop();
@ -79,60 +83,68 @@ public:
// //
// A background streaming thread (keeps active streams processed) // A background streaming thread (keeps active streams processed)
// //
struct StreamThread { struct OpenAL_Output::StreamThread {
typedef std::vector<OpenAL_SoundStream*> StreamVec; typedef std::vector<OpenAL_SoundStream*> StreamVec;
static StreamVec sStreams; StreamVec mStreams;
static boost::mutex sMutex; boost::mutex mMutex;
boost::thread mThread;
StreamThread()
: mThread(boost::ref(*this))
{
}
~StreamThread()
{
mThread.interrupt();
}
// boost::thread entry point // boost::thread entry point
void operator()() void operator()()
{ {
while(1) while(1)
{ {
sMutex.lock(); mMutex.lock();
StreamVec::iterator iter = sStreams.begin(); StreamVec::iterator iter = mStreams.begin();
while(iter != sStreams.end()) while(iter != mStreams.end())
{ {
if((*iter)->process() == false) if((*iter)->process() == false)
iter = sStreams.erase(iter); iter = mStreams.erase(iter);
else else
iter++; iter++;
} }
sMutex.unlock(); mMutex.unlock();
boost::this_thread::sleep(boost::posix_time::milliseconds(20)); boost::this_thread::sleep(boost::posix_time::milliseconds(20));
} }
} }
static void add(OpenAL_SoundStream *stream) void add(OpenAL_SoundStream *stream)
{ {
sMutex.lock(); mMutex.lock();
if(std::find(sStreams.begin(), sStreams.end(), stream) == sStreams.end()) if(std::find(mStreams.begin(), mStreams.end(), stream) == mStreams.end())
sStreams.push_back(stream); mStreams.push_back(stream);
sMutex.unlock(); mMutex.unlock();
} }
static void remove(OpenAL_SoundStream *stream) void remove(OpenAL_SoundStream *stream)
{ {
sMutex.lock(); mMutex.lock();
StreamVec::iterator iter = std::find(sStreams.begin(), sStreams.end(), stream); StreamVec::iterator iter = std::find(mStreams.begin(), mStreams.end(), stream);
if(iter != sStreams.end()) if(iter != mStreams.end())
sStreams.erase(iter); mStreams.erase(iter);
sMutex.unlock(); mMutex.unlock();
} }
static void removeAll() void removeAll()
{ {
sMutex.lock(); mMutex.lock();
sStreams.clear(); mStreams.clear();
sMutex.unlock(); mMutex.unlock();
} }
}; };
StreamThread::StreamVec StreamThread::sStreams;
boost::mutex StreamThread::sMutex;
OpenAL_SoundStream::OpenAL_SoundStream(DecoderPtr decoder) OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, DecoderPtr decoder)
: mDecoder(decoder), mIsFinished(true) : mOutput(output), mDecoder(decoder), mIsFinished(true)
{ {
throwALerror(); throwALerror();
@ -170,7 +182,7 @@ OpenAL_SoundStream::OpenAL_SoundStream(DecoderPtr decoder)
} }
OpenAL_SoundStream::~OpenAL_SoundStream() OpenAL_SoundStream::~OpenAL_SoundStream()
{ {
StreamThread::remove(this); mOutput.mStreamThread->remove(this);
alDeleteSources(1, &mSource); alDeleteSources(1, &mSource);
alDeleteBuffers(sNumBuffers, mBuffers); alDeleteBuffers(sNumBuffers, mBuffers);
@ -201,13 +213,13 @@ void OpenAL_SoundStream::play(float volume, float pitch)
alSourcePlay(mSource); alSourcePlay(mSource);
throwALerror(); throwALerror();
StreamThread::add(this); mOutput.mStreamThread->add(this);
mIsFinished = false; mIsFinished = false;
} }
void OpenAL_SoundStream::stop() void OpenAL_SoundStream::stop()
{ {
StreamThread::remove(this); mOutput.mStreamThread->remove(this);
mIsFinished = true; mIsFinished = true;
alSourceStop(mSource); alSourceStop(mSource);
@ -379,7 +391,8 @@ void OpenAL_Output::init(const std::string &devname)
void OpenAL_Output::deinit() void OpenAL_Output::deinit()
{ {
StreamThread::removeAll(); if(mStreamThread.get() != 0)
mStreamThread->removeAll();
alcMakeContextCurrent(0); alcMakeContextCurrent(0);
if(mContext) if(mContext)
@ -496,7 +509,7 @@ Sound* OpenAL_Output::streamSound(const std::string &fname, float volume, float
DecoderPtr decoder = mManager.getDecoder(); DecoderPtr decoder = mManager.getDecoder();
decoder->open(fname); decoder->open(fname);
sound.reset(new OpenAL_SoundStream(decoder)); sound.reset(new OpenAL_SoundStream(*this, decoder));
sound->play(volume, pitch); sound->play(volume, pitch);
return sound.release(); return sound.release();
@ -517,13 +530,13 @@ void OpenAL_Output::updateListener(const float *pos, const float *atdir, const f
OpenAL_Output::OpenAL_Output(SoundManager &mgr) OpenAL_Output::OpenAL_Output(SoundManager &mgr)
: Sound_Output(mgr), mDevice(0), mContext(0), mStreamThread(StreamThread()) : Sound_Output(mgr), mDevice(0), mContext(0), mStreamThread(new StreamThread)
{ {
} }
OpenAL_Output::~OpenAL_Output() OpenAL_Output::~OpenAL_Output()
{ {
mStreamThread.interrupt(); mStreamThread.reset();
deinit(); deinit();
} }

View file

@ -3,8 +3,6 @@
#include <string> #include <string>
#include <boost/thread.hpp>
#include "alc.h" #include "alc.h"
#include "al.h" #include "al.h"
@ -13,7 +11,6 @@
namespace MWSound namespace MWSound
{ {
class SoundManager; class SoundManager;
class Sound_Decoder;
class Sound; class Sound;
class OpenAL_Output : public Sound_Output class OpenAL_Output : public Sound_Output
@ -21,8 +18,6 @@ namespace MWSound
ALCdevice *mDevice; ALCdevice *mDevice;
ALCcontext *mContext; ALCcontext *mContext;
boost::thread mStreamThread;
virtual void init(const std::string &devname=""); virtual void init(const std::string &devname="");
virtual void deinit(); virtual void deinit();
@ -37,6 +32,10 @@ namespace MWSound
OpenAL_Output(SoundManager &mgr); OpenAL_Output(SoundManager &mgr);
virtual ~OpenAL_Output(); virtual ~OpenAL_Output();
class StreamThread;
std::auto_ptr<StreamThread> mStreamThread;
friend class OpenAL_SoundStream;
friend class SoundManager; friend class SoundManager;
}; };
#ifndef DEFAULT_OUTPUT #ifndef DEFAULT_OUTPUT