Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/sound/SoundBase.cc @ 5706

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

Merged resource2 branch back to trunk.

IMPORTANT NOTE:
Upon this merge you need to specifically call your data directory "data_extern" when checking it out (when you don't provide a name, it will be just called 'trunk').
The new CMake variable is EXTERNAL_DATA_DIRECTORY. DATA_DIRECTORY now points to the one the source part of the repository.
UPDATE YOUR DATA DIRECTORY AS WELL!!!

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