diff options
Diffstat (limited to 'intern/audaspace/OpenAL/AUD_OpenALDevice.cpp')
-rw-r--r-- | intern/audaspace/OpenAL/AUD_OpenALDevice.cpp | 1641 |
1 files changed, 781 insertions, 860 deletions
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index 71e7b7677e8..d5b365fa62f 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -43,56 +43,727 @@ #include <unistd.h> #endif -#define AUD_OPENAL_CYCLE_BUFFERS 3 +/*struct AUD_OpenALBufferedFactory +{ + /// The factory. + AUD_IFactory* factory; + + /// The OpenAL buffer. + ALuint buffer; +};*/ + +//typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator; + + +/******************************************************************************/ +/*********************** AUD_OpenALHandle Handle Code *************************/ +/******************************************************************************/ + +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."; -/// Saves the data for playback. -struct AUD_OpenALHandle : AUD_Handle +AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep) : + m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0), + m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), + m_device(device) { - /// Whether it's a buffered or a streamed source. - bool isBuffered; + AUD_DeviceSpecs specs = m_device->m_specs; + specs.specs = m_reader->getSpecs(); - /// The reader source. - AUD_IReader* reader; + // OpenAL playback code + alGenBuffers(CYCLE_BUFFERS, m_buffers); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error); - /// Whether to keep the source if end of it is reached. - bool keep; + try + { + m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs)); + int length; + bool eos; - /// OpenAL sample format. - ALenum format; + for(int i = 0; i < CYCLE_BUFFERS; i++) + { + length = m_device->m_buffersize; + reader->read(length, eos, m_device->m_buffer.getBuffer()); + alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(), + length * AUD_DEVICE_SAMPLE_SIZE(specs), + specs.rate); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error); + } - /// OpenAL source. - ALuint source; + alGenSources(1, &m_source); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL, gensource_error); - /// OpenAL buffers. - ALuint buffers[AUD_OPENAL_CYCLE_BUFFERS]; + try + { + alSourceQueueBuffers(m_source, CYCLE_BUFFERS, + m_buffers); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL, queue_error); + } + catch(AUD_Exception&) + { + alDeleteSources(1, &m_source); + throw; + } + } + catch(AUD_Exception&) + { + alDeleteBuffers(CYCLE_BUFFERS, m_buffers); + throw; + } + alSourcei(m_source, AL_SOURCE_RELATIVE, 1); +} - /// The first buffer to be read next. - int current; +bool AUD_OpenALDevice::AUD_OpenALHandle::pause() +{ + if(m_status) + { + m_device->lock(); - /// Whether the stream doesn't return any more data. - bool data_end; + if(m_status == AUD_STATUS_PLAYING) + { + m_device->m_playingSounds.remove(this); + m_device->m_pausedSounds.push_back(this); - /// The loop count of the source. - int loopcount; + alSourcePause(m_source); - /// The stop callback. - stopCallback stop; + m_status = AUD_STATUS_PAUSED; + m_device->unlock(); - /// Stop callback data. - void* stop_data; -}; + return true; + } + + m_device->unlock(); + } -struct AUD_OpenALBufferedFactory + return false; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::resume() { - /// The factory. - AUD_IFactory* factory; + if(m_status) + { + m_device->lock(); - /// The OpenAL buffer. - ALuint buffer; -}; + if(m_status == AUD_STATUS_PAUSED) + { + m_device->m_pausedSounds.remove(this); + m_device->m_playingSounds.push_back(this); + + m_device->start(); + m_status = AUD_STATUS_PLAYING; + m_device->unlock(); + return true; + } + + m_device->unlock(); + } + + return false; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::stop() +{ + if(!m_status) + return false; + + m_device->lock(); + + // AUD_XXX Create a reference of our own object so that it doesn't get + // deleted before the end of this function + AUD_Reference<AUD_OpenALHandle> This = this; + + if(m_status == AUD_STATUS_PLAYING) + m_device->m_playingSounds.remove(This); + else + m_device->m_pausedSounds.remove(This); + + m_device->unlock(); + + alDeleteSources(1, &m_source); + if(!m_isBuffered) + alDeleteBuffers(CYCLE_BUFFERS, m_buffers); + + m_status = AUD_STATUS_INVALID; + return true; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep() +{ + if(m_status) + return m_keep; + + return false; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setKeep(bool keep) +{ + if(!m_status) + return false; + + m_device->lock(); + + m_keep = keep; + + m_device->unlock(); + + return true; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position) +{ + if(!m_status) + return false; + + m_device->lock(); + + if(m_isBuffered) + alSourcef(m_source, AL_SEC_OFFSET, position); + else + { + m_reader->seek((int)(position * m_reader->getSpecs().rate)); + m_eos = false; + + ALint info; + + alGetSourcei(m_source, AL_SOURCE_STATE, &info); + + if(info != AL_PLAYING) + { + if(info == AL_PAUSED) + alSourceStop(m_source); + + alSourcei(m_source, AL_BUFFER, 0); + m_current = 0; + + ALenum err; + if((err = alGetError()) == AL_NO_ERROR) + { + int length; + AUD_DeviceSpecs specs = m_device->m_specs; + specs.specs = m_reader->getSpecs(); + m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs)); + + for(int i = 0; i < CYCLE_BUFFERS; i++) + { + length = m_device->m_buffersize; + m_reader->read(length, m_eos, m_device->m_buffer.getBuffer()); + alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(), + length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); + + if(alGetError() != AL_NO_ERROR) + break; + } + + if(m_loopcount != 0) + m_eos = false; -typedef std::list<AUD_OpenALHandle*>::iterator AUD_HandleIterator; -typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator; + alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers); + } + + alSourceRewind(m_source); + } + } + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getPosition() +{ + if(!m_status) + return 0.0f; + + m_device->lock(); + + float position = 0.0f; + + alGetSourcef(m_source, AL_SEC_OFFSET, &position); + + if(!m_isBuffered) + { + AUD_Specs specs = m_reader->getSpecs(); + position += (m_reader->getPosition() - m_device->m_buffersize * + CYCLE_BUFFERS) / (float)specs.rate; + } + + m_device->unlock(); + + return position; +} + +AUD_Status AUD_OpenALDevice::AUD_OpenALHandle::getStatus() +{ + return m_status; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getVolume() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_GAIN, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_GAIN, volume); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getPitch() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_PITCH, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_PITCH, pitch); + + m_device->unlock(); + + return true; +} + +int AUD_OpenALDevice::AUD_OpenALHandle::getLoopCount() +{ + if(!m_status) + return 0; + return m_loopcount; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setLoopCount(int count) +{ + if(!m_status) + return false; + m_loopcount = count; + return true; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, void* data) +{ + if(!m_status) + return false; + + m_device->lock(); + + m_stop = callback; + m_stop_data = data; + + m_device->unlock(); + + return true; +} + +/******************************************************************************/ +/********************* AUD_OpenALHandle 3DHandle Code *************************/ +/******************************************************************************/ + +AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceLocation() +{ + AUD_Vector3 result = AUD_Vector3(0, 0, 0); + + if(!m_status) + return result; + + m_device->lock(); + + ALfloat p[3]; + alGetSourcefv(m_source, AL_POSITION, p); + + m_device->unlock(); + + result = AUD_Vector3(p[0], p[1], p[2]); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceLocation(const AUD_Vector3& location) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get()); + + m_device->unlock(); + + return true; +} + +AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity() +{ + AUD_Vector3 result = AUD_Vector3(0, 0, 0); + + if(!m_status) + return result; + + m_device->lock(); + + ALfloat v[3]; + alGetSourcefv(m_source, AL_VELOCITY, v); + + m_device->unlock(); + + result = AUD_Vector3(v[0], v[1], v[2]); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceVelocity(const AUD_Vector3& velocity) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get()); + + m_device->unlock(); + + return true; +} + +AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation() +{ + return m_orientation; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation) +{ + if(!m_status) + return false; + + 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; + m_device->lock(); + + alSourcefv(m_source, AL_DIRECTION, direction); + + m_device->unlock(); + + m_orientation = orientation; + + return true; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative() +{ + int result; + + if(!m_status) + return false; + + m_device->lock(); + + alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcei(m_source, AL_SOURCE_RELATIVE, relative); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_MAX_GAIN, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_MAX_GAIN, volume); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_MIN_GAIN, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_MIN_GAIN, volume); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_MAX_DISTANCE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_MAX_DISTANCE, distance); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_REFERENCE_DISTANCE, distance); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_ROLLOFF_FACTOR, factor); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_CONE_INNER_ANGLE, angle); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_CONE_OUTER_GAIN, volume); + + m_device->unlock(); + + return true; +} /******************************************************************************/ /**************************** Threading Code **********************************/ @@ -130,16 +801,15 @@ void AUD_OpenALDevice::start(bool join) void AUD_OpenALDevice::updateStreams() { - AUD_OpenALHandle* sound; + AUD_Reference<AUD_OpenALHandle> sound; int length; - sample_t* buffer; ALint info; AUD_DeviceSpecs specs = m_specs; ALCenum cerr; - std::list<AUD_OpenALHandle*> stopSounds; - std::list<AUD_OpenALHandle*> pauseSounds; + std::list<AUD_Reference<AUD_OpenALHandle> > stopSounds; + std::list<AUD_Reference<AUD_OpenALHandle> > pauseSounds; AUD_HandleIterator it; while(1) @@ -151,83 +821,86 @@ void AUD_OpenALDevice::updateStreams() if(cerr == ALC_NO_ERROR) { // for all sounds - for(it = m_playingSounds->begin(); it != m_playingSounds->end(); it++) + for(it = m_playingSounds.begin(); it != m_playingSounds.end(); it++) { sound = *it; // is it a streamed sound? - if(!sound->isBuffered) + if(!sound->m_isBuffered) { // check for buffer refilling - alGetSourcei(sound->source, AL_BUFFERS_PROCESSED, &info); + alGetSourcei(sound->m_source, AL_BUFFERS_PROCESSED, &info); if(info) { - specs.specs = sound->reader->getSpecs(); + specs.specs = sound->m_reader->getSpecs(); + m_buffer.assureSize(m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs)); // for all empty buffers while(info--) { // if there's still data to play back - if(!sound->data_end) + if(!sound->m_eos) { // read data length = m_buffersize; - sound->reader->read(length, buffer); + sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer()); // looping necessary? - if(length == 0 && sound->loopcount) + if(length == 0 && sound->m_loopcount) { - if(sound->loopcount > 0) - sound->loopcount--; + if(sound->m_loopcount > 0) + sound->m_loopcount--; - sound->reader->seek(0); + sound->m_reader->seek(0); length = m_buffersize; - sound->reader->read(length, buffer); + sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer()); } + if(sound->m_loopcount != 0) + sound->m_eos = false; + // read nothing? if(length == 0) { - sound->data_end = true; break; } // unqueue buffer - alSourceUnqueueBuffers(sound->source, 1, - &sound->buffers[sound->current]); + alSourceUnqueueBuffers(sound->m_source, 1, + &sound->m_buffers[sound->m_current]); ALenum err; if((err = alGetError()) != AL_NO_ERROR) { - sound->data_end = true; + sound->m_eos = true; break; } // fill with new data - alBufferData(sound->buffers[sound->current], - sound->format, - buffer, length * + alBufferData(sound->m_buffers[sound->m_current], + sound->m_format, + m_buffer.getBuffer(), length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if((err = alGetError()) != AL_NO_ERROR) { - sound->data_end = true; + sound->m_eos = true; break; } // and queue again - alSourceQueueBuffers(sound->source, 1, - &sound->buffers[sound->current]); + alSourceQueueBuffers(sound->m_source, 1, + &sound->m_buffers[sound->m_current]); if(alGetError() != AL_NO_ERROR) { - sound->data_end = true; + sound->m_eos = true; break; } - sound->current = (sound->current+1) % - AUD_OPENAL_CYCLE_BUFFERS; + sound->m_current = (sound->m_current+1) % + AUD_OpenALHandle::CYCLE_BUFFERS; } else break; @@ -236,18 +909,18 @@ void AUD_OpenALDevice::updateStreams() } // check if the sound has been stopped - alGetSourcei(sound->source, AL_SOURCE_STATE, &info); + alGetSourcei(sound->m_source, AL_SOURCE_STATE, &info); if(info != AL_PLAYING) { // if it really stopped - if(sound->data_end) + if(sound->m_eos) { - if(sound->stop) - sound->stop(sound->stop_data); + if(sound->m_stop) + sound->m_stop(sound->m_stop_data); // pause or - if(sound->keep) + if(sound->m_keep) pauseSounds.push_back(sound); // stop else @@ -255,15 +928,15 @@ void AUD_OpenALDevice::updateStreams() } // continue playing else - alSourcePlay(sound->source); + alSourcePlay(sound->m_source); } } for(it = pauseSounds.begin(); it != pauseSounds.end(); it++) - pause(*it); + (*it)->pause(); for(it = stopSounds.begin(); it != stopSounds.end(); it++) - stop(*it); + (*it)->stop(); pauseSounds.clear(); stopSounds.clear(); @@ -272,7 +945,7 @@ void AUD_OpenALDevice::updateStreams() } // stop thread - if(m_playingSounds->empty() || (cerr != ALC_NO_ERROR)) + if(m_playingSounds.empty() || (cerr != ALC_NO_ERROR)) { m_playing = false; unlock(); @@ -293,19 +966,6 @@ void AUD_OpenALDevice::updateStreams() /**************************** IDevice Code ************************************/ /******************************************************************************/ -bool AUD_OpenALDevice::isValid(AUD_Handle* handle) -{ - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - if(*i == handle) - return true; - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - if(*i == handle) - return true; - return false; -} - static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened."; AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) @@ -358,9 +1018,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) m_buffersize = buffersize; m_playing = false; - m_playingSounds = new std::list<AUD_OpenALHandle*>(); - m_pausedSounds = new std::list<AUD_OpenALHandle*>(); - m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>(); +// m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>(); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -375,46 +1033,23 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) AUD_OpenALDevice::~AUD_OpenALDevice() { - AUD_OpenALHandle* sound; - lock(); alcSuspendContext(m_context); - // delete all playing sounds - while(!m_playingSounds->empty()) - { - sound = *(m_playingSounds->begin()); - alDeleteSources(1, &sound->source); - if(!sound->isBuffered) - { - delete sound->reader; - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - } - delete sound; - m_playingSounds->erase(m_playingSounds->begin()); - } + while(!m_playingSounds.empty()) + m_playingSounds.front()->stop(); + + while(!m_pausedSounds.empty()) + m_pausedSounds.front()->stop(); - // delete all paused sounds - while(!m_pausedSounds->empty()) - { - sound = *(m_pausedSounds->begin()); - alDeleteSources(1, &sound->source); - if(!sound->isBuffered) - { - delete sound->reader; - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - } - delete sound; - m_pausedSounds->erase(m_pausedSounds->begin()); - } // delete all buffered factories - while(!m_bufferedFactories->empty()) + /*while(!m_bufferedFactories->empty()) { alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer); delete *m_bufferedFactories->begin(); m_bufferedFactories->erase(m_bufferedFactories->begin()); - } + }*/ alcProcessContext(m_context); @@ -422,9 +1057,7 @@ AUD_OpenALDevice::~AUD_OpenALDevice() unlock(); pthread_join(m_thread, NULL); - delete m_playingSounds; - delete m_pausedSounds; - delete m_bufferedFactories; + //delete m_bufferedFactories; // quit OpenAL alcMakeContextCurrent(NULL); @@ -530,120 +1163,54 @@ 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_IReader* reader, bool keep) +AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) { - AUD_OpenALHandle* sound = NULL; - - AUD_DeviceSpecs specs = m_specs; - specs.specs = reader->getSpecs(); + AUD_Specs specs = reader->getSpecs(); // check format - bool valid = specs.channels != AUD_CHANNELS_INVALID; + if(specs.channels == AUD_CHANNELS_INVALID) + return AUD_Reference<AUD_IHandle>(); if(m_specs.format != AUD_FORMAT_FLOAT32) reader = new AUD_ConverterReader(reader, m_specs); - // create the 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; + ALenum format; - valid &= getFormat(sound->format, specs.specs); - - if(!valid) - { - delete sound; - delete reader; - return NULL; - } + if(!getFormat(format, specs)) + return AUD_Reference<AUD_IHandle>(); lock(); alcSuspendContext(m_context); - // OpenAL playback code + AUD_Reference<AUD_OpenALDevice::AUD_OpenALHandle> sound; + try { - alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error); - - try - { - sample_t* buf; - int length; - - for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++) - { - length = m_buffersize; - reader->read(length, buf); - alBufferData(sound->buffers[i], sound->format, buf, - length * AUD_DEVICE_SAMPLE_SIZE(specs), - specs.rate); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error); - } - - alGenSources(1, &sound->source); - if(alGetError() != AL_NO_ERROR) - 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, queue_error); - } - catch(AUD_Exception&) - { - alDeleteSources(1, &sound->source); - throw; - } - } - catch(AUD_Exception&) - { - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - throw; - } + // create the handle + sound = new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep); } catch(AUD_Exception&) { - delete sound; - delete reader; alcProcessContext(m_context); unlock(); throw; } + alcProcessContext(m_context); + // play sound - m_playingSounds->push_back(sound); - alSourcei(sound->source, AL_SOURCE_RELATIVE, 1); + m_playingSounds.push_back(sound); start(); - alcProcessContext(m_context); unlock(); - return sound; + return AUD_Reference<AUD_IHandle>(sound); } -AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) +AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) { + /* AUD_XXX disabled AUD_OpenALHandle* sound = NULL; lock(); @@ -661,7 +1228,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) sound->keep = keep; sound->current = -1; sound->isBuffered = true; - sound->data_end = true; + sound->eos = true; sound->loopcount = 0; sound->stop = NULL; sound->stop_data = NULL; @@ -713,264 +1280,24 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) unlock(); if(sound) - return sound; + return sound;*/ return play(factory->createReader(), keep); } -bool AUD_OpenALDevice::pause(AUD_Handle* handle) +void AUD_OpenALDevice::stopAll() { - bool result = false; - - lock(); - - // only songs that are played can be paused - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - { - if(*i == handle) - { - m_pausedSounds->push_back(*i); - alSourcePause((*i)->source); - m_playingSounds->erase(i); - result = true; - break; - } - } - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::resume(AUD_Handle* handle) -{ - bool result = false; - lock(); + alcSuspendContext(m_context); - // only songs that are paused can be resumed - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - { - if(*i == handle) - { - m_playingSounds->push_back(*i); - start(); - m_pausedSounds->erase(i); - result = true; - break; - } - } - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::stop(AUD_Handle* handle) -{ - AUD_OpenALHandle* sound; - - bool result = false; - - lock(); - - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - { - if(*i == handle) - { - sound = *i; - alDeleteSources(1, &sound->source); - if(!sound->isBuffered) - { - delete sound->reader; - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - } - delete *i; - m_playingSounds->erase(i); - result = true; - break; - } - } - if(!result) - { - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - { - if(*i == handle) - { - sound = *i; - alDeleteSources(1, &sound->source); - if(!sound->isBuffered) - { - delete sound->reader; - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - } - delete *i; - m_pausedSounds->erase(i); - result = true; - break; - } - } - } - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::getKeep(AUD_Handle* handle) -{ - bool result = false; - - lock(); - - if(isValid(handle)) - result = ((AUD_OpenALHandle*)handle)->keep; - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep) -{ - bool result = false; - - lock(); - - if(isValid(handle)) - { - ((AUD_OpenALHandle*)handle)->keep = keep; - result = true; - } - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position) -{ - bool result = false; - - lock(); - - if(isValid(handle)) - { - AUD_OpenALHandle* alhandle = (AUD_OpenALHandle*)handle; - if(alhandle->isBuffered) - alSourcef(alhandle->source, AL_SEC_OFFSET, position); - else - { - alhandle->reader->seek((int)(position * - alhandle->reader->getSpecs().rate)); - alhandle->data_end = false; - - ALint info; - - alGetSourcei(alhandle->source, AL_SOURCE_STATE, &info); - - if(info != AL_PLAYING) - { - if(info == AL_PAUSED) - alSourceStop(alhandle->source); - - alSourcei(alhandle->source, AL_BUFFER, 0); - alhandle->current = 0; - - ALenum err; - if((err = alGetError()) == AL_NO_ERROR) - { - sample_t* buf; - int length; - AUD_DeviceSpecs specs = m_specs; - specs.specs = alhandle->reader->getSpecs(); - - for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++) - { - length = m_buffersize; - alhandle->reader->read(length, buf); - alBufferData(alhandle->buffers[i], alhandle->format, - buf, - length * AUD_DEVICE_SAMPLE_SIZE(specs), - specs.rate); - - if(alGetError() != AL_NO_ERROR) - break; - } - - alSourceQueueBuffers(alhandle->source, - AUD_OPENAL_CYCLE_BUFFERS, - alhandle->buffers); - } - - alSourceRewind(alhandle->source); - } - } - result = true; - } - - unlock(); - return result; -} - -float AUD_OpenALDevice::getPosition(AUD_Handle* handle) -{ - float position = 0.0f; - - lock(); - - if(isValid(handle)) - { - AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle; - alGetSourcef(h->source, AL_SEC_OFFSET, &position); - if(!h->isBuffered) - { - AUD_Specs specs = h->reader->getSpecs(); - position += (h->reader->getPosition() - m_buffersize * - AUD_OPENAL_CYCLE_BUFFERS) / - (float)specs.rate; - } - } - - unlock(); - return position; -} - -AUD_Status AUD_OpenALDevice::getStatus(AUD_Handle* handle) -{ - AUD_Status status = AUD_STATUS_INVALID; + while(!m_playingSounds.empty()) + m_playingSounds.front()->stop(); - lock(); - - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - { - if(*i == handle) - { - status = AUD_STATUS_PLAYING; - break; - } - } - if(status == AUD_STATUS_INVALID) - { - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - { - if(*i == handle) - { - status = AUD_STATUS_PAUSED; - break; - } - } - } + while(!m_pausedSounds.empty()) + m_pausedSounds.front()->stop(); + alcProcessContext(m_context); unlock(); - - return status; } void AUD_OpenALDevice::lock() @@ -995,80 +1322,6 @@ void AUD_OpenALDevice::setVolume(float volume) 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::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) @@ -1109,7 +1362,6 @@ bool AUD_OpenALDevice::bufferFactory(void *value) if(!getFormat(format, specs.specs)) { - delete reader; return false; } @@ -1147,7 +1399,6 @@ bool AUD_OpenALDevice::bufferFactory(void *value) catch(AUD_Exception&) { delete bf; - delete reader; alcProcessContext(m_context); unlock(); return false; @@ -1219,8 +1470,7 @@ void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity) AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const { - // AUD_XXX not implemented yet - return AUD_Quaternion(0, 0, 0, 0); + return m_orientation; } void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation) @@ -1239,6 +1489,7 @@ void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation) direction[5] = 2 * (orientation.w() * orientation.x() + orientation.y() * orientation.z()); alListenerfv(AL_ORIENTATION, direction); + m_orientation = orientation; } float AUD_OpenALDevice::getSpeedOfSound() const @@ -1308,333 +1559,3 @@ void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model) 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; -} - -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()); - - unlock(); - return result; -} - -AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* 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::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, - (ALfloat*)velocity.get()); - - unlock(); - return result; -} - -AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle) -{ - // AUD_XXX not implemented yet - return AUD_Quaternion(0, 0, 0, 0); -} - -bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation) -{ - lock(); - bool result = isValid(handle); - - if(result) - { - 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::isRelative(AUD_Handle* handle) -{ - int result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - 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; -} - -float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - 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)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN, - &result); - - 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::getDistanceMaximum(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE, - &result); - - 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; -} |