Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6326 was 6322, checked in by rgrieder, 16 years ago

Added audio source management. This should reduce the problems when loading too many sounds.
However if there are too many players shooting at the same time, some sounds may still not play.

  • Property svn:eol-style set to native
File size: 8.5 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();
[3060]62    }
63
[6117]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);
[6188]68        XMLPortParam(BaseSound, "play",   setPlaying, isPlaying,  xmlelement, mode);
[6117]69        XMLPortParam(BaseSound, "source", setSource,  getSource,  xmlelement, mode);
70    }
71
[5896]72    void BaseSound::play()
[3060]73    {
[6255]74        this->state_ = Playing;
[6322]75        if (GameMode::playsSound() && this->getSourceState() != AL_PLAYING && this->soundBuffer_ != NULL)
[5896]76        {
[6322]77            if (!alIsSource(this->audioSource_))
78                this->audioSource_ = SoundManager::getInstance().getSoundSource();
79            if (!alIsSource(this->audioSource_))
80                return;
81            this->initialiseSource();
82
[5899]83            alSourcePlay(this->audioSource_);
[6203]84            if (int error = alGetError())
[6322]85                COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
[3060]86        }
87    }
88
[5896]89    void BaseSound::stop()
90    {
[6117]91        this->state_ = Stopped;
[6322]92        if (alIsSource(this->audioSource_))
93        {
[5899]94            alSourceStop(this->audioSource_);
[6322]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        }
[3060]103    }
104
[5896]105    void BaseSound::pause()
106    {
[6117]107        if (this->isStopped())
108            return;
109        this->state_ = Paused;
[6322]110        if (alIsSource(this->audioSource_))
[5899]111            alSourcePause(this->audioSource_);
[3060]112    }
113
[6255]114    ALint BaseSound::getSourceState() const
115    {
[6322]116        if (alIsSource(this->audioSource_))
[6255]117        {
118            ALint state;
119            alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
120            return state;
121        }
122        else
123            return AL_INITIAL;
124    }
125
[6322]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
[6117]145    void BaseSound::setVolume(float vol)
[5896]146    {
[6117]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;
[6186]154       
155        this->updateVolume();
[3060]156    }
[6184]157   
[6186]158    float BaseSound::getVolumeGain()
[6184]159    {
[6322]160        assert(GameMode::playsSound());
[6186]161        return SoundManager::getInstance().getVolume(SoundType::none);
[6184]162    }
163   
[6186]164    void BaseSound::updateVolume(void)
[6184]165    {
[6186]166        if (alIsSource(this->audioSource_))
[6204]167        {
[6322]168            float volume = this->volume_ * this->getVolumeGain();
169            alSourcef(this->audioSource_, AL_GAIN, volume);
[6204]170            if (int error = alGetError())
[6322]171                COUT(2) << "Sound: Error setting volume to " << volume
172                        << ": " << SoundManager::getALErrorString(error) << std::endl;
[6204]173        }
[6184]174    }
[3060]175
[6117]176    void BaseSound::setLooping(bool val)
[5896]177    {
[6307]178        this->bLooping_ = val;
[6322]179        if (alIsSource(this->audioSource_))
[6117]180            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
[3060]181    }
182
[6202]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;
[6322]192        if (alIsSource(this->audioSource_))
[6204]193        {
194            if (int error = alGetError())
[6322]195                COUT(2) << "Sound: Error setting pitch: " << SoundManager::getALErrorString(error) << std::endl;
[6205]196            alSourcef(this->audioSource_, AL_PITCH, pitch);
[6204]197        }
[6202]198    }
199
[5899]200    void BaseSound::setSource(const std::string& source)
[5896]201    {
[6117]202        if (!GameMode::playsSound() || source == this->source_) 
203        {
204            this->source_ = source;
[5896]205            return;
[6117]206        }
[5896]207
[6203]208        if (this->soundBuffer_ != NULL)
[3060]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;
[6322]221        if (source_.empty())
[6117]222            return;
223
[6270]224        this->soundBuffer_ = SoundManager::getInstance().getSoundBuffer(this->source_);
[6203]225        if (this->soundBuffer_ == NULL)
226            return;
[5695]227
[6322]228        if (alIsSource(this->audioSource_))
[5896]229        {
[6322]230            alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
231            if (ALuint error = alGetError())
232            {
233                COUT(1) << "Sound Error: Could not set buffer \"" << source << "\": " << SoundManager::getALErrorString(error) << std::endl;
234                return;
235            }
[5896]236
[6322]237            if (this->isPlaying() || this->isPaused())
238            {
239                alSourcePlay(this->audioSource_);
240                if (int error = alGetError())
241                    COUT(2) << "Sound: Error playing sound: " << SoundManager::getALErrorString(error) << std::endl;
242            }
243            if (this->isPaused())
244                alSourcePause(this->audioSource_);
[6234]245        }
[3060]246    }
[6320]247   
248    void BaseSound::stateChanged()
249    {
250        CCOUT(0) << "changed state to " << this->state_ << endl;
251        switch( this->state_ )
252        {
253            case Playing:
254                this->play();
255                break;
256            case Paused:
257                this->pause();
258                break;
259            case Stopped:
260            default:
261                this->stop();
262                break;
263        }
264    }
[6117]265}
Note: See TracBrowser for help on using the repository browser.