2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * Copyright 2009-2011 Jörg Hermann Müller
6 * This file is part of AudaSpace.
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.
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.
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.
22 * ***** END GPL LICENSE BLOCK *****
25 /** \file audaspace/OpenAL/AUD_OpenALDevice.cpp
30 #include "AUD_OpenALDevice.h"
31 #include "AUD_IFactory.h"
32 #include "AUD_IReader.h"
33 #include "AUD_ConverterReader.h"
44 /*struct AUD_OpenALBufferedFactory
47 AUD_IFactory* factory;
49 /// The OpenAL buffer.
53 //typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
56 /******************************************************************************/
57 /*********************** AUD_OpenALHandle Handle Code *************************/
58 /******************************************************************************/
60 static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be "
62 static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be "
64 static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
65 "queued to the source.";
66 static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
69 AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep) :
70 m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0),
71 m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING),
74 AUD_DeviceSpecs specs = m_device->m_specs;
75 specs.specs = m_reader->getSpecs();
77 // OpenAL playback code
78 alGenBuffers(CYCLE_BUFFERS, m_buffers);
79 if(alGetError() != AL_NO_ERROR)
80 AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
84 m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
88 for(int i = 0; i < CYCLE_BUFFERS; i++)
90 length = m_device->m_buffersize;
91 reader->read(length, eos, m_device->m_buffer.getBuffer());
92 alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
93 length * AUD_DEVICE_SAMPLE_SIZE(specs),
95 if(alGetError() != AL_NO_ERROR)
96 AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
99 alGenSources(1, &m_source);
100 if(alGetError() != AL_NO_ERROR)
101 AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
105 alSourceQueueBuffers(m_source, CYCLE_BUFFERS,
107 if(alGetError() != AL_NO_ERROR)
108 AUD_THROW(AUD_ERROR_OPENAL, queue_error);
110 catch(AUD_Exception&)
112 alDeleteSources(1, &m_source);
116 catch(AUD_Exception&)
118 alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
121 alSourcei(m_source, AL_SOURCE_RELATIVE, 1);
124 bool AUD_OpenALDevice::AUD_OpenALHandle::pause()
130 if(m_status == AUD_STATUS_PLAYING)
132 m_device->m_playingSounds.remove(this);
133 m_device->m_pausedSounds.push_back(this);
135 alSourcePause(m_source);
137 m_status = AUD_STATUS_PAUSED;
149 bool AUD_OpenALDevice::AUD_OpenALHandle::resume()
155 if(m_status == AUD_STATUS_PAUSED)
157 m_device->m_pausedSounds.remove(this);
158 m_device->m_playingSounds.push_back(this);
161 m_status = AUD_STATUS_PLAYING;
172 bool AUD_OpenALDevice::AUD_OpenALHandle::stop()
179 // AUD_XXX Create a reference of our own object so that it doesn't get
180 // deleted before the end of this function
181 AUD_Reference<AUD_OpenALHandle> This = this;
183 if(m_status == AUD_STATUS_PLAYING)
184 m_device->m_playingSounds.remove(This);
186 m_device->m_pausedSounds.remove(This);
190 alDeleteSources(1, &m_source);
192 alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
194 m_status = AUD_STATUS_INVALID;
198 bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep()
206 bool AUD_OpenALDevice::AUD_OpenALHandle::setKeep(bool keep)
220 bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position)
228 alSourcef(m_source, AL_SEC_OFFSET, position);
231 m_reader->seek((int)(position * m_reader->getSpecs().rate));
236 alGetSourcei(m_source, AL_SOURCE_STATE, &info);
238 if(info != AL_PLAYING)
240 if(info == AL_PAUSED)
241 alSourceStop(m_source);
243 alSourcei(m_source, AL_BUFFER, 0);
247 if((err = alGetError()) == AL_NO_ERROR)
250 AUD_DeviceSpecs specs = m_device->m_specs;
251 specs.specs = m_reader->getSpecs();
252 m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
254 for(int i = 0; i < CYCLE_BUFFERS; i++)
256 length = m_device->m_buffersize;
257 m_reader->read(length, m_eos, m_device->m_buffer.getBuffer());
258 alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
259 length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate);
261 if(alGetError() != AL_NO_ERROR)
268 alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers);
271 alSourceRewind(m_source);
280 float AUD_OpenALDevice::AUD_OpenALHandle::getPosition()
287 float position = 0.0f;
289 alGetSourcef(m_source, AL_SEC_OFFSET, &position);
293 AUD_Specs specs = m_reader->getSpecs();
294 position += (m_reader->getPosition() - m_device->m_buffersize *
295 CYCLE_BUFFERS) / (float)specs.rate;
303 AUD_Status AUD_OpenALDevice::AUD_OpenALHandle::getStatus()
308 float AUD_OpenALDevice::AUD_OpenALHandle::getVolume()
310 float result = std::numeric_limits<float>::quiet_NaN();
317 alGetSourcef(m_source, AL_GAIN, &result);
324 bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume)
331 alSourcef(m_source, AL_GAIN, volume);
338 float AUD_OpenALDevice::AUD_OpenALHandle::getPitch()
340 float result = std::numeric_limits<float>::quiet_NaN();
347 alGetSourcef(m_source, AL_PITCH, &result);
354 bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch)
361 alSourcef(m_source, AL_PITCH, pitch);
368 int AUD_OpenALDevice::AUD_OpenALHandle::getLoopCount()
375 bool AUD_OpenALDevice::AUD_OpenALHandle::setLoopCount(int count)
383 bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, void* data)
398 /******************************************************************************/
399 /********************* AUD_OpenALHandle 3DHandle Code *************************/
400 /******************************************************************************/
402 AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceLocation()
404 AUD_Vector3 result = AUD_Vector3(0, 0, 0);
412 alGetSourcefv(m_source, AL_POSITION, p);
416 result = AUD_Vector3(p[0], p[1], p[2]);
421 bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceLocation(const AUD_Vector3& location)
428 alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get());
435 AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity()
437 AUD_Vector3 result = AUD_Vector3(0, 0, 0);
445 alGetSourcefv(m_source, AL_VELOCITY, v);
449 result = AUD_Vector3(v[0], v[1], v[2]);
454 bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceVelocity(const AUD_Vector3& velocity)
461 alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get());
468 AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation()
470 return m_orientation;
473 bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation)
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;
487 alSourcefv(m_source, AL_DIRECTION, direction);
491 m_orientation = orientation;
496 bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative()
505 alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result);
512 bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative)
519 alSourcei(m_source, AL_SOURCE_RELATIVE, relative);
526 float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum()
528 float result = std::numeric_limits<float>::quiet_NaN();
535 alGetSourcef(m_source, AL_MAX_GAIN, &result);
542 bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume)
549 alSourcef(m_source, AL_MAX_GAIN, volume);
556 float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum()
558 float result = std::numeric_limits<float>::quiet_NaN();
565 alGetSourcef(m_source, AL_MIN_GAIN, &result);
572 bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume)
579 alSourcef(m_source, AL_MIN_GAIN, volume);
586 float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum()
588 float result = std::numeric_limits<float>::quiet_NaN();
595 alGetSourcef(m_source, AL_MAX_DISTANCE, &result);
602 bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance)
609 alSourcef(m_source, AL_MAX_DISTANCE, distance);
616 float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference()
618 float result = std::numeric_limits<float>::quiet_NaN();
625 alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result);
632 bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance)
639 alSourcef(m_source, AL_REFERENCE_DISTANCE, distance);
646 float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation()
648 float result = std::numeric_limits<float>::quiet_NaN();
655 alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result);
662 bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor)
669 alSourcef(m_source, AL_ROLLOFF_FACTOR, factor);
676 float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter()
678 float result = std::numeric_limits<float>::quiet_NaN();
685 alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result);
692 bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle)
699 alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle);
706 float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner()
708 float result = std::numeric_limits<float>::quiet_NaN();
715 alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result);
722 bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle)
729 alSourcef(m_source, AL_CONE_INNER_ANGLE, angle);
736 float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter()
738 float result = std::numeric_limits<float>::quiet_NaN();
745 alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result);
752 bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume)
759 alSourcef(m_source, AL_CONE_OUTER_GAIN, volume);
766 /******************************************************************************/
767 /**************************** Threading Code **********************************/
768 /******************************************************************************/
770 void* AUD_openalRunThread(void* device)
772 AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device;
773 dev->updateStreams();
777 void AUD_OpenALDevice::start(bool join)
784 pthread_join(m_thread, NULL);
787 pthread_attr_init(&attr);
788 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
790 pthread_create(&m_thread, &attr, AUD_openalRunThread, this);
792 pthread_attr_destroy(&attr);
800 void AUD_OpenALDevice::updateStreams()
802 AUD_Reference<AUD_OpenALHandle> sound;
807 AUD_DeviceSpecs specs = m_specs;
809 std::list<AUD_Reference<AUD_OpenALHandle> > stopSounds;
810 std::list<AUD_Reference<AUD_OpenALHandle> > pauseSounds;
811 AUD_HandleIterator it;
817 alcSuspendContext(m_context);
818 cerr = alcGetError(m_device);
819 if(cerr == ALC_NO_ERROR)
822 for(it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
826 // is it a streamed sound?
827 if(!sound->m_isBuffered)
829 // check for buffer refilling
830 alGetSourcei(sound->m_source, AL_BUFFERS_PROCESSED, &info);
834 specs.specs = sound->m_reader->getSpecs();
835 m_buffer.assureSize(m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
837 // for all empty buffers
840 // if there's still data to play back
844 length = m_buffersize;
845 sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
847 // looping necessary?
848 if(length == 0 && sound->m_loopcount)
850 if(sound->m_loopcount > 0)
851 sound->m_loopcount--;
853 sound->m_reader->seek(0);
855 length = m_buffersize;
856 sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
859 if(sound->m_loopcount != 0)
860 sound->m_eos = false;
869 alSourceUnqueueBuffers(sound->m_source, 1,
870 &sound->m_buffers[sound->m_current]);
872 if((err = alGetError()) != AL_NO_ERROR)
878 // fill with new data
879 alBufferData(sound->m_buffers[sound->m_current],
881 m_buffer.getBuffer(), length *
882 AUD_DEVICE_SAMPLE_SIZE(specs),
885 if((err = alGetError()) != AL_NO_ERROR)
892 alSourceQueueBuffers(sound->m_source, 1,
893 &sound->m_buffers[sound->m_current]);
894 if(alGetError() != AL_NO_ERROR)
900 sound->m_current = (sound->m_current+1) %
901 AUD_OpenALHandle::CYCLE_BUFFERS;
909 // check if the sound has been stopped
910 alGetSourcei(sound->m_source, AL_SOURCE_STATE, &info);
912 if(info != AL_PLAYING)
914 // if it really stopped
918 sound->m_stop(sound->m_stop_data);
922 pauseSounds.push_back(sound);
925 stopSounds.push_back(sound);
929 alSourcePlay(sound->m_source);
933 for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
936 for(it = stopSounds.begin(); it != stopSounds.end(); it++)
942 alcProcessContext(m_context);
946 if(m_playingSounds.empty() || (cerr != ALC_NO_ERROR))
963 /******************************************************************************/
964 /**************************** IDevice Code ************************************/
965 /******************************************************************************/
967 static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened.";
969 AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
971 // cannot determine how many channels or which format OpenAL uses, but
972 // it at least is able to play 16 bit stereo audio
973 specs.channels = AUD_CHANNELS_STEREO;
974 specs.format = AUD_FORMAT_S16;
977 if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
979 ALCchar* devices = const_cast<ALCchar*>(alcGetString(NULL, ALC_DEVICE_SPECIFIER));
980 printf("OpenAL devices (standard is: %s):\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
984 printf("%s\n", devices);
985 devices += strlen(devices) + 1;
990 m_device = alcOpenDevice(NULL);
993 AUD_THROW(AUD_ERROR_OPENAL, open_error);
995 // at least try to set the frequency
996 ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 };
997 ALCint* attributes = attribs;
998 if(specs.rate == AUD_RATE_INVALID)
1001 m_context = alcCreateContext(m_device, attributes);
1002 alcMakeContextCurrent(m_context);
1004 alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
1006 // check for specific formats and channel counts to be played back
1007 if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
1008 specs.format = AUD_FORMAT_FLOAT32;
1010 m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
1013 alcGetError(m_device);
1016 m_buffersize = buffersize;
1019 // m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
1021 pthread_mutexattr_t attr;
1022 pthread_mutexattr_init(&attr);
1023 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1025 pthread_mutex_init(&m_mutex, &attr);
1027 pthread_mutexattr_destroy(&attr);
1032 AUD_OpenALDevice::~AUD_OpenALDevice()
1035 alcSuspendContext(m_context);
1037 while(!m_playingSounds.empty())
1038 m_playingSounds.front()->stop();
1040 while(!m_pausedSounds.empty())
1041 m_pausedSounds.front()->stop();
1044 // delete all buffered factories
1045 /*while(!m_bufferedFactories->empty())
1047 alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
1048 delete *m_bufferedFactories->begin();
1049 m_bufferedFactories->erase(m_bufferedFactories->begin());
1052 alcProcessContext(m_context);
1054 // wait for the thread to stop
1056 pthread_join(m_thread, NULL);
1058 //delete m_bufferedFactories;
1061 alcMakeContextCurrent(NULL);
1062 alcDestroyContext(m_context);
1063 alcCloseDevice(m_device);
1065 pthread_mutex_destroy(&m_mutex);
1068 AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const
1073 bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
1078 switch(m_specs.format)
1080 case AUD_FORMAT_S16:
1081 switch(specs.channels)
1083 case AUD_CHANNELS_MONO:
1084 format = AL_FORMAT_MONO16;
1086 case AUD_CHANNELS_STEREO:
1087 format = AL_FORMAT_STEREO16;
1089 case AUD_CHANNELS_SURROUND4:
1092 format = alGetEnumValue("AL_FORMAT_QUAD16");
1095 case AUD_CHANNELS_SURROUND51:
1098 format = alGetEnumValue("AL_FORMAT_51CHN16");
1101 case AUD_CHANNELS_SURROUND61:
1104 format = alGetEnumValue("AL_FORMAT_61CHN16");
1107 case AUD_CHANNELS_SURROUND71:
1110 format = alGetEnumValue("AL_FORMAT_71CHN16");
1117 case AUD_FORMAT_FLOAT32:
1118 switch(specs.channels)
1120 case AUD_CHANNELS_MONO:
1121 format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
1123 case AUD_CHANNELS_STEREO:
1124 format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
1126 case AUD_CHANNELS_SURROUND4:
1129 format = alGetEnumValue("AL_FORMAT_QUAD32");
1132 case AUD_CHANNELS_SURROUND51:
1135 format = alGetEnumValue("AL_FORMAT_51CHN32");
1138 case AUD_CHANNELS_SURROUND61:
1141 format = alGetEnumValue("AL_FORMAT_61CHN32");
1144 case AUD_CHANNELS_SURROUND71:
1147 format = alGetEnumValue("AL_FORMAT_71CHN32");
1164 AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
1166 AUD_Specs specs = reader->getSpecs();
1169 if(specs.channels == AUD_CHANNELS_INVALID)
1170 return AUD_Reference<AUD_IHandle>();
1172 if(m_specs.format != AUD_FORMAT_FLOAT32)
1173 reader = new AUD_ConverterReader(reader, m_specs);
1177 if(!getFormat(format, specs))
1178 return AUD_Reference<AUD_IHandle>();
1181 alcSuspendContext(m_context);
1183 AUD_Reference<AUD_OpenALDevice::AUD_OpenALHandle> sound;
1187 // create the handle
1188 sound = new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep);
1190 catch(AUD_Exception&)
1192 alcProcessContext(m_context);
1197 alcProcessContext(m_context);
1200 m_playingSounds.push_back(sound);
1206 return AUD_Reference<AUD_IHandle>(sound);
1209 AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
1212 AUD_OpenALHandle* sound = NULL;
1218 // check if it is a buffered factory
1219 for(AUD_BFIterator i = m_bufferedFactories->begin();
1220 i != m_bufferedFactories->end(); i++)
1222 if((*i)->factory == factory)
1224 // create the handle
1225 sound = new AUD_OpenALHandle;
1227 sound->current = -1;
1228 sound->isBuffered = true;
1230 sound->loopcount = 0;
1232 sound->stop_data = NULL;
1234 alcSuspendContext(m_context);
1236 // OpenAL playback code
1239 alGenSources(1, &sound->source);
1240 if(alGetError() != AL_NO_ERROR)
1241 AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
1245 alSourcei(sound->source, AL_BUFFER, (*i)->buffer);
1246 if(alGetError() != AL_NO_ERROR)
1247 AUD_THROW(AUD_ERROR_OPENAL, queue_error);
1249 catch(AUD_Exception&)
1251 alDeleteSources(1, &sound->source);
1255 catch(AUD_Exception&)
1258 alcProcessContext(m_context);
1263 m_playingSounds->push_back(sound);
1265 alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
1268 alcProcessContext(m_context);
1272 catch(AUD_Exception&)
1283 return play(factory->createReader(), keep);
1286 void AUD_OpenALDevice::stopAll()
1289 alcSuspendContext(m_context);
1291 while(!m_playingSounds.empty())
1292 m_playingSounds.front()->stop();
1294 while(!m_pausedSounds.empty())
1295 m_pausedSounds.front()->stop();
1297 alcProcessContext(m_context);
1301 void AUD_OpenALDevice::lock()
1303 pthread_mutex_lock(&m_mutex);
1306 void AUD_OpenALDevice::unlock()
1308 pthread_mutex_unlock(&m_mutex);
1311 float AUD_OpenALDevice::getVolume() const
1314 alGetListenerf(AL_GAIN, &result);
1318 void AUD_OpenALDevice::setVolume(float volume)
1320 alListenerf(AL_GAIN, volume);
1323 /* AUD_XXX Temorary disabled
1325 bool AUD_OpenALDevice::bufferFactory(void *value)
1327 bool result = false;
1328 AUD_IFactory* factory = (AUD_IFactory*) value;
1330 // load the factory into an OpenAL buffer
1333 // check if the factory is already buffered
1335 for(AUD_BFIterator i = m_bufferedFactories->begin();
1336 i != m_bufferedFactories->end(); i++)
1338 if((*i)->factory == factory)
1348 AUD_IReader* reader = factory->createReader();
1353 AUD_DeviceSpecs specs = m_specs;
1354 specs.specs = reader->getSpecs();
1356 if(m_specs.format != AUD_FORMAT_FLOAT32)
1357 reader = new AUD_ConverterReader(reader, m_specs);
1361 if(!getFormat(format, specs.specs))
1366 // load into a buffer
1368 alcSuspendContext(m_context);
1370 AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory;
1371 bf->factory = factory;
1375 alGenBuffers(1, &bf->buffer);
1376 if(alGetError() != AL_NO_ERROR)
1377 AUD_THROW(AUD_ERROR_OPENAL);
1382 int length = reader->getLength();
1384 reader->read(length, buf);
1385 alBufferData(bf->buffer, format, buf,
1386 length * AUD_DEVICE_SAMPLE_SIZE(specs),
1388 if(alGetError() != AL_NO_ERROR)
1389 AUD_THROW(AUD_ERROR_OPENAL);
1391 catch(AUD_Exception&)
1393 alDeleteBuffers(1, &bf->buffer);
1397 catch(AUD_Exception&)
1400 alcProcessContext(m_context);
1405 m_bufferedFactories->push_back(bf);
1407 alcProcessContext(m_context);
1412 // stop all playing and paused buffered sources
1414 alcSuspendContext(m_context);
1416 AUD_OpenALHandle* sound;
1417 AUD_HandleIterator it = m_playingSounds->begin();
1418 while(it != m_playingSounds->end())
1423 if(sound->isBuffered)
1426 alcProcessContext(m_context);
1428 while(!m_bufferedFactories->empty())
1431 &(*(m_bufferedFactories->begin()))->buffer);
1432 delete *m_bufferedFactories->begin();
1433 m_bufferedFactories->erase(m_bufferedFactories->begin());
1441 /******************************************************************************/
1442 /**************************** 3D Device Code **********************************/
1443 /******************************************************************************/
1445 AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const
1448 alGetListenerfv(AL_POSITION, p);
1449 return AUD_Vector3(p[0], p[1], p[2]);
1452 void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location)
1454 alListenerfv(AL_POSITION, (ALfloat*)location.get());
1457 AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const
1460 alGetListenerfv(AL_VELOCITY, v);
1461 return AUD_Vector3(v[0], v[1], v[2]);
1464 void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity)
1466 alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get());
1469 AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const
1471 return m_orientation;
1474 void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation)
1476 ALfloat direction[6];
1477 direction[0] = -2 * (orientation.w() * orientation.y() +
1478 orientation.x() * orientation.z());
1479 direction[1] = 2 * (orientation.x() * orientation.w() -
1480 orientation.z() * orientation.y());
1481 direction[2] = 2 * (orientation.x() * orientation.x() +
1482 orientation.y() * orientation.y()) - 1;
1483 direction[3] = 2 * (orientation.x() * orientation.y() -
1484 orientation.w() * orientation.z());
1485 direction[4] = 1 - 2 * (orientation.x() * orientation.x() +
1486 orientation.z() * orientation.z());
1487 direction[5] = 2 * (orientation.w() * orientation.x() +
1488 orientation.y() * orientation.z());
1489 alListenerfv(AL_ORIENTATION, direction);
1490 m_orientation = orientation;
1493 float AUD_OpenALDevice::getSpeedOfSound() const
1495 return alGetFloat(AL_SPEED_OF_SOUND);
1498 void AUD_OpenALDevice::setSpeedOfSound(float speed)
1500 alSpeedOfSound(speed);
1503 float AUD_OpenALDevice::getDopplerFactor() const
1505 return alGetFloat(AL_DOPPLER_FACTOR);
1508 void AUD_OpenALDevice::setDopplerFactor(float factor)
1510 alDopplerFactor(factor);
1513 AUD_DistanceModel AUD_OpenALDevice::getDistanceModel() const
1515 switch(alGetInteger(AL_DISTANCE_MODEL))
1517 case AL_INVERSE_DISTANCE:
1518 return AUD_DISTANCE_MODEL_INVERSE;
1519 case AL_INVERSE_DISTANCE_CLAMPED:
1520 return AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
1521 case AL_LINEAR_DISTANCE:
1522 return AUD_DISTANCE_MODEL_LINEAR;
1523 case AL_LINEAR_DISTANCE_CLAMPED:
1524 return AUD_DISTANCE_MODEL_LINEAR_CLAMPED;
1525 case AL_EXPONENT_DISTANCE:
1526 return AUD_DISTANCE_MODEL_EXPONENT;
1527 case AL_EXPONENT_DISTANCE_CLAMPED:
1528 return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED;
1530 return AUD_DISTANCE_MODEL_INVALID;
1534 void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model)
1538 case AUD_DISTANCE_MODEL_INVERSE:
1539 alDistanceModel(AL_INVERSE_DISTANCE);
1541 case AUD_DISTANCE_MODEL_INVERSE_CLAMPED:
1542 alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
1544 case AUD_DISTANCE_MODEL_LINEAR:
1545 alDistanceModel(AL_LINEAR_DISTANCE);
1547 case AUD_DISTANCE_MODEL_LINEAR_CLAMPED:
1548 alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
1550 case AUD_DISTANCE_MODEL_EXPONENT:
1551 alDistanceModel(AL_EXPONENT_DISTANCE);
1553 case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED:
1554 alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
1557 alDistanceModel(AL_NONE);