Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/sound4/src/orxonox/sound/BaseSound.cc @ 6476

Last change on this file since 6476 was 6435, checked in by rgrieder, 15 years ago

Moved getALErrorString function from SoundManager.h to newly created SoundPrereqs.h file.
Also moved forward declarations to that file (from OrxonoxPrereqs.h).

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