Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation2/src/orxonox/sound/BaseSound.cc @ 6327

Last change on this file since 6327 was 6327, checked in by rgrieder, 14 years ago

Engine synchronisation seems to work more or less.
Fire sound still doesn't work on client.

  • Property svn:eol-style set to native
File size: 8.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 "core/CoreIncludes.h"
36#include "core/GameMode.h"
37#include "core/Resource.h"
38#include "core/XMLPort.h"
39#include "SoundBuffer.h"
40#include "SoundManager.h"
41
42namespace orxonox
43{
44    BaseSound::BaseSound()
45        : bPooling_(false)
46        , volume_(1.0)
47        , bLooping_(false)
48        , state_(Stopped)
49        , pitch_ (1.0)
50    {
51        RegisterRootObject(BaseSound);
52
53        // Initialise audioSource_ to a value that is not a source
54        // 0 is unfortunately not guaranteed to be no source ID.
55        this->audioSource_ = 123456789;
56        while (alIsSource(++this->audioSource_));
57    }
58
59    BaseSound::~BaseSound()
60    {
61        this->stop();
62    }
63
64    void BaseSound::XMLPortExtern(Element& xmlelement, XMLPort::Mode mode)
65    {
66        XMLPortParam(BaseSound, "volume", setVolume,  getVolume,  xmlelement, mode);
67        XMLPortParam(BaseSound, "loop",   setLooping, getLooping, xmlelement, mode);
68        XMLPortParam(BaseSound, "play",   setPlaying, isPlaying,  xmlelement, mode);
69        XMLPortParam(BaseSound, "source", setSource,  getSource,  xmlelement, mode);
70    }
71
72    void BaseSound::play()
73    {
74        this->state_ = Playing;
75        if (GameMode::playsSound() && this->getSourceState() != AL_PLAYING && this->soundBuffer_ != NULL)
76        {
77            if (!alIsSource(this->audioSource_))
78                this->audioSource_ = SoundManager::getInstance().getSoundSource();
79            if (!alIsSource(this->audioSource_))
80                return;
81            this->initialiseSource();
82
83            alSourcePlay(this->audioSource_);
84            if (int error = alGetError())
85                COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
86        }
87    }
88
89    void BaseSound::stop()
90    {
91        this->state_ = Stopped;
92        if (alIsSource(this->audioSource_))
93        {
94            alSourceStop(this->audioSource_);
95            // Release buffer
96            alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
97            // Release source again
98            SoundManager::getInstance().releaseSoundSource(this->audioSource_);
99            // Get a no source ID
100            this->audioSource_ += 123455;
101            while (alIsSource(++this->audioSource_));
102        }
103    }
104
105    void BaseSound::pause()
106    {
107        if (this->isStopped())
108            return;
109        this->state_ = Paused;
110        if (alIsSource(this->audioSource_))
111            alSourcePause(this->audioSource_);
112    }
113
114    ALint BaseSound::getSourceState() const
115    {
116        if (alIsSource(this->audioSource_))
117        {
118            ALint state;
119            alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
120            return state;
121        }
122        else
123            return AL_INITIAL;
124    }
125
126    void BaseSound::initialiseSource()
127    {
128        this->updateVolume();
129        this->setPitch(this->getPitch());
130        this->setLooping(this->getLooping());
131        alSource3f(this->audioSource_, AL_POSITION,  0, 0, 0);
132        alSource3f(this->audioSource_, AL_VELOCITY,  0, 0, 0);
133        alSource3f(this->audioSource_, AL_DIRECTION, 0, 0, 0);
134        alSourcei(this->audioSource_, AL_REFERENCE_DISTANCE, 20);
135        alSourcei(this->audioSource_, AL_MAX_DISTANCE, 10000);
136        if (ALint error = alGetError())
137            COUT(2) << "Sound Warning: Setting source parameters to 0 failed: "
138                    << SoundManager::getALErrorString(error) << std::endl;
139        assert(this->soundBuffer_ != NULL);
140        alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
141        if (ALuint error = alGetError())
142            COUT(1) << "Sound Error: Could not set buffer \"" << this->source_ << "\": " << SoundManager::getALErrorString(error) << std::endl;
143    }
144
145    void BaseSound::setVolume(float vol)
146    {
147        if (vol > 1 || vol < 0)
148        {
149            COUT(2) << "Sound warning: volume out of range, cropping value." << std::endl;
150            vol = vol > 1 ? 1 : vol;
151            vol = vol < 0 ? 0 : vol;
152        }
153        this->volume_ = vol;
154       
155        this->updateVolume();
156    }
157   
158    float BaseSound::getVolumeGain()
159    {
160        assert(GameMode::playsSound());
161        return SoundManager::getInstance().getVolume(SoundType::none);
162    }
163   
164    void BaseSound::updateVolume(void)
165    {
166        if (alIsSource(this->audioSource_))
167        {
168            float volume = this->volume_ * this->getVolumeGain();
169            alSourcef(this->audioSource_, AL_GAIN, volume);
170            if (int error = alGetError())
171                COUT(2) << "Sound: Error setting volume to " << volume
172                        << ": " << SoundManager::getALErrorString(error) << std::endl;
173        }
174    }
175
176    void BaseSound::setLooping(bool val)
177    {
178        this->bLooping_ = val;
179        if (alIsSource(this->audioSource_))
180            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
181    }
182
183    void BaseSound::setPitch(float pitch)
184    {
185        if (pitch > 2 || pitch < 0.5)
186        {
187            COUT(2) << "Sound warning: pitch out of range, cropping value." << std::endl;
188            pitch = pitch > 2 ? 2 : pitch;
189            pitch = pitch < 0.5 ? 0.5 : pitch;
190        }       
191        this->pitch_ = pitch;
192        if (alIsSource(this->audioSource_))
193        {
194            if (int error = alGetError())
195                COUT(2) << "Sound: Error setting pitch: " << SoundManager::getALErrorString(error) << std::endl;
196            alSourcef(this->audioSource_, AL_PITCH, pitch);
197        }
198    }
199
200    void BaseSound::setSource(const std::string& source)
201    {
202        if (!GameMode::playsSound())
203        {
204            this->source_ = source;
205            return;
206        }
207
208        if (this->soundBuffer_ != NULL)
209        {
210            if (this->soundBuffer_->getFilename() == source)
211            {
212                assert(this->source_ == source_);
213                return;
214            }
215            // Stopping is imperative here!
216            if (alIsSource(this->audioSource_))
217            {
218                alSourceStop(this->audioSource_);
219                alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
220            }
221            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
222            this->soundBuffer_.reset();
223        }
224
225        this->source_ = source;
226        if (source_.empty())
227            return;
228
229        this->soundBuffer_ = SoundManager::getInstance().getSoundBuffer(this->source_);
230        if (this->soundBuffer_ == NULL)
231            return;
232
233        if (alIsSource(this->audioSource_))
234        {
235            alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
236            if (ALuint error = alGetError())
237            {
238                COUT(1) << "Sound Error: Could not set buffer \"" << source << "\": " << SoundManager::getALErrorString(error) << std::endl;
239                return;
240            }
241
242            if (this->isPlaying() || this->isPaused())
243            {
244                alSourcePlay(this->audioSource_);
245                if (int error = alGetError())
246                    COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
247            }
248            if (this->isPaused())
249                alSourcePause(this->audioSource_);
250        }
251    }
252   
253    void BaseSound::stateChanged()
254    {
255        switch (this->state_)
256        {
257            case Playing:
258                this->play();
259                break;
260            case Paused:
261                this->pause();
262                break;
263            case Stopped:
264            default:
265                this->stop();
266                break;
267        }
268    }
269}
Note: See TracBrowser for help on using the repository browser.