Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6185 was 6184, checked in by dafrick, 16 years ago

Created capability in SoundManager to set an overall volume, and to also adjust general ambient and effects volumes.
For this to work, you need to delete your config-file (orxonox.ini) so that it can be reset.
It has still som quirks, though.

  • 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
[6117]31#include <cassert>
[3060]32#include <vector>
33#include <AL/alut.h>
34#include <vorbis/vorbisfile.h>
35
[5896]36#include "core/CoreIncludes.h"
37#include "core/GameMode.h"
[5695]38#include "core/Resource.h"
[6117]39#include "core/XMLPort.h"
[3060]40
[5738]41namespace orxonox
[3060]42{
[5896]43    BaseSound::BaseSound()
[5899]44        : audioSource_(0)
45        , audioBuffer_(0)
[5896]46        , bLoop_(false)
[6117]47        , state_(Stopped)
[3060]48    {
[5896]49        RegisterRootObject(BaseSound);
[6117]50
51        if (GameMode::playsSound())
52        {
53            alGenSources(1, &this->audioSource_);
54            assert(this->audioSource_ != 0);
55        }
[3060]56    }
57
[5896]58    BaseSound::~BaseSound()
[3060]59    {
[5899]60        this->setSource("");
[6117]61        if (GameMode::playsSound())
62            alDeleteSources(1, &this->audioSource_);
[3060]63    }
64
[6117]65    void BaseSound::XMLPortExtern(Element& xmlelement, XMLPort::Mode mode)
66    {
67        XMLPortParam(BaseSound, "volume", setVolume,  getVolume,  xmlelement, mode);
68        XMLPortParam(BaseSound, "loop",   setLooping, getLooping, xmlelement, mode);
69        XMLPortParam(BaseSound, "play",   play,       isPlaying,  xmlelement, mode);
70        XMLPortParam(BaseSound, "source", setSource,  getSource,  xmlelement, mode);
71    }
72
[5896]73    void BaseSound::play()
[3060]74    {
[6117]75        if (!this->isPlaying() && GameMode::showsGraphics())
[5896]76        {
[6117]77            this->state_ = Playing;
[5899]78            alSourcePlay(this->audioSource_);
[3108]79
[5896]80            if (alGetError() != AL_NO_ERROR)
[6117]81                 COUT(2) << "Sound: OpenAL: Error playing sound " << this->audioSource_ << std::endl;
[3060]82        }
83    }
84
[5896]85    void BaseSound::stop()
86    {
[6117]87        this->state_ = Stopped;
88        if (GameMode::playsSound())
[5899]89            alSourceStop(this->audioSource_);
[3060]90    }
91
[5896]92    void BaseSound::pause()
93    {
[6117]94        if (this->isStopped())
95            return;
96        this->state_ = Paused;
97        if (GameMode::playsSound())
[5899]98            alSourcePause(this->audioSource_);
[3060]99    }
100
[6117]101    void BaseSound::setVolume(float vol)
[5896]102    {
[6117]103        if (vol > 1 || vol < 0)
104        {
105            COUT(2) << "Sound warning: volume out of range, cropping value." << std::endl;
106            vol = vol > 1 ? 1 : vol;
107            vol = vol < 0 ? 0 : vol;
108        }
109        this->volume_ = vol;
[5899]110        if (alIsSource(this->audioSource_))
[6184]111            alSourcef(this->audioSource_, AL_GAIN, this->getEffectiveVolume());
[3060]112    }
[6184]113   
114    void BaseSound::setVolumeGain(float gain)
115    {
116        COUT(1) << "blubb: " << gain << std::endl;
117        if (gain > 1 || gain < 0)
118        {
119            COUT(2) << "Sound warning: volume gain out of range, cropping value." << std::endl;
120            gain = gain > 1 ? 1 : gain;
121            gain = gain < 0 ? 0 : gain;
122        }
123        this->volumeGain_ = gain;
124        if (alIsSource(this->audioSource_))
125            alSourcef(this->audioSource_, AL_GAIN, this->getEffectiveVolume());
126    }
127   
128    float BaseSound::getEffectiveVolume(void)
129    {
130        return this->volume_*this->volumeGain_;
131    }
[3060]132
[6117]133    void BaseSound::setLooping(bool val)
[5896]134    {
[6117]135        this->bLoop_ = val;
136        if (GameMode::playsSound())
137            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
[3060]138    }
139
[5899]140    void BaseSound::setSource(const std::string& source)
[5896]141    {
[6117]142        if (!GameMode::playsSound() || source == this->source_) 
143        {
144            this->source_ = source;
[5896]145            return;
[6117]146        }
[5896]147
[6117]148        if (this->audioBuffer_ != 0 && alIsBuffer(this->audioBuffer_))
[3060]149        {
[6117]150            alSourceStop(this->audioSource_);
151            // Unload old sound first
[5899]152            alSourcei(this->audioSource_, AL_BUFFER, 0);
153            alDeleteBuffers(1, &this->audioBuffer_);
[6117]154            this->audioBuffer_ = 0;
[3060]155        }
156
[6117]157        this->source_ = source;
158        if (source_.empty()) 
159            return;
160
[5899]161        COUT(3) << "Sound: OpenAL ALUT: loading file " << source << std::endl;
[5695]162        // Get DataStream from the resources
[5899]163        shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(source);
[5896]164        if (fileInfo == NULL)
165        {
[6117]166            COUT(2) << "Sound: Warning: Sound file '" << source << "' not found" << std::endl;
[5896]167            return;
[5695]168        }
[5904]169        dataStream_ = Resource::open(source);
[5695]170        // Read everything into a temporary buffer
171        char* buffer = new char[fileInfo->size];
[5904]172        dataStream_->read(buffer, fileInfo->size);
173        dataStream_->seek(0);
[5695]174
[5899]175        this->audioBuffer_ = alutCreateBufferFromFileImage(buffer, fileInfo->size);
[5695]176        delete[] buffer;
177
[5899]178        if (this->audioBuffer_ == AL_NONE)
[5896]179        {
[3060]180            COUT(2) << "Sound: OpenAL ALUT: " << alutGetErrorString(alutGetError()) << std::endl;
[5904]181            if (source.find("ogg", 0) != std::string::npos)
182            {
183                COUT(2) << "Sound: Trying fallback ogg loader" << std::endl;
[6117]184                this->audioBuffer_ = this->loadOggFile();
[5904]185            }
[3060]186
[5904]187            if (this->audioBuffer_ == AL_NONE)
188            {
189                COUT(2) << "Sound: fallback ogg loader failed: " << alutGetErrorString(alutGetError()) << std::endl;
190                return;
191            }
[3060]192        }
193
[5899]194        alSourcei(this->audioSource_, AL_BUFFER, this->audioBuffer_);
[5896]195        if (alGetError() != AL_NO_ERROR)
196        {
[5899]197            COUT(2) << "Sound: OpenAL: Error loading sample file: " << source << std::endl;
[5896]198            return;
[3060]199        }
[5896]200
[5899]201        alSource3f(this->audioSource_, AL_POSITION,  0, 0, 0);
[6184]202        alSourcef (this->audioSource_, AL_GAIN, this->getEffectiveVolume());
[6117]203        alSourcei (this->audioSource_, AL_LOOPING, (this->bLoop_ ? AL_TRUE : AL_FALSE));
204        if (this->isPlaying() || this->isPaused())
205            alSourcePlay(this->audioSource_);
206        if (this->isPaused())
207            alSourcePause(this->audioSource_);
[5896]208
[6117]209        if (alGetError() != AL_NO_ERROR)
210            COUT(2) << "Sound: OpenAL: Error playing sound " << this->audioSource_ << std::endl;
[3060]211    }
212
[5904]213    size_t readVorbis(void* ptr, size_t size, size_t nmemb, void* datasource)
[3060]214    {
[5904]215        return static_cast<Ogre::DataStream*>(datasource)->read(ptr, size * nmemb);
216    }
217
218    int seekVorbis(void* datasource, ogg_int64_t offset, int whence)
219    {
220        Ogre::DataStream* stream = static_cast<Ogre::DataStream*>(datasource);
221        int offset_beg = offset;
222        if (whence == SEEK_CUR)
223            offset_beg = stream->tell() + offset;
224        else if (whence == SEEK_END)
225            offset_beg = stream->size() + offset;
226        else if (whence != SEEK_SET)
227            return -1;
228        stream->seek(offset_beg);
229        return 0;
230    }
231
232    long tellVorbis(void* datasource)
233    {
234        return static_cast<long>(static_cast<Ogre::DataStream*>(datasource)->tell());
235    }
236
237    ALuint BaseSound::loadOggFile()
238    {
[6127]239        char inbuffer[256*1024];
[3060]240        std::vector<char> outbuffer;
[6127]241        outbuffer.reserve(80*1024*1024);
[3060]242        OggVorbis_File vf;
[3075]243        vorbis_info* vorbisInfo;
[3060]244        int eof = false;
245        int current_section;
[3075]246        ALuint buffer;
247        ALenum format;
[3060]248
[5904]249        // Open file with custom streaming
250        ov_callbacks vorbisCallbacks;
251        vorbisCallbacks.read_func  = &readVorbis;
252        vorbisCallbacks.seek_func  = &seekVorbis;
253        vorbisCallbacks.tell_func  = &tellVorbis;
254        vorbisCallbacks.close_func = NULL;
[3060]255
[5904]256        int ret = ov_open_callbacks(dataStream_.get(), &vf, NULL, 0, vorbisCallbacks);
257        if (ret < 0)
[3060]258        {
[3370]259            COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
[3060]260            ov_clear(&vf);
261            return AL_NONE;
262        }
263
[5896]264        while (!eof)
[3060]265        {
266            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
267            if (ret == 0)
268            {
269                eof = true;
270            }
271            else if (ret < 0)
272            {
273                COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
274                ov_clear(&vf);
275                return AL_NONE;
276            }
277            else
278            {
[6127]279                outbuffer.insert(outbuffer.end(), inbuffer, inbuffer + ret);
[3060]280            }
281        }
282
[3075]283        vorbisInfo = ov_info(&vf, -1);
[5896]284        if (vorbisInfo->channels == 1)
[3075]285            format = AL_FORMAT_MONO16;
286        else
287            format = AL_FORMAT_STEREO16;
288
289        alGenBuffers(1, &buffer);
290        alBufferData(buffer, format, &outbuffer[0], outbuffer.size(), vorbisInfo->rate);
[3060]291        ov_clear(&vf);
292
[3075]293        return buffer;
[3060]294    }
[6117]295}
Note: See TracBrowser for help on using the repository browser.