forked from bartvdbraak/blender
3D Audio GSoC:
Software 3D Audio implementation.
This commit is contained in:
parent
d9cf985730
commit
208b69e3a7
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user