Skip to content

Commit

Permalink
fix(hrtf): Support for MIT dataset, fixed sphere generation.
Browse files Browse the repository at this point in the history
Signed-off-by: Axel Nana <[email protected]>
  • Loading branch information
na2axl committed Jul 4, 2024
1 parent 15d9174 commit 8dbe69f
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 98 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ set(SA_SOURCE
include/SparkyStudios/Audio/Amplitude/Math/Curve.h
include/SparkyStudios/Audio/Amplitude/Math/FFT.h
include/SparkyStudios/Audio/Amplitude/Math/HandmadeMath.h
include/SparkyStudios/Audio/Amplitude/Math/PolarPosition.h
include/SparkyStudios/Audio/Amplitude/Math/Shape.h
include/SparkyStudios/Audio/Amplitude/Math/SplitComplex.h
include/SparkyStudios/Audio/Amplitude/Math/Utils.h
Expand Down Expand Up @@ -254,6 +255,7 @@ set(SA_SOURCE

src/Math/Curve.cpp
src/Math/FFT.cpp
src/Math/PolarPosition.cpp
src/Math/Shape.cpp
src/Math/SplitComplex.cpp

Expand Down
1 change: 1 addition & 0 deletions include/SparkyStudios/Audio/Amplitude/Amplitude.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include <SparkyStudios/Audio/Amplitude/Math/Curve.h>
#include <SparkyStudios/Audio/Amplitude/Math/FFT.h>
#include <SparkyStudios/Audio/Amplitude/Math/HandmadeMath.h>
#include <SparkyStudios/Audio/Amplitude/Math/PolarPosition.h>
#include <SparkyStudios/Audio/Amplitude/Math/Shape.h>
#include <SparkyStudios/Audio/Amplitude/Math/SplitComplex.h>
#include <SparkyStudios/Audio/Amplitude/Math/Utils.h>
Expand Down
19 changes: 19 additions & 0 deletions include/SparkyStudios/Audio/Amplitude/Core/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,25 @@ namespace SparkyStudios::Audio::Amplitude
AM_FADER_STATE_ACTIVE = 1,
};

/**
* @brief Enumerates the list of supported up axis.
*
* This should be synchronized with the game engine settings.
* It will affect how vectors and matrices calculation are performed.
*/
enum GameEngineUpAxis : AmUInt8
{
/**
* @brief The up axis is Y.
*/
eUpAxis_Y = 0,

/**
* @brief The up axis is Z.
*/
eUpAxis_Z = 1,
};

/**
* @brief Describe the format of an audio sample.
*
Expand Down
33 changes: 33 additions & 0 deletions include/SparkyStudios/Audio/Amplitude/Math/PolarPosition.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2024-present Sparky Studios. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <SparkyStudios/Audio/Amplitude/Core/Common.h>

namespace SparkyStudios::Audio::Amplitude
{
struct PolarPosition
{
PolarPosition() = default;
PolarPosition(AmReal32 azimuth, AmReal32 elevation, AmReal32 radius);
PolarPosition(AmVec3 originPosition, AmVec3 originDirection, AmVec3 originUp, AmVec3 position);

[[nodiscard]] AmVec3 ToCartesian(GameEngineUpAxis upAxis) const;

AmReal32 m_Azimuth = 0;
AmReal32 m_Elevation = 0;
AmReal32 m_Radius = 0;
};
} // namespace SparkyStudios::Audio::Amplitude
6 changes: 3 additions & 3 deletions src/Core/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ namespace SparkyStudios::Audio::Amplitude
_state->samples_per_stream = config->output()->buffer_size() / config->output()->channels();

// Set the game engine up axis
_state->up_axis = config->game()->up_axis();
_state->up_axis = static_cast<GameEngineUpAxis>(config->game()->up_axis());

// Save obstruction/occlusion configurations
_state->obstruction_config.Init(config->game()->obstruction());
Expand Down Expand Up @@ -1043,10 +1043,10 @@ namespace SparkyStudios::Audio::Amplitude
switch (amEngine->GetState()->up_axis)
{
default:
case eGameEngineUpAxis_Y:
case eUpAxis_Y:
return AM_V2(AM_Dot(AM_V3(1, 0, 0), direction), AM_Dot(AM_V3(0, 0, 1), direction));

case eGameEngineUpAxis_Z:
case eUpAxis_Z:
return AM_V2(AM_Dot(AM_V3(1, 0, 0), direction), AM_Dot(AM_V3(0, 1, 0), direction));
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Core/EngineInternalState.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ namespace SparkyStudios::Audio::Amplitude
, listener_fetch_mode(eListenerFetchMode_None)
, sound_speed(333.0)
, doppler_factor(1.0)
, up_axis(eGameEngineUpAxis_Y)
, up_axis(eUpAxis_Y)
, obstruction_config()
, occlusion_config()
, track_environments(false)
Expand Down Expand Up @@ -266,7 +266,7 @@ namespace SparkyStudios::Audio::Amplitude
AmReal32 doppler_factor;

// The up axis of the game engine.
eGameEngineUpAxis up_axis;
GameEngineUpAxis up_axis;

ObstructionOcclusionState obstruction_config;

Expand Down
93 changes: 93 additions & 0 deletions src/Math/PolarPosition.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (c) 2024-present Sparky Studios. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <SparkyStudios/Audio/Amplitude/Math/PolarPosition.h>

namespace SparkyStudios::Audio::Amplitude
{
PolarPosition::PolarPosition(AmReal32 azimuth, AmReal32 elevation, AmReal32 radius)
: m_Azimuth(azimuth)
, m_Elevation(elevation)
, m_Radius(radius)
{}

PolarPosition::PolarPosition(AmVec3 originPosition, AmVec3 originDirection, AmVec3 originUp, AmVec3 position)
{
if (originPosition == position)
{
m_Azimuth = 0;
m_Elevation = 0;
m_Radius = 0;
return;
}

AmVec3 fwd = AM_Norm(originDirection);
AmVec3 right = AM_Norm(AM_Cross(fwd, originUp));
AmVec3 up = AM_Cross(right, fwd);
AmVec3 pos = position - originPosition;

m_Radius = AM_Len(pos);

pos = AM_V3(AM_Dot(pos, right), AM_Dot(pos, up), AM_Dot(pos, fwd));

if (AM_EqV3(up, AM_V3(0, 1, 0)))
{
m_Azimuth = std::atan2(pos.X, pos.Z);

AmVec3 proj = AM_V3(pos.X, 0, pos.Z);
m_Elevation = std::acos(AM_Dot(AM_Norm(pos), AM_Norm(proj)));

if (pos.Y < 0)
m_Elevation = -m_Elevation;
}
else if (AM_EqV3(up, AM_V3(0, 0, 1)))
{
m_Azimuth = std::atan2(pos.X, pos.Y);

AmVec3 proj = AM_V3(pos.X, pos.Y, 0);
m_Elevation = std::acos(AM_Dot(AM_Norm(pos), AM_Norm(proj)));

if (pos.Z < 0)
m_Elevation = -m_Elevation;
}
}

AmVec3 PolarPosition::ToCartesian(GameEngineUpAxis upAxis) const
{
switch (upAxis)
{
case eUpAxis_Y:
{
// Translates spherical to cartesian, where Y - up, Z - forward, X - right
const AmReal32 x = +m_Radius * std::cos(m_Elevation) * std::cos(m_Azimuth);
const AmReal32 y = +m_Radius * std::sin(m_Elevation);
const AmReal32 z = -m_Radius * std::cos(m_Elevation) * std::sin(m_Azimuth);

return AM_V3(x, y, z);
}
case eUpAxis_Z:
{
// Translates spherical to cartesian, where Z - up, Y - forward, X - right
const AmReal32 x = +m_Radius * std::cos(m_Elevation) * std::cos(m_Azimuth);
const AmReal32 y = -m_Radius * std::cos(m_Elevation) * std::sin(m_Azimuth);
const AmReal32 z = +m_Radius * std::sin(m_Elevation);

return AM_V3(x, y, z);
}
}

AMPLITUDE_ASSERT(false);
return AM_V3(0, 0, 0);
}
} // namespace SparkyStudios::Audio::Amplitude
22 changes: 11 additions & 11 deletions src/Math/Shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ namespace SparkyStudios::Audio::Amplitude
{
default:
[[fallthrough]];
case eGameEngineUpAxis_Y:
case eUpAxis_Y:
{
const AmReal32 dP1 = AM_Dot(location - _p1, AM_Norm(_p2 - _p1));
const AmReal32 dP2 = AM_Dot(location - _p2, AM_Norm(_p1 - _p2));
Expand All @@ -249,7 +249,7 @@ namespace SparkyStudios::Audio::Amplitude
return AM_MIN(dP1, AM_MIN(dP2, AM_MIN(dP3, AM_MIN(dP4, AM_MIN(dP5, dP6)))));
}

case eGameEngineUpAxis_Z:
case eUpAxis_Z:
{
const AmReal32 dP1 = AM_Dot(location - _p1, AM_Norm(_p2 - _p1));
const AmReal32 dP2 = AM_Dot(location - _p2, AM_Norm(_p1 - _p2));
Expand Down Expand Up @@ -283,14 +283,14 @@ namespace SparkyStudios::Audio::Amplitude
switch (amEngine->GetState()->up_axis)
{
default:
case eGameEngineUpAxis_Y:
case eUpAxis_Y:
_p1 = AM_Mul(m_lookAtMatrix, AM_V4(-_halfWidth, -_halfHeight, -_halfDepth, 1.0f)).XYZ;
_p2 = AM_Mul(m_lookAtMatrix, AM_V4(-_halfWidth, -_halfHeight, _halfDepth, 1.0f)).XYZ;
_p3 = AM_Mul(m_lookAtMatrix, AM_V4(_halfWidth, -_halfHeight, -_halfDepth, 1.0f)).XYZ;
_p4 = AM_Mul(m_lookAtMatrix, AM_V4(-_halfWidth, _halfHeight, -_halfDepth, 1.0f)).XYZ;
break;

case eGameEngineUpAxis_Z:
case eUpAxis_Z:
_p1 = AM_Mul(m_lookAtMatrix, AM_V4(-_halfWidth, -_halfDepth, -_halfHeight, 1.0f)).XYZ;
_p2 = AM_Mul(m_lookAtMatrix, AM_V4(-_halfWidth, _halfDepth, -_halfHeight, 1.0f)).XYZ;
_p3 = AM_Mul(m_lookAtMatrix, AM_V4(_halfWidth, -_halfDepth, -_halfHeight, 1.0f)).XYZ;
Expand Down Expand Up @@ -416,12 +416,12 @@ namespace SparkyStudios::Audio::Amplitude
switch (amEngine->GetState()->up_axis)
{
default:
case eGameEngineUpAxis_Y:
case eUpAxis_Y:
_a = AM_Mul(m_lookAtMatrix, AM_V4(0.0f, halfHeight, 0.0f, 1.0f)).XYZ;
_b = AM_Mul(m_lookAtMatrix, AM_V4(0.0f, -halfHeight, 0.0f, 1.0f)).XYZ;
break;

case eGameEngineUpAxis_Z:
case eUpAxis_Z:
_a = AM_Mul(m_lookAtMatrix, AM_V4(0.0f, 0.0f, halfHeight, 1.0f)).XYZ;
_b = AM_Mul(m_lookAtMatrix, AM_V4(0.0f, 0.0f, -halfHeight, 1.0f)).XYZ;
break;
Expand Down Expand Up @@ -577,7 +577,7 @@ namespace SparkyStudios::Audio::Amplitude
if (outer->m_needUpdate)
outer->_update();

const eGameEngineUpAxis upAxis = amEngine->GetState()->up_axis;
const GameEngineUpAxis upAxis = amEngine->GetState()->up_axis;

const AmVec3& x = position;

Expand All @@ -600,7 +600,7 @@ namespace SparkyStudios::Audio::Amplitude
switch (upAxis)
{
default:
case eGameEngineUpAxis_Y:
case eUpAxis_Y:
{
const AmReal32 dP1 =
AM_ABS(AM_Dot(x - outer->_p1, AM_Norm(outer->_p2 - outer->_p1))) / (outer->GetHalfDepth() - inner->GetHalfDepth());
Expand All @@ -620,7 +620,7 @@ namespace SparkyStudios::Audio::Amplitude
return AM_CLAMP(shortestPath, 0.0f, 1.0f);
}

case eGameEngineUpAxis_Z:
case eUpAxis_Z:
{
const AmReal32 dP1 =
AM_ABS(AM_Dot(x - outer->_p1, AM_Norm(outer->_p2 - outer->_p1))) / (outer->GetHalfHeight() - inner->GetHalfHeight());
Expand Down Expand Up @@ -659,7 +659,7 @@ namespace SparkyStudios::Audio::Amplitude
if (outer->m_needUpdate)
outer->Update();

const eGameEngineUpAxis upAxis = amEngine->GetState()->up_axis;
const GameEngineUpAxis upAxis = amEngine->GetState()->up_axis;

const AmVec3& x = position;

Expand Down Expand Up @@ -715,7 +715,7 @@ namespace SparkyStudios::Audio::Amplitude
if (outer->m_needUpdate)
outer->Update();

const eGameEngineUpAxis upAxis = amEngine->GetState()->up_axis;
const GameEngineUpAxis upAxis = amEngine->GetState()->up_axis;

const AmVec3& soundToListener = position - inner->GetLocation();
const AmReal32 distance = AM_Len(soundToListener);
Expand Down
4 changes: 2 additions & 2 deletions src/Sound/AttenuationShapes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,15 +318,15 @@ namespace SparkyStudios::Audio::Amplitude
switch (amEngine->GetState()->up_axis)
{
default:
case eGameEngineUpAxis_Y:
case eUpAxis_Y:
iA = AM_Mul(lookAt, AM_V4(0.0f, innerHalfHeight, 0.0f, 1.0f)).XYZ;
iB = AM_Mul(lookAt, AM_V4(0.0f, -innerHalfHeight, 0.0f, 1.0f)).XYZ;

oA = AM_Mul(lookAt, AM_V4(0.0f, outerHalfHeight, 0.0f, 1.0f)).XYZ;
oB = AM_Mul(lookAt, AM_V4(0.0f, -outerHalfHeight, 0.0f, 1.0f)).XYZ;
break;

case eGameEngineUpAxis_Z:
case eUpAxis_Z:
iA = AM_Mul(lookAt, AM_V4(0.0f, 0.0f, innerHalfHeight, 1.0f)).XYZ;
iB = AM_Mul(lookAt, AM_V4(0.0f, 0.0f, -innerHalfHeight, 1.0f)).XYZ;

Expand Down
10 changes: 0 additions & 10 deletions src/Utils/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,6 @@ namespace SparkyStudios::Audio::Amplitude
std::memcpy(dest.GetBuffer(), src, srcSize * sizeof(AmReal32));
std::memset(dest.GetBuffer() + srcSize, 0, (dest.GetSize() - srcSize) * sizeof(AmReal32));
}

AM_INLINE(AmVec3) SphericalToCartesian(AmReal32 azimuth, AmReal32 elevation, AmReal32 radius)
{
// Translates spherical to cartesian, where Y - up, Z - forward, X - right
const AmReal32 x = +radius * std::cos(elevation) * std::cos(azimuth);
const AmReal32 y = +radius * std::sin(elevation);
const AmReal32 z = -radius * std::cos(elevation) * std::sin(azimuth);

return AM_V3(x, y, z);
}
} // namespace SparkyStudios::Audio::Amplitude

#endif // SS_AMPLITUDE_AUDIO_UTILS_H
Loading

0 comments on commit 8dbe69f

Please sign in to comment.