Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6514 was 6411, checked in by rgrieder, 15 years ago

BaseSound should release the buffer upon destruction and the SoundManager should delete all remaining buffers and sources.

  • Property svn:eol-style set to native
File size: 8.9 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: " << SoundManager::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: "
144                    << SoundManager::getALErrorString(error) << std::endl;
145        assert(this->soundBuffer_ != NULL);
146        alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
147        if (ALuint error = alGetError())
148            COUT(1) << "Sound Error: Could not set buffer \"" << this->source_ << "\": " << SoundManager::getALErrorString(error) << std::endl;
149    }
150
151    void BaseSound::setVolume(float vol)
152    {
153        this->volume_ = clamp(vol, 0.0f, 1.0f);
154        if (this->volume_ != vol)
155            COUT(2) << "Sound warning: volume out of range, clamping value." << std::endl;
156        this->updateVolume();
157    }
158
159    void BaseSound::updateVolume()
160    {
161        if (alIsSource(this->audioSource_))
162        {
163            float volume = this->volume_ * this->getRealVolume();
164            alSourcef(this->audioSource_, AL_GAIN, volume);
165            if (int error = alGetError())
166                COUT(2) << "Sound: Error setting volume to " << volume
167                        << ": " << SoundManager::getALErrorString(error) << std::endl;
168        }
169    }
170
171    void BaseSound::setLooping(bool val)
172    {
173        this->bLooping_ = val;
174        if (alIsSource(this->audioSource_))
175            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
176    }
177
178    void BaseSound::setPitch(float pitch)
179    {
180        if (pitch > 2 || pitch < 0.5)
181        {
182            COUT(2) << "Sound warning: pitch out of range, cropping value." << std::endl;
183            pitch = pitch > 2 ? 2 : pitch;
184            pitch = pitch < 0.5 ? 0.5 : pitch;
185        }
186        this->pitch_ = pitch;
187        if (alIsSource(this->audioSource_))
188        {
189            alSourcef(this->audioSource_, AL_PITCH, pitch);
190            if (int error = alGetError())
191                COUT(2) << "Sound: Error setting pitch: " << SoundManager::getALErrorString(error) << std::endl;
192        }
193    }
194
195    void BaseSound::setSource(const std::string& source)
196    {
197        if (!GameMode::playsSound())
198        {
199            this->source_ = source;
200            return;
201        }
202
203        if (this->soundBuffer_ != NULL)
204        {
205            if (this->soundBuffer_->getFilename() == source)
206            {
207                assert(this->source_ == source_);
208                return;
209            }
210            // Stopping is imperative here!
211            if (alIsSource(this->audioSource_))
212            {
213                alSourceStop(this->audioSource_);
214                alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
215            }
216            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
217            this->soundBuffer_.reset();
218        }
219
220        this->source_ = source;
221        // Don't load ""
222        if (source_.empty())
223            return;
224
225        // Get new sound buffer
226        this->soundBuffer_ = SoundManager::getInstance().getSoundBuffer(this->source_);
227        if (this->soundBuffer_ == NULL)
228            return;
229
230        if (alIsSource(this->audioSource_)) // already playing or paused
231        {
232            // Set new buffer
233            alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
234            if (ALuint error = alGetError())
235            {
236                COUT(1) << "Sound Error: Could not set buffer \"" << source << "\": " << SoundManager::getALErrorString(error) << std::endl;
237                return;
238            }
239
240            // Sound was already playing or paused because there was a source acquired
241            assert(this->isPlaying() || this->isPaused());
242            alSourcePlay(this->audioSource_);
243            if (int error = alGetError())
244                COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
245            if (this->isPaused())
246                alSourcePause(this->audioSource_);
247        }
248        else // No source acquired so far, but might be set to playing or paused
249        {
250            State state = this->state_; // save
251            if (this->isPlaying() || this->isPaused())
252                doPlay();
253            if (state == Paused)
254            {
255                this->state_ = Paused;
256                doPause();
257            }
258        }
259    }
260
261    void BaseSound::stateChanged()
262    {
263        switch (this->state_)
264        {
265            case Playing:
266                this->play();
267                break;
268            case Paused:
269                this->pause();
270                break;
271            case Stopped:
272            default:
273                this->stop();
274                break;
275        }
276    }
277}
Note: See TracBrowser for help on using the repository browser.