Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: setClassID implemented in all files

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