Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/openAL: added Buffer to the ResourceManager

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