|
Blender
V2.59
|
00001 /* 00002 * $Id: AUD_OpenALDevice.cpp 38631 2011-07-23 16:08:37Z nexyon $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * Copyright 2009-2011 Jörg Hermann Müller 00007 * 00008 * This file is part of AudaSpace. 00009 * 00010 * Audaspace is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * AudaSpace is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with Audaspace; if not, write to the Free Software Foundation, 00022 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include "AUD_OpenALDevice.h" 00033 #include "AUD_IFactory.h" 00034 #include "AUD_IReader.h" 00035 #include "AUD_ConverterReader.h" 00036 00037 #include <cstring> 00038 #include <limits> 00039 00040 #ifdef WIN32 00041 #include <windows.h> 00042 #else 00043 #include <unistd.h> 00044 #endif 00045 00046 #define AUD_OPENAL_CYCLE_BUFFERS 3 00047 00049 struct AUD_OpenALHandle : AUD_Handle 00050 { 00052 bool isBuffered; 00053 00055 AUD_IReader* reader; 00056 00058 bool keep; 00059 00061 ALenum format; 00062 00064 ALuint source; 00065 00067 ALuint buffers[AUD_OPENAL_CYCLE_BUFFERS]; 00068 00070 int current; 00071 00073 bool data_end; 00074 00076 int loopcount; 00077 00079 stopCallback stop; 00080 00082 void* stop_data; 00083 }; 00084 00085 struct AUD_OpenALBufferedFactory 00086 { 00088 AUD_IFactory* factory; 00089 00091 ALuint buffer; 00092 }; 00093 00094 typedef std::list<AUD_OpenALHandle*>::iterator AUD_HandleIterator; 00095 typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator; 00096 00097 /******************************************************************************/ 00098 /**************************** Threading Code **********************************/ 00099 /******************************************************************************/ 00100 00101 void* AUD_openalRunThread(void* device) 00102 { 00103 AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device; 00104 dev->updateStreams(); 00105 return NULL; 00106 } 00107 00108 void AUD_OpenALDevice::start(bool join) 00109 { 00110 lock(); 00111 00112 if(!m_playing) 00113 { 00114 if(join) 00115 pthread_join(m_thread, NULL); 00116 00117 pthread_attr_t attr; 00118 pthread_attr_init(&attr); 00119 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 00120 00121 pthread_create(&m_thread, &attr, AUD_openalRunThread, this); 00122 00123 pthread_attr_destroy(&attr); 00124 00125 m_playing = true; 00126 } 00127 00128 unlock(); 00129 } 00130 00131 void AUD_OpenALDevice::updateStreams() 00132 { 00133 AUD_OpenALHandle* sound; 00134 00135 int length; 00136 sample_t* buffer; 00137 00138 ALint info; 00139 AUD_DeviceSpecs specs = m_specs; 00140 ALCenum cerr; 00141 std::list<AUD_OpenALHandle*> stopSounds; 00142 std::list<AUD_OpenALHandle*> pauseSounds; 00143 AUD_HandleIterator it; 00144 00145 while(1) 00146 { 00147 lock(); 00148 00149 alcSuspendContext(m_context); 00150 cerr = alcGetError(m_device); 00151 if(cerr == ALC_NO_ERROR) 00152 { 00153 // for all sounds 00154 for(it = m_playingSounds->begin(); it != m_playingSounds->end(); it++) 00155 { 00156 sound = *it; 00157 00158 // is it a streamed sound? 00159 if(!sound->isBuffered) 00160 { 00161 // check for buffer refilling 00162 alGetSourcei(sound->source, AL_BUFFERS_PROCESSED, &info); 00163 00164 if(info) 00165 { 00166 specs.specs = sound->reader->getSpecs(); 00167 00168 // for all empty buffers 00169 while(info--) 00170 { 00171 // if there's still data to play back 00172 if(!sound->data_end) 00173 { 00174 // read data 00175 length = m_buffersize; 00176 sound->reader->read(length, buffer); 00177 00178 // looping necessary? 00179 if(length == 0 && sound->loopcount) 00180 { 00181 if(sound->loopcount > 0) 00182 sound->loopcount--; 00183 00184 sound->reader->seek(0); 00185 00186 length = m_buffersize; 00187 sound->reader->read(length, buffer); 00188 } 00189 00190 // read nothing? 00191 if(length == 0) 00192 { 00193 sound->data_end = true; 00194 break; 00195 } 00196 00197 // unqueue buffer 00198 alSourceUnqueueBuffers(sound->source, 1, 00199 &sound->buffers[sound->current]); 00200 ALenum err; 00201 if((err = alGetError()) != AL_NO_ERROR) 00202 { 00203 sound->data_end = true; 00204 break; 00205 } 00206 00207 // fill with new data 00208 alBufferData(sound->buffers[sound->current], 00209 sound->format, 00210 buffer, length * 00211 AUD_DEVICE_SAMPLE_SIZE(specs), 00212 specs.rate); 00213 00214 if((err = alGetError()) != AL_NO_ERROR) 00215 { 00216 sound->data_end = true; 00217 break; 00218 } 00219 00220 // and queue again 00221 alSourceQueueBuffers(sound->source, 1, 00222 &sound->buffers[sound->current]); 00223 if(alGetError() != AL_NO_ERROR) 00224 { 00225 sound->data_end = true; 00226 break; 00227 } 00228 00229 sound->current = (sound->current+1) % 00230 AUD_OPENAL_CYCLE_BUFFERS; 00231 } 00232 else 00233 break; 00234 } 00235 } 00236 } 00237 00238 // check if the sound has been stopped 00239 alGetSourcei(sound->source, AL_SOURCE_STATE, &info); 00240 00241 if(info != AL_PLAYING) 00242 { 00243 // if it really stopped 00244 if(sound->data_end) 00245 { 00246 if(sound->stop) 00247 sound->stop(sound->stop_data); 00248 00249 // pause or 00250 if(sound->keep) 00251 pauseSounds.push_back(sound); 00252 // stop 00253 else 00254 stopSounds.push_back(sound); 00255 } 00256 // continue playing 00257 else 00258 alSourcePlay(sound->source); 00259 } 00260 } 00261 00262 for(it = pauseSounds.begin(); it != pauseSounds.end(); it++) 00263 pause(*it); 00264 00265 for(it = stopSounds.begin(); it != stopSounds.end(); it++) 00266 stop(*it); 00267 00268 pauseSounds.clear(); 00269 stopSounds.clear(); 00270 00271 alcProcessContext(m_context); 00272 } 00273 00274 // stop thread 00275 if(m_playingSounds->empty() || (cerr != ALC_NO_ERROR)) 00276 { 00277 m_playing = false; 00278 unlock(); 00279 pthread_exit(NULL); 00280 } 00281 00282 unlock(); 00283 00284 #ifdef WIN32 00285 Sleep(20); 00286 #else 00287 usleep(20000); 00288 #endif 00289 } 00290 } 00291 00292 /******************************************************************************/ 00293 /**************************** IDevice Code ************************************/ 00294 /******************************************************************************/ 00295 00296 bool AUD_OpenALDevice::isValid(AUD_Handle* handle) 00297 { 00298 for(AUD_HandleIterator i = m_playingSounds->begin(); 00299 i != m_playingSounds->end(); i++) 00300 if(*i == handle) 00301 return true; 00302 for(AUD_HandleIterator i = m_pausedSounds->begin(); 00303 i != m_pausedSounds->end(); i++) 00304 if(*i == handle) 00305 return true; 00306 return false; 00307 } 00308 00309 static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened."; 00310 00311 AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) 00312 { 00313 // cannot determine how many channels or which format OpenAL uses, but 00314 // it at least is able to play 16 bit stereo audio 00315 specs.channels = AUD_CHANNELS_STEREO; 00316 specs.format = AUD_FORMAT_S16; 00317 00318 #if 0 00319 if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE) 00320 { 00321 ALCchar* devices = const_cast<ALCchar*>(alcGetString(NULL, ALC_DEVICE_SPECIFIER)); 00322 printf("OpenAL devices (standard is: %s):\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)); 00323 00324 while(*devices) 00325 { 00326 printf("%s\n", devices); 00327 devices += strlen(devices) + 1; 00328 } 00329 } 00330 #endif 00331 00332 m_device = alcOpenDevice(NULL); 00333 00334 if(!m_device) 00335 AUD_THROW(AUD_ERROR_OPENAL, open_error); 00336 00337 // at least try to set the frequency 00338 ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 }; 00339 ALCint* attributes = attribs; 00340 if(specs.rate == AUD_RATE_INVALID) 00341 attributes = NULL; 00342 00343 m_context = alcCreateContext(m_device, attributes); 00344 alcMakeContextCurrent(m_context); 00345 00346 alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate); 00347 00348 // check for specific formats and channel counts to be played back 00349 if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE) 00350 specs.format = AUD_FORMAT_FLOAT32; 00351 00352 m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE; 00353 00354 alGetError(); 00355 alcGetError(m_device); 00356 00357 m_specs = specs; 00358 m_buffersize = buffersize; 00359 m_playing = false; 00360 00361 m_playingSounds = new std::list<AUD_OpenALHandle*>(); 00362 m_pausedSounds = new std::list<AUD_OpenALHandle*>(); 00363 m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>(); 00364 00365 pthread_mutexattr_t attr; 00366 pthread_mutexattr_init(&attr); 00367 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 00368 00369 pthread_mutex_init(&m_mutex, &attr); 00370 00371 pthread_mutexattr_destroy(&attr); 00372 00373 start(false); 00374 } 00375 00376 AUD_OpenALDevice::~AUD_OpenALDevice() 00377 { 00378 AUD_OpenALHandle* sound; 00379 00380 lock(); 00381 alcSuspendContext(m_context); 00382 00383 // delete all playing sounds 00384 while(!m_playingSounds->empty()) 00385 { 00386 sound = *(m_playingSounds->begin()); 00387 alDeleteSources(1, &sound->source); 00388 if(!sound->isBuffered) 00389 { 00390 delete sound->reader; 00391 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); 00392 } 00393 delete sound; 00394 m_playingSounds->erase(m_playingSounds->begin()); 00395 } 00396 00397 // delete all paused sounds 00398 while(!m_pausedSounds->empty()) 00399 { 00400 sound = *(m_pausedSounds->begin()); 00401 alDeleteSources(1, &sound->source); 00402 if(!sound->isBuffered) 00403 { 00404 delete sound->reader; 00405 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); 00406 } 00407 delete sound; 00408 m_pausedSounds->erase(m_pausedSounds->begin()); 00409 } 00410 00411 // delete all buffered factories 00412 while(!m_bufferedFactories->empty()) 00413 { 00414 alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer); 00415 delete *m_bufferedFactories->begin(); 00416 m_bufferedFactories->erase(m_bufferedFactories->begin()); 00417 } 00418 00419 alcProcessContext(m_context); 00420 00421 // wait for the thread to stop 00422 unlock(); 00423 pthread_join(m_thread, NULL); 00424 00425 delete m_playingSounds; 00426 delete m_pausedSounds; 00427 delete m_bufferedFactories; 00428 00429 // quit OpenAL 00430 alcMakeContextCurrent(NULL); 00431 alcDestroyContext(m_context); 00432 alcCloseDevice(m_device); 00433 00434 pthread_mutex_destroy(&m_mutex); 00435 } 00436 00437 AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const 00438 { 00439 return m_specs; 00440 } 00441 00442 bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs) 00443 { 00444 bool valid = true; 00445 format = 0; 00446 00447 switch(m_specs.format) 00448 { 00449 case AUD_FORMAT_S16: 00450 switch(specs.channels) 00451 { 00452 case AUD_CHANNELS_MONO: 00453 format = AL_FORMAT_MONO16; 00454 break; 00455 case AUD_CHANNELS_STEREO: 00456 format = AL_FORMAT_STEREO16; 00457 break; 00458 case AUD_CHANNELS_SURROUND4: 00459 if(m_useMC) 00460 { 00461 format = alGetEnumValue("AL_FORMAT_QUAD16"); 00462 break; 00463 } 00464 case AUD_CHANNELS_SURROUND51: 00465 if(m_useMC) 00466 { 00467 format = alGetEnumValue("AL_FORMAT_51CHN16"); 00468 break; 00469 } 00470 case AUD_CHANNELS_SURROUND61: 00471 if(m_useMC) 00472 { 00473 format = alGetEnumValue("AL_FORMAT_61CHN16"); 00474 break; 00475 } 00476 case AUD_CHANNELS_SURROUND71: 00477 if(m_useMC) 00478 { 00479 format = alGetEnumValue("AL_FORMAT_71CHN16"); 00480 break; 00481 } 00482 default: 00483 valid = false; 00484 } 00485 break; 00486 case AUD_FORMAT_FLOAT32: 00487 switch(specs.channels) 00488 { 00489 case AUD_CHANNELS_MONO: 00490 format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32"); 00491 break; 00492 case AUD_CHANNELS_STEREO: 00493 format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32"); 00494 break; 00495 case AUD_CHANNELS_SURROUND4: 00496 if(m_useMC) 00497 { 00498 format = alGetEnumValue("AL_FORMAT_QUAD32"); 00499 break; 00500 } 00501 case AUD_CHANNELS_SURROUND51: 00502 if(m_useMC) 00503 { 00504 format = alGetEnumValue("AL_FORMAT_51CHN32"); 00505 break; 00506 } 00507 case AUD_CHANNELS_SURROUND61: 00508 if(m_useMC) 00509 { 00510 format = alGetEnumValue("AL_FORMAT_61CHN32"); 00511 break; 00512 } 00513 case AUD_CHANNELS_SURROUND71: 00514 if(m_useMC) 00515 { 00516 format = alGetEnumValue("AL_FORMAT_71CHN32"); 00517 break; 00518 } 00519 default: 00520 valid = false; 00521 } 00522 break; 00523 default: 00524 valid = false; 00525 } 00526 00527 if(!format) 00528 valid = false; 00529 00530 return valid; 00531 } 00532 00533 static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be " 00534 "generated."; 00535 static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be " 00536 "generated."; 00537 static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be " 00538 "queued to the source."; 00539 static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be " 00540 "filled with data."; 00541 00542 AUD_Handle* AUD_OpenALDevice::play(AUD_IReader* reader, bool keep) 00543 { 00544 AUD_OpenALHandle* sound = NULL; 00545 00546 AUD_DeviceSpecs specs = m_specs; 00547 specs.specs = reader->getSpecs(); 00548 00549 // check format 00550 bool valid = specs.channels != AUD_CHANNELS_INVALID; 00551 00552 if(m_specs.format != AUD_FORMAT_FLOAT32) 00553 reader = new AUD_ConverterReader(reader, m_specs); 00554 00555 // create the handle 00556 sound = new AUD_OpenALHandle; 00557 sound->keep = keep; 00558 sound->reader = reader; 00559 sound->current = 0; 00560 sound->isBuffered = false; 00561 sound->data_end = false; 00562 sound->loopcount = 0; 00563 sound->stop = NULL; 00564 sound->stop_data = NULL; 00565 00566 valid &= getFormat(sound->format, specs.specs); 00567 00568 if(!valid) 00569 { 00570 delete sound; 00571 delete reader; 00572 return NULL; 00573 } 00574 00575 lock(); 00576 alcSuspendContext(m_context); 00577 00578 // OpenAL playback code 00579 try 00580 { 00581 alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); 00582 if(alGetError() != AL_NO_ERROR) 00583 AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error); 00584 00585 try 00586 { 00587 sample_t* buf; 00588 int length; 00589 00590 for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++) 00591 { 00592 length = m_buffersize; 00593 reader->read(length, buf); 00594 alBufferData(sound->buffers[i], sound->format, buf, 00595 length * AUD_DEVICE_SAMPLE_SIZE(specs), 00596 specs.rate); 00597 if(alGetError() != AL_NO_ERROR) 00598 AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error); 00599 } 00600 00601 alGenSources(1, &sound->source); 00602 if(alGetError() != AL_NO_ERROR) 00603 AUD_THROW(AUD_ERROR_OPENAL, gensource_error); 00604 00605 try 00606 { 00607 alSourceQueueBuffers(sound->source, AUD_OPENAL_CYCLE_BUFFERS, 00608 sound->buffers); 00609 if(alGetError() != AL_NO_ERROR) 00610 AUD_THROW(AUD_ERROR_OPENAL, queue_error); 00611 } 00612 catch(AUD_Exception&) 00613 { 00614 alDeleteSources(1, &sound->source); 00615 throw; 00616 } 00617 } 00618 catch(AUD_Exception&) 00619 { 00620 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); 00621 throw; 00622 } 00623 } 00624 catch(AUD_Exception&) 00625 { 00626 delete sound; 00627 delete reader; 00628 alcProcessContext(m_context); 00629 unlock(); 00630 throw; 00631 } 00632 00633 // play sound 00634 m_playingSounds->push_back(sound); 00635 alSourcei(sound->source, AL_SOURCE_RELATIVE, 1); 00636 00637 start(); 00638 00639 alcProcessContext(m_context); 00640 unlock(); 00641 00642 return sound; 00643 } 00644 00645 AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) 00646 { 00647 AUD_OpenALHandle* sound = NULL; 00648 00649 lock(); 00650 00651 try 00652 { 00653 // check if it is a buffered factory 00654 for(AUD_BFIterator i = m_bufferedFactories->begin(); 00655 i != m_bufferedFactories->end(); i++) 00656 { 00657 if((*i)->factory == factory) 00658 { 00659 // create the handle 00660 sound = new AUD_OpenALHandle; 00661 sound->keep = keep; 00662 sound->current = -1; 00663 sound->isBuffered = true; 00664 sound->data_end = true; 00665 sound->loopcount = 0; 00666 sound->stop = NULL; 00667 sound->stop_data = NULL; 00668 00669 alcSuspendContext(m_context); 00670 00671 // OpenAL playback code 00672 try 00673 { 00674 alGenSources(1, &sound->source); 00675 if(alGetError() != AL_NO_ERROR) 00676 AUD_THROW(AUD_ERROR_OPENAL, gensource_error); 00677 00678 try 00679 { 00680 alSourcei(sound->source, AL_BUFFER, (*i)->buffer); 00681 if(alGetError() != AL_NO_ERROR) 00682 AUD_THROW(AUD_ERROR_OPENAL, queue_error); 00683 } 00684 catch(AUD_Exception&) 00685 { 00686 alDeleteSources(1, &sound->source); 00687 throw; 00688 } 00689 } 00690 catch(AUD_Exception&) 00691 { 00692 delete sound; 00693 alcProcessContext(m_context); 00694 throw; 00695 } 00696 00697 // play sound 00698 m_playingSounds->push_back(sound); 00699 00700 alSourcei(sound->source, AL_SOURCE_RELATIVE, 1); 00701 start(); 00702 00703 alcProcessContext(m_context); 00704 } 00705 } 00706 } 00707 catch(AUD_Exception&) 00708 { 00709 unlock(); 00710 throw; 00711 } 00712 00713 unlock(); 00714 00715 if(sound) 00716 return sound; 00717 00718 return play(factory->createReader(), keep); 00719 } 00720 00721 bool AUD_OpenALDevice::pause(AUD_Handle* handle) 00722 { 00723 bool result = false; 00724 00725 lock(); 00726 00727 // only songs that are played can be paused 00728 for(AUD_HandleIterator i = m_playingSounds->begin(); 00729 i != m_playingSounds->end(); i++) 00730 { 00731 if(*i == handle) 00732 { 00733 m_pausedSounds->push_back(*i); 00734 alSourcePause((*i)->source); 00735 m_playingSounds->erase(i); 00736 result = true; 00737 break; 00738 } 00739 } 00740 00741 unlock(); 00742 00743 return result; 00744 } 00745 00746 bool AUD_OpenALDevice::resume(AUD_Handle* handle) 00747 { 00748 bool result = false; 00749 00750 lock(); 00751 00752 // only songs that are paused can be resumed 00753 for(AUD_HandleIterator i = m_pausedSounds->begin(); 00754 i != m_pausedSounds->end(); i++) 00755 { 00756 if(*i == handle) 00757 { 00758 m_playingSounds->push_back(*i); 00759 start(); 00760 m_pausedSounds->erase(i); 00761 result = true; 00762 break; 00763 } 00764 } 00765 00766 unlock(); 00767 00768 return result; 00769 } 00770 00771 bool AUD_OpenALDevice::stop(AUD_Handle* handle) 00772 { 00773 AUD_OpenALHandle* sound; 00774 00775 bool result = false; 00776 00777 lock(); 00778 00779 for(AUD_HandleIterator i = m_playingSounds->begin(); 00780 i != m_playingSounds->end(); i++) 00781 { 00782 if(*i == handle) 00783 { 00784 sound = *i; 00785 alDeleteSources(1, &sound->source); 00786 if(!sound->isBuffered) 00787 { 00788 delete sound->reader; 00789 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); 00790 } 00791 delete *i; 00792 m_playingSounds->erase(i); 00793 result = true; 00794 break; 00795 } 00796 } 00797 if(!result) 00798 { 00799 for(AUD_HandleIterator i = m_pausedSounds->begin(); 00800 i != m_pausedSounds->end(); i++) 00801 { 00802 if(*i == handle) 00803 { 00804 sound = *i; 00805 alDeleteSources(1, &sound->source); 00806 if(!sound->isBuffered) 00807 { 00808 delete sound->reader; 00809 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); 00810 } 00811 delete *i; 00812 m_pausedSounds->erase(i); 00813 result = true; 00814 break; 00815 } 00816 } 00817 } 00818 00819 unlock(); 00820 00821 return result; 00822 } 00823 00824 bool AUD_OpenALDevice::getKeep(AUD_Handle* handle) 00825 { 00826 bool result = false; 00827 00828 lock(); 00829 00830 if(isValid(handle)) 00831 result = ((AUD_OpenALHandle*)handle)->keep; 00832 00833 unlock(); 00834 00835 return result; 00836 } 00837 00838 bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep) 00839 { 00840 bool result = false; 00841 00842 lock(); 00843 00844 if(isValid(handle)) 00845 { 00846 ((AUD_OpenALHandle*)handle)->keep = keep; 00847 result = true; 00848 } 00849 00850 unlock(); 00851 00852 return result; 00853 } 00854 00855 bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position) 00856 { 00857 bool result = false; 00858 00859 lock(); 00860 00861 if(isValid(handle)) 00862 { 00863 AUD_OpenALHandle* alhandle = (AUD_OpenALHandle*)handle; 00864 if(alhandle->isBuffered) 00865 alSourcef(alhandle->source, AL_SEC_OFFSET, position); 00866 else 00867 { 00868 alhandle->reader->seek((int)(position * 00869 alhandle->reader->getSpecs().rate)); 00870 alhandle->data_end = false; 00871 00872 ALint info; 00873 00874 alGetSourcei(alhandle->source, AL_SOURCE_STATE, &info); 00875 00876 if(info != AL_PLAYING) 00877 { 00878 if(info == AL_PAUSED) 00879 alSourceStop(alhandle->source); 00880 00881 alSourcei(alhandle->source, AL_BUFFER, 0); 00882 alhandle->current = 0; 00883 00884 ALenum err; 00885 if((err = alGetError()) == AL_NO_ERROR) 00886 { 00887 sample_t* buf; 00888 int length; 00889 AUD_DeviceSpecs specs = m_specs; 00890 specs.specs = alhandle->reader->getSpecs(); 00891 00892 for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++) 00893 { 00894 length = m_buffersize; 00895 alhandle->reader->read(length, buf); 00896 alBufferData(alhandle->buffers[i], alhandle->format, 00897 buf, 00898 length * AUD_DEVICE_SAMPLE_SIZE(specs), 00899 specs.rate); 00900 00901 if(alGetError() != AL_NO_ERROR) 00902 break; 00903 } 00904 00905 alSourceQueueBuffers(alhandle->source, 00906 AUD_OPENAL_CYCLE_BUFFERS, 00907 alhandle->buffers); 00908 } 00909 00910 alSourceRewind(alhandle->source); 00911 } 00912 } 00913 result = true; 00914 } 00915 00916 unlock(); 00917 return result; 00918 } 00919 00920 float AUD_OpenALDevice::getPosition(AUD_Handle* handle) 00921 { 00922 float position = 0.0f; 00923 00924 lock(); 00925 00926 if(isValid(handle)) 00927 { 00928 AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle; 00929 alGetSourcef(h->source, AL_SEC_OFFSET, &position); 00930 if(!h->isBuffered) 00931 { 00932 AUD_Specs specs = h->reader->getSpecs(); 00933 position += (h->reader->getPosition() - m_buffersize * 00934 AUD_OPENAL_CYCLE_BUFFERS) / 00935 (float)specs.rate; 00936 } 00937 } 00938 00939 unlock(); 00940 return position; 00941 } 00942 00943 AUD_Status AUD_OpenALDevice::getStatus(AUD_Handle* handle) 00944 { 00945 AUD_Status status = AUD_STATUS_INVALID; 00946 00947 lock(); 00948 00949 for(AUD_HandleIterator i = m_playingSounds->begin(); 00950 i != m_playingSounds->end(); i++) 00951 { 00952 if(*i == handle) 00953 { 00954 status = AUD_STATUS_PLAYING; 00955 break; 00956 } 00957 } 00958 if(status == AUD_STATUS_INVALID) 00959 { 00960 for(AUD_HandleIterator i = m_pausedSounds->begin(); 00961 i != m_pausedSounds->end(); i++) 00962 { 00963 if(*i == handle) 00964 { 00965 status = AUD_STATUS_PAUSED; 00966 break; 00967 } 00968 } 00969 } 00970 00971 unlock(); 00972 00973 return status; 00974 } 00975 00976 void AUD_OpenALDevice::lock() 00977 { 00978 pthread_mutex_lock(&m_mutex); 00979 } 00980 00981 void AUD_OpenALDevice::unlock() 00982 { 00983 pthread_mutex_unlock(&m_mutex); 00984 } 00985 00986 float AUD_OpenALDevice::getVolume() const 00987 { 00988 float result; 00989 alGetListenerf(AL_GAIN, &result); 00990 return result; 00991 } 00992 00993 void AUD_OpenALDevice::setVolume(float volume) 00994 { 00995 alListenerf(AL_GAIN, volume); 00996 } 00997 00998 float AUD_OpenALDevice::getVolume(AUD_Handle* handle) 00999 { 01000 lock(); 01001 float result = std::numeric_limits<float>::quiet_NaN(); 01002 if(isValid(handle)) 01003 alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_GAIN, &result); 01004 unlock(); 01005 return result; 01006 } 01007 01008 bool AUD_OpenALDevice::setVolume(AUD_Handle* handle, float volume) 01009 { 01010 lock(); 01011 bool result = isValid(handle); 01012 if(result) 01013 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_GAIN, volume); 01014 unlock(); 01015 return result; 01016 } 01017 01018 float AUD_OpenALDevice::getPitch(AUD_Handle* handle) 01019 { 01020 lock(); 01021 float result = std::numeric_limits<float>::quiet_NaN(); 01022 if(isValid(handle)) 01023 alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_PITCH, &result); 01024 unlock(); 01025 return result; 01026 } 01027 01028 bool AUD_OpenALDevice::setPitch(AUD_Handle* handle, float pitch) 01029 { 01030 lock(); 01031 bool result = isValid(handle); 01032 if(result) 01033 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_PITCH, pitch); 01034 unlock(); 01035 return result; 01036 } 01037 01038 int AUD_OpenALDevice::getLoopCount(AUD_Handle* handle) 01039 { 01040 lock(); 01041 int result = 0; 01042 if(isValid(handle)) 01043 result = ((AUD_OpenALHandle*)handle)->loopcount; 01044 unlock(); 01045 return result; 01046 } 01047 01048 bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count) 01049 { 01050 lock(); 01051 bool result = isValid(handle); 01052 if(result) 01053 ((AUD_OpenALHandle*)handle)->loopcount = count; 01054 unlock(); 01055 return result; 01056 } 01057 01058 bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data) 01059 { 01060 lock(); 01061 bool result = isValid(handle); 01062 if(result) 01063 { 01064 AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle; 01065 h->stop = callback; 01066 h->stop_data = data; 01067 } 01068 unlock(); 01069 return result; 01070 } 01071 01072 /* AUD_XXX Temorary disabled 01073 01074 bool AUD_OpenALDevice::bufferFactory(void *value) 01075 { 01076 bool result = false; 01077 AUD_IFactory* factory = (AUD_IFactory*) value; 01078 01079 // load the factory into an OpenAL buffer 01080 if(factory) 01081 { 01082 // check if the factory is already buffered 01083 lock(); 01084 for(AUD_BFIterator i = m_bufferedFactories->begin(); 01085 i != m_bufferedFactories->end(); i++) 01086 { 01087 if((*i)->factory == factory) 01088 { 01089 result = true; 01090 break; 01091 } 01092 } 01093 unlock(); 01094 if(result) 01095 return result; 01096 01097 AUD_IReader* reader = factory->createReader(); 01098 01099 if(reader == NULL) 01100 return false; 01101 01102 AUD_DeviceSpecs specs = m_specs; 01103 specs.specs = reader->getSpecs(); 01104 01105 if(m_specs.format != AUD_FORMAT_FLOAT32) 01106 reader = new AUD_ConverterReader(reader, m_specs); 01107 01108 ALenum format; 01109 01110 if(!getFormat(format, specs.specs)) 01111 { 01112 delete reader; 01113 return false; 01114 } 01115 01116 // load into a buffer 01117 lock(); 01118 alcSuspendContext(m_context); 01119 01120 AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory; 01121 bf->factory = factory; 01122 01123 try 01124 { 01125 alGenBuffers(1, &bf->buffer); 01126 if(alGetError() != AL_NO_ERROR) 01127 AUD_THROW(AUD_ERROR_OPENAL); 01128 01129 try 01130 { 01131 sample_t* buf; 01132 int length = reader->getLength(); 01133 01134 reader->read(length, buf); 01135 alBufferData(bf->buffer, format, buf, 01136 length * AUD_DEVICE_SAMPLE_SIZE(specs), 01137 specs.rate); 01138 if(alGetError() != AL_NO_ERROR) 01139 AUD_THROW(AUD_ERROR_OPENAL); 01140 } 01141 catch(AUD_Exception&) 01142 { 01143 alDeleteBuffers(1, &bf->buffer); 01144 throw; 01145 } 01146 } 01147 catch(AUD_Exception&) 01148 { 01149 delete bf; 01150 delete reader; 01151 alcProcessContext(m_context); 01152 unlock(); 01153 return false; 01154 } 01155 01156 m_bufferedFactories->push_back(bf); 01157 01158 alcProcessContext(m_context); 01159 unlock(); 01160 } 01161 else 01162 { 01163 // stop all playing and paused buffered sources 01164 lock(); 01165 alcSuspendContext(m_context); 01166 01167 AUD_OpenALHandle* sound; 01168 AUD_HandleIterator it = m_playingSounds->begin(); 01169 while(it != m_playingSounds->end()) 01170 { 01171 sound = *it; 01172 ++it; 01173 01174 if(sound->isBuffered) 01175 stop(sound); 01176 } 01177 alcProcessContext(m_context); 01178 01179 while(!m_bufferedFactories->empty()) 01180 { 01181 alDeleteBuffers(1, 01182 &(*(m_bufferedFactories->begin()))->buffer); 01183 delete *m_bufferedFactories->begin(); 01184 m_bufferedFactories->erase(m_bufferedFactories->begin()); 01185 } 01186 unlock(); 01187 } 01188 01189 return true; 01190 }*/ 01191 01192 /******************************************************************************/ 01193 /**************************** 3D Device Code **********************************/ 01194 /******************************************************************************/ 01195 01196 AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const 01197 { 01198 ALfloat p[3]; 01199 alGetListenerfv(AL_POSITION, p); 01200 return AUD_Vector3(p[0], p[1], p[2]); 01201 } 01202 01203 void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location) 01204 { 01205 alListenerfv(AL_POSITION, (ALfloat*)location.get()); 01206 } 01207 01208 AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const 01209 { 01210 ALfloat v[3]; 01211 alGetListenerfv(AL_VELOCITY, v); 01212 return AUD_Vector3(v[0], v[1], v[2]); 01213 } 01214 01215 void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity) 01216 { 01217 alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get()); 01218 } 01219 01220 AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const 01221 { 01222 // AUD_XXX not implemented yet 01223 return AUD_Quaternion(0, 0, 0, 0); 01224 } 01225 01226 void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation) 01227 { 01228 ALfloat direction[6]; 01229 direction[0] = -2 * (orientation.w() * orientation.y() + 01230 orientation.x() * orientation.z()); 01231 direction[1] = 2 * (orientation.x() * orientation.w() - 01232 orientation.z() * orientation.y()); 01233 direction[2] = 2 * (orientation.x() * orientation.x() + 01234 orientation.y() * orientation.y()) - 1; 01235 direction[3] = 2 * (orientation.x() * orientation.y() - 01236 orientation.w() * orientation.z()); 01237 direction[4] = 1 - 2 * (orientation.x() * orientation.x() + 01238 orientation.z() * orientation.z()); 01239 direction[5] = 2 * (orientation.w() * orientation.x() + 01240 orientation.y() * orientation.z()); 01241 alListenerfv(AL_ORIENTATION, direction); 01242 } 01243 01244 float AUD_OpenALDevice::getSpeedOfSound() const 01245 { 01246 return alGetFloat(AL_SPEED_OF_SOUND); 01247 } 01248 01249 void AUD_OpenALDevice::setSpeedOfSound(float speed) 01250 { 01251 alSpeedOfSound(speed); 01252 } 01253 01254 float AUD_OpenALDevice::getDopplerFactor() const 01255 { 01256 return alGetFloat(AL_DOPPLER_FACTOR); 01257 } 01258 01259 void AUD_OpenALDevice::setDopplerFactor(float factor) 01260 { 01261 alDopplerFactor(factor); 01262 } 01263 01264 AUD_DistanceModel AUD_OpenALDevice::getDistanceModel() const 01265 { 01266 switch(alGetInteger(AL_DISTANCE_MODEL)) 01267 { 01268 case AL_INVERSE_DISTANCE: 01269 return AUD_DISTANCE_MODEL_INVERSE; 01270 case AL_INVERSE_DISTANCE_CLAMPED: 01271 return AUD_DISTANCE_MODEL_INVERSE_CLAMPED; 01272 case AL_LINEAR_DISTANCE: 01273 return AUD_DISTANCE_MODEL_LINEAR; 01274 case AL_LINEAR_DISTANCE_CLAMPED: 01275 return AUD_DISTANCE_MODEL_LINEAR_CLAMPED; 01276 case AL_EXPONENT_DISTANCE: 01277 return AUD_DISTANCE_MODEL_EXPONENT; 01278 case AL_EXPONENT_DISTANCE_CLAMPED: 01279 return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED; 01280 default: 01281 return AUD_DISTANCE_MODEL_INVALID; 01282 } 01283 } 01284 01285 void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model) 01286 { 01287 switch(model) 01288 { 01289 case AUD_DISTANCE_MODEL_INVERSE: 01290 alDistanceModel(AL_INVERSE_DISTANCE); 01291 break; 01292 case AUD_DISTANCE_MODEL_INVERSE_CLAMPED: 01293 alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); 01294 break; 01295 case AUD_DISTANCE_MODEL_LINEAR: 01296 alDistanceModel(AL_LINEAR_DISTANCE); 01297 break; 01298 case AUD_DISTANCE_MODEL_LINEAR_CLAMPED: 01299 alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); 01300 break; 01301 case AUD_DISTANCE_MODEL_EXPONENT: 01302 alDistanceModel(AL_EXPONENT_DISTANCE); 01303 break; 01304 case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED: 01305 alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED); 01306 break; 01307 default: 01308 alDistanceModel(AL_NONE); 01309 } 01310 } 01311 01312 AUD_Vector3 AUD_OpenALDevice::getSourceLocation(AUD_Handle* handle) 01313 { 01314 AUD_Vector3 result = AUD_Vector3(0, 0, 0); 01315 ALfloat p[3]; 01316 lock(); 01317 01318 if(isValid(handle)) 01319 { 01320 alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, p); 01321 result = AUD_Vector3(p[0], p[1], p[2]); 01322 } 01323 01324 unlock(); 01325 return result; 01326 } 01327 01328 bool AUD_OpenALDevice::setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location) 01329 { 01330 lock(); 01331 bool result = isValid(handle); 01332 01333 if(result) 01334 alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, 01335 (ALfloat*)location.get()); 01336 01337 unlock(); 01338 return result; 01339 } 01340 01341 AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* handle) 01342 { 01343 AUD_Vector3 result = AUD_Vector3(0, 0, 0); 01344 ALfloat v[3]; 01345 lock(); 01346 01347 if(isValid(handle)) 01348 { 01349 alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, v); 01350 result = AUD_Vector3(v[0], v[1], v[2]); 01351 } 01352 01353 unlock(); 01354 return result; 01355 } 01356 01357 bool AUD_OpenALDevice::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity) 01358 { 01359 lock(); 01360 bool result = isValid(handle); 01361 01362 if(result) 01363 alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, 01364 (ALfloat*)velocity.get()); 01365 01366 unlock(); 01367 return result; 01368 } 01369 01370 AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle) 01371 { 01372 // AUD_XXX not implemented yet 01373 return AUD_Quaternion(0, 0, 0, 0); 01374 } 01375 01376 bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation) 01377 { 01378 lock(); 01379 bool result = isValid(handle); 01380 01381 if(result) 01382 { 01383 ALfloat direction[3]; 01384 direction[0] = -2 * (orientation.w() * orientation.y() + 01385 orientation.x() * orientation.z()); 01386 direction[1] = 2 * (orientation.x() * orientation.w() - 01387 orientation.z() * orientation.y()); 01388 direction[2] = 2 * (orientation.x() * orientation.x() + 01389 orientation.y() * orientation.y()) - 1; 01390 alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_DIRECTION, 01391 direction); 01392 } 01393 01394 unlock(); 01395 return result; 01396 } 01397 01398 bool AUD_OpenALDevice::isRelative(AUD_Handle* handle) 01399 { 01400 int result = std::numeric_limits<float>::quiet_NaN();; 01401 01402 lock(); 01403 01404 if(isValid(handle)) 01405 alGetSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE, 01406 &result); 01407 01408 unlock(); 01409 return result; 01410 } 01411 01412 bool AUD_OpenALDevice::setRelative(AUD_Handle* handle, bool relative) 01413 { 01414 lock(); 01415 bool result = isValid(handle); 01416 01417 if(result) 01418 alSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE, 01419 relative); 01420 01421 unlock(); 01422 return result; 01423 } 01424 01425 float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle) 01426 { 01427 float result = std::numeric_limits<float>::quiet_NaN();; 01428 01429 lock(); 01430 01431 if(isValid(handle)) 01432 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN, 01433 &result); 01434 01435 unlock(); 01436 return result; 01437 } 01438 01439 bool AUD_OpenALDevice::setVolumeMaximum(AUD_Handle* handle, float volume) 01440 { 01441 lock(); 01442 bool result = isValid(handle); 01443 01444 if(result) 01445 01446 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN, 01447 volume); 01448 01449 unlock(); 01450 return result; 01451 } 01452 01453 float AUD_OpenALDevice::getVolumeMinimum(AUD_Handle* handle) 01454 { 01455 float result = std::numeric_limits<float>::quiet_NaN();; 01456 01457 lock(); 01458 01459 if(isValid(handle)) 01460 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN, 01461 &result); 01462 01463 unlock(); 01464 return result; 01465 } 01466 01467 bool AUD_OpenALDevice::setVolumeMinimum(AUD_Handle* handle, float volume) 01468 { 01469 lock(); 01470 bool result = isValid(handle); 01471 01472 if(result) 01473 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN, 01474 volume); 01475 01476 unlock(); 01477 return result; 01478 } 01479 01480 float AUD_OpenALDevice::getDistanceMaximum(AUD_Handle* handle) 01481 { 01482 float result = std::numeric_limits<float>::quiet_NaN();; 01483 01484 lock(); 01485 01486 if(isValid(handle)) 01487 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE, 01488 &result); 01489 01490 unlock(); 01491 return result; 01492 } 01493 01494 bool AUD_OpenALDevice::setDistanceMaximum(AUD_Handle* handle, float distance) 01495 { 01496 lock(); 01497 bool result = isValid(handle); 01498 01499 if(result) 01500 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE, 01501 distance); 01502 01503 unlock(); 01504 return result; 01505 } 01506 01507 float AUD_OpenALDevice::getDistanceReference(AUD_Handle* handle) 01508 { 01509 float result = std::numeric_limits<float>::quiet_NaN();; 01510 01511 lock(); 01512 01513 if(isValid(handle)) 01514 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE, 01515 &result); 01516 01517 unlock(); 01518 return result; 01519 } 01520 01521 bool AUD_OpenALDevice::setDistanceReference(AUD_Handle* handle, float distance) 01522 { 01523 lock(); 01524 bool result = isValid(handle); 01525 01526 if(result) 01527 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE, 01528 distance); 01529 01530 unlock(); 01531 return result; 01532 } 01533 01534 float AUD_OpenALDevice::getAttenuation(AUD_Handle* handle) 01535 { 01536 float result = std::numeric_limits<float>::quiet_NaN();; 01537 01538 lock(); 01539 01540 if(isValid(handle)) 01541 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR, 01542 &result); 01543 01544 unlock(); 01545 return result; 01546 } 01547 01548 bool AUD_OpenALDevice::setAttenuation(AUD_Handle* handle, float factor) 01549 { 01550 lock(); 01551 bool result = isValid(handle); 01552 01553 if(result) 01554 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR, 01555 factor); 01556 01557 unlock(); 01558 return result; 01559 } 01560 01561 float AUD_OpenALDevice::getConeAngleOuter(AUD_Handle* handle) 01562 { 01563 float result = std::numeric_limits<float>::quiet_NaN();; 01564 01565 lock(); 01566 01567 if(isValid(handle)) 01568 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE, 01569 &result); 01570 01571 unlock(); 01572 return result; 01573 } 01574 01575 bool AUD_OpenALDevice::setConeAngleOuter(AUD_Handle* handle, float angle) 01576 { 01577 lock(); 01578 bool result = isValid(handle); 01579 01580 if(result) 01581 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE, 01582 angle); 01583 01584 unlock(); 01585 return result; 01586 } 01587 01588 float AUD_OpenALDevice::getConeAngleInner(AUD_Handle* handle) 01589 { 01590 float result = std::numeric_limits<float>::quiet_NaN();; 01591 01592 lock(); 01593 01594 if(isValid(handle)) 01595 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE, 01596 &result); 01597 01598 unlock(); 01599 return result; 01600 } 01601 01602 bool AUD_OpenALDevice::setConeAngleInner(AUD_Handle* handle, float angle) 01603 { 01604 lock(); 01605 bool result = isValid(handle); 01606 01607 if(result) 01608 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE, 01609 angle); 01610 01611 unlock(); 01612 return result; 01613 } 01614 01615 float AUD_OpenALDevice::getConeVolumeOuter(AUD_Handle* handle) 01616 { 01617 float result = std::numeric_limits<float>::quiet_NaN();; 01618 01619 lock(); 01620 01621 if(isValid(handle)) 01622 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN, 01623 &result); 01624 01625 unlock(); 01626 return result; 01627 } 01628 01629 bool AUD_OpenALDevice::setConeVolumeOuter(AUD_Handle* handle, float volume) 01630 { 01631 lock(); 01632 bool result = isValid(handle); 01633 01634 if(result) 01635 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN, 01636 volume); 01637 01638 unlock(); 01639 return result; 01640 }