| [4597] | 1 | /* | 
|---|
| [4504] | 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 |  | 
|---|
| [5386] | 19 | #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SOUND | 
|---|
| [4504] | 20 |  | 
|---|
 | 21 | #include "sound_engine.h" | 
|---|
 | 22 |  | 
|---|
| [4960] | 23 | #include "class_list.h" | 
|---|
| [4504] | 24 |  | 
|---|
 | 25 | #include "p_node.h" | 
|---|
 | 26 | #include "resource_manager.h" | 
|---|
 | 27 | #include "debug.h" | 
|---|
| [5944] | 28 | #include "parser/ini_parser/ini_parser.h" | 
|---|
| [5427] | 29 | #include "globals.h" | 
|---|
| [4504] | 30 |  | 
|---|
 | 31 | using namespace std; | 
|---|
 | 32 |  | 
|---|
| [4597] | 33 |  | 
|---|
| [4504] | 34 | ////////////////// | 
|---|
 | 35 | /* SOUND-ENGINE */ | 
|---|
 | 36 | ////////////////// | 
|---|
 | 37 | /** | 
|---|
| [4836] | 38 |  *  standard constructor | 
|---|
| [4504] | 39 | */ | 
|---|
| [4597] | 40 | SoundEngine::SoundEngine () | 
|---|
| [4504] | 41 | { | 
|---|
| [4597] | 42 |   this->setClassID(CL_SOUND_ENGINE, "SoundEngine"); | 
|---|
 | 43 |   this->setName("SoundEngine"); | 
|---|
 | 44 |  | 
|---|
| [4504] | 45 |   this->listener = NULL; | 
|---|
| [4960] | 46 |   this->bufferList = NULL; | 
|---|
 | 47 |   this->sourceList = NULL; | 
|---|
| [5930] | 48 |  | 
|---|
 | 49 |   this->device = NULL; | 
|---|
 | 50 |   this->context = NULL; | 
|---|
 | 51 |  | 
|---|
 | 52 |   this->maxSourceCount = 32; | 
|---|
| [6829] | 53 |  | 
|---|
 | 54 |   this->effectsVolume = .80; | 
|---|
 | 55 |   this->musicVolume = .75; | 
|---|
| [4504] | 56 | } | 
|---|
 | 57 |  | 
|---|
 | 58 | /** | 
|---|
| [4836] | 59 |  *  the singleton reference to this class | 
|---|
| [4504] | 60 | */ | 
|---|
 | 61 | SoundEngine* SoundEngine::singletonRef = NULL; | 
|---|
 | 62 |  | 
|---|
 | 63 | /** | 
|---|
| [4836] | 64 |  *  standard deconstructor | 
|---|
| [5293] | 65 |  */ | 
|---|
| [4597] | 66 | SoundEngine::~SoundEngine () | 
|---|
| [4504] | 67 | { | 
|---|
 | 68 |   // deleting all the SoundSources | 
|---|
| [4960] | 69 |   if(this->sourceList != NULL) | 
|---|
 | 70 |   { | 
|---|
| [5779] | 71 |     while (this->sourceList->size() > 0) | 
|---|
 | 72 |       delete dynamic_cast<SoundSource*>(this->sourceList->front()); | 
|---|
| [4960] | 73 |   } | 
|---|
| [4504] | 74 |  | 
|---|
| [5930] | 75 |   while(!this->ALSources.empty()) | 
|---|
 | 76 |   { | 
|---|
 | 77 |     alDeleteSources(1, &this->ALSources.top()); | 
|---|
 | 78 |     this->ALSources.pop(); | 
|---|
 | 79 |   } | 
|---|
 | 80 |  | 
|---|
| [4504] | 81 |   // deleting all the SoundBuffers | 
|---|
| [4960] | 82 |   if (this->bufferList != NULL) | 
|---|
 | 83 |   { | 
|---|
| [5779] | 84 |     while(this->bufferList->size() > 0) | 
|---|
 | 85 |       ResourceManager::getInstance()->unload(dynamic_cast<SoundBuffer*>(this->bufferList->front())); | 
|---|
| [4960] | 86 |   } | 
|---|
| [5293] | 87 |  | 
|---|
| [4504] | 88 |   // removing openAL from AudioResource | 
|---|
| [5473] | 89 |   //! @todo this should be terminated through alc | 
|---|
 | 90 |   //alutExit(); | 
|---|
| [5293] | 91 |  | 
|---|
 | 92 |   SoundEngine::singletonRef = NULL; | 
|---|
| [4504] | 93 | } | 
|---|
 | 94 |  | 
|---|
 | 95 | /** | 
|---|
| [4985] | 96 |  * loads the settings of the SoundEngine from an ini-file | 
|---|
 | 97 |  * @param iniParser the IniParser of the inifile | 
|---|
 | 98 |  */ | 
|---|
 | 99 | void SoundEngine::loadSettings(IniParser* iniParser) | 
|---|
 | 100 | { | 
|---|
| [5953] | 101 |   const char* channels = iniParser->getVar(CONFIG_NAME_AUDIO_CHANNELS, CONFIG_SECTION_AUDIO, "32"); | 
|---|
 | 102 |   this->maxSourceCount = atoi(channels); | 
|---|
| [4985] | 103 |  | 
|---|
 | 104 |   const char* effectsVolume = iniParser->getVar(CONFIG_NAME_EFFECTS_VOLUME, CONFIG_SECTION_AUDIO, "80"); | 
|---|
 | 105 |   this->effectsVolume = atof(effectsVolume)/100.0; | 
|---|
| [6830] | 106 |  | 
|---|
| [6840] | 107 |   const char* musicVolume = iniParser->getVar(CONFIG_NAME_MUSIC_VOLUME, CONFIG_SECTION_AUDIO, "75"); | 
|---|
 | 108 |   this->musicVolume = atof(musicVolume)/100.0; | 
|---|
| [4985] | 109 | } | 
|---|
 | 110 |  | 
|---|
 | 111 | /** | 
|---|
| [4836] | 112 |  *  creates a new SoundSource. | 
|---|
 | 113 |  * @param fileName The Name to load the SoundBuffer from | 
|---|
 | 114 |  * @param sourceNode The sourceNode to bind this SoundSource to. | 
|---|
 | 115 |  * @returns The newly created SoundSource | 
|---|
| [4504] | 116 |  | 
|---|
 | 117 |    acctualy this is nothing more than a wrapper around the ResourceManager. | 
|---|
 | 118 | */ | 
|---|
 | 119 | SoundSource* SoundEngine::createSource(const char* fileName, PNode* sourceNode) | 
|---|
 | 120 | { | 
|---|
| [4885] | 121 |   return new SoundSource(sourceNode, (SoundBuffer*)ResourceManager::getInstance()->load(fileName, WAV, RP_LEVEL)); | 
|---|
| [4504] | 122 | } | 
|---|
 | 123 |  | 
|---|
 | 124 | /** | 
|---|
| [4836] | 125 |  *  Sets the doppler values of openAL | 
|---|
 | 126 |  * @param dopplerFactor the extent of the doppler-effect | 
|---|
 | 127 |  * @param dopplerVelocity the Speed the sound travels | 
|---|
| [4504] | 128 | */ | 
|---|
 | 129 | void SoundEngine::setDopplerValues(ALfloat dopplerFactor, ALfloat dopplerVelocity) | 
|---|
 | 130 | { | 
|---|
 | 131 |   alDopplerFactor(dopplerFactor); | 
|---|
| [6840] | 132 |   this->checkError("Setting Doppler Factor", __LINE__); | 
|---|
 | 133 |  | 
|---|
| [4504] | 134 |   alDopplerVelocity(dopplerVelocity); | 
|---|
| [6840] | 135 |   this->checkError("Setting Doppler Velocity", __LINE__); | 
|---|
| [4504] | 136 | } | 
|---|
 | 137 |  | 
|---|
 | 138 |  | 
|---|
| [5930] | 139 | void SoundEngine::popALSource(ALuint& source) | 
|---|
| [4504] | 140 | { | 
|---|
| [5930] | 141 |   if (source != 0) | 
|---|
 | 142 |     return; | 
|---|
 | 143 |   else | 
|---|
 | 144 |   { | 
|---|
| [4504] | 145 |  | 
|---|
| [5930] | 146 |     /// @TODO try to create more sources if needed | 
|---|
 | 147 |     if (!this->ALSources.empty()) | 
|---|
| [4504] | 148 |     { | 
|---|
| [5930] | 149 |       source = this->ALSources.top(); | 
|---|
 | 150 |       this->ALSources.pop(); | 
|---|
| [4504] | 151 |     } | 
|---|
| [5779] | 152 |   } | 
|---|
| [4504] | 153 | } | 
|---|
 | 154 |  | 
|---|
 | 155 |  | 
|---|
 | 156 | /** | 
|---|
| [4836] | 157 |  *  updates all The positions, Directions and Velocities of all Sounds | 
|---|
| [4504] | 158 | */ | 
|---|
| [4746] | 159 | void SoundEngine::update() | 
|---|
| [4504] | 160 | { | 
|---|
 | 161 |  | 
|---|
 | 162 |   // updating the Listeners Position | 
|---|
 | 163 |   if (likely(this->listener != NULL)) | 
|---|
| [6846] | 164 |   { | 
|---|
 | 165 |     alListener3f(AL_POSITION, | 
|---|
 | 166 |                  this->listener->getAbsCoor().x, | 
|---|
 | 167 |                  this->listener->getAbsCoor().y, | 
|---|
 | 168 |                  this->listener->getAbsCoor().z); | 
|---|
 | 169 |     alListener3f(AL_VELOCITY, | 
|---|
 | 170 |                  this->listener->getVelocity().x, | 
|---|
 | 171 |                  this->listener->getVelocity().y, | 
|---|
 | 172 |                  this->listener->getVelocity().z); | 
|---|
 | 173 |     Vector absDirV = this->listener->getAbsDirV(); | 
|---|
 | 174 |     ALfloat orientation [6] = {1,0,0, absDirV.x, absDirV.y, absDirV.z}; | 
|---|
 | 175 |     alListenerfv(AL_ORIENTATION, orientation); | 
|---|
 | 176 |   } | 
|---|
| [4504] | 177 |   else | 
|---|
 | 178 |     PRINTF(2)("no listener defined\n"); | 
|---|
 | 179 |  | 
|---|
 | 180 |   // updating all the Sources positions | 
|---|
| [5930] | 181 |   if (likely(this->sourceList != NULL || (this->sourceList = ClassList::getList(CL_SOUND_SOURCE)) != NULL)) | 
|---|
| [4960] | 182 |   { | 
|---|
| [5885] | 183 |     list<BaseObject*>::const_iterator sourceIT; | 
|---|
| [5779] | 184 |     SoundSource* source; | 
|---|
 | 185 |     for (sourceIT = this->sourceList->begin(); sourceIT != this->sourceList->end(); sourceIT++) | 
|---|
| [4504] | 186 |     { | 
|---|
| [5779] | 187 |       source = static_cast<SoundSource*>(*sourceIT); | 
|---|
| [5930] | 188 |       if (source->isPlaying()) | 
|---|
| [4504] | 189 |       { | 
|---|
| [6073] | 190 |         int play = 0x000; | 
|---|
| [5930] | 191 |         alGetSourcei(source->getID(), AL_SOURCE_STATE, &play); | 
|---|
 | 192 |         if(play == AL_PLAYING) | 
|---|
 | 193 |         { | 
|---|
 | 194 |           if (likely(source->getNode() != NULL)) | 
|---|
 | 195 |           { | 
|---|
 | 196 |             alSource3f(source->getID(), AL_POSITION, | 
|---|
 | 197 |                        source->getNode()->getAbsCoor().x, | 
|---|
 | 198 |                        source->getNode()->getAbsCoor().y, | 
|---|
 | 199 |                        source->getNode()->getAbsCoor().z); | 
|---|
 | 200 |             alSource3f(source->getID(), AL_VELOCITY, | 
|---|
 | 201 |                        source->getNode()->getVelocity().x, | 
|---|
 | 202 |                        source->getNode()->getVelocity().y, | 
|---|
 | 203 |                        source->getNode()->getVelocity().z); | 
|---|
 | 204 |           } | 
|---|
 | 205 |  | 
|---|
 | 206 |         } | 
|---|
 | 207 |         else | 
|---|
 | 208 |         { | 
|---|
 | 209 |           source->stop(); | 
|---|
 | 210 |         } | 
|---|
| [4504] | 211 |       } | 
|---|
 | 212 |     } | 
|---|
| [4960] | 213 |   } | 
|---|
| [4504] | 214 | } | 
|---|
 | 215 |  | 
|---|
 | 216 | /** | 
|---|
| [4836] | 217 |  *  Removes all the Buffers that are not anymore needed by any Sources | 
|---|
| [4504] | 218 | */ | 
|---|
| [4746] | 219 | void SoundEngine::flushUnusedBuffers() | 
|---|
| [4504] | 220 | { | 
|---|
| [5819] | 221 |   /// FIXME | 
|---|
| [6846] | 222 |   /*  if(this->sourceList && this->bufferList) | 
|---|
| [4504] | 223 |     { | 
|---|
| [6846] | 224 |       tIterator<BaseObject>* bufferIterator = this->bufferList->getIterator(); | 
|---|
 | 225 |       SoundBuffer* enumBuffer = (SoundBuffer*)bufferIterator->firstElement(); | 
|---|
 | 226 |       while (enumBuffer) | 
|---|
| [4960] | 227 |       { | 
|---|
| [6846] | 228 |         tIterator<BaseObject>* sourceIterator = this->sourceList->getIterator(); | 
|---|
 | 229 |         SoundSource* enumSource = (SoundSource*)sourceIterator->firstElement(); | 
|---|
 | 230 |         while (enumSource) | 
|---|
 | 231 |         { | 
|---|
 | 232 |           if (enumBuffer == enumSource->getBuffer()) | 
|---|
 | 233 |             break; | 
|---|
 | 234 |           enumSource = (SoundSource*)sourceIterator->nextElement(); | 
|---|
 | 235 |         } | 
|---|
 | 236 |         delete sourceIterator; | 
|---|
 | 237 |         if (enumSource == NULL) | 
|---|
 | 238 |           ResourceManager::getInstance()->unload(enumBuffer); | 
|---|
 | 239 |         enumBuffer = (SoundBuffer*)bufferIterator->nextElement(); | 
|---|
| [4960] | 240 |       } | 
|---|
| [6846] | 241 |       delete bufferIterator; | 
|---|
 | 242 |   }*/ /// FIXME | 
|---|
| [4504] | 243 | } | 
|---|
 | 244 |  | 
|---|
 | 245 | /** | 
|---|
| [5293] | 246 |  * flushes all the Buffers | 
|---|
 | 247 |  * deletes them from the BufferList, and also removes them via the ResourceManager. | 
|---|
 | 248 |  */ | 
|---|
| [4746] | 249 | void SoundEngine::flushAllBuffers() | 
|---|
| [4504] | 250 | { | 
|---|
| [4960] | 251 |   if (this->bufferList) | 
|---|
 | 252 |   { | 
|---|
| [5779] | 253 |     while (this->bufferList->size() > 0) | 
|---|
 | 254 |       ResourceManager::getInstance()->unload(static_cast<SoundBuffer*>(this->bufferList->front()), RP_LEVEL); | 
|---|
| [4960] | 255 |   } | 
|---|
| [4504] | 256 | } | 
|---|
 | 257 |  | 
|---|
 | 258 | /** | 
|---|
| [5293] | 259 |  * deletes all the Sources. | 
|---|
| [4830] | 260 |  */ | 
|---|
 | 261 | void SoundEngine::flushAllSources() | 
|---|
 | 262 | { | 
|---|
| [4960] | 263 |   if (this->sourceList) | 
|---|
| [4830] | 264 |   { | 
|---|
| [5779] | 265 |     while(this->sourceList->size() > 0) | 
|---|
 | 266 |       delete this->sourceList->front(); | 
|---|
| [4830] | 267 |   } | 
|---|
 | 268 | } | 
|---|
 | 269 |  | 
|---|
 | 270 | /** | 
|---|
| [4836] | 271 |  *  initializes Audio in general | 
|---|
| [4504] | 272 | */ | 
|---|
| [4746] | 273 | bool SoundEngine::initAudio() | 
|---|
| [4504] | 274 | { | 
|---|
| [6856] | 275 | //   ALenum result; | 
|---|
 | 276 | //   PRINTF(3)("Initialisazing openAL sound engine\n"); | 
|---|
 | 277 | //   const char* defaultDevice =(const char*) alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); | 
|---|
 | 278 | //   const char* deviceList = (const char*)alcGetString(NULL,ALC_DEVICE_SPECIFIER); | 
|---|
 | 279 | //   const char* devWalk = deviceList; | 
|---|
 | 280 | //   //  if (alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE) | 
|---|
 | 281 | //   { // try out enumeration extension | 
|---|
 | 282 | //     PRINTF(3)("Enumeration-extension found\n"); | 
|---|
 | 283 | // | 
|---|
 | 284 | //     PRINTF(3)("Default device: %s\n", defaultDevice); | 
|---|
 | 285 | //     do | 
|---|
 | 286 | //     { | 
|---|
 | 287 | //       PRINTF(3)("%s\n", devWalk); | 
|---|
 | 288 | //       devWalk += strlen(devWalk)+1; | 
|---|
 | 289 | //     } | 
|---|
 | 290 | //     while (devWalk[0] != '\0'); | 
|---|
 | 291 | //  } | 
|---|
| [4504] | 292 |  | 
|---|
| [5819] | 293 |   // INITIALIZING THE DEVICE: | 
|---|
| [6858] | 294 | //   char deviceName[] = | 
|---|
 | 295 | //   #ifdef __WIN32__ | 
|---|
 | 296 | //     "Direct3D"; | 
|---|
 | 297 | //   #else | 
|---|
 | 298 | //     "'( ( devices '( native null ) ) )"; | 
|---|
 | 299 | //   #endif | 
|---|
| [5385] | 300 |  | 
|---|
| [6858] | 301 |   this->device = alcOpenDevice(NULL); | 
|---|
| [6856] | 302 |   this->checkALCError("opening Device", __LINE__); | 
|---|
| [5819] | 303 |  | 
|---|
| [6857] | 304 |   PRINTF(4)("Audio-Specifier: %s\n", (const char*)alcGetString(this->device, ALC_DEVICE_SPECIFIER)); | 
|---|
 | 305 |   PRINTF(4)("Audio-Extensions: %s\n", (const char*)alcGetString(this->device, ALC_EXTENSIONS)); | 
|---|
| [6849] | 306 |  | 
|---|
| [6856] | 307 |  | 
|---|
| [6836] | 308 |   this->context = alcCreateContext(this->device, NULL); | 
|---|
| [6856] | 309 |   this->checkALCError("creating Context", __LINE__); | 
|---|
| [6849] | 310 |  | 
|---|
| [6856] | 311 |   alcMakeContextCurrent(this->context); | 
|---|
 | 312 |   this->checkALCError("making Context Current", __LINE__); | 
|---|
| [6846] | 313 |   // #endif | 
|---|
| [5819] | 314 |  | 
|---|
| [4504] | 315 |   this->setDopplerValues(SOUND_DOPPLER_FACTOR, SOUND_DOPPLER_VELOCITY); | 
|---|
| [6840] | 316 |   this->allocateSources(this->maxSourceCount); | 
|---|
| [4504] | 317 | } | 
|---|
 | 318 |  | 
|---|
| [5917] | 319 |  | 
|---|
| [4504] | 320 | /** | 
|---|
| [5917] | 321 |  * Allocates openAL sources | 
|---|
 | 322 |  * @param count how many sources to allocate | 
|---|
 | 323 |  * @returns true on success, false if at least one source could not be allocated | 
|---|
 | 324 |  */ | 
|---|
 | 325 | bool SoundEngine::allocateSources(unsigned int count) | 
|---|
 | 326 | { | 
|---|
| [6844] | 327 |   unsigned int failCount = 0; | 
|---|
| [5930] | 328 |   for (unsigned int i = 0; i < count; i++) | 
|---|
| [5917] | 329 |   { | 
|---|
| [6836] | 330 |     ALuint source = 0; | 
|---|
| [5917] | 331 |  | 
|---|
| [5930] | 332 |     alGenSources(1, &source); | 
|---|
| [6840] | 333 |     this->checkError("allocate Source", __LINE__); | 
|---|
| [6842] | 334 |     if (!alIsSource(source)) | 
|---|
 | 335 |     { | 
|---|
| [6844] | 336 |       PRINTF(5)("not allocated Source\n"); | 
|---|
 | 337 |       failCount++; | 
|---|
| [6842] | 338 |       continue; | 
|---|
 | 339 |     } | 
|---|
| [5917] | 340 |  | 
|---|
| [5930] | 341 |     alSourcef (source, AL_PITCH,    1.0      ); | 
|---|
 | 342 |     alSourcef (source, AL_GAIN,     this->getEffectsVolume() ); | 
|---|
 | 343 |     alSourcei (source, AL_LOOPING,  AL_FALSE ); | 
|---|
 | 344 |     this->ALSources.push(source); | 
|---|
| [5917] | 345 |   } | 
|---|
| [6844] | 346 |   if (failCount == 0) | 
|---|
 | 347 |     return true; | 
|---|
 | 348 |   else | 
|---|
 | 349 |   { | 
|---|
 | 350 |     PRINTF(2)("Failed to allocate %d of %d SoundSources\n", failCount, count); | 
|---|
 | 351 |   } | 
|---|
| [5917] | 352 | } | 
|---|
 | 353 |  | 
|---|
| [6836] | 354 | bool SoundEngine::checkError(const char* error, unsigned int line) | 
|---|
 | 355 | { | 
|---|
 | 356 |   ALenum errorCode; | 
|---|
 | 357 |   if ((errorCode = alGetError()) != AL_NO_ERROR) | 
|---|
 | 358 |   { | 
|---|
 | 359 |     PRINTF(1)("Error %s (line:%d): '%s'\n", error, line, SoundEngine::getALErrorString(errorCode)); | 
|---|
 | 360 |     return false; | 
|---|
 | 361 |   } | 
|---|
 | 362 |   else | 
|---|
 | 363 |     return true; | 
|---|
 | 364 | } | 
|---|
 | 365 |  | 
|---|
| [6849] | 366 | bool SoundEngine::checkALCError(const char* error, unsigned int line) | 
|---|
 | 367 | { | 
|---|
 | 368 |   ALenum errorCode; | 
|---|
 | 369 |   if ((errorCode = alcGetError(this->device)) != ALC_NO_ERROR) | 
|---|
 | 370 |   { | 
|---|
 | 371 |     PRINTF(1)("Error %s (line:%d): '%s'\n", error, line, SoundEngine::getALCErrorString(errorCode)); | 
|---|
 | 372 |     return false; | 
|---|
 | 373 |   } | 
|---|
 | 374 |   else | 
|---|
 | 375 |     return true; | 
|---|
 | 376 | } | 
|---|
 | 377 |  | 
|---|
 | 378 |  | 
|---|
 | 379 |  | 
|---|
 | 380 | void SoundEngine::listDevices() | 
|---|
 | 381 | { | 
|---|
 | 382 |   printf("%s\n",(const char*)alcGetString(NULL, ALC_DEVICE_SPECIFIER)); | 
|---|
 | 383 | } | 
|---|
 | 384 |  | 
|---|
| [5917] | 385 | /** | 
|---|
| [4836] | 386 |  *  Transforms AL-errors into something readable | 
|---|
 | 387 |  * @param err The error found | 
|---|
| [4504] | 388 | */ | 
|---|
| [5930] | 389 | const char* SoundEngine::getALErrorString(ALenum err) | 
|---|
| [4504] | 390 | { | 
|---|
 | 391 |   switch(err) | 
|---|
| [6846] | 392 |   { | 
|---|
| [4504] | 393 |     case AL_NO_ERROR: | 
|---|
| [5930] | 394 |       return ("AL_NO_ERROR"); | 
|---|
| [4504] | 395 |     case AL_INVALID_NAME: | 
|---|
| [5930] | 396 |       return ("AL_INVALID_NAME"); | 
|---|
| [4504] | 397 |     case AL_INVALID_ENUM: | 
|---|
| [5930] | 398 |       return ("AL_INVALID_ENUM"); | 
|---|
| [4504] | 399 |     case AL_INVALID_VALUE: | 
|---|
| [5930] | 400 |       return ("AL_INVALID_VALUE"); | 
|---|
| [4504] | 401 |     case AL_INVALID_OPERATION: | 
|---|
| [5930] | 402 |       return ("AL_INVALID_OPERATION"); | 
|---|
| [4504] | 403 |     case AL_OUT_OF_MEMORY: | 
|---|
| [5930] | 404 |       return ("AL_OUT_OF_MEMORY"); | 
|---|
| [6846] | 405 |   }; | 
|---|
| [4504] | 406 | } | 
|---|
 | 407 |  | 
|---|
| [4959] | 408 |  | 
|---|
| [6847] | 409 | const char* SoundEngine::getALCErrorString(ALenum err) | 
|---|
| [4504] | 410 | { | 
|---|
 | 411 |   switch(err) | 
|---|
 | 412 |     { | 
|---|
 | 413 |     case ALC_NO_ERROR: | 
|---|
| [6849] | 414 |       return ("AL_NO_ERROR"); | 
|---|
| [4504] | 415 |     case ALC_INVALID_DEVICE: | 
|---|
| [6849] | 416 |       return ("ALC_INVALID_DEVICE"); | 
|---|
| [4504] | 417 |     case ALC_INVALID_CONTEXT: | 
|---|
| [6849] | 418 |       return("ALC_INVALID_CONTEXT"); | 
|---|
| [4504] | 419 |     case ALC_INVALID_ENUM: | 
|---|
| [6849] | 420 |       return("ALC_INVALID_ENUM"); | 
|---|
| [4504] | 421 |     case ALC_INVALID_VALUE: | 
|---|
| [6849] | 422 |       return ("ALC_INVALID_VALUE"); | 
|---|
| [4504] | 423 |     case ALC_OUT_OF_MEMORY: | 
|---|
| [6849] | 424 |       return("ALC_OUT_OF_MEMORY"); | 
|---|
| [4504] | 425 |     }; | 
|---|
 | 426 | } | 
|---|
| [6847] | 427 |  | 
|---|