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