Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/sound/BaseSound.cc @ 8520

Last change on this file since 8520 was 8514, checked in by youngk, 14 years ago

Testing commit: Sound

  • Property svn:eol-style set to native
File size: 9.5 KB
RevLine 
[3060]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
[5896]23 *      Erwin 'vaiursch' Herrsche
[3060]24 *   Co-authors:
[5896]25 *      Reto Grieder
[3060]26 *
27 */
[3196]28
[5896]29#include "BaseSound.h"
[3196]30
[6417]31#include <cassert>
[3060]32#include <vector>
[6417]33#include <al.h>
[3060]34
[7163]35#include "util/Math.h"
[5896]36#include "core/CoreIncludes.h"
37#include "core/GameMode.h"
[5695]38#include "core/Resource.h"
[6417]39#include "core/XMLPort.h"
40#include "SoundBuffer.h"
41#include "SoundManager.h"
[3060]42
[5738]43namespace orxonox
[3060]44{
[5896]45    BaseSound::BaseSound()
[6417]46        : bPooling_(false)
47        , volume_(1.0)
48        , bLooping_(false)
49        , state_(Stopped)
50        , pitch_ (1.0)
[3060]51    {
[5896]52        RegisterRootObject(BaseSound);
[8514]53       
54        if (int error = alGetError())
55            COUT(4) << "Sound: Received ALError before alIsSource(): " << SoundManager::getALErrorString(error) << std::endl;
[6417]56
57        // Initialise audioSource_ to a value that is not a source
58        // 0 is unfortunately not guaranteed to be no source ID.
[8514]59        // HACK!
60        this->audioSource_ = 0;
[6417]61        while (alIsSource(++this->audioSource_));
[8514]62       
63        if (int error = alGetError())
64            COUT(4) << "Sound: Received ALError after alIsSource(): " << SoundManager::getALErrorString(error) << std::endl;
[3060]65    }
66
[5896]67    BaseSound::~BaseSound()
[3060]68    {
[6417]69        this->stop();
70        // Release buffer
71        if (this->soundBuffer_ != NULL)
72        {
73            assert(GameMode::playsSound());
74            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
75        }
[3060]76    }
77
[6417]78    void BaseSound::XMLPortExtern(Element& xmlelement, XMLPort::Mode mode)
[3060]79    {
[6417]80        XMLPortParam(BaseSound, "volume",  setVolume,  getVolume,  xmlelement, mode);
81        XMLPortParam(BaseSound, "looping", setLooping, getLooping, xmlelement, mode);
82        XMLPortParam(BaseSound, "pitch",   setPitch,   getPitch,   xmlelement, mode);
83        XMLPortParam(BaseSound, "source",  setSource,  getSource,  xmlelement, mode);
84    }
85
86    void BaseSound::doPlay()
87    {
88        this->state_ = Playing;
89        if (GameMode::playsSound() && this->getSourceState() != AL_PLAYING && this->soundBuffer_ != NULL)
[5896]90        {
[6417]91            if (!alIsSource(this->audioSource_))
[3108]92            {
[6417]93                this->audioSource_ = SoundManager::getInstance().getSoundSource(this);
94                if (!alIsSource(this->audioSource_))
95                    return;
96                this->initialiseSource();
[3108]97            }
[6417]98
99            alSourcePlay(this->audioSource_);
100            if (int error = alGetError())
101                COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
[3060]102        }
103    }
104
[7856]105    bool BaseSound::doStop()
[5896]106    {
[6417]107        this->state_ = Stopped;
[5899]108        if (alIsSource(this->audioSource_))
[6417]109        {
[5899]110            alSourceStop(this->audioSource_);
[6417]111            // Release buffer
112            alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
113            // Release source again
114            SoundManager::getInstance().releaseSoundSource(this->audioSource_);
115            // Get a no source ID
116            this->audioSource_ += 123455;
117            while (alIsSource(++this->audioSource_));
[7858]118
[7856]119            return true; // sound source destroyed - return true
[6417]120        }
[7856]121        return false; // nothing done - return false
[3060]122    }
123
[6417]124    void BaseSound::doPause()
[5896]125    {
[6417]126        if (this->isStopped())
127            return;
128        this->state_ = Paused;
[5899]129        if (alIsSource(this->audioSource_))
130            alSourcePause(this->audioSource_);
[3060]131    }
132
[6417]133    ALint BaseSound::getSourceState() const
[5896]134    {
[5899]135        if (alIsSource(this->audioSource_))
[6417]136        {
137            ALint state;
138            alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
139            return state;
140        }
141        else
142            return AL_INITIAL;
[3060]143    }
144
[6417]145    void BaseSound::initialiseSource()
[5896]146    {
[6417]147        this->updateVolume();
148        this->setPitch(this->getPitch());
149        this->setLooping(this->getLooping());
150        alSource3f(this->audioSource_, AL_POSITION,  0, 0, 0);
151        alSource3f(this->audioSource_, AL_VELOCITY,  0, 0, 0);
152        alSource3f(this->audioSource_, AL_DIRECTION, 0, 0, 0);
153        if (ALint error = alGetError())
154            COUT(2) << "Sound Warning: Setting source parameters to 0 failed: "
155                    << SoundManager::getALErrorString(error) << std::endl;
156        assert(this->soundBuffer_ != NULL);
157        alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
158        if (ALuint error = alGetError())
159            COUT(1) << "Sound Error: Could not set buffer \"" << this->source_ << "\": " << SoundManager::getALErrorString(error) << std::endl;
160    }
161
162    void BaseSound::setVolume(float vol)
163    {
164        this->volume_ = clamp(vol, 0.0f, 1.0f);
165        if (this->volume_ != vol)
166            COUT(2) << "Sound warning: volume out of range, clamping value." << std::endl;
167        this->updateVolume();
168    }
169
170    void BaseSound::updateVolume()
171    {
[5899]172        if (alIsSource(this->audioSource_))
[6417]173        {
[8514]174            float volume = this->volume_ * this->getRealVolume();               
[6417]175            alSourcef(this->audioSource_, AL_GAIN, volume);
176            if (int error = alGetError())
177                COUT(2) << "Sound: Error setting volume to " << volume
178                        << ": " << SoundManager::getALErrorString(error) << std::endl;
179        }
[3060]180    }
181
[6417]182    void BaseSound::setLooping(bool val)
[5896]183    {
[6417]184        this->bLooping_ = val;
[5899]185        if (alIsSource(this->audioSource_))
[6417]186            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
[3060]187    }
188
[6417]189    void BaseSound::setPitch(float pitch)
[5896]190    {
[6502]191        if (pitch > 2 || pitch < 0.5f)
[6417]192        {
193            COUT(2) << "Sound warning: pitch out of range, cropping value." << std::endl;
[6502]194            pitch = pitch > 2.0f ? 2.0f : pitch;
195            pitch = pitch < 0.5f ? 0.5f : pitch;
[6417]196        }
197        this->pitch_ = pitch;
198        if (alIsSource(this->audioSource_))
199        {
200            alSourcef(this->audioSource_, AL_PITCH, pitch);
201            if (int error = alGetError())
202                COUT(2) << "Sound: Error setting pitch: " << SoundManager::getALErrorString(error) << std::endl;
203        }
[5896]204    }
205
[5899]206    void BaseSound::setSource(const std::string& source)
[5896]207    {
208        if (!GameMode::playsSound())
[3060]209        {
[6417]210            this->source_ = source;
[5896]211            return;
[3060]212        }
213
[6417]214        if (this->soundBuffer_ != NULL)
[5896]215        {
[6417]216            if (this->soundBuffer_->getFilename() == source)
[5904]217            {
[6417]218                assert(this->source_ == source_);
219                return;
[5904]220            }
[6417]221            // Stopping is imperative here!
222            if (alIsSource(this->audioSource_))
[5904]223            {
[6417]224                alSourceStop(this->audioSource_);
225                alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
[5904]226            }
[6417]227            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
228            this->soundBuffer_.reset();
[3060]229        }
230
[6417]231        this->source_ = source;
232        // Don't load ""
233        if (source_.empty())
[5896]234            return;
235
[6417]236        // Get new sound buffer
237        this->soundBuffer_ = SoundManager::getInstance().getSoundBuffer(this->source_);
238        if (this->soundBuffer_ == NULL)
239            return;
[5896]240
[6417]241        if (alIsSource(this->audioSource_)) // already playing or paused
242        {
243            // Set new buffer
244            alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
245            if (ALuint error = alGetError())
246            {
247                COUT(1) << "Sound Error: Could not set buffer \"" << source << "\": " << SoundManager::getALErrorString(error) << std::endl;
248                return;
249            }
[3060]250
[6417]251            // Sound was already playing or paused because there was a source acquired
252            assert(this->isPlaying() || this->isPaused());
253            alSourcePlay(this->audioSource_);
254            if (int error = alGetError())
255                COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
256            if (this->isPaused())
257                alSourcePause(this->audioSource_);
[3060]258        }
[6417]259        else // No source acquired so far, but might be set to playing or paused
[3060]260        {
[7163]261            State state = static_cast<State>(this->state_); // save
[6417]262            if (this->isPlaying() || this->isPaused())
263                doPlay();
264            if (state == Paused)
[3060]265            {
[6417]266                this->state_ = Paused;
267                doPause();
[3060]268            }
269        }
[6417]270    }
[3060]271
[6417]272    void BaseSound::stateChanged()
273    {
274        switch (this->state_)
275        {
276            case Playing:
277                this->play();
278                break;
279            case Paused:
280                this->pause();
281                break;
282            case Stopped:
283            default:
284                this->stop();
285                break;
286        }
[3060]287    }
[6417]288}
Note: See TracBrowser for help on using the repository browser.