Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/openAL/src/lib/sound/sound_engine.cc @ 4205

Last change on this file since 4205 was 4205, checked in by bensch, 19 years ago

orxonox/branches/openAL: segfault-prevention :)

File size: 8.0 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14
15   code has been taken from http://www.devmaster.net/articles.php?catID=6
16   The code has been applied to our needs, and many things have been changed.
17*/
18
19//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
20
21#include "sound_engine.h"
22
23#include "p_node.h"
24#include "list.h"
25#include "AL/alc.h"
26#include "resource_manager.h"
27using namespace std;
28
29
30//////////////////
31/* SOUND-BUFFER */
32//////////////////
33/**
34   \brief Creates a Soundbuffer out of an inputfile
35   \param fileName The name of the File
36*/
37SoundBuffer::SoundBuffer(const char* fileName)
38{
39  SoundEngine::getInstance()->addBuffer(this);
40
41  ALenum format;
42  ALvoid* data;
43  ALsizei freq;
44 
45  ALenum result;
46
47  // generate a Buffer
48  alGenBuffers(1, &this->bufferID);
49  if ((result = alGetError()) != AL_NO_ERROR)
50    SoundEngine::PrintALErrorString(result);
51
52  // read in the wav data
53  alutLoadWAVFile((ALbyte*)fileName, &format, &data, &this->size, &freq, &this->loop);
54  if ((result = alGetError()) != AL_NO_ERROR)
55    SoundEngine::PrintALErrorString(result);
56 
57  // send the loaded wav data to the buffer
58  alBufferData(this->bufferID, format, data, this->size, freq);
59  if ((result = alGetError()) != AL_NO_ERROR)
60    SoundEngine::PrintALErrorString(result);
61
62  // remove the wav data (redundant)
63  alutUnloadWAV(format, data, this->size, freq);
64  if ((result = alGetError()) != AL_NO_ERROR)
65    SoundEngine::PrintALErrorString(result);
66}
67
68SoundBuffer::~SoundBuffer(void)
69{
70  SoundEngine::getInstance()->removeBuffer(this);
71  alDeleteBuffers(1, &this->bufferID);
72}
73
74//////////////////
75/* SOUND-SOURCE */
76//////////////////
77/**
78   \brief creates a SoundSource at position sourceNode with the SoundBuffer buffer
79*/
80SoundSource::SoundSource(SoundBuffer* buffer, PNode* sourceNode)
81{
82  ALenum result;
83
84  // adding the Source to the SourcesList of the SoundEngine
85  SoundEngine::getInstance()->addSource(this);
86
87  this->buffer = buffer;
88  this->sourceNode = sourceNode;
89
90  alGenSources(1, &this->sourceID);
91  if ((result = alGetError()) != AL_NO_ERROR)
92    SoundEngine::PrintALErrorString(result);
93  alSourcei (this->sourceID, AL_BUFFER,   this->buffer->getID());
94  alSourcef (this->sourceID, AL_PITCH,    1.0      );
95  alSourcef (this->sourceID, AL_GAIN,     1.0      );
96  alSourcei (sourceID, AL_LOOPING,  true     );
97}
98
99SoundSource::~SoundSource(void)
100{
101  SoundEngine::getInstance()->removeSource(this);
102  alDeleteSources(1, &this->sourceID);
103}
104
105
106void SoundSource::play()
107{
108  alSourcePlay(this->sourceID);
109}
110void SoundSource::stop()
111{
112  alSourceStop(this->sourceID);
113}
114void SoundSource::pause()
115{
116  alSourcePause(this->sourceID);
117}
118
119void SoundSource::setRolloffFactor(ALfloat rolloffFactor)
120{
121  alSourcef(this->sourceID, AL_ROLLOFF_FACTOR, rolloffFactor);
122}
123
124
125
126//////////////////
127/* SOUND-ENGINE */
128//////////////////
129/**
130   \brief standard constructor
131*/
132SoundEngine::SoundEngine () 
133{
134  this->setClassName ("SoundEngine");
135   
136   this->initAudio();
137
138   this->listener = NULL;
139   this->bufferList = new tList<SoundBuffer>;
140   this->sourceList = new tList<SoundSource>;
141}
142
143/**
144   \brief the singleton reference to this class
145*/
146SoundEngine* SoundEngine::singletonRef = NULL;
147
148/**
149   \returns a Pointer to this Class
150*/
151SoundEngine* SoundEngine::getInstance(void)
152{
153  if (!SoundEngine::singletonRef)
154    SoundEngine::singletonRef = new SoundEngine();
155  return SoundEngine::singletonRef;
156}
157
158/**
159   \brief standard deconstructor
160
161*/
162SoundEngine::~SoundEngine () 
163{
164  SoundEngine::singletonRef = NULL;
165
166  // deleting all the Resources
167  tIterator<SoundSource>* sourceIterator = this->sourceList->getIterator();
168  SoundSource* enumSource = sourceIterator->nextElement();
169  while (enumSource)
170    {
171      delete enumSource;
172      enumSource = sourceIterator->nextElement();
173    }
174  delete sourceIterator;
175
176  tIterator<SoundBuffer>* bufferIterator = this->bufferList->getIterator();
177  SoundBuffer* enumBuffer = bufferIterator->nextElement();
178  while (enumBuffer)
179    {
180      ResourceManager::getInstance()->unload(enumBuffer);
181      enumBuffer = bufferIterator->nextElement();
182    }
183  delete bufferIterator;
184}
185
186/**
187   \brief creates a new SoundSource.
188   \param fileName The Name to load the SoundBuffer from
189   \param The sourceNode to bind this SoundSource to.
190   \returns The newly created SoundSource
191
192   acctualy this is nothing more than a wrapper around the ResourceManager.
193*/
194SoundSource* SoundEngine::createSource(const char* fileName, PNode* sourceNode)
195{
196  return new SoundSource((SoundBuffer*)ResourceManager::getInstance()->load(fileName, WAV, RP_LEVEL), sourceNode);
197}
198
199
200/**
201   \brief sets The listener (normaly the Camera)
202*/
203void SoundEngine::setListener(PNode* listener)
204{
205  this->listener = listener;
206}
207
208
209void SoundEngine::addBuffer(SoundBuffer* buffer)
210{
211  this->bufferList->add(buffer);
212}
213
214void SoundEngine::removeBuffer(SoundBuffer* buffer)
215{
216  this->bufferList->remove(buffer);
217}
218
219void SoundEngine::addSource(SoundSource* source)
220{
221  this->sourceList->add(source);
222}
223void SoundEngine::removeSource(SoundSource* source)
224{
225  this->sourceList->remove(source);
226}
227
228
229/**
230   \brief updates all The positions, Directions and Velocities of all Sounds
231*/
232void SoundEngine::update(void)
233{
234
235  // updating the Listeners Position
236  if (likely(this->listener != NULL))
237    {
238      alListener3f(AL_POSITION,
239                   this->listener->getAbsCoor().x,
240                   this->listener->getAbsCoor().y,
241                   this->listener->getAbsCoor().z);
242      alListener3f(AL_VELOCITY,
243                   this->listener->getVelocity().x,
244                   this->listener->getVelocity().y,
245                   this->listener->getVelocity().z);
246      Vector absDirV = this->listener->getAbsDirV();
247      ALfloat orientation [6] = {1,0,0, absDirV.x, absDirV.y, absDirV.z};
248      alListenerfv(AL_ORIENTATION, orientation);
249    }
250  else
251    PRINTF(2)("no listener defined\n");
252
253  // updating all the Sources positions
254  tIterator<SoundSource>* iterator = this->sourceList->getIterator();
255  SoundSource* enumSource = iterator->nextElement();
256  while (enumSource)
257    {
258      if (likely(enumSource->getNode()!=NULL))
259      {
260        alSource3f(enumSource->getID(), AL_POSITION,
261                   enumSource->getNode()->getAbsCoor().x,
262                   enumSource->getNode()->getAbsCoor().y,
263                   enumSource->getNode()->getAbsCoor().z);
264        alSource3f(enumSource->getID(), AL_VELOCITY,
265                   enumSource->getNode()->getVelocity().x,
266                   enumSource->getNode()->getVelocity().y,
267                   enumSource->getNode()->getVelocity().z);
268      }
269      enumSource = iterator->nextElement();
270    }
271  delete iterator;
272}
273
274/**
275   \brief initializes Audio in general
276*/
277bool SoundEngine::initAudio(void)
278{
279  alutInit(NULL, 0);
280  alGetError();
281
282  alDopplerFactor(SOUND_DOPPLER_FACTOR);
283  alDopplerVelocity(SOUND_DOPPLER_VELOCITY);
284}
285
286void SoundEngine::PrintALErrorString(ALenum err)
287{
288  switch(err)
289    {
290    case AL_NO_ERROR:
291      PRINTF(4)("AL_NO_ERROR\n");
292      break;
293     
294    case AL_INVALID_NAME:
295      PRINTF(2)("AL_INVALID_NAME\n");
296      break;
297
298    case AL_INVALID_ENUM:
299      PRINTF(2)("AL_INVALID_ENUM\n");
300      break;
301
302    case AL_INVALID_VALUE:
303      PRINTF(2)("AL_INVALID_VALUE\n");
304      break;
305
306    case AL_INVALID_OPERATION:
307      PRINTF(2)("AL_INVALID_OPERATION\n");
308      break;
309
310    case AL_OUT_OF_MEMORY:
311      PRINTF(2)("AL_OUT_OF_MEMORY\n");
312      break;
313    };
314}
315
316
317void SoundEngine::PrintALCErrorString(ALenum err)
318{
319  switch(err)
320    {
321    case ALC_NO_ERROR:
322      PRINTF(4)("AL_NO_ERROR\n");
323      break;
324
325    case ALC_INVALID_DEVICE:
326      PRINTF(2)("ALC_INVALID_DEVICE\n");
327      break;
328
329    case ALC_INVALID_CONTEXT:
330      PRINTF(2)("ALC_INVALID_CONTEXT\n");
331      break;
332
333    case ALC_INVALID_ENUM:
334      PRINTF(2)("ALC_INVALID_ENUM\n");
335      break;
336
337    case ALC_INVALID_VALUE:
338      PRINTF(2)("ALC_INVALID_VALUE\n");
339      break;
340
341    case ALC_OUT_OF_MEMORY:
342      PRINTF(2)("ALC_OUT_OF_MEMORY\n");
343      break;
344    };
345}
Note: See TracBrowser for help on using the repository browser.