Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core5/src/orxonox/sound/SoundBase.cc @ 5836

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

Extracted path related parts of Core into a new PathConfig class. This should decrease the mess in Core.cc a little bit.

  • Property svn:eol-style set to native
File size: 7.3 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 *      ...
26 *
27 */
28
29#include "SoundBase.h"
30
31#include <string>
32#include <vector>
33#include <AL/alut.h>
34#include <vorbis/vorbisfile.h>
35
36#include "util/Math.h"
37#include "core/Resource.h"
38#include "worldentities/WorldEntity.h"
39#include "SoundManager.h"
40
41namespace orxonox
42{
43    SoundBase::SoundBase(WorldEntity* entity)
44    {
45        this->source_ = 0;
46        this->buffer_ = 0;
47        this->entity_ = entity;
48
49        SoundManager::getInstance().addSound(this);
50    }
51
52    SoundBase::~SoundBase()
53    {
54        alSourcei(this->source_, AL_BUFFER, 0);
55        alDeleteSources(1, &this->source_);
56        alDeleteBuffers(1, &this->buffer_);
57    }
58
59    void SoundBase::attachToEntity(WorldEntity* entity)
60    {
61        this->entity_ = entity;
62        this->update();
63    }
64
65    void SoundBase::update() {
66        if(this->entity_ != NULL && alIsSource(this->source_)) {
67            const Vector3& pos = this->entity_->getPosition();
68            alSource3f(this->source_, AL_POSITION, pos.x, pos.y, pos.z);
69            ALenum error = alGetError();
70            if(error == AL_INVALID_VALUE)
71                COUT(2) << "Sound: OpenAL: Invalid sound position" << std::endl;
72
73            const Vector3& vel = this->entity_->getVelocity();
74            alSource3f(this->source_, AL_VELOCITY, vel.x, vel.y, vel.z);
75            error = alGetError();
76            if(error == AL_INVALID_VALUE)
77                COUT(2) << "Sound: OpenAL: Invalid sound velocity" << std::endl;
78
79            const Quaternion& orient = this->entity_->getOrientation();
80            Vector3 at = orient.zAxis();
81            alSource3f(this->source_, AL_DIRECTION, at.x, at.y, at.z);
82            error = alGetError();
83            if(error == AL_INVALID_VALUE)
84                COUT(2) << "Sound: OpenAL: Invalid sound direction" << std::endl;
85        }
86    }
87
88    void SoundBase::play(bool loop) {
89        if(alIsSource(this->source_)) {
90            if(loop)
91                alSourcei(this->source_, AL_LOOPING, AL_TRUE);
92            else
93                alSourcei(this->source_, AL_LOOPING, AL_FALSE);
94            alSourcePlay(this->source_);
95
96            if(alGetError() != AL_NO_ERROR)
97            {
98                 COUT(2) << "Sound: OpenAL: Error playin sound " << this->source_ << std::endl;
99            }
100        }
101    }
102
103    void SoundBase::stop() {
104        if(alIsSource(this->source_)) {
105            alSourceStop(this->source_);
106        }
107    }
108
109    void SoundBase::pause() {
110        if(alIsSource(this->source_)) {
111            alSourcePause(this->source_);
112        }
113    }
114
115    bool SoundBase::isPlaying() {
116        if(alIsSource(this->source_)) {
117            return getSourceState() == AL_PLAYING;
118        }
119        return false;
120    }
121
122    bool SoundBase::isPaused() {
123        if(alIsSource(this->source_)) {
124            return getSourceState() == AL_PAUSED;
125        }
126        return true;
127    }
128
129    bool SoundBase::isStopped() {
130        if(alIsSource(this->source_)) {
131            return getSourceState() == AL_INITIAL || getSourceState() == AL_STOPPED;
132        }
133        return true;
134    }
135
136    bool SoundBase::loadFile(const std::string& filename) {
137        if(!SoundManager::getInstance().isSoundAvailable())
138        {
139            COUT(3) << "Sound: not available, skipping " << filename << std::endl;
140            return false;
141        }
142
143        COUT(3) << "Sound: OpenAL ALUT: loading file " << filename << std::endl;
144        // Get DataStream from the resources
145        shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(filename);
146        if (fileInfo == NULL) {
147            COUT(2) << "Warning: Sound file '" << filename << "' not found" << std::endl;
148            return false;
149        }
150        DataStreamPtr stream = Resource::open(filename);
151        // Read everything into a temporary buffer
152        char* buffer = new char[fileInfo->size];
153        stream->read(buffer, fileInfo->size);
154
155        this->buffer_ = alutCreateBufferFromFileImage(buffer, fileInfo->size);
156        delete[] buffer;
157
158        if(this->buffer_ == AL_NONE) {
159            COUT(2) << "Sound: OpenAL ALUT: " << alutGetErrorString(alutGetError()) << std::endl;
160            if(filename.find("ogg", 0) != std::string::npos)
161            {
162                COUT(2) << "Sound: Trying fallback ogg loader" << std::endl;
163                this->buffer_ = loadOggFile(filename);
164            }
165
166            if(this->buffer_ == AL_NONE)
167            {
168                COUT(2) << "Sound: fallback ogg loader failed: " << alutGetErrorString(alutGetError()) << std::endl;
169                return false;
170            }
171        }
172
173        alGenSources(1, &this->source_);
174        alSourcei(this->source_, AL_BUFFER, this->buffer_);
175        if(alGetError() != AL_NO_ERROR) {
176            COUT(2) << "Sound: OpenAL: Error loading sample file: " << filename << std::endl;
177            return false;
178        }
179        return true;
180    }
181
182    ALint SoundBase::getSourceState() {
183        ALint state;
184        alGetSourcei(this->source_, AL_SOURCE_STATE, &state);
185        return state;
186    }
187
188    ALuint SoundBase::loadOggFile(const std::string& filename)
189    {
190        char inbuffer[4096];
191        std::vector<char> outbuffer;
192        OggVorbis_File vf;
193        vorbis_info* vorbisInfo;
194        int eof = false;
195        int current_section;
196        ALuint buffer;
197        ALenum format;
198
199        FILE* f = fopen(filename.c_str(), "rb");
200
201        if(ov_open(f, &vf, NULL, 0) < 0)
202        {
203            COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
204            ov_clear(&vf);
205            return AL_NONE;
206        }
207
208        while(!eof)
209        {
210            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
211            if (ret == 0)
212            {
213                eof = true;
214            }
215            else if (ret < 0)
216            {
217                COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
218                ov_clear(&vf);
219                return AL_NONE;
220            }
221            else
222            {
223                outbuffer.insert(outbuffer.end(), inbuffer, inbuffer + sizeof(inbuffer));
224            }
225        }
226
227        vorbisInfo = ov_info(&vf, -1);
228        if(vorbisInfo->channels == 1)
229            format = AL_FORMAT_MONO16;
230        else
231            format = AL_FORMAT_STEREO16;
232
233        alGenBuffers(1, &buffer);
234        alBufferData(buffer, format, &outbuffer[0], outbuffer.size(), vorbisInfo->rate);
235        ov_clear(&vf);
236
237        return buffer;
238    }
239} // namespace: orxonox
Note: See TracBrowser for help on using the repository browser.