Changeset 7460 in orxonox.OLD for trunk/src/lib
- Timestamp:
- May 1, 2006, 12:30:34 AM (19 years ago)
- Location:
- trunk/src/lib
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lib/sound/ogg_player.cc
r7314 r7460 32 32 #include "debug.h" 33 33 34 /** 35 * initializes an Ogg-player from a file 36 * @param fileName the file to load 37 */ 38 OggPlayer::OggPlayer(const std::string& fileName) 34 namespace OrxSound 39 35 { 40 this->setClassID(CL_SOUND_OGG_PLAYER, "OggPlayer"); 41 42 this->state = OggPlayer::None; 43 44 this->source = 0; 45 this->buffers[0] = 0; 46 this->buffers[1] = 0; 47 this->musicThreadID = NULL; 48 this->musicMutex = SDL_CreateMutex(); 49 50 if (!fileName.empty()) 51 { 52 if (this->open(fileName)) 53 this->setName(fileName); 54 } 55 56 } 57 58 /** 59 * @brief deletes the OggPlayer 60 */ 61 OggPlayer::~OggPlayer() 62 { 63 this->release(); 64 SDL_DestroyMutex(this->musicMutex); 65 } 66 67 /////////////// 68 // INTERFACE // 69 /////////////// 70 /** 71 * @brief opens a file for playback 72 * @param fileName the file to open 73 */ 74 bool OggPlayer::open(const std::string& fileName) 75 { 76 MutexLock(this->musicMutex); 77 // release old Ogg-File (if loaded) 78 if (this->state & OggPlayer::FileOpened) 79 this->release(); 80 81 // allocating Buffers 82 if (this->buffers[0] == 0) 83 alGenBuffers(2, this->buffers); 84 SoundEngine::checkError("Allocating Buffers", __LINE__); 85 if (this->buffers[0] != 0 && this->buffers[1] != 0) 86 state |= OggPlayer::BuffersAllocated; 87 else 88 { 89 PRINTF(2)("Unable to allocate al-Buffers\n"); 90 this->release(); 91 return false; 92 } 93 // allocating source 94 if (this->source == 0) 95 SoundEngine::getInstance()->popALSource(this->source); 96 if (this->source != 0) 97 state |= OggPlayer::SourceAllocated; 98 else 99 { 100 PRINTF(2)("No more Sources Availiable (maybe you should consider raising the source-count.)\n"); 101 this->release(); 102 return false; 103 } 104 105 // opening the FILE; 106 int result; 107 if(!(oggFile = fopen(fileName.c_str(), "rb"))) 108 { 109 PRINTF(2)("Could not open Ogg file."); 110 this->release(); 111 return false; 112 } 113 // reading the Stream. 114 if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0) 115 { 116 PRINTF(2)("Could not open Ogg stream. %s", getVorbisError(result)); 117 fclose(oggFile); 118 this->release(); 119 return false; 120 } 121 this->state |= OggPlayer::FileOpened; 122 123 // acquiring the vorbis-properties. 124 vorbisInfo = ov_info(&oggStream, -1); 125 vorbisComment = ov_comment(&oggStream, -1); 126 127 if(vorbisInfo->channels == 1) 128 format = AL_FORMAT_MONO16; 129 else 130 format = AL_FORMAT_STEREO16; 131 132 // setting the Source Properties. 133 alSource3f(source, AL_POSITION, 0.0, 0.0, 0.0); 134 alSource3f(source, AL_VELOCITY, 0.0, 0.0, 0.0); 135 alSource3f(source, AL_DIRECTION, 0.0, 0.0, 0.0); 136 alSourcef (source, AL_ROLLOFF_FACTOR, 0.0 ); 137 alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE ); 138 alSourcef (source, AL_GAIN, SoundEngine::getInstance()->getMusicVolume()); 139 SoundEngine::checkError("OggPlayer::open()::SetSourceProperties", __LINE__); 140 141 // Set to State Stopped 142 this->state |= OggPlayer::Stopped; 143 return true; 144 } 145 146 147 /** 148 * @brief start Playing Music. 149 * @returns true on success false otherwise. 150 */ 151 bool OggPlayer::play() 152 { 153 if (!(this->state & OggPlayer::FileOpened)) 154 return false; 155 156 this->state &= ~(OggPlayer::Stopped | OggPlayer::Paused); 157 158 if (!this->playback()) 159 return false; 160 161 if (this->musicThreadID == NULL) 162 return ((this->musicThreadID = SDL_CreateThread(OggPlayer::musicThread, (void*)this)) != NULL); 163 return true; 164 } 165 166 /** 167 * @brief stop the OggPlayer from Playing. 168 */ 169 void OggPlayer::stop() 170 { 171 this->state &= ~(OggPlayer::Playing | OggPlayer::Paused); 172 this->state |= OggPlayer::Stopped; 173 174 this->suspend(); 175 this->rewind(); 176 } 177 178 /** 179 * @brief Pause the Playing. 180 */ 181 void OggPlayer::pause() 182 { 183 this->state &= ~OggPlayer::Playing; 184 185 if (!(this->state & OggPlayer::Stopped)) 186 this->state |= OggPlayer::Paused; 187 188 this->suspend(); 189 } 190 191 /** 192 * @brief rewind to the beginning, and play (if already playing) 193 */ 194 void OggPlayer::rewind() 195 { 196 this->jumpTo(0.0f); 197 } 198 199 /** 200 * @brief jump to Second timeCode in the MusicFile 201 * @param timeCode where to jump to. 202 */ 203 void OggPlayer::jumpTo(float timeCode) 204 { 205 206 if (this->state & OggPlayer::FileOpened) 207 { 208 SDL_mutexP(this->musicMutex); 209 ov_time_seek(&this->oggStream, timeCode); 210 SDL_mutexV(this->musicMutex); 211 } 212 } 213 214 /** 215 * @returns the Length of the Music in Seconds 216 */ 217 float OggPlayer::length() 218 { 219 if (this->state & OggPlayer::FileOpened) 220 return ov_time_total(&this->oggStream, -1); 221 else 222 return 0.0f; 223 } 224 225 226 /** 227 * @returns true if the file is playing 228 */ 229 bool OggPlayer::isPlaying() 230 { 231 if (!(this->state & OggPlayer::FileOpened)) 232 return false; 233 ALenum state; 234 235 alGetSourcei(this->source, AL_SOURCE_STATE, &state); 236 237 return (state == AL_PLAYING); 238 } 239 240 241 242 //////////////////////// 243 // INTERNAL FUNCTIONS // 244 //////////////////////// 245 /** 246 * @brief creates a Thread for Playing back the music even if the rest of the Engine is slow 247 * @param oggPlayer the OggPlayer to play back 248 * @returns -1 on error. 249 */ 250 int OggPlayer::musicThread(void* oggPlayer) 251 { 252 if (oggPlayer == NULL) 253 return -1; 254 OggPlayer* ogg = (OggPlayer*)oggPlayer; 255 256 PRINTF(4)("STARTIG AUDIO THREAD\n"); 257 while (ogg->state & OggPlayer::Playing) 258 { 259 SDL_mutexP(ogg->musicMutex); 260 ogg->update(); 261 SDL_mutexV(ogg->musicMutex); 262 SDL_Delay(1); 263 } 264 PRINTF(4)("End the AudioThread\n"); 265 } 266 267 268 /** 269 * @brief plays back the sound 270 * @return true if running, false otherwise 271 */ 272 bool OggPlayer::playback() 273 { 274 if (!(this->state & OggPlayer::FileOpened)) 275 return false; 276 277 if(this->state & OggPlayer::Playing) 278 return true; 279 this->state |= OggPlayer::Playing; 280 281 SDL_mutexP(this->musicMutex); 282 if(!this->stream(this->buffers[0]) || !this->stream(this->buffers[1])) 283 { 284 SDL_mutexV(this->musicMutex); 285 this->state &= ~OggPlayer::Playing; 286 return false; 287 } 288 289 alSourceQueueBuffers(this->source, 2, this->buffers); 290 if (DEBUG >= 3) 291 SoundEngine::checkError("OggPlayer::playback()::alSourceQueueBuffers", __LINE__); 292 293 alSourcePlay(this->source); 294 if (DEBUG >= 3) 295 SoundEngine::checkError("OggPlayer::playback()::alSourcePlay", __LINE__); 296 SDL_mutexV(this->musicMutex); 297 return true; 298 } 299 300 301 /** 302 * @brief waits for the AudioThread to be finished. 303 */ 304 void OggPlayer::suspend() 305 { 306 if (this->musicThreadID != NULL) 307 { 308 assert (!(this->state & Playing)); 309 SDL_WaitThread(this->musicThreadID, NULL); 310 this->musicThreadID = NULL; 311 } 312 if (this->state & OggPlayer::SourceAllocated) 313 { 314 alSourceStop(this->source); 315 alSourcei(this->source, AL_BUFFER, 0); 316 } 317 } 318 319 /** 320 * @brief updates the stream, this has to be done every few parts of a second, for sound-consistency 321 * @returns true, if the Sound is playing flawlessly 322 */ 323 bool OggPlayer::update() 324 { 325 int processed = 0; 326 bool active = true; 327 328 alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed); 329 if (DEBUG >= 3) 330 SoundEngine::checkError("OggPlayer::update()::alGetSourceI", __LINE__); 331 332 while(processed--) 333 { 334 ALuint buffer; 335 336 alSourceUnqueueBuffers(source, 1, &buffer); 337 if (DEBUG >= 3) 338 SoundEngine::checkError("OggPlayer::update()::unqueue", __LINE__); 339 340 active = stream(buffer); 341 342 alSourceQueueBuffers(source, 1, &buffer); 343 if (DEBUG >= 3) 344 SoundEngine::checkError("OggPlayer::update()::queue", __LINE__); 345 } 346 347 return active; 348 } 349 350 /** 351 * @brief gets a new Stream from buffer 352 * @param buffer the buffer to get the stream from 353 * @return true, if everything worked as planed 354 */ 355 bool OggPlayer::stream(ALuint buffer) 356 { 357 if (unlikely(!(this->state & Playing))) 358 return false; 359 char pcm[OGG_PLAYER_BUFFER_SIZE]; 360 int size = 0; 361 int section; 362 int result; 363 364 while(size < OGG_PLAYER_BUFFER_SIZE) 365 { 366 result = ov_read(&this->oggStream, pcm + size, OGG_PLAYER_BUFFER_SIZE - size, 0, 2, 1, §ion); 367 368 if(result > 0) 369 size += result; 370 else if(result < 0) 371 throw getVorbisError(result); 372 else /* eof */ 373 ov_time_seek(&this->oggStream, 0.0); 374 } 375 376 if(size == 0) 377 return false; 378 379 alBufferData(buffer, format, pcm, size, vorbisInfo->rate); 380 if (DEBUG >= 3) 381 SoundEngine::checkError("OggPlayer::stream()::BUFFER", __LINE__); 382 383 return true; 384 } 385 386 387 /** 388 * @brief releases a stream 389 */ 390 void OggPlayer::release() 391 { 392 if (this->state & OggPlayer::SourceAllocated) 393 { 394 assert(alIsSource(this->source)); 395 if (this->state & OggPlayer::Playing); 396 { 397 // Kill the Music Thread. 398 this->state &= ~OggPlayer::Playing; 399 this->suspend(); 400 401 SoundEngine::checkError("OggPlayer::release()::alSourceStop", __LINE__); 402 } 403 empty(); 404 alSourcei(this->source, AL_BUFFER, 0); 405 SoundEngine::getInstance()->pushALSource(this->source); 36 /** 37 * initializes an Ogg-player from a file 38 * @param fileName the file to load 39 */ 40 OggPlayer::OggPlayer(const std::string& fileName) 41 { 42 this->setClassID(CL_SOUND_OGG_PLAYER, "OggPlayer"); 43 44 this->state = OggPlayer::None; 45 406 46 this->source = 0; 407 this->state &= ~SourceAllocated;408 }409 if (this->state & OggPlayer::BuffersAllocated)410 {411 assert (this->buffers[0] != 0 && this->buffers[1] != 0);412 alDeleteBuffers(2, buffers);413 SoundEngine::checkError("OggPlayer::release()::alDeleteBuffers", __LINE__);414 47 this->buffers[0] = 0; 415 48 this->buffers[1] = 0; 416 this->state &= ~OggPlayer::BuffersAllocated; 417 } 418 419 if (this->state & OggPlayer::FileOpened) 420 { 421 ov_clear(&oggStream); 422 this->state &= ~OggPlayer::FileOpened; 423 } 424 425 } 426 427 428 /** 429 * @brief empties the buffers 430 */ 431 void OggPlayer::empty() 432 { 433 int queued; 434 435 alGetSourcei(source, AL_BUFFERS_QUEUED, &queued); 436 437 while(queued--) 438 { 439 ALuint buffer; 440 441 alSourceUnqueueBuffers(source, 1, &buffer); 442 SoundEngine::checkError("OggPlayer::empty()::unqueue Buffers", __LINE__); 443 } 444 } 445 446 447 ///////////////////// 448 // DEBUG FUNCTIONS // 449 ///////////////////// 450 /** 451 * displays some info about the ogg-file 452 */ 453 void OggPlayer::debug() const 454 { 455 cout 456 << "version " << vorbisInfo->version << "\n" 457 << "channels " << vorbisInfo->channels << "\n" 458 << "rate (hz) " << vorbisInfo->rate << "\n" 459 << "bitrate upper " << vorbisInfo->bitrate_upper << "\n" 460 << "bitrate nominal " << vorbisInfo->bitrate_nominal << "\n" 461 << "bitrate lower " << vorbisInfo->bitrate_lower << "\n" 462 << "bitrate window " << vorbisInfo->bitrate_window << "\n" 463 << "\n" 464 << "vendor " << vorbisComment->vendor << "\n"; 465 466 for(int i = 0; i < vorbisComment->comments; i++) 467 cout << " " << vorbisComment->user_comments[i] << "\n"; 468 469 cout << endl; 470 } 471 472 473 void OggPlayer::printState() const 474 { 475 PRINTF(0)("OggPlayer is in the following States: "); 476 if (this->state & OggPlayer::FileOpened) 477 PRINT(0)("FileOpened "); 478 if (this->state & OggPlayer::SourceAllocated) 479 PRINT(0)("SourceAllocated "); 480 if (this->state & OggPlayer::BuffersAllocated) 481 PRINT(0)("BuffersAllocated "); 482 if (this->state & OggPlayer::Stopped) 483 PRINT(0)("Stopped "); 484 if (this->state & OggPlayer::Playing) 485 PRINT(0)("Playing "); 486 if (this->state & OggPlayer::Paused) 487 PRINT(0)("Paused "); 488 if (this->state & OggPlayer::Error) 489 PRINT(0)("Error "); 490 PRINT(0)("\n"); 491 } 492 493 /** 494 * returns errors 495 * @param code the error-code 496 * @return the error as a String 497 */ 498 const char* OggPlayer::getVorbisError(int code) 499 { 500 switch(code) 501 { 49 this->musicThreadID = NULL; 50 this->musicMutex = SDL_CreateMutex(); 51 52 if (!fileName.empty()) 53 { 54 if (this->open(fileName)) 55 this->setName(fileName); 56 } 57 58 } 59 60 /** 61 * @brief deletes the OggPlayer 62 */ 63 OggPlayer::~OggPlayer() 64 { 65 this->release(); 66 SDL_DestroyMutex(this->musicMutex); 67 } 68 69 /////////////// 70 // INTERFACE // 71 /////////////// 72 /** 73 * @brief opens a file for playback 74 * @param fileName the file to open 75 */ 76 bool OggPlayer::open(const std::string& fileName) 77 { 78 MutexLock(this->musicMutex); 79 // release old Ogg-File (if loaded) 80 if (this->state & OggPlayer::FileOpened) 81 this->release(); 82 83 // allocating Buffers 84 if (this->buffers[0] == 0) 85 alGenBuffers(2, this->buffers); 86 SoundEngine::checkError("Allocating Buffers", __LINE__); 87 if (this->buffers[0] != 0 && this->buffers[1] != 0) 88 state |= OggPlayer::BuffersAllocated; 89 else 90 { 91 PRINTF(2)("Unable to allocate al-Buffers\n"); 92 this->release(); 93 return false; 94 } 95 // allocating source 96 if (this->source == 0) 97 SoundEngine::getInstance()->popALSource(this->source); 98 if (this->source != 0) 99 state |= OggPlayer::SourceAllocated; 100 else 101 { 102 PRINTF(2)("No more Sources Availiable (maybe you should consider raising the source-count.)\n"); 103 this->release(); 104 return false; 105 } 106 107 // opening the FILE; 108 int result; 109 if(!(oggFile = fopen(fileName.c_str(), "rb"))) 110 { 111 PRINTF(2)("Could not open Ogg file."); 112 this->release(); 113 return false; 114 } 115 // reading the Stream. 116 if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0) 117 { 118 PRINTF(2)("Could not open Ogg stream. %s", getVorbisError(result)); 119 fclose(oggFile); 120 this->release(); 121 return false; 122 } 123 this->state |= OggPlayer::FileOpened; 124 125 // acquiring the vorbis-properties. 126 vorbisInfo = ov_info(&oggStream, -1); 127 vorbisComment = ov_comment(&oggStream, -1); 128 129 if(vorbisInfo->channels == 1) 130 format = AL_FORMAT_MONO16; 131 else 132 format = AL_FORMAT_STEREO16; 133 134 // setting the Source Properties. 135 alSource3f(source, AL_POSITION, 0.0, 0.0, 0.0); 136 alSource3f(source, AL_VELOCITY, 0.0, 0.0, 0.0); 137 alSource3f(source, AL_DIRECTION, 0.0, 0.0, 0.0); 138 alSourcef (source, AL_ROLLOFF_FACTOR, 0.0 ); 139 alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE ); 140 alSourcef (source, AL_GAIN, SoundEngine::getInstance()->getMusicVolume()); 141 SoundEngine::checkError("OggPlayer::open()::SetSourceProperties", __LINE__); 142 143 // Set to State Stopped 144 this->state |= OggPlayer::Stopped; 145 return true; 146 } 147 148 149 /** 150 * @brief start Playing Music. 151 * @returns true on success false otherwise. 152 */ 153 bool OggPlayer::play() 154 { 155 if (!(this->state & OggPlayer::FileOpened)) 156 return false; 157 158 this->state &= ~(OggPlayer::Stopped | OggPlayer::Paused); 159 160 if (!this->playback()) 161 return false; 162 163 if (this->musicThreadID == NULL) 164 return ((this->musicThreadID = SDL_CreateThread(OggPlayer::musicThread, (void*)this)) != NULL); 165 return true; 166 } 167 168 /** 169 * @brief stop the OggPlayer from Playing. 170 */ 171 void OggPlayer::stop() 172 { 173 this->state &= ~(OggPlayer::Playing | OggPlayer::Paused); 174 this->state |= OggPlayer::Stopped; 175 176 this->suspend(); 177 this->rewind(); 178 } 179 180 /** 181 * @brief Pause the Playing. 182 */ 183 void OggPlayer::pause() 184 { 185 this->state &= ~OggPlayer::Playing; 186 187 if (!(this->state & OggPlayer::Stopped)) 188 this->state |= OggPlayer::Paused; 189 190 this->suspend(); 191 } 192 193 /** 194 * @brief rewind to the beginning, and play (if already playing) 195 */ 196 void OggPlayer::rewind() 197 { 198 this->jumpTo(0.0f); 199 } 200 201 /** 202 * @brief jump to Second timeCode in the MusicFile 203 * @param timeCode where to jump to. 204 */ 205 void OggPlayer::jumpTo(float timeCode) 206 { 207 208 if (this->state & OggPlayer::FileOpened) 209 { 210 SDL_mutexP(this->musicMutex); 211 ov_time_seek(&this->oggStream, timeCode); 212 SDL_mutexV(this->musicMutex); 213 } 214 } 215 216 /** 217 * @returns the Length of the Music in Seconds 218 */ 219 float OggPlayer::length() 220 { 221 if (this->state & OggPlayer::FileOpened) 222 return ov_time_total(&this->oggStream, -1); 223 else 224 return 0.0f; 225 } 226 227 228 /** 229 * @returns true if the file is playing 230 */ 231 bool OggPlayer::isPlaying() 232 { 233 if (!(this->state & OggPlayer::FileOpened)) 234 return false; 235 ALenum state; 236 237 alGetSourcei(this->source, AL_SOURCE_STATE, &state); 238 239 return (state == AL_PLAYING); 240 } 241 242 243 244 //////////////////////// 245 // INTERNAL FUNCTIONS // 246 //////////////////////// 247 /** 248 * @brief creates a Thread for Playing back the music even if the rest of the Engine is slow 249 * @param oggPlayer the OggPlayer to play back 250 * @returns -1 on error. 251 */ 252 int OggPlayer::musicThread(void* oggPlayer) 253 { 254 if (oggPlayer == NULL) 255 return -1; 256 OggPlayer* ogg = (OggPlayer*)oggPlayer; 257 258 PRINTF(4)("STARTIG AUDIO THREAD\n"); 259 while (ogg->state & OggPlayer::Playing) 260 { 261 SDL_mutexP(ogg->musicMutex); 262 ogg->update(); 263 SDL_mutexV(ogg->musicMutex); 264 SDL_Delay(1); 265 } 266 PRINTF(4)("End the AudioThread\n"); 267 } 268 269 270 /** 271 * @brief plays back the sound 272 * @return true if running, false otherwise 273 */ 274 bool OggPlayer::playback() 275 { 276 if (!(this->state & OggPlayer::FileOpened)) 277 return false; 278 279 if(this->state & OggPlayer::Playing) 280 return true; 281 this->state |= OggPlayer::Playing; 282 283 SDL_mutexP(this->musicMutex); 284 if(!this->stream(this->buffers[0]) || !this->stream(this->buffers[1])) 285 { 286 SDL_mutexV(this->musicMutex); 287 this->state &= ~OggPlayer::Playing; 288 return false; 289 } 290 291 alSourceQueueBuffers(this->source, 2, this->buffers); 292 if (DEBUG >= 3) 293 SoundEngine::checkError("OggPlayer::playback()::alSourceQueueBuffers", __LINE__); 294 295 alSourcePlay(this->source); 296 if (DEBUG >= 3) 297 SoundEngine::checkError("OggPlayer::playback()::alSourcePlay", __LINE__); 298 SDL_mutexV(this->musicMutex); 299 return true; 300 } 301 302 303 /** 304 * @brief waits for the AudioThread to be finished. 305 */ 306 void OggPlayer::suspend() 307 { 308 if (this->musicThreadID != NULL) 309 { 310 assert (!(this->state & Playing)); 311 SDL_WaitThread(this->musicThreadID, NULL); 312 this->musicThreadID = NULL; 313 } 314 if (this->state & OggPlayer::SourceAllocated) 315 { 316 alSourceStop(this->source); 317 alSourcei(this->source, AL_BUFFER, 0); 318 } 319 } 320 321 /** 322 * @brief updates the stream, this has to be done every few parts of a second, for sound-consistency 323 * @returns true, if the Sound is playing flawlessly 324 */ 325 bool OggPlayer::update() 326 { 327 int processed = 0; 328 bool active = true; 329 330 alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed); 331 if (DEBUG >= 3) 332 SoundEngine::checkError("OggPlayer::update()::alGetSourceI", __LINE__); 333 334 while(processed--) 335 { 336 ALuint buffer; 337 338 alSourceUnqueueBuffers(source, 1, &buffer); 339 if (DEBUG >= 3) 340 SoundEngine::checkError("OggPlayer::update()::unqueue", __LINE__); 341 342 active = stream(buffer); 343 344 alSourceQueueBuffers(source, 1, &buffer); 345 if (DEBUG >= 3) 346 SoundEngine::checkError("OggPlayer::update()::queue", __LINE__); 347 } 348 349 return active; 350 } 351 352 /** 353 * @brief gets a new Stream from buffer 354 * @param buffer the buffer to get the stream from 355 * @return true, if everything worked as planed 356 */ 357 bool OggPlayer::stream(ALuint buffer) 358 { 359 if (unlikely(!(this->state & Playing))) 360 return false; 361 char pcm[OGG_PLAYER_BUFFER_SIZE]; 362 int size = 0; 363 int section; 364 int result; 365 366 while(size < OGG_PLAYER_BUFFER_SIZE) 367 { 368 result = ov_read(&this->oggStream, pcm + size, OGG_PLAYER_BUFFER_SIZE - size, 0, 2, 1, §ion); 369 370 if(result > 0) 371 size += result; 372 else if(result < 0) 373 throw getVorbisError(result); 374 else /* eof */ 375 ov_time_seek(&this->oggStream, 0.0); 376 } 377 378 if(size == 0) 379 return false; 380 381 alBufferData(buffer, format, pcm, size, vorbisInfo->rate); 382 if (DEBUG >= 3) 383 SoundEngine::checkError("OggPlayer::stream()::BUFFER", __LINE__); 384 385 return true; 386 } 387 388 389 /** 390 * @brief releases a stream 391 */ 392 void OggPlayer::release() 393 { 394 if (this->state & OggPlayer::SourceAllocated) 395 { 396 assert(alIsSource(this->source)); 397 if (this->state & OggPlayer::Playing); 398 { 399 // Kill the Music Thread. 400 this->state &= ~OggPlayer::Playing; 401 this->suspend(); 402 403 SoundEngine::checkError("OggPlayer::release()::alSourceStop", __LINE__); 404 } 405 empty(); 406 alSourcei(this->source, AL_BUFFER, 0); 407 SoundEngine::getInstance()->pushALSource(this->source); 408 this->source = 0; 409 this->state &= ~SourceAllocated; 410 } 411 if (this->state & OggPlayer::BuffersAllocated) 412 { 413 assert (this->buffers[0] != 0 && this->buffers[1] != 0); 414 alDeleteBuffers(2, buffers); 415 SoundEngine::checkError("OggPlayer::release()::alDeleteBuffers", __LINE__); 416 this->buffers[0] = 0; 417 this->buffers[1] = 0; 418 this->state &= ~OggPlayer::BuffersAllocated; 419 } 420 421 if (this->state & OggPlayer::FileOpened) 422 { 423 ov_clear(&oggStream); 424 this->state &= ~OggPlayer::FileOpened; 425 } 426 427 } 428 429 430 /** 431 * @brief empties the buffers 432 */ 433 void OggPlayer::empty() 434 { 435 int queued; 436 437 alGetSourcei(source, AL_BUFFERS_QUEUED, &queued); 438 439 while(queued--) 440 { 441 ALuint buffer; 442 443 alSourceUnqueueBuffers(source, 1, &buffer); 444 SoundEngine::checkError("OggPlayer::empty()::unqueue Buffers", __LINE__); 445 } 446 } 447 448 449 ///////////////////// 450 // DEBUG FUNCTIONS // 451 ///////////////////// 452 /** 453 * displays some info about the ogg-file 454 */ 455 void OggPlayer::debug() const 456 { 457 std::cout 458 << "version " << vorbisInfo->version << "\n" 459 << "channels " << vorbisInfo->channels << "\n" 460 << "rate (hz) " << vorbisInfo->rate << "\n" 461 << "bitrate upper " << vorbisInfo->bitrate_upper << "\n" 462 << "bitrate nominal " << vorbisInfo->bitrate_nominal << "\n" 463 << "bitrate lower " << vorbisInfo->bitrate_lower << "\n" 464 << "bitrate window " << vorbisInfo->bitrate_window << "\n" 465 << "\n" 466 << "vendor " << vorbisComment->vendor << "\n"; 467 468 for(int i = 0; i < vorbisComment->comments; i++) 469 std::cout << " " << vorbisComment->user_comments[i] << "\n"; 470 471 std::cout << std::endl; 472 } 473 474 475 void OggPlayer::printState() const 476 { 477 PRINTF(0)("OggPlayer is in the following States: "); 478 if (this->state & OggPlayer::FileOpened) 479 PRINT(0)("FileOpened "); 480 if (this->state & OggPlayer::SourceAllocated) 481 PRINT(0)("SourceAllocated "); 482 if (this->state & OggPlayer::BuffersAllocated) 483 PRINT(0)("BuffersAllocated "); 484 if (this->state & OggPlayer::Stopped) 485 PRINT(0)("Stopped "); 486 if (this->state & OggPlayer::Playing) 487 PRINT(0)("Playing "); 488 if (this->state & OggPlayer::Paused) 489 PRINT(0)("Paused "); 490 if (this->state & OggPlayer::Error) 491 PRINT(0)("Error "); 492 PRINT(0)("\n"); 493 } 494 495 /** 496 * returns errors 497 * @param code the error-code 498 * @return the error as a String 499 */ 500 const char* OggPlayer::getVorbisError(int code) 501 { 502 switch(code) 503 { 502 504 case OV_EREAD: 503 505 return ("Read from media."); … … 512 514 default: 513 515 return ("Unknown Ogg error."); 514 } 516 } 517 } 518 515 519 } 516 -
trunk/src/lib/sound/ogg_player.h
r7331 r7460 7 7 #ifndef _OGG_PLAYER_H 8 8 #define _OGG_PLAYER_H 9 10 using namespace std;11 9 12 10 #include "base_object.h" … … 22 20 #define OGG_PLAYER_BUFFER_SIZE (8096 * 2) 23 21 22 namespace OrxSound 23 { 24 // the definition of a Ogg-Player 25 class OggPlayer : public BaseObject 26 { 27 public: 28 /** 29 * An enumerator defining in what State the OggPlayer is. 30 * The OggPlayer can be in multiple States listed here. 31 * It can as an example be in FileOpened and Stopped. 32 */ 33 typedef enum { 34 None = 0x000, //!< Initialized 35 FileOpened = 0x100, //!< File is Opened 36 SourceAllocated = 0x200, //!< Source is Allocated. 37 BuffersAllocated = 0x400, //!< 2 Buffers are Allocated. 38 Stopped = 0x010, //!< OggPlayer is stopped. 39 Playing = 0x020, //!< OggPlayer is Playing. 40 Paused = 0x040, //!< OggPlayer is Paused. 41 Error = 0x001, //!< An Error has occured. 42 } State; 24 43 25 // the definition of a Ogg-Player 26 class OggPlayer : public BaseObject 27 { 28 public: 29 /** 30 * An enumerator defining in what State the OggPlayer is. 31 * The OggPlayer can be in multiple States listed here. 32 * It can as an example be in FileOpened and Stopped. 33 */ 34 typedef enum { 35 None = 0x000, //!< Initialized 36 FileOpened = 0x100, //!< File is Opened 37 SourceAllocated = 0x200, //!< Source is Allocated. 38 BuffersAllocated = 0x400, //!< 2 Buffers are Allocated. 39 Stopped = 0x010, //!< OggPlayer is stopped. 40 Playing = 0x020, //!< OggPlayer is Playing. 41 Paused = 0x040, //!< OggPlayer is Paused. 42 Error = 0x001, //!< An Error has occured. 43 } State; 44 OggPlayer(const std::string& fileName = ""); 45 virtual ~OggPlayer(); 46 /** @param state compare this State with the internal State @returns true on match */ 47 bool operator==(OggPlayer::State state) { return this->state & state; }; 44 48 45 OggPlayer(const std::string& fileName = ""); 46 virtual ~OggPlayer(); 47 /** @param state compare this State with the internal State @returns true on match */ 48 bool operator==(OggPlayer::State state) { return this->state & state; }; 49 bool open(const std::string& fileName = ""); 49 50 50 bool open(const std::string& fileName = ""); 51 bool play(); 52 void stop(); 53 void pause(); 54 void rewind(); // convenience 55 void jumpTo(float timeCode); 51 56 52 bool play(); 53 void stop(); 54 void pause(); 55 void rewind(); // convenience 56 void jumpTo(float timeCode); 57 float length(); 58 bool isPlaying(); 59 bool getState() { return this->state; }; 57 60 58 float length(); 59 bool isPlaying(); 60 bool getState() { return this->state; }; 61 62 void debug() const; 63 void printState() const; 64 const char* getVorbisError(int code); 61 void debug() const; 62 void printState() const; 63 const char* getVorbisError(int code); 65 64 66 65 67 private:68 static int musicThread(void* oggPlayer);69 bool playback();70 void suspend();71 bool update();66 private: 67 static int musicThread(void* oggPlayer); 68 bool playback(); 69 void suspend(); 70 bool update(); 72 71 73 void release();72 void release(); 74 73 75 bool stream(ALuint buffer);76 void empty();74 bool stream(ALuint buffer); 75 void empty(); 77 76 78 private:79 FILE* oggFile; //!< general file-handler, to open the sound-file80 OggVorbis_File oggStream; //!< The stream this Ogg-player is playing back81 vorbis_info* vorbisInfo; //!< The information held in the opened ogg-file82 vorbis_comment* vorbisComment; //!< Comments about the ogg-file77 private: 78 FILE* oggFile; //!< general file-handler, to open the sound-file 79 OggVorbis_File oggStream; //!< The stream this Ogg-player is playing back 80 vorbis_info* vorbisInfo; //!< The information held in the opened ogg-file 81 vorbis_comment* vorbisComment; //!< Comments about the ogg-file 83 82 84 ALuint buffers[2]; //!< buffers that handle sequentially buffering of the audio85 ALuint source; //!< The source we play back on86 ALenum format; //!< The format we play back87 unsigned int state; //!< The States the OggPlayer is in (this can be multiple entries from OggPlayer::State).83 ALuint buffers[2]; //!< buffers that handle sequentially buffering of the audio 84 ALuint source; //!< The source we play back on 85 ALenum format; //!< The format we play back 86 unsigned int state; //!< The States the OggPlayer is in (this can be multiple entries from OggPlayer::State). 88 87 89 SDL_Thread* musicThreadID; //!< The Thread in which music is Played back.90 SDL_mutex* musicMutex; //!< A Mutex so that the two threads do not interfere.91 };88 SDL_Thread* musicThreadID; //!< The Thread in which music is Played back. 89 SDL_mutex* musicMutex; //!< A Mutex so that the two threads do not interfere. 90 }; 92 91 93 92 } 94 93 #endif /* _OGG_PLAYER_H */ -
trunk/src/lib/sound/sound_buffer.cc
r7290 r7460 23 23 #include <cassert> 24 24 25 using namespace std; 25 namespace OrxSound 26 { 27 ////////////////// 28 /* SOUND-BUFFER */ 29 ////////////////// 30 /** 31 * Creates a Soundbuffer out of an inputfile 32 * @param fileName The name of the File 33 */ 34 SoundBuffer::SoundBuffer(const std::string& fileName) 35 { 36 this->setClassID(CL_SOUND_BUFFER, "SoundBuffer"); 37 this->setName(fileName); 26 38 27 ////////////////// 28 /* SOUND-BUFFER */ 29 ////////////////// 30 /** 31 * Creates a Soundbuffer out of an inputfile 32 * @param fileName The name of the File 33 */ 34 SoundBuffer::SoundBuffer(const std::string& fileName) 35 { 36 this->setClassID(CL_SOUND_BUFFER, "SoundBuffer"); 37 this->setName(fileName); 38 39 // generate a Buffer 40 alGenBuffers(1, &this->bufferID); 41 SoundEngine::checkError("Generate Buffer", __LINE__); 42 this->loadWAV(fileName); 43 } 44 45 SoundBuffer::~SoundBuffer() 46 { 47 // SoundEngine::getInstance()->removeBuffer(this); 48 alDeleteBuffers(1, &this->bufferID); 49 SoundEngine::checkError("SoundBuffer: Delete Buffer", __LINE__); 50 } 51 52 /** 53 * @brief loads a Waveform from the local fileSystem into this Source. 54 * @param fileName the Name of the File to Load. 55 * @returns true on success. 56 */ 57 bool SoundBuffer::loadWAV(const std::string& fileName) 58 { 59 SDL_AudioSpec wavSpec; 60 Uint32 wavLength; 61 Uint8 *wavBuffer; 62 63 /* Load the WAV */ 64 if( SDL_LoadWAV(fileName.c_str(), &wavSpec, &wavBuffer, &wavLength) == NULL) 65 { 66 PRINTF(2)("Could not open %s: %s\n", fileName.c_str(), SDL_GetError()); 67 return false; 39 // generate a Buffer 40 alGenBuffers(1, &this->bufferID); 41 SoundEngine::checkError("Generate Buffer", __LINE__); 42 this->loadWAV(fileName); 68 43 } 69 44 70 alBufferData(this->bufferID, SoundBuffer::sdlAudioSpecToAlFormat(&wavSpec), wavBuffer, wavLength, wavSpec.freq); 71 SDL_FreeWAV(wavBuffer); 72 if (SoundEngine::checkError("Could not load Wave file", __LINE__)) 73 return true; 74 else 75 return false; 45 SoundBuffer::~SoundBuffer() 46 { 47 // SoundEngine::getInstance()->removeBuffer(this); 48 alDeleteBuffers(1, &this->bufferID); 49 SoundEngine::checkError("SoundBuffer: Delete Buffer", __LINE__); 50 } 51 52 /** 53 * @brief loads a Waveform from the local fileSystem into this Source. 54 * @param fileName the Name of the File to Load. 55 * @returns true on success. 56 */ 57 bool SoundBuffer::loadWAV(const std::string& fileName) 58 { 59 SDL_AudioSpec wavSpec; 60 Uint32 wavLength; 61 Uint8 *wavBuffer; 62 63 /* Load the WAV */ 64 if( SDL_LoadWAV(fileName.c_str(), &wavSpec, &wavBuffer, &wavLength) == NULL) 65 { 66 PRINTF(2)("Could not open %s: %s\n", fileName.c_str(), SDL_GetError()); 67 return false; 68 } 69 70 alBufferData(this->bufferID, SoundBuffer::sdlAudioSpecToAlFormat(&wavSpec), wavBuffer, wavLength, wavSpec.freq); 71 SDL_FreeWAV(wavBuffer); 72 if (SoundEngine::checkError("Could not load Wave file", __LINE__)) 73 return true; 74 else 75 return false; 76 } 77 78 /** 79 * @brief converts an SDL_AudioSpec into a valid OpenAL AUDIO_FORMAT enumerator 80 * @param audiospec the AudioSpec to convert. 81 * @returns the AL_FORMAT 82 */ 83 ALenum SoundBuffer::sdlAudioSpecToAlFormat(const SDL_AudioSpec* audiospec) 84 { 85 assert (audiospec != NULL); 86 bool stereo = true; 87 bool is16Bit = true; 88 if (audiospec->format == AUDIO_U8 || audiospec->format == AUDIO_S8) 89 is16Bit = false; 90 if (audiospec->channels == 1) 91 stereo = false; 92 93 if (!stereo && !is16Bit) 94 return AL_FORMAT_MONO8; 95 else if (!stereo && is16Bit) 96 return AL_FORMAT_MONO16; 97 else if (stereo && !is16Bit) 98 return AL_FORMAT_STEREO8; 99 else if (stereo && is16Bit) 100 return AL_FORMAT_STEREO16; 101 } 76 102 } 77 78 /**79 * @brief converts an SDL_AudioSpec into a valid OpenAL AUDIO_FORMAT enumerator80 * @param audiospec the AudioSpec to convert.81 * @returns the AL_FORMAT82 */83 ALenum SoundBuffer::sdlAudioSpecToAlFormat(const SDL_AudioSpec* audiospec)84 {85 assert (audiospec != NULL);86 bool stereo = true;87 bool is16Bit = true;88 if (audiospec->format == AUDIO_U8 || audiospec->format == AUDIO_S8)89 is16Bit = false;90 if (audiospec->channels == 1)91 stereo = false;92 93 if (!stereo && !is16Bit)94 return AL_FORMAT_MONO8;95 else if (!stereo && is16Bit)96 return AL_FORMAT_MONO16;97 else if (stereo && !is16Bit)98 return AL_FORMAT_STEREO8;99 else if (stereo && is16Bit)100 return AL_FORMAT_STEREO16;101 }102 -
trunk/src/lib/sound/sound_buffer.h
r7221 r7460 13 13 typedef struct SDL_AudioSpec; 14 14 15 //! A class that represents a datastructure to play Sounds. 16 class SoundBuffer : public BaseObject 15 namespace OrxSound 17 16 { 17 //! A class that represents a datastructure to play Sounds. 18 class SoundBuffer : public BaseObject 19 { 18 20 public: 19 21 SoundBuffer(const std::string& fileName); … … 33 35 ALsizei size; //!< The size of the Buffer. 34 36 ALboolean loop; //!< loop information. 35 };36 37 }; 38 } 37 39 #endif /* _SOUND_BUFFER_H */ -
trunk/src/lib/sound/sound_engine.cc
r7318 r7460 29 29 #include "globals.h" 30 30 31 using namespace std; 32 33 34 ////////////////// 35 /* SOUND-ENGINE */ 36 ////////////////// 37 /** 38 * @brief standard constructor 39 */ 40 SoundEngine::SoundEngine () 31 namespace OrxSound 41 32 { 42 this->setClassID(CL_SOUND_ENGINE, "SoundEngine"); 43 this->setName("SoundEngine"); 44 45 this->listener = NULL; 46 this->bufferList = NULL; 47 this->sourceList = NULL; 48 49 this->device = NULL; 50 this->context = NULL; 51 52 this->maxSourceCount = 32; 53 54 this->effectsVolume = .80; 55 this->musicVolume = .75; 56 57 this->sourceMutex = SDL_CreateMutex(); 58 } 59 60 /** 61 * @brief the singleton reference to this class 62 */ 63 SoundEngine* SoundEngine::singletonRef = NULL; 64 65 /** 66 * @brief standard destructor 67 */ 68 SoundEngine::~SoundEngine () 69 { 70 // deleting all the SoundSources 71 if(this->sourceList != NULL) 72 { 73 while (this->sourceList->size() > 0) 74 delete static_cast<SoundSource*>(this->sourceList->front()); 75 } 76 77 while(!this->ALSources.empty()) 78 { 79 if (alIsSource(this->ALSources.top())) 80 { 81 alDeleteSources(1, &this->ALSources.top()); 82 SoundEngine::checkError("Deleting Source", __LINE__); 33 34 ////////////////// 35 /* SOUND-ENGINE */ 36 ////////////////// 37 /** 38 * @brief standard constructor 39 */ 40 SoundEngine::SoundEngine () 41 { 42 this->setClassID(CL_SOUND_ENGINE, "SoundEngine"); 43 this->setName("SoundEngine"); 44 45 this->listener = NULL; 46 this->bufferList = NULL; 47 this->sourceList = NULL; 48 49 this->device = NULL; 50 this->context = NULL; 51 52 this->maxSourceCount = 32; 53 54 this->effectsVolume = .80; 55 this->musicVolume = .75; 56 57 this->sourceMutex = SDL_CreateMutex(); 58 } 59 60 /** 61 * @brief the singleton reference to this class 62 */ 63 SoundEngine* SoundEngine::singletonRef = NULL; 64 65 /** 66 * @brief standard destructor 67 */ 68 SoundEngine::~SoundEngine () 69 { 70 // deleting all the SoundSources 71 if(this->sourceList != NULL) 72 { 73 while (this->sourceList->size() > 0) 74 delete static_cast<SoundSource*>(this->sourceList->front()); 75 } 76 77 while(!this->ALSources.empty()) 78 { 79 if (alIsSource(this->ALSources.top())) 80 { 81 alDeleteSources(1, &this->ALSources.top()); 82 SoundEngine::checkError("Deleting Source", __LINE__); 83 } 84 else 85 PRINTF(1)("%d is not a Source\n", this->ALSources.top()); 86 87 this->ALSources.pop(); 88 } 89 90 // deleting all the SoundBuffers 91 if (this->bufferList != NULL) 92 { 93 while(this->bufferList->size() > 0) 94 ResourceManager::getInstance()->unload(static_cast<SoundBuffer*>(this->bufferList->front())); 95 } 96 97 // removing openAL from AudioResource 98 //! @todo this should be terminated through alc 99 //alutExit(); 100 101 SDL_DestroyMutex(this->sourceMutex); 102 103 SoundEngine::singletonRef = NULL; 104 } 105 106 /** 107 * @brief loads the settings of the SoundEngine from an ini-file 108 */ 109 void SoundEngine::loadSettings() 110 { 111 MultiType channels = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_AUDIO_CHANNELS, "32"); 112 this->maxSourceCount = channels.getInt(); 113 114 MultiType effectsVolume = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_EFFECTS_VOLUME, "80"); 115 this->effectsVolume = effectsVolume.getFloat()/100.0; 116 117 MultiType musicVolume = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_MUSIC_VOLUME, "75"); 118 this->musicVolume = musicVolume.getFloat()/100.0; 119 } 120 121 /** 122 * @brief creates a new SoundSource. 123 * @param fileName The Name to load the SoundBuffer from 124 * @param sourceNode The sourceNode to bind this SoundSource to. 125 * @returns The newly created SoundSource 126 * 127 * acctualy this is nothing more than a wrapper around the ResourceManager. 128 */ 129 SoundSource* SoundEngine::createSource(const std::string& fileName, PNode* sourceNode) 130 { 131 SoundBuffer* buffer = NULL; 132 if (!fileName.empty()) 133 { 134 buffer= (SoundBuffer*)ResourceManager::getInstance()->load(fileName, WAV, RP_LEVEL); 135 if (buffer == NULL) 136 PRINTF(2)("Wav-Sound %s could not be loaded onto new Source\n", fileName.c_str()); 137 } 138 return new SoundSource(sourceNode, buffer); 139 } 140 141 /** 142 * @brief Sets the doppler values of openAL 143 * @param dopplerFactor the extent of the doppler-effect 144 * @param dopplerVelocity the Speed the sound travels 145 */ 146 void SoundEngine::setDopplerValues(ALfloat dopplerFactor, ALfloat dopplerVelocity) 147 { 148 alDopplerFactor(dopplerFactor); 149 this->checkError("Setting Doppler Factor", __LINE__); 150 151 alDopplerVelocity(dopplerVelocity); 152 this->checkError("Setting Doppler Velocity", __LINE__); 153 } 154 155 156 /** 157 * @brief retrieves an OpenAL Source from the availiable Sources. 158 * @param source the Source to fill with the Value. 159 */ 160 void SoundEngine::popALSource(ALuint& source) 161 { 162 assert (source == 0); 163 /// @TODO try to create more sources if needed 164 if (!this->ALSources.empty()) 165 { 166 SDL_mutexP(this->sourceMutex); 167 source = this->ALSources.top(); 168 this->ALSources.pop(); 169 SDL_mutexV(this->sourceMutex); 170 } 171 } 172 173 174 /** 175 * @brief Pushes an OpenAL Source back into the Stack of known sources 176 * @param source the Source to push onto the top of the SourceStack 177 */ 178 void SoundEngine::pushALSource(ALuint& source) 179 { 180 if (source != 0) 181 { 182 SDL_mutexP(this->sourceMutex); 183 this->ALSources.push(source); 184 SDL_mutexV(this->sourceMutex); 185 } 186 }; 187 188 189 /** 190 * @brief updates all The positions, Directions and Velocities of all Sounds 191 */ 192 void SoundEngine::update() 193 { 194 // updating the Listeners Position 195 if (likely(this->listener != NULL)) 196 { 197 alListener3f(AL_POSITION, 198 this->listener->getAbsCoor().x, 199 this->listener->getAbsCoor().y, 200 this->listener->getAbsCoor().z); 201 alListener3f(AL_VELOCITY, 202 this->listener->getVelocity().x, 203 this->listener->getVelocity().y, 204 this->listener->getVelocity().z); 205 Vector absDirV = this->listener->getAbsDirV(); 206 ALfloat orientation [6] = {1,0,0, absDirV.x, absDirV.y, absDirV.z}; 207 alListenerfv(AL_ORIENTATION, orientation); 208 SoundEngine::checkError("SoundEngine::update() - Listener Error", __LINE__); 83 209 } 84 210 else 85 PRINTF(1)("%d is not a Source\n", this->ALSources.top()); 86 87 this->ALSources.pop(); 88 } 89 90 // deleting all the SoundBuffers 91 if (this->bufferList != NULL) 92 { 93 while(this->bufferList->size() > 0) 94 ResourceManager::getInstance()->unload(static_cast<SoundBuffer*>(this->bufferList->front())); 95 } 96 97 // removing openAL from AudioResource 98 //! @todo this should be terminated through alc 99 //alutExit(); 100 101 SDL_DestroyMutex(this->sourceMutex); 102 103 SoundEngine::singletonRef = NULL; 104 } 105 106 /** 107 * @brief loads the settings of the SoundEngine from an ini-file 108 */ 109 void SoundEngine::loadSettings() 110 { 111 MultiType channels = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_AUDIO_CHANNELS, "32"); 112 this->maxSourceCount = channels.getInt(); 113 114 MultiType effectsVolume = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_EFFECTS_VOLUME, "80"); 115 this->effectsVolume = effectsVolume.getFloat()/100.0; 116 117 MultiType musicVolume = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_MUSIC_VOLUME, "75"); 118 this->musicVolume = musicVolume.getFloat()/100.0; 119 } 120 121 /** 122 * @brief creates a new SoundSource. 123 * @param fileName The Name to load the SoundBuffer from 124 * @param sourceNode The sourceNode to bind this SoundSource to. 125 * @returns The newly created SoundSource 126 * 127 * acctualy this is nothing more than a wrapper around the ResourceManager. 128 */ 129 SoundSource* SoundEngine::createSource(const std::string& fileName, PNode* sourceNode) 130 { 131 SoundBuffer* buffer = NULL; 132 if (!fileName.empty()) 133 { 134 buffer= (SoundBuffer*)ResourceManager::getInstance()->load(fileName, WAV, RP_LEVEL); 135 if (buffer == NULL) 136 PRINTF(2)("Wav-Sound %s could not be loaded onto new Source\n", fileName.c_str()); 137 } 138 return new SoundSource(sourceNode, buffer); 139 } 140 141 /** 142 * @brief Sets the doppler values of openAL 143 * @param dopplerFactor the extent of the doppler-effect 144 * @param dopplerVelocity the Speed the sound travels 145 */ 146 void SoundEngine::setDopplerValues(ALfloat dopplerFactor, ALfloat dopplerVelocity) 147 { 148 alDopplerFactor(dopplerFactor); 149 this->checkError("Setting Doppler Factor", __LINE__); 150 151 alDopplerVelocity(dopplerVelocity); 152 this->checkError("Setting Doppler Velocity", __LINE__); 153 } 154 155 156 /** 157 * @brief retrieves an OpenAL Source from the availiable Sources. 158 * @param source the Source to fill with the Value. 159 */ 160 void SoundEngine::popALSource(ALuint& source) 161 { 162 assert (source == 0); 163 /// @TODO try to create more sources if needed 164 if (!this->ALSources.empty()) 165 { 166 SDL_mutexP(this->sourceMutex); 167 source = this->ALSources.top(); 168 this->ALSources.pop(); 169 SDL_mutexV(this->sourceMutex); 170 } 171 } 172 173 174 /** 175 * @brief Pushes an OpenAL Source back into the Stack of known sources 176 * @param source the Source to push onto the top of the SourceStack 177 */ 178 void SoundEngine::pushALSource(ALuint& source) 179 { 180 if (source != 0) 181 { 182 SDL_mutexP(this->sourceMutex); 183 this->ALSources.push(source); 184 SDL_mutexV(this->sourceMutex); 185 } 186 }; 187 188 189 /** 190 * @brief updates all The positions, Directions and Velocities of all Sounds 191 */ 192 void SoundEngine::update() 193 { 194 // updating the Listeners Position 195 if (likely(this->listener != NULL)) 196 { 197 alListener3f(AL_POSITION, 198 this->listener->getAbsCoor().x, 199 this->listener->getAbsCoor().y, 200 this->listener->getAbsCoor().z); 201 alListener3f(AL_VELOCITY, 202 this->listener->getVelocity().x, 203 this->listener->getVelocity().y, 204 this->listener->getVelocity().z); 205 Vector absDirV = this->listener->getAbsDirV(); 206 ALfloat orientation [6] = {1,0,0, absDirV.x, absDirV.y, absDirV.z}; 207 alListenerfv(AL_ORIENTATION, orientation); 208 SoundEngine::checkError("SoundEngine::update() - Listener Error", __LINE__); 209 } 210 else 211 PRINTF(2)("no listener defined\n"); 212 213 // updating all the Sources positions 214 if (likely(this->sourceList != NULL || (this->sourceList = ClassList::getList(CL_SOUND_SOURCE)) != NULL)) 215 { 216 list<BaseObject*>::const_iterator sourceIT; 217 SoundSource* source; 218 for (sourceIT = this->sourceList->begin(); sourceIT != this->sourceList->end(); sourceIT++) 219 { 220 source = static_cast<SoundSource*>(*sourceIT); 221 if (source->isPlaying()) 211 PRINTF(2)("no listener defined\n"); 212 213 // updating all the Sources positions 214 if (likely(this->sourceList != NULL || (this->sourceList = ClassList::getList(CL_SOUND_SOURCE)) != NULL)) 215 { 216 std::list<BaseObject*>::const_iterator sourceIT; 217 SoundSource* source; 218 for (sourceIT = this->sourceList->begin(); sourceIT != this->sourceList->end(); sourceIT++) 222 219 { 223 int play = 0x000; 224 alGetSourcei(source->getID(), AL_SOURCE_STATE, &play); 225 if (DEBUG > 2) 226 SoundEngine::checkError("SoundEngine::update() Play", __LINE__); 227 if(play == AL_PLAYING) 220 source = static_cast<SoundSource*>(*sourceIT); 221 if (source->isPlaying()) 228 222 { 229 if (likely(source->getNode() != NULL)) 223 int play = 0x000; 224 alGetSourcei(source->getID(), AL_SOURCE_STATE, &play); 225 if (DEBUG > 2) 226 SoundEngine::checkError("SoundEngine::update() Play", __LINE__); 227 if(play == AL_PLAYING) 230 228 { 231 alSource3f(source->getID(), AL_POSITION, 232 source->getNode()->getAbsCoor().x, 233 source->getNode()->getAbsCoor().y, 234 source->getNode()->getAbsCoor().z); 235 if (DEBUG > 2) 236 SoundEngine::checkError("SoundEngine::update() Set Source Position", __LINE__); 237 alSource3f(source->getID(), AL_VELOCITY, 238 source->getNode()->getVelocity().x, 239 source->getNode()->getVelocity().y, 240 source->getNode()->getVelocity().z); 241 if (DEBUG > 2) 242 SoundEngine::checkError("SoundEngine::update() Set Source Velocity", __LINE__); 229 if (likely(source->getNode() != NULL)) 230 { 231 alSource3f(source->getID(), AL_POSITION, 232 source->getNode()->getAbsCoor().x, 233 source->getNode()->getAbsCoor().y, 234 source->getNode()->getAbsCoor().z); 235 if (DEBUG > 2) 236 SoundEngine::checkError("SoundEngine::update() Set Source Position", __LINE__); 237 alSource3f(source->getID(), AL_VELOCITY, 238 source->getNode()->getVelocity().x, 239 source->getNode()->getVelocity().y, 240 source->getNode()->getVelocity().z); 241 if (DEBUG > 2) 242 SoundEngine::checkError("SoundEngine::update() Set Source Velocity", __LINE__); 243 } 244 } 245 else 246 { 247 source->stop(); 243 248 } 244 249 } 245 else246 {247 source->stop();248 }249 250 } 250 251 } 251 } 252 SoundEngine::checkError("SoundEngine::update()", __LINE__); 253 } 254 255 256 /** 257 * initializes Audio in general 258 */ 259 bool SoundEngine::initAudio() 260 { 261 // ALenum result; 262 // PRINTF(3)("Initialisazing openAL sound engine\n"); 263 // const char* defaultDevice =(const char*) alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); 264 // const char* deviceList = (const char*)alcGetString(NULL,ALC_DEVICE_SPECIFIER); 265 // const char* devWalk = deviceList; 266 // // if (alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE) 267 // { // try out enumeration extension 268 // PRINTF(3)("Enumeration-extension found\n"); 269 // 270 // PRINTF(3)("Default device: %s\n", defaultDevice); 271 // do 272 // { 273 // PRINTF(3)("%s\n", devWalk); 274 // devWalk += strlen(devWalk)+1; 275 // } 276 // while (devWalk[0] != '\0'); 277 // } 278 279 // INITIALIZING THE DEVICE: 280 // char deviceName[] = 281 // #ifdef __WIN32__ 282 // "Direct3D"; 283 // #else 284 // "'( ( devices '( native null ) ) )"; 285 // #endif 286 287 this->device = alcOpenDevice(NULL); 288 this->checkALCError("opening Device", __LINE__); 289 290 PRINTF(4)("Audio-Specifier: %s\n", (const char*)alcGetString(this->device, ALC_DEVICE_SPECIFIER)); 291 PRINTF(4)("Audio-Extensions: %s\n", (const char*)alcGetString(this->device, ALC_EXTENSIONS)); 292 293 294 this->context = alcCreateContext(this->device, NULL); 295 this->checkALCError("creating Context", __LINE__); 296 297 alcMakeContextCurrent(this->context); 298 this->checkALCError("making Context Current", __LINE__); 299 // #endif 300 301 this->setDopplerValues(SOUND_DOPPLER_FACTOR, SOUND_DOPPLER_VELOCITY); 302 this->allocateSources(this->maxSourceCount); 303 this->checkError("Allocating Sources", __LINE__); 304 } 305 306 307 /** 308 * Allocates openAL sources 309 * @param count how many sources to allocate 310 * @returns true on success, false if at least one source could not be allocated 311 */ 312 bool SoundEngine::allocateSources(unsigned int count) 313 { 314 unsigned int failCount = 0; 315 for (unsigned int i = 0; i < count; i++) 316 { 317 ALuint source = 0; 318 319 alGenSources(1, &source); 320 this->checkError("allocate Source", __LINE__); 321 if (!alIsSource(source)) 322 { 323 PRINTF(5)("not allocated Source\n"); 324 failCount++; 325 continue; 326 } 327 328 alSourcef (source, AL_PITCH, 1.0 ); 329 alSourcef (source, AL_GAIN, this->getEffectsVolume() ); 330 alSourcei (source, AL_LOOPING, AL_FALSE ); 331 this->ALSources.push(source); 332 } 333 if (failCount == 0) 334 return true; 335 else 336 { 337 PRINTF(2)("Failed to allocate %d of %d SoundSources\n", failCount, count); 338 } 339 } 340 341 /** 342 * @brief checks for an OpenAL error 343 * @param error the ErrorMessage to display 344 * @param line on what line did the error occure. 345 */ 346 bool SoundEngine::checkError(const std::string& error, unsigned int line) 347 { 348 ALenum errorCode; 349 if ((errorCode = alGetError()) != AL_NO_ERROR) 350 { 351 PRINTF(1)("Error %s (line:%d): '%s'\n", error.c_str(), line, SoundEngine::getALErrorString(errorCode)); 352 return false; 353 } 354 else 355 return true; 356 } 357 358 /** 359 * @brief check for an ALC error. 360 * @brief error the Error-String to display 361 * @param line on that line, the error occured (debugging mode). 362 */ 363 bool SoundEngine::checkALCError(const std::string& error, unsigned int line) 364 { 365 ALenum errorCode; 366 if ((errorCode = alcGetError(this->device)) != ALC_NO_ERROR) 367 { 368 PRINTF(1)("Error %s (line:%d): '%s'\n", error.c_str(), line, SoundEngine::getALCErrorString(errorCode)); 369 return false; 370 } 371 else 372 return true; 373 } 374 375 376 377 void SoundEngine::listDevices() 378 { 379 printf("%s\n",(const char*)alcGetString(NULL, ALC_DEVICE_SPECIFIER)); 380 } 381 382 /** 383 * Transforms AL-errors into something readable 384 * @param err The error found 385 */ 386 const char* SoundEngine::getALErrorString(ALenum err) 387 { 388 switch(err) 389 { 252 SoundEngine::checkError("SoundEngine::update()", __LINE__); 253 } 254 255 256 /** 257 * initializes Audio in general 258 */ 259 bool SoundEngine::initAudio() 260 { 261 // ALenum result; 262 // PRINTF(3)("Initialisazing openAL sound engine\n"); 263 // const char* defaultDevice =(const char*) alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); 264 // const char* deviceList = (const char*)alcGetString(NULL,ALC_DEVICE_SPECIFIER); 265 // const char* devWalk = deviceList; 266 // // if (alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE) 267 // { // try out enumeration extension 268 // PRINTF(3)("Enumeration-extension found\n"); 269 // 270 // PRINTF(3)("Default device: %s\n", defaultDevice); 271 // do 272 // { 273 // PRINTF(3)("%s\n", devWalk); 274 // devWalk += strlen(devWalk)+1; 275 // } 276 // while (devWalk[0] != '\0'); 277 // } 278 279 // INITIALIZING THE DEVICE: 280 // char deviceName[] = 281 // #ifdef __WIN32__ 282 // "Direct3D"; 283 // #else 284 // "'( ( devices '( native null ) ) )"; 285 // #endif 286 287 this->device = alcOpenDevice(NULL); 288 this->checkALCError("opening Device", __LINE__); 289 290 PRINTF(4)("Audio-Specifier: %s\n", (const char*)alcGetString(this->device, ALC_DEVICE_SPECIFIER)); 291 PRINTF(4)("Audio-Extensions: %s\n", (const char*)alcGetString(this->device, ALC_EXTENSIONS)); 292 293 294 this->context = alcCreateContext(this->device, NULL); 295 this->checkALCError("creating Context", __LINE__); 296 297 alcMakeContextCurrent(this->context); 298 this->checkALCError("making Context Current", __LINE__); 299 // #endif 300 301 this->setDopplerValues(SOUND_DOPPLER_FACTOR, SOUND_DOPPLER_VELOCITY); 302 this->allocateSources(this->maxSourceCount); 303 this->checkError("Allocating Sources", __LINE__); 304 } 305 306 307 /** 308 * Allocates openAL sources 309 * @param count how many sources to allocate 310 * @returns true on success, false if at least one source could not be allocated 311 */ 312 bool SoundEngine::allocateSources(unsigned int count) 313 { 314 unsigned int failCount = 0; 315 for (unsigned int i = 0; i < count; i++) 316 { 317 ALuint source = 0; 318 319 alGenSources(1, &source); 320 this->checkError("allocate Source", __LINE__); 321 if (!alIsSource(source)) 322 { 323 PRINTF(5)("not allocated Source\n"); 324 failCount++; 325 continue; 326 } 327 328 alSourcef (source, AL_PITCH, 1.0 ); 329 alSourcef (source, AL_GAIN, this->getEffectsVolume() ); 330 alSourcei (source, AL_LOOPING, AL_FALSE ); 331 this->ALSources.push(source); 332 } 333 if (failCount == 0) 334 return true; 335 else 336 { 337 PRINTF(2)("Failed to allocate %d of %d SoundSources\n", failCount, count); 338 } 339 } 340 341 /** 342 * @brief checks for an OpenAL error 343 * @param error the ErrorMessage to display 344 * @param line on what line did the error occure. 345 */ 346 bool SoundEngine::checkError(const std::string& error, unsigned int line) 347 { 348 ALenum errorCode; 349 if ((errorCode = alGetError()) != AL_NO_ERROR) 350 { 351 PRINTF(1)("Error %s (line:%d): '%s'\n", error.c_str(), line, SoundEngine::getALErrorString(errorCode)); 352 return false; 353 } 354 else 355 return true; 356 } 357 358 /** 359 * @brief check for an ALC error. 360 * @brief error the Error-String to display 361 * @param line on that line, the error occured (debugging mode). 362 */ 363 bool SoundEngine::checkALCError(const std::string& error, unsigned int line) 364 { 365 ALenum errorCode; 366 if ((errorCode = alcGetError(this->device)) != ALC_NO_ERROR) 367 { 368 PRINTF(1)("Error %s (line:%d): '%s'\n", error.c_str(), line, SoundEngine::getALCErrorString(errorCode)); 369 return false; 370 } 371 else 372 return true; 373 } 374 375 376 377 void SoundEngine::listDevices() 378 { 379 printf("%s\n",(const char*)alcGetString(NULL, ALC_DEVICE_SPECIFIER)); 380 } 381 382 /** 383 * Transforms AL-errors into something readable 384 * @param err The error found 385 */ 386 const char* SoundEngine::getALErrorString(ALenum err) 387 { 388 switch(err) 389 { 390 390 case AL_NO_ERROR: 391 391 return ("AL_NO_ERROR"); … … 400 400 case AL_OUT_OF_MEMORY: 401 401 return ("AL_OUT_OF_MEMORY"); 402 };403 }404 405 406 const char* SoundEngine::getALCErrorString(ALenum err)407 {408 switch(err)409 {402 }; 403 } 404 405 406 const char* SoundEngine::getALCErrorString(ALenum err) 407 { 408 switch(err) 409 { 410 410 case ALC_NO_ERROR: 411 411 return ("AL_NO_ERROR"); … … 420 420 case ALC_OUT_OF_MEMORY: 421 421 return("ALC_OUT_OF_MEMORY"); 422 }; 422 }; 423 } 423 424 } -
trunk/src/lib/sound/sound_engine.h
r7355 r7460 22 22 // FORWARD DECLARATION 23 23 class PNode; 24 class IniParser; 25 26 27 //! A class that handles audio via the openAudioLibrary 28 class SoundEngine : public BaseObject{24 namespace OrxSound 25 { 26 //! A class that handles audio via the openAudioLibrary 27 class SoundEngine : public BaseObject 28 { 29 29 public: 30 30 virtual ~SoundEngine(); … … 32 32 inline static SoundEngine* getInstance() { if (!SoundEngine::singletonRef) SoundEngine::singletonRef = new SoundEngine(); return SoundEngine::singletonRef; }; 33 33 34 SoundSource* createSource(const std::string& fileName, PNode* sourceNode = NULL); 34 35 void loadSettings(); 35 36 SoundSource* createSource(const std::string& fileName, PNode* sourceNode = NULL); 36 bool initAudio(); 37 37 38 38 /** @param listener the listener in the scene */ 39 void setListener(PNode* listener) { this->listener = listener; };39 void setListener(const PNode* listener) { this->listener = listener; }; 40 40 void setDopplerValues(ALfloat dopplerFactor, ALfloat dopplerVelocity); 41 41 42 42 43 … … 48 49 void update(); 49 50 50 // administrative51 // administrative 51 52 void popALSource(ALuint& source); 52 53 void pushALSource(ALuint& source); 53 54 54 55 bool initAudio(); 56 bool allocateSources(unsigned int count); 57 58 // error handling: 55 // error handling: 59 56 static bool checkError(const std::string& error, unsigned int line); 60 57 bool checkALCError(const std::string& error, unsigned int line); … … 64 61 private: 65 62 SoundEngine(); 63 bool allocateSources(unsigned int count); 66 64 67 65 void listDevices(); … … 75 73 float musicVolume; //!< the maximum volume of the music in % (0f,1f] 76 74 float effectsVolume; //!< the maximum volume of sound-effects in % (0f,1f] 77 PNode*listener; //!< The listener of the Scene75 const PNode* listener; //!< The listener of the Scene 78 76 79 77 const std::list<BaseObject*>* bufferList; //!< A list of buffers … … 84 82 85 83 SDL_mutex* sourceMutex; //!< A mutex so we can not harm the stack 86 }; 84 }; 85 } 87 86 88 87 #endif /* _SOUND_ENGINE_H */ -
trunk/src/lib/sound/sound_source.cc
r7386 r7460 22 22 #include "compiler.h" 23 23 24 using namespace std; 25 26 /** 27 * @brief creates a SoundSource at position sourceNode with the SoundBuffer buffer 28 */ 29 SoundSource::SoundSource(const PNode* sourceNode, const SoundBuffer* buffer) 24 namespace OrxSound 30 25 { 31 this->setClassID(CL_SOUND_SOURCE, "SoundSource"); 32 33 // adding the Source to the SourcesList of the SoundEngine 34 this->buffer = buffer; 35 this->sourceNode = sourceNode; 36 this->resident = false; 37 38 this->sourceID = 0; 39 this->bPlay = false; 26 /** 27 * @brief creates a SoundSource at position sourceNode with the SoundBuffer buffer 28 */ 29 SoundSource::SoundSource(const PNode* sourceNode, const SoundBuffer* buffer) 30 { 31 this->setClassID(CL_SOUND_SOURCE, "SoundSource"); 32 33 // adding the Source to the SourcesList of the SoundEngine 34 this->buffer = buffer; 35 this->sourceNode = sourceNode; 36 this->resident = false; 37 38 this->sourceID = 0; 39 this->bPlay = false; 40 } 41 42 43 /** 44 * @brief construct a SoundSource out of the another soundSource 45 * @param source the Source to create this source from. 46 * 47 * Copies the buffer from source to this Source. 48 * Acquires a new SourceID if source is Playing. 49 */ 50 SoundSource::SoundSource(const SoundSource& source) 51 { 52 this->setClassID(CL_SOUND_SOURCE, "SoundSource"); 53 54 // adding the Source to the SourcesList of the SoundEngine 55 this->buffer = source.buffer; 56 this->sourceNode = source.sourceNode; 57 this->resident = source.resident; 58 59 this->sourceID = 0; 60 if (source.bPlay == true) 61 { 62 this->bPlay = true; 63 SoundEngine::getInstance()->popALSource(this->sourceID); 64 } 65 else 66 this->bPlay = false; 67 } 68 69 70 /** 71 * @brief paste a copy of the source into this Source. 72 * @param source the SoundSource to paste into this one. 73 * @returns a Reference to this Source. 74 * 75 */ 76 SoundSource& SoundSource::operator=(const SoundSource& source) 77 { 78 this->buffer = source.buffer; 79 this->sourceNode = sourceNode; 80 this->resident = source.resident; 81 82 if (source.bPlay) 83 this->play(); 84 else 85 this->stop(); 86 } 87 88 89 /** 90 * @brief compares two Sources with each other. 91 * @param source the Source to compare against this One. 92 * Two Sources are the same, if the PNodes match, and the Sound Played are the same. 93 * The alSource must not match, because no two Sources can have the same alSource. 94 */ 95 bool SoundSource::operator==(const SoundSource& source) 96 { 97 return (this->buffer == source.buffer && 98 this->bPlay == source.bPlay && 99 this->sourceNode == source.sourceNode); 100 } 101 102 103 /** 104 * @brief deletes a SoundSource 105 */ 106 SoundSource::~SoundSource() 107 { 108 this->stop(); 109 if (this->sourceID != 0) 110 SoundEngine::getInstance()->pushALSource(this->sourceID); 111 } 112 113 114 /** 115 * @brief Plays back a SoundSource 116 */ 117 void SoundSource::play() 118 { 119 if (this->buffer && this->retrieveSource()) 120 { 121 if (this->bPlay) 122 alSourceStop(this->sourceID); 123 alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID()); 124 alSourcePlay(this->sourceID); 125 126 if (DEBUG >= 3) 127 SoundEngine::checkError("Play Source", __LINE__); 128 this->bPlay = true; 129 } 130 } 131 132 133 /** 134 * @brief Plays back buffer on this Source 135 * @param buffer the buffer to play back on this Source 136 */ 137 void SoundSource::play(const SoundBuffer* buffer) 138 { 139 if (!this->retrieveSource()) 140 { 141 PRINTF(3)("No more Free sources (You might consider raising the Source-Count).\n"); 142 return; 143 } 144 145 alSourceStop(this->sourceID); 146 alSourcei (this->sourceID, AL_BUFFER, buffer->getID()); 147 alSourcePlay(this->sourceID); 148 149 if (unlikely(this->buffer != NULL)) 150 alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID()); 151 this->bPlay = true; 152 153 if (DEBUG >= 3) 154 SoundEngine::checkError("Play Source", __LINE__); 155 } 156 157 158 /** 159 * @brief Stops playback of a SoundSource 160 */ 161 void SoundSource::stop() 162 { 163 this->bPlay = false; 164 if (this->sourceID != 0) 165 { 166 alSourceStop(this->sourceID); 167 if (DEBUG >= 3) 168 SoundEngine::checkError("StopSource", __LINE__); 169 alSourcei(this->sourceID, AL_BUFFER, 0); 170 if (!this->resident) 171 SoundEngine::getInstance()->pushALSource(this->sourceID); 172 this->sourceID = 0; 173 } 174 } 175 176 177 /** 178 * @brief Pauses Playback of a SoundSource 179 */ 180 void SoundSource::pause() 181 { 182 alSourcePause(this->sourceID); 183 if (DEBUG >= 3) 184 SoundEngine::checkError("Pause Source", __LINE__); 185 } 186 187 188 /** 189 * @brief Rewinds Playback of a SoundSource 190 */ 191 void SoundSource::rewind() 192 { 193 alSourceRewind(this->sourceID); 194 195 if (DEBUG >= 3) 196 SoundEngine::checkError("Rewind Source", __LINE__); 197 } 198 199 200 /** 201 * @brief sets the RolloffFactor of the Sound emitted from the SoundSource 202 * @param rolloffFactor The Factor described 203 * 204 * this tells openAL how fast the Sounds decay outward from the Source 205 */ 206 void SoundSource::setRolloffFactor(ALfloat rolloffFactor) 207 { 208 alSourcef(this->sourceID, AL_ROLLOFF_FACTOR, rolloffFactor); 209 210 if (DEBUG >= 3) 211 SoundEngine::checkError("Set Source Rolloff-factor", __LINE__); 212 } 213 214 215 /** 216 * @brief sets the Positional this Source should be attached to. 217 * @param sourceNode the Source this is attached to. 218 * If sourceNode == NULL then the Source will be centered, and Audio will be played on all channels. 219 */ 220 void SoundSource::setSourceNode(const PNode* sourceNode) 221 { 222 this->sourceNode = sourceNode; 223 } 224 225 /** 226 * @brief retrieve a Source. 227 */ 228 bool SoundSource::retrieveSource() 229 { 230 if (this->sourceID != 0) 231 return true; 232 else 233 { 234 SoundEngine::getInstance()->popALSource(this->sourceID); 235 if (this->sourceID != 0) 236 { 237 if (unlikely(this->sourceNode == NULL)) 238 resetSource(this->sourceID); 239 return true; 240 } 241 } 242 return false; 243 } 244 245 246 /** 247 * @brief reset an alSource to its default Values. 248 */ 249 void SoundSource::resetSource(ALuint sourceID) 250 { 251 alSource3f(sourceID, AL_POSITION, 0.0, 0.0, 0.0); 252 alSource3f(sourceID, AL_VELOCITY, 0.0, 0.0, 0.0); 253 alSource3f(sourceID, AL_DIRECTION, 0.0, 0.0, 0.0); 254 alSourcef (sourceID, AL_ROLLOFF_FACTOR, 0.0 ); 255 //alSourcei (sourceID, AL_SOURCE_RELATIVE, AL_TRUE ); 256 alSourcef (sourceID, AL_GAIN, SoundEngine::getInstance()->getEffectsVolume()); 257 } 40 258 } 41 42 43 /**44 * @brief construct a SoundSource out of the another soundSource45 * @param source the Source to create this source from.46 *47 * Copies the buffer from source to this Source.48 * Acquires a new SourceID if source is Playing.49 */50 SoundSource::SoundSource(const SoundSource& source)51 {52 this->setClassID(CL_SOUND_SOURCE, "SoundSource");53 54 // adding the Source to the SourcesList of the SoundEngine55 this->buffer = source.buffer;56 this->sourceNode = source.sourceNode;57 this->resident = source.resident;58 59 this->sourceID = 0;60 if (source.bPlay == true)61 {62 this->bPlay = true;63 SoundEngine::getInstance()->popALSource(this->sourceID);64 }65 else66 this->bPlay = false;67 }68 69 70 /**71 * @brief paste a copy of the source into this Source.72 * @param source the SoundSource to paste into this one.73 * @returns a Reference to this Source.74 *75 */76 SoundSource& SoundSource::operator=(const SoundSource& source)77 {78 this->buffer = source.buffer;79 this->sourceNode = sourceNode;80 this->resident = source.resident;81 82 if (source.bPlay)83 this->play();84 else85 this->stop();86 }87 88 89 /**90 * @brief compares two Sources with each other.91 * @param source the Source to compare against this One.92 * Two Sources are the same, if the PNodes match, and the Sound Played are the same.93 * The alSource must not match, because no two Sources can have the same alSource.94 */95 bool SoundSource::operator==(const SoundSource& source)96 {97 return (this->buffer == source.buffer &&98 this->bPlay == source.bPlay &&99 this->sourceNode == source.sourceNode);100 }101 102 103 /**104 * @brief deletes a SoundSource105 */106 SoundSource::~SoundSource()107 {108 this->stop();109 if (this->sourceID != 0)110 SoundEngine::getInstance()->pushALSource(this->sourceID);111 }112 113 114 /**115 * @brief Plays back a SoundSource116 */117 void SoundSource::play()118 {119 if (this->buffer && this->retrieveSource())120 {121 if (this->bPlay)122 alSourceStop(this->sourceID);123 alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID());124 alSourcePlay(this->sourceID);125 126 if (DEBUG >= 3)127 SoundEngine::checkError("Play Source", __LINE__);128 this->bPlay = true;129 }130 }131 132 133 /**134 * @brief Plays back buffer on this Source135 * @param buffer the buffer to play back on this Source136 */137 void SoundSource::play(const SoundBuffer* buffer)138 {139 if (!this->retrieveSource())140 {141 PRINTF(3)("No more Free sources (You might consider raising the Source-Count).\n");142 return;143 }144 145 alSourceStop(this->sourceID);146 alSourcei (this->sourceID, AL_BUFFER, buffer->getID());147 alSourcePlay(this->sourceID);148 149 if (unlikely(this->buffer != NULL))150 alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID());151 this->bPlay = true;152 153 if (DEBUG >= 3)154 SoundEngine::checkError("Play Source", __LINE__);155 }156 157 158 /**159 * @brief Stops playback of a SoundSource160 */161 void SoundSource::stop()162 {163 this->bPlay = false;164 if (this->sourceID != 0)165 {166 alSourceStop(this->sourceID);167 if (DEBUG >= 3)168 SoundEngine::checkError("StopSource", __LINE__);169 alSourcei(this->sourceID, AL_BUFFER, 0);170 if (!this->resident)171 SoundEngine::getInstance()->pushALSource(this->sourceID);172 this->sourceID = 0;173 }174 }175 176 177 /**178 * @brief Pauses Playback of a SoundSource179 */180 void SoundSource::pause()181 {182 alSourcePause(this->sourceID);183 if (DEBUG >= 3)184 SoundEngine::checkError("Pause Source", __LINE__);185 }186 187 188 /**189 * @brief Rewinds Playback of a SoundSource190 */191 void SoundSource::rewind()192 {193 alSourceRewind(this->sourceID);194 195 if (DEBUG >= 3)196 SoundEngine::checkError("Rewind Source", __LINE__);197 }198 199 200 /**201 * @brief sets the RolloffFactor of the Sound emitted from the SoundSource202 * @param rolloffFactor The Factor described203 *204 * this tells openAL how fast the Sounds decay outward from the Source205 */206 void SoundSource::setRolloffFactor(ALfloat rolloffFactor)207 {208 alSourcef(this->sourceID, AL_ROLLOFF_FACTOR, rolloffFactor);209 210 if (DEBUG >= 3)211 SoundEngine::checkError("Set Source Rolloff-factor", __LINE__);212 }213 214 215 /**216 * @brief sets the Positional this Source should be attached to.217 * @param sourceNode the Source this is attached to.218 * If sourceNode == NULL then the Source will be centered, and Audio will be played on all channels.219 */220 void SoundSource::setSourceNode(const PNode* sourceNode)221 {222 this->sourceNode = sourceNode;223 }224 225 /**226 * @brief retrieve a Source.227 */228 bool SoundSource::retrieveSource()229 {230 if (this->sourceID != 0)231 return true;232 else233 {234 SoundEngine::getInstance()->popALSource(this->sourceID);235 if (this->sourceID != 0)236 {237 if (unlikely(this->sourceNode == NULL))238 resetSource(this->sourceID);239 return true;240 }241 }242 return false;243 }244 245 246 /**247 * @brief reset an alSource to its default Values.248 */249 void SoundSource::resetSource(ALuint sourceID)250 {251 alSource3f(sourceID, AL_POSITION, 0.0, 0.0, 0.0);252 alSource3f(sourceID, AL_VELOCITY, 0.0, 0.0, 0.0);253 alSource3f(sourceID, AL_DIRECTION, 0.0, 0.0, 0.0);254 alSourcef (sourceID, AL_ROLLOFF_FACTOR, 0.0 );255 //alSourcei (sourceID, AL_SOURCE_RELATIVE, AL_TRUE );256 alSourcef (sourceID, AL_GAIN, SoundEngine::getInstance()->getEffectsVolume());257 } -
trunk/src/lib/sound/sound_source.h
r7317 r7460 11 11 12 12 // FORWARD DECLARATION 13 class SoundBuffer;14 13 class PNode; 15 16 //! A class that represents a SoundSource 17 class SoundSource : public BaseObject 14 namespace OrxSound 18 15 { 16 class SoundBuffer; 17 //! A class that represents a SoundSource 18 class SoundSource : public BaseObject 19 { 19 20 public: 20 21 SoundSource(const PNode* sourceNode = NULL, const SoundBuffer* buffer = NULL); … … 25 26 virtual ~SoundSource(); 26 27 27 // user interaction28 // user interaction 28 29 void play(); 29 30 void play(const SoundBuffer* buffer); … … 32 33 void rewind(); 33 34 34 // development functions35 // development functions 35 36 /** @returns The ID of this Source */ 36 37 inline ALuint getID() const { return this->sourceID; }; … … 60 61 const SoundBuffer* buffer; //!< The buffer to play in this source. 61 62 const PNode* sourceNode; //!< The SourceNode representing the position/velocity... of this source. 62 }; 63 }; 64 } 63 65 #endif /* _SOUND_SOURCE_H */ -
trunk/src/lib/util/loading/resource_manager.cc
r7225 r7460 434 434 case WAV: 435 435 if(isFile(fullName)) 436 tmpResource->pointer = new SoundBuffer(fullName);436 tmpResource->pointer = new OrxSound::SoundBuffer(fullName); 437 437 break; 438 438 case OGG: 439 439 if (isFile(fullName)) 440 tmpResource->pointer = new O ggPlayer(fullName);440 tmpResource->pointer = new OrxSound::OggPlayer(fullName); 441 441 break; 442 442 #endif /* NO_AUDIO */
Note: See TracChangeset
for help on using the changeset viewer.