3D Audio GSoC:

Software 3D Audio implementation.
This commit is contained in:
Joerg Mueller 2011-07-12 13:11:00 +00:00
parent d9cf985730
commit 208b69e3a7
6 changed files with 784 additions and 90 deletions

@ -492,10 +492,10 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaterni
bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative()
{
int result = std::numeric_limits<float>::quiet_NaN();
int result;
if(!m_status)
return result;
return false;
m_device->lock();

@ -32,6 +32,128 @@
#ifndef AUD_3DMATH
#define AUD_3DMATH
#include <cmath>
class AUD_Vector3
{
private:
union
{
float m_v[3];
struct
{
float m_x;
float m_y;
float m_z;
};
};
public:
/**
* Creates a new 3 dimensional vector.
* \param x The x component.
* \param y The y component.
* \param z The z component.
*/
inline AUD_Vector3(float x = 0, float y = 0, float z = 0) :
m_x(x), m_y(y), m_z(z)
{
}
/**
* Retrieves the x component of the vector.
* \return The x component.
*/
inline const float& x() const
{
return m_x;
}
/**
* Retrieves the y component of the vector.
* \return The y component.
*/
inline const float& y() const
{
return m_y;
}
/**
* Retrieves the z component of the vector.
* \return The z component.
*/
inline const float& z() const
{
return m_z;
}
/**
* Retrieves the components of the vector.
* \param destination Where the 3 float values should be saved to.
*/
inline void get(float* destination) const
{
destination[0] = m_x;
destination[1] = m_y;
destination[2] = m_z;
}
/**
* Retrieves the components of the vector.
* \return The components as float[3].
*/
inline const float* get() const
{
return m_v;
}
/**
* Retrieves the length of the vector.
* \return The length of the vector.
*/
inline float length() const
{
return sqrt(m_x*m_x + m_y*m_y + m_z*m_z);
}
inline AUD_Vector3 cross(const AUD_Vector3& op) const
{
return AUD_Vector3(m_y * op.m_z - m_z * op.m_y,
m_z * op.m_x - m_x * op.m_z,
m_x * op.m_y - m_y * op.m_x);
}
/**
* Retrieves the dot product.
* \param op The second operand.
* \return The dot product of the two vectors.
*/
inline float operator*(const AUD_Vector3& op) const
{
return m_x * op.m_x + m_y * op.m_y + m_z * op.m_z;
}
inline AUD_Vector3 operator*(const float& op) const
{
return AUD_Vector3(m_x * op, m_y * op, m_z * op);
}
inline AUD_Vector3 operator+(const AUD_Vector3& op) const
{
return AUD_Vector3(m_x + op.m_x, m_y + op.m_y, m_z + op.m_z);
}
inline AUD_Vector3 operator-(const AUD_Vector3& op) const
{
return AUD_Vector3(m_x - op.m_x, m_y - op.m_y, m_z - op.m_z);
}
inline AUD_Vector3 operator-() const
{
return AUD_Vector3(-m_x, -m_y, -m_z);
}
};
class AUD_Quaternion
{
private:
@ -55,7 +177,7 @@ public:
* \param y The y component.
* \param z The z component.
*/
inline AUD_Quaternion(float w, float x, float y, float z) :
inline AUD_Quaternion(float w = 1, float x = 0, float y = 0, float z = 0) :
m_w(w), m_x(x), m_y(y), m_z(z)
{
}
@ -116,79 +238,19 @@ public:
{
return m_v;
}
};
class AUD_Vector3
{
private:
union
{
float m_v[3];
struct
{
float m_x;
float m_y;
float m_z;
};
};
public:
/**
* Creates a new 3 dimensional vector.
* \param x The x component.
* \param y The y component.
* \param z The z component.
*/
inline AUD_Vector3(float x, float y, float z) :
m_x(x), m_y(y), m_z(z)
inline AUD_Vector3 getLookAt() const
{
return AUD_Vector3(-2 * (m_w * m_y + m_x * m_z),
2 * (m_x * m_w - m_z * m_y),
2 * (m_x * m_x + m_y * m_y) - 1);
}
/**
* Retrieves the x component of the vector.
* \return The x component.
*/
inline const float& x() const
inline AUD_Vector3 getUp() const
{
return m_x;
}
/**
* Retrieves the y component of the vector.
* \return The y component.
*/
inline const float& y() const
{
return m_y;
}
/**
* Retrieves the z component of the vector.
* \return The z component.
*/
inline const float& z() const
{
return m_z;
}
/**
* Retrieves the components of the vector.
* \param destination Where the 3 float values should be saved to.
*/
inline void get(float* destination) const
{
destination[0] = m_x;
destination[1] = m_y;
destination[2] = m_z;
}
/**
* Retrieves the components of the vector.
* \return The components as float[3].
*/
inline const float* get() const
{
return m_v;
return AUD_Vector3(2 * (m_x * m_y - m_w * m_z),
1 - 2 * (m_x * m_x + m_z * m_z),
2 * (m_w * m_x + m_y * m_z));
}
};

@ -43,7 +43,7 @@
AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader,
AUD_Channels channels) :
AUD_EffectReader(reader), m_target_channels(channels),
m_source_channels(AUD_CHANNELS_INVALID), m_mapping(0)
m_source_channels(AUD_CHANNELS_INVALID), m_mapping(0), m_map_size(0), m_mono_angle(0)
{
}
@ -58,6 +58,13 @@ void AUD_ChannelMapperReader::setChannels(AUD_Channels channels)
calculateMapping();
}
void AUD_ChannelMapperReader::setMonoAngle(float angle)
{
m_mono_angle = angle;
if(m_source_channels == AUD_CHANNELS_MONO)
calculateMapping();
}
float AUD_ChannelMapperReader::angleDistance(float alpha, float beta)
{
alpha = fabs(alpha - beta);
@ -68,10 +75,19 @@ float AUD_ChannelMapperReader::angleDistance(float alpha, float beta)
return alpha;
}
#include <iostream>
void AUD_ChannelMapperReader::calculateMapping()
{
delete[] m_mapping;
m_mapping = new float[m_source_channels * m_target_channels];
if(m_map_size < m_source_channels * m_target_channels)
{
delete[] m_mapping;
m_mapping = new float[m_source_channels * m_target_channels];
m_map_size = m_source_channels * m_target_channels;
}
for(int i = 0; i < m_source_channels * m_target_channels; i++)
m_mapping[i] = 0;
const AUD_Channel* source_channels = CHANNEL_MAPS[m_source_channels - 1];
const AUD_Channel* target_channels = CHANNEL_MAPS[m_target_channels - 1];
@ -90,6 +106,9 @@ void AUD_ChannelMapperReader::calculateMapping()
const float* source_angles = CHANNEL_ANGLES[m_source_channels - 1];
const float* target_angles = CHANNEL_ANGLES[m_target_channels - 1];
if(m_source_channels == AUD_CHANNELS_MONO)
source_angles = &m_mono_angle;
int channel_min1, channel_min2;
float angle_min1, angle_min2, angle;
@ -124,17 +143,26 @@ void AUD_ChannelMapperReader::calculateMapping()
}
}
if(channel_min2 == -1)
angle = angle_min1 + angle_min2;
if(channel_min2 == -1 || angle == 0)
{
m_mapping[channel_min1 * m_source_channels + i] = 1;
}
else
{
angle = angle_min1 + angle_min2;
m_mapping[channel_min1 * m_source_channels + i] = cos(M_PI_2 * angle_min1 / angle);
m_mapping[channel_min2 * m_source_channels + i] = cos(M_PI_2 * angle_min2 / angle);
}
}
/* AUD_XXX for(int i = 0; i < m_source_channels; i++)
{
for(int j = 0; j < m_target_channels; j++)
{
std::cout << m_mapping[i * m_source_channels + j] << " ";
}
std::cout << std::endl;
}*/
}
AUD_Specs AUD_ChannelMapperReader::getSpecs() const

@ -62,6 +62,16 @@ private:
*/
float* m_mapping;
/**
* The size of the mapping.
*/
int m_map_size;
/**
* The mono source angle.
*/
float m_mono_angle;
static const AUD_Channel MONO_MAP[];
static const AUD_Channel STEREO_MAP[];
static const AUD_Channel STEREO_LFE_MAP[];
@ -111,6 +121,8 @@ public:
void setChannels(AUD_Channels channels);
void setMonoAngle(float angle);
virtual AUD_Specs getSpecs() const;
virtual void read(int& length, bool& eos, sample_t* buffer);
};

@ -38,15 +38,178 @@
#else
#include "AUD_LinearResampleReader.h"
#endif
#include "AUD_ChannelMapperReader.h"
#include <cstring>
#include <cmath>
#include <limits>
AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, bool keep) :
m_reader(reader), m_pitch(pitch), m_keep(keep), m_volume(1.0f), m_loopcount(0),
m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device)
typedef enum
{
AUD_RENDER_DISTANCE = 0x01,
AUD_RENDER_DOPPLER = 0x02,
AUD_RENDER_CONE = 0x04,
AUD_RENDER_VOLUME = 0x08
} AUD_RenderFlags;
#define AUD_PITCH_MAX 10
/******************************************************************************/
/********************** AUD_SoftwareHandle Handle Code ************************/
/******************************************************************************/
AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep) :
m_reader(reader), m_pitch(pitch), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_volume(1.0f), m_loopcount(0),
m_relative(false), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0),
m_flags(AUD_RENDER_CONE), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device)
{
}
#include <iostream>
void AUD_SoftwareDevice::AUD_SoftwareHandle::update()
{
int flags = 0;
AUD_Vector3 SL;
if(m_relative)
SL = m_location;
else
SL = m_device->m_location - m_location;
float distance = SL * SL;
if(distance > 0)
distance = sqrt(distance);
else
flags |= AUD_RENDER_DOPPLER | AUD_RENDER_DISTANCE;
if(m_pitch->getSpecs().channels != AUD_CHANNELS_MONO)
{
m_volume = m_user_volume;
m_pitch->setPitch(m_user_pitch);
return;
}
flags = ~(flags | m_flags | m_device->m_flags);
// Doppler and Pitch
if(flags & AUD_RENDER_DOPPLER)
{
float vls;
if(m_relative)
vls = 0;
else
vls = SL * m_device->m_velocity / distance;
float vss = SL * m_velocity / distance;
float max = m_device->m_speed_of_sound / m_device->m_doppler_factor;
if(vss >= max)
{
m_pitch->setPitch(AUD_PITCH_MAX);
}
else
{
if(vls > max)
vls = max;
m_pitch->setPitch((m_device->m_speed_of_sound - m_device->m_doppler_factor * vls) / (m_device->m_speed_of_sound - m_device->m_doppler_factor * vss) * m_user_pitch);
}
}
else
m_pitch->setPitch(m_user_pitch);
if(flags & AUD_RENDER_VOLUME)
{
// Distance
if(flags & AUD_RENDER_DISTANCE)
{
if(m_device->m_distance_model == AUD_DISTANCE_MODEL_INVERSE_CLAMPED || m_device->m_distance_model == AUD_DISTANCE_MODEL_LINEAR_CLAMPED || m_device->m_distance_model == AUD_DISTANCE_MODEL_EXPONENT_CLAMPED)
{
distance = AUD_MAX(AUD_MIN(m_distance_max, distance), m_distance_reference);
}
switch(m_device->m_distance_model)
{
case AUD_DISTANCE_MODEL_INVERSE:
case AUD_DISTANCE_MODEL_INVERSE_CLAMPED:
m_volume = m_distance_reference / (m_distance_reference + m_attenuation * (distance - m_distance_reference));
break;
case AUD_DISTANCE_MODEL_LINEAR:
case AUD_DISTANCE_MODEL_LINEAR_CLAMPED:
{
float temp = m_distance_max - m_distance_reference;
if(temp == 0)
{
if(distance > m_distance_reference)
m_volume = 0.0f;
else
m_volume = 1.0f;
}
else
m_volume = 1.0f - m_attenuation * (distance - m_distance_reference) / (m_distance_max - m_distance_reference);
break;
}
case AUD_DISTANCE_MODEL_EXPONENT:
case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED:
if(m_distance_reference == 0)
m_volume = 0;
else
m_volume = pow(distance / m_distance_reference, -m_attenuation);
break;
default:
m_volume = 1.0f;
}
}
else
m_volume = 1.0f;
// Cone
if(flags & AUD_RENDER_CONE)
{
AUD_Vector3 SZ = m_orientation.getLookAt();
float phi = acos(SZ * SL / (SZ.length() * SL.length()));
float t = (phi - m_cone_angle_inner)/(m_cone_angle_outer - m_cone_angle_inner);
if(t > 0)
{
if(t > 1)
m_volume *= m_cone_volume_outer;
else
m_volume *= 1 + t * (m_cone_volume_outer - 1);
}
}
// Volume
m_volume *= m_user_volume;
}
// 3D Cue
AUD_Quaternion orientation;
if(!m_relative)
orientation = m_device->m_orientation;
AUD_Vector3 Z = orientation.getLookAt();
AUD_Vector3 N = orientation.getUp();
AUD_Vector3 A = N * ((SL * N) / (N * N)) - SL;
float Asquare = A * A;
if(Asquare > 0)
{
float phi = acos(Z * A/ (Z.length() * sqrt(Asquare)));
if(N.cross(Z) * A > 0)
phi = -phi;
m_mapper->setMonoAngle(phi);
}
else
m_mapper->setMonoAngle(0);
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause()
@ -177,25 +340,36 @@ AUD_Status AUD_SoftwareDevice::AUD_SoftwareHandle::getStatus()
float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolume()
{
return m_volume;
return m_user_volume;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolume(float volume)
{
if(!m_status)
return false;
m_volume = volume;
m_user_volume = volume;
if(volume == 0)
{
m_volume = volume;
m_flags |= AUD_RENDER_VOLUME;
}
else
m_flags &= ~AUD_RENDER_VOLUME;
return true;
}
float AUD_SoftwareDevice::AUD_SoftwareHandle::getPitch()
{
return m_pitch->getPitch();
return m_user_pitch;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setPitch(float pitch)
{
m_pitch->setPitch(pitch);
if(!m_status)
return false;
m_user_pitch = pitch;
return true;
}
@ -231,19 +405,249 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setStopCallback(stopCallback callba
/******************************************************************************/
/******************** AUD_SoftwareHandle 3DHandle Code ************************/
/******************************************************************************/
AUD_Vector3 AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceLocation()
{
if(!m_status)
return AUD_Vector3();
return m_location;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceLocation(const AUD_Vector3& location)
{
if(!m_status)
return false;
m_location = location;
return true;
}
AUD_Vector3 AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceVelocity()
{
if(!m_status)
return AUD_Vector3();
return m_velocity;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceVelocity(const AUD_Vector3& velocity)
{
if(!m_status)
return false;
m_velocity = velocity;
return true;
}
AUD_Quaternion AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceOrientation()
{
if(!m_status)
return AUD_Quaternion();
return m_orientation;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceOrientation(const AUD_Quaternion& orientation)
{
if(!m_status)
return false;
m_orientation = orientation;
return true;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::isRelative()
{
if(!m_status)
return false;
return m_relative;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setRelative(bool relative)
{
if(!m_status)
return false;
m_relative = relative;
return true;
}
float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolumeMaximum()
{
if(!m_status)
return std::numeric_limits<float>::quiet_NaN();
return m_volume_max;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolumeMaximum(float volume)
{
if(!m_status)
return false;
m_volume_max = volume;
return true;
}
float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolumeMinimum()
{
if(!m_status)
return std::numeric_limits<float>::quiet_NaN();;
return m_volume_min;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolumeMinimum(float volume)
{
if(!m_status)
return false;
m_volume_min = volume;
return true;
}
float AUD_SoftwareDevice::AUD_SoftwareHandle::getDistanceMaximum()
{
if(!m_status)
return std::numeric_limits<float>::quiet_NaN();
return m_distance_max;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setDistanceMaximum(float distance)
{
if(!m_status)
return false;
m_distance_max = distance;
return true;
}
float AUD_SoftwareDevice::AUD_SoftwareHandle::getDistanceReference()
{
if(!m_status)
return std::numeric_limits<float>::quiet_NaN();
return m_distance_reference;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setDistanceReference(float distance)
{
if(!m_status)
return false;
m_distance_reference = distance;
return true;
}
float AUD_SoftwareDevice::AUD_SoftwareHandle::getAttenuation()
{
if(!m_status)
return std::numeric_limits<float>::quiet_NaN();
return m_attenuation;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setAttenuation(float factor)
{
if(!m_status)
return false;
m_attenuation = factor;
if(factor == 0)
m_flags |= AUD_RENDER_DISTANCE;
else
m_flags &= ~AUD_RENDER_DISTANCE;
return true;
}
float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeAngleOuter()
{
if(!m_status)
return std::numeric_limits<float>::quiet_NaN();
return m_cone_angle_outer * 360.0f / M_PI;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeAngleOuter(float angle)
{
if(!m_status)
return false;
m_cone_angle_outer = angle * M_PI / 360.0f;
return true;
}
float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeAngleInner()
{
if(!m_status)
return std::numeric_limits<float>::quiet_NaN();
return m_cone_angle_inner * 360.0f / M_PI;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeAngleInner(float angle)
{
if(!m_status)
return false;
if(angle >= 360)
m_flags |= AUD_RENDER_CONE;
else
m_flags &= ~AUD_RENDER_CONE;
m_cone_angle_inner = angle * M_PI / 360.0f;
return true;
}
float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeVolumeOuter()
{
if(!m_status)
return std::numeric_limits<float>::quiet_NaN();;
return m_cone_volume_outer;
}
bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeVolumeOuter(float volume)
{
if(!m_status)
return false;
m_cone_volume_outer = volume;
return true;
}
/******************************************************************************/
/**************************** IDevice Code ************************************/
/******************************************************************************/
void AUD_SoftwareDevice::create()
{
m_playback = false;
m_volume = 1.0f;
m_mixer = new AUD_Mixer(m_specs);
m_speed_of_sound = 343.0f;
m_doppler_factor = 1.0f;
m_distance_model = AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
m_flags = 0;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
@ -297,6 +701,9 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
pos = 0;
len = length;
// update 3D Info
sound->update();
sound->m_reader->read(len, eos, buf);
// in case of looping
@ -370,13 +777,14 @@ AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> r
#endif
// rechannel
reader = new AUD_ChannelMapperReader(reader, m_specs.channels);
AUD_Reference<AUD_ChannelMapperReader> mapper = new AUD_ChannelMapperReader(reader, m_specs.channels);
reader = AUD_Reference<AUD_IReader>(mapper);
if(reader.isNull())
return NULL;
// play sound
AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, keep);
AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, mapper, keep);
lock();
m_playingSounds.push_back(sound);
@ -412,3 +820,75 @@ void AUD_SoftwareDevice::setVolume(float volume)
{
m_volume = volume;
}
/******************************************************************************/
/**************************** 3D Device Code **********************************/
/******************************************************************************/
AUD_Vector3 AUD_SoftwareDevice::getListenerLocation() const
{
return m_location;
}
void AUD_SoftwareDevice::setListenerLocation(const AUD_Vector3& location)
{
m_location = location;
}
AUD_Vector3 AUD_SoftwareDevice::getListenerVelocity() const
{
return m_velocity;
}
void AUD_SoftwareDevice::setListenerVelocity(const AUD_Vector3& velocity)
{
m_velocity = velocity;
}
AUD_Quaternion AUD_SoftwareDevice::getListenerOrientation() const
{
return m_orientation;
}
void AUD_SoftwareDevice::setListenerOrientation(const AUD_Quaternion& orientation)
{
m_orientation = orientation;
}
float AUD_SoftwareDevice::getSpeedOfSound() const
{
return m_speed_of_sound;
}
void AUD_SoftwareDevice::setSpeedOfSound(float speed)
{
m_speed_of_sound = speed;
}
float AUD_SoftwareDevice::getDopplerFactor() const
{
return m_doppler_factor;
}
void AUD_SoftwareDevice::setDopplerFactor(float factor)
{
m_doppler_factor = factor;
if(factor == 0)
m_flags |= AUD_RENDER_DOPPLER;
else
m_flags &= ~AUD_RENDER_DOPPLER;
}
AUD_DistanceModel AUD_SoftwareDevice::getDistanceModel() const
{
return m_distance_model;
}
void AUD_SoftwareDevice::setDistanceModel(AUD_DistanceModel model)
{
m_distance_model = model;
if(model == AUD_DISTANCE_MODEL_INVALID)
m_flags |= AUD_RENDER_DISTANCE;
else
m_flags &= ~AUD_RENDER_DISTANCE;
}

@ -34,9 +34,12 @@
#include "AUD_IDevice.h"
#include "AUD_IHandle.h"
#include "AUD_I3DDevice.h"
#include "AUD_I3DHandle.h"
#include "AUD_Mixer.h"
#include "AUD_Buffer.h"
#include "AUD_PitchReader.h"
#include "AUD_ChannelMapperReader.h"
#include <list>
#include <pthread.h>
@ -49,11 +52,11 @@
* - Call the create and destroy functions.
* - Call the mix function to retrieve their audio data.
*/
class AUD_SoftwareDevice : public AUD_IDevice
class AUD_SoftwareDevice : public AUD_IDevice, public AUD_I3DDevice
{
protected:
/// Saves the data for playback.
class AUD_SoftwareHandle : public AUD_IHandle
class AUD_SoftwareHandle : public AUD_IHandle, public AUD_I3DHandle
{
public:
/// The reader source.
@ -62,15 +65,63 @@ protected:
/// The pitch reader in between.
AUD_Reference<AUD_PitchReader> m_pitch;
/// The channel mapper reader in between.
AUD_Reference<AUD_ChannelMapperReader> m_mapper;
/// Whether to keep the source if end of it is reached.
bool m_keep;
/// The volume of the source.
/// The user set pitch of the source.
float m_user_pitch;
/// The user set volume of the source.
float m_user_volume;
/// The calculated final volume of the source.
float m_volume;
/// The loop count of the source.
int m_loopcount;
/// Location in 3D Space.
AUD_Vector3 m_location;
/// Velocity in 3D Space.
AUD_Vector3 m_velocity;
/// Orientation in 3D Space.
AUD_Quaternion m_orientation;
/// Whether the position to the listener is relative or absolute
bool m_relative;
/// Maximum volume.
float m_volume_max;
/// Minimum volume.
float m_volume_min;
/// Maximum distance.
float m_distance_max;
/// Reference distance;
float m_distance_reference;
/// Attenuation
float m_attenuation;
/// Cone outer angle.
float m_cone_angle_outer;
/// Cone inner angle.
float m_cone_angle_inner;
/// Cone outer volume.
float m_cone_volume_outer;
/// Rendering flags
int m_flags;
/// The stop callback.
stopCallback m_stop;
@ -85,7 +136,9 @@ protected:
public:
AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, bool keep);
AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep);
void update();
virtual ~AUD_SoftwareHandle() {}
virtual bool pause();
@ -103,6 +156,31 @@ protected:
virtual int getLoopCount();
virtual bool setLoopCount(int count);
virtual bool setStopCallback(stopCallback callback = 0, void* data = 0);
virtual AUD_Vector3 getSourceLocation();
virtual bool setSourceLocation(const AUD_Vector3& location);
virtual AUD_Vector3 getSourceVelocity();
virtual bool setSourceVelocity(const AUD_Vector3& velocity);
virtual AUD_Quaternion getSourceOrientation();
virtual bool setSourceOrientation(const AUD_Quaternion& orientation);
virtual bool isRelative();
virtual bool setRelative(bool relative);
virtual float getVolumeMaximum();
virtual bool setVolumeMaximum(float volume);
virtual float getVolumeMinimum();
virtual bool setVolumeMinimum(float volume);
virtual float getDistanceMaximum();
virtual bool setDistanceMaximum(float distance);
virtual float getDistanceReference();
virtual bool setDistanceReference(float distance);
virtual float getAttenuation();
virtual bool setAttenuation(float factor);
virtual float getConeAngleOuter();
virtual bool setConeAngleOuter(float angle);
virtual float getConeAngleInner();
virtual bool setConeAngleInner(float angle);
virtual float getConeVolumeOuter();
virtual bool setConeVolumeOuter(float volume);
};
typedef std::list<AUD_Reference<AUD_SoftwareHandle> >::iterator AUD_HandleIterator;
@ -171,6 +249,27 @@ private:
*/
float m_volume;
/// Listener location.
AUD_Vector3 m_location;
/// Listener velocity.
AUD_Vector3 m_velocity;
/// Listener orientation.
AUD_Quaternion m_orientation;
/// Speed of Sound.
float m_speed_of_sound;
/// Doppler factor.
float m_doppler_factor;
/// Distance model.
AUD_DistanceModel m_distance_model;
/// Rendering flags
int m_flags;
public:
virtual AUD_DeviceSpecs getSpecs() const;
virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false);
@ -179,6 +278,19 @@ public:
virtual void unlock();
virtual float getVolume() const;
virtual void setVolume(float volume);
virtual AUD_Vector3 getListenerLocation() const;
virtual void setListenerLocation(const AUD_Vector3& location);
virtual AUD_Vector3 getListenerVelocity() const;
virtual void setListenerVelocity(const AUD_Vector3& velocity);
virtual AUD_Quaternion getListenerOrientation() const;
virtual void setListenerOrientation(const AUD_Quaternion& orientation);
virtual float getSpeedOfSound() const;
virtual void setSpeedOfSound(float speed);
virtual float getDopplerFactor() const;
virtual void setDopplerFactor(float factor);
virtual AUD_DistanceModel getDistanceModel() const;
virtual void setDistanceModel(AUD_DistanceModel model);
};
#endif //AUD_SOFTWAREDEVICE