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