Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/sound/BaseSound.cc @ 5972

Last change on this file since 5972 was 5929, checked in by rgrieder, 15 years ago

Merged core5 branch back to the trunk.
Key features include clean level unloading and an extended XML event system.

Two important notes:
Delete your keybindings.ini files! * or you will still get parser errors when loading the key bindings.
Delete build_dir/lib/modules/libgamestates.module! * or orxonox won't start.
Best thing to do is to delete the build folder ;)

  • Property svn:eol-style set to native
File size: 7.5 KB
Line 
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:
23 *      Erwin 'vaiursch' Herrsche
24 *   Co-authors:
25 *      Reto Grieder
26 *
27 */
28
29#include "BaseSound.h"
30
31#include <vector>
32#include <AL/alut.h>
33#include <vorbis/vorbisfile.h>
34
35#include "core/CoreIncludes.h"
36#include "core/GameMode.h"
37#include "core/Resource.h"
38
39namespace orxonox
40{
41    BaseSound::BaseSound()
42        : audioSource_(0)
43        , audioBuffer_(0)
44        , bPlayOnLoad_(false)
45        , bLoop_(false)
46    {
47        RegisterRootObject(BaseSound);
48    }
49
50    BaseSound::~BaseSound()
51    {
52        this->setSource("");
53    }
54
55    void BaseSound::play()
56    {
57        if (alIsSource(this->audioSource_))
58        {
59            if (this->bLoop_)
60                alSourcei(this->audioSource_, AL_LOOPING, AL_TRUE);
61            else
62                alSourcei(this->audioSource_, AL_LOOPING, AL_FALSE);
63            alSourcePlay(this->audioSource_);
64
65            if (alGetError() != AL_NO_ERROR)
66            {
67                 COUT(2) << "Sound: OpenAL: Error playin sound " << this->audioSource_ << std::endl;
68            }
69        }
70    }
71
72    void BaseSound::stop()
73    {
74        if (alIsSource(this->audioSource_))
75            alSourceStop(this->audioSource_);
76    }
77
78    void BaseSound::pause()
79    {
80        if (alIsSource(this->audioSource_))
81            alSourcePause(this->audioSource_);
82    }
83
84    bool BaseSound::isPlaying()
85    {
86        if (alIsSource(this->audioSource_))
87            return getSourceState() == AL_PLAYING;
88        return false;
89    }
90
91    bool BaseSound::isPaused()
92    {
93        if (alIsSource(this->audioSource_))
94            return getSourceState() == AL_PAUSED;
95        return true;
96    }
97
98    bool BaseSound::isStopped()
99    {
100        if (alIsSource(this->audioSource_))
101            return getSourceState() == AL_INITIAL || getSourceState() == AL_STOPPED;
102        return true;
103    }
104
105    void BaseSound::setPlayOnLoad(bool val)
106    {
107        this->bPlayOnLoad_ = true;
108        this->play();
109    }
110
111    void BaseSound::setSource(const std::string& source)
112    {
113        this->source_ = source;
114        if (!GameMode::playsSound())
115            return;
116
117        if (source.empty() && alIsSource(this->audioSource_))
118        {
119            // Unload sound
120            alSourcei(this->audioSource_, AL_BUFFER, 0);
121            alDeleteSources(1, &this->audioSource_);
122            alDeleteBuffers(1, &this->audioBuffer_);
123            return;
124        }
125
126        COUT(3) << "Sound: OpenAL ALUT: loading file " << source << std::endl;
127        // Get DataStream from the resources
128        shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(source);
129        if (fileInfo == NULL)
130        {
131            COUT(2) << "Warning: Sound file '" << source << "' not found" << std::endl;
132            return;
133        }
134        dataStream_ = Resource::open(source);
135        // Read everything into a temporary buffer
136        char* buffer = new char[fileInfo->size];
137        dataStream_->read(buffer, fileInfo->size);
138        dataStream_->seek(0);
139
140        this->audioBuffer_ = alutCreateBufferFromFileImage(buffer, fileInfo->size);
141        delete[] buffer;
142
143        if (this->audioBuffer_ == AL_NONE)
144        {
145            COUT(2) << "Sound: OpenAL ALUT: " << alutGetErrorString(alutGetError()) << std::endl;
146            if (source.find("ogg", 0) != std::string::npos)
147            {
148                COUT(2) << "Sound: Trying fallback ogg loader" << std::endl;
149                this->audioBuffer_ = loadOggFile();
150            }
151
152            if (this->audioBuffer_ == AL_NONE)
153            {
154                COUT(2) << "Sound: fallback ogg loader failed: " << alutGetErrorString(alutGetError()) << std::endl;
155                return;
156            }
157        }
158
159        alGenSources(1, &this->audioSource_);
160        alSourcei(this->audioSource_, AL_BUFFER, this->audioBuffer_);
161        if (alGetError() != AL_NO_ERROR)
162        {
163            COUT(2) << "Sound: OpenAL: Error loading sample file: " << source << std::endl;
164            return;
165        }
166
167        alSource3f(this->audioSource_, AL_POSITION,  0, 0, 0);
168
169        if (this->bPlayOnLoad_)
170            this->play();
171    }
172
173    ALint BaseSound::getSourceState()
174    {
175        ALint state;
176        alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
177        return state;
178    }
179
180    size_t readVorbis(void* ptr, size_t size, size_t nmemb, void* datasource)
181    {
182        return static_cast<Ogre::DataStream*>(datasource)->read(ptr, size * nmemb);
183    }
184
185    int seekVorbis(void* datasource, ogg_int64_t offset, int whence)
186    {
187        Ogre::DataStream* stream = static_cast<Ogre::DataStream*>(datasource);
188        int offset_beg = offset;
189        if (whence == SEEK_CUR)
190            offset_beg = stream->tell() + offset;
191        else if (whence == SEEK_END)
192            offset_beg = stream->size() + offset;
193        else if (whence != SEEK_SET)
194            return -1;
195        stream->seek(offset_beg);
196        return 0;
197    }
198
199    long tellVorbis(void* datasource)
200    {
201        return static_cast<long>(static_cast<Ogre::DataStream*>(datasource)->tell());
202    }
203
204    ALuint BaseSound::loadOggFile()
205    {
206        char inbuffer[4096];
207        std::vector<char> outbuffer;
208        OggVorbis_File vf;
209        vorbis_info* vorbisInfo;
210        int eof = false;
211        int current_section;
212        ALuint buffer;
213        ALenum format;
214
215        // Open file with custom streaming
216        ov_callbacks vorbisCallbacks;
217        vorbisCallbacks.read_func  = &readVorbis;
218        vorbisCallbacks.seek_func  = &seekVorbis;
219        vorbisCallbacks.tell_func  = &tellVorbis;
220        vorbisCallbacks.close_func = NULL;
221
222        int ret = ov_open_callbacks(dataStream_.get(), &vf, NULL, 0, vorbisCallbacks);
223        if (ret < 0)
224        {
225            COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
226            ov_clear(&vf);
227            return AL_NONE;
228        }
229
230        while (!eof)
231        {
232            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
233            if (ret == 0)
234            {
235                eof = true;
236            }
237            else if (ret < 0)
238            {
239                COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
240                ov_clear(&vf);
241                return AL_NONE;
242            }
243            else
244            {
245                outbuffer.insert(outbuffer.end(), inbuffer, inbuffer + sizeof(inbuffer));
246            }
247        }
248
249        vorbisInfo = ov_info(&vf, -1);
250        if (vorbisInfo->channels == 1)
251            format = AL_FORMAT_MONO16;
252        else
253            format = AL_FORMAT_STEREO16;
254
255        alGenBuffers(1, &buffer);
256        alBufferData(buffer, format, &outbuffer[0], outbuffer.size(), vorbisInfo->rate);
257        ov_clear(&vf);
258
259        return buffer;
260    }
261
262} // namespace: orxonox
Note: See TracBrowser for help on using the repository browser.