Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/unity_build/src/orxonox/sound/BaseSound.cc @ 8748

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

Another hierarchy initialisation bug: BaseSound d'tor was always stopping a sound source. This one is a bit trickier because BaseSound is not a BaseObject and therefore does not have the isInitialized() method. However an instance is still being created through WorldSound.
This change also 'fixes' the POSIX IOConsole loosing lines between its construction and its first update because OpenAL sends output to STDOUT.

@Kevin: this could very well explain your mysterious error code.

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