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