Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8516 was 8514, checked in by youngk, 13 years ago

Testing commit: Sound

  • Property svn:eol-style set to native
File size: 9.5 KB
Line 
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:
23 *      Erwin 'vaiursch' Herrsche
24 *   Co-authors:
25 *      Reto Grieder
26 *
27 */
28
29#include "BaseSound.h"
30
31#include <cassert>
32#include <vector>
33#include <al.h>
34
35#include "util/Math.h"
36#include "core/CoreIncludes.h"
37#include "core/GameMode.h"
38#include "core/Resource.h"
39#include "core/XMLPort.h"
40#include "SoundBuffer.h"
41#include "SoundManager.h"
42
43namespace orxonox
44{
45    BaseSound::BaseSound()
46        : bPooling_(false)
47        , volume_(1.0)
48        , bLooping_(false)
49        , state_(Stopped)
50        , pitch_ (1.0)
51    {
52        RegisterRootObject(BaseSound);
53       
54        if (int error = alGetError())
55            COUT(4) << "Sound: Received ALError before alIsSource(): " << SoundManager::getALErrorString(error) << std::endl;
56
57        // Initialise audioSource_ to a value that is not a source
58        // 0 is unfortunately not guaranteed to be no source ID.
59        // HACK!
60        this->audioSource_ = 0;
61        while (alIsSource(++this->audioSource_));
62       
63        if (int error = alGetError())
64            COUT(4) << "Sound: Received ALError after alIsSource(): " << SoundManager::getALErrorString(error) << std::endl;
65    }
66
67    BaseSound::~BaseSound()
68    {
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        }
76    }
77
78    void BaseSound::XMLPortExtern(Element& xmlelement, XMLPort::Mode mode)
79    {
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)
90        {
91            if (!alIsSource(this->audioSource_))
92            {
93                this->audioSource_ = SoundManager::getInstance().getSoundSource(this);
94                if (!alIsSource(this->audioSource_))
95                    return;
96                this->initialiseSource();
97            }
98
99            alSourcePlay(this->audioSource_);
100            if (int error = alGetError())
101                COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
102        }
103    }
104
105    bool BaseSound::doStop()
106    {
107        this->state_ = Stopped;
108        if (alIsSource(this->audioSource_))
109        {
110            alSourceStop(this->audioSource_);
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_));
118
119            return true; // sound source destroyed - return true
120        }
121        return false; // nothing done - return false
122    }
123
124    void BaseSound::doPause()
125    {
126        if (this->isStopped())
127            return;
128        this->state_ = Paused;
129        if (alIsSource(this->audioSource_))
130            alSourcePause(this->audioSource_);
131    }
132
133    ALint BaseSound::getSourceState() const
134    {
135        if (alIsSource(this->audioSource_))
136        {
137            ALint state;
138            alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
139            return state;
140        }
141        else
142            return AL_INITIAL;
143    }
144
145    void BaseSound::initialiseSource()
146    {
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    {
172        if (alIsSource(this->audioSource_))
173        {
174            float volume = this->volume_ * this->getRealVolume();               
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        }
180    }
181
182    void BaseSound::setLooping(bool val)
183    {
184        this->bLooping_ = val;
185        if (alIsSource(this->audioSource_))
186            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
187    }
188
189    void BaseSound::setPitch(float pitch)
190    {
191        if (pitch > 2 || pitch < 0.5f)
192        {
193            COUT(2) << "Sound warning: pitch out of range, cropping value." << std::endl;
194            pitch = pitch > 2.0f ? 2.0f : pitch;
195            pitch = pitch < 0.5f ? 0.5f : pitch;
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        }
204    }
205
206    void BaseSound::setSource(const std::string& source)
207    {
208        if (!GameMode::playsSound())
209        {
210            this->source_ = source;
211            return;
212        }
213
214        if (this->soundBuffer_ != NULL)
215        {
216            if (this->soundBuffer_->getFilename() == source)
217            {
218                assert(this->source_ == source_);
219                return;
220            }
221            // Stopping is imperative here!
222            if (alIsSource(this->audioSource_))
223            {
224                alSourceStop(this->audioSource_);
225                alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
226            }
227            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
228            this->soundBuffer_.reset();
229        }
230
231        this->source_ = source;
232        // Don't load ""
233        if (source_.empty())
234            return;
235
236        // Get new sound buffer
237        this->soundBuffer_ = SoundManager::getInstance().getSoundBuffer(this->source_);
238        if (this->soundBuffer_ == NULL)
239            return;
240
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            }
250
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_);
258        }
259        else // No source acquired so far, but might be set to playing or paused
260        {
261            State state = static_cast<State>(this->state_); // save
262            if (this->isPlaying() || this->isPaused())
263                doPlay();
264            if (state == Paused)
265            {
266                this->state_ = Paused;
267                doPause();
268            }
269        }
270    }
271
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        }
287    }
288}
Note: See TracBrowser for help on using the repository browser.