diff options
author | Joerg Mueller <nexyon@gmail.com> | 2011-07-12 17:11:00 +0400 |
---|---|---|
committer | Joerg Mueller <nexyon@gmail.com> | 2011-07-12 17:11:00 +0400 |
commit | 208b69e3a71573453c7dc0e5b12785052233b4e1 (patch) | |
tree | 03ffad7c0a854fa4c3ae2e33c1398129b28a190c /intern/audaspace | |
parent | d9cf98573050fa10f586ed121f514986e688e609 (diff) |
3D Audio GSoC:
Software 3D Audio implementation.
Diffstat (limited to 'intern/audaspace')
-rw-r--r-- | intern/audaspace/OpenAL/AUD_OpenALDevice.cpp | 4 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_3DMath.h | 138 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_ChannelMapperReader.cpp | 38 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_ChannelMapperReader.h | 12 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_SoftwareDevice.cpp | 500 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_SoftwareDevice.h | 120 |
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 |