Audaspace:
[blender-staging.git] / intern / audaspace / intern / AUD_SoftwareDevice.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * Copyright 2009-2011 Jörg Hermann Müller
5  *
6  * This file is part of AudaSpace.
7  *
8  * Audaspace is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * AudaSpace is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Audaspace; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file audaspace/intern/AUD_SoftwareDevice.cpp
26  *  \ingroup audaspaceintern
27  */
28
29
30 #include "AUD_SoftwareDevice.h"
31 #include "AUD_IReader.h"
32 #include "AUD_Mixer.h"
33 #include "AUD_IFactory.h"
34 #include "AUD_JOSResampleReader.h"
35 #include "AUD_LinearResampleReader.h"
36 #include "AUD_MutexLock.h"
37
38 #include <cstring>
39 #include <cmath>
40 #include <limits>
41
42 #ifndef M_PI
43 #define M_PI 3.14159265358979323846
44 #endif
45
46 typedef enum
47 {
48         AUD_RENDER_DISTANCE = 0x01,
49         AUD_RENDER_DOPPLER = 0x02,
50         AUD_RENDER_CONE = 0x04,
51         AUD_RENDER_VOLUME = 0x08
52 } AUD_RenderFlags;
53
54 #define AUD_PITCH_MAX 10
55
56 /******************************************************************************/
57 /********************** AUD_SoftwareHandle Handle Code ************************/
58 /******************************************************************************/
59
60 AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_PitchReader> pitch, boost::shared_ptr<AUD_ResampleReader> resampler, boost::shared_ptr<AUD_ChannelMapperReader> mapper, bool keep) :
61         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),
62         m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
63         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),
64         m_flags(AUD_RENDER_CONE), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device)
65 {
66 }
67
68 void AUD_SoftwareDevice::AUD_SoftwareHandle::update()
69 {
70         int flags = 0;
71
72         AUD_Vector3 SL;
73         if(m_relative)
74                 SL = -m_location;
75         else
76                 SL = m_device->m_location - m_location;
77         float distance = SL * SL;
78
79         if(distance > 0)
80                 distance = sqrt(distance);
81         else
82                 flags |= AUD_RENDER_DOPPLER | AUD_RENDER_DISTANCE;
83
84         if(m_pitch->getSpecs().channels != AUD_CHANNELS_MONO)
85         {
86                 m_volume = m_user_volume;
87                 m_pitch->setPitch(m_user_pitch);
88                 return;
89         }
90
91         flags = ~(flags | m_flags | m_device->m_flags);
92
93         // Doppler and Pitch
94
95         if(flags & AUD_RENDER_DOPPLER)
96         {
97                 float vls;
98                 if(m_relative)
99                         vls = 0;
100                 else
101                         vls = SL * m_device->m_velocity / distance;
102                 float vss = SL * m_velocity / distance;
103                 float max = m_device->m_speed_of_sound / m_device->m_doppler_factor;
104                 if(vss >= max)
105                 {
106                         m_pitch->setPitch(AUD_PITCH_MAX);
107                 }
108                 else
109                 {
110                         if(vls > max)
111                                 vls = max;
112
113                         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);
114                 }
115         }
116         else
117                 m_pitch->setPitch(m_user_pitch);
118
119         if(flags & AUD_RENDER_VOLUME)
120         {
121                 // Distance
122
123                 if(flags & AUD_RENDER_DISTANCE)
124                 {
125                         if(m_device->m_distance_model == AUD_DISTANCE_MODEL_INVERSE_CLAMPED ||
126                            m_device->m_distance_model == AUD_DISTANCE_MODEL_LINEAR_CLAMPED ||
127                            m_device->m_distance_model == AUD_DISTANCE_MODEL_EXPONENT_CLAMPED)
128                         {
129                                 distance = AUD_MAX(AUD_MIN(m_distance_max, distance), m_distance_reference);
130                         }
131
132                         switch(m_device->m_distance_model)
133                         {
134                         case AUD_DISTANCE_MODEL_INVERSE:
135                         case AUD_DISTANCE_MODEL_INVERSE_CLAMPED:
136                                 m_volume = m_distance_reference / (m_distance_reference + m_attenuation * (distance - m_distance_reference));
137                                 break;
138                         case AUD_DISTANCE_MODEL_LINEAR:
139                         case AUD_DISTANCE_MODEL_LINEAR_CLAMPED:
140                         {
141                                 float temp = m_distance_max - m_distance_reference;
142                                 if(temp == 0)
143                                 {
144                                         if(distance > m_distance_reference)
145                                                 m_volume = 0.0f;
146                                         else
147                                                 m_volume = 1.0f;
148                                 }
149                                 else
150                                         m_volume = 1.0f - m_attenuation * (distance - m_distance_reference) / (m_distance_max - m_distance_reference);
151                                 break;
152                         }
153                         case AUD_DISTANCE_MODEL_EXPONENT:
154                         case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED:
155                                 if(m_distance_reference == 0)
156                                         m_volume = 0;
157                                 else
158                                         m_volume = pow(distance / m_distance_reference, -m_attenuation);
159                                 break;
160                         default:
161                                 m_volume = 1.0f;
162                         }
163                 }
164                 else
165                         m_volume = 1.0f;
166
167                 // Cone
168
169                 if(flags & AUD_RENDER_CONE)
170                 {
171                         AUD_Vector3 SZ = m_orientation.getLookAt();
172
173                         float phi = acos(float(SZ * SL / (SZ.length() * SL.length())));
174                         float t = (phi - m_cone_angle_inner)/(m_cone_angle_outer - m_cone_angle_inner);
175
176                         if(t > 0)
177                         {
178                                 if(t > 1)
179                                         m_volume *= m_cone_volume_outer;
180                                 else
181                                         m_volume *= 1 + t * (m_cone_volume_outer - 1);
182                         }
183                 }
184
185                 if(m_volume > m_volume_max)
186                         m_volume = m_volume_max;
187                 else if(m_volume < m_volume_min)
188                         m_volume = m_volume_min;
189
190                 // Volume
191
192                 m_volume *= m_user_volume;
193         }
194
195         // 3D Cue
196
197         AUD_Quaternion orientation;
198
199         if(!m_relative)
200                 orientation = m_device->m_orientation;
201
202         AUD_Vector3 Z = orientation.getLookAt();
203         AUD_Vector3 N = orientation.getUp();
204         AUD_Vector3 A = N * ((SL * N) / (N * N)) - SL;
205
206         float Asquare = A * A;
207
208         if(Asquare > 0)
209         {
210                 float phi = acos(float(Z * A / (Z.length() * sqrt(Asquare))));
211                 if(N.cross(Z) * A > 0)
212                         phi = -phi;
213
214                 m_mapper->setMonoAngle(phi);
215         }
216         else
217                 m_mapper->setMonoAngle(m_relative ? m_user_pan * M_PI / 2.0 : 0);
218 }
219
220 void AUD_SoftwareDevice::AUD_SoftwareHandle::setSpecs(AUD_Specs specs)
221 {
222         m_mapper->setChannels(specs.channels);
223         m_resampler->setRate(specs.rate);
224 }
225
226 bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause()
227 {
228         if(m_status)
229         {
230                 AUD_MutexLock lock(*m_device);
231
232                 if(m_status == AUD_STATUS_PLAYING)
233                 {
234                         for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
235                         {
236                                 if(it->get() == this)
237                                 {
238                                         boost::shared_ptr<AUD_SoftwareHandle> This = *it;
239
240                                         m_device->m_playingSounds.erase(it);
241                                         m_device->m_pausedSounds.push_back(This);
242
243                                         if(m_device->m_playingSounds.empty())
244                                                 m_device->playing(m_device->m_playback = false);
245
246                                         m_status = AUD_STATUS_PAUSED;
247
248                                         return true;
249                                 }
250                         }
251                 }
252         }
253
254         return false;
255 }
256
257 bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume()
258 {
259         if(m_status)
260         {
261                 AUD_MutexLock lock(*m_device);
262
263                 if(m_status == AUD_STATUS_PAUSED)
264                 {
265                         for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++)
266                         {
267                                 if(it->get() == this)
268                                 {
269                                         boost::shared_ptr<AUD_SoftwareHandle> This = *it;
270
271                                         m_device->m_pausedSounds.erase(it);
272
273                                         m_device->m_playingSounds.push_back(This);
274
275                                         if(!m_device->m_playback)
276                                                 m_device->playing(m_device->m_playback = true);
277                                         m_status = AUD_STATUS_PLAYING;
278
279                                         return true;
280                                 }
281                         }
282                 }
283
284         }
285
286         return false;
287 }
288
289 bool AUD_SoftwareDevice::AUD_SoftwareHandle::stop()
290 {
291         if(!m_status)
292                 return false;
293
294         AUD_MutexLock lock(*m_device);
295
296         if(!m_status)
297                 return false;
298
299         m_status = AUD_STATUS_INVALID;
300
301         for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
302         {
303                 if(it->get() == this)
304                 {
305                         boost::shared_ptr<AUD_SoftwareHandle> This = *it;
306
307                         m_device->m_playingSounds.erase(it);
308
309                         if(m_device->m_playingSounds.empty())
310                                 m_device->playing(m_device->m_playback = false);
311
312                         return true;
313                 }
314         }
315
316         for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++)
317         {
318                 if(it->get() == this)
319                 {
320                         m_device->m_pausedSounds.erase(it);
321                         return true;
322                 }
323         }
324
325         return false;
326 }
327
328 bool AUD_SoftwareDevice::AUD_SoftwareHandle::getKeep()
329 {
330         if(m_status)
331                 return m_keep;
332
333         return false;
334 }
335
336 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setKeep(bool keep)
337 {
338         if(!m_status)
339                 return false;
340
341         AUD_MutexLock lock(*m_device);
342
343         if(!m_status)
344                 return false;
345
346         m_keep = keep;
347
348         return true;
349 }
350
351 bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position)
352 {
353         if(!m_status)
354                 return false;
355
356         AUD_MutexLock lock(*m_device);
357
358         if(!m_status)
359                 return false;
360
361         m_reader->seek((int)(position * m_reader->getSpecs().rate));
362
363         return true;
364 }
365
366 float AUD_SoftwareDevice::AUD_SoftwareHandle::getPosition()
367 {
368         if(!m_status)
369                 return false;
370
371         AUD_MutexLock lock(*m_device);
372
373         if(!m_status)
374                 return 0.0f;
375
376         float position = m_reader->getPosition() / (float)m_device->m_specs.rate;
377
378         return position;
379 }
380
381 AUD_Status AUD_SoftwareDevice::AUD_SoftwareHandle::getStatus()
382 {
383         return m_status;
384 }
385
386 float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolume()
387 {
388         return m_user_volume;
389 }
390
391 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolume(float volume)
392 {
393         if(!m_status)
394                 return false;
395         m_user_volume = volume;
396
397         if(volume == 0)
398         {
399                 m_volume = volume;
400                 m_flags |= AUD_RENDER_VOLUME;
401         }
402         else
403                 m_flags &= ~AUD_RENDER_VOLUME;
404
405         return true;
406 }
407
408 float AUD_SoftwareDevice::AUD_SoftwareHandle::getPitch()
409 {
410         return m_user_pitch;
411 }
412
413 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setPitch(float pitch)
414 {
415         if(!m_status)
416                 return false;
417         m_user_pitch = pitch;
418         return true;
419 }
420
421 int AUD_SoftwareDevice::AUD_SoftwareHandle::getLoopCount()
422 {
423         if(!m_status)
424                 return 0;
425         return m_loopcount;
426 }
427
428 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setLoopCount(int count)
429 {
430         if(!m_status)
431                 return false;
432         m_loopcount = count;
433         return true;
434 }
435
436 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setStopCallback(stopCallback callback, void* data)
437 {
438         if(!m_status)
439                 return false;
440
441         AUD_MutexLock lock(*m_device);
442
443         if(!m_status)
444                 return false;
445
446         m_stop = callback;
447         m_stop_data = data;
448
449         return true;
450 }
451
452
453
454 /******************************************************************************/
455 /******************** AUD_SoftwareHandle 3DHandle Code ************************/
456 /******************************************************************************/
457
458 AUD_Vector3 AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceLocation()
459 {
460         if(!m_status)
461                 return AUD_Vector3();
462
463         return m_location;
464 }
465
466 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceLocation(const AUD_Vector3& location)
467 {
468         if(!m_status)
469                 return false;
470
471         m_location = location;
472
473         return true;
474 }
475
476 AUD_Vector3 AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceVelocity()
477 {
478         if(!m_status)
479                 return AUD_Vector3();
480
481         return m_velocity;
482 }
483
484 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceVelocity(const AUD_Vector3& velocity)
485 {
486         if(!m_status)
487                 return false;
488
489         m_velocity = velocity;
490
491         return true;
492 }
493
494 AUD_Quaternion AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceOrientation()
495 {
496         if(!m_status)
497                 return AUD_Quaternion();
498
499         return m_orientation;
500 }
501
502 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceOrientation(const AUD_Quaternion& orientation)
503 {
504         if(!m_status)
505                 return false;
506
507         m_orientation = orientation;
508
509         return true;
510 }
511
512 bool AUD_SoftwareDevice::AUD_SoftwareHandle::isRelative()
513 {
514         if(!m_status)
515                 return false;
516
517         return m_relative;
518 }
519
520 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setRelative(bool relative)
521 {
522         if(!m_status)
523                 return false;
524
525         m_relative = relative;
526
527         return true;
528 }
529
530 float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolumeMaximum()
531 {
532         if(!m_status)
533                 return std::numeric_limits<float>::quiet_NaN();
534
535         return m_volume_max;
536 }
537
538 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolumeMaximum(float volume)
539 {
540         if(!m_status)
541                 return false;
542
543         m_volume_max = volume;
544
545         return true;
546 }
547
548 float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolumeMinimum()
549 {
550         if(!m_status)
551                 return std::numeric_limits<float>::quiet_NaN();
552
553         return m_volume_min;
554 }
555
556 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolumeMinimum(float volume)
557 {
558         if(!m_status)
559                 return false;
560
561         m_volume_min = volume;
562
563         return true;
564 }
565
566 float AUD_SoftwareDevice::AUD_SoftwareHandle::getDistanceMaximum()
567 {
568         if(!m_status)
569                 return std::numeric_limits<float>::quiet_NaN();
570
571         return m_distance_max;
572 }
573
574 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setDistanceMaximum(float distance)
575 {
576         if(!m_status)
577                 return false;
578
579         m_distance_max = distance;
580
581         return true;
582 }
583
584 float AUD_SoftwareDevice::AUD_SoftwareHandle::getDistanceReference()
585 {
586         if(!m_status)
587                 return std::numeric_limits<float>::quiet_NaN();
588
589         return m_distance_reference;
590 }
591
592 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setDistanceReference(float distance)
593 {
594         if(!m_status)
595                 return false;
596
597         m_distance_reference = distance;
598
599         return true;
600 }
601
602 float AUD_SoftwareDevice::AUD_SoftwareHandle::getAttenuation()
603 {
604         if(!m_status)
605                 return std::numeric_limits<float>::quiet_NaN();
606
607         return m_attenuation;
608 }
609
610 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setAttenuation(float factor)
611 {
612         if(!m_status)
613                 return false;
614
615         m_attenuation = factor;
616
617         if(factor == 0)
618                 m_flags |= AUD_RENDER_DISTANCE;
619         else
620                 m_flags &= ~AUD_RENDER_DISTANCE;
621
622         return true;
623 }
624
625 float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeAngleOuter()
626 {
627         if(!m_status)
628                 return std::numeric_limits<float>::quiet_NaN();
629
630         return m_cone_angle_outer * 360.0f / M_PI;
631 }
632
633 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeAngleOuter(float angle)
634 {
635         if(!m_status)
636                 return false;
637
638         m_cone_angle_outer = angle * M_PI / 360.0f;
639
640         return true;
641 }
642
643 float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeAngleInner()
644 {
645         if(!m_status)
646                 return std::numeric_limits<float>::quiet_NaN();
647
648         return m_cone_angle_inner * 360.0f / M_PI;
649 }
650
651 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeAngleInner(float angle)
652 {
653         if(!m_status)
654                 return false;
655
656         if(angle >= 360)
657                 m_flags |= AUD_RENDER_CONE;
658         else
659                 m_flags &= ~AUD_RENDER_CONE;
660
661         m_cone_angle_inner = angle * M_PI / 360.0f;
662
663         return true;
664 }
665
666 float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeVolumeOuter()
667 {
668         if(!m_status)
669                 return std::numeric_limits<float>::quiet_NaN();
670
671         return m_cone_volume_outer;
672 }
673
674 bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeVolumeOuter(float volume)
675 {
676         if(!m_status)
677                 return false;
678
679         m_cone_volume_outer = volume;
680
681         return true;
682 }
683
684 /******************************************************************************/
685 /**************************** IDevice Code ************************************/
686 /******************************************************************************/
687
688 void AUD_SoftwareDevice::create()
689 {
690         m_playback = false;
691         m_volume = 1.0f;
692         m_mixer = boost::shared_ptr<AUD_Mixer>(new AUD_Mixer(m_specs));
693         m_speed_of_sound = 343.0f;
694         m_doppler_factor = 1.0f;
695         m_distance_model = AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
696         m_flags = 0;
697         m_quality = false;
698
699         pthread_mutexattr_t attr;
700         pthread_mutexattr_init(&attr);
701         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
702
703         pthread_mutex_init(&m_mutex, &attr);
704
705         pthread_mutexattr_destroy(&attr);
706 }
707
708 void AUD_SoftwareDevice::destroy()
709 {
710         if(m_playback)
711                 playing(m_playback = false);
712
713         while(!m_playingSounds.empty())
714                 m_playingSounds.front()->stop();
715
716         while(!m_pausedSounds.empty())
717                 m_pausedSounds.front()->stop();
718
719         pthread_mutex_destroy(&m_mutex);
720 }
721
722 void AUD_SoftwareDevice::mix(data_t* buffer, int length)
723 {
724         m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs));
725
726         AUD_MutexLock lock(*this);
727
728         {
729                 boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle> sound;
730                 int len;
731                 int pos;
732                 bool eos;
733                 std::list<boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle> > stopSounds;
734                 std::list<boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle> > pauseSounds;
735                 sample_t* buf = m_buffer.getBuffer();
736
737                 m_mixer->clear(length);
738
739                 // for all sounds
740                 AUD_HandleIterator it = m_playingSounds.begin();
741                 while(it != m_playingSounds.end())
742                 {
743                         sound = *it;
744                         // increment the iterator to make sure it's valid,
745                         // in case the sound gets deleted after stopping
746                         ++it;
747
748                         // get the buffer from the source
749                         pos = 0;
750                         len = length;
751
752                         // update 3D Info
753                         sound->update();
754
755                         sound->m_reader->read(len, eos, buf);
756
757                         // in case of looping
758                         while(pos + len < length && sound->m_loopcount && eos)
759                         {
760                                 m_mixer->mix(buf, pos, len, sound->m_volume);
761
762                                 pos += len;
763
764                                 if(sound->m_loopcount > 0)
765                                         sound->m_loopcount--;
766
767                                 sound->m_reader->seek(0);
768
769                                 len = length - pos;
770                                 sound->m_reader->read(len, eos, buf);
771
772                                 // prevent endless loop
773                                 if(!len)
774                                         break;
775                         }
776
777                         m_mixer->mix(buf, pos, len, sound->m_volume);
778
779                         // in case the end of the sound is reached
780                         if(eos && !sound->m_loopcount)
781                         {
782                                 if(sound->m_stop)
783                                         sound->m_stop(sound->m_stop_data);
784
785                                 if(sound->m_keep)
786                                         pauseSounds.push_back(sound);
787                                 else
788                                         stopSounds.push_back(sound);
789                         }
790                 }
791
792                 // superpose
793                 m_mixer->read(buffer, m_volume);
794
795                 // cleanup
796                 while(!stopSounds.empty())
797                 {
798                         sound = stopSounds.front();
799                         stopSounds.pop_front();
800                         sound->stop();
801                 }
802
803                 while(!pauseSounds.empty())
804                 {
805                         sound = pauseSounds.front();
806                         pauseSounds.pop_front();
807                         sound->pause();
808                 }
809         }
810 }
811
812 void AUD_SoftwareDevice::setPanning(AUD_IHandle* handle, float pan)
813 {
814         AUD_SoftwareDevice::AUD_SoftwareHandle* h = dynamic_cast<AUD_SoftwareDevice::AUD_SoftwareHandle*>(handle);
815         h->m_user_pan = pan;
816 }
817
818 void AUD_SoftwareDevice::setQuality(bool quality)
819 {
820         m_quality = quality;
821 }
822
823 void AUD_SoftwareDevice::setSpecs(AUD_Specs specs)
824 {
825         m_specs.specs = specs;
826         m_mixer->setSpecs(specs);
827
828         for(AUD_HandleIterator it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
829         {
830                 (*it)->setSpecs(specs);
831         }
832 }
833
834 AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const
835 {
836         return m_specs;
837 }
838
839 boost::shared_ptr<AUD_IHandle> AUD_SoftwareDevice::play(boost::shared_ptr<AUD_IReader> reader, bool keep)
840 {
841         // prepare the reader
842         // pitch
843
844         boost::shared_ptr<AUD_PitchReader> pitch = boost::shared_ptr<AUD_PitchReader>(new AUD_PitchReader(reader, 1));
845         reader = boost::shared_ptr<AUD_IReader>(pitch);
846
847         boost::shared_ptr<AUD_ResampleReader> resampler;
848
849         // resample
850         if(m_quality)
851                 resampler = boost::shared_ptr<AUD_ResampleReader>(new AUD_JOSResampleReader(reader, m_specs.specs));
852         else
853                 resampler = boost::shared_ptr<AUD_ResampleReader>(new AUD_LinearResampleReader(reader, m_specs.specs));
854         reader = boost::shared_ptr<AUD_IReader>(resampler);
855
856         // rechannel
857         boost::shared_ptr<AUD_ChannelMapperReader> mapper = boost::shared_ptr<AUD_ChannelMapperReader>(new AUD_ChannelMapperReader(reader, m_specs.channels));
858         reader = boost::shared_ptr<AUD_IReader>(mapper);
859
860         if(!reader.get())
861                 return boost::shared_ptr<AUD_IHandle>();
862
863         // play sound
864         boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle>(new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, resampler, mapper, keep));
865
866         AUD_MutexLock lock(*this);
867
868         m_playingSounds.push_back(sound);
869
870         if(!m_playback)
871                 playing(m_playback = true);
872
873         return boost::shared_ptr<AUD_IHandle>(sound);
874 }
875
876 boost::shared_ptr<AUD_IHandle> AUD_SoftwareDevice::play(boost::shared_ptr<AUD_IFactory> factory, bool keep)
877 {
878         return play(factory->createReader(), keep);
879 }
880
881 void AUD_SoftwareDevice::stopAll()
882 {
883         AUD_MutexLock lock(*this);
884
885         while(!m_playingSounds.empty())
886                 m_playingSounds.front()->stop();
887
888         while(!m_pausedSounds.empty())
889                 m_pausedSounds.front()->stop();
890 }
891
892 void AUD_SoftwareDevice::lock()
893 {
894         pthread_mutex_lock(&m_mutex);
895 }
896
897 void AUD_SoftwareDevice::unlock()
898 {
899         pthread_mutex_unlock(&m_mutex);
900 }
901
902 float AUD_SoftwareDevice::getVolume() const
903 {
904         return m_volume;
905 }
906
907 void AUD_SoftwareDevice::setVolume(float volume)
908 {
909         m_volume = volume;
910 }
911
912 /******************************************************************************/
913 /**************************** 3D Device Code **********************************/
914 /******************************************************************************/
915
916 AUD_Vector3 AUD_SoftwareDevice::getListenerLocation() const
917 {
918         return m_location;
919 }
920
921 void AUD_SoftwareDevice::setListenerLocation(const AUD_Vector3& location)
922 {
923         m_location = location;
924 }
925
926 AUD_Vector3 AUD_SoftwareDevice::getListenerVelocity() const
927 {
928         return m_velocity;
929 }
930
931 void AUD_SoftwareDevice::setListenerVelocity(const AUD_Vector3& velocity)
932 {
933         m_velocity = velocity;
934 }
935
936 AUD_Quaternion AUD_SoftwareDevice::getListenerOrientation() const
937 {
938         return m_orientation;
939 }
940
941 void AUD_SoftwareDevice::setListenerOrientation(const AUD_Quaternion& orientation)
942 {
943         m_orientation = orientation;
944 }
945
946 float AUD_SoftwareDevice::getSpeedOfSound() const
947 {
948         return m_speed_of_sound;
949 }
950
951 void AUD_SoftwareDevice::setSpeedOfSound(float speed)
952 {
953         m_speed_of_sound = speed;
954 }
955
956 float AUD_SoftwareDevice::getDopplerFactor() const
957 {
958         return m_doppler_factor;
959 }
960
961 void AUD_SoftwareDevice::setDopplerFactor(float factor)
962 {
963         m_doppler_factor = factor;
964         if(factor == 0)
965                 m_flags |= AUD_RENDER_DOPPLER;
966         else
967                 m_flags &= ~AUD_RENDER_DOPPLER;
968 }
969
970 AUD_DistanceModel AUD_SoftwareDevice::getDistanceModel() const
971 {
972         return m_distance_model;
973 }
974
975 void AUD_SoftwareDevice::setDistanceModel(AUD_DistanceModel model)
976 {
977         m_distance_model = model;
978         if(model == AUD_DISTANCE_MODEL_INVALID)
979                 m_flags |= AUD_RENDER_DISTANCE;
980         else
981                 m_flags &= ~AUD_RENDER_DISTANCE;
982 }