4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * Copyright 2009-2011 Jörg Hermann Müller
8 * This file is part of AudaSpace.
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.
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.
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.
24 * ***** END GPL LICENSE BLOCK *****
27 /** \file audaspace/OpenAL/AUD_OpenALDevice.cpp
32 #include "AUD_OpenALDevice.h"
33 #include "AUD_IFactory.h"
34 #include "AUD_IReader.h"
35 #include "AUD_ConverterReader.h"
46 #define AUD_OPENAL_CYCLE_BUFFERS 3
48 /// Saves the data for playback.
49 struct AUD_OpenALHandle : AUD_Handle
51 /// Whether it's a buffered or a streamed source.
54 /// The reader source.
57 /// Whether to keep the source if end of it is reached.
60 /// OpenAL sample format.
67 ALuint buffers[AUD_OPENAL_CYCLE_BUFFERS];
69 /// The first buffer to be read next.
72 /// Whether the stream doesn't return any more data.
75 /// The loop count of the source.
78 /// The stop callback.
81 /// Stop callback data.
85 struct AUD_OpenALBufferedFactory
88 AUD_IFactory* factory;
90 /// The OpenAL buffer.
94 typedef std::list<AUD_OpenALHandle*>::iterator AUD_HandleIterator;
95 typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
97 /******************************************************************************/
98 /**************************** Threading Code **********************************/
99 /******************************************************************************/
101 void* AUD_openalRunThread(void* device)
103 AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device;
104 dev->updateStreams();
108 void AUD_OpenALDevice::start(bool join)
115 pthread_join(m_thread, NULL);
118 pthread_attr_init(&attr);
119 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
121 pthread_create(&m_thread, &attr, AUD_openalRunThread, this);
123 pthread_attr_destroy(&attr);
131 void AUD_OpenALDevice::updateStreams()
133 AUD_OpenALHandle* sound;
139 AUD_DeviceSpecs specs = m_specs;
141 std::list<AUD_OpenALHandle*> stopSounds;
142 std::list<AUD_OpenALHandle*> pauseSounds;
143 AUD_HandleIterator it;
149 alcSuspendContext(m_context);
150 cerr = alcGetError(m_device);
151 if(cerr == ALC_NO_ERROR)
154 for(it = m_playingSounds->begin(); it != m_playingSounds->end(); it++)
158 // is it a streamed sound?
159 if(!sound->isBuffered)
161 // check for buffer refilling
162 alGetSourcei(sound->source, AL_BUFFERS_PROCESSED, &info);
166 specs.specs = sound->reader->getSpecs();
168 // for all empty buffers
171 // if there's still data to play back
175 length = m_buffersize;
176 sound->reader->read(length, buffer);
178 // looping necessary?
179 if(length == 0 && sound->loopcount)
181 if(sound->loopcount > 0)
184 sound->reader->seek(0);
186 length = m_buffersize;
187 sound->reader->read(length, buffer);
193 sound->data_end = true;
198 alSourceUnqueueBuffers(sound->source, 1,
199 &sound->buffers[sound->current]);
201 if((err = alGetError()) != AL_NO_ERROR)
203 sound->data_end = true;
207 // fill with new data
208 alBufferData(sound->buffers[sound->current],
211 AUD_DEVICE_SAMPLE_SIZE(specs),
214 if((err = alGetError()) != AL_NO_ERROR)
216 sound->data_end = true;
221 alSourceQueueBuffers(sound->source, 1,
222 &sound->buffers[sound->current]);
223 if(alGetError() != AL_NO_ERROR)
225 sound->data_end = true;
229 sound->current = (sound->current+1) %
230 AUD_OPENAL_CYCLE_BUFFERS;
238 // check if the sound has been stopped
239 alGetSourcei(sound->source, AL_SOURCE_STATE, &info);
241 if(info != AL_PLAYING)
243 // if it really stopped
247 sound->stop(sound->stop_data);
251 pauseSounds.push_back(sound);
254 stopSounds.push_back(sound);
258 alSourcePlay(sound->source);
262 for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
265 for(it = stopSounds.begin(); it != stopSounds.end(); it++)
271 alcProcessContext(m_context);
275 if(m_playingSounds->empty() || (cerr != ALC_NO_ERROR))
292 /******************************************************************************/
293 /**************************** IDevice Code ************************************/
294 /******************************************************************************/
296 bool AUD_OpenALDevice::isValid(AUD_Handle* handle)
298 for(AUD_HandleIterator i = m_playingSounds->begin();
299 i != m_playingSounds->end(); i++)
302 for(AUD_HandleIterator i = m_pausedSounds->begin();
303 i != m_pausedSounds->end(); i++)
309 static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened.";
311 AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
313 // cannot determine how many channels or which format OpenAL uses, but
314 // it at least is able to play 16 bit stereo audio
315 specs.channels = AUD_CHANNELS_STEREO;
316 specs.format = AUD_FORMAT_S16;
319 if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
321 ALCchar* devices = const_cast<ALCchar*>(alcGetString(NULL, ALC_DEVICE_SPECIFIER));
322 printf("OpenAL devices (standard is: %s):\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
326 printf("%s\n", devices);
327 devices += strlen(devices) + 1;
332 m_device = alcOpenDevice(NULL);
335 AUD_THROW(AUD_ERROR_OPENAL, open_error);
337 // at least try to set the frequency
338 ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 };
339 ALCint* attributes = attribs;
340 if(specs.rate == AUD_RATE_INVALID)
343 m_context = alcCreateContext(m_device, attributes);
344 alcMakeContextCurrent(m_context);
346 alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
348 // check for specific formats and channel counts to be played back
349 if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
350 specs.format = AUD_FORMAT_FLOAT32;
352 m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
355 alcGetError(m_device);
358 m_buffersize = buffersize;
361 m_playingSounds = new std::list<AUD_OpenALHandle*>();
362 m_pausedSounds = new std::list<AUD_OpenALHandle*>();
363 m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
365 pthread_mutexattr_t attr;
366 pthread_mutexattr_init(&attr);
367 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
369 pthread_mutex_init(&m_mutex, &attr);
371 pthread_mutexattr_destroy(&attr);
376 AUD_OpenALDevice::~AUD_OpenALDevice()
378 AUD_OpenALHandle* sound;
381 alcSuspendContext(m_context);
383 // delete all playing sounds
384 while(!m_playingSounds->empty())
386 sound = *(m_playingSounds->begin());
387 alDeleteSources(1, &sound->source);
388 if(!sound->isBuffered)
390 delete sound->reader;
391 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
394 m_playingSounds->erase(m_playingSounds->begin());
397 // delete all paused sounds
398 while(!m_pausedSounds->empty())
400 sound = *(m_pausedSounds->begin());
401 alDeleteSources(1, &sound->source);
402 if(!sound->isBuffered)
404 delete sound->reader;
405 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
408 m_pausedSounds->erase(m_pausedSounds->begin());
411 // delete all buffered factories
412 while(!m_bufferedFactories->empty())
414 alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
415 delete *m_bufferedFactories->begin();
416 m_bufferedFactories->erase(m_bufferedFactories->begin());
419 alcProcessContext(m_context);
421 // wait for the thread to stop
423 pthread_join(m_thread, NULL);
425 delete m_playingSounds;
426 delete m_pausedSounds;
427 delete m_bufferedFactories;
430 alcMakeContextCurrent(NULL);
431 alcDestroyContext(m_context);
432 alcCloseDevice(m_device);
434 pthread_mutex_destroy(&m_mutex);
437 AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const
442 bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
447 switch(m_specs.format)
450 switch(specs.channels)
452 case AUD_CHANNELS_MONO:
453 format = AL_FORMAT_MONO16;
455 case AUD_CHANNELS_STEREO:
456 format = AL_FORMAT_STEREO16;
458 case AUD_CHANNELS_SURROUND4:
461 format = alGetEnumValue("AL_FORMAT_QUAD16");
464 case AUD_CHANNELS_SURROUND51:
467 format = alGetEnumValue("AL_FORMAT_51CHN16");
470 case AUD_CHANNELS_SURROUND61:
473 format = alGetEnumValue("AL_FORMAT_61CHN16");
476 case AUD_CHANNELS_SURROUND71:
479 format = alGetEnumValue("AL_FORMAT_71CHN16");
486 case AUD_FORMAT_FLOAT32:
487 switch(specs.channels)
489 case AUD_CHANNELS_MONO:
490 format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
492 case AUD_CHANNELS_STEREO:
493 format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
495 case AUD_CHANNELS_SURROUND4:
498 format = alGetEnumValue("AL_FORMAT_QUAD32");
501 case AUD_CHANNELS_SURROUND51:
504 format = alGetEnumValue("AL_FORMAT_51CHN32");
507 case AUD_CHANNELS_SURROUND61:
510 format = alGetEnumValue("AL_FORMAT_61CHN32");
513 case AUD_CHANNELS_SURROUND71:
516 format = alGetEnumValue("AL_FORMAT_71CHN32");
533 static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be "
535 static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be "
537 static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
538 "queued to the source.";
539 static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
542 AUD_Handle* AUD_OpenALDevice::play(AUD_IReader* reader, bool keep)
544 AUD_OpenALHandle* sound = NULL;
546 AUD_DeviceSpecs specs = m_specs;
547 specs.specs = reader->getSpecs();
550 bool valid = specs.channels != AUD_CHANNELS_INVALID;
552 if(m_specs.format != AUD_FORMAT_FLOAT32)
553 reader = new AUD_ConverterReader(reader, m_specs);
556 sound = new AUD_OpenALHandle;
558 sound->reader = reader;
560 sound->isBuffered = false;
561 sound->data_end = false;
562 sound->loopcount = 0;
564 sound->stop_data = NULL;
566 valid &= getFormat(sound->format, specs.specs);
576 alcSuspendContext(m_context);
578 // OpenAL playback code
581 alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
582 if(alGetError() != AL_NO_ERROR)
583 AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
590 for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++)
592 length = m_buffersize;
593 reader->read(length, buf);
594 alBufferData(sound->buffers[i], sound->format, buf,
595 length * AUD_DEVICE_SAMPLE_SIZE(specs),
597 if(alGetError() != AL_NO_ERROR)
598 AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
601 alGenSources(1, &sound->source);
602 if(alGetError() != AL_NO_ERROR)
603 AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
607 alSourceQueueBuffers(sound->source, AUD_OPENAL_CYCLE_BUFFERS,
609 if(alGetError() != AL_NO_ERROR)
610 AUD_THROW(AUD_ERROR_OPENAL, queue_error);
612 catch(AUD_Exception&)
614 alDeleteSources(1, &sound->source);
618 catch(AUD_Exception&)
620 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
624 catch(AUD_Exception&)
628 alcProcessContext(m_context);
634 m_playingSounds->push_back(sound);
635 alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
639 alcProcessContext(m_context);
645 AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
647 AUD_OpenALHandle* sound = NULL;
653 // check if it is a buffered factory
654 for(AUD_BFIterator i = m_bufferedFactories->begin();
655 i != m_bufferedFactories->end(); i++)
657 if((*i)->factory == factory)
660 sound = new AUD_OpenALHandle;
663 sound->isBuffered = true;
664 sound->data_end = true;
665 sound->loopcount = 0;
667 sound->stop_data = NULL;
669 alcSuspendContext(m_context);
671 // OpenAL playback code
674 alGenSources(1, &sound->source);
675 if(alGetError() != AL_NO_ERROR)
676 AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
680 alSourcei(sound->source, AL_BUFFER, (*i)->buffer);
681 if(alGetError() != AL_NO_ERROR)
682 AUD_THROW(AUD_ERROR_OPENAL, queue_error);
684 catch(AUD_Exception&)
686 alDeleteSources(1, &sound->source);
690 catch(AUD_Exception&)
693 alcProcessContext(m_context);
698 m_playingSounds->push_back(sound);
700 alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
703 alcProcessContext(m_context);
707 catch(AUD_Exception&)
718 return play(factory->createReader(), keep);
721 bool AUD_OpenALDevice::pause(AUD_Handle* handle)
727 // only songs that are played can be paused
728 for(AUD_HandleIterator i = m_playingSounds->begin();
729 i != m_playingSounds->end(); i++)
733 m_pausedSounds->push_back(*i);
734 alSourcePause((*i)->source);
735 m_playingSounds->erase(i);
746 bool AUD_OpenALDevice::resume(AUD_Handle* handle)
752 // only songs that are paused can be resumed
753 for(AUD_HandleIterator i = m_pausedSounds->begin();
754 i != m_pausedSounds->end(); i++)
758 m_playingSounds->push_back(*i);
760 m_pausedSounds->erase(i);
771 bool AUD_OpenALDevice::stop(AUD_Handle* handle)
773 AUD_OpenALHandle* sound;
779 for(AUD_HandleIterator i = m_playingSounds->begin();
780 i != m_playingSounds->end(); i++)
785 alDeleteSources(1, &sound->source);
786 if(!sound->isBuffered)
788 delete sound->reader;
789 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
792 m_playingSounds->erase(i);
799 for(AUD_HandleIterator i = m_pausedSounds->begin();
800 i != m_pausedSounds->end(); i++)
805 alDeleteSources(1, &sound->source);
806 if(!sound->isBuffered)
808 delete sound->reader;
809 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
812 m_pausedSounds->erase(i);
824 bool AUD_OpenALDevice::getKeep(AUD_Handle* handle)
831 result = ((AUD_OpenALHandle*)handle)->keep;
838 bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep)
846 ((AUD_OpenALHandle*)handle)->keep = keep;
855 bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position)
863 AUD_OpenALHandle* alhandle = (AUD_OpenALHandle*)handle;
864 if(alhandle->isBuffered)
865 alSourcef(alhandle->source, AL_SEC_OFFSET, position);
868 alhandle->reader->seek((int)(position *
869 alhandle->reader->getSpecs().rate));
870 alhandle->data_end = false;
874 alGetSourcei(alhandle->source, AL_SOURCE_STATE, &info);
876 if(info != AL_PLAYING)
878 if(info == AL_PAUSED)
879 alSourceStop(alhandle->source);
881 alSourcei(alhandle->source, AL_BUFFER, 0);
882 alhandle->current = 0;
885 if((err = alGetError()) == AL_NO_ERROR)
889 AUD_DeviceSpecs specs = m_specs;
890 specs.specs = alhandle->reader->getSpecs();
892 for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++)
894 length = m_buffersize;
895 alhandle->reader->read(length, buf);
896 alBufferData(alhandle->buffers[i], alhandle->format,
898 length * AUD_DEVICE_SAMPLE_SIZE(specs),
901 if(alGetError() != AL_NO_ERROR)
905 alSourceQueueBuffers(alhandle->source,
906 AUD_OPENAL_CYCLE_BUFFERS,
910 alSourceRewind(alhandle->source);
920 float AUD_OpenALDevice::getPosition(AUD_Handle* handle)
922 float position = 0.0f;
928 AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
929 alGetSourcef(h->source, AL_SEC_OFFSET, &position);
932 AUD_Specs specs = h->reader->getSpecs();
933 position += (h->reader->getPosition() - m_buffersize *
934 AUD_OPENAL_CYCLE_BUFFERS) /
943 AUD_Status AUD_OpenALDevice::getStatus(AUD_Handle* handle)
945 AUD_Status status = AUD_STATUS_INVALID;
949 for(AUD_HandleIterator i = m_playingSounds->begin();
950 i != m_playingSounds->end(); i++)
954 status = AUD_STATUS_PLAYING;
958 if(status == AUD_STATUS_INVALID)
960 for(AUD_HandleIterator i = m_pausedSounds->begin();
961 i != m_pausedSounds->end(); i++)
965 status = AUD_STATUS_PAUSED;
976 void AUD_OpenALDevice::lock()
978 pthread_mutex_lock(&m_mutex);
981 void AUD_OpenALDevice::unlock()
983 pthread_mutex_unlock(&m_mutex);
986 float AUD_OpenALDevice::getVolume() const
989 alGetListenerf(AL_GAIN, &result);
993 void AUD_OpenALDevice::setVolume(float volume)
995 alListenerf(AL_GAIN, volume);
998 float AUD_OpenALDevice::getVolume(AUD_Handle* handle)
1001 float result = std::numeric_limits<float>::quiet_NaN();
1003 alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_GAIN, &result);
1008 bool AUD_OpenALDevice::setVolume(AUD_Handle* handle, float volume)
1011 bool result = isValid(handle);
1013 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_GAIN, volume);
1018 float AUD_OpenALDevice::getPitch(AUD_Handle* handle)
1021 float result = std::numeric_limits<float>::quiet_NaN();
1023 alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_PITCH, &result);
1028 bool AUD_OpenALDevice::setPitch(AUD_Handle* handle, float pitch)
1031 bool result = isValid(handle);
1033 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_PITCH, pitch);
1038 int AUD_OpenALDevice::getLoopCount(AUD_Handle* handle)
1043 result = ((AUD_OpenALHandle*)handle)->loopcount;
1048 bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count)
1051 bool result = isValid(handle);
1053 ((AUD_OpenALHandle*)handle)->loopcount = count;
1058 bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
1061 bool result = isValid(handle);
1064 AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
1066 h->stop_data = data;
1072 /* AUD_XXX Temorary disabled
1074 bool AUD_OpenALDevice::bufferFactory(void *value)
1076 bool result = false;
1077 AUD_IFactory* factory = (AUD_IFactory*) value;
1079 // load the factory into an OpenAL buffer
1082 // check if the factory is already buffered
1084 for(AUD_BFIterator i = m_bufferedFactories->begin();
1085 i != m_bufferedFactories->end(); i++)
1087 if((*i)->factory == factory)
1097 AUD_IReader* reader = factory->createReader();
1102 AUD_DeviceSpecs specs = m_specs;
1103 specs.specs = reader->getSpecs();
1105 if(m_specs.format != AUD_FORMAT_FLOAT32)
1106 reader = new AUD_ConverterReader(reader, m_specs);
1110 if(!getFormat(format, specs.specs))
1116 // load into a buffer
1118 alcSuspendContext(m_context);
1120 AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory;
1121 bf->factory = factory;
1125 alGenBuffers(1, &bf->buffer);
1126 if(alGetError() != AL_NO_ERROR)
1127 AUD_THROW(AUD_ERROR_OPENAL);
1132 int length = reader->getLength();
1134 reader->read(length, buf);
1135 alBufferData(bf->buffer, format, buf,
1136 length * AUD_DEVICE_SAMPLE_SIZE(specs),
1138 if(alGetError() != AL_NO_ERROR)
1139 AUD_THROW(AUD_ERROR_OPENAL);
1141 catch(AUD_Exception&)
1143 alDeleteBuffers(1, &bf->buffer);
1147 catch(AUD_Exception&)
1151 alcProcessContext(m_context);
1156 m_bufferedFactories->push_back(bf);
1158 alcProcessContext(m_context);
1163 // stop all playing and paused buffered sources
1165 alcSuspendContext(m_context);
1167 AUD_OpenALHandle* sound;
1168 AUD_HandleIterator it = m_playingSounds->begin();
1169 while(it != m_playingSounds->end())
1174 if(sound->isBuffered)
1177 alcProcessContext(m_context);
1179 while(!m_bufferedFactories->empty())
1182 &(*(m_bufferedFactories->begin()))->buffer);
1183 delete *m_bufferedFactories->begin();
1184 m_bufferedFactories->erase(m_bufferedFactories->begin());
1192 /******************************************************************************/
1193 /**************************** 3D Device Code **********************************/
1194 /******************************************************************************/
1196 AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const
1199 alGetListenerfv(AL_POSITION, p);
1200 return AUD_Vector3(p[0], p[1], p[2]);
1203 void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location)
1205 alListenerfv(AL_POSITION, (ALfloat*)location.get());
1208 AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const
1211 alGetListenerfv(AL_VELOCITY, v);
1212 return AUD_Vector3(v[0], v[1], v[2]);
1215 void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity)
1217 alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get());
1220 AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const
1222 // AUD_XXX not implemented yet
1223 return AUD_Quaternion(0, 0, 0, 0);
1226 void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation)
1228 ALfloat direction[6];
1229 direction[0] = -2 * (orientation.w() * orientation.y() +
1230 orientation.x() * orientation.z());
1231 direction[1] = 2 * (orientation.x() * orientation.w() -
1232 orientation.z() * orientation.y());
1233 direction[2] = 2 * (orientation.x() * orientation.x() +
1234 orientation.y() * orientation.y()) - 1;
1235 direction[3] = 2 * (orientation.x() * orientation.y() -
1236 orientation.w() * orientation.z());
1237 direction[4] = 1 - 2 * (orientation.x() * orientation.x() +
1238 orientation.z() * orientation.z());
1239 direction[5] = 2 * (orientation.w() * orientation.x() +
1240 orientation.y() * orientation.z());
1241 alListenerfv(AL_ORIENTATION, direction);
1244 float AUD_OpenALDevice::getSpeedOfSound() const
1246 return alGetFloat(AL_SPEED_OF_SOUND);
1249 void AUD_OpenALDevice::setSpeedOfSound(float speed)
1251 alSpeedOfSound(speed);
1254 float AUD_OpenALDevice::getDopplerFactor() const
1256 return alGetFloat(AL_DOPPLER_FACTOR);
1259 void AUD_OpenALDevice::setDopplerFactor(float factor)
1261 alDopplerFactor(factor);
1264 AUD_DistanceModel AUD_OpenALDevice::getDistanceModel() const
1266 switch(alGetInteger(AL_DISTANCE_MODEL))
1268 case AL_INVERSE_DISTANCE:
1269 return AUD_DISTANCE_MODEL_INVERSE;
1270 case AL_INVERSE_DISTANCE_CLAMPED:
1271 return AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
1272 case AL_LINEAR_DISTANCE:
1273 return AUD_DISTANCE_MODEL_LINEAR;
1274 case AL_LINEAR_DISTANCE_CLAMPED:
1275 return AUD_DISTANCE_MODEL_LINEAR_CLAMPED;
1276 case AL_EXPONENT_DISTANCE:
1277 return AUD_DISTANCE_MODEL_EXPONENT;
1278 case AL_EXPONENT_DISTANCE_CLAMPED:
1279 return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED;
1281 return AUD_DISTANCE_MODEL_INVALID;
1285 void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model)
1289 case AUD_DISTANCE_MODEL_INVERSE:
1290 alDistanceModel(AL_INVERSE_DISTANCE);
1292 case AUD_DISTANCE_MODEL_INVERSE_CLAMPED:
1293 alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
1295 case AUD_DISTANCE_MODEL_LINEAR:
1296 alDistanceModel(AL_LINEAR_DISTANCE);
1298 case AUD_DISTANCE_MODEL_LINEAR_CLAMPED:
1299 alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
1301 case AUD_DISTANCE_MODEL_EXPONENT:
1302 alDistanceModel(AL_EXPONENT_DISTANCE);
1304 case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED:
1305 alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
1308 alDistanceModel(AL_NONE);
1312 AUD_Vector3 AUD_OpenALDevice::getSourceLocation(AUD_Handle* handle)
1314 AUD_Vector3 result = AUD_Vector3(0, 0, 0);
1320 alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, p);
1321 result = AUD_Vector3(p[0], p[1], p[2]);
1328 bool AUD_OpenALDevice::setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location)
1331 bool result = isValid(handle);
1334 alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION,
1335 (ALfloat*)location.get());
1341 AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* handle)
1343 AUD_Vector3 result = AUD_Vector3(0, 0, 0);
1349 alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, v);
1350 result = AUD_Vector3(v[0], v[1], v[2]);
1357 bool AUD_OpenALDevice::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity)
1360 bool result = isValid(handle);
1363 alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY,
1364 (ALfloat*)velocity.get());
1370 AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle)
1372 // AUD_XXX not implemented yet
1373 return AUD_Quaternion(0, 0, 0, 0);
1376 bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation)
1379 bool result = isValid(handle);
1383 ALfloat direction[3];
1384 direction[0] = -2 * (orientation.w() * orientation.y() +
1385 orientation.x() * orientation.z());
1386 direction[1] = 2 * (orientation.x() * orientation.w() -
1387 orientation.z() * orientation.y());
1388 direction[2] = 2 * (orientation.x() * orientation.x() +
1389 orientation.y() * orientation.y()) - 1;
1390 alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_DIRECTION,
1398 bool AUD_OpenALDevice::isRelative(AUD_Handle* handle)
1400 int result = std::numeric_limits<float>::quiet_NaN();;
1405 alGetSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE,
1412 bool AUD_OpenALDevice::setRelative(AUD_Handle* handle, bool relative)
1415 bool result = isValid(handle);
1418 alSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE,
1425 float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle)
1427 float result = std::numeric_limits<float>::quiet_NaN();;
1432 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN,
1439 bool AUD_OpenALDevice::setVolumeMaximum(AUD_Handle* handle, float volume)
1442 bool result = isValid(handle);
1446 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN,
1453 float AUD_OpenALDevice::getVolumeMinimum(AUD_Handle* handle)
1455 float result = std::numeric_limits<float>::quiet_NaN();;
1460 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN,
1467 bool AUD_OpenALDevice::setVolumeMinimum(AUD_Handle* handle, float volume)
1470 bool result = isValid(handle);
1473 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN,
1480 float AUD_OpenALDevice::getDistanceMaximum(AUD_Handle* handle)
1482 float result = std::numeric_limits<float>::quiet_NaN();;
1487 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE,
1494 bool AUD_OpenALDevice::setDistanceMaximum(AUD_Handle* handle, float distance)
1497 bool result = isValid(handle);
1500 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE,
1507 float AUD_OpenALDevice::getDistanceReference(AUD_Handle* handle)
1509 float result = std::numeric_limits<float>::quiet_NaN();;
1514 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE,
1521 bool AUD_OpenALDevice::setDistanceReference(AUD_Handle* handle, float distance)
1524 bool result = isValid(handle);
1527 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE,
1534 float AUD_OpenALDevice::getAttenuation(AUD_Handle* handle)
1536 float result = std::numeric_limits<float>::quiet_NaN();;
1541 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR,
1548 bool AUD_OpenALDevice::setAttenuation(AUD_Handle* handle, float factor)
1551 bool result = isValid(handle);
1554 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR,
1561 float AUD_OpenALDevice::getConeAngleOuter(AUD_Handle* handle)
1563 float result = std::numeric_limits<float>::quiet_NaN();;
1568 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE,
1575 bool AUD_OpenALDevice::setConeAngleOuter(AUD_Handle* handle, float angle)
1578 bool result = isValid(handle);
1581 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE,
1588 float AUD_OpenALDevice::getConeAngleInner(AUD_Handle* handle)
1590 float result = std::numeric_limits<float>::quiet_NaN();;
1595 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE,
1602 bool AUD_OpenALDevice::setConeAngleInner(AUD_Handle* handle, float angle)
1605 bool result = isValid(handle);
1608 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE,
1615 float AUD_OpenALDevice::getConeVolumeOuter(AUD_Handle* handle)
1617 float result = std::numeric_limits<float>::quiet_NaN();;
1622 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN,
1629 bool AUD_OpenALDevice::setConeVolumeOuter(AUD_Handle* handle, float volume)
1632 bool result = isValid(handle);
1635 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN,