diff options
Diffstat (limited to 'intern/audaspace/OpenAL/AUD_OpenALDevice.cpp')
-rw-r--r-- | intern/audaspace/OpenAL/AUD_OpenALDevice.cpp | 1069 |
1 files changed, 651 insertions, 418 deletions
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index 796764989ba..aa7cfcfd880 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -24,9 +24,9 @@ */ #include "AUD_OpenALDevice.h" +#include "AUD_IFactory.h" #include "AUD_IReader.h" -#include "AUD_ConverterFactory.h" -#include "AUD_SourceCaps.h" +#include "AUD_ConverterReader.h" #include <cstring> #include <limits> @@ -65,6 +65,15 @@ struct AUD_OpenALHandle : AUD_Handle /// Whether the stream doesn't return any more data. bool data_end; + + /// The loop count of the source. + int loopcount; + + /// The stop callback. + stopCallback stop; + + /// Stop callback data. + void* stop_data; }; struct AUD_OpenALBufferedFactory @@ -128,13 +137,9 @@ void AUD_OpenALDevice::updateStreams() { // for all sounds - AUD_HandleIterator it = m_playingSounds->begin(); - while(it != m_playingSounds->end()) + for(AUD_HandleIterator it = m_playingSounds->begin(); it != m_playingSounds->end(); it++) { sound = *it; - // increment the iterator to make sure it's valid, - // in case the sound gets deleted after stopping - ++it; // is it a streamed sound? if(!sound->isBuffered) @@ -156,6 +161,18 @@ void AUD_OpenALDevice::updateStreams() length = m_buffersize; sound->reader->read(length, buffer); + // looping necessary? + if(length == 0 && sound->loopcount) + { + if(sound->loopcount > 0) + sound->loopcount--; + + sound->reader->seek(0); + + length = m_buffersize; + sound->reader->read(length, buffer); + } + // read nothing? if(length == 0) { @@ -212,12 +229,21 @@ void AUD_OpenALDevice::updateStreams() // if it really stopped if(sound->data_end) { + if(sound->stop) + sound->stop(sound->stop_data); + + // increment the iterator to the next value, + // because the sound gets deleted in the list here. + ++it; // pause or if(sound->keep) pause(sound); // stop else stop(sound); + // decrement again, so that we get the next sound in the + // next loop run + --it; } // continue playing else @@ -263,6 +289,8 @@ bool AUD_OpenALDevice::isValid(AUD_Handle* handle) return false; } +static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened."; + AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) { // cannot determine how many channels or which format OpenAL uses, but @@ -287,7 +315,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) m_device = alcOpenDevice(NULL); if(!m_device) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, open_error); // at least try to set the frequency ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 }; @@ -302,12 +330,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) // check for specific formats and channel counts to be played back if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE) - { specs.format = AUD_FORMAT_FLOAT32; - m_converter = NULL; - } - else - m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory") m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE; @@ -317,10 +340,9 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) m_buffersize = buffersize; m_playing = false; - m_playingSounds = new std::list<AUD_OpenALHandle*>(); AUD_NEW("list") - m_pausedSounds = new std::list<AUD_OpenALHandle*>(); AUD_NEW("list") + m_playingSounds = new std::list<AUD_OpenALHandle*>(); + m_pausedSounds = new std::list<AUD_OpenALHandle*>(); m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>(); - AUD_NEW("list") pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -345,10 +367,10 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; AUD_DELETE("reader") + delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } - delete sound; AUD_DELETE("handle") + delete sound; m_playingSounds->erase(m_playingSounds->begin()); } @@ -359,10 +381,10 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; AUD_DELETE("reader") + delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } - delete sound; AUD_DELETE("handle") + delete sound; m_pausedSounds->erase(m_pausedSounds->begin()); } @@ -370,7 +392,7 @@ AUD_OpenALDevice::~AUD_OpenALDevice() while(!m_bufferedFactories->empty()) { alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer); - delete *m_bufferedFactories->begin(); AUD_DELETE("bufferedfactory"); + delete *m_bufferedFactories->begin(); m_bufferedFactories->erase(m_bufferedFactories->begin()); } @@ -385,22 +407,19 @@ AUD_OpenALDevice::~AUD_OpenALDevice() else unlock(); - delete m_playingSounds; AUD_DELETE("list") - delete m_pausedSounds; AUD_DELETE("list") - delete m_bufferedFactories; AUD_DELETE("list") + delete m_playingSounds; + delete m_pausedSounds; + delete m_bufferedFactories; // quit OpenAL alcMakeContextCurrent(NULL); alcDestroyContext(m_context); alcCloseDevice(m_device); - if(m_converter) - delete m_converter; AUD_DELETE("factory") - pthread_mutex_destroy(&m_mutex); } -AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() +AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const { return m_specs; } @@ -496,6 +515,15 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs) return valid; } +static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be " + "generated."; +static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be " + "generated."; +static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be " + "queued to the source."; +static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be " + "filled with data."; + AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) { lock(); @@ -511,11 +539,14 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) if((*i)->factory == factory) { // create the handle - sound = new AUD_OpenALHandle; AUD_NEW("handle") + sound = new AUD_OpenALHandle; sound->keep = keep; sound->current = -1; sound->isBuffered = true; sound->data_end = true; + sound->loopcount = 0; + sound->stop = NULL; + sound->stop_data = NULL; alcSuspendContext(m_context); @@ -524,23 +555,23 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) { alGenSources(1, &sound->source); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, gensource_error); try { alSourcei(sound->source, AL_BUFFER, (*i)->buffer); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, queue_error); } - catch(AUD_Exception) + catch(AUD_Exception&) { alDeleteSources(1, &sound->source); throw; } } - catch(AUD_Exception) + catch(AUD_Exception&) { - delete sound; AUD_DELETE("handle") + delete sound; alcProcessContext(m_context); throw; } @@ -555,7 +586,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) } } } - catch(AUD_Exception) + catch(AUD_Exception&) { unlock(); throw; @@ -568,35 +599,32 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) AUD_IReader* reader = factory->createReader(); - if(reader == NULL) - AUD_THROW(AUD_ERROR_READER); - AUD_DeviceSpecs specs = m_specs; specs.specs = reader->getSpecs(); // check format bool valid = specs.channels != AUD_CHANNELS_INVALID; - if(m_converter) - { - m_converter->setReader(reader); - reader = m_converter->createReader(); - } + if(m_specs.format != AUD_FORMAT_FLOAT32) + reader = new AUD_ConverterReader(reader, m_specs); // create the handle - sound = new AUD_OpenALHandle; AUD_NEW("handle") + sound = new AUD_OpenALHandle; sound->keep = keep; sound->reader = reader; sound->current = 0; sound->isBuffered = false; sound->data_end = false; + sound->loopcount = 0; + sound->stop = NULL; + sound->stop_data = NULL; valid &= getFormat(sound->format, specs.specs); if(!valid) { - delete sound; AUD_DELETE("handle") - delete reader; AUD_DELETE("reader") + delete sound; + delete reader; return NULL; } @@ -608,7 +636,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) { alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error); try { @@ -623,36 +651,36 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error); } alGenSources(1, &sound->source); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, gensource_error); try { alSourceQueueBuffers(sound->source, AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, queue_error); } - catch(AUD_Exception) + catch(AUD_Exception&) { alDeleteSources(1, &sound->source); throw; } } - catch(AUD_Exception) + catch(AUD_Exception&) { alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); throw; } } - catch(AUD_Exception) + catch(AUD_Exception&) { - delete sound; AUD_DELETE("handle") - delete reader; AUD_DELETE("reader") + delete sound; + delete reader; alcProcessContext(m_context); unlock(); throw; @@ -737,10 +765,10 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle) alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; AUD_DELETE("reader") + delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } - delete *i; AUD_DELETE("handle") + delete *i; m_playingSounds->erase(i); result = true; break; @@ -757,10 +785,10 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle) alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; AUD_DELETE("reader") + delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } - delete *i; AUD_DELETE("handle") + delete *i; m_pausedSounds->erase(i); result = true; break; @@ -773,43 +801,31 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle) return result; } -bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep) +bool AUD_OpenALDevice::getKeep(AUD_Handle* handle) { bool result = false; lock(); if(isValid(handle)) - { - ((AUD_OpenALHandle*)handle)->keep = keep; - result = true; - } + result = ((AUD_OpenALHandle*)handle)->keep; unlock(); return result; } -bool AUD_OpenALDevice::sendMessage(AUD_Handle* handle, AUD_Message &message) +bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep) { bool result = false; lock(); - if(handle == 0) + if(isValid(handle)) { - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - if(!(*i)->isBuffered) - result |= (*i)->reader->notify(message); - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - if(!(*i)->isBuffered) - result |= (*i)->reader->notify(message); + ((AUD_OpenALHandle*)handle)->keep = keep; + result = true; } - else if(isValid(handle)) - if(!((AUD_OpenALHandle*)handle)->isBuffered) - result = ((AUD_OpenALHandle*)handle)->reader->notify(message); unlock(); @@ -947,440 +963,657 @@ void AUD_OpenALDevice::unlock() pthread_mutex_unlock(&m_mutex); } -/******************************************************************************/ -/**************************** Capabilities Code *******************************/ -/******************************************************************************/ +float AUD_OpenALDevice::getVolume() const +{ + float result; + alGetListenerf(AL_GAIN, &result); + return result; +} -bool AUD_OpenALDevice::checkCapability(int capability) +void AUD_OpenALDevice::setVolume(float volume) { - return capability == AUD_CAPS_3D_DEVICE || - capability == AUD_CAPS_VOLUME || - capability == AUD_CAPS_SOURCE_VOLUME || - capability == AUD_CAPS_SOURCE_PITCH || - capability == AUD_CAPS_BUFFERED_FACTORY; + alListenerf(AL_GAIN, volume); +} + +float AUD_OpenALDevice::getVolume(AUD_Handle* handle) +{ + lock(); + float result = std::numeric_limits<float>::quiet_NaN(); + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_GAIN, &result); + unlock(); + return result; } -bool AUD_OpenALDevice::setCapability(int capability, void *value) +bool AUD_OpenALDevice::setVolume(AUD_Handle* handle, float volume) +{ + lock(); + bool result = isValid(handle); + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_GAIN, volume); + unlock(); + return result; +} + +float AUD_OpenALDevice::getPitch(AUD_Handle* handle) +{ + lock(); + float result = std::numeric_limits<float>::quiet_NaN(); + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_PITCH, &result); + unlock(); + return result; +} + +bool AUD_OpenALDevice::setPitch(AUD_Handle* handle, float pitch) +{ + lock(); + bool result = isValid(handle); + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_PITCH, pitch); + unlock(); + return result; +} + +int AUD_OpenALDevice::getLoopCount(AUD_Handle* handle) +{ + lock(); + int result = 0; + if(isValid(handle)) + result = ((AUD_OpenALHandle*)handle)->loopcount; + unlock(); + return result; +} + +bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count) +{ + lock(); + bool result = isValid(handle); + if(result) + ((AUD_OpenALHandle*)handle)->loopcount = count; + unlock(); + return result; +} + +bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data) +{ + lock(); + bool result = isValid(handle); + if(result) + { + AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle; + h->stop = callback; + h->stop_data = data; + } + unlock(); + return result; +} + +/* AUD_XXX Temorary disabled + +bool AUD_OpenALDevice::bufferFactory(void *value) { bool result = false; - switch(capability) + AUD_IFactory* factory = (AUD_IFactory*) value; + + // load the factory into an OpenAL buffer + if(factory) { - case AUD_CAPS_VOLUME: - alListenerf(AL_GAIN, *((float*)value)); - return true; - case AUD_CAPS_SOURCE_VOLUME: + // check if the factory is already buffered + lock(); + for(AUD_BFIterator i = m_bufferedFactories->begin(); + i != m_bufferedFactories->end(); i++) { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; - lock(); - if(isValid(caps->handle)) + if((*i)->factory == factory) { - alSourcef(((AUD_OpenALHandle*)caps->handle)->source, - AL_GAIN, caps->value); result = true; + break; } - unlock(); } - break; - case AUD_CAPS_SOURCE_PITCH: + unlock(); + if(result) + return result; + + AUD_IReader* reader = factory->createReader(); + + if(reader == NULL) + return false; + + AUD_DeviceSpecs specs = m_specs; + specs.specs = reader->getSpecs(); + + if(m_specs.format != AUD_FORMAT_FLOAT32) + reader = new AUD_ConverterReader(reader, m_specs); + + ALenum format; + + if(!getFormat(format, specs.specs)) { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; - lock(); - if(isValid(caps->handle)) - { - alSourcef(((AUD_OpenALHandle*)caps->handle)->source, - AL_PITCH, caps->value); - result = true; - } - unlock(); + delete reader; + return false; } - break; - case AUD_CAPS_BUFFERED_FACTORY: + + // load into a buffer + lock(); + alcSuspendContext(m_context); + + AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory; + bf->factory = factory; + + try { - AUD_IFactory* factory = (AUD_IFactory*) value; + alGenBuffers(1, &bf->buffer); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL); - // load the factory into an OpenAL buffer - if(factory) + try { - // check if the factory is already buffered - lock(); - for(AUD_BFIterator i = m_bufferedFactories->begin(); - i != m_bufferedFactories->end(); i++) - { - if((*i)->factory == factory) - { - result = true; - break; - } - } - unlock(); - if(result) - return result; + sample_t* buf; + int length = reader->getLength(); - AUD_IReader* reader = factory->createReader(); + reader->read(length, buf); + alBufferData(bf->buffer, format, buf, + length * AUD_DEVICE_SAMPLE_SIZE(specs), + specs.rate); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL); + } + catch(AUD_Exception&) + { + alDeleteBuffers(1, &bf->buffer); + throw; + } + } + catch(AUD_Exception&) + { + delete bf; + delete reader; + alcProcessContext(m_context); + unlock(); + return false; + } - if(reader == NULL) - return false; + m_bufferedFactories->push_back(bf); - AUD_DeviceSpecs specs = m_specs; - specs.specs = reader->getSpecs(); + alcProcessContext(m_context); + unlock(); + } + else + { + // stop all playing and paused buffered sources + lock(); + alcSuspendContext(m_context); - // determine format - bool valid = reader->getType() == AUD_TYPE_BUFFER; + AUD_OpenALHandle* sound; + AUD_HandleIterator it = m_playingSounds->begin(); + while(it != m_playingSounds->end()) + { + sound = *it; + ++it; - if(valid) - { - if(m_converter) - { - m_converter->setReader(reader); - reader = m_converter->createReader(); - } - } + if(sound->isBuffered) + stop(sound); + } + alcProcessContext(m_context); - ALenum format; + while(!m_bufferedFactories->empty()) + { + alDeleteBuffers(1, + &(*(m_bufferedFactories->begin()))->buffer); + delete *m_bufferedFactories->begin(); + m_bufferedFactories->erase(m_bufferedFactories->begin()); + } + unlock(); + } - if(valid) - valid = getFormat(format, specs.specs); + return true; +}*/ - if(!valid) - { - delete reader; AUD_DELETE("reader") - return false; - } +/******************************************************************************/ +/**************************** 3D Device Code **********************************/ +/******************************************************************************/ - // load into a buffer - lock(); - alcSuspendContext(m_context); +AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const +{ + ALfloat p[3]; + alGetListenerfv(AL_POSITION, p); + return AUD_Vector3(p[0], p[1], p[2]); +} - AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory; - AUD_NEW("bufferedfactory"); - bf->factory = factory; +void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location) +{ + alListenerfv(AL_POSITION, (ALfloat*)location.get()); +} - try - { - alGenBuffers(1, &bf->buffer); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); +AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const +{ + ALfloat v[3]; + alGetListenerfv(AL_VELOCITY, v); + return AUD_Vector3(v[0], v[1], v[2]); +} - try - { - sample_t* buf; - int length = reader->getLength(); +void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity) +{ + alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get()); +} - reader->read(length, buf); - alBufferData(bf->buffer, format, buf, - length * AUD_DEVICE_SAMPLE_SIZE(specs), - specs.rate); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); - } - catch(AUD_Exception) - { - alDeleteBuffers(1, &bf->buffer); - throw; - } - } - catch(AUD_Exception) - { - delete bf; AUD_DELETE("bufferedfactory") - delete reader; AUD_DELETE("reader") - alcProcessContext(m_context); - unlock(); - return false; - } +AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const +{ + // AUD_XXX not implemented yet + return AUD_Quaternion(0, 0, 0, 0); +} - m_bufferedFactories->push_back(bf); +void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation) +{ + ALfloat direction[6]; + direction[0] = -2 * (orientation.w() * orientation.y() + + orientation.x() * orientation.z()); + direction[1] = 2 * (orientation.x() * orientation.w() - + orientation.z() * orientation.y()); + direction[2] = 2 * (orientation.x() * orientation.x() + + orientation.y() * orientation.y()) - 1; + direction[3] = 2 * (orientation.x() * orientation.y() - + orientation.w() * orientation.z()); + direction[4] = 1 - 2 * (orientation.x() * orientation.x() + + orientation.z() * orientation.z()); + direction[5] = 2 * (orientation.w() * orientation.x() + + orientation.y() * orientation.z()); + alListenerfv(AL_ORIENTATION, direction); +} - alcProcessContext(m_context); - unlock(); - } - else - { - // stop all playing and paused buffered sources - lock(); - alcSuspendContext(m_context); +float AUD_OpenALDevice::getSpeedOfSound() const +{ + return alGetFloat(AL_SPEED_OF_SOUND); +} - AUD_OpenALHandle* sound; - AUD_HandleIterator it = m_playingSounds->begin(); - while(it != m_playingSounds->end()) - { - sound = *it; - ++it; +void AUD_OpenALDevice::setSpeedOfSound(float speed) +{ + alSpeedOfSound(speed); +} - if(sound->isBuffered) - stop(sound); - } - alcProcessContext(m_context); +float AUD_OpenALDevice::getDopplerFactor() const +{ + return alGetFloat(AL_DOPPLER_FACTOR); +} - while(!m_bufferedFactories->empty()) - { - alDeleteBuffers(1, - &(*(m_bufferedFactories->begin()))->buffer); - delete *m_bufferedFactories->begin(); - AUD_DELETE("bufferedfactory"); - m_bufferedFactories->erase(m_bufferedFactories->begin()); - } - unlock(); - } +void AUD_OpenALDevice::setDopplerFactor(float factor) +{ + alDopplerFactor(factor); +} - return true; - } - break; +AUD_DistanceModel AUD_OpenALDevice::getDistanceModel() const +{ + switch(alGetInteger(AL_DISTANCE_MODEL)) + { + case AL_INVERSE_DISTANCE: + return AUD_DISTANCE_MODEL_INVERSE; + case AL_INVERSE_DISTANCE_CLAMPED: + return AUD_DISTANCE_MODEL_INVERSE_CLAMPED; + case AL_LINEAR_DISTANCE: + return AUD_DISTANCE_MODEL_LINEAR; + case AL_LINEAR_DISTANCE_CLAMPED: + return AUD_DISTANCE_MODEL_LINEAR_CLAMPED; + case AL_EXPONENT_DISTANCE: + return AUD_DISTANCE_MODEL_EXPONENT; + case AL_EXPONENT_DISTANCE_CLAMPED: + return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED; + default: + return AUD_DISTANCE_MODEL_INVALID; } - return result; } -bool AUD_OpenALDevice::getCapability(int capability, void *value) +void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model) { - bool result = false; - - switch(capability) + switch(model) { - case AUD_CAPS_VOLUME: - alGetListenerf(AL_GAIN, (float*)value); - return true; - case AUD_CAPS_SOURCE_VOLUME: - { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; - lock(); - if(isValid(caps->handle)) - { - alGetSourcef(((AUD_OpenALHandle*)caps->handle)->source, - AL_GAIN, &caps->value); - result = true; - } - unlock(); - } + case AUD_DISTANCE_MODEL_INVERSE: + alDistanceModel(AL_INVERSE_DISTANCE); break; - case AUD_CAPS_SOURCE_PITCH: - { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; - lock(); - if(isValid(caps->handle)) - { - alGetSourcef(((AUD_OpenALHandle*)caps->handle)->source, - AL_PITCH, &caps->value); - result = true; - } - unlock(); - } + case AUD_DISTANCE_MODEL_INVERSE_CLAMPED: + alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); + break; + case AUD_DISTANCE_MODEL_LINEAR: + alDistanceModel(AL_LINEAR_DISTANCE); + break; + case AUD_DISTANCE_MODEL_LINEAR_CLAMPED: + alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); + break; + case AUD_DISTANCE_MODEL_EXPONENT: + alDistanceModel(AL_EXPONENT_DISTANCE); break; + case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED: + alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED); + break; + default: + alDistanceModel(AL_NONE); } +} + +AUD_Vector3 AUD_OpenALDevice::getSourceLocation(AUD_Handle* handle) +{ + AUD_Vector3 result = AUD_Vector3(0, 0, 0); + ALfloat p[3]; + lock(); + if(isValid(handle)) + { + alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, p); + result = AUD_Vector3(p[0], p[1], p[2]); + } + + unlock(); return result; } -/******************************************************************************/ -/**************************** 3D Device Code **********************************/ -/******************************************************************************/ +bool AUD_OpenALDevice::setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, + (ALfloat*)location.get()); -AUD_Handle* AUD_OpenALDevice::play3D(AUD_IFactory* factory, bool keep) + unlock(); + return result; +} + +AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* handle) { - AUD_OpenALHandle* handle = (AUD_OpenALHandle*)play(factory, keep); - if(handle) - alSourcei(handle->source, AL_SOURCE_RELATIVE, 0); - return handle; + AUD_Vector3 result = AUD_Vector3(0, 0, 0); + ALfloat v[3]; + lock(); + + if(isValid(handle)) + { + alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, v); + result = AUD_Vector3(v[0], v[1], v[2]); + } + + unlock(); + return result; } -bool AUD_OpenALDevice::updateListener(AUD_3DData &data) +bool AUD_OpenALDevice::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity) { - alListenerfv(AL_POSITION, (ALfloat*)data.position); - alListenerfv(AL_VELOCITY, (ALfloat*)data.velocity); - alListenerfv(AL_ORIENTATION, (ALfloat*)&(data.orientation[3])); + lock(); + bool result = isValid(handle); - return true; + if(result) + alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, + (ALfloat*)velocity.get()); + + unlock(); + return result; } -bool AUD_OpenALDevice::setSetting(AUD_3DSetting setting, float value) +AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle) { - switch(setting) - { - case AUD_3DS_DISTANCE_MODEL: - if(value == AUD_DISTANCE_MODEL_NONE) - alDistanceModel(AL_NONE); - else if(value == AUD_DISTANCE_MODEL_INVERSE) - alDistanceModel(AL_INVERSE_DISTANCE); - else if(value == AUD_DISTANCE_MODEL_INVERSE_CLAMPED) - alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); - else if(value == AUD_DISTANCE_MODEL_LINEAR) - alDistanceModel(AL_LINEAR_DISTANCE); - else if(value == AUD_DISTANCE_MODEL_LINEAR_CLAMPED) - alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); - else if(value == AUD_DISTANCE_MODEL_EXPONENT) - alDistanceModel(AL_EXPONENT_DISTANCE); - else if(value == AUD_DISTANCE_MODEL_EXPONENT_CLAMPED) - alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED); - else - return false; - return true; - case AUD_3DS_DOPPLER_FACTOR: - alDopplerFactor(value); - return true; - case AUD_3DS_SPEED_OF_SOUND: - alSpeedOfSound(value); - return true; - default: - return false; - } + // AUD_XXX not implemented yet + return AUD_Quaternion(0, 0, 0, 0); } -float AUD_OpenALDevice::getSetting(AUD_3DSetting setting) +bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation) { - switch(setting) + lock(); + bool result = isValid(handle); + + if(result) { - case AUD_3DS_DISTANCE_MODEL: - switch(alGetInteger(AL_DISTANCE_MODEL)) - { - case AL_NONE: - return AUD_DISTANCE_MODEL_NONE; - case AL_INVERSE_DISTANCE: - return AUD_DISTANCE_MODEL_INVERSE; - case AL_INVERSE_DISTANCE_CLAMPED: - return AUD_DISTANCE_MODEL_INVERSE_CLAMPED; - case AL_LINEAR_DISTANCE: - return AUD_DISTANCE_MODEL_LINEAR; - case AL_LINEAR_DISTANCE_CLAMPED: - return AUD_DISTANCE_MODEL_LINEAR_CLAMPED; - case AL_EXPONENT_DISTANCE: - return AUD_DISTANCE_MODEL_EXPONENT; - case AL_EXPONENT_DISTANCE_CLAMPED: - return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED; - } - case AUD_3DS_DOPPLER_FACTOR: - return alGetFloat(AL_DOPPLER_FACTOR); - case AUD_3DS_SPEED_OF_SOUND: - return alGetFloat(AL_SPEED_OF_SOUND); - default: - return std::numeric_limits<float>::quiet_NaN(); + ALfloat direction[3]; + direction[0] = -2 * (orientation.w() * orientation.y() + + orientation.x() * orientation.z()); + direction[1] = 2 * (orientation.x() * orientation.w() - + orientation.z() * orientation.y()); + direction[2] = 2 * (orientation.x() * orientation.x() + + orientation.y() * orientation.y()) - 1; + alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_DIRECTION, + direction); } + + unlock(); + return result; } -bool AUD_OpenALDevice::updateSource(AUD_Handle* handle, AUD_3DData &data) +bool AUD_OpenALDevice::isRelative(AUD_Handle* handle) { - bool result = false; + int result = std::numeric_limits<float>::quiet_NaN();; lock(); if(isValid(handle)) - { - int source = ((AUD_OpenALHandle*)handle)->source; - alSourcefv(source, AL_POSITION, (ALfloat*)data.position); - alSourcefv(source, AL_VELOCITY, (ALfloat*)data.velocity); - alSourcefv(source, AL_DIRECTION, (ALfloat*)&(data.orientation[3])); - result = true; - } + alGetSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE, + &result); unlock(); + return result; +} +bool AUD_OpenALDevice::setRelative(AUD_Handle* handle, bool relative) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE, + relative); + + unlock(); return result; } -bool AUD_OpenALDevice::setSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting, - float value) +float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle) { + float result = std::numeric_limits<float>::quiet_NaN();; + lock(); - bool result = false; + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setVolumeMaximum(AUD_Handle* handle, float volume) +{ + lock(); + bool result = isValid(handle); + + if(result) + + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN, + volume); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getVolumeMinimum(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); if(isValid(handle)) - { - int source = ((AUD_OpenALHandle*)handle)->source; + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN, + &result); - switch(setting) - { - case AUD_3DSS_CONE_INNER_ANGLE: - alSourcef(source, AL_CONE_INNER_ANGLE, value); - result = true; - break; - case AUD_3DSS_CONE_OUTER_ANGLE: - alSourcef(source, AL_CONE_OUTER_ANGLE, value); - result = true; - break; - case AUD_3DSS_CONE_OUTER_GAIN: - alSourcef(source, AL_CONE_OUTER_GAIN, value); - result = true; - break; - case AUD_3DSS_IS_RELATIVE: - alSourcei(source, AL_SOURCE_RELATIVE, value > 0.0f); - result = true; - break; - case AUD_3DSS_MAX_DISTANCE: - alSourcef(source, AL_MAX_DISTANCE, value); - result = true; - break; - case AUD_3DSS_MAX_GAIN: - alSourcef(source, AL_MAX_GAIN, value); - result = true; - break; - case AUD_3DSS_MIN_GAIN: - alSourcef(source, AL_MIN_GAIN, value); - result = true; - break; - case AUD_3DSS_REFERENCE_DISTANCE: - alSourcef(source, AL_REFERENCE_DISTANCE, value); - result = true; - break; - case AUD_3DSS_ROLLOFF_FACTOR: - alSourcef(source, AL_ROLLOFF_FACTOR, value); - result = true; - break; - default: - break; - } - } + unlock(); + return result; +} + +bool AUD_OpenALDevice::setVolumeMinimum(AUD_Handle* handle, float volume) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN, + volume); unlock(); return result; } -float AUD_OpenALDevice::getSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting) +float AUD_OpenALDevice::getDistanceMaximum(AUD_Handle* handle) { float result = std::numeric_limits<float>::quiet_NaN();; lock(); if(isValid(handle)) - { - int source = ((AUD_OpenALHandle*)handle)->source; + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE, + &result); - switch(setting) - { - case AUD_3DSS_CONE_INNER_ANGLE: - alGetSourcef(source, AL_CONE_INNER_ANGLE, &result); - break; - case AUD_3DSS_CONE_OUTER_ANGLE: - alGetSourcef(source, AL_CONE_OUTER_ANGLE, &result); - break; - case AUD_3DSS_CONE_OUTER_GAIN: - alGetSourcef(source, AL_CONE_OUTER_GAIN, &result); - break; - case AUD_3DSS_IS_RELATIVE: - { - ALint i; - alGetSourcei(source, AL_SOURCE_RELATIVE, &i); - result = i ? 1.0f : 0.0f; - break; - } - case AUD_3DSS_MAX_DISTANCE: - alGetSourcef(source, AL_MAX_DISTANCE, &result); - break; - case AUD_3DSS_MAX_GAIN: - alGetSourcef(source, AL_MAX_GAIN, &result); - break; - case AUD_3DSS_MIN_GAIN: - alGetSourcef(source, AL_MIN_GAIN, &result); - break; - case AUD_3DSS_REFERENCE_DISTANCE: - alGetSourcef(source, AL_REFERENCE_DISTANCE, &result); - break; - case AUD_3DSS_ROLLOFF_FACTOR: - alGetSourcef(source, AL_ROLLOFF_FACTOR, &result); - break; - default: - break; - } - } + unlock(); + return result; +} + +bool AUD_OpenALDevice::setDistanceMaximum(AUD_Handle* handle, float distance) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE, + distance); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getDistanceReference(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setDistanceReference(AUD_Handle* handle, float distance) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE, + distance); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getAttenuation(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setAttenuation(AUD_Handle* handle, float factor) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR, + factor); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getConeAngleOuter(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setConeAngleOuter(AUD_Handle* handle, float angle) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE, + angle); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getConeAngleInner(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setConeAngleInner(AUD_Handle* handle, float angle) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE, + angle); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getConeVolumeOuter(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setConeVolumeOuter(AUD_Handle* handle, float volume) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN, + volume); unlock(); return result; |