]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/Sound.cc
renamed mippleton to library
[chaz/yoink] / src / Moof / Sound.cc
index f912b318d153c2dfa13ecf1b991169f4e87751ee..a04d29b814943de018f678a3425448053f17ab8f 100644 (file)
 #include <vorbis/codec.h>
 #include <vorbis/vorbisfile.h>
 
+#include "Library.hh"
 #include "Log.hh"
-#include "Mippleton.hh"
 #include "Sound.hh"
+#include "Timer.hh"
 
 #define BUFFER_SIZE (64 * 1024)
 //#define BUFFER_SIZE (5*2048)
@@ -45,8 +46,9 @@
 namespace Mf {
 
 
-struct Sound::Impl
+class Sound::Impl
 {
+public:
 
        static ALenum getAudioFormat(const vorbis_info* audioInfo)
        {
@@ -54,50 +56,51 @@ struct Sound::Impl
                else                                              return AL_FORMAT_STEREO16;
        }
        
+
        class Buffer;
        typedef boost::shared_ptr<Buffer> BufferP;
        
-       class Buffer : public Mippleton<Buffer>
+       class Buffer : public Library<Buffer>
        {
-               OggVorbis_File                  oggStream;
-               ALenum                                  audioFormat;
-               ALsizei                                 audioFreq;
-               std::vector<ALuint>             objects;
+               OggVorbis_File                  mOggStream;
+               ALenum                                  mFormat;
+               ALsizei                                 mFreq;
+               std::vector<ALuint>             mObjects;
 
        public:
 
                Buffer(const std::string& name) :
-                       Mippleton<Buffer>(name)
+                       Library<Buffer>(name)
                {
-                       oggStream.datasource = 0;
+                       mOggStream.datasource = 0;
                        openFile();
                }
 
                ~Buffer()
                {
-                       while (!objects.empty())
+                       while (!mObjects.empty())
                        {
-                               alDeleteBuffers(1, &objects.back());
-                               objects.pop_back();
+                               alDeleteBuffers(1, &mObjects.back());
+                               mObjects.pop_back();
                        }
 
-                       if (oggStream.datasource)
+                       if (mOggStream.datasource)
                        {
-                               ov_clear(&oggStream);
+                               ov_clear(&mOggStream);
                        }
                }
 
 
                void openFile()
                {
-                       if (oggStream.datasource)
+                       if (mOggStream.datasource)
                        {
-                               ov_clear(&oggStream);
-                               oggStream.datasource = 0;
+                               ov_clear(&mOggStream);
+                               mOggStream.datasource = 0;
                        }
 
                        std::string filePath = Sound::getPath(getName());
-                       int result = ov_fopen((char*)filePath.c_str(), &oggStream);
+                       int result = ov_fopen((char*)filePath.c_str(), &mOggStream);
 
                        if (result < 0)
                        {
@@ -106,9 +109,9 @@ struct Sound::Impl
                                throw Exception(Exception::BAD_AUDIO_FORMAT);
                        }
 
-                       vorbis_info* vorbisInfo = ov_info(&oggStream, -1);
-                       audioFormat = getAudioFormat(vorbisInfo);
-                       audioFreq = vorbisInfo->rate;
+                       vorbis_info* vorbisInfo = ov_info(&mOggStream, -1);
+                       mFormat = getAudioFormat(vorbisInfo);
+                       mFreq = vorbisInfo->rate;
 
                        logDebug("   channels: %d", vorbisInfo->channels);
                        logDebug("  frequency: %d", vorbisInfo->rate);
@@ -117,8 +120,8 @@ struct Sound::Impl
 
                void loadAll(ALuint source)
                {
-                       if (!oggStream.datasource) openFile();
-                       if (!oggStream.datasource) return;
+                       if (!mOggStream.datasource) openFile();
+                       if (!mOggStream.datasource) return;
 
                        char data[BUFFER_SIZE];
                        int size = 0;
@@ -126,7 +129,7 @@ struct Sound::Impl
                        for (;;)
                        {
                                int section;
-                               int result = ov_read(&oggStream, data + size,
+                               int result = ov_read(&mOggStream, data + size,
                                                BUFFER_SIZE - size, 0, 2, 1, &section);
 
                                if (result > 0)
@@ -149,29 +152,29 @@ struct Sound::Impl
                        ALuint obj;
                        alGenBuffers(1, &obj);
 
-                       alBufferData(obj, audioFormat, data, size, audioFreq);
+                       alBufferData(obj, mFormat, data, size, mFreq);
 
-                       objects.push_back(obj);
+                       mObjects.push_back(obj);
 
                        alSourcei(source, AL_BUFFER, obj);
 
                        // don't need this anymore
-                       ov_clear(&oggStream);
-                       oggStream.datasource = 0;
+                       ov_clear(&mOggStream);
+                       mOggStream.datasource = 0;
                }
 
 
-               void beginStream(ALuint source, int nBuffers = 4)
+               void beginStream(ALuint source, int nBuffers = 8)
                {
-                       if (!oggStream.datasource) openFile();
-                       if (!oggStream.datasource) return;
+                       if (!mOggStream.datasource) openFile();
+                       if (!mOggStream.datasource) return;
 
                        ALuint objs[nBuffers];
                        alGenBuffers(nBuffers, objs);
 
                        for (int i = 0; i < nBuffers; ++i)
                        {
-                               objects.push_back(objs[i]);
+                               mObjects.push_back(objs[i]);
                                stream(objs[i]);
                        }
 
@@ -188,10 +191,10 @@ struct Sound::Impl
                StreamStatus stream(ALuint buffer)
                {
                        std::vector<ALuint>::iterator it =
-                               std::find(objects.begin(), objects.end(), buffer);
+                               std::find(mObjects.begin(), mObjects.end(), buffer);
 
                        // that buffer doesn't belong to us
-                       if (it == objects.end()) return STREAM_WRONG;
+                       if (it == mObjects.end()) return STREAM_WRONG;
 
                        char data[BUFFER_SIZE];
                        int size = 0;
@@ -199,7 +202,7 @@ struct Sound::Impl
                        while (size < BUFFER_SIZE)
                        {
                                int section;
-                               int result = ov_read(&oggStream, data + size,
+                               int result = ov_read(&mOggStream, data + size,
                                                BUFFER_SIZE - size, 0, 2, 1, &section);
 
                                if (result > 0)
@@ -215,15 +218,15 @@ struct Sound::Impl
 
                        if (size == 0) return STREAM_EOF;
 
-                       alBufferData(buffer, audioFormat, data, size, audioFreq);
+                       alBufferData(buffer, mFormat, data, size, mFreq);
 
                        return STREAM_OK;
                }
 
                inline void rewind()
                {
-                       if (!oggStream.datasource) openFile();
-                       else ov_raw_seek(&oggStream, 0);
+                       if (!mOggStream.datasource) openFile();
+                       else ov_raw_seek(&mOggStream, 0);
                }
 
 
@@ -233,16 +236,16 @@ struct Sound::Impl
                        // clear any openal errors
                        alGetError();
 
-                       while (!objects.empty())
+                       while (!mObjects.empty())
                        {
-                               ALuint buffer = objects.back();
+                               ALuint buffer = mObjects.back();
                                alDeleteBuffers(1, &buffer);
 
                                // if an error occured, the buffer was not deleted because it's
                                // still in use by some source
                                if (alGetError() != AL_NO_ERROR) return false;
 
-                               objects.pop_back();
+                               mObjects.pop_back();
                        }
 
                        return true;
@@ -251,107 +254,110 @@ struct Sound::Impl
 
 
        Impl(const std::string& name) :
-               buffer_(Buffer::getInstance(name)),
-               playing_(false),
-               looping_(false)
+               mBuffer(Buffer::getInstance(name)),
+               mIsPlaying(false),
+               mIsLooping(false)
        {
                ALfloat zero[] = {0.0f, 0.0f, 0.0f};
                
-               alGenSources(1, &source_);
+               alGenSources(1, &mSource);
 
-               alSourcef(source_,  AL_PITCH, 1.0f);
-               alSourcef(source_,  AL_GAIN, 1.0f);
-               alSourcefv(source_, AL_POSITION, zero);
-               alSourcefv(source_, AL_VELOCITY, zero);
+               alSourcef(mSource,  AL_PITCH, 1.0f);
+               alSourcef(mSource,  AL_GAIN, 1.0f);
+               alSourcefv(mSource, AL_POSITION, zero);
+               alSourcefv(mSource, AL_VELOCITY, zero);
        }
 
        ~Impl()
        {
-               alDeleteSources(1, &source_);
+               alDeleteSources(1, &mSource);
        }
 
 
        void play()
        {
                ALenum type;
-               alGetSourcei(source_, AL_SOURCE_TYPE, &type);
+               alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
 
                if (type != AL_STATIC)
                {
-                       buffer_->loadAll(source_);
+                       mBuffer->loadAll(mSource);
                }
 
-               alSourcei(source_, AL_LOOPING, looping_);
-               alSourcePlay(source_);
-               playing_ = true;
+               alSourcei(mSource, AL_LOOPING, mIsLooping);
+               alSourcePlay(mSource);
+               mIsPlaying = true;
        }
 
 
        void stream()
        {
                ALenum type;
-               alGetSourcei(source_, AL_SOURCE_TYPE, &type);
+               alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
+
+               alSourcei(mSource, AL_BUFFER, AL_NONE);
+               mBuffer->rewind();
+               mBuffer->beginStream(mSource);
 
-               alSourcei(source_, AL_BUFFER, AL_NONE);
-               buffer_->rewind();
-               buffer_->beginStream(source_);
+               alSourcei(mSource, AL_LOOPING, AL_FALSE);
+               alSourcePlay(mSource);
+               mIsPlaying = true;
 
-               alSourcei(source_, AL_LOOPING, AL_FALSE);
-               alSourcePlay(source_);
-               playing_ = true;
+               mStreamTimer.init(boost::bind(&Impl::streamUpdate, this, _1, _2), 1.0,
+                               Timer::REPEAT);
        }
 
        inline void update()
        {
                ALint finished = 0;
 
-               alGetSourcei(source_, AL_BUFFERS_PROCESSED, &finished);
+               alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &finished);
 
                while (finished-- > 0)
                {
                        ALuint buffer;
 
-                       alSourceUnqueueBuffers(source_, 1, &buffer);
+                       alSourceUnqueueBuffers(mSource, 1, &buffer);
 
-                       Buffer::StreamStatus status = buffer_->stream(buffer);
+                       Buffer::StreamStatus status = mBuffer->stream(buffer);
 
                        if (status == Buffer::STREAM_OK)
                        {
-                               alSourceQueueBuffers(source_, 1, &buffer);
+                               alSourceQueueBuffers(mSource, 1, &buffer);
                        }
                        else if (status == Buffer::STREAM_EOF)
                        {
-                               if (!queue_.empty())
+                               if (!mQueue.empty())
                                {
                                        // begin the next buffer in the queue
-                                       expired_.push_back(buffer_);
-                                       buffer_ = queue_.front();
-                                       queue_.pop();
-                                       buffer_->beginStream(source_, 1);
+                                       mExpired.push_back(mBuffer);
+                                       mBuffer = mQueue.front();
+                                       mQueue.pop();
+                                       mBuffer->beginStream(mSource, 1);
                                }
-                               else if (looping_)
+                               else if (mIsLooping)
                                {
                                        // restart from the beginning
-                                       buffer_->rewind();
-                                       buffer_->stream(buffer);
-                                       alSourceQueueBuffers(source_, 1, &buffer);
+                                       mBuffer->rewind();
+                                       mBuffer->stream(buffer);
+                                       alSourceQueueBuffers(mSource, 1, &buffer);
                                }
                        }
                        else if (status == Buffer::STREAM_WRONG)
                        {
                                clear();
-                               buffer_->beginStream(source_, 1);
+                               mBuffer->beginStream(mSource, 1);
                        }
                }
 
                ALenum state;
-               alGetSourcei(source_, AL_SOURCE_STATE, &state);
+               alGetSourcei(mSource, AL_SOURCE_STATE, &state);
 
                // restart playing if we're stopped but supposed to be playing... this
                // means we didn't queue enough and the audio skipped
-               if (playing_ && state != AL_PLAYING)
+               if (mIsPlaying && state != AL_PLAYING)
                {
-                       alSourcePlay(source_);
+                       alSourcePlay(mSource);
                }
        }
 
@@ -359,29 +365,29 @@ struct Sound::Impl
        {
                // try to remove expired buffers
                std::vector<BufferP>::iterator it;
-               for (it = expired_.end() - 1; it >= expired_.begin(); --it)
+               for (it = mExpired.end() - 1; it >= mExpired.begin(); --it)
                {
-                       if ((*it)->clear()) expired_.erase(it);
+                       if ((*it)->clear()) mExpired.erase(it);
                }
        }
 
 
        void stop()
        {
-               alSourceStop(source_);
-               playing_ = false;
+               alSourceStop(mSource);
+               mIsPlaying = false;
        }
 
        inline void pause()
        {
-               alSourcePause(source_);
-               playing_ = false;
+               alSourcePause(mSource);
+               mIsPlaying = false;
        }
 
        inline void resume()
        {
-               alSourcePlay(source_);
-               playing_ = true;
+               alSourcePlay(mSource);
+               mIsPlaying = true;
        }
 
 
@@ -389,12 +395,12 @@ struct Sound::Impl
        {
                bool playing = isPlaying();
                ALenum type;
-               alGetSourcei(source_, AL_SOURCE_TYPE, &type);
+               alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
 
                stop();
 
-               //alSourcei(source_, AL_BUFFER, AL_NONE);
-               buffer_ = Buffer::getInstance(name);
+               //alSourcei(mSource, AL_BUFFER, AL_NONE);
+               mBuffer = Buffer::getInstance(name);
 
                if (type == AL_STREAMING)
                {
@@ -409,16 +415,16 @@ struct Sound::Impl
        inline void enqueue(const std::string& name)
        {
                BufferP buffer = Buffer::getInstance(name);
-               queue_.push(buffer);
+               mQueue.push(buffer);
        }
 
 
        inline bool isPlaying() const
        {
-               if (playing_) return true;
+               if (mIsPlaying) return true;
 
                ALenum state;
-               alGetSourcei(source_, AL_SOURCE_STATE, &state);
+               alGetSourcei(mSource, AL_SOURCE_STATE, &state);
 
                return state == AL_PLAYING;
        }
@@ -426,74 +432,77 @@ struct Sound::Impl
 
        inline void setLooping(bool looping)
        {
-               looping_ = looping;
+               mIsLooping = looping;
 
                ALenum type;
-               alGetSourcei(source_, AL_SOURCE_TYPE, &type);
+               alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
 
                if (type != AL_STREAMING)
                {
-                       alSourcei(source_, AL_LOOPING, looping_);
+                       alSourcei(mSource, AL_LOOPING, mIsLooping);
                }
        }
 
 
-       ALuint                                  source_;
-       BufferP                                 buffer_;
+       ALuint                                  mSource;
+       BufferP                                 mBuffer;
+
+       bool                                    mIsPlaying;
+       bool                                    mIsLooping;
 
-       bool                                    playing_;
-       bool                                    looping_;
+       std::queue<BufferP>             mQueue;
+       std::vector<BufferP>    mExpired;
 
-       std::queue<BufferP>             queue_;
-       std::vector<BufferP>    expired_;
+       Timer                                   mStreamTimer;
+
+       void streamUpdate(Timer& timer, Scalar t)
+       {
+               // don't let the music die!
+               update();
+               // TODO - might be nice to also allow using threads for streaming rather
+               // than a timer, probably as a compile-time option
+       }
 };
 
 Sound::Sound(const std::string& name) :
        // pass through
-       impl_(new Sound::Impl(name)) {}
+       mImpl(new Sound::Impl(name)) {}
 
 
 void Sound::play()
 {
        // pass through
-       impl_->play();
+       mImpl->play();
 }
 
-
 void Sound::stream()
 {
        // pass through
-       impl_->stream();
-}
-
-void Sound::update(Scalar t, Scalar dt)
-{
-       // pass through
-       impl_->update();
+       mImpl->stream();
 }
 
 
 void Sound::stop()
 {
        // pass through
-       impl_->stop();
+       mImpl->stop();
 }
 
 void Sound::pause()
 {
        // pass through
-       impl_->pause();
+       mImpl->pause();
 }
 
 void Sound::resume()
 {
        // pass through
-       impl_->resume();
+       mImpl->resume();
 }
 
 void Sound::toggle()
 {
-       if (impl_->playing_) pause();
+       if (mImpl->mIsPlaying) pause();
        else resume();
 }
 
@@ -501,48 +510,73 @@ void Sound::toggle()
 void Sound::setSample(const std::string& name)
 {
        // pass through
-       impl_->setSample(name);
+       mImpl->setSample(name);
 }
 
 void Sound::enqueue(const std::string& name)
 {
        // pass through
-       impl_->enqueue(name);
+       mImpl->enqueue(name);
 }
 
 
 bool Sound::isPlaying() const
 {
        // pass through
-       return impl_->isPlaying();
+       return mImpl->isPlaying();
 }
 
-void Sound::setPosition(Vector3 position)
+void Sound::setPosition(const Vector3& position)
 {
        float p[3] = {position[0], position[1], position[2]};
-       alSourcefv(impl_->source_, AL_POSITION, p);
+       alSourcefv(mImpl->mSource, AL_POSITION, p);
 }
 
-void Sound::setVelocity(Vector3 velocity)
+void Sound::setVelocity(const Vector3& velocity)
 {
        float v[3] = {velocity[0], velocity[1], velocity[2]};
-       alSourcefv(impl_->source_, AL_VELOCITY, v);
+       alSourcefv(mImpl->mSource, AL_VELOCITY, v);
 }
 
 void Sound::setGain(Scalar gain)
 {
-       alSourcef(impl_->source_, AL_GAIN, float(gain));
+       alSourcef(mImpl->mSource, AL_GAIN, float(gain));
 }
 
 void Sound::setPitch(Scalar pitch)
 {
-       alSourcef(impl_->source_, AL_PITCH, float(pitch));
+       alSourcef(mImpl->mSource, AL_PITCH, float(pitch));
 }
 
 void Sound::setLooping(bool looping)
 {
        // pass through
-       impl_->setLooping(looping);
+       mImpl->setLooping(looping);
+}
+
+
+void Sound::setListenerPosition(const Vector3& position)
+{
+       alListener3f(AL_POSITION, float(position[0]), float(position[1]),
+                       float(position[2]));
+}
+
+void Sound::setListenerVelocity(const Vector3& velocity)
+{
+       alListener3f(AL_VELOCITY, float(velocity[0]), float(velocity[1]),
+                       float(velocity[2]));
+}
+
+void Sound::setListenerOrientation(const Vector3& forward, const Vector3& up)
+{
+       float vec[6];
+       vec[0] = float(forward[0]);
+       vec[1] = float(forward[1]);
+       vec[2] = float(forward[2]);
+       vec[3] = float(up[0]);
+       vec[4] = float(up[1]);
+       vec[5] = float(up[2]);
+       alListenerfv(AL_ORIENTATION, vec);
 }
 
 
This page took 0.042373 seconds and 4 git commands to generate.