Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/weaponSystem/src/lib/sound/sound_engine.cc @ 4880

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

orxonox/branches/weaponSystem: more functionality, but firing does not work anymore… this will soon be fixed

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