Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4883 was 4883, checked in by bensch, 20 years ago

orxonox/branches/weaponSystem: connecting sounds to the weapon works fine now

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