Index: code/branches/pickup2/src/orxonox/sound/AmbientSound.cc
===================================================================
--- code/branches/pickup2/src/orxonox/sound/AmbientSound.cc	(revision 5942)
+++ code/branches/pickup2/src/orxonox/sound/AmbientSound.cc	(revision 6412)
@@ -31,5 +31,8 @@
 #include "core/CoreIncludes.h"
 #include "core/EventIncludes.h"
+#include "core/GameMode.h"
+#include "core/Resource.h"
 #include "core/XMLPort.h"
+#include "SoundManager.h"
 
 namespace orxonox
@@ -39,10 +42,29 @@
     AmbientSound::AmbientSound(BaseObject* creator)
         : BaseObject(creator)
+        , Synchronisable(creator)
+        , bPlayOnLoad_(false)
     {
         RegisterObject(AmbientSound);
+
+        // Ambient sounds always fade in
+        this->setVolume(0);
+        this->registerVariables();
     }
 
-    AmbientSound::~AmbientSound()
+    void AmbientSound::preDestroy()
     {
+        if (GameMode::playsSound())
+        {
+            // Smoothly fade out by keeping a SmartPtr
+            SoundManager::getInstance().unregisterAmbientSound(this);
+        }
+    }
+
+    void AmbientSound::registerVariables()
+    {
+        registerVariable(ambientSource_, ObjectDirection::ToClient, new NetworkCallback<AmbientSound>(this, &AmbientSound::ambientSourceChanged));
+        registerVariable(bLooping_,      ObjectDirection::ToClient, new NetworkCallback<AmbientSound>(this, &AmbientSound::loopingChanged));
+        registerVariable(pitch_,         ObjectDirection::ToClient, new NetworkCallback<AmbientSound>(this, &AmbientSound::pitchChanged));
+        registerVariable(bPlayOnLoad_,   ObjectDirection::ToClient, new NetworkCallback<AmbientSound>(this, &AmbientSound::playOnLoadChanged));
     }
 
@@ -50,7 +72,7 @@
     {
         SUPER(AmbientSound, XMLPort, xmlelement, mode);
-        XMLPortParamExtern(AmbientSound, BaseSound, this, "source", setSource, getSource, xmlelement, mode);
-        XMLPortParamExtern(AmbientSound, BaseSound, this, "loop", setLoop, getLoop, xmlelement, mode);
-        XMLPortParamExtern(AmbientSound, BaseSound, this, "playOnLoad", setPlayOnLoad, getPlayOnLoad, xmlelement, mode);
+        BaseSound::XMLPortExtern(xmlelement, mode);
+        XMLPortParam(AmbientSound, "ambientSource", setAmbientSource, getAmbientSource, xmlelement, mode);
+        XMLPortParam(AmbientSound, "playOnLoad", setPlayOnLoad, getPlayOnLoad, xmlelement, mode);
     }
 
@@ -60,3 +82,62 @@
         XMLPortEventState(AmbientSound, BaseObject, "play", play, xmlelement, mode);
     }
+
+    void AmbientSound::play()
+    {
+        if (GameMode::playsSound())
+            SoundManager::getInstance().registerAmbientSound(this);
+    }
+
+    void AmbientSound::stop()
+    {
+        if (GameMode::playsSound())
+            SoundManager::getInstance().unregisterAmbientSound(this);
+    }
+
+    void AmbientSound::pause()
+    {
+        if (GameMode::playsSound())
+            SoundManager::getInstance().pauseAmbientSound(this);
+    }
+
+    float AmbientSound::getRealVolume()
+    {
+        assert(GameMode::playsSound());
+        return SoundManager::getInstance().getRealVolume(SoundType::Music);
+    }
+
+    void AmbientSound::setAmbientSource(const std::string& source)
+    {
+        this->ambientSource_ = source;
+        this->moodChanged(this->getMood());
+    }
+
+    void AmbientSound::moodChanged(const std::string& mood)
+    {
+        if (GameMode::playsSound())
+        {
+            const std::string& path = "ambient/" + MoodManager::getInstance().getMood() + '/' + this->ambientSource_;
+            shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(path);
+            if (fileInfo != NULL)
+                this->setSource(path);
+            else
+                COUT(3) << "Sound: " << this->ambientSource_ << ": Not a valid name! Ambient sound will not change." << std::endl;
+        }
+    }
+
+    void AmbientSound::setPlayOnLoad(bool val)
+    {
+        this->bPlayOnLoad_ = val;
+        if (val)
+            this->play();
+    }
+
+    void AmbientSound::changedActivity()
+    {
+        SUPER(AmbientSound, changedActivity);
+        if (this->isActive())
+            this->play();
+        else
+            this->stop();
+    }
 }
Index: code/branches/pickup2/src/orxonox/sound/AmbientSound.h
===================================================================
--- code/branches/pickup2/src/orxonox/sound/AmbientSound.h	(revision 5942)
+++ code/branches/pickup2/src/orxonox/sound/AmbientSound.h	(revision 6412)
@@ -22,8 +22,10 @@
  *   Author:
  *      Reto Grieder
+ *      Kevin Young
  *   Co-authors:
  *      ...
  *
  */
+
 #ifndef _AmbientSound_H__
 #define _AmbientSound_H__
@@ -32,5 +34,7 @@
 
 #include "core/BaseObject.h"
-#include "sound/BaseSound.h"
+#include "network/synchronisable/Synchronisable.h"
+#include "BaseSound.h"
+#include "MoodManager.h"
 
 namespace orxonox
@@ -41,14 +45,42 @@
      *
      */
-    class _OrxonoxExport AmbientSound : public BaseSound, public BaseObject
+    class _OrxonoxExport AmbientSound : public BaseSound, public BaseObject, public Synchronisable, public MoodListener
     {
+        friend class SoundManager;
+
     public:
         AmbientSound(BaseObject* creator);
-        virtual ~AmbientSound();
 
-        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
-        virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+        void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+        void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+        void changedActivity();
+
+        void play();
+        void stop();
+        void pause();
+
+        void setAmbientSource(const std::string& source);
+        inline const std::string& getAmbientSource() const
+            { return this->ambientSource_; }
+
+        void setPlayOnLoad(bool val);
+        bool getPlayOnLoad() const
+            { return this->bPlayOnLoad_; }
+
+    protected:
+        ~AmbientSound() { }
 
     private:
+        void preDestroy();
+        void registerVariables();
+        float getRealVolume();
+        void moodChanged(const std::string& mood);
+        inline void ambientSourceChanged()
+            { this->setAmbientSource(this->ambientSource_); }
+        inline void playOnLoadChanged()
+            { this->setPlayOnLoad(this->bPlayOnLoad_); }
+
+        std::string ambientSource_; //!< Analogous to source_, but mood independent
+        bool        bPlayOnLoad_;   //!< Play the sound immediately when loaded
     };
 }
Index: code/branches/pickup2/src/orxonox/sound/BaseSound.cc
===================================================================
--- code/branches/pickup2/src/orxonox/sound/BaseSound.cc	(revision 5942)
+++ code/branches/pickup2/src/orxonox/sound/BaseSound.cc	(revision 6412)
@@ -29,234 +29,249 @@
 #include "BaseSound.h"
 
+#include <cassert>
 #include <vector>
-#include <AL/alut.h>
-#include <vorbis/vorbisfile.h>
+#include <al.h>
 
 #include "core/CoreIncludes.h"
 #include "core/GameMode.h"
 #include "core/Resource.h"
+#include "core/XMLPort.h"
+#include "SoundBuffer.h"
+#include "SoundManager.h"
 
 namespace orxonox
 {
     BaseSound::BaseSound()
-        : audioSource_(0)
-        , audioBuffer_(0)
-        , bPlayOnLoad_(false)
-        , bLoop_(false)
+        : bPooling_(false)
+        , volume_(1.0)
+        , bLooping_(false)
+        , state_(Stopped)
+        , pitch_ (1.0)
     {
         RegisterRootObject(BaseSound);
+
+        // Initialise audioSource_ to a value that is not a source
+        // 0 is unfortunately not guaranteed to be no source ID.
+        this->audioSource_ = 123456789;
+        while (alIsSource(++this->audioSource_));
     }
 
     BaseSound::~BaseSound()
     {
-        this->setSource("");
-    }
-
-    void BaseSound::play()
-    {
-        if (alIsSource(this->audioSource_))
-        {
-            if (this->bLoop_)
-                alSourcei(this->audioSource_, AL_LOOPING, AL_TRUE);
-            else
-                alSourcei(this->audioSource_, AL_LOOPING, AL_FALSE);
+        this->stop();
+        // Release buffer
+        if (this->soundBuffer_ != NULL)
+        {
+            assert(GameMode::playsSound());
+            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
+        }
+    }
+
+    void BaseSound::XMLPortExtern(Element& xmlelement, XMLPort::Mode mode)
+    {
+        XMLPortParam(BaseSound, "volume",  setVolume,  getVolume,  xmlelement, mode);
+        XMLPortParam(BaseSound, "looping", setLooping, getLooping, xmlelement, mode);
+        XMLPortParam(BaseSound, "pitch",   setPitch,   getPitch,   xmlelement, mode);
+        XMLPortParam(BaseSound, "source",  setSource,  getSource,  xmlelement, mode);
+    }
+
+    void BaseSound::doPlay()
+    {
+        this->state_ = Playing;
+        if (GameMode::playsSound() && this->getSourceState() != AL_PLAYING && this->soundBuffer_ != NULL)
+        {
+            if (!alIsSource(this->audioSource_))
+            {
+                this->audioSource_ = SoundManager::getInstance().getSoundSource(this);
+                if (!alIsSource(this->audioSource_))
+                    return;
+                this->initialiseSource();
+            }
+
             alSourcePlay(this->audioSource_);
-
-            if (alGetError() != AL_NO_ERROR)
-            {
-                 COUT(2) << "Sound: OpenAL: Error playin sound " << this->audioSource_ << std::endl;
-            }
-        }
-    }
-
-    void BaseSound::stop()
-    {
-        if (alIsSource(this->audioSource_))
+            if (int error = alGetError())
+                COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
+        }
+    }
+
+    void BaseSound::doStop()
+    {
+        this->state_ = Stopped;
+        if (alIsSource(this->audioSource_))
+        {
             alSourceStop(this->audioSource_);
-    }
-
-    void BaseSound::pause()
-    {
+            // Release buffer
+            alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
+            // Release source again
+            SoundManager::getInstance().releaseSoundSource(this->audioSource_);
+            // Get a no source ID
+            this->audioSource_ += 123455;
+            while (alIsSource(++this->audioSource_));
+        }
+    }
+
+    void BaseSound::doPause()
+    {
+        if (this->isStopped())
+            return;
+        this->state_ = Paused;
         if (alIsSource(this->audioSource_))
             alSourcePause(this->audioSource_);
     }
 
-    bool BaseSound::isPlaying()
-    {
-        if (alIsSource(this->audioSource_))
-            return getSourceState() == AL_PLAYING;
-        return false;
-    }
-
-    bool BaseSound::isPaused()
-    {
-        if (alIsSource(this->audioSource_))
-            return getSourceState() == AL_PAUSED;
-        return true;
-    }
-
-    bool BaseSound::isStopped()
-    {
-        if (alIsSource(this->audioSource_))
-            return getSourceState() == AL_INITIAL || getSourceState() == AL_STOPPED;
-        return true;
-    }
-
-    void BaseSound::setPlayOnLoad(bool val)
-    {
-        this->bPlayOnLoad_ = true;
-        this->play();
+    ALint BaseSound::getSourceState() const
+    {
+        if (alIsSource(this->audioSource_))
+        {
+            ALint state;
+            alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
+            return state;
+        }
+        else
+            return AL_INITIAL;
+    }
+
+    void BaseSound::initialiseSource()
+    {
+        this->updateVolume();
+        this->setPitch(this->getPitch());
+        this->setLooping(this->getLooping());
+        alSource3f(this->audioSource_, AL_POSITION,  0, 0, 0);
+        alSource3f(this->audioSource_, AL_VELOCITY,  0, 0, 0);
+        alSource3f(this->audioSource_, AL_DIRECTION, 0, 0, 0);
+        if (ALint error = alGetError())
+            COUT(2) << "Sound Warning: Setting source parameters to 0 failed: "
+                    << SoundManager::getALErrorString(error) << std::endl;
+        assert(this->soundBuffer_ != NULL);
+        alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
+        if (ALuint error = alGetError())
+            COUT(1) << "Sound Error: Could not set buffer \"" << this->source_ << "\": " << SoundManager::getALErrorString(error) << std::endl;
+    }
+
+    void BaseSound::setVolume(float vol)
+    {
+        this->volume_ = clamp(vol, 0.0f, 1.0f);
+        if (this->volume_ != vol)
+            COUT(2) << "Sound warning: volume out of range, clamping value." << std::endl;
+        this->updateVolume();
+    }
+
+    void BaseSound::updateVolume()
+    {
+        if (alIsSource(this->audioSource_))
+        {
+            float volume = this->volume_ * this->getRealVolume();
+            alSourcef(this->audioSource_, AL_GAIN, volume);
+            if (int error = alGetError())
+                COUT(2) << "Sound: Error setting volume to " << volume
+                        << ": " << SoundManager::getALErrorString(error) << std::endl;
+        }
+    }
+
+    void BaseSound::setLooping(bool val)
+    {
+        this->bLooping_ = val;
+        if (alIsSource(this->audioSource_))
+            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
+    }
+
+    void BaseSound::setPitch(float pitch)
+    {
+        if (pitch > 2 || pitch < 0.5)
+        {
+            COUT(2) << "Sound warning: pitch out of range, cropping value." << std::endl;
+            pitch = pitch > 2 ? 2 : pitch;
+            pitch = pitch < 0.5 ? 0.5 : pitch;
+        }
+        this->pitch_ = pitch;
+        if (alIsSource(this->audioSource_))
+        {
+            alSourcef(this->audioSource_, AL_PITCH, pitch);
+            if (int error = alGetError())
+                COUT(2) << "Sound: Error setting pitch: " << SoundManager::getALErrorString(error) << std::endl;
+        }
     }
 
     void BaseSound::setSource(const std::string& source)
     {
+        if (!GameMode::playsSound())
+        {
+            this->source_ = source;
+            return;
+        }
+
+        if (this->soundBuffer_ != NULL)
+        {
+            if (this->soundBuffer_->getFilename() == source)
+            {
+                assert(this->source_ == source_);
+                return;
+            }
+            // Stopping is imperative here!
+            if (alIsSource(this->audioSource_))
+            {
+                alSourceStop(this->audioSource_);
+                alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
+            }
+            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
+            this->soundBuffer_.reset();
+        }
+
         this->source_ = source;
-        if (!GameMode::playsSound())
-            return;
-
-        if (source.empty() && alIsSource(this->audioSource_))
-        {
-            // Unload sound
-            alSourcei(this->audioSource_, AL_BUFFER, 0);
-            alDeleteSources(1, &this->audioSource_);
-            alDeleteBuffers(1, &this->audioBuffer_);
-            return;
-        }
-
-        COUT(3) << "Sound: OpenAL ALUT: loading file " << source << std::endl;
-        // Get DataStream from the resources
-        shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(source);
-        if (fileInfo == NULL)
-        {
-            COUT(2) << "Warning: Sound file '" << source << "' not found" << std::endl;
-            return;
-        }
-        dataStream_ = Resource::open(source);
-        // Read everything into a temporary buffer
-        char* buffer = new char[fileInfo->size];
-        dataStream_->read(buffer, fileInfo->size);
-        dataStream_->seek(0);
-
-        this->audioBuffer_ = alutCreateBufferFromFileImage(buffer, fileInfo->size);
-        delete[] buffer;
-
-        if (this->audioBuffer_ == AL_NONE)
-        {
-            COUT(2) << "Sound: OpenAL ALUT: " << alutGetErrorString(alutGetError()) << std::endl;
-            if (source.find("ogg", 0) != std::string::npos)
-            {
-                COUT(2) << "Sound: Trying fallback ogg loader" << std::endl;
-                this->audioBuffer_ = loadOggFile();
-            }
-
-            if (this->audioBuffer_ == AL_NONE)
-            {
-                COUT(2) << "Sound: fallback ogg loader failed: " << alutGetErrorString(alutGetError()) << std::endl;
+        // Don't load ""
+        if (source_.empty())
+            return;
+
+        // Get new sound buffer
+        this->soundBuffer_ = SoundManager::getInstance().getSoundBuffer(this->source_);
+        if (this->soundBuffer_ == NULL)
+            return;
+
+        if (alIsSource(this->audioSource_)) // already playing or paused
+        {
+            // Set new buffer
+            alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
+            if (ALuint error = alGetError())
+            {
+                COUT(1) << "Sound Error: Could not set buffer \"" << source << "\": " << SoundManager::getALErrorString(error) << std::endl;
                 return;
             }
-        }
-
-        alGenSources(1, &this->audioSource_);
-        alSourcei(this->audioSource_, AL_BUFFER, this->audioBuffer_);
-        if (alGetError() != AL_NO_ERROR)
-        {
-            COUT(2) << "Sound: OpenAL: Error loading sample file: " << source << std::endl;
-            return;
-        }
-
-        alSource3f(this->audioSource_, AL_POSITION,  0, 0, 0);
-
-        if (this->bPlayOnLoad_)
-            this->play();
-    }
-
-    ALint BaseSound::getSourceState()
-    {
-        ALint state;
-        alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
-        return state;
-    }
-
-    size_t readVorbis(void* ptr, size_t size, size_t nmemb, void* datasource)
-    {
-        return static_cast<Ogre::DataStream*>(datasource)->read(ptr, size * nmemb);
-    }
-
-    int seekVorbis(void* datasource, ogg_int64_t offset, int whence)
-    {
-        Ogre::DataStream* stream = static_cast<Ogre::DataStream*>(datasource);
-        int offset_beg = offset;
-        if (whence == SEEK_CUR)
-            offset_beg = stream->tell() + offset;
-        else if (whence == SEEK_END)
-            offset_beg = stream->size() + offset;
-        else if (whence != SEEK_SET)
-            return -1;
-        stream->seek(offset_beg);
-        return 0;
-    }
-
-    long tellVorbis(void* datasource)
-    {
-        return static_cast<long>(static_cast<Ogre::DataStream*>(datasource)->tell());
-    }
-
-    ALuint BaseSound::loadOggFile()
-    {
-        char inbuffer[4096];
-        std::vector<char> outbuffer;
-        OggVorbis_File vf;
-        vorbis_info* vorbisInfo;
-        int eof = false;
-        int current_section;
-        ALuint buffer;
-        ALenum format;
-
-        // Open file with custom streaming
-        ov_callbacks vorbisCallbacks;
-        vorbisCallbacks.read_func  = &readVorbis;
-        vorbisCallbacks.seek_func  = &seekVorbis;
-        vorbisCallbacks.tell_func  = &tellVorbis;
-        vorbisCallbacks.close_func = NULL;
-
-        int ret = ov_open_callbacks(dataStream_.get(), &vf, NULL, 0, vorbisCallbacks);
-        if (ret < 0)
-        {
-            COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
-            ov_clear(&vf);
-            return AL_NONE;
-        }
-
-        while (!eof)
-        {
-            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
-            if (ret == 0)
-            {
-                eof = true;
-            }
-            else if (ret < 0)
-            {
-                COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
-                ov_clear(&vf);
-                return AL_NONE;
-            }
-            else
-            {
-                outbuffer.insert(outbuffer.end(), inbuffer, inbuffer + sizeof(inbuffer));
-            }
-        }
-
-        vorbisInfo = ov_info(&vf, -1);
-        if (vorbisInfo->channels == 1)
-            format = AL_FORMAT_MONO16;
-        else
-            format = AL_FORMAT_STEREO16;
-
-        alGenBuffers(1, &buffer);
-        alBufferData(buffer, format, &outbuffer[0], outbuffer.size(), vorbisInfo->rate);
-        ov_clear(&vf);
-
-        return buffer;
-    }
-
-} // namespace: orxonox
+
+            // Sound was already playing or paused because there was a source acquired
+            assert(this->isPlaying() || this->isPaused());
+            alSourcePlay(this->audioSource_);
+            if (int error = alGetError())
+                COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
+            if (this->isPaused())
+                alSourcePause(this->audioSource_);
+        }
+        else // No source acquired so far, but might be set to playing or paused
+        {
+            State state = this->state_; // save
+            if (this->isPlaying() || this->isPaused())
+                doPlay();
+            if (state == Paused)
+            {
+                this->state_ = Paused;
+                doPause();
+            }
+        }
+    }
+
+    void BaseSound::stateChanged()
+    {
+        switch (this->state_)
+        {
+            case Playing:
+                this->play();
+                break;
+            case Paused:
+                this->pause();
+                break;
+            case Stopped:
+            default:
+                this->stop();
+                break;
+        }
+    }
+}
Index: code/branches/pickup2/src/orxonox/sound/BaseSound.h
===================================================================
--- code/branches/pickup2/src/orxonox/sound/BaseSound.h	(revision 5942)
+++ code/branches/pickup2/src/orxonox/sound/BaseSound.h	(revision 6412)
@@ -26,4 +26,5 @@
  *
  */
+
 #ifndef _BaseSound_H__
 #define _BaseSound_H__
@@ -32,5 +33,5 @@
 
 #include <string>
-#include <OgreSharedPtr.h>
+#include <boost/shared_ptr.hpp>
 #include <OgreDataStream.h>
 #include "core/OrxonoxClass.h"
@@ -47,35 +48,73 @@
     public:
         BaseSound();
+
+        void XMLPortExtern(Element& xmlelement, XMLPort::Mode mode);
+
+        virtual void play()  { this->doPlay(); }
+        virtual void stop()  { this->doStop(); }
+        virtual void pause() { this->doPause(); }
+
+        bool isPlaying() const { return this->state_ == Playing; }
+        bool isPaused()  const { return this->state_ == Paused; }
+        bool isStopped() const { return this->state_ == Stopped; }
+
+        virtual void setSource(const std::string& source);
+        virtual const std::string& getSource() const
+            { return this->source_; }
+
+        void setVolume(float vol);
+        float getVolume() const
+            { return this->volume_; }
+        void updateVolume();
+
+        bool getLooping() const
+            { return this->bLooping_; }
+        void setLooping(bool val);
+
+        float getPitch() const
+            { return this->pitch_; }
+        void setPitch(float pitch);
+
+    protected:
+        enum State
+        {
+            Stopped,
+            Playing,
+            Paused
+        };
+
         virtual ~BaseSound();
 
-        void play();
-        void stop();
-        void pause();
+        void doPlay();
+        void doStop();
+        void doPause();
 
-        bool isPlaying();
-        bool isPaused();
-        bool isStopped();
+        // network callbacks
+        inline void pitchChanged()
+            { this->setPitch(this->pitch_); }
+        inline void loopingChanged()
+            { this->setLooping(this->bLooping_); }
+        inline void volumeChanged()
+            { this->setVolume(this->volume_); }
+        inline void sourceChanged()
+            { this->setSource(this->source_); }
+        void stateChanged();
 
-        void setSource(const std::string& source);
-        const std::string& getSource() { return this->source_; }
+        virtual void initialiseSource();
+        ALint getSourceState() const;
 
-        bool getPlayOnLoad() { return this->bPlayOnLoad_; }
-        void setPlayOnLoad(bool val);
+        virtual float getRealVolume() = 0;
 
-        bool getLoop() { return this->bLoop_; }
-        void setLoop(bool val) { this->bLoop_ = val; }
-
-    protected:
-        ALuint loadOggFile();
-        ALint getSourceState();
-
-        ALuint audioSource_;
-        ALuint audioBuffer_;
+        ALuint          audioSource_;
+        bool            bPooling_;
+        shared_ptr<SoundBuffer> soundBuffer_;
+        std::string     source_;
+        float           volume_;
+        bool            bLooping_;
+        State           state_;
+        float           pitch_;
 
     private:
-        std::string source_;
-        bool bPlayOnLoad_;
-        bool bLoop_;
-        DataStreamPtr dataStream_;
+        DataStreamPtr   dataStream_;
     };
 }
Index: code/branches/pickup2/src/orxonox/sound/CMakeLists.txt
===================================================================
--- code/branches/pickup2/src/orxonox/sound/CMakeLists.txt	(revision 5942)
+++ code/branches/pickup2/src/orxonox/sound/CMakeLists.txt	(revision 6412)
@@ -2,6 +2,8 @@
     AmbientSound.cc
     BaseSound.cc
+    SoundBuffer.cc
     SoundManager.cc
     WorldSound.cc
+    SoundStreamer.cc
 )
 
Index: code/branches/pickup2/src/orxonox/sound/SoundBuffer.cc
===================================================================
--- code/branches/pickup2/src/orxonox/sound/SoundBuffer.cc	(revision 6412)
+++ code/branches/pickup2/src/orxonox/sound/SoundBuffer.cc	(revision 6412)
@@ -0,0 +1,187 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *      Erwin 'vaiursch' Herrsche
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "SoundBuffer.h"
+
+#include <AL/alut.h>
+#include <vorbis/vorbisfile.h>
+
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "sound/SoundManager.h"
+
+namespace orxonox
+{
+    SoundBuffer::SoundBuffer(const std::string& filename, std::list<shared_ptr<SoundBuffer> >::iterator poolIterator)
+        : filename_(filename)
+        , audioBuffer_(AL_NONE)
+        , poolIterator_(poolIterator)
+    {
+        if (this->filename_.empty())
+            ThrowException(General, "SoundBuffer construction: fileInfo was NULL");
+
+        // Get resource info
+        shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(filename);
+        if (fileInfo == NULL)
+        {
+            COUT(2) << "Sound: Warning: Sound file '" << filename << "' not found" << std::endl;
+            return;
+        }
+        // Open data stream
+        DataStreamPtr dataStream = Resource::open(fileInfo);
+
+        const std::string& extension = this->filename_.substr(this->filename_.find_last_of('.') + 1);
+        if (getLowercase(extension) == "ogg")
+        {
+            // Try ogg loader
+            this->loadOgg(fileInfo, dataStream);
+        }
+        else
+        {
+            // Try standard OpenAL loader
+            this->loadStandard(fileInfo, dataStream);
+        }
+    }
+
+    SoundBuffer::~SoundBuffer()
+    {
+        // Destroy buffer
+        alDeleteBuffers(1, &this->audioBuffer_);
+    }
+
+    unsigned int SoundBuffer::getSize() const
+    {
+        ALint size;
+        alGetBufferi(this->audioBuffer_, AL_SIZE, &size);
+        return alGetError() ? 0 : size;
+    }
+
+    void SoundBuffer::loadStandard(const shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream)
+    {
+        // Read everything into a temporary buffer
+        char* buffer = new char[fileInfo->size];
+        dataStream->read(buffer, fileInfo->size);
+        dataStream->seek(0);
+
+        this->audioBuffer_ = alutCreateBufferFromFileImage(buffer, fileInfo->size);
+        delete[] buffer;
+
+        if (!alIsBuffer(this->audioBuffer_))
+            ThrowException(General, "Sound Error: Standard file loader failed: " << alutGetErrorString(alutGetError()));
+    }
+
+    size_t readVorbis(void* ptr, size_t size, size_t nmemb, void* datasource)
+    {
+        return static_cast<Ogre::DataStream*>(datasource)->read(ptr, size * nmemb);
+    }
+
+    int seekVorbis(void* datasource, ogg_int64_t offset, int whence)
+    {
+        Ogre::DataStream* stream = static_cast<Ogre::DataStream*>(datasource);
+        switch (whence)
+        {
+        case SEEK_SET:
+            stream->seek(offset);
+            break;
+        case SEEK_CUR:
+            stream->skip(offset);
+            break;
+        case SEEK_END:
+            stream->seek(stream->size() + offset);
+            break;
+        default:
+            return -1;
+        }
+        return 0;
+    }
+
+    long tellVorbis(void* datasource)
+    {
+        return static_cast<long>(static_cast<Ogre::DataStream*>(datasource)->tell());
+    }
+
+    void SoundBuffer::loadOgg(const shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream)
+    {
+        char inbuffer[256*1024];
+        std::vector<char> outbuffer;
+        outbuffer.reserve(80*1024*1024);
+
+        // Open file with custom streaming
+        ov_callbacks vorbisCallbacks;
+        vorbisCallbacks.read_func  = &readVorbis;
+        vorbisCallbacks.seek_func  = &seekVorbis;
+        vorbisCallbacks.tell_func  = &tellVorbis;
+        vorbisCallbacks.close_func = NULL;
+
+        OggVorbis_File vf;
+        int ret = ov_open_callbacks(dataStream.get(), &vf, NULL, 0, vorbisCallbacks);
+        if (ret < 0)
+        {
+            COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
+            ov_clear(&vf);
+            ThrowException(General, "Sound Error: Ogg file loader failed when opening the bitstream");
+        }
+
+        int current_section;
+        int eof = false;
+        while (!eof)
+        {
+            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
+            if (ret == 0)
+            {
+                eof = true;
+            }
+            else if (ret < 0)
+            {
+                COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
+                ov_clear(&vf);
+                ThrowException(General, "Sound Error: Ogg file loader failed when decoding the file");
+            }
+            else
+            {
+                outbuffer.insert(outbuffer.end(), inbuffer, inbuffer + ret);
+            }
+        }
+
+        vorbis_info* vorbisInfo;
+        vorbisInfo = ov_info(&vf, -1);
+        ALenum format;
+        if (vorbisInfo->channels == 1)
+            format = AL_FORMAT_MONO16;
+        else
+            format = AL_FORMAT_STEREO16;
+
+        alGenBuffers(1, &this->audioBuffer_);
+        alBufferData(this->audioBuffer_, format, &outbuffer[0], outbuffer.size(), vorbisInfo->rate);
+        ov_clear(&vf);
+
+        if (!alIsBuffer(this->audioBuffer_))
+            ThrowException(General, "Sound: Ogg file loader failed when creating the buffer.");
+    }
+}
Index: code/branches/pickup2/src/orxonox/sound/SoundBuffer.h
===================================================================
--- code/branches/pickup2/src/orxonox/sound/SoundBuffer.h	(revision 6412)
+++ code/branches/pickup2/src/orxonox/sound/SoundBuffer.h	(revision 6412)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _SoundBuffer_H__
+#define _SoundBuffer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <list>
+#include <boost/shared_ptr.hpp>
+#include "core/Resource.h"
+
+namespace orxonox
+{
+    /*
+    @brief
+        The SoundBuffer class is to be used for sounds with position and orientation.
+    */
+    class _OrxonoxExport SoundBuffer
+    {
+        friend class SoundManager;
+        // Make sure nobody deletes an instance (using smart pointers)
+        template <class T>
+        friend void boost::checked_delete(T*);
+
+    public:
+        inline ALuint getBuffer()
+            { return this->audioBuffer_; }
+
+        unsigned int getSize() const;
+
+        const std::string& getFilename() const
+            { return this->filename_; }
+
+    private:
+        SoundBuffer(const std::string& filename, std::list<shared_ptr<SoundBuffer> >::iterator poolIterator);
+        ~SoundBuffer();
+        void loadStandard(const shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream);
+        void loadOgg(const shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream);
+
+        std::string filename_;
+        ALuint audioBuffer_;
+        std::list<shared_ptr<SoundBuffer> >::iterator poolIterator_;
+    };
+}
+
+#endif /* _SoundBuffer_H__ */
Index: code/branches/pickup2/src/orxonox/sound/SoundManager.cc
===================================================================
--- code/branches/pickup2/src/orxonox/sound/SoundManager.cc	(revision 5942)
+++ code/branches/pickup2/src/orxonox/sound/SoundManager.cc	(revision 6412)
@@ -22,4 +22,6 @@
  *   Author:
  *       Erwin 'vaiursch' Herrsche
+ *       Kevin Young
+ *       Reto Grieder
  *   Co-authors:
  *      ...
@@ -30,64 +32,289 @@
 
 #include <AL/alut.h>
+#include <utility>
 
 #include "util/Exception.h"
 #include "util/Math.h"
 #include "util/ScopeGuard.h"
+#include "util/Clock.h"
+#include "core/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
 #include "core/GameMode.h"
 #include "core/ScopedSingletonManager.h"
+#include "core/Resource.h"
+#include "SoundBuffer.h"
+#include "BaseSound.h"
+#include "AmbientSound.h"
+#include "WorldSound.h"
 
 namespace orxonox
 {
-    SoundManager* SoundManager::singletonPtr_s = NULL;
     ManageScopedSingleton(SoundManager, ScopeID::Graphics, true);
 
+    std::string SoundManager::getALErrorString(ALenum code)
+    {
+        switch (code)
+        {
+        case AL_NO_ERROR:          return "No error";
+        case AL_INVALID_NAME:      return "Invalid AL parameter name";
+        case AL_INVALID_ENUM:      return "Invalid AL enum";
+        case AL_INVALID_VALUE:     return "Invalid AL value";
+        case AL_INVALID_OPERATION: return "Invalid AL operation";
+        case AL_OUT_OF_MEMORY:     return "AL reports out of memory";
+        default:                   return "Unknown AL error";
+        }
+    }
+
     SoundManager::SoundManager()
-    {
-        if (!alutInitWithoutContext(NULL,NULL))
-            ThrowException(InitialisationFailed, "OpenAL ALUT error: " << alutGetErrorString(alutGetError()));
+        : effectsPoolSize_(0)
+    {
+        RegisterRootObject(SoundManager);
+
+        // See whether we even want to load
+        bool bDisableSound_ = false;
+        SetConfigValue(bDisableSound_, false);
+        if (bDisableSound_)
+            ThrowException(InitialisationAborted, "Sound: Not loading at all");
+
+        if (!alutInitWithoutContext(NULL, NULL))
+            ThrowException(InitialisationFailed, "Sound Error: ALUT initialisation failed: " << alutGetErrorString(alutGetError()));
         Loki::ScopeGuard alutExitGuard = Loki::MakeGuard(&alutExit);
 
-        COUT(3) << "OpenAL: Opening sound device..." << std::endl;
+/*
+        // Get list of available sound devices and display them
+        const char* devices = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
+        char* device = new char[strlen(devices)+1];
+        strcpy(device, devices);
+        std::string renderDevice;
+        SetConfigValue(renderDevice, std::string(device)).description("Sound device used for rendering");
+        COUT(4) << "Sound: Available devices: ";
+        while (true)
+        {
+            this->deviceNames_.push_back(devices);
+            COUT(4) << '"' << devices << "\", ";
+            devices += strlen(devices) + 1;
+            if (*devices == '\0')
+                break;
+        }
+        COUT(4) << std::endl;
+
+        // Open the selected device
+        COUT(3) << "Sound: Opening device \"" << renderDevice << '\' << std::endl;
+        this->device_ = alcOpenDevice(renderDevice.c_str());
+*/
         this->device_ = alcOpenDevice(NULL);
         if (this->device_ == NULL)
         {
-            COUT(0) << "OpenaAL: Could not open sound device. Have you installed OpenAL?" << std::endl;
+            COUT(1) << "Sound: Could not open sound device. Have you installed OpenAL?" << std::endl;
 #ifdef ORXONOX_PLATFORM_WINDOWS
-            COUT(0) << "Just getting the DLL with the dependencies is not enough for Windows (esp. Windows 7)!" << std::endl;
+            COUT(1) << "Sound: Just getting the DLL with the dependencies is not enough for Windows (esp. Windows 7)!" << std::endl;
 #endif
-            ThrowException(InitialisationFailed, "OpenAL error: Could not open sound device.");
+            ThrowException(InitialisationFailed, "Sound Error: Could not open sound device.");
         }
         Loki::ScopeGuard closeDeviceGuard = Loki::MakeGuard(&alcCloseDevice, this->device_);
 
-        COUT(3) << "OpenAL: Sound device opened" << std::endl;
+        // Create sound context and make it the currently used one
         this->context_ = alcCreateContext(this->device_, NULL);
         if (this->context_ == NULL)
-            ThrowException(InitialisationFailed, "OpenAL error: Could not create sound context");
+            ThrowException(InitialisationFailed, "Sound Error: Could not create ALC context");
         Loki::ScopeGuard desroyContextGuard = Loki::MakeGuard(&alcDestroyContext, this->context_);
-
-        if (alcMakeContextCurrent(this->context_) == AL_TRUE)
-            COUT(3) << "OpenAL: Context " << this->context_ << " loaded" << std::endl;
-
-        COUT(4) << "Sound: OpenAL ALUT version: " << alutGetMajorVersion() << "." << alutGetMinorVersion() << std::endl;
-
-        const char* str = alutGetMIMETypes(ALUT_LOADER_BUFFER);
-        if (str == NULL)
-            COUT(2) << "OpenAL ALUT error: " << alutGetErrorString(alutGetError()) << std::endl;
+        if (!alcMakeContextCurrent(this->context_))
+            ThrowException(InitialisationFailed, "Sound Error: Could not use ALC context");
+
+        GameMode::setPlaysSound(true);
+        Loki::ScopeGuard resetPlaysSoundGuard = Loki::MakeGuard(&GameMode::setPlaysSound, false);
+
+        // Get some information about the sound
+        if (const char* version = alGetString(AL_VERSION))
+            COUT(4) << "Sound: --- OpenAL Version: " << version << std::endl;
+        if (const char* vendor = alGetString(AL_VENDOR))
+            COUT(4) << "Sound: --- OpenAL Vendor : " << vendor << std::endl;
+        if (const char* types = alutGetMIMETypes(ALUT_LOADER_BUFFER))
+            COUT(4) << "Sound: --- Supported MIME Types: " << types << std::endl;
         else
-            COUT(4) << "OpenAL ALUT supported MIME types: " << str << std::endl;
-
-        GameMode::setPlaysSound(true);
+            COUT(2) << "Sound Warning: MIME Type retrieval failed: " << alutGetErrorString(alutGetError()) << std::endl;
+
+        this->mute_[SoundType::All]     = 1.0f;
+        this->mute_[SoundType::Music]   = 1.0f;
+        this->mute_[SoundType::Effects] = 1.0f;
+
+        this->setConfigValues();
+
+        // Try to get at least one source
+        ALuint source;
+        alGenSources(1, &source);
+        if (!alGetError() && alIsSource(source))
+            this->availableSoundSources_.push_back(source);
+        else
+            ThrowException(InitialisationFailed, "Sound Error: Could not create even a single source");
+        // Create a few initial sources
+        this->createSoundSources(this->minSources_ - 1);
+
         // Disarm guards
         alutExitGuard.Dismiss();
         closeDeviceGuard.Dismiss();
         desroyContextGuard.Dismiss();
+        resetPlaysSoundGuard.Dismiss();
+
+        COUT(4) << "Sound: Initialisation complete" << std::endl;
     }
 
     SoundManager::~SoundManager()
     {
+        // Erase fade lists because of the smart pointers
+        this->fadeInList_.clear();
+        this->fadeOutList_.clear();
+
+        // If there are still used buffers around, well, that's just very bad...
+        if (this->soundBuffers_.size() != this->effectsPool_.size())
+            COUT(1) << "Sound Error: Some sound buffers are still in use but OpenAL is about to shut down. Fix this!" << std::endl;
+        // Empty buffer pool and buffer list
+        this->effectsPool_.clear();
+        this->soundBuffers_.clear();
+
+        // There should not be any sources in use anymore
+        if (!this->usedSoundSources_.empty())
+            COUT(1) << "Sound Error: Some sound sources are still in use but OpenAL is about to shut down. Fix this!" << std::endl;
+        while (!this->availableSoundSources_.empty())
+        {
+            alDeleteSources(1, &this->availableSoundSources_.back());
+            this->availableSoundSources_.pop_back();
+        }
+
         GameMode::setPlaysSound(false);
+
+        // Relieve context to destroy it
+        if (!alcMakeContextCurrent(NULL))
+            COUT(1) << "Sound Error: Could not unset ALC context" << std::endl;
         alcDestroyContext(this->context_);
+        if (ALCenum error = alcGetError(this->device_))
+        {
+            if (error == AL_INVALID_OPERATION)
+                COUT(1) << "Sound Error: Could not destroy ALC context because it is the current one" << std::endl;
+            else
+                COUT(1) << "Sound Error: Could not destroy ALC context because it is invalid" << std::endl;
+        }
+#ifdef AL_VERSION_1_1
+        if (!alcCloseDevice(this->device_))
+            COUT(1) << "Sound Error: Could not destroy ALC device. This might be because there are still buffers in use!" << std::endl;
+#else
         alcCloseDevice(this->device_);
-        alutExit();
+#endif
+        if (!alutExit())
+            COUT(1) << "Sound Error: Closing ALUT failed: " << alutGetErrorString(alutGetError()) << std::endl;
+    }
+
+    void SoundManager::setConfigValues()
+    {
+        SetConfigValue(crossFadeStep_, 0.2f)
+            .description("Determines how fast sounds should fade, per second.")
+            .callback(this, &SoundManager::checkFadeStepValidity);
+
+        SetConfigValueAlias(volume_[SoundType::All], "soundVolume_", 1.0f)
+            .description("Defines the overall volume.")
+            .callback(this, &SoundManager::checkSoundVolumeValidity);
+        SetConfigValueAlias(volume_[SoundType::Music], "ambientVolume_", 1.0f)
+            .description("Defines the ambient volume.")
+            .callback(this, &SoundManager::checkAmbientVolumeValidity);
+        SetConfigValueAlias(volume_[SoundType::Effects], "effectsVolume_", 1.0f)
+            .description("Defines the effects volume.")
+            .callback(this, &SoundManager::checkEffectsVolumeValidity);
+
+        SetConfigValue(minSources_, 16)
+            .description("Minimum number of sources being generated (if possible)");
+        SetConfigValue(maxSources_, 1024)
+            .description("Maximum number of sources to be made available");
+    }
+
+    void SoundManager::preUpdate(const Clock& time)
+    {
+        this->processCrossFading(time.getDeltaTime());
+
+        // Check whether a sound object has stopped playing
+        for (unsigned int i = 0; i < this->usedSoundSources_.size(); ++i)
+        {
+            ALint state;
+            alGetSourcei(this->usedSoundSources_[i].first, AL_SOURCE_STATE, &state);
+            if (state == AL_STOPPED)
+            {
+                this->usedSoundSources_[i].second->stop();
+                --i;
+            }
+        }
+    }
+
+    void SoundManager::checkFadeStepValidity()
+    {
+        if (crossFadeStep_ <= 0.0 || crossFadeStep_ >= 1.0 )
+        {
+            COUT(2) << "Sound warning: fade step out of range, ignoring change." << std::endl;
+            ResetConfigValue(crossFadeStep_);
+        }
+    }
+
+    void SoundManager::checkVolumeValidity(SoundType::Value type)
+    {
+        float clampedVolume = clamp(this->volume_[type], 0.0f, 1.0f);
+        if (clampedVolume != this->volume_[type])
+            COUT(2) << "Sound warning: Volume setting (" << type << ") out of range, clamping." << std::endl;
+        this->updateVolume(type);
+    }
+
+    void SoundManager::setVolume(float vol, SoundType::Value type)
+    {
+        if (type < 0 || type > SoundType::Effects)
+            return;
+        this->volume_[type] = vol;
+        this->checkVolumeValidity(type);
+    }
+
+    float SoundManager::getVolume(SoundType::Value type)
+    {
+        if (type < 0 || type > SoundType::Effects)
+            return 0.0f;
+        return this->volume_[type];
+    }
+
+    float SoundManager::getRealVolume(SoundType::Value type)
+    {
+        if (type != SoundType::Music && type != SoundType::Effects)
+            return 0.0f;
+        return this->volume_[SoundType::All] * this->mute_[SoundType::All] * this->volume_[type] * this->mute_[type];
+    }
+
+    void SoundManager::updateVolume(SoundType::Value type)
+    {
+        switch(type)
+        {
+        case SoundType::All:
+            for (ObjectList<BaseSound>::iterator it = ObjectList<BaseSound>::begin(); it != ObjectList<BaseSound>::end(); ++it)
+                (*it)->updateVolume();
+            break;
+        case SoundType::Music:
+            for (ObjectList<AmbientSound>::iterator it = ObjectList<AmbientSound>::begin(); it != ObjectList<AmbientSound>::end(); ++it)
+                (*it)->updateVolume();
+            break;
+        case SoundType::Effects:
+            for (ObjectList<WorldSound>::iterator it = ObjectList<WorldSound>::begin(); it != ObjectList<WorldSound>::end(); ++it)
+                (*it)->updateVolume();
+            break;
+        default:
+            assert(false);
+        }
+    }
+
+    void SoundManager::toggleMute(SoundType::Value type)
+    {
+        if (type < 0 || type > SoundType::Effects)
+            return;
+        this->mute_[type] = (this->mute_[type] == 0) ? 1.0f : 0.0f;
+        this->updateVolume(type);
+    }
+
+    bool SoundManager::getMute(SoundType::Value type)
+    {
+        if (type < 0 || type > SoundType::Effects)
+            return true;
+        return (this->mute_[type] == 0);
     }
 
@@ -103,14 +330,310 @@
     {
         // update listener orientation
-        Vector3 up = orientation.xAxis(); // just a wild guess
-        Vector3 at = orientation.zAxis();
-
-        ALfloat orient[6] = { at.x, at.y, at.z,
-                              up.x, up.y, up.z };
-
-        alListenerfv(AL_POSITION, orient);
+        const Vector3& direction = -orientation.zAxis();
+        const Vector3& up = orientation.yAxis();
+
+        ALfloat orient[6] = { direction.x, direction.y, direction.z, up.x, up.y, up.z };
+
+        alListenerfv(AL_ORIENTATION, orient);
         ALenum error = alGetError();
         if (error == AL_INVALID_VALUE)
             COUT(2) << "Sound: OpenAL: Invalid listener orientation" << std::endl;
     }
+
+    void SoundManager::registerAmbientSound(AmbientSound* newAmbient)
+    {
+        if (newAmbient != NULL)
+        {
+            for (AmbientList::const_iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
+            {
+                if (it->first == newAmbient)
+                {
+                    COUT(2) << "Sound warning: Will not play an AmbientSound twice." << std::endl;
+                    return;
+                }
+            }
+
+            if (!this->ambientSounds_.empty())
+            {
+                this->fadeOut(ambientSounds_.front().first);
+            }
+            this->ambientSounds_.push_front(std::make_pair(newAmbient, false));
+            newAmbient->doPlay();
+            this->fadeIn(newAmbient);
+        }
+    }
+
+    void SoundManager::unregisterAmbientSound(AmbientSound* oldAmbient)
+    {
+        if (oldAmbient == NULL || ambientSounds_.empty())
+            return;
+
+        if (this->ambientSounds_.front().first == oldAmbient)
+        {
+            this->fadeOut(oldAmbient);
+            this->ambientSounds_.pop_front();
+            if (!this->ambientSounds_.empty())
+            {
+                if (!this->ambientSounds_.front().second) // Not paused before
+                {
+                    this->ambientSounds_.front().first->doPlay();
+                }
+                this->fadeIn(this->ambientSounds_.front().first);
+            }
+        }
+        else
+        {
+            for (AmbientList::iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
+            {
+                if (it->first == oldAmbient)
+                {
+                    this->fadeOut(oldAmbient);
+                    this->ambientSounds_.erase(it);
+                    break;
+                }
+            }
+        }
+    }
+
+    void SoundManager::pauseAmbientSound(AmbientSound* ambient)
+    {
+        if (ambient != NULL)
+        {
+            for (AmbientList::iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
+            {
+                if (it->first == ambient)
+                {
+                    it->second = true;
+                    this->fadeOut(it->first);
+                    return;
+                }
+            }
+        }
+    }
+
+    void SoundManager::fadeIn(const SmartPtr<AmbientSound>& sound)
+    {
+        // If we're already fading out --> remove that
+        for (std::list<SmartPtr<AmbientSound> >::iterator it = this->fadeOutList_.begin(); it != this->fadeOutList_.end(); it++)
+        {
+            if (*it == sound)
+            {
+                this->fadeOutList_.erase(it);
+                break;
+            }
+        }
+        // No duplicate entries
+        if (std::find(this->fadeInList_.begin(), this->fadeInList_.end(), sound) == this->fadeInList_.end())
+            this->fadeInList_.push_back(sound);
+    }
+
+    void SoundManager::fadeOut(const SmartPtr<AmbientSound>& sound)
+    {
+        // If we're already fading in --> remove that
+        for (std::list<SmartPtr<AmbientSound> >::iterator it = this->fadeInList_.begin(); it != this->fadeInList_.end(); it++)
+        {
+            if (*it == sound)
+            {
+                this->fadeInList_.erase(it);
+                break;
+            }
+        }
+        // No duplicate entries
+        if (std::find(this->fadeOutList_.begin(), this->fadeOutList_.end(), sound) == this->fadeOutList_.end())
+            this->fadeOutList_.push_back(sound);
+    }
+
+    void SoundManager::processCrossFading(float dt)
+    {
+
+        // Hacky solution to the fade delay while loading a level.
+        if(dt > 0.2)
+        {
+            return;
+        }
+
+        // FADE IN
+        for (std::list<SmartPtr<AmbientSound> >::iterator it= this->fadeInList_.begin(); it != this->fadeInList_.end(); )
+        {
+            if ((*it)->getVolume() + this->crossFadeStep_*dt > 1.0f)
+            {
+                (*it)->setVolume(1.0f);
+                this->fadeInList_.erase(it++);
+            }
+            else
+            {
+                (*it)->setVolume((*it)->getVolume() + this->crossFadeStep_*dt);
+                ++it;
+            }
+        }
+
+        // FADE OUT
+        for (std::list<SmartPtr<AmbientSound> >::iterator it = this->fadeOutList_.begin(); it != this->fadeOutList_.end(); )
+        {
+            if ((*it)->getVolume() - this->crossFadeStep_*dt < 0.0f)
+            {
+                (*it)->setVolume(0.0f);
+
+                // If sound is in the ambient list --> pause
+                for (AmbientList::const_iterator it2 = this->ambientSounds_.begin(); it2 != this->ambientSounds_.end(); ++it2)
+                {
+                    if (it2->first == *it)
+                    {
+                        (*it)->doPause();
+                        break;
+                    }
+                }
+                // If not pause (by loop above for instance) --> stop
+                if (!(*it)->isPaused())
+                    (*it)->doStop();
+
+                this->fadeOutList_.erase(it++);
+            }
+            else
+            {
+                (*it)->setVolume((*it)->getVolume() - this->crossFadeStep_*dt);
+                ++it;
+            }
+        }
+    }
+
+    shared_ptr<SoundBuffer> SoundManager::getSoundBuffer(const std::string& filename)
+    {
+        shared_ptr<SoundBuffer> buffer;
+        // Check active or pooled buffers
+        SoundBufferMap::const_iterator it = this->soundBuffers_.find(filename);
+        if (it != this->soundBuffers_.end())
+        {
+            buffer = it->second;
+
+            // Remove from effects pool if not active used before
+            if (buffer->poolIterator_ != this->effectsPool_.end())
+            {
+                this->effectsPoolSize_ -= buffer->getSize();
+                this->effectsPool_.erase(buffer->poolIterator_);
+                buffer->poolIterator_ = this->effectsPool_.end();
+            }
+        }
+        else
+        {
+            try
+            {
+                buffer.reset(new SoundBuffer(filename, this->effectsPool_.end()));
+            }
+            catch (...)
+            {
+                COUT(1) << Exception::handleMessage() << std::endl;
+                return buffer;
+            }
+            this->soundBuffers_[filename] = buffer;
+        }
+        return buffer;
+    }
+
+    void SoundManager::releaseSoundBuffer(const shared_ptr<SoundBuffer>& buffer, bool bPoolBuffer)
+    {
+        // Check if others are still using the buffer
+        if (buffer.use_count() != 2)
+            return;
+        SoundBufferMap::iterator it = this->soundBuffers_.find(buffer->getFilename());
+        if (it != this->soundBuffers_.end())
+        {
+            if (bPoolBuffer)
+            {
+                // Pool already too large?
+                while (this->effectsPoolSize_ + it->second->getSize() > this->maxEffectsPoolSize_s && !this->effectsPool_.empty())
+                {
+                    shared_ptr<SoundBuffer> bufferDel = this->effectsPool_.back();
+                    this->effectsPoolSize_ -= bufferDel->getSize();
+                    bufferDel->poolIterator_ = this->effectsPool_.end();
+                    this->effectsPool_.pop_back();
+                    // Remove from buffer map too
+                    SoundBufferMap::iterator itDel = this->soundBuffers_.find(bufferDel->getFilename());
+                    if (itDel != this->soundBuffers_.end())
+                        this->soundBuffers_.erase(itDel);
+                }
+                // Put buffer into the pool
+                this->effectsPoolSize_ += it->second->getSize();
+                this->effectsPool_.push_front(it->second);
+                it->second->poolIterator_ = this->effectsPool_.begin();
+            }
+            else
+                this->soundBuffers_.erase(it);
+        }
+    }
+
+    ALuint SoundManager::getSoundSource(BaseSound* object)
+    {
+        if (!this->availableSoundSources_.empty())
+        {
+            ALuint source = this->availableSoundSources_.back();
+            this->availableSoundSources_.pop_back();
+            this->usedSoundSources_.push_back(std::make_pair(source, object));
+            return source;
+        }
+        else
+        {
+            if (this->usedSoundSources_.size() < this->maxSources_)
+            {
+                ALuint source;
+                alGenSources(1, &source);
+                // Try to create new sources (50% more, but at least one)
+                if (alIsSource(source) && !alGetError())
+                {
+                    this->usedSoundSources_.push_back(std::make_pair(source, object));
+                    return source;
+                }
+            }
+            // Return no source ID
+            ALuint source = 123456789;
+            while (alIsSource(++source));
+            return source;
+        }
+    }
+
+    void SoundManager::releaseSoundSource(ALuint source)
+    {
+#ifndef NDEBUG
+        for (std::vector<ALuint>::const_iterator it = this->availableSoundSources_.begin(); it != this->availableSoundSources_.end(); ++it)
+            assert((*it) != source);
+#endif
+        this->availableSoundSources_.push_back(source);
+        for (std::vector<std::pair<ALuint, BaseSound*> >::iterator it = this->usedSoundSources_.begin();
+            it != this->usedSoundSources_.end(); ++it)
+        {
+            if (it->first == source)
+            {
+                this->usedSoundSources_.erase(it);
+                break;
+            }
+        }
+        int used = std::max(this->usedSoundSources_.size(), this->minSources_);
+        // Subtract those we added in the statement above trough std::max
+        int available = (int)this->availableSoundSources_.size() - (used - (int)this->usedSoundSources_.size());
+        // Delete sources again to free resources if appropriate (more than 50% more available than used)
+        int toDelete = available - used / 2;
+        while (toDelete-- > 0)
+        {
+            alDeleteSources(1, &this->availableSoundSources_.back());
+            if (alGetError())
+                COUT(1) << "Sound Error: Failed to delete a source --> lost forever" << std::endl;
+            this->availableSoundSources_.pop_back();
+        }
+    }
+
+    unsigned int SoundManager::createSoundSources(unsigned int n)
+    {
+        unsigned int count = this->availableSoundSources_.size() + this->usedSoundSources_.size();
+        while (count < this->maxSources_ && count <= n)
+        {
+            ALuint source;
+            alGenSources(1, &source);
+            if (alIsSource(source) && !alGetError())
+                this->availableSoundSources_.push_back(source);
+            else
+                break;
+            ++count;
+        }
+        return count - this->availableSoundSources_.size() - this->usedSoundSources_.size();
+    }
 }
Index: code/branches/pickup2/src/orxonox/sound/SoundManager.h
===================================================================
--- code/branches/pickup2/src/orxonox/sound/SoundManager.h	(revision 5942)
+++ code/branches/pickup2/src/orxonox/sound/SoundManager.h	(revision 6412)
@@ -22,7 +22,10 @@
  *   Author:
  *       Erwin 'vaiursch' Herrsche
+ *       Kevin Young
+ *       Reto Grieder
  *   Co-authors:
  *      ...
  */
+
 #ifndef _SoundManager_H__
 #define _SoundManager_H__
@@ -30,33 +33,121 @@
 #include "OrxonoxPrereqs.h"
 
-#include <cassert>
 #include <list>
+#include <map>
+#include <string>
+#include <boost/shared_ptr.hpp>
+
 #include "util/Singleton.h"
-#include "tools/interfaces/Tickable.h"
+#include "core/OrxonoxClass.h"
+#include "core/SmartPtr.h"
 
+// tolua_begin
 namespace orxonox
 {
-    /**
-     * The SoundManager class manages the OpenAL device, context and listener
-     * position. It is a singleton.
-     *
-     */
-    class _OrxonoxExport SoundManager : public Singleton<SoundManager>
+    //! Enum for the sound type.
+    namespace SoundType
     {
+        enum Value
+        {
+            All     = 0,
+            Music   = 1,
+            Effects = 2
+        };
+    }
+
+    //! The SoundManager class manages the OpenAL device, context and listener position.
+    class _OrxonoxExport SoundManager
+    // tolua_end
+        : public Singleton<SoundManager>, public OrxonoxClass
+    { // tolua_export
         friend class Singleton<SoundManager>;
+
     public:
         SoundManager();
         ~SoundManager();
 
+        void preUpdate(const Clock& time);
+        void setConfigValues();
+
+        // tolua_begin
+        static SoundManager& getInstance() { return Singleton<SoundManager>::getInstance(); }
+
+        std::string getDeviceName(unsigned int index) const
+            { return index < this->deviceNames_.size() ? this->deviceNames_[index] : std::string(); }
+        // tolua_end
+
         void setListenerPosition(const Vector3& position);
         void setListenerOrientation(const Quaternion& orientation);
 
+        void registerAmbientSound(AmbientSound* newAmbient);
+        void unregisterAmbientSound(AmbientSound* oldAmbient);
+        void pauseAmbientSound(AmbientSound* ambient);
+
+        // tolua_begin
+        void setVolume(float vol, SoundType::Value type);
+        float getVolume(SoundType::Value type);
+        float getRealVolume(SoundType::Value type);
+
+        void toggleMute(SoundType::Value type);
+        bool getMute(SoundType::Value type);
+        // tolua_end
+
+        shared_ptr<SoundBuffer> getSoundBuffer(const std::string& filename);
+        void releaseSoundBuffer(const shared_ptr<SoundBuffer>& buffer, bool bPoolBuffer);
+
+        ALuint getSoundSource(BaseSound* object);
+        void releaseSoundSource(ALuint source);
+
+        static std::string getALErrorString(ALenum error);
+
     private:
+        void processCrossFading(float dt);
+        void fadeIn(const SmartPtr<AmbientSound>& sound);
+        void fadeOut(const SmartPtr<AmbientSound>& sound);
+
+        void checkFadeStepValidity();
+
+        void checkVolumeValidity(SoundType::Value type);
+        void checkSoundVolumeValidity()   { this->checkVolumeValidity(SoundType::All); }
+        void checkAmbientVolumeValidity() { this->checkVolumeValidity(SoundType::Music); }
+        void checkEffectsVolumeValidity() { this->checkVolumeValidity(SoundType::Effects); }
+        void updateVolume(SoundType::Value type);
+
+        unsigned int createSoundSources(unsigned int n);
+
+        // OpenAL device/context related
+        std::vector<std::string> deviceNames_;
         ALCdevice* device_;
         ALCcontext* context_;
 
+        // Ambient sound related
+        typedef std::list<std::pair<AmbientSound*, bool> > AmbientList;
+        AmbientList                        ambientSounds_;
+        //! Absolute change per second (0.1 means 10% of the nominal volume) for cross fading
+        float                              crossFadeStep_;
+        std::list<SmartPtr<AmbientSound> > fadeInList_;
+        std::list<SmartPtr<AmbientSound> > fadeOutList_;
+
+        // Volume related
+        float volume_[3];
+        float mute_[3];
+
+        // Sound buffer related
+        static const unsigned int maxEffectsPoolSize_s = 40 * 1024 * 1024;
+        unsigned int effectsPoolSize_;
+        typedef std::list<shared_ptr<SoundBuffer> > EffectsPoolList;
+        EffectsPoolList effectsPool_;
+        typedef std::map<std::string, shared_ptr<SoundBuffer> > SoundBufferMap;
+        SoundBufferMap soundBuffers_;
+
+        // Sound source related
+        unsigned int minSources_;
+        unsigned int maxSources_;
+        std::vector<ALuint> availableSoundSources_;
+        std::vector<std::pair<ALuint, BaseSound*> > usedSoundSources_;
+
         static SoundManager* singletonPtr_s;
-    };
-}
+    }; // tolua_export
+} // tolua_export
 
 #endif /* _SoundManager_H__ */
Index: code/branches/pickup2/src/orxonox/sound/SoundStreamer.cc
===================================================================
--- code/branches/pickup2/src/orxonox/sound/SoundStreamer.cc	(revision 6412)
+++ code/branches/pickup2/src/orxonox/sound/SoundStreamer.cc	(revision 6412)
@@ -0,0 +1,128 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Erwin 'vaiursch' Herrsche
+ *   Co-authors:
+ *
+ */
+#include "SoundStreamer.h"
+
+#include <al.h>
+#include <vorbis/vorbisfile.h>
+#include "SoundManager.h"
+
+namespace orxonox
+{
+    // vorbis callbacks
+    size_t readVorbis(void* ptr, size_t size, size_t nmemb, void* datasource);
+    int seekVorbis(void* datasource, ogg_int64_t offset, int whence);
+    long tellVorbis(void* datasource);
+
+    void orxonox::SoundStreamer::operator()(ALuint audioSource, DataStreamPtr dataStream)
+    {
+        // Open file with custom streaming
+        ov_callbacks vorbisCallbacks;
+        vorbisCallbacks.read_func  = &readVorbis;
+        vorbisCallbacks.seek_func  = &seekVorbis;
+        vorbisCallbacks.tell_func  = &tellVorbis;
+        vorbisCallbacks.close_func = NULL;
+
+        OggVorbis_File vf;
+        int ret = ov_open_callbacks(dataStream.get(), &vf, NULL, 0, vorbisCallbacks);
+        if (ret < 0)
+        {
+            COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
+            ov_clear(&vf);
+            return;
+        }
+        vorbis_info* vorbisInfo;
+        vorbisInfo = ov_info(&vf, -1);
+        ALenum format;
+        if (vorbisInfo->channels == 1)
+            format = AL_FORMAT_MONO16;
+        else
+            format = AL_FORMAT_STEREO16;
+
+        char inbuffer[256*1024];
+        ALuint initbuffers[4];
+        alGenBuffers(4, initbuffers);
+        int current_section;
+
+        for(int i = 0; i < 4; i++)
+        {
+            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
+            if (ret == 0)
+            {
+                return;
+            }
+            else if (ret < 0)
+            {
+                COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
+                ov_clear(&vf);
+                return;
+            }
+
+            alBufferData(initbuffers[i], format, &inbuffer, ret, vorbisInfo->rate);
+        }
+        alSourceQueueBuffers(audioSource, 4, initbuffers);
+
+        while(true) // Stream forever, control through thread control
+        {
+            int processed;
+            alGetSourcei(audioSource, AL_BUFFERS_PROCESSED, &processed);
+            if (ALint error = alGetError())
+            COUT(2) << "Sound Warning: Couldn't get number of processed buffers: "
+                    << SoundManager::getALErrorString(error) << std::endl;
+
+            if(processed > 0)
+            {
+                ALuint* buffers = new ALuint[processed];
+                alSourceUnqueueBuffers(audioSource, processed, buffers);
+                if (ALint error = alGetError())
+                    COUT(2) << "Sound Warning: Couldn't unqueue buffers: "
+                    << SoundManager::getALErrorString(error) << std::endl;
+
+                for(int i = 0; i < processed; i++)
+                {
+                    long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
+                    if (ret == 0)
+                    {
+                        return;
+                    }
+                    else if (ret < 0)
+                    {
+                        COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
+                        ov_clear(&vf);
+                        return;
+                    }
+
+                    alBufferData(buffers[i], format, &inbuffer, ret, vorbisInfo->rate);
+                }
+
+                alSourceQueueBuffers(audioSource, processed, buffers);
+                if (ALint error = alGetError())
+                    COUT(2) << "Sound Warning: Couldn't queue buffers: "
+                    << SoundManager::getALErrorString(error) << std::endl;
+            }
+        }
+    }
+}
Index: code/branches/pickup2/src/orxonox/sound/SoundStreamer.h
===================================================================
--- code/branches/pickup2/src/orxonox/sound/SoundStreamer.h	(revision 6412)
+++ code/branches/pickup2/src/orxonox/sound/SoundStreamer.h	(revision 6412)
@@ -0,0 +1,46 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Erwin 'vaiursch' Herrsche
+ *   Co-authors:
+ *
+ */
+
+#ifndef _SoundStreamer_H__
+#define _SoundStreamer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <OgreDataStream.h>
+#include "core/CorePrereqs.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport SoundStreamer // class for stream threads
+    {
+    public:
+        void operator()(ALuint audioSource, DataStreamPtr dataStream);
+    };
+}
+
+#endif /* _SoundStreamer_H__ */
Index: code/branches/pickup2/src/orxonox/sound/WorldSound.cc
===================================================================
--- code/branches/pickup2/src/orxonox/sound/WorldSound.cc	(revision 5942)
+++ code/branches/pickup2/src/orxonox/sound/WorldSound.cc	(revision 6412)
@@ -35,4 +35,7 @@
 #include "core/EventIncludes.h"
 #include "core/XMLPort.h"
+#include "Scene.h"
+#include "SoundManager.h"
+#include <core/ConsoleCommandCompilation.h>
 
 namespace orxonox
@@ -44,8 +47,16 @@
     {
         RegisterObject(WorldSound);
+        // WorldSound buffers should be pooled when they're not used anymore
+        this->bPooling_ = true;
+        this->registerVariables();
     }
 
-    WorldSound::~WorldSound()
+    void WorldSound::registerVariables()
     {
+        registerVariable(volume_,   ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::volumeChanged));
+        registerVariable(source_,   ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::sourceChanged));
+        registerVariable(bLooping_, ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::loopingChanged));
+        registerVariable(pitch_,    ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::pitchChanged));
+        registerVariable((int&)(BaseSound::state_), ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::stateChanged));
     }
 
@@ -53,7 +64,5 @@
     {
         SUPER(WorldSound, XMLPort, xmlelement, mode);
-        XMLPortParamExtern(WorldSound, BaseSound, this, "source", setSource, getSource, xmlelement, mode);
-        XMLPortParamExtern(WorldSound, BaseSound, this, "loop", setLoop, getLoop, xmlelement, mode);
-        XMLPortParamExtern(WorldSound, BaseSound, this, "playOnLoad", setPlayOnLoad, getPlayOnLoad, xmlelement, mode);
+        BaseSound::XMLPortExtern(xmlelement, mode);
     }
 
@@ -62,4 +71,17 @@
         SUPER(WorldSound, XMLEventPort, xmlelement, mode);
         XMLPortEventState(WorldSound, BaseObject, "play", play, xmlelement, mode);
+    }
+
+    void WorldSound::initialiseSource()
+    {
+        BaseSound::initialiseSource();
+        if (this->getScene())
+        {
+            float refDist = this->getScene()->getSoundReferenceDistance();
+            alSourcef(this->audioSource_, AL_REFERENCE_DISTANCE, refDist);
+            // TODO: 500 is very magical here. Derive something better
+            alSourcef(this->audioSource_, AL_MAX_DISTANCE, refDist * 500);
+        }
+        this->tick(0); // update position, orientation and velocity
     }
 
@@ -80,7 +102,6 @@
                 COUT(2) << "Sound: OpenAL: Invalid sound velocity" << std::endl;
 
-            const Quaternion& orient = this->getWorldOrientation();
-            Vector3 at = orient.zAxis();
-            alSource3f(this->audioSource_, AL_DIRECTION, at.x, at.y, at.z);
+            const Vector3& direction = -this->getWorldOrientation().zAxis();
+            alSource3f(this->audioSource_, AL_DIRECTION, direction.x, direction.y, direction.z);
             error = alGetError();
             if (error == AL_INVALID_VALUE)
@@ -89,3 +110,17 @@
     }
 
+    void WorldSound::changedActivity()
+    {
+        SUPER(WorldSound, changedActivity);
+        if (this->isActive())
+            this->play();
+        else
+            this->stop();
+    }
+
+    float WorldSound::getRealVolume()
+    {
+        assert(GameMode::playsSound());
+        return SoundManager::getInstance().getRealVolume(SoundType::Effects);
+    }
 }
Index: code/branches/pickup2/src/orxonox/sound/WorldSound.h
===================================================================
--- code/branches/pickup2/src/orxonox/sound/WorldSound.h	(revision 5942)
+++ code/branches/pickup2/src/orxonox/sound/WorldSound.h	(revision 6412)
@@ -26,4 +26,5 @@
  *
  */
+
 #ifndef _WorldSound_H__
 #define _WorldSound_H__
@@ -45,12 +46,18 @@
     public:
         WorldSound(BaseObject* creator);
-        virtual ~WorldSound();
 
-        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
-        virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+        void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+        void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+        void changedActivity();
 
-        virtual void tick(float dt);
+        void tick(float dt);
+
+    protected:
+        ~WorldSound() {}
 
     private:
+        void registerVariables();
+        void initialiseSource();
+        float getRealVolume();
     };
 }
