Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Merged resource branch back to the trunk. Changes:

  • Automated graphics loading by evaluating whether a GameState requires it
  • Using native Tcl library (x3n)

Windows users: Update your dependency package!

  • Property svn:eol-style set to native
File size: 6.9 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 "orxonox/objects/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(std::string filename) {
137        filename = Core::getMediaPathString() + "/audio/" + filename;
138
139        if(!SoundManager::getInstance().isSoundAvailable())
140        {
141            COUT(3) << "Sound: not available, skipping " << filename << std::endl;
142            return false;
143        }
144
145        COUT(3) << "Sound: OpenAL ALUT: loading file " << filename << std::endl;
146        this->buffer_ = alutCreateBufferFromFile(filename.c_str());
147        if(this->buffer_ == AL_NONE) {
148            COUT(2) << "Sound: OpenAL ALUT: " << alutGetErrorString(alutGetError()) << std::endl;
149            if(filename.find("ogg", 0) != std::string::npos)
150            {
151                COUT(2) << "Sound: Trying fallback ogg loader" << std::endl;
152                this->buffer_ = loadOggFile(filename);
153            }
154
155            if(this->buffer_ == AL_NONE)
156            {
157                COUT(2) << "Sound: fallback ogg loader failed: " << alutGetErrorString(alutGetError()) << std::endl;
158                return false;
159            }
160        }
161
162        alGenSources(1, &this->source_);
163        alSourcei(this->source_, AL_BUFFER, this->buffer_);
164        if(alGetError() != AL_NO_ERROR) {
165            COUT(2) << "Sound: OpenAL: Error loading sample file: " << filename << std::endl;
166            return false;
167        }
168        return true;
169    }
170
171    ALint SoundBase::getSourceState() {
172        ALint state;
173        alGetSourcei(this->source_, AL_SOURCE_STATE, &state);
174        return state;
175    }
176
177    ALuint SoundBase::loadOggFile(const std::string& filename)
178    {
179        char inbuffer[4096];
180        std::vector<char> outbuffer;
181        OggVorbis_File vf;
182        vorbis_info* vorbisInfo;
183        int eof = false;
184        int current_section;
185        ALuint buffer;
186        ALenum format;
187
188        FILE* f = fopen(filename.c_str(), "rb");
189
190        if(ov_open(f, &vf, NULL, 0) < 0)
191        {
192            COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
193            ov_clear(&vf);
194            return AL_NONE;
195        }
196
197        while(!eof)
198        {
199            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
200            if (ret == 0)
201            {
202                eof = true;
203            }
204            else if (ret < 0)
205            {
206                COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
207                ov_clear(&vf);
208                return AL_NONE;
209            }
210            else
211            {
212                outbuffer.insert(outbuffer.end(), inbuffer, inbuffer + sizeof(inbuffer));
213            }
214        }
215
216        vorbisInfo = ov_info(&vf, -1);
217        if(vorbisInfo->channels == 1)
218            format = AL_FORMAT_MONO16;
219        else
220            format = AL_FORMAT_STEREO16;
221
222        alGenBuffers(1, &buffer);
223        alBufferData(buffer, format, &outbuffer[0], outbuffer.size(), vorbisInfo->rate);
224        ov_clear(&vf);
225
226        return buffer;
227    }
228} // namespace: orxonox
Note: See TracBrowser for help on using the repository browser.