forked from bartvdbraak/blender
c8f75fb5b1
Now sounds that stopped playing but are still kept in the device can be differentiated from paused sounds with this state. This should also fix the performance issues mentioned in [#36466] End of SequencerEntrys not set correctly. Please test if sound pausing, resuming and stopping works fine in the BGE and sequencer, my tests all worked fine, but there might be a use case that needs some fixing.
1630 lines
33 KiB
C++
1630 lines
33 KiB
C++
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* Copyright 2009-2011 Jörg Hermann Müller
|
|
*
|
|
* This file is part of AudaSpace.
|
|
*
|
|
* Audaspace is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* AudaSpace is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Audaspace; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
/** \file audaspace/OpenAL/AUD_OpenALDevice.cpp
|
|
* \ingroup audopenal
|
|
*/
|
|
|
|
|
|
#include "AUD_OpenALDevice.h"
|
|
#include "AUD_IFactory.h"
|
|
#include "AUD_IReader.h"
|
|
#include "AUD_ConverterReader.h"
|
|
#include "AUD_MutexLock.h"
|
|
|
|
#include <cstring>
|
|
#include <limits>
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
/*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.";
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::pause(bool keep)
|
|
{
|
|
if(m_status)
|
|
{
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(m_status == AUD_STATUS_PLAYING)
|
|
{
|
|
for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
|
|
{
|
|
if(it->get() == this)
|
|
{
|
|
boost::shared_ptr<AUD_OpenALHandle> This = *it;
|
|
|
|
m_device->m_playingSounds.erase(it);
|
|
m_device->m_pausedSounds.push_back(This);
|
|
|
|
alSourcePause(m_source);
|
|
|
|
m_status = keep ? AUD_STATUS_STOPPED : AUD_STATUS_PAUSED;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;}
|
|
|
|
AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, boost::shared_ptr<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)
|
|
{
|
|
AUD_DeviceSpecs specs = m_device->m_specs;
|
|
specs.specs = m_reader->getSpecs();
|
|
|
|
// OpenAL playback code
|
|
alGenBuffers(CYCLE_BUFFERS, m_buffers);
|
|
if(alGetError() != AL_NO_ERROR)
|
|
AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
|
|
|
|
try
|
|
{
|
|
m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
|
|
int length;
|
|
bool eos;
|
|
|
|
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);
|
|
}
|
|
|
|
alGenSources(1, &m_source);
|
|
if(alGetError() != AL_NO_ERROR)
|
|
AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
|
|
|
|
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);
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::pause()
|
|
{
|
|
return pause(false);
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::resume()
|
|
{
|
|
if(m_status)
|
|
{
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(m_status == AUD_STATUS_PAUSED)
|
|
{
|
|
for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++)
|
|
{
|
|
if(it->get() == this)
|
|
{
|
|
boost::shared_ptr<AUD_OpenALHandle> This = *it;
|
|
|
|
m_device->m_pausedSounds.erase(it);
|
|
m_device->m_playingSounds.push_back(This);
|
|
|
|
m_device->start();
|
|
m_status = AUD_STATUS_PLAYING;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::stop()
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
m_status = AUD_STATUS_INVALID;
|
|
|
|
alDeleteSources(1, &m_source);
|
|
if(!m_isBuffered)
|
|
alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
|
|
|
|
for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
|
|
{
|
|
if(it->get() == this)
|
|
{
|
|
boost::shared_ptr<AUD_OpenALHandle> This = *it;
|
|
|
|
m_device->m_playingSounds.erase(it);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++)
|
|
{
|
|
if(it->get() == this)
|
|
{
|
|
m_device->m_pausedSounds.erase(it);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
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;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
m_keep = keep;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
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;
|
|
|
|
alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers);
|
|
}
|
|
|
|
alSourceRewind(m_source);
|
|
}
|
|
}
|
|
|
|
if(m_status == AUD_STATUS_STOPPED)
|
|
m_status = AUD_STATUS_PAUSED;
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getPosition()
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return 0.0f;
|
|
|
|
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;
|
|
}
|
|
|
|
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 false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_GAIN, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_GAIN, volume);
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getPitch()
|
|
{
|
|
float result = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_PITCH, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_PITCH, pitch);
|
|
|
|
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;
|
|
|
|
if(m_status == AUD_STATUS_STOPPED && (count > m_loopcount || count < 0))
|
|
m_status = AUD_STATUS_PAUSED;
|
|
|
|
m_loopcount = count;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, void* data)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
m_stop = callback;
|
|
m_stop_data = data;
|
|
|
|
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 false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
ALfloat p[3];
|
|
alGetSourcefv(m_source, AL_POSITION, p);
|
|
|
|
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;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get());
|
|
|
|
return true;
|
|
}
|
|
|
|
AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity()
|
|
{
|
|
AUD_Vector3 result = AUD_Vector3(0, 0, 0);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
ALfloat v[3];
|
|
alGetSourcefv(m_source, AL_VELOCITY, v);
|
|
|
|
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;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get());
|
|
|
|
return true;
|
|
}
|
|
|
|
AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation()
|
|
{
|
|
return m_orientation;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation)
|
|
{
|
|
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;
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcefv(m_source, AL_DIRECTION, direction);
|
|
|
|
m_orientation = orientation;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative()
|
|
{
|
|
int result;
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcei(m_source, AL_SOURCE_RELATIVE, relative);
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum()
|
|
{
|
|
float result = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_MAX_GAIN, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_MAX_GAIN, volume);
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum()
|
|
{
|
|
float result = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_MIN_GAIN, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_MIN_GAIN, volume);
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum()
|
|
{
|
|
float result = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_MAX_DISTANCE, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_MAX_DISTANCE, distance);
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference()
|
|
{
|
|
float result = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_REFERENCE_DISTANCE, distance);
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation()
|
|
{
|
|
float result = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_ROLLOFF_FACTOR, factor);
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter()
|
|
{
|
|
float result = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle);
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner()
|
|
{
|
|
float result = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_CONE_INNER_ANGLE, angle);
|
|
|
|
return true;
|
|
}
|
|
|
|
float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter()
|
|
{
|
|
float result = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return result;
|
|
|
|
alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume)
|
|
{
|
|
if(!m_status)
|
|
return false;
|
|
|
|
AUD_MutexLock lock(*m_device);
|
|
|
|
if(!m_status)
|
|
return false;
|
|
|
|
alSourcef(m_source, AL_CONE_OUTER_GAIN, volume);
|
|
|
|
return true;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**************************** Threading Code **********************************/
|
|
/******************************************************************************/
|
|
|
|
static void *AUD_openalRunThread(void *device)
|
|
{
|
|
AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device;
|
|
dev->updateStreams();
|
|
return NULL;
|
|
}
|
|
|
|
void AUD_OpenALDevice::start(bool join)
|
|
{
|
|
AUD_MutexLock lock(*this);
|
|
|
|
if(!m_playing)
|
|
{
|
|
if(join)
|
|
pthread_join(m_thread, NULL);
|
|
|
|
pthread_attr_t attr;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
|
|
pthread_create(&m_thread, &attr, AUD_openalRunThread, this);
|
|
|
|
pthread_attr_destroy(&attr);
|
|
|
|
m_playing = true;
|
|
}
|
|
}
|
|
|
|
void AUD_OpenALDevice::updateStreams()
|
|
{
|
|
boost::shared_ptr<AUD_OpenALHandle> sound;
|
|
|
|
int length;
|
|
|
|
ALint info;
|
|
AUD_DeviceSpecs specs = m_specs;
|
|
ALCenum cerr;
|
|
std::list<boost::shared_ptr<AUD_OpenALHandle> > stopSounds;
|
|
std::list<boost::shared_ptr<AUD_OpenALHandle> > pauseSounds;
|
|
AUD_HandleIterator it;
|
|
|
|
while(1)
|
|
{
|
|
lock();
|
|
|
|
alcSuspendContext(m_context);
|
|
cerr = alcGetError(m_device);
|
|
if(cerr == ALC_NO_ERROR)
|
|
{
|
|
// for all sounds
|
|
for(it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
|
|
{
|
|
sound = *it;
|
|
|
|
// is it a streamed sound?
|
|
if(!sound->m_isBuffered)
|
|
{
|
|
// check for buffer refilling
|
|
alGetSourcei(sound->m_source, AL_BUFFERS_PROCESSED, &info);
|
|
|
|
if(info)
|
|
{
|
|
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->m_eos)
|
|
{
|
|
// read data
|
|
length = m_buffersize;
|
|
sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
|
|
|
|
// looping necessary?
|
|
if(length == 0 && sound->m_loopcount)
|
|
{
|
|
if(sound->m_loopcount > 0)
|
|
sound->m_loopcount--;
|
|
|
|
sound->m_reader->seek(0);
|
|
|
|
length = m_buffersize;
|
|
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)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// unqueue buffer
|
|
alSourceUnqueueBuffers(sound->m_source, 1,
|
|
&sound->m_buffers[sound->m_current]);
|
|
ALenum err;
|
|
if((err = alGetError()) != AL_NO_ERROR)
|
|
{
|
|
sound->m_eos = true;
|
|
break;
|
|
}
|
|
|
|
// fill with new data
|
|
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->m_eos = true;
|
|
break;
|
|
}
|
|
|
|
// and queue again
|
|
alSourceQueueBuffers(sound->m_source, 1,
|
|
&sound->m_buffers[sound->m_current]);
|
|
if(alGetError() != AL_NO_ERROR)
|
|
{
|
|
sound->m_eos = true;
|
|
break;
|
|
}
|
|
|
|
sound->m_current = (sound->m_current+1) %
|
|
AUD_OpenALHandle::CYCLE_BUFFERS;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if the sound has been stopped
|
|
alGetSourcei(sound->m_source, AL_SOURCE_STATE, &info);
|
|
|
|
if(info != AL_PLAYING)
|
|
{
|
|
// if it really stopped
|
|
if(sound->m_eos)
|
|
{
|
|
if(sound->m_stop)
|
|
sound->m_stop(sound->m_stop_data);
|
|
|
|
// pause or
|
|
if(sound->m_keep)
|
|
pauseSounds.push_back(sound);
|
|
// stop
|
|
else
|
|
stopSounds.push_back(sound);
|
|
}
|
|
// continue playing
|
|
else
|
|
alSourcePlay(sound->m_source);
|
|
}
|
|
}
|
|
|
|
for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
|
|
(*it)->pause(true);
|
|
|
|
for(it = stopSounds.begin(); it != stopSounds.end(); it++)
|
|
(*it)->stop();
|
|
|
|
pauseSounds.clear();
|
|
stopSounds.clear();
|
|
|
|
alcProcessContext(m_context);
|
|
}
|
|
|
|
// stop thread
|
|
if(m_playingSounds.empty() || (cerr != ALC_NO_ERROR))
|
|
{
|
|
m_playing = false;
|
|
unlock();
|
|
pthread_exit(NULL);
|
|
}
|
|
|
|
unlock();
|
|
|
|
#ifdef WIN32
|
|
Sleep(20);
|
|
#else
|
|
usleep(20000);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**************************** IDevice Code ************************************/
|
|
/******************************************************************************/
|
|
|
|
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
|
|
// it at least is able to play 16 bit stereo audio
|
|
specs.format = AUD_FORMAT_S16;
|
|
|
|
#if 0
|
|
if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
|
|
{
|
|
ALCchar* devices = const_cast<ALCchar*>(alcGetString(NULL, ALC_DEVICE_SPECIFIER));
|
|
printf("OpenAL devices (standard is: %s):\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
|
|
|
|
while(*devices)
|
|
{
|
|
printf("%s\n", devices);
|
|
devices += strlen(devices) + 1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
m_device = alcOpenDevice(NULL);
|
|
|
|
if(!m_device)
|
|
AUD_THROW(AUD_ERROR_OPENAL, open_error);
|
|
|
|
// at least try to set the frequency
|
|
ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 };
|
|
ALCint* attributes = attribs;
|
|
if(specs.rate == AUD_RATE_INVALID)
|
|
attributes = NULL;
|
|
|
|
m_context = alcCreateContext(m_device, attributes);
|
|
alcMakeContextCurrent(m_context);
|
|
|
|
alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
|
|
|
|
// check for specific formats and channel counts to be played back
|
|
if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
|
|
specs.format = AUD_FORMAT_FLOAT32;
|
|
|
|
m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
|
|
|
|
if((!m_useMC && specs.channels > AUD_CHANNELS_STEREO) ||
|
|
specs.channels == AUD_CHANNELS_STEREO_LFE ||
|
|
specs.channels == AUD_CHANNELS_SURROUND5)
|
|
specs.channels = AUD_CHANNELS_STEREO;
|
|
|
|
alGetError();
|
|
alcGetError(m_device);
|
|
|
|
m_specs = specs;
|
|
m_buffersize = buffersize;
|
|
m_playing = false;
|
|
|
|
// m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
|
|
|
|
pthread_mutexattr_t attr;
|
|
pthread_mutexattr_init(&attr);
|
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
|
|
|
pthread_mutex_init(&m_mutex, &attr);
|
|
|
|
pthread_mutexattr_destroy(&attr);
|
|
|
|
start(false);
|
|
}
|
|
|
|
AUD_OpenALDevice::~AUD_OpenALDevice()
|
|
{
|
|
lock();
|
|
alcSuspendContext(m_context);
|
|
|
|
while(!m_playingSounds.empty())
|
|
m_playingSounds.front()->stop();
|
|
|
|
while(!m_pausedSounds.empty())
|
|
m_pausedSounds.front()->stop();
|
|
|
|
|
|
// delete all buffered factories
|
|
/*while(!m_bufferedFactories->empty())
|
|
{
|
|
alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
|
|
delete *m_bufferedFactories->begin();
|
|
m_bufferedFactories->erase(m_bufferedFactories->begin());
|
|
}*/
|
|
|
|
alcProcessContext(m_context);
|
|
|
|
// wait for the thread to stop
|
|
unlock();
|
|
pthread_join(m_thread, NULL);
|
|
|
|
//delete m_bufferedFactories;
|
|
|
|
// quit OpenAL
|
|
alcMakeContextCurrent(NULL);
|
|
alcDestroyContext(m_context);
|
|
alcCloseDevice(m_device);
|
|
|
|
pthread_mutex_destroy(&m_mutex);
|
|
}
|
|
|
|
AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const
|
|
{
|
|
return m_specs;
|
|
}
|
|
|
|
bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
|
|
{
|
|
bool valid = true;
|
|
format = 0;
|
|
|
|
switch(m_specs.format)
|
|
{
|
|
case AUD_FORMAT_S16:
|
|
switch(specs.channels)
|
|
{
|
|
case AUD_CHANNELS_MONO:
|
|
format = AL_FORMAT_MONO16;
|
|
break;
|
|
case AUD_CHANNELS_STEREO:
|
|
format = AL_FORMAT_STEREO16;
|
|
break;
|
|
case AUD_CHANNELS_SURROUND4:
|
|
if(m_useMC)
|
|
{
|
|
format = alGetEnumValue("AL_FORMAT_QUAD16");
|
|
break;
|
|
}
|
|
case AUD_CHANNELS_SURROUND51:
|
|
if(m_useMC)
|
|
{
|
|
format = alGetEnumValue("AL_FORMAT_51CHN16");
|
|
break;
|
|
}
|
|
case AUD_CHANNELS_SURROUND61:
|
|
if(m_useMC)
|
|
{
|
|
format = alGetEnumValue("AL_FORMAT_61CHN16");
|
|
break;
|
|
}
|
|
case AUD_CHANNELS_SURROUND71:
|
|
if(m_useMC)
|
|
{
|
|
format = alGetEnumValue("AL_FORMAT_71CHN16");
|
|
break;
|
|
}
|
|
default:
|
|
valid = false;
|
|
}
|
|
break;
|
|
case AUD_FORMAT_FLOAT32:
|
|
switch(specs.channels)
|
|
{
|
|
case AUD_CHANNELS_MONO:
|
|
format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
|
|
break;
|
|
case AUD_CHANNELS_STEREO:
|
|
format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
|
|
break;
|
|
case AUD_CHANNELS_SURROUND4:
|
|
if(m_useMC)
|
|
{
|
|
format = alGetEnumValue("AL_FORMAT_QUAD32");
|
|
break;
|
|
}
|
|
case AUD_CHANNELS_SURROUND51:
|
|
if(m_useMC)
|
|
{
|
|
format = alGetEnumValue("AL_FORMAT_51CHN32");
|
|
break;
|
|
}
|
|
case AUD_CHANNELS_SURROUND61:
|
|
if(m_useMC)
|
|
{
|
|
format = alGetEnumValue("AL_FORMAT_61CHN32");
|
|
break;
|
|
}
|
|
case AUD_CHANNELS_SURROUND71:
|
|
if(m_useMC)
|
|
{
|
|
format = alGetEnumValue("AL_FORMAT_71CHN32");
|
|
break;
|
|
}
|
|
default:
|
|
valid = false;
|
|
}
|
|
break;
|
|
default:
|
|
valid = false;
|
|
}
|
|
|
|
if(!format)
|
|
valid = false;
|
|
|
|
return valid;
|
|
}
|
|
|
|
boost::shared_ptr<AUD_IHandle> AUD_OpenALDevice::play(boost::shared_ptr<AUD_IReader> reader, bool keep)
|
|
{
|
|
AUD_Specs specs = reader->getSpecs();
|
|
|
|
// check format
|
|
if(specs.channels == AUD_CHANNELS_INVALID)
|
|
return boost::shared_ptr<AUD_IHandle>();
|
|
|
|
if(m_specs.format != AUD_FORMAT_FLOAT32)
|
|
reader = boost::shared_ptr<AUD_IReader>(new AUD_ConverterReader(reader, m_specs));
|
|
|
|
ALenum format;
|
|
|
|
if(!getFormat(format, specs))
|
|
return boost::shared_ptr<AUD_IHandle>();
|
|
|
|
AUD_MutexLock lock(*this);
|
|
|
|
alcSuspendContext(m_context);
|
|
|
|
boost::shared_ptr<AUD_OpenALDevice::AUD_OpenALHandle> sound;
|
|
|
|
try
|
|
{
|
|
// create the handle
|
|
sound = boost::shared_ptr<AUD_OpenALDevice::AUD_OpenALHandle>(new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep));
|
|
}
|
|
catch(AUD_Exception&)
|
|
{
|
|
alcProcessContext(m_context);
|
|
throw;
|
|
}
|
|
|
|
alcProcessContext(m_context);
|
|
|
|
// play sound
|
|
m_playingSounds.push_back(sound);
|
|
|
|
start();
|
|
|
|
return boost::shared_ptr<AUD_IHandle>(sound);
|
|
}
|
|
|
|
boost::shared_ptr<AUD_IHandle> AUD_OpenALDevice::play(boost::shared_ptr<AUD_IFactory> factory, bool keep)
|
|
{
|
|
/* AUD_XXX disabled
|
|
AUD_OpenALHandle* sound = NULL;
|
|
|
|
lock();
|
|
|
|
try
|
|
{
|
|
// check if it is a buffered factory
|
|
for(AUD_BFIterator i = m_bufferedFactories->begin();
|
|
i != m_bufferedFactories->end(); i++)
|
|
{
|
|
if((*i)->factory == factory)
|
|
{
|
|
// create the handle
|
|
sound = new AUD_OpenALHandle;
|
|
sound->keep = keep;
|
|
sound->current = -1;
|
|
sound->isBuffered = true;
|
|
sound->eos = true;
|
|
sound->loopcount = 0;
|
|
sound->stop = NULL;
|
|
sound->stop_data = NULL;
|
|
|
|
alcSuspendContext(m_context);
|
|
|
|
// OpenAL playback code
|
|
try
|
|
{
|
|
alGenSources(1, &sound->source);
|
|
if(alGetError() != AL_NO_ERROR)
|
|
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, queue_error);
|
|
}
|
|
catch(AUD_Exception&)
|
|
{
|
|
alDeleteSources(1, &sound->source);
|
|
throw;
|
|
}
|
|
}
|
|
catch(AUD_Exception&)
|
|
{
|
|
delete sound;
|
|
alcProcessContext(m_context);
|
|
throw;
|
|
}
|
|
|
|
// play sound
|
|
m_playingSounds->push_back(sound);
|
|
|
|
alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
|
|
start();
|
|
|
|
alcProcessContext(m_context);
|
|
}
|
|
}
|
|
}
|
|
catch(AUD_Exception&)
|
|
{
|
|
unlock();
|
|
throw;
|
|
}
|
|
|
|
unlock();
|
|
|
|
if(sound)
|
|
return sound;*/
|
|
|
|
return play(factory->createReader(), keep);
|
|
}
|
|
|
|
void AUD_OpenALDevice::stopAll()
|
|
{
|
|
AUD_MutexLock lock(*this);
|
|
|
|
alcSuspendContext(m_context);
|
|
|
|
while(!m_playingSounds.empty())
|
|
m_playingSounds.front()->stop();
|
|
|
|
while(!m_pausedSounds.empty())
|
|
m_pausedSounds.front()->stop();
|
|
|
|
alcProcessContext(m_context);
|
|
}
|
|
|
|
void AUD_OpenALDevice::lock()
|
|
{
|
|
pthread_mutex_lock(&m_mutex);
|
|
}
|
|
|
|
void AUD_OpenALDevice::unlock()
|
|
{
|
|
pthread_mutex_unlock(&m_mutex);
|
|
}
|
|
|
|
float AUD_OpenALDevice::getVolume() const
|
|
{
|
|
float result;
|
|
alGetListenerf(AL_GAIN, &result);
|
|
return result;
|
|
}
|
|
|
|
void AUD_OpenALDevice::setVolume(float volume)
|
|
{
|
|
alListenerf(AL_GAIN, volume);
|
|
}
|
|
|
|
/* AUD_XXX Temorary disabled
|
|
|
|
bool AUD_OpenALDevice::bufferFactory(void *value)
|
|
{
|
|
bool result = false;
|
|
AUD_IFactory* factory = (AUD_IFactory*) value;
|
|
|
|
// load the factory into an OpenAL buffer
|
|
if(factory)
|
|
{
|
|
// 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;
|
|
|
|
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))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// load into a buffer
|
|
lock();
|
|
alcSuspendContext(m_context);
|
|
|
|
AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory;
|
|
bf->factory = factory;
|
|
|
|
try
|
|
{
|
|
alGenBuffers(1, &bf->buffer);
|
|
if(alGetError() != AL_NO_ERROR)
|
|
AUD_THROW(AUD_ERROR_OPENAL);
|
|
|
|
try
|
|
{
|
|
sample_t* buf;
|
|
int length = reader->getLength();
|
|
|
|
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;
|
|
alcProcessContext(m_context);
|
|
unlock();
|
|
return false;
|
|
}
|
|
|
|
m_bufferedFactories->push_back(bf);
|
|
|
|
alcProcessContext(m_context);
|
|
unlock();
|
|
}
|
|
else
|
|
{
|
|
// stop all playing and paused buffered sources
|
|
lock();
|
|
alcSuspendContext(m_context);
|
|
|
|
AUD_OpenALHandle* sound;
|
|
AUD_HandleIterator it = m_playingSounds->begin();
|
|
while(it != m_playingSounds->end())
|
|
{
|
|
sound = *it;
|
|
++it;
|
|
|
|
if(sound->isBuffered)
|
|
stop(sound);
|
|
}
|
|
alcProcessContext(m_context);
|
|
|
|
while(!m_bufferedFactories->empty())
|
|
{
|
|
alDeleteBuffers(1,
|
|
&(*(m_bufferedFactories->begin()))->buffer);
|
|
delete *m_bufferedFactories->begin();
|
|
m_bufferedFactories->erase(m_bufferedFactories->begin());
|
|
}
|
|
unlock();
|
|
}
|
|
|
|
return true;
|
|
}*/
|
|
|
|
/******************************************************************************/
|
|
/**************************** 3D Device Code **********************************/
|
|
/******************************************************************************/
|
|
|
|
AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const
|
|
{
|
|
ALfloat p[3];
|
|
alGetListenerfv(AL_POSITION, p);
|
|
return AUD_Vector3(p[0], p[1], p[2]);
|
|
}
|
|
|
|
void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location)
|
|
{
|
|
alListenerfv(AL_POSITION, (ALfloat*)location.get());
|
|
}
|
|
|
|
AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const
|
|
{
|
|
ALfloat v[3];
|
|
alGetListenerfv(AL_VELOCITY, v);
|
|
return AUD_Vector3(v[0], v[1], v[2]);
|
|
}
|
|
|
|
void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity)
|
|
{
|
|
alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get());
|
|
}
|
|
|
|
AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const
|
|
{
|
|
return m_orientation;
|
|
}
|
|
|
|
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);
|
|
m_orientation = orientation;
|
|
}
|
|
|
|
float AUD_OpenALDevice::getSpeedOfSound() const
|
|
{
|
|
return alGetFloat(AL_SPEED_OF_SOUND);
|
|
}
|
|
|
|
void AUD_OpenALDevice::setSpeedOfSound(float speed)
|
|
{
|
|
alSpeedOfSound(speed);
|
|
}
|
|
|
|
float AUD_OpenALDevice::getDopplerFactor() const
|
|
{
|
|
return alGetFloat(AL_DOPPLER_FACTOR);
|
|
}
|
|
|
|
void AUD_OpenALDevice::setDopplerFactor(float factor)
|
|
{
|
|
alDopplerFactor(factor);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model)
|
|
{
|
|
switch(model)
|
|
{
|
|
case AUD_DISTANCE_MODEL_INVERSE:
|
|
alDistanceModel(AL_INVERSE_DISTANCE);
|
|
break;
|
|
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);
|
|
}
|
|
}
|