Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/openAL: doxygen-Tags

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