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