Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/sound/sound_engine.cc @ 4576

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

orxonox/trunk: changed all getInstances into inline functions to save some (minor) time

File size: 11.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 <AL/alc.h> // maybe later
24
25#include "p_node.h"
26#include "list.h"
27#include "resource_manager.h"
28#include "debug.h"
29
30using namespace std;
31
32
33//////////////////
34/* SOUND-BUFFER */
35//////////////////
36/**
37   \brief Creates a Soundbuffer out of an inputfile
38   \param fileName The name of the File
39*/
40SoundBuffer::SoundBuffer(const char* fileName)
41{
42  SoundEngine::getInstance()->addBuffer(this);
43
44  ALenum format;
45  ALvoid* data;
46  ALsizei freq;
47 
48  ALenum result;
49
50  // generate a Buffer
51  alGenBuffers(1, &this->bufferID);
52  if ((result = alGetError()) != AL_NO_ERROR)
53    SoundEngine::PrintALErrorString(result);
54
55  // read in the wav data
56  alutLoadWAVFile((ALbyte*)fileName, &format, &data, &this->size, &freq, &this->loop);
57  if ((result = alGetError()) != AL_NO_ERROR)
58    SoundEngine::PrintALErrorString(result);
59 
60  // send the loaded wav data to the buffer
61  alBufferData(this->bufferID, format, data, this->size, freq);
62  if ((result = alGetError()) != AL_NO_ERROR)
63    SoundEngine::PrintALErrorString(result);
64
65  // remove the wav data (redundant)
66  alutUnloadWAV(format, data, this->size, freq);
67  if ((result = alGetError()) != AL_NO_ERROR)
68    SoundEngine::PrintALErrorString(result);
69}
70
71SoundBuffer::~SoundBuffer(void)
72{
73  SoundEngine::getInstance()->removeBuffer(this);
74  alDeleteBuffers(1, &this->bufferID);
75}
76
77//////////////////
78/* SOUND-SOURCE */
79//////////////////
80/**
81   \brief creates a SoundSource at position sourceNode with the SoundBuffer buffer
82*/
83SoundSource::SoundSource(SoundBuffer* buffer, PNode* sourceNode)
84{
85  ALenum result;
86
87  // adding the Source to the SourcesList of the SoundEngine
88  SoundEngine::getInstance()->addSource(this);
89
90  this->buffer = buffer;
91  this->sourceNode = sourceNode;
92
93  alGenSources(1, &this->sourceID);
94  if ((result = alGetError()) != AL_NO_ERROR)
95    SoundEngine::PrintALErrorString(result);
96  alSourcei (this->sourceID, AL_BUFFER,   this->buffer->getID());
97  alSourcef (this->sourceID, AL_PITCH,    1.0      );
98  alSourcef (this->sourceID, AL_GAIN,     1.0      );
99  alSourcei (sourceID, AL_LOOPING,  AL_FALSE     );
100}
101
102/**
103   \brief deletes a SoundSource
104*/
105SoundSource::~SoundSource(void)
106{
107  SoundEngine::getInstance()->removeSource(this);
108  alDeleteSources(1, &this->sourceID);
109}
110
111
112/**
113   \brief Plays back a SoundSource
114*/
115void SoundSource::play()
116{
117  alSourcePlay(this->sourceID);
118}
119
120/**
121   \brief Stops playback of a SoundSource
122*/
123void SoundSource::stop()
124{
125  alSourceStop(this->sourceID);
126}
127
128/**
129   \brief Pauses Playback of a SoundSource
130*/
131void SoundSource::pause()
132{
133  alSourcePause(this->sourceID);
134}
135
136/**
137   \brief Rewinds Playback of a SoundSource
138*/
139void SoundSource::rewind()
140{
141  alSourceRewind(this->sourceID);
142}
143
144/**
145   \brief sets the RolloffFactor of the Sound emitted from the SoundSource
146   \param rolloffFactor The Factor described
147
148   this tells openAL how fast the Sounds decay outward from the Source
149*/
150void SoundSource::setRolloffFactor(ALfloat rolloffFactor)
151{
152  alSourcef(this->sourceID, AL_ROLLOFF_FACTOR, rolloffFactor);
153}
154
155
156
157//////////////////
158/* SOUND-ENGINE */
159//////////////////
160/**
161   \brief standard constructor
162*/
163SoundEngine::SoundEngine () 
164{
165  this->setClassName ("SoundEngine");
166 
167  this->listener = NULL;
168  this->bufferList = new tList<SoundBuffer>;
169  this->sourceList = new tList<SoundSource>;
170}
171
172/**
173   \brief the singleton reference to this class
174*/
175SoundEngine* SoundEngine::singletonRef = NULL;
176
177/**
178   \brief standard deconstructor
179
180*/
181SoundEngine::~SoundEngine () 
182{
183  SoundEngine::singletonRef = NULL;
184
185  // deleting all the SoundSources
186  tIterator<SoundSource>* sourceIterator = this->sourceList->getIterator();
187  SoundSource* enumSource = sourceIterator->nextElement();
188  while (enumSource)
189    {
190      delete enumSource;
191      enumSource = sourceIterator->nextElement();
192    }
193  delete sourceIterator;
194
195  // deleting all the SoundBuffers
196  tIterator<SoundBuffer>* bufferIterator = this->bufferList->getIterator();
197  SoundBuffer* enumBuffer = bufferIterator->nextElement();
198  while (enumBuffer)
199    {
200      ResourceManager::getInstance()->unload(enumBuffer);
201      enumBuffer = bufferIterator->nextElement();
202    }
203  delete bufferIterator;
204
205  // removing openAL from AudioResource
206  alutExit();
207}
208
209/**
210   \brief creates a new SoundSource.
211   \param fileName The Name to load the SoundBuffer from
212   \param sourceNode The sourceNode to bind this SoundSource to.
213   \returns The newly created SoundSource
214
215   acctualy this is nothing more than a wrapper around the ResourceManager.
216*/
217SoundSource* SoundEngine::createSource(const char* fileName, PNode* sourceNode)
218{
219  return new SoundSource((SoundBuffer*)ResourceManager::getInstance()->load(fileName, WAV, RP_LEVEL), sourceNode);
220}
221
222
223/**
224   \brief sets The listener (normaly the Camera)
225*/
226void SoundEngine::setListener(PNode* listener)
227{
228  this->listener = listener;
229}
230
231/**
232   \brief Sets the doppler values of openAL
233   \param dopplerFactor the extent of the doppler-effect
234   \param dopplerVelocity the Speed the sound travels
235*/
236void SoundEngine::setDopplerValues(ALfloat dopplerFactor, ALfloat dopplerVelocity)
237{
238  alDopplerFactor(dopplerFactor);
239  alDopplerVelocity(dopplerVelocity);
240}
241
242
243/**
244   \brief adds a SoundBuffer to the bufferList of the SoundEngine
245   \param buffer The buffer to add to the bufferList
246*/
247void SoundEngine::addBuffer(SoundBuffer* buffer)
248{
249  this->bufferList->add(buffer);
250}
251
252/**
253   \brief removes a SoundBuffer from the bufferList of the SoundEngine
254   \param buffer The buffer to delete from the SoundEngine
255*/
256void SoundEngine::removeBuffer(SoundBuffer* buffer)
257{
258  // look if there are any sources that have the buffer still loaded
259  tIterator<SoundSource>* sourceIterator = this->sourceList->getIterator();
260  SoundSource* enumSource = sourceIterator->nextElement();
261  while (enumSource)
262    {
263      if (buffer == enumSource->getBuffer())
264        delete enumSource;
265      enumSource = sourceIterator->nextElement();
266    }
267  delete sourceIterator;
268
269  // remove the Buffer
270  this->bufferList->remove(buffer);
271}
272
273/**
274   \brief adds a SoundSource to the sourceList of the SoundEngine
275   \param source The source to add to the sourceList
276*/
277void SoundEngine::addSource(SoundSource* source)
278{
279  this->sourceList->add(source);
280}
281
282/**
283   \brief removes a SoundSource from the sourceList of the SoundEngine
284   \param source The source to delete from the SoundEngine
285*/
286void SoundEngine::removeSource(SoundSource* source)
287{
288  this->sourceList->remove(source);
289}
290
291
292/**
293   \brief updates all The positions, Directions and Velocities of all Sounds
294*/
295void SoundEngine::update(void)
296{
297
298  // updating the Listeners Position
299  if (likely(this->listener != NULL))
300    {
301      alListener3f(AL_POSITION,
302                   this->listener->getAbsCoor().x,
303                   this->listener->getAbsCoor().y,
304                   this->listener->getAbsCoor().z);
305      alListener3f(AL_VELOCITY,
306                   this->listener->getVelocity().x,
307                   this->listener->getVelocity().y,
308                   this->listener->getVelocity().z);
309      Vector absDirV = this->listener->getAbsDirV();
310      ALfloat orientation [6] = {1,0,0, absDirV.x, absDirV.y, absDirV.z};
311      alListenerfv(AL_ORIENTATION, orientation);
312    }
313  else
314    PRINTF(2)("no listener defined\n");
315
316  // updating all the Sources positions
317  tIterator<SoundSource>* iterator = this->sourceList->getIterator();
318  SoundSource* enumSource = iterator->nextElement();
319  while (enumSource)
320    {
321      if (likely(enumSource->getNode()!=NULL))
322      {
323        alSource3f(enumSource->getID(), AL_POSITION,
324                   enumSource->getNode()->getAbsCoor().x,
325                   enumSource->getNode()->getAbsCoor().y,
326                   enumSource->getNode()->getAbsCoor().z);
327        alSource3f(enumSource->getID(), AL_VELOCITY,
328                   enumSource->getNode()->getVelocity().x,
329                   enumSource->getNode()->getVelocity().y,
330                   enumSource->getNode()->getVelocity().z);
331      }
332      enumSource = iterator->nextElement();
333    }
334  delete iterator;
335}
336
337/**
338   \brief Removes all the Buffers that are not anymore needed by any Sources
339*/
340void SoundEngine::flushUnusedBuffers(void)
341{
342  tIterator<SoundBuffer>* bufferIterator = this->bufferList->getIterator();
343  SoundBuffer* enumBuffer = bufferIterator->nextElement();
344  while (enumBuffer)
345    {
346      tIterator<SoundSource>* sourceIterator = this->sourceList->getIterator();
347      SoundSource* enumSource = sourceIterator->nextElement();
348      while (enumSource)
349        {
350          if (enumBuffer == enumSource->getBuffer())
351            break;
352          enumSource = sourceIterator->nextElement();
353        }
354      delete sourceIterator;
355      if (enumSource == NULL)
356        ResourceManager::getInstance()->unload(enumBuffer);
357      enumBuffer = bufferIterator->nextElement();
358    }
359  delete bufferIterator;
360}
361
362/**
363   \brief SourceEngine::flushAllBuffers
364*/
365void SoundEngine::flushAllBuffers(void)
366{
367    tIterator<SoundBuffer>* bufferIterator = this->bufferList->getIterator();
368  SoundBuffer* enumBuffer = bufferIterator->nextElement();
369  while (enumBuffer)
370    {
371      ResourceManager::getInstance()->unload(enumBuffer, RP_LEVEL);
372      enumBuffer = bufferIterator->nextElement();
373    }
374  delete bufferIterator;
375}
376
377/**
378   \brief initializes Audio in general
379*/
380bool SoundEngine::initAudio(void)
381{
382  ALenum result;
383
384  PRINTF(3)("Initialisazing openAL sound library\n");
385
386  alutInit(NULL, 0);
387  if ((result = alGetError()) != AL_NO_ERROR)
388    SoundEngine::PrintALErrorString(result);
389
390  this->setDopplerValues(SOUND_DOPPLER_FACTOR, SOUND_DOPPLER_VELOCITY);
391}
392
393/**
394   \brief Transforms AL-errors into something readable
395   \param err The error found
396*/
397void SoundEngine::PrintALErrorString(ALenum err)
398{
399  switch(err)
400    {
401    case AL_NO_ERROR:
402      PRINTF(4)("AL_NO_ERROR\n");
403      break;
404     
405    case AL_INVALID_NAME:
406      PRINTF(2)("AL_INVALID_NAME\n");
407      break;
408
409    case AL_INVALID_ENUM:
410      PRINTF(2)("AL_INVALID_ENUM\n");
411      break;
412
413    case AL_INVALID_VALUE:
414      PRINTF(2)("AL_INVALID_VALUE\n");
415      break;
416
417    case AL_INVALID_OPERATION:
418      PRINTF(2)("AL_INVALID_OPERATION\n");
419      break;
420
421    case AL_OUT_OF_MEMORY:
422      PRINTF(2)("AL_OUT_OF_MEMORY\n");
423      break;
424    };
425}
426
427/*
428void SoundEngine::PrintALCErrorString(ALenum err)
429{
430  switch(err)
431    {
432    case ALC_NO_ERROR:
433      PRINTF(4)("AL_NO_ERROR\n");
434      break;
435
436    case ALC_INVALID_DEVICE:
437      PRINTF(2)("ALC_INVALID_DEVICE\n");
438      break;
439
440    case ALC_INVALID_CONTEXT:
441      PRINTF(2)("ALC_INVALID_CONTEXT\n");
442      break;
443
444    case ALC_INVALID_ENUM:
445      PRINTF(2)("ALC_INVALID_ENUM\n");
446      break;
447
448    case ALC_INVALID_VALUE:
449      PRINTF(2)("ALC_INVALID_VALUE\n");
450      break;
451
452    case ALC_OUT_OF_MEMORY:
453      PRINTF(2)("ALC_OUT_OF_MEMORY\n");
454      break;
455    };
456}
457*/
Note: See TracBrowser for help on using the repository browser.