Audaspace:
[blender.git] / intern / audaspace / OpenAL / AUD_OpenALDevice.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/OpenAL/AUD_OpenALDevice.cpp
26  *  \ingroup audopenal
27  */
28
29
30 #include "AUD_OpenALDevice.h"
31 #include "AUD_IFactory.h"
32 #include "AUD_IReader.h"
33 #include "AUD_ConverterReader.h"
34 #include "AUD_MutexLock.h"
35
36 #include <cstring>
37 #include <limits>
38
39 #ifdef WIN32
40 #include <windows.h>
41 #else
42 #include <unistd.h>
43 #endif
44
45 /*struct AUD_OpenALBufferedFactory
46 {
47         /// The factory.
48         AUD_IFactory* factory;
49
50         /// The OpenAL buffer.
51         ALuint buffer;
52 };*/
53
54 //typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
55
56
57 /******************************************************************************/
58 /*********************** AUD_OpenALHandle Handle Code *************************/
59 /******************************************************************************/
60
61 static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be "
62                                                                          "generated.";
63 static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be "
64                                                                          "generated.";
65 static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
66                                                                  "queued to the source.";
67 static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
68                                                                           "filled with data.";
69
70 AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, boost::shared_ptr<AUD_IReader> reader, bool keep) :
71         m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0),
72         m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING),
73         m_device(device)
74 {
75         AUD_DeviceSpecs specs = m_device->m_specs;
76         specs.specs = m_reader->getSpecs();
77
78         // OpenAL playback code
79         alGenBuffers(CYCLE_BUFFERS, m_buffers);
80         if(alGetError() != AL_NO_ERROR)
81                 AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
82
83         try
84         {
85                 m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
86                 int length;
87                 bool eos;
88
89                 for(int i = 0; i < CYCLE_BUFFERS; i++)
90                 {
91                         length = m_device->m_buffersize;
92                         reader->read(length, eos, m_device->m_buffer.getBuffer());
93                         alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
94                                                  length * AUD_DEVICE_SAMPLE_SIZE(specs),
95                                                  specs.rate);
96                         if(alGetError() != AL_NO_ERROR)
97                                 AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
98                 }
99
100                 alGenSources(1, &m_source);
101                 if(alGetError() != AL_NO_ERROR)
102                         AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
103
104                 try
105                 {
106                         alSourceQueueBuffers(m_source, CYCLE_BUFFERS,
107                                                                  m_buffers);
108                         if(alGetError() != AL_NO_ERROR)
109                                 AUD_THROW(AUD_ERROR_OPENAL, queue_error);
110                 }
111                 catch(AUD_Exception&)
112                 {
113                         alDeleteSources(1, &m_source);
114                         throw;
115                 }
116         }
117         catch(AUD_Exception&)
118         {
119                 alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
120                 throw;
121         }
122         alSourcei(m_source, AL_SOURCE_RELATIVE, 1);
123 }
124
125 bool AUD_OpenALDevice::AUD_OpenALHandle::pause()
126 {
127         if(m_status)
128         {
129                 AUD_MutexLock lock(*m_device);
130
131                 if(m_status == AUD_STATUS_PLAYING)
132                 {
133                         for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
134                         {
135                                 if(it->get() == this)
136                                 {
137                                         boost::shared_ptr<AUD_OpenALHandle> This = *it;
138
139                                         m_device->m_playingSounds.erase(it);
140                                         m_device->m_pausedSounds.push_back(This);
141
142                                         alSourcePause(m_source);
143
144                                         m_status = AUD_STATUS_PAUSED;
145
146                                         return true;
147                                 }
148                         }
149                 }
150         }
151
152         return false;
153 }
154
155 bool AUD_OpenALDevice::AUD_OpenALHandle::resume()
156 {
157         if(m_status)
158         {
159                 AUD_MutexLock lock(*m_device);
160
161                 if(m_status == AUD_STATUS_PAUSED)
162                 {
163                         for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++)
164                         {
165                                 if(it->get() == this)
166                                 {
167                                         boost::shared_ptr<AUD_OpenALHandle> This = *it;
168
169                                         m_device->m_pausedSounds.erase(it);
170                                         m_device->m_playingSounds.push_back(This);
171
172                                         m_device->start();
173                                         m_status = AUD_STATUS_PLAYING;
174
175                                         return true;
176                                 }
177                         }
178                 }
179         }
180
181         return false;
182 }
183
184 bool AUD_OpenALDevice::AUD_OpenALHandle::stop()
185 {
186         if(!m_status)
187                 return false;
188
189         AUD_MutexLock lock(*m_device);
190
191         if(!m_status)
192                 return false;
193
194         m_status = AUD_STATUS_INVALID;
195
196         alDeleteSources(1, &m_source);
197         if(!m_isBuffered)
198                 alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
199
200         for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
201         {
202                 if(it->get() == this)
203                 {
204                         boost::shared_ptr<AUD_OpenALHandle> This = *it;
205
206                         m_device->m_playingSounds.erase(it);
207
208                         return true;
209                 }
210         }
211
212         for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++)
213         {
214                 if(it->get() == this)
215                 {
216                         m_device->m_pausedSounds.erase(it);
217                         return true;
218                 }
219         }
220
221         return false;
222 }
223
224 bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep()
225 {
226         if(m_status)
227                 return m_keep;
228
229         return false;
230 }
231
232 bool AUD_OpenALDevice::AUD_OpenALHandle::setKeep(bool keep)
233 {
234         if(!m_status)
235                 return false;
236
237         AUD_MutexLock lock(*m_device);
238
239         if(!m_status)
240                 return false;
241
242         m_keep = keep;
243
244         return true;
245 }
246
247 bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position)
248 {
249         if(!m_status)
250                 return false;
251
252         AUD_MutexLock lock(*m_device);
253
254         if(!m_status)
255                 return false;
256
257         if(m_isBuffered)
258                 alSourcef(m_source, AL_SEC_OFFSET, position);
259         else
260         {
261                 m_reader->seek((int)(position * m_reader->getSpecs().rate));
262                 m_eos = false;
263
264                 ALint info;
265
266                 alGetSourcei(m_source, AL_SOURCE_STATE, &info);
267
268                 if(info != AL_PLAYING)
269                 {
270                         if(info == AL_PAUSED)
271                                 alSourceStop(m_source);
272
273                         alSourcei(m_source, AL_BUFFER, 0);
274                         m_current = 0;
275
276                         ALenum err;
277                         if((err = alGetError()) == AL_NO_ERROR)
278                         {
279                                 int length;
280                                 AUD_DeviceSpecs specs = m_device->m_specs;
281                                 specs.specs = m_reader->getSpecs();
282                                 m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
283
284                                 for(int i = 0; i < CYCLE_BUFFERS; i++)
285                                 {
286                                         length = m_device->m_buffersize;
287                                         m_reader->read(length, m_eos, m_device->m_buffer.getBuffer());
288                                         alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
289                                                                  length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate);
290
291                                         if(alGetError() != AL_NO_ERROR)
292                                                 break;
293                                 }
294
295                                 if(m_loopcount != 0)
296                                         m_eos = false;
297
298                                 alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers);
299                         }
300
301                         alSourceRewind(m_source);
302                 }
303         }
304
305         return true;
306 }
307
308 float AUD_OpenALDevice::AUD_OpenALHandle::getPosition()
309 {
310         if(!m_status)
311                 return false;
312
313         AUD_MutexLock lock(*m_device);
314
315         if(!m_status)
316                 return 0.0f;
317
318         float position = 0.0f;
319
320         alGetSourcef(m_source, AL_SEC_OFFSET, &position);
321
322         if(!m_isBuffered)
323         {
324                 AUD_Specs specs = m_reader->getSpecs();
325                 position += (m_reader->getPosition() - m_device->m_buffersize *
326                                          CYCLE_BUFFERS) / (float)specs.rate;
327         }
328
329         return position;
330 }
331
332 AUD_Status AUD_OpenALDevice::AUD_OpenALHandle::getStatus()
333 {
334         return m_status;
335 }
336
337 float AUD_OpenALDevice::AUD_OpenALHandle::getVolume()
338 {
339         float result = std::numeric_limits<float>::quiet_NaN();
340
341         if(!m_status)
342                 return false;
343
344         AUD_MutexLock lock(*m_device);
345
346         if(!m_status)
347                 return result;
348
349         alGetSourcef(m_source, AL_GAIN, &result);
350
351         return result;
352 }
353
354 bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume)
355 {
356         if(!m_status)
357                 return false;
358
359         AUD_MutexLock lock(*m_device);
360
361         if(!m_status)
362                 return false;
363
364         alSourcef(m_source, AL_GAIN, volume);
365
366         return true;
367 }
368
369 float AUD_OpenALDevice::AUD_OpenALHandle::getPitch()
370 {
371         float result = std::numeric_limits<float>::quiet_NaN();
372
373         if(!m_status)
374                 return false;
375
376         AUD_MutexLock lock(*m_device);
377
378         if(!m_status)
379                 return result;
380
381         alGetSourcef(m_source, AL_PITCH, &result);
382
383         return result;
384 }
385
386 bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch)
387 {
388         if(!m_status)
389                 return false;
390
391         AUD_MutexLock lock(*m_device);
392
393         if(!m_status)
394                 return false;
395
396         alSourcef(m_source, AL_PITCH, pitch);
397
398         return true;
399 }
400
401 int AUD_OpenALDevice::AUD_OpenALHandle::getLoopCount()
402 {
403         if(!m_status)
404                 return 0;
405         return m_loopcount;
406 }
407
408 bool AUD_OpenALDevice::AUD_OpenALHandle::setLoopCount(int count)
409 {
410         if(!m_status)
411                 return false;
412         m_loopcount = count;
413         return true;
414 }
415
416 bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, void* data)
417 {
418         if(!m_status)
419                 return false;
420
421         AUD_MutexLock lock(*m_device);
422
423         if(!m_status)
424                 return false;
425
426         m_stop = callback;
427         m_stop_data = data;
428
429         return true;
430 }
431
432 /******************************************************************************/
433 /********************* AUD_OpenALHandle 3DHandle Code *************************/
434 /******************************************************************************/
435
436 AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceLocation()
437 {
438         AUD_Vector3 result = AUD_Vector3(0, 0, 0);
439
440         if(!m_status)
441                 return false;
442
443         AUD_MutexLock lock(*m_device);
444
445         if(!m_status)
446                 return result;
447
448         ALfloat p[3];
449         alGetSourcefv(m_source, AL_POSITION, p);
450
451         result = AUD_Vector3(p[0], p[1], p[2]);
452
453         return result;
454 }
455
456 bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceLocation(const AUD_Vector3& location)
457 {
458         if(!m_status)
459                 return false;
460
461         AUD_MutexLock lock(*m_device);
462
463         if(!m_status)
464                 return false;
465
466         alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get());
467
468         return true;
469 }
470
471 AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity()
472 {
473         AUD_Vector3 result = AUD_Vector3(0, 0, 0);
474
475         if(!m_status)
476                 return false;
477
478         AUD_MutexLock lock(*m_device);
479
480         if(!m_status)
481                 return result;
482
483         ALfloat v[3];
484         alGetSourcefv(m_source, AL_VELOCITY, v);
485
486         result = AUD_Vector3(v[0], v[1], v[2]);
487
488         return result;
489 }
490
491 bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceVelocity(const AUD_Vector3& velocity)
492 {
493         if(!m_status)
494                 return false;
495
496         AUD_MutexLock lock(*m_device);
497
498         if(!m_status)
499                 return false;
500
501         alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get());
502
503         return true;
504 }
505
506 AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation()
507 {
508         return m_orientation;
509 }
510
511 bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation)
512 {
513         ALfloat direction[3];
514         direction[0] = -2 * (orientation.w() * orientation.y() +
515                                                  orientation.x() * orientation.z());
516         direction[1] = 2 * (orientation.x() * orientation.w() -
517                                                 orientation.z() * orientation.y());
518         direction[2] = 2 * (orientation.x() * orientation.x() +
519                                                 orientation.y() * orientation.y()) - 1;
520
521         if(!m_status)
522                 return false;
523
524         AUD_MutexLock lock(*m_device);
525
526         if(!m_status)
527                 return false;
528
529         alSourcefv(m_source, AL_DIRECTION, direction);
530
531         m_orientation = orientation;
532
533         return true;
534 }
535
536 bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative()
537 {
538         int result;
539
540         if(!m_status)
541                 return false;
542
543         AUD_MutexLock lock(*m_device);
544
545         if(!m_status)
546                 return false;
547
548         alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result);
549
550         return result;
551 }
552
553 bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative)
554 {
555         if(!m_status)
556                 return false;
557
558         AUD_MutexLock lock(*m_device);
559
560         if(!m_status)
561                 return false;
562
563         alSourcei(m_source, AL_SOURCE_RELATIVE, relative);
564
565         return true;
566 }
567
568 float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum()
569 {
570         float result = std::numeric_limits<float>::quiet_NaN();
571
572         if(!m_status)
573                 return false;
574
575         AUD_MutexLock lock(*m_device);
576
577         if(!m_status)
578                 return result;
579
580         alGetSourcef(m_source, AL_MAX_GAIN, &result);
581
582         return result;
583 }
584
585 bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume)
586 {
587         if(!m_status)
588                 return false;
589
590         AUD_MutexLock lock(*m_device);
591
592         if(!m_status)
593                 return false;
594
595         alSourcef(m_source, AL_MAX_GAIN, volume);
596
597         return true;
598 }
599
600 float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum()
601 {
602         float result = std::numeric_limits<float>::quiet_NaN();
603
604         if(!m_status)
605                 return false;
606
607         AUD_MutexLock lock(*m_device);
608
609         if(!m_status)
610                 return result;
611
612         alGetSourcef(m_source, AL_MIN_GAIN, &result);
613
614         return result;
615 }
616
617 bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume)
618 {
619         if(!m_status)
620                 return false;
621
622         AUD_MutexLock lock(*m_device);
623
624         if(!m_status)
625                 return false;
626
627         alSourcef(m_source, AL_MIN_GAIN, volume);
628
629         return true;
630 }
631
632 float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum()
633 {
634         float result = std::numeric_limits<float>::quiet_NaN();
635
636         if(!m_status)
637                 return false;
638
639         AUD_MutexLock lock(*m_device);
640
641         if(!m_status)
642                 return result;
643
644         alGetSourcef(m_source, AL_MAX_DISTANCE, &result);
645
646         return result;
647 }
648
649 bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance)
650 {
651         if(!m_status)
652                 return false;
653
654         AUD_MutexLock lock(*m_device);
655
656         if(!m_status)
657                 return false;
658
659         alSourcef(m_source, AL_MAX_DISTANCE, distance);
660
661         return true;
662 }
663
664 float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference()
665 {
666         float result = std::numeric_limits<float>::quiet_NaN();
667
668         if(!m_status)
669                 return false;
670
671         AUD_MutexLock lock(*m_device);
672
673         if(!m_status)
674                 return result;
675
676         alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result);
677
678         return result;
679 }
680
681 bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance)
682 {
683         if(!m_status)
684                 return false;
685
686         AUD_MutexLock lock(*m_device);
687
688         if(!m_status)
689                 return false;
690
691         alSourcef(m_source, AL_REFERENCE_DISTANCE, distance);
692
693         return true;
694 }
695
696 float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation()
697 {
698         float result = std::numeric_limits<float>::quiet_NaN();
699
700         if(!m_status)
701                 return false;
702
703         AUD_MutexLock lock(*m_device);
704
705         if(!m_status)
706                 return result;
707
708         alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result);
709
710         return result;
711 }
712
713 bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor)
714 {
715         if(!m_status)
716                 return false;
717
718         AUD_MutexLock lock(*m_device);
719
720         if(!m_status)
721                 return false;
722
723         alSourcef(m_source, AL_ROLLOFF_FACTOR, factor);
724
725         return true;
726 }
727
728 float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter()
729 {
730         float result = std::numeric_limits<float>::quiet_NaN();
731
732         if(!m_status)
733                 return false;
734
735         AUD_MutexLock lock(*m_device);
736
737         if(!m_status)
738                 return result;
739
740         alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result);
741
742         return result;
743 }
744
745 bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle)
746 {
747         if(!m_status)
748                 return false;
749
750         AUD_MutexLock lock(*m_device);
751
752         if(!m_status)
753                 return false;
754
755         alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle);
756
757         return true;
758 }
759
760 float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner()
761 {
762         float result = std::numeric_limits<float>::quiet_NaN();
763
764         if(!m_status)
765                 return false;
766
767         AUD_MutexLock lock(*m_device);
768
769         if(!m_status)
770                 return result;
771
772         alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result);
773
774         return result;
775 }
776
777 bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle)
778 {
779         if(!m_status)
780                 return false;
781
782         AUD_MutexLock lock(*m_device);
783
784         if(!m_status)
785                 return false;
786
787         alSourcef(m_source, AL_CONE_INNER_ANGLE, angle);
788
789         return true;
790 }
791
792 float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter()
793 {
794         float result = std::numeric_limits<float>::quiet_NaN();
795
796         if(!m_status)
797                 return false;
798
799         AUD_MutexLock lock(*m_device);
800
801         if(!m_status)
802                 return result;
803
804         alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result);
805
806         return result;
807 }
808
809 bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume)
810 {
811         if(!m_status)
812                 return false;
813
814         AUD_MutexLock lock(*m_device);
815
816         if(!m_status)
817                 return false;
818
819         alSourcef(m_source, AL_CONE_OUTER_GAIN, volume);
820
821         return true;
822 }
823
824 /******************************************************************************/
825 /**************************** Threading Code **********************************/
826 /******************************************************************************/
827
828 static void *AUD_openalRunThread(void *device)
829 {
830         AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device;
831         dev->updateStreams();
832         return NULL;
833 }
834
835 void AUD_OpenALDevice::start(bool join)
836 {
837         AUD_MutexLock lock(*this);
838
839         if(!m_playing)
840         {
841                 if(join)
842                         pthread_join(m_thread, NULL);
843
844                 pthread_attr_t attr;
845                 pthread_attr_init(&attr);
846                 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
847
848                 pthread_create(&m_thread, &attr, AUD_openalRunThread, this);
849
850                 pthread_attr_destroy(&attr);
851
852                 m_playing = true;
853         }
854 }
855
856 void AUD_OpenALDevice::updateStreams()
857 {
858         boost::shared_ptr<AUD_OpenALHandle> sound;
859
860         int length;
861
862         ALint info;
863         AUD_DeviceSpecs specs = m_specs;
864         ALCenum cerr;
865         std::list<boost::shared_ptr<AUD_OpenALHandle> > stopSounds;
866         std::list<boost::shared_ptr<AUD_OpenALHandle> > pauseSounds;
867         AUD_HandleIterator it;
868
869         while(1)
870         {
871                 lock();
872
873                 alcSuspendContext(m_context);
874                 cerr = alcGetError(m_device);
875                 if(cerr == ALC_NO_ERROR)
876                 {
877                         // for all sounds
878                         for(it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
879                         {
880                                 sound = *it;
881
882                                 // is it a streamed sound?
883                                 if(!sound->m_isBuffered)
884                                 {
885                                         // check for buffer refilling
886                                         alGetSourcei(sound->m_source, AL_BUFFERS_PROCESSED, &info);
887
888                                         if(info)
889                                         {
890                                                 specs.specs = sound->m_reader->getSpecs();
891                                                 m_buffer.assureSize(m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
892
893                                                 // for all empty buffers
894                                                 while(info--)
895                                                 {
896                                                         // if there's still data to play back
897                                                         if(!sound->m_eos)
898                                                         {
899                                                                 // read data
900                                                                 length = m_buffersize;
901                                                                 sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
902
903                                                                 // looping necessary?
904                                                                 if(length == 0 && sound->m_loopcount)
905                                                                 {
906                                                                         if(sound->m_loopcount > 0)
907                                                                                 sound->m_loopcount--;
908
909                                                                         sound->m_reader->seek(0);
910
911                                                                         length = m_buffersize;
912                                                                         sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
913                                                                 }
914
915                                                                 if(sound->m_loopcount != 0)
916                                                                         sound->m_eos = false;
917
918                                                                 // read nothing?
919                                                                 if(length == 0)
920                                                                 {
921                                                                         break;
922                                                                 }
923
924                                                                 // unqueue buffer
925                                                                 alSourceUnqueueBuffers(sound->m_source, 1,
926                                                                                                 &sound->m_buffers[sound->m_current]);
927                                                                 ALenum err;
928                                                                 if((err = alGetError()) != AL_NO_ERROR)
929                                                                 {
930                                                                         sound->m_eos = true;
931                                                                         break;
932                                                                 }
933
934                                                                 // fill with new data
935                                                                 alBufferData(sound->m_buffers[sound->m_current],
936                                                                                          sound->m_format,
937                                                                                          m_buffer.getBuffer(), length *
938                                                                                          AUD_DEVICE_SAMPLE_SIZE(specs),
939                                                                                          specs.rate);
940
941                                                                 if((err = alGetError()) != AL_NO_ERROR)
942                                                                 {
943                                                                         sound->m_eos = true;
944                                                                         break;
945                                                                 }
946
947                                                                 // and queue again
948                                                                 alSourceQueueBuffers(sound->m_source, 1,
949                                                                                                 &sound->m_buffers[sound->m_current]);
950                                                                 if(alGetError() != AL_NO_ERROR)
951                                                                 {
952                                                                         sound->m_eos = true;
953                                                                         break;
954                                                                 }
955
956                                                                 sound->m_current = (sound->m_current+1) %
957                                                                                                  AUD_OpenALHandle::CYCLE_BUFFERS;
958                                                         }
959                                                         else
960                                                                 break;
961                                                 }
962                                         }
963                                 }
964
965                                 // check if the sound has been stopped
966                                 alGetSourcei(sound->m_source, AL_SOURCE_STATE, &info);
967
968                                 if(info != AL_PLAYING)
969                                 {
970                                         // if it really stopped
971                                         if(sound->m_eos)
972                                         {
973                                                 if(sound->m_stop)
974                                                         sound->m_stop(sound->m_stop_data);
975
976                                                 // pause or
977                                                 if(sound->m_keep)
978                                                         pauseSounds.push_back(sound);
979                                                 // stop
980                                                 else
981                                                         stopSounds.push_back(sound);
982                                         }
983                                         // continue playing
984                                         else
985                                                 alSourcePlay(sound->m_source);
986                                 }
987                         }
988
989                         for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
990                                 (*it)->pause();
991
992                         for(it = stopSounds.begin(); it != stopSounds.end(); it++)
993                                 (*it)->stop();
994
995                         pauseSounds.clear();
996                         stopSounds.clear();
997
998                         alcProcessContext(m_context);
999                 }
1000
1001                 // stop thread
1002                 if(m_playingSounds.empty() || (cerr != ALC_NO_ERROR))
1003                 {
1004                         m_playing = false;
1005                         unlock();
1006                         pthread_exit(NULL);
1007                 }
1008
1009                 unlock();
1010
1011 #ifdef WIN32
1012                 Sleep(20);
1013 #else
1014                 usleep(20000);
1015 #endif
1016         }
1017 }
1018
1019 /******************************************************************************/
1020 /**************************** IDevice Code ************************************/
1021 /******************************************************************************/
1022
1023 static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened.";
1024
1025 AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
1026 {
1027         // cannot determine how many channels or which format OpenAL uses, but
1028         // it at least is able to play 16 bit stereo audio
1029         specs.format = AUD_FORMAT_S16;
1030
1031 #if 0
1032         if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
1033         {
1034                 ALCchar* devices = const_cast<ALCchar*>(alcGetString(NULL, ALC_DEVICE_SPECIFIER));
1035                 printf("OpenAL devices (standard is: %s):\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
1036
1037                 while(*devices)
1038                 {
1039                         printf("%s\n", devices);
1040                         devices += strlen(devices) + 1;
1041                 }
1042         }
1043 #endif
1044
1045         m_device = alcOpenDevice(NULL);
1046
1047         if(!m_device)
1048                 AUD_THROW(AUD_ERROR_OPENAL, open_error);
1049
1050         // at least try to set the frequency
1051         ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 };
1052         ALCint* attributes = attribs;
1053         if(specs.rate == AUD_RATE_INVALID)
1054                 attributes = NULL;
1055
1056         m_context = alcCreateContext(m_device, attributes);
1057         alcMakeContextCurrent(m_context);
1058
1059         alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
1060
1061         // check for specific formats and channel counts to be played back
1062         if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
1063                 specs.format = AUD_FORMAT_FLOAT32;
1064
1065         m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
1066
1067         if((!m_useMC && specs.channels > AUD_CHANNELS_STEREO) ||
1068                         specs.channels == AUD_CHANNELS_STEREO_LFE ||
1069                         specs.channels == AUD_CHANNELS_SURROUND5)
1070                 specs.channels = AUD_CHANNELS_STEREO;
1071
1072         alGetError();
1073         alcGetError(m_device);
1074
1075         m_specs = specs;
1076         m_buffersize = buffersize;
1077         m_playing = false;
1078
1079 //      m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
1080
1081         pthread_mutexattr_t attr;
1082         pthread_mutexattr_init(&attr);
1083         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1084
1085         pthread_mutex_init(&m_mutex, &attr);
1086
1087         pthread_mutexattr_destroy(&attr);
1088
1089         start(false);
1090 }
1091
1092 AUD_OpenALDevice::~AUD_OpenALDevice()
1093 {
1094         lock();
1095         alcSuspendContext(m_context);
1096
1097         while(!m_playingSounds.empty())
1098                 m_playingSounds.front()->stop();
1099
1100         while(!m_pausedSounds.empty())
1101                 m_pausedSounds.front()->stop();
1102
1103
1104         // delete all buffered factories
1105         /*while(!m_bufferedFactories->empty())
1106         {
1107                 alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
1108                 delete *m_bufferedFactories->begin();
1109                 m_bufferedFactories->erase(m_bufferedFactories->begin());
1110         }*/
1111
1112         alcProcessContext(m_context);
1113
1114         // wait for the thread to stop
1115         unlock();
1116         pthread_join(m_thread, NULL);
1117
1118         //delete m_bufferedFactories;
1119
1120         // quit OpenAL
1121         alcMakeContextCurrent(NULL);
1122         alcDestroyContext(m_context);
1123         alcCloseDevice(m_device);
1124
1125         pthread_mutex_destroy(&m_mutex);
1126 }
1127
1128 AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const
1129 {
1130         return m_specs;
1131 }
1132
1133 bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
1134 {
1135         bool valid = true;
1136         format = 0;
1137
1138         switch(m_specs.format)
1139         {
1140         case AUD_FORMAT_S16:
1141                 switch(specs.channels)
1142                 {
1143                 case AUD_CHANNELS_MONO:
1144                         format = AL_FORMAT_MONO16;
1145                         break;
1146                 case AUD_CHANNELS_STEREO:
1147                         format = AL_FORMAT_STEREO16;
1148                         break;
1149                 case AUD_CHANNELS_SURROUND4:
1150                         if(m_useMC)
1151                         {
1152                                 format = alGetEnumValue("AL_FORMAT_QUAD16");
1153                                 break;
1154                         }
1155                 case AUD_CHANNELS_SURROUND51:
1156                         if(m_useMC)
1157                         {
1158                                 format = alGetEnumValue("AL_FORMAT_51CHN16");
1159                                 break;
1160                         }
1161                 case AUD_CHANNELS_SURROUND61:
1162                         if(m_useMC)
1163                         {
1164                                 format = alGetEnumValue("AL_FORMAT_61CHN16");
1165                                 break;
1166                         }
1167                 case AUD_CHANNELS_SURROUND71:
1168                         if(m_useMC)
1169                         {
1170                                 format = alGetEnumValue("AL_FORMAT_71CHN16");
1171                                 break;
1172                         }
1173                 default:
1174                         valid = false;
1175                 }
1176                 break;
1177         case AUD_FORMAT_FLOAT32:
1178                 switch(specs.channels)
1179                 {
1180                 case AUD_CHANNELS_MONO:
1181                         format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
1182                         break;
1183                 case AUD_CHANNELS_STEREO:
1184                         format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
1185                         break;
1186                 case AUD_CHANNELS_SURROUND4:
1187                         if(m_useMC)
1188                         {
1189                                 format = alGetEnumValue("AL_FORMAT_QUAD32");
1190                                 break;
1191                         }
1192                 case AUD_CHANNELS_SURROUND51:
1193                         if(m_useMC)
1194                         {
1195                                 format = alGetEnumValue("AL_FORMAT_51CHN32");
1196                                 break;
1197                         }
1198                 case AUD_CHANNELS_SURROUND61:
1199                         if(m_useMC)
1200                         {
1201                                 format = alGetEnumValue("AL_FORMAT_61CHN32");
1202                                 break;
1203                         }
1204                 case AUD_CHANNELS_SURROUND71:
1205                         if(m_useMC)
1206                         {
1207                                 format = alGetEnumValue("AL_FORMAT_71CHN32");
1208                                 break;
1209                         }
1210                 default:
1211                         valid = false;
1212                 }
1213                 break;
1214         default:
1215                 valid = false;
1216         }
1217
1218         if(!format)
1219                 valid = false;
1220
1221         return valid;
1222 }
1223
1224 boost::shared_ptr<AUD_IHandle> AUD_OpenALDevice::play(boost::shared_ptr<AUD_IReader> reader, bool keep)
1225 {
1226         AUD_Specs specs = reader->getSpecs();
1227
1228         // check format
1229         if(specs.channels == AUD_CHANNELS_INVALID)
1230                 return boost::shared_ptr<AUD_IHandle>();
1231
1232         if(m_specs.format != AUD_FORMAT_FLOAT32)
1233                 reader = boost::shared_ptr<AUD_IReader>(new AUD_ConverterReader(reader, m_specs));
1234
1235         ALenum format;
1236
1237         if(!getFormat(format, specs))
1238                 return boost::shared_ptr<AUD_IHandle>();
1239
1240         AUD_MutexLock lock(*this);
1241
1242         alcSuspendContext(m_context);
1243
1244         boost::shared_ptr<AUD_OpenALDevice::AUD_OpenALHandle> sound;
1245
1246         try
1247         {
1248                 // create the handle
1249                 sound = boost::shared_ptr<AUD_OpenALDevice::AUD_OpenALHandle>(new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep));
1250         }
1251         catch(AUD_Exception&)
1252         {
1253                 alcProcessContext(m_context);
1254                 throw;
1255         }
1256
1257         alcProcessContext(m_context);
1258
1259         // play sound
1260         m_playingSounds.push_back(sound);
1261
1262         start();
1263
1264         return boost::shared_ptr<AUD_IHandle>(sound);
1265 }
1266
1267 boost::shared_ptr<AUD_IHandle> AUD_OpenALDevice::play(boost::shared_ptr<AUD_IFactory> factory, bool keep)
1268 {
1269         /* AUD_XXX disabled
1270         AUD_OpenALHandle* sound = NULL;
1271
1272         lock();
1273
1274         try
1275         {
1276                 // check if it is a buffered factory
1277                 for(AUD_BFIterator i = m_bufferedFactories->begin();
1278                         i != m_bufferedFactories->end(); i++)
1279                 {
1280                         if((*i)->factory == factory)
1281                         {
1282                                 // create the handle
1283                                 sound = new AUD_OpenALHandle;
1284                                 sound->keep = keep;
1285                                 sound->current = -1;
1286                                 sound->isBuffered = true;
1287                                 sound->eos = true;
1288                                 sound->loopcount = 0;
1289                                 sound->stop = NULL;
1290                                 sound->stop_data = NULL;
1291
1292                                 alcSuspendContext(m_context);
1293
1294                                 // OpenAL playback code
1295                                 try
1296                                 {
1297                                         alGenSources(1, &sound->source);
1298                                         if(alGetError() != AL_NO_ERROR)
1299                                                 AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
1300
1301                                         try
1302                                         {
1303                                                 alSourcei(sound->source, AL_BUFFER, (*i)->buffer);
1304                                                 if(alGetError() != AL_NO_ERROR)
1305                                                         AUD_THROW(AUD_ERROR_OPENAL, queue_error);
1306                                         }
1307                                         catch(AUD_Exception&)
1308                                         {
1309                                                 alDeleteSources(1, &sound->source);
1310                                                 throw;
1311                                         }
1312                                 }
1313                                 catch(AUD_Exception&)
1314                                 {
1315                                         delete sound;
1316                                         alcProcessContext(m_context);
1317                                         throw;
1318                                 }
1319
1320                                 // play sound
1321                                 m_playingSounds->push_back(sound);
1322
1323                                 alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
1324                                 start();
1325
1326                                 alcProcessContext(m_context);
1327                         }
1328                 }
1329         }
1330         catch(AUD_Exception&)
1331         {
1332                 unlock();
1333                 throw;
1334         }
1335
1336         unlock();
1337
1338         if(sound)
1339                 return sound;*/
1340
1341         return play(factory->createReader(), keep);
1342 }
1343
1344 void AUD_OpenALDevice::stopAll()
1345 {
1346         AUD_MutexLock lock(*this);
1347
1348         alcSuspendContext(m_context);
1349
1350         while(!m_playingSounds.empty())
1351                 m_playingSounds.front()->stop();
1352
1353         while(!m_pausedSounds.empty())
1354                 m_pausedSounds.front()->stop();
1355
1356         alcProcessContext(m_context);
1357 }
1358
1359 void AUD_OpenALDevice::lock()
1360 {
1361         pthread_mutex_lock(&m_mutex);
1362 }
1363
1364 void AUD_OpenALDevice::unlock()
1365 {
1366         pthread_mutex_unlock(&m_mutex);
1367 }
1368
1369 float AUD_OpenALDevice::getVolume() const
1370 {
1371         float result;
1372         alGetListenerf(AL_GAIN, &result);
1373         return result;
1374 }
1375
1376 void AUD_OpenALDevice::setVolume(float volume)
1377 {
1378         alListenerf(AL_GAIN, volume);
1379 }
1380
1381 /* AUD_XXX Temorary disabled
1382
1383 bool AUD_OpenALDevice::bufferFactory(void *value)
1384 {
1385         bool result = false;
1386         AUD_IFactory* factory = (AUD_IFactory*) value;
1387
1388         // load the factory into an OpenAL buffer
1389         if(factory)
1390         {
1391                 // check if the factory is already buffered
1392                 lock();
1393                 for(AUD_BFIterator i = m_bufferedFactories->begin();
1394                         i != m_bufferedFactories->end(); i++)
1395                 {
1396                         if((*i)->factory == factory)
1397                         {
1398                                 result = true;
1399                                 break;
1400                         }
1401                 }
1402                 unlock();
1403                 if(result)
1404                         return result;
1405
1406                 AUD_IReader* reader = factory->createReader();
1407
1408                 if(reader == NULL)
1409                         return false;
1410
1411                 AUD_DeviceSpecs specs = m_specs;
1412                 specs.specs = reader->getSpecs();
1413
1414                 if(m_specs.format != AUD_FORMAT_FLOAT32)
1415                         reader = new AUD_ConverterReader(reader, m_specs);
1416
1417                 ALenum format;
1418
1419                 if(!getFormat(format, specs.specs))
1420                 {
1421                         return false;
1422                 }
1423
1424                 // load into a buffer
1425                 lock();
1426                 alcSuspendContext(m_context);
1427
1428                 AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory;
1429                 bf->factory = factory;
1430
1431                 try
1432                 {
1433                         alGenBuffers(1, &bf->buffer);
1434                         if(alGetError() != AL_NO_ERROR)
1435                                 AUD_THROW(AUD_ERROR_OPENAL);
1436
1437                         try
1438                         {
1439                                 sample_t* buf;
1440                                 int length = reader->getLength();
1441
1442                                 reader->read(length, buf);
1443                                 alBufferData(bf->buffer, format, buf,
1444                                                          length * AUD_DEVICE_SAMPLE_SIZE(specs),
1445                                                          specs.rate);
1446                                 if(alGetError() != AL_NO_ERROR)
1447                                         AUD_THROW(AUD_ERROR_OPENAL);
1448                         }
1449                         catch(AUD_Exception&)
1450                         {
1451                                 alDeleteBuffers(1, &bf->buffer);
1452                                 throw;
1453                         }
1454                 }
1455                 catch(AUD_Exception&)
1456                 {
1457                         delete bf;
1458                         alcProcessContext(m_context);
1459                         unlock();
1460                         return false;
1461                 }
1462
1463                 m_bufferedFactories->push_back(bf);
1464
1465                 alcProcessContext(m_context);
1466                 unlock();
1467         }
1468         else
1469         {
1470                 // stop all playing and paused buffered sources
1471                 lock();
1472                 alcSuspendContext(m_context);
1473
1474                 AUD_OpenALHandle* sound;
1475                 AUD_HandleIterator it = m_playingSounds->begin();
1476                 while(it != m_playingSounds->end())
1477                 {
1478                         sound = *it;
1479                         ++it;
1480
1481                         if(sound->isBuffered)
1482                                 stop(sound);
1483                 }
1484                 alcProcessContext(m_context);
1485
1486                 while(!m_bufferedFactories->empty())
1487                 {
1488                         alDeleteBuffers(1,
1489                                                         &(*(m_bufferedFactories->begin()))->buffer);
1490                         delete *m_bufferedFactories->begin();
1491                         m_bufferedFactories->erase(m_bufferedFactories->begin());
1492                 }
1493                 unlock();
1494         }
1495
1496         return true;
1497 }*/
1498
1499 /******************************************************************************/
1500 /**************************** 3D Device Code **********************************/
1501 /******************************************************************************/
1502
1503 AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const
1504 {
1505         ALfloat p[3];
1506         alGetListenerfv(AL_POSITION, p);
1507         return AUD_Vector3(p[0], p[1], p[2]);
1508 }
1509
1510 void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location)
1511 {
1512         alListenerfv(AL_POSITION, (ALfloat*)location.get());
1513 }
1514
1515 AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const
1516 {
1517         ALfloat v[3];
1518         alGetListenerfv(AL_VELOCITY, v);
1519         return AUD_Vector3(v[0], v[1], v[2]);
1520 }
1521
1522 void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity)
1523 {
1524         alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get());
1525 }
1526
1527 AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const
1528 {
1529         return m_orientation;
1530 }
1531
1532 void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation)
1533 {
1534         ALfloat direction[6];
1535         direction[0] = -2 * (orientation.w() * orientation.y() +
1536                                                  orientation.x() * orientation.z());
1537         direction[1] = 2 * (orientation.x() * orientation.w() -
1538                                                 orientation.z() * orientation.y());
1539         direction[2] = 2 * (orientation.x() * orientation.x() +
1540                                                 orientation.y() * orientation.y()) - 1;
1541         direction[3] = 2 * (orientation.x() * orientation.y() -
1542                                                 orientation.w() * orientation.z());
1543         direction[4] = 1 - 2 * (orientation.x() * orientation.x() +
1544                                                         orientation.z() * orientation.z());
1545         direction[5] = 2 * (orientation.w() * orientation.x() +
1546                                                 orientation.y() * orientation.z());
1547         alListenerfv(AL_ORIENTATION, direction);
1548         m_orientation = orientation;
1549 }
1550
1551 float AUD_OpenALDevice::getSpeedOfSound() const
1552 {
1553         return alGetFloat(AL_SPEED_OF_SOUND);
1554 }
1555
1556 void AUD_OpenALDevice::setSpeedOfSound(float speed)
1557 {
1558         alSpeedOfSound(speed);
1559 }
1560
1561 float AUD_OpenALDevice::getDopplerFactor() const
1562 {
1563         return alGetFloat(AL_DOPPLER_FACTOR);
1564 }
1565
1566 void AUD_OpenALDevice::setDopplerFactor(float factor)
1567 {
1568         alDopplerFactor(factor);
1569 }
1570
1571 AUD_DistanceModel AUD_OpenALDevice::getDistanceModel() const
1572 {
1573         switch(alGetInteger(AL_DISTANCE_MODEL))
1574         {
1575         case AL_INVERSE_DISTANCE:
1576                 return AUD_DISTANCE_MODEL_INVERSE;
1577         case AL_INVERSE_DISTANCE_CLAMPED:
1578                 return AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
1579         case AL_LINEAR_DISTANCE:
1580                 return AUD_DISTANCE_MODEL_LINEAR;
1581         case AL_LINEAR_DISTANCE_CLAMPED:
1582                 return AUD_DISTANCE_MODEL_LINEAR_CLAMPED;
1583         case AL_EXPONENT_DISTANCE:
1584                 return AUD_DISTANCE_MODEL_EXPONENT;
1585         case AL_EXPONENT_DISTANCE_CLAMPED:
1586                 return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED;
1587         default:
1588                 return AUD_DISTANCE_MODEL_INVALID;
1589         }
1590 }
1591
1592 void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model)
1593 {
1594         switch(model)
1595         {
1596         case AUD_DISTANCE_MODEL_INVERSE:
1597                 alDistanceModel(AL_INVERSE_DISTANCE);
1598                 break;
1599         case AUD_DISTANCE_MODEL_INVERSE_CLAMPED:
1600                 alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
1601                 break;
1602         case AUD_DISTANCE_MODEL_LINEAR:
1603                 alDistanceModel(AL_LINEAR_DISTANCE);
1604                 break;
1605         case AUD_DISTANCE_MODEL_LINEAR_CLAMPED:
1606                 alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
1607                 break;
1608         case AUD_DISTANCE_MODEL_EXPONENT:
1609                 alDistanceModel(AL_EXPONENT_DISTANCE);
1610                 break;
1611         case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED:
1612                 alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
1613                 break;
1614         default:
1615                 alDistanceModel(AL_NONE);
1616         }
1617 }