From e7118e10757f6b817921c1c5137a2075cfb3e16b Mon Sep 17 00:00:00 2001 From: Axel Nana Date: Wed, 6 Nov 2024 18:17:46 +0100 Subject: [PATCH] feat(tests): More math tests. --- .../Audio/Amplitude/DSP/Resampler.h | 4 +- .../Audio/Amplitude/Math/Utils.h | 4 +- tests/math.cpp | 112 +++++++++++++++++- 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/include/SparkyStudios/Audio/Amplitude/DSP/Resampler.h b/include/SparkyStudios/Audio/Amplitude/DSP/Resampler.h index 4c0bf62..e712ee5 100644 --- a/include/SparkyStudios/Audio/Amplitude/DSP/Resampler.h +++ b/include/SparkyStudios/Audio/Amplitude/DSP/Resampler.h @@ -158,7 +158,7 @@ namespace SparkyStudios::Audio::Amplitude /** * @brief Create a new Resampler instance. * - * @param[in] name The resampler name. eg. "MiniAudioLinear". + * @param[in] name The resampler name. e.g. "MiniAudioLinear". */ explicit Resampler(AmString name); @@ -213,7 +213,7 @@ namespace SparkyStudios::Audio::Amplitude static void Unregister(const Resampler* resampler); /** - * @brief Creates a new instance of the the resampler with the given name and returns its pointer. + * @brief Creates a new instance of the resampler with the given name and returns its pointer. * * @note The returned pointer should be deleted using @ref Destruct `Destruct()`. * diff --git a/include/SparkyStudios/Audio/Amplitude/Math/Utils.h b/include/SparkyStudios/Audio/Amplitude/Math/Utils.h index 20a2c8d..9494797 100644 --- a/include/SparkyStudios/Audio/Amplitude/Math/Utils.h +++ b/include/SparkyStudios/Audio/Amplitude/Math/Utils.h @@ -72,7 +72,7 @@ namespace SparkyStudios::Audio::Amplitude AM_API_PRIVATE AM_INLINE AmReal32 AmDitherReal32(const AmReal32 ditherMin, const AmReal32 ditherMax) { gLCG.state = (AM_LCG_A * gLCG.state + AM_LCG_C) % AM_LCG_M; - const AmReal32 x = gLCG.state / (double)0x7FFFFFFF; + const AmReal32 x = gLCG.state / static_cast(0x7FFFFFFF); return ditherMin + x * (ditherMax - ditherMin); } @@ -274,7 +274,7 @@ namespace SparkyStudios::Audio::Amplitude /** * @brief Computes the value base^exp using the squared exponentiation method. * - * @tparam T An integer type, a floating-point type, or a any other type where operator *= is defined. + * @tparam T An integer type, a floating-point type, or any other type where operator *= is defined. * @param[in] base Input of the power function. * @param[in] exp The exponent of the power function. Must be non-negative. diff --git a/tests/math.cpp b/tests/math.cpp index 13bfdce..51e8e05 100644 --- a/tests/math.cpp +++ b/tests/math.cpp @@ -254,7 +254,7 @@ TEST_CASE("Spherical Position Tests", "[spherical_position][math][amplitude]") { GIVEN("a spherical position") { - const auto position = SphericalPosition(AM_DegToRad * 45.0f, AM_DegToRad * 30.0f, 5.0f); + SphericalPosition position(AM_DegToRad * 45.0f, AM_DegToRad * 30.0f, 5.0f); THEN("it should store the correct spherical coordinates") { @@ -281,6 +281,17 @@ TEST_CASE("Spherical Position Tests", "[spherical_position][math][amplitude]") REQUIRE(flippedPosition.GetRadius() == position.GetRadius()); } + THEN("it can change azimuth, elevation and radius") + { + position.SetAzimuth(AM_DegToRad * 60.0f); + position.SetElevation(AM_DegToRad * 45.0f); + position.SetRadius(10.0f); + + REQUIRE(position.GetAzimuth() == AM_DegToRad * 60.0f); + REQUIRE(position.GetElevation() == AM_DegToRad * 45.0f); + REQUIRE(position.GetRadius() == 10.0f); + } + THEN("it can be rotated") { const auto rotation = AM_QFromAxisAngle_RH(AM_V3(0, 0, 1), AM_DegToRad * 90.0f); @@ -493,4 +504,103 @@ TEST_CASE("Curve Tests", "[curve][math][amplitude]") REQUIRE(curve.Get(2.0) == 0.0f); } } +} + +TEST_CASE("Utilities Tests", "[utilities][math][amplitude]") +{ + THEN("dithering always works") + { + // This is only to increase coverage, as the dithering function is a simple function that always returns a value + AmDitherReal32(1.0f / INT16_MIN, 1.0f / INT16_MAX); + } + + SECTION("floating-point to fixed-point conversion") + { + THEN("it can convert floating-point audio sample to fixed-point") + { + constexpr AmReal32 value = 0.5f; + const AmInt32 fixedPointValue = AmFloatToFixedPoint(value); + REQUIRE(std::abs(fixedPointValue - 16384) < kEpsilon); + } + + THEN("it can convert 16-bit integer to 32-bit floating-point") + { + constexpr AmInt16 fxp = 16384; + const AmReal32 value = AmInt16ToReal32(fxp); + REQUIRE(std::abs(value - 0.5f) < kEpsilon); + } + + THEN("it can convert 32-bit integer to 32-bit floating-point") + { + constexpr AmInt32 value = 16384; + const AmReal32 fxp = AmInt32ToReal32(value); + REQUIRE(std::abs(fxp - 0.5f) < kEpsilon); + } + + THEN("it can convert 32-bit floating-point to 16-bit integer") + { + constexpr AmReal32 value = 0.5f; + + const AmInt16 fxp1 = AmReal32ToInt16(value, false); + REQUIRE((fxp1 - 16384) < kEpsilon); + + const AmInt16 fxp2 = AmReal32ToInt16(value, true); + REQUIRE((fxp2 - 16384) < kEpsilon); + + REQUIRE(std::abs(fxp1 - fxp2) < kEpsilon); + } + } + + SECTION("catmull_rom") + { + constexpr AmReal32 p1 = 0.0f; + constexpr AmReal32 p2 = 1.0f; + constexpr AmReal32 p3 = 2.0f; + constexpr AmReal32 p4 = 3.0f; + + REQUIRE(CatmullRom(0.0f, p1, p2, p3, p4) == 1.0f); + REQUIRE(CatmullRom(1.0f, p1, p2, p3, p4) == 2.0f); + REQUIRE(CatmullRom(0.5f, p1, p2, p3, p4) == 1.5f); + } + + SECTION("doppler factor") + { + constexpr AmReal32 soundSpeed = 343.0f; + constexpr AmVec3 source = { 10.0f, 25.0f, 1.0f }; + constexpr AmVec3 listener = { 0.0f, 0.0f, 0.0f }; + + const AmReal32 dopplerFactor = ComputeDopplerFactor(source - listener, source, listener, soundSpeed, 1.0f); + + REQUIRE(std::abs(dopplerFactor - 0.927166343f) < kEpsilon); + } + + SECTION("next power of two") + { + REQUIRE(NextPowerOf2(1) == 1); + REQUIRE(NextPowerOf2(2) == 2); + REQUIRE(NextPowerOf2(3) == 4); + REQUIRE(NextPowerOf2(16) == 16); + REQUIRE(NextPowerOf2(250) == 256); + REQUIRE(NextPowerOf2(4000) == 4096); + REQUIRE(NextPowerOf2(1024) == 1024); + REQUIRE(NextPowerOf2(2024) == 2048); + REQUIRE(NextPowerOf2(4096) == 4096); + } + + SECTION("integer pow") + { + REQUIRE(IntegerPow(2, 0) == 1); + REQUIRE(IntegerPow(2.5, 1) == 2.5); + REQUIRE(IntegerPow(3.1f, 2) == 9.61f); + REQUIRE(IntegerPow(2, 10) == 1024); + } + + SECTION("gcd") + { + REQUIRE(FindGCD(12, 18) == 6); + REQUIRE(FindGCD(20, 30) == 10); + REQUIRE(FindGCD(48, 144) == 48); + REQUIRE(FindGCD(-100, 200) == 100); + REQUIRE(FindGCD(0, 200) == 200); + } } \ No newline at end of file