mirror of https://github.com/AxioDL/amuse.git
176 lines
4.5 KiB
C++
176 lines
4.5 KiB
C++
#include "amuse/SurroundProfiles.hpp"
|
|
#include <cmath>
|
|
#include <algorithm>
|
|
#include <cfloat>
|
|
|
|
namespace amuse
|
|
{
|
|
|
|
static float Dot(const Vector3f& a, const Vector3f& b)
|
|
{
|
|
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
}
|
|
|
|
static float Length(const Vector3f& a)
|
|
{
|
|
if (std::fabs(a[0]) <= FLT_EPSILON &&
|
|
std::fabs(a[1]) <= FLT_EPSILON &&
|
|
std::fabs(a[2]) <= FLT_EPSILON)
|
|
return 0.f;
|
|
return std::sqrt(Dot(a, a));
|
|
}
|
|
|
|
static float Normalize(Vector3f& out, const Vector3f& in)
|
|
{
|
|
out[0] = in[0];
|
|
out[1] = in[1];
|
|
out[2] = in[2];
|
|
float dist = Length(out);
|
|
out[0] /= dist;
|
|
out[1] /= dist;
|
|
out[2] /= dist;
|
|
return dist;
|
|
}
|
|
|
|
static void Cross(Vector3f& out, const Vector3f& a, const Vector3f& b)
|
|
{
|
|
out[0] = a[1] * b[2] - a[2] * b[1];
|
|
out[1] = a[2] * b[0] - a[0] * b[2];
|
|
out[2] = a[0] * b[1] - a[1] * b[0];
|
|
}
|
|
|
|
class SimpleMatrix
|
|
{
|
|
Vector3f m_mat[3];
|
|
public:
|
|
SimpleMatrix(const Vector3f& dir, const Vector3f& up)
|
|
{
|
|
Vector3f temp;
|
|
Normalize(temp, dir);
|
|
m_mat[0][1] = temp[0];
|
|
m_mat[1][1] = temp[1];
|
|
m_mat[2][1] = temp[2];
|
|
|
|
Normalize(temp, up);
|
|
m_mat[0][2] = temp[0];
|
|
m_mat[1][2] = temp[1];
|
|
m_mat[2][2] = temp[2];
|
|
|
|
Cross(temp, dir, up);
|
|
m_mat[0][0] = temp[0];
|
|
m_mat[1][0] = temp[1];
|
|
m_mat[2][0] = temp[2];
|
|
}
|
|
|
|
void vecMult(Vector3f& out, const Vector3f& in)
|
|
{
|
|
out[0] = Dot(m_mat[0], in);
|
|
out[1] = Dot(m_mat[1], in);
|
|
out[2] = Dot(m_mat[2], in);
|
|
}
|
|
};
|
|
|
|
struct ReferenceVector
|
|
{
|
|
Vector3f vec;
|
|
float bias;
|
|
bool valid = false;
|
|
ReferenceVector() = default;
|
|
ReferenceVector(float x, float y, float z, float thres)
|
|
{
|
|
vec[0] = x;
|
|
vec[1] = y;
|
|
vec[2] = z;
|
|
bias = thres;
|
|
valid = true;
|
|
}
|
|
};
|
|
|
|
static const ReferenceVector StereoVectors[8] =
|
|
{
|
|
{-0.80901f, 0.58778f, 0.f, 0.3f},
|
|
{ 0.80901f, 0.58778f, 0.f, 0.3f},
|
|
};
|
|
|
|
static const ReferenceVector QuadVectors[8] =
|
|
{
|
|
{-0.70710f, 0.70710f, 0.f, 0.1f},
|
|
{ 0.70710f, 0.70710f, 0.f, 0.1f},
|
|
{-0.70710f, -0.70710f, 0.f, 0.1f},
|
|
{ 0.70710f, -0.70710f, 0.f, 0.1f},
|
|
};
|
|
|
|
static const ReferenceVector Sur51Vectors[8] =
|
|
{
|
|
{-0.70710f, 0.70710f, 0.f, 0.1f},
|
|
{ 0.70710f, 0.70710f, 0.f, 0.1f},
|
|
{-0.70710f, -0.70710f, 0.f, 0.1f},
|
|
{ 0.70710f, -0.70710f, 0.f, 0.1f},
|
|
{ 0.0f, 1.0f, 0.f, 0.1f},
|
|
{ 0.0f, 1.0f, 0.f, 1.0f},
|
|
};
|
|
|
|
static const ReferenceVector Sur71Vectors[8] =
|
|
{
|
|
{-0.70710f, 0.70710f, 0.f, 0.1f},
|
|
{ 0.70710f, 0.70710f, 0.f, 0.1f},
|
|
{-0.70710f, -0.70710f, 0.f, 0.1f},
|
|
{ 0.70710f, -0.70710f, 0.f, 0.1f},
|
|
{ 0.0f, 1.0f, 0.f, 0.1f},
|
|
{ 0.0f, 1.0f, 0.f, 1.0f},
|
|
{-1.f, 0.0f, 0.f, 0.1f},
|
|
{ 1.f, 0.0f, 0.f, 0.1f},
|
|
};
|
|
|
|
void SurroundProfiles::SetupRefs(float matOut[8], const ChannelMap& map,
|
|
const Vector3f& listenEmit, const ReferenceVector refs[])
|
|
{
|
|
for (unsigned i=0 ; i<map.m_channelCount && i<8 ; ++i)
|
|
{
|
|
matOut[i] = 0.f;
|
|
if (map.m_channels[i] == AudioChannel::Unknown)
|
|
continue;
|
|
const ReferenceVector& refVec = refs[int(map.m_channels[i])];
|
|
if (!refVec.valid)
|
|
continue;
|
|
matOut[i] = std::max(1.f, Dot(listenEmit, refVec.vec) + refVec.bias);
|
|
}
|
|
}
|
|
|
|
void SurroundProfiles::SetupMatrix(float matOut[8], const ChannelMap& map, AudioChannelSet set,
|
|
const Vector3f& emitPos, const Vector3f& listenPos,
|
|
const Vector3f& listenHeading, const Vector3f& listenUp)
|
|
{
|
|
Vector3f listenDelta;
|
|
listenDelta[0] = emitPos[0] - listenPos[0];
|
|
listenDelta[1] = emitPos[1] - listenPos[1];
|
|
listenDelta[2] = emitPos[2] - listenPos[2];
|
|
|
|
Vector3f listenNorm;
|
|
float dist = Normalize(listenNorm, listenDelta);
|
|
|
|
SimpleMatrix listenerMat(listenHeading, listenUp);
|
|
Vector3f listenEmit;
|
|
listenerMat.vecMult(listenEmit, listenNorm);
|
|
|
|
/* Factor for each channel in set */
|
|
switch (set)
|
|
{
|
|
case AudioChannelSet::Stereo:
|
|
default:
|
|
SetupRefs(matOut, map, listenEmit, StereoVectors);
|
|
break;
|
|
case AudioChannelSet::Quad:
|
|
SetupRefs(matOut, map, listenEmit, QuadVectors);
|
|
break;
|
|
case AudioChannelSet::Surround51:
|
|
SetupRefs(matOut, map, listenEmit, Sur51Vectors);
|
|
break;
|
|
case AudioChannelSet::Surround71:
|
|
SetupRefs(matOut, map, listenEmit, Sur71Vectors);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|