Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6731 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
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
[6117]31#include <cassert>
[3060]32#include <vector>
[6203]33#include <al.h>
[3060]34
[5896]35#include "core/CoreIncludes.h"
36#include "core/GameMode.h"
[5695]37#include "core/Resource.h"
[6117]38#include "core/XMLPort.h"
[6203]39#include "SoundBuffer.h"
[6186]40#include "SoundManager.h"
[3060]41
[5738]42namespace orxonox
[3060]43{
[5896]44    BaseSound::BaseSound()
[6322]45        : bPooling_(false)
[6203]46        , volume_(1.0)
[6307]47        , bLooping_(false)
[6117]48        , state_(Stopped)
[6222]49        , pitch_ (1.0)
[3060]50    {
[5896]51        RegisterRootObject(BaseSound);
[6117]52
[6322]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_));
[3060]57    }
58
[5896]59    BaseSound::~BaseSound()
[3060]60    {
[6322]61        this->stop();
[6411]62        // Release buffer
63        if (this->soundBuffer_ != NULL)
64        {
65            assert(GameMode::playsSound());
66            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
67        }
[3060]68    }
69
[6117]70    void BaseSound::XMLPortExtern(Element& xmlelement, XMLPort::Mode mode)
71    {
[6382]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);
[6117]76    }
77
[6382]78    void BaseSound::doPlay()
[3060]79    {
[6255]80        this->state_ = Playing;
[6322]81        if (GameMode::playsSound() && this->getSourceState() != AL_PLAYING && this->soundBuffer_ != NULL)
[5896]82        {
[6322]83            if (!alIsSource(this->audioSource_))
[6382]84            {
[6383]85                this->audioSource_ = SoundManager::getInstance().getSoundSource(this);
[6382]86                if (!alIsSource(this->audioSource_))
87                    return;
88                this->initialiseSource();
89            }
[6322]90
[5899]91            alSourcePlay(this->audioSource_);
[6203]92            if (int error = alGetError())
[6322]93                COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
[3060]94        }
95    }
96
[6382]97    void BaseSound::doStop()
[5896]98    {
[6117]99        this->state_ = Stopped;
[6322]100        if (alIsSource(this->audioSource_))
101        {
[5899]102            alSourceStop(this->audioSource_);
[6322]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        }
[3060]111    }
112
[6382]113    void BaseSound::doPause()
[5896]114    {
[6117]115        if (this->isStopped())
116            return;
117        this->state_ = Paused;
[6322]118        if (alIsSource(this->audioSource_))
[5899]119            alSourcePause(this->audioSource_);
[3060]120    }
121
[6255]122    ALint BaseSound::getSourceState() const
123    {
[6322]124        if (alIsSource(this->audioSource_))
[6255]125        {
126            ALint state;
127            alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
128            return state;
129        }
130        else
131            return AL_INITIAL;
132    }
133
[6322]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
[6117]151    void BaseSound::setVolume(float vol)
[5896]152    {
[6370]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;
[6186]156        this->updateVolume();
[3060]157    }
[6387]158
[6370]159    void BaseSound::updateVolume()
[6184]160    {
[6186]161        if (alIsSource(this->audioSource_))
[6204]162        {
[6370]163            float volume = this->volume_ * this->getRealVolume();
[6322]164            alSourcef(this->audioSource_, AL_GAIN, volume);
[6204]165            if (int error = alGetError())
[6322]166                COUT(2) << "Sound: Error setting volume to " << volume
167                        << ": " << SoundManager::getALErrorString(error) << std::endl;
[6204]168        }
[6184]169    }
[3060]170
[6117]171    void BaseSound::setLooping(bool val)
[5896]172    {
[6307]173        this->bLooping_ = val;
[6322]174        if (alIsSource(this->audioSource_))
[6117]175            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
[3060]176    }
177
[6202]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;
[6388]185        }
[6202]186        this->pitch_ = pitch;
[6322]187        if (alIsSource(this->audioSource_))
[6204]188        {
[6397]189            alSourcef(this->audioSource_, AL_PITCH, pitch);
[6204]190            if (int error = alGetError())
[6322]191                COUT(2) << "Sound: Error setting pitch: " << SoundManager::getALErrorString(error) << std::endl;
[6204]192        }
[6202]193    }
194
[5899]195    void BaseSound::setSource(const std::string& source)
[5896]196    {
[6327]197        if (!GameMode::playsSound())
[6117]198        {
199            this->source_ = source;
[5896]200            return;
[6117]201        }
[5896]202
[6203]203        if (this->soundBuffer_ != NULL)
[3060]204        {
[6327]205            if (this->soundBuffer_->getFilename() == source)
206            {
207                assert(this->source_ == source_);
208                return;
209            }
[6322]210            // Stopping is imperative here!
[6260]211            if (alIsSource(this->audioSource_))
212            {
213                alSourceStop(this->audioSource_);
[6322]214                alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
[6260]215            }
[6254]216            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
[6203]217            this->soundBuffer_.reset();
[3060]218        }
219
[6117]220        this->source_ = source;
[6340]221        // Don't load ""
[6322]222        if (source_.empty())
[6117]223            return;
224
[6340]225        // Get new sound buffer
[6270]226        this->soundBuffer_ = SoundManager::getInstance().getSoundBuffer(this->source_);
[6203]227        if (this->soundBuffer_ == NULL)
228            return;
[5695]229
[6340]230        if (alIsSource(this->audioSource_)) // already playing or paused
[5896]231        {
[6388]232            // Set new buffer
[6322]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            }
[5896]239
[6340]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
[6322]251            if (this->isPlaying() || this->isPaused())
[6382]252                doPlay();
[6340]253            if (state == Paused)
[6322]254            {
[6340]255                this->state_ = Paused;
[6382]256                doPause();
[6322]257            }
[6234]258        }
[3060]259    }
[6387]260
[6320]261    void BaseSound::stateChanged()
262    {
[6327]263        switch (this->state_)
[6320]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    }
[6117]277}
Note: See TracBrowser for help on using the repository browser.