Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Mueller <nexyon@gmail.com>2011-07-12 17:11:00 +0400
committerJoerg Mueller <nexyon@gmail.com>2011-07-12 17:11:00 +0400
commit208b69e3a71573453c7dc0e5b12785052233b4e1 (patch)
tree03ffad7c0a854fa4c3ae2e33c1398129b28a190c /intern/audaspace
parentd9cf98573050fa10f586ed121f514986e688e609 (diff)
3D Audio GSoC:
Software 3D Audio implementation.
Diffstat (limited to 'intern/audaspace')
-rw-r--r--intern/audaspace/OpenAL/AUD_OpenALDevice.cpp4
-rw-r--r--intern/audaspace/intern/AUD_3DMath.h138
-rw-r--r--intern/audaspace/intern/AUD_ChannelMapperReader.cpp38
-rw-r--r--intern/audaspace/intern/AUD_ChannelMapperReader.h12
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.cpp500
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.h120
6 files changed, 753 insertions, 59 deletions
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
index c36f29aa179..3b306d89d7b 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
@@ -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();
diff --git a/intern/audaspace/intern/AUD_3DMath.h b/intern/audaspace/intern/AUD_3DMath.h
index fc095ebaca7..3a6abf811ce 100644
--- a/intern/audaspace/intern/AUD_3DMath.h
+++ b/intern/audaspace/intern/AUD_3DMath.h
@@ -32,15 +32,16 @@
#ifndef AUD_3DMATH
#define AUD_3DMATH
-class AUD_Quaternion
+#include <cmath>
+
+class AUD_Vector3
{
private:
union
{
- float m_v[4];
+ float m_v[3];
struct
{
- float m_w;
float m_x;
float m_y;
float m_z;
@@ -49,28 +50,18 @@ private:
public:
/**
- * Creates a new quaternion.
- * \param w The w component.
+ * Creates a new 3 dimensional vector.
* \param x The x component.
* \param y The y component.
* \param z The z component.
*/
- inline AUD_Quaternion(float w, float x, float y, float z) :
- m_w(w), m_x(x), m_y(y), m_z(z)
- {
- }
-
- /**
- * Retrieves the w component of the quarternion.
- * \return The w component.
- */
- inline const float& w() const
+ inline AUD_Vector3(float x = 0, float y = 0, float z = 0) :
+ m_x(x), m_y(y), m_z(z)
{
- return m_w;
}
/**
- * Retrieves the x component of the quarternion.
+ * Retrieves the x component of the vector.
* \return The x component.
*/
inline const float& x() const
@@ -79,7 +70,7 @@ public:
}
/**
- * Retrieves the y component of the quarternion.
+ * Retrieves the y component of the vector.
* \return The y component.
*/
inline const float& y() const
@@ -88,7 +79,7 @@ public:
}
/**
- * Retrieves the z component of the quarternion.
+ * Retrieves the z component of the vector.
* \return The z component.
*/
inline const float& z() const
@@ -98,34 +89,80 @@ public:
/**
* Retrieves the components of the vector.
- * \param destination Where the 4 float values should be saved to.
+ * \param destination Where the 3 float values should be saved to.
*/
inline void get(float* destination) const
{
- destination[0] = m_w;
- destination[1] = m_x;
- destination[2] = m_y;
- destination[3] = m_z;
+ destination[0] = m_x;
+ destination[1] = m_y;
+ destination[2] = m_z;
}
/**
* Retrieves the components of the vector.
- * \return The components as float[4].
+ * \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_Vector3
+class AUD_Quaternion
{
private:
union
{
- float m_v[3];
+ float m_v[4];
struct
{
+ float m_w;
float m_x;
float m_y;
float m_z;
@@ -134,18 +171,28 @@ private:
public:
/**
- * Creates a new 3 dimensional vector.
+ * Creates a new quaternion.
+ * \param w The w component.
* \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_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)
{
}
/**
- * Retrieves the x component of the vector.
+ * Retrieves the w component of the quarternion.
+ * \return The w component.
+ */
+ inline const float& w() const
+ {
+ return m_w;
+ }
+
+ /**
+ * Retrieves the x component of the quarternion.
* \return The x component.
*/
inline const float& x() const
@@ -154,7 +201,7 @@ public:
}
/**
- * Retrieves the y component of the vector.
+ * Retrieves the y component of the quarternion.
* \return The y component.
*/
inline const float& y() const
@@ -163,7 +210,7 @@ public:
}
/**
- * Retrieves the z component of the vector.
+ * Retrieves the z component of the quarternion.
* \return The z component.
*/
inline const float& z() const
@@ -173,23 +220,38 @@ public:
/**
* Retrieves the components of the vector.
- * \param destination Where the 3 float values should be saved to.
+ * \param destination Where the 4 float values should be saved to.
*/
inline void get(float* destination) const
{
- destination[0] = m_x;
- destination[1] = m_y;
- destination[2] = m_z;
+ destination[0] = m_w;
+ destination[1] = m_x;
+ destination[2] = m_y;
+ destination[3] = m_z;
}
/**
* Retrieves the components of the vector.
- * \return The components as float[3].
+ * \return The components as float[4].
*/
inline const float* get() const
{
return m_v;
}
+
+ 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);
+ }
+
+ inline AUD_Vector3 getUp() const
+ {
+ 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));
+ }
};
#endif //AUD_3DMATH
diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp
index 5b937a30242..56c45da3fe4 100644
--- a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp
+++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp
@@ -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
diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.h b/intern/audaspace/intern/AUD_ChannelMapperReader.h
index 3da34ed85ce..fa035531763 100644
--- a/intern/audaspace/intern/AUD_ChannelMapperReader.h
+++ b/intern/audaspace/intern/AUD_ChannelMapperReader.h
@@ -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);
};
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index ba5f121f617..c19f65afc6d 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -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;
+}
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h
index 58aaebddb96..c7dbf1d41eb 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.h
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.h
@@ -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