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_SoftwareDevice.h" 00031 #include "AUD_IReader.h" 00032 #include "AUD_Mixer.h" 00033 #include "AUD_IFactory.h" 00034 #include "AUD_JOSResampleReader.h" 00035 #include "AUD_LinearResampleReader.h" 00036 00037 #include <cstring> 00038 #include <cmath> 00039 #include <limits> 00040 00041 #ifndef M_PI 00042 #define M_PI 3.14159265358979323846 00043 #endif 00044 00045 typedef enum 00046 { 00047 AUD_RENDER_DISTANCE = 0x01, 00048 AUD_RENDER_DOPPLER = 0x02, 00049 AUD_RENDER_CONE = 0x04, 00050 AUD_RENDER_VOLUME = 0x08 00051 } AUD_RenderFlags; 00052 00053 #define AUD_PITCH_MAX 10 00054 00055 /******************************************************************************/ 00056 /********************** AUD_SoftwareHandle Handle Code ************************/ 00057 /******************************************************************************/ 00058 00059 AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ResampleReader> resampler, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep) : 00060 m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(1.0f), m_loopcount(0), 00061 m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()), 00062 m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0), 00063 m_flags(AUD_RENDER_CONE), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device) 00064 { 00065 } 00066 00067 void AUD_SoftwareDevice::AUD_SoftwareHandle::update() 00068 { 00069 int flags = 0; 00070 00071 AUD_Vector3 SL; 00072 if(m_relative) 00073 SL = -m_location; 00074 else 00075 SL = m_device->m_location - m_location; 00076 float distance = SL * SL; 00077 00078 if(distance > 0) 00079 distance = sqrt(distance); 00080 else 00081 flags |= AUD_RENDER_DOPPLER | AUD_RENDER_DISTANCE; 00082 00083 if(m_pitch->getSpecs().channels != AUD_CHANNELS_MONO) 00084 { 00085 m_volume = m_user_volume; 00086 m_pitch->setPitch(m_user_pitch); 00087 return; 00088 } 00089 00090 flags = ~(flags | m_flags | m_device->m_flags); 00091 00092 // Doppler and Pitch 00093 00094 if(flags & AUD_RENDER_DOPPLER) 00095 { 00096 float vls; 00097 if(m_relative) 00098 vls = 0; 00099 else 00100 vls = SL * m_device->m_velocity / distance; 00101 float vss = SL * m_velocity / distance; 00102 float max = m_device->m_speed_of_sound / m_device->m_doppler_factor; 00103 if(vss >= max) 00104 { 00105 m_pitch->setPitch(AUD_PITCH_MAX); 00106 } 00107 else 00108 { 00109 if(vls > max) 00110 vls = max; 00111 00112 m_pitch->setPitch((m_device->m_speed_of_sound - m_device->m_doppler_factor * vls) / (m_device->m_speed_of_sound - m_device->m_doppler_factor * vss) * m_user_pitch); 00113 } 00114 } 00115 else 00116 m_pitch->setPitch(m_user_pitch); 00117 00118 if(flags & AUD_RENDER_VOLUME) 00119 { 00120 // Distance 00121 00122 if(flags & AUD_RENDER_DISTANCE) 00123 { 00124 if(m_device->m_distance_model == AUD_DISTANCE_MODEL_INVERSE_CLAMPED || 00125 m_device->m_distance_model == AUD_DISTANCE_MODEL_LINEAR_CLAMPED || 00126 m_device->m_distance_model == AUD_DISTANCE_MODEL_EXPONENT_CLAMPED) 00127 { 00128 distance = AUD_MAX(AUD_MIN(m_distance_max, distance), m_distance_reference); 00129 } 00130 00131 switch(m_device->m_distance_model) 00132 { 00133 case AUD_DISTANCE_MODEL_INVERSE: 00134 case AUD_DISTANCE_MODEL_INVERSE_CLAMPED: 00135 m_volume = m_distance_reference / (m_distance_reference + m_attenuation * (distance - m_distance_reference)); 00136 break; 00137 case AUD_DISTANCE_MODEL_LINEAR: 00138 case AUD_DISTANCE_MODEL_LINEAR_CLAMPED: 00139 { 00140 float temp = m_distance_max - m_distance_reference; 00141 if(temp == 0) 00142 { 00143 if(distance > m_distance_reference) 00144 m_volume = 0.0f; 00145 else 00146 m_volume = 1.0f; 00147 } 00148 else 00149 m_volume = 1.0f - m_attenuation * (distance - m_distance_reference) / (m_distance_max - m_distance_reference); 00150 break; 00151 } 00152 case AUD_DISTANCE_MODEL_EXPONENT: 00153 case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED: 00154 if(m_distance_reference == 0) 00155 m_volume = 0; 00156 else 00157 m_volume = pow(distance / m_distance_reference, -m_attenuation); 00158 break; 00159 default: 00160 m_volume = 1.0f; 00161 } 00162 } 00163 else 00164 m_volume = 1.0f; 00165 00166 // Cone 00167 00168 if(flags & AUD_RENDER_CONE) 00169 { 00170 AUD_Vector3 SZ = m_orientation.getLookAt(); 00171 00172 float phi = acos(float(SZ * SL / (SZ.length() * SL.length()))); 00173 float t = (phi - m_cone_angle_inner)/(m_cone_angle_outer - m_cone_angle_inner); 00174 00175 if(t > 0) 00176 { 00177 if(t > 1) 00178 m_volume *= m_cone_volume_outer; 00179 else 00180 m_volume *= 1 + t * (m_cone_volume_outer - 1); 00181 } 00182 } 00183 00184 if(m_volume > m_volume_max) 00185 m_volume = m_volume_max; 00186 else if(m_volume < m_volume_min) 00187 m_volume = m_volume_min; 00188 00189 // Volume 00190 00191 m_volume *= m_user_volume; 00192 } 00193 00194 // 3D Cue 00195 00196 AUD_Quaternion orientation; 00197 00198 if(!m_relative) 00199 orientation = m_device->m_orientation; 00200 00201 AUD_Vector3 Z = orientation.getLookAt(); 00202 AUD_Vector3 N = orientation.getUp(); 00203 AUD_Vector3 A = N * ((SL * N) / (N * N)) - SL; 00204 00205 float Asquare = A * A; 00206 00207 if(Asquare > 0) 00208 { 00209 float phi = acos(float(Z * A / (Z.length() * sqrt(Asquare)))); 00210 if(N.cross(Z) * A > 0) 00211 phi = -phi; 00212 00213 m_mapper->setMonoAngle(phi); 00214 } 00215 else 00216 m_mapper->setMonoAngle(m_relative ? m_user_pan * M_PI / 2.0 : 0); 00217 } 00218 00219 void AUD_SoftwareDevice::AUD_SoftwareHandle::setSpecs(AUD_Specs specs) 00220 { 00221 m_mapper->setChannels(specs.channels); 00222 m_resampler->setRate(specs.rate); 00223 } 00224 00225 bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause() 00226 { 00227 if(m_status) 00228 { 00229 m_device->lock(); 00230 00231 if(m_status == AUD_STATUS_PLAYING) 00232 { 00233 m_device->m_playingSounds.remove(this); 00234 m_device->m_pausedSounds.push_back(this); 00235 00236 if(m_device->m_playingSounds.empty()) 00237 m_device->playing(m_device->m_playback = false); 00238 m_status = AUD_STATUS_PAUSED; 00239 m_device->unlock(); 00240 00241 return true; 00242 } 00243 00244 m_device->unlock(); 00245 } 00246 00247 return false; 00248 } 00249 00250 bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume() 00251 { 00252 if(m_status) 00253 { 00254 m_device->lock(); 00255 00256 if(m_status == AUD_STATUS_PAUSED) 00257 { 00258 m_device->m_pausedSounds.remove(this); 00259 m_device->m_playingSounds.push_back(this); 00260 00261 if(!m_device->m_playback) 00262 m_device->playing(m_device->m_playback = true); 00263 m_status = AUD_STATUS_PLAYING; 00264 m_device->unlock(); 00265 return true; 00266 } 00267 00268 m_device->unlock(); 00269 } 00270 00271 return false; 00272 } 00273 00274 bool AUD_SoftwareDevice::AUD_SoftwareHandle::stop() 00275 { 00276 if(!m_status) 00277 return false; 00278 00279 m_device->lock(); 00280 00281 // AUD_XXX Create a reference of our own object so that it doesn't get 00282 // deleted before the end of this function 00283 AUD_Reference<AUD_SoftwareHandle> This = this; 00284 00285 if(m_status == AUD_STATUS_PLAYING) 00286 { 00287 m_device->m_playingSounds.remove(This); 00288 00289 if(m_device->m_playingSounds.empty()) 00290 m_device->playing(m_device->m_playback = false); 00291 } 00292 else 00293 m_device->m_pausedSounds.remove(This); 00294 00295 m_device->unlock(); 00296 m_status = AUD_STATUS_INVALID; 00297 return true; 00298 } 00299 00300 bool AUD_SoftwareDevice::AUD_SoftwareHandle::getKeep() 00301 { 00302 if(m_status) 00303 return m_keep; 00304 00305 return false; 00306 } 00307 00308 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setKeep(bool keep) 00309 { 00310 if(!m_status) 00311 return false; 00312 00313 m_device->lock(); 00314 00315 m_keep = keep; 00316 00317 m_device->unlock(); 00318 00319 return true; 00320 } 00321 00322 bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position) 00323 { 00324 if(!m_status) 00325 return false; 00326 00327 m_device->lock(); 00328 00329 m_reader->seek((int)(position * m_reader->getSpecs().rate)); 00330 00331 m_device->unlock(); 00332 00333 return true; 00334 } 00335 00336 float AUD_SoftwareDevice::AUD_SoftwareHandle::getPosition() 00337 { 00338 if(!m_status) 00339 return 0.0f; 00340 00341 m_device->lock(); 00342 00343 float position = m_reader->getPosition() / (float)m_device->m_specs.rate; 00344 00345 m_device->unlock(); 00346 00347 return position; 00348 } 00349 00350 AUD_Status AUD_SoftwareDevice::AUD_SoftwareHandle::getStatus() 00351 { 00352 return m_status; 00353 } 00354 00355 float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolume() 00356 { 00357 return m_user_volume; 00358 } 00359 00360 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolume(float volume) 00361 { 00362 if(!m_status) 00363 return false; 00364 m_user_volume = volume; 00365 00366 if(volume == 0) 00367 { 00368 m_volume = volume; 00369 m_flags |= AUD_RENDER_VOLUME; 00370 } 00371 else 00372 m_flags &= ~AUD_RENDER_VOLUME; 00373 00374 return true; 00375 } 00376 00377 float AUD_SoftwareDevice::AUD_SoftwareHandle::getPitch() 00378 { 00379 return m_user_pitch; 00380 } 00381 00382 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setPitch(float pitch) 00383 { 00384 if(!m_status) 00385 return false; 00386 m_user_pitch = pitch; 00387 return true; 00388 } 00389 00390 int AUD_SoftwareDevice::AUD_SoftwareHandle::getLoopCount() 00391 { 00392 if(!m_status) 00393 return 0; 00394 return m_loopcount; 00395 } 00396 00397 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setLoopCount(int count) 00398 { 00399 if(!m_status) 00400 return false; 00401 m_loopcount = count; 00402 return true; 00403 } 00404 00405 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setStopCallback(stopCallback callback, void* data) 00406 { 00407 if(!m_status) 00408 return false; 00409 00410 m_device->lock(); 00411 00412 m_stop = callback; 00413 m_stop_data = data; 00414 00415 m_device->unlock(); 00416 00417 return true; 00418 } 00419 00420 00421 00422 /******************************************************************************/ 00423 /******************** AUD_SoftwareHandle 3DHandle Code ************************/ 00424 /******************************************************************************/ 00425 00426 AUD_Vector3 AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceLocation() 00427 { 00428 if(!m_status) 00429 return AUD_Vector3(); 00430 00431 return m_location; 00432 } 00433 00434 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceLocation(const AUD_Vector3& location) 00435 { 00436 if(!m_status) 00437 return false; 00438 00439 m_location = location; 00440 00441 return true; 00442 } 00443 00444 AUD_Vector3 AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceVelocity() 00445 { 00446 if(!m_status) 00447 return AUD_Vector3(); 00448 00449 return m_velocity; 00450 } 00451 00452 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceVelocity(const AUD_Vector3& velocity) 00453 { 00454 if(!m_status) 00455 return false; 00456 00457 m_velocity = velocity; 00458 00459 return true; 00460 } 00461 00462 AUD_Quaternion AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceOrientation() 00463 { 00464 if(!m_status) 00465 return AUD_Quaternion(); 00466 00467 return m_orientation; 00468 } 00469 00470 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceOrientation(const AUD_Quaternion& orientation) 00471 { 00472 if(!m_status) 00473 return false; 00474 00475 m_orientation = orientation; 00476 00477 return true; 00478 } 00479 00480 bool AUD_SoftwareDevice::AUD_SoftwareHandle::isRelative() 00481 { 00482 if(!m_status) 00483 return false; 00484 00485 return m_relative; 00486 } 00487 00488 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setRelative(bool relative) 00489 { 00490 if(!m_status) 00491 return false; 00492 00493 m_relative = relative; 00494 00495 return true; 00496 } 00497 00498 float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolumeMaximum() 00499 { 00500 if(!m_status) 00501 return std::numeric_limits<float>::quiet_NaN(); 00502 00503 return m_volume_max; 00504 } 00505 00506 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolumeMaximum(float volume) 00507 { 00508 if(!m_status) 00509 return false; 00510 00511 m_volume_max = volume; 00512 00513 return true; 00514 } 00515 00516 float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolumeMinimum() 00517 { 00518 if(!m_status) 00519 return std::numeric_limits<float>::quiet_NaN(); 00520 00521 return m_volume_min; 00522 } 00523 00524 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolumeMinimum(float volume) 00525 { 00526 if(!m_status) 00527 return false; 00528 00529 m_volume_min = volume; 00530 00531 return true; 00532 } 00533 00534 float AUD_SoftwareDevice::AUD_SoftwareHandle::getDistanceMaximum() 00535 { 00536 if(!m_status) 00537 return std::numeric_limits<float>::quiet_NaN(); 00538 00539 return m_distance_max; 00540 } 00541 00542 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setDistanceMaximum(float distance) 00543 { 00544 if(!m_status) 00545 return false; 00546 00547 m_distance_max = distance; 00548 00549 return true; 00550 } 00551 00552 float AUD_SoftwareDevice::AUD_SoftwareHandle::getDistanceReference() 00553 { 00554 if(!m_status) 00555 return std::numeric_limits<float>::quiet_NaN(); 00556 00557 return m_distance_reference; 00558 } 00559 00560 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setDistanceReference(float distance) 00561 { 00562 if(!m_status) 00563 return false; 00564 00565 m_distance_reference = distance; 00566 00567 return true; 00568 } 00569 00570 float AUD_SoftwareDevice::AUD_SoftwareHandle::getAttenuation() 00571 { 00572 if(!m_status) 00573 return std::numeric_limits<float>::quiet_NaN(); 00574 00575 return m_attenuation; 00576 } 00577 00578 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setAttenuation(float factor) 00579 { 00580 if(!m_status) 00581 return false; 00582 00583 m_attenuation = factor; 00584 00585 if(factor == 0) 00586 m_flags |= AUD_RENDER_DISTANCE; 00587 else 00588 m_flags &= ~AUD_RENDER_DISTANCE; 00589 00590 return true; 00591 } 00592 00593 float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeAngleOuter() 00594 { 00595 if(!m_status) 00596 return std::numeric_limits<float>::quiet_NaN(); 00597 00598 return m_cone_angle_outer * 360.0f / M_PI; 00599 } 00600 00601 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeAngleOuter(float angle) 00602 { 00603 if(!m_status) 00604 return false; 00605 00606 m_cone_angle_outer = angle * M_PI / 360.0f; 00607 00608 return true; 00609 } 00610 00611 float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeAngleInner() 00612 { 00613 if(!m_status) 00614 return std::numeric_limits<float>::quiet_NaN(); 00615 00616 return m_cone_angle_inner * 360.0f / M_PI; 00617 } 00618 00619 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeAngleInner(float angle) 00620 { 00621 if(!m_status) 00622 return false; 00623 00624 if(angle >= 360) 00625 m_flags |= AUD_RENDER_CONE; 00626 else 00627 m_flags &= ~AUD_RENDER_CONE; 00628 00629 m_cone_angle_inner = angle * M_PI / 360.0f; 00630 00631 return true; 00632 } 00633 00634 float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeVolumeOuter() 00635 { 00636 if(!m_status) 00637 return std::numeric_limits<float>::quiet_NaN(); 00638 00639 return m_cone_volume_outer; 00640 } 00641 00642 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeVolumeOuter(float volume) 00643 { 00644 if(!m_status) 00645 return false; 00646 00647 m_cone_volume_outer = volume; 00648 00649 return true; 00650 } 00651 00652 /******************************************************************************/ 00653 /**************************** IDevice Code ************************************/ 00654 /******************************************************************************/ 00655 00656 void AUD_SoftwareDevice::create() 00657 { 00658 m_playback = false; 00659 m_volume = 1.0f; 00660 m_mixer = new AUD_Mixer(m_specs); 00661 m_speed_of_sound = 343.0f; 00662 m_doppler_factor = 1.0f; 00663 m_distance_model = AUD_DISTANCE_MODEL_INVERSE_CLAMPED; 00664 m_flags = 0; 00665 m_quality = false; 00666 00667 pthread_mutexattr_t attr; 00668 pthread_mutexattr_init(&attr); 00669 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 00670 00671 pthread_mutex_init(&m_mutex, &attr); 00672 00673 pthread_mutexattr_destroy(&attr); 00674 } 00675 00676 void AUD_SoftwareDevice::destroy() 00677 { 00678 if(m_playback) 00679 playing(m_playback = false); 00680 00681 while(!m_playingSounds.empty()) 00682 m_playingSounds.front()->stop(); 00683 00684 while(!m_pausedSounds.empty()) 00685 m_pausedSounds.front()->stop(); 00686 00687 pthread_mutex_destroy(&m_mutex); 00688 } 00689 00690 void AUD_SoftwareDevice::mix(data_t* buffer, int length) 00691 { 00692 m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs)); 00693 00694 lock(); 00695 00696 { 00697 AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound; 00698 int len; 00699 int pos; 00700 bool eos; 00701 std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> > stopSounds; 00702 std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> > pauseSounds; 00703 sample_t* buf = m_buffer.getBuffer(); 00704 00705 m_mixer->clear(length); 00706 00707 // for all sounds 00708 AUD_HandleIterator it = m_playingSounds.begin(); 00709 while(it != m_playingSounds.end()) 00710 { 00711 sound = *it; 00712 // increment the iterator to make sure it's valid, 00713 // in case the sound gets deleted after stopping 00714 ++it; 00715 00716 // get the buffer from the source 00717 pos = 0; 00718 len = length; 00719 00720 // update 3D Info 00721 sound->update(); 00722 00723 sound->m_reader->read(len, eos, buf); 00724 00725 // in case of looping 00726 while(pos + len < length && sound->m_loopcount && eos) 00727 { 00728 m_mixer->mix(buf, pos, len, sound->m_volume); 00729 00730 pos += len; 00731 00732 if(sound->m_loopcount > 0) 00733 sound->m_loopcount--; 00734 00735 sound->m_reader->seek(0); 00736 00737 len = length - pos; 00738 sound->m_reader->read(len, eos, buf); 00739 00740 // prevent endless loop 00741 if(!len) 00742 break; 00743 } 00744 00745 m_mixer->mix(buf, pos, len, sound->m_volume); 00746 00747 // in case the end of the sound is reached 00748 if(eos && !sound->m_loopcount) 00749 { 00750 if(sound->m_stop) 00751 sound->m_stop(sound->m_stop_data); 00752 00753 if(sound->m_keep) 00754 pauseSounds.push_back(sound); 00755 else 00756 stopSounds.push_back(sound); 00757 } 00758 } 00759 00760 // superpose 00761 m_mixer->read(buffer, m_volume); 00762 00763 // cleanup 00764 while(!stopSounds.empty()) 00765 { 00766 sound = stopSounds.front(); 00767 stopSounds.pop_front(); 00768 sound->stop(); 00769 } 00770 00771 while(!pauseSounds.empty()) 00772 { 00773 sound = pauseSounds.front(); 00774 pauseSounds.pop_front(); 00775 sound->pause(); 00776 } 00777 } 00778 00779 unlock(); 00780 } 00781 00782 void AUD_SoftwareDevice::setPanning(AUD_IHandle* handle, float pan) 00783 { 00784 AUD_SoftwareDevice::AUD_SoftwareHandle* h = dynamic_cast<AUD_SoftwareDevice::AUD_SoftwareHandle*>(handle); 00785 h->m_user_pan = pan; 00786 } 00787 00788 void AUD_SoftwareDevice::setQuality(bool quality) 00789 { 00790 m_quality = quality; 00791 } 00792 00793 void AUD_SoftwareDevice::setSpecs(AUD_Specs specs) 00794 { 00795 m_specs.specs = specs; 00796 m_mixer->setSpecs(specs); 00797 00798 for(AUD_HandleIterator it = m_playingSounds.begin(); it != m_playingSounds.end(); it++) 00799 { 00800 (*it)->setSpecs(specs); 00801 } 00802 } 00803 00804 AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const 00805 { 00806 return m_specs; 00807 } 00808 00809 AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) 00810 { 00811 // prepare the reader 00812 // pitch 00813 00814 AUD_Reference<AUD_PitchReader> pitch = new AUD_PitchReader(reader, 1); 00815 reader = AUD_Reference<AUD_IReader>(pitch); 00816 00817 AUD_Reference<AUD_ResampleReader> resampler; 00818 00819 // resample 00820 if(m_quality) 00821 resampler = new AUD_JOSResampleReader(reader, m_specs.specs); 00822 else 00823 resampler = new AUD_LinearResampleReader(reader, m_specs.specs); 00824 reader = AUD_Reference<AUD_IReader>(resampler); 00825 00826 // rechannel 00827 AUD_Reference<AUD_ChannelMapperReader> mapper = new AUD_ChannelMapperReader(reader, m_specs.channels); 00828 reader = AUD_Reference<AUD_IReader>(mapper); 00829 00830 if(reader.isNull()) 00831 return AUD_Reference<AUD_IHandle>(); 00832 00833 // play sound 00834 AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, resampler, mapper, keep); 00835 00836 lock(); 00837 m_playingSounds.push_back(sound); 00838 00839 if(!m_playback) 00840 playing(m_playback = true); 00841 unlock(); 00842 00843 return AUD_Reference<AUD_IHandle>(sound); 00844 } 00845 00846 AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) 00847 { 00848 return play(factory->createReader(), keep); 00849 } 00850 00851 void AUD_SoftwareDevice::stopAll() 00852 { 00853 lock(); 00854 00855 while(!m_playingSounds.empty()) 00856 m_playingSounds.front()->stop(); 00857 00858 while(!m_pausedSounds.empty()) 00859 m_pausedSounds.front()->stop(); 00860 00861 unlock(); 00862 } 00863 00864 void AUD_SoftwareDevice::lock() 00865 { 00866 pthread_mutex_lock(&m_mutex); 00867 } 00868 00869 void AUD_SoftwareDevice::unlock() 00870 { 00871 pthread_mutex_unlock(&m_mutex); 00872 } 00873 00874 float AUD_SoftwareDevice::getVolume() const 00875 { 00876 return m_volume; 00877 } 00878 00879 void AUD_SoftwareDevice::setVolume(float volume) 00880 { 00881 m_volume = volume; 00882 } 00883 00884 /******************************************************************************/ 00885 /**************************** 3D Device Code **********************************/ 00886 /******************************************************************************/ 00887 00888 AUD_Vector3 AUD_SoftwareDevice::getListenerLocation() const 00889 { 00890 return m_location; 00891 } 00892 00893 void AUD_SoftwareDevice::setListenerLocation(const AUD_Vector3& location) 00894 { 00895 m_location = location; 00896 } 00897 00898 AUD_Vector3 AUD_SoftwareDevice::getListenerVelocity() const 00899 { 00900 return m_velocity; 00901 } 00902 00903 void AUD_SoftwareDevice::setListenerVelocity(const AUD_Vector3& velocity) 00904 { 00905 m_velocity = velocity; 00906 } 00907 00908 AUD_Quaternion AUD_SoftwareDevice::getListenerOrientation() const 00909 { 00910 return m_orientation; 00911 } 00912 00913 void AUD_SoftwareDevice::setListenerOrientation(const AUD_Quaternion& orientation) 00914 { 00915 m_orientation = orientation; 00916 } 00917 00918 float AUD_SoftwareDevice::getSpeedOfSound() const 00919 { 00920 return m_speed_of_sound; 00921 } 00922 00923 void AUD_SoftwareDevice::setSpeedOfSound(float speed) 00924 { 00925 m_speed_of_sound = speed; 00926 } 00927 00928 float AUD_SoftwareDevice::getDopplerFactor() const 00929 { 00930 return m_doppler_factor; 00931 } 00932 00933 void AUD_SoftwareDevice::setDopplerFactor(float factor) 00934 { 00935 m_doppler_factor = factor; 00936 if(factor == 0) 00937 m_flags |= AUD_RENDER_DOPPLER; 00938 else 00939 m_flags &= ~AUD_RENDER_DOPPLER; 00940 } 00941 00942 AUD_DistanceModel AUD_SoftwareDevice::getDistanceModel() const 00943 { 00944 return m_distance_model; 00945 } 00946 00947 void AUD_SoftwareDevice::setDistanceModel(AUD_DistanceModel model) 00948 { 00949 m_distance_model = model; 00950 if(model == AUD_DISTANCE_MODEL_INVALID) 00951 m_flags |= AUD_RENDER_DISTANCE; 00952 else 00953 m_flags &= ~AUD_RENDER_DISTANCE; 00954 }