Blender V2.61 - r43446

AUD_SoftwareDevice.cpp

Go to the documentation of this file.
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 }