Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6186 was 6186, checked in by dafrick, 14 years ago

Some cleanup in SoundManager and related classes. Overrall volume works now. Mute function has been implemented into the gui.
Once again you'll have to delete your orxonox.ini file to be trouble free.

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