From e372e2d3116bd990242fc8e0ae1cfe1a790581cc Mon Sep 17 00:00:00 2001 From: Axel Nana Date: Fri, 1 Nov 2024 00:10:33 +0100 Subject: [PATCH] fix: Stability fixes. Signed-off-by: Axel Nana --- sample_project/rtpc/rtpc_player_height.json | 4 +- sample_project/rtpc/wind_force.json | 17 +++ sample_project/soundbanks/init.json | 3 +- sample_project/soundbanks/tests.init.json | 3 +- src/Core/Engine.cpp | 5 +- src/Sound/Rtpc.cpp | 10 +- tests/CMakeLists.txt | 2 +- tests/engine.cpp | 156 ++++++++++++++++++++ tests/thread.cpp | 2 +- 9 files changed, 189 insertions(+), 13 deletions(-) create mode 100644 sample_project/rtpc/wind_force.json diff --git a/sample_project/rtpc/rtpc_player_height.json b/sample_project/rtpc/rtpc_player_height.json index 8fd7a4d3..9dfb7897 100644 --- a/sample_project/rtpc/rtpc_player_height.json +++ b/sample_project/rtpc/rtpc_player_height.json @@ -7,11 +7,11 @@ "enabled": false, "fade_attack": { "duration": 1, - "fader": "Exponential" + "fader": "Linear" }, "fade_release": { "duration": 1, - "fader": "Exponential" + "fader": "Linear" } } } \ No newline at end of file diff --git a/sample_project/rtpc/wind_force.json b/sample_project/rtpc/wind_force.json new file mode 100644 index 00000000..84d5846e --- /dev/null +++ b/sample_project/rtpc/wind_force.json @@ -0,0 +1,17 @@ +{ + "id": 2, + "name": "wind_force", + "min_value": 0, + "max_value": 343000, + "fade_settings": { + "enabled": true, + "fade_attack": { + "duration": 1000, + "fader": "Linear" + }, + "fade_release": { + "duration": 500, + "fader": "Linear" + } + } +} \ No newline at end of file diff --git a/sample_project/soundbanks/init.json b/sample_project/soundbanks/init.json index 46fd36c8..a84ba3b7 100644 --- a/sample_project/soundbanks/init.json +++ b/sample_project/soundbanks/init.json @@ -57,6 +57,7 @@ "footsteps.amswitchcontainer" ], "rtpc": [ - "rtpc_player_height.amrtpc" + "rtpc_player_height.amrtpc", + "wind_force.amrtpc" ] } \ No newline at end of file diff --git a/sample_project/soundbanks/tests.init.json b/sample_project/soundbanks/tests.init.json index d0b49e19..5205b00d 100644 --- a/sample_project/soundbanks/tests.init.json +++ b/sample_project/soundbanks/tests.init.json @@ -61,6 +61,7 @@ "footsteps.amswitchcontainer" ], "rtpc": [ - "rtpc_player_height.amrtpc" + "rtpc_player_height.amrtpc", + "wind_force.amrtpc" ] } \ No newline at end of file diff --git a/src/Core/Engine.cpp b/src/Core/Engine.cpp index c1255d9e..d1082b8b 100644 --- a/src/Core/Engine.cpp +++ b/src/Core/Engine.cpp @@ -1840,7 +1840,10 @@ namespace SparkyStudios::Audio::Amplitude void EngineImpl::SetDefaultListener(const Listener* listener) { - if (listener->Valid()) + if (listener == nullptr) + _defaultListener = nullptr; + + else if (listener->Valid()) _defaultListener = listener->GetState(); } diff --git a/src/Sound/Rtpc.cpp b/src/Sound/Rtpc.cpp index ef69f9ed..102f4340 100644 --- a/src/Sound/Rtpc.cpp +++ b/src/Sound/Rtpc.cpp @@ -51,23 +51,21 @@ namespace SparkyStudios::Audio::Amplitude void RtpcImpl::Update(AmTime deltaTime) { if (_faderRelease && _currentValue > _targetValue) - { _currentValue = _faderRelease->GetFromTime(Engine::GetInstance()->GetTotalTime()); - } if (_faderAttack && _currentValue < _targetValue) - { _currentValue = _faderAttack->GetFromTime(Engine::GetInstance()->GetTotalTime()); - } + + _currentValue = std::clamp(_currentValue, _minValue, _maxValue); } void RtpcImpl::SetValue(AmReal64 value) { - _targetValue = AM_CLAMP(value, _minValue, _maxValue); + _targetValue = std::clamp(value, _minValue, _maxValue); if (_faderAttack == nullptr || _faderRelease == nullptr) { - _currentValue = value; + _currentValue = _targetValue; } else { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ab4d9f92..e6de530e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -36,7 +36,7 @@ add_executable(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} PRIVATE Catch2::Catch2 Static) add_custom_target(ss_amplitude_audio_test_package - COMMAND $ -v -c 0 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/samples/assets ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/samples/assets.ampk + COMMAND $ -q -c 0 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/samples/assets" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/samples/assets.ampk" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) diff --git a/tests/engine.cpp b/tests/engine.cpp index 483cd7e0..10760e08 100644 --- a/tests/engine.cpp +++ b/tests/engine.cpp @@ -216,6 +216,33 @@ TEST_CASE("Engine Tests", "[engine][core][amplitude]") amEngine->SetDefaultListener(1); REQUIRE(amEngine->GetDefaultListener().GetState() == listener.GetState()); + THEN("it can set its master gain") + { + amEngine->SetMasterGain(0.1f); + REQUIRE(amEngine->GetMasterGain() == 0.1f); + + amEngine->SetMasterGain(1.0f); + REQUIRE(amEngine->GetMasterGain() == 1.0f); + } + + THEN("it can be muted") + { + amEngine->SetMute(true); + REQUIRE(amEngine->IsMuted()); + + amEngine->SetMute(false); + REQUIRE_FALSE(amEngine->IsMuted()); + } + + THEN("it can be paused") + { + amEngine->Pause(true); + REQUIRE(amEngine->IsPaused()); + + amEngine->Pause(false); + REQUIRE_FALSE(amEngine->IsPaused()); + } + THEN("it can load sound files") { REQUIRE(amEngine->TryFinalizeLoadSoundFiles()); @@ -286,6 +313,15 @@ TEST_CASE("Engine Tests", "[engine][core][amplitude]") REQUIRE_FALSE(l3.Valid()); REQUIRE_FALSE(l4.Valid()); REQUIRE_FALSE(l5.Valid()); + + AND_THEN("it ca set the default listener") + { + amEngine->SetDefaultListener(&l1); + REQUIRE(amEngine->GetDefaultListener().GetState() == l1.GetState()); + + amEngine->SetDefaultListener(nullptr); + REQUIRE_FALSE(amEngine->GetDefaultListener().Valid()); + } } THEN("it can register environments") @@ -541,6 +577,22 @@ TEST_CASE("Engine Tests", "[engine][core][amplitude]") SwitchHandle invalidSwitch2 = amEngine->GetSwitchHandle(99999); REQUIRE(invalidSwitch2 == nullptr); + AND_THEN("engine cannot set switch states of invalid switch IDs") + { + // This is to increase coverage, the methods will effectively do nothing with invalid handles + amEngine->SetSwitchState(99999, 1); + amEngine->SetSwitchState(99999, "unknown"); + amEngine->SetSwitchState(99999, SwitchState()); + } + + AND_THEN("engine cannot set switch states of invalid switch names") + { + // This is to increase coverage, the methods will effectively do nothing with invalid handles + amEngine->SetSwitchState("invalid_switch", 1); + amEngine->SetSwitchState("invalid_switch", "unknown"); + amEngine->SetSwitchState("invalid_switch", SwitchState()); + } + AND_THEN("engine cannot set switch states of invalid switch handles") { // This is to increase coverage, the methods will effectively do nothing with invalid handles @@ -550,6 +602,45 @@ TEST_CASE("Engine Tests", "[engine][core][amplitude]") } } + THEN("engine can load rtpc handles by name") + { + RtpcHandle rtpc1 = amEngine->GetRtpcHandle("rtpc_player_height"); + REQUIRE(rtpc1 != nullptr); + } + + THEN("engine can load rtpc handles by ID") + { + RtpcHandle rtpc1 = amEngine->GetRtpcHandle(1); + REQUIRE(rtpc1 != nullptr); + } + + THEN("engine cannot load rtpc handles with invalid names or IDs") + { + RtpcHandle invalidRtpc1 = amEngine->GetRtpcHandle("invalid_rtpc"); + REQUIRE(invalidRtpc1 == nullptr); + + RtpcHandle invalidRtpc2 = amEngine->GetRtpcHandle(99999); + REQUIRE(invalidRtpc2 == nullptr); + + AND_THEN("engine cannot set rtpc values of invalid rtpc IDs") + { + // This is to increase coverage, the methods will effectively do nothing with invalid handles + amEngine->SetRtpcValue(99999, 1); + } + + AND_THEN("engine cannot set rtpc values of invalid rtpc names") + { + // This is to increase coverage, the methods will effectively do nothing with invalid handles + amEngine->SetRtpcValue("invalid_rtpc", 1); + } + + AND_THEN("engine cannot set rtpc values of invalid rtpc handles") + { + // This is to increase coverage, the methods will effectively do nothing with invalid handles + amEngine->SetRtpcValue(invalidRtpc1, 1); + } + } + GIVEN("a playing channel") { AmVec3 location = { 10.0f, 20.0f, 30.0f }; @@ -896,6 +987,71 @@ TEST_CASE("Engine Tests", "[engine][core][amplitude]") } } } + + GIVEN("a rtpc") + { + RtpcHandle rtpc1 = amEngine->GetRtpcHandle(1); + REQUIRE(rtpc1 != nullptr); + + RtpcHandle rtpc2 = amEngine->GetRtpcHandle("wind_force"); + REQUIRE(rtpc2 != nullptr); + + THEN("it can change its value") + { + rtpc1->SetValue(50); + REQUIRE(rtpc1->GetValue() == 50.0); + + rtpc2->SetValue(1000); + REQUIRE_FALSE(rtpc2->GetValue() == 1000); + amEngine->WaitUntilFrames(65); + REQUIRE(std::abs(rtpc2->GetValue() - 1000.0) < kEpsilon); + + AND_THEN("engine can change its value by ID") + { + amEngine->SetRtpcValue(rtpc1->GetId(), 75); + REQUIRE(rtpc1->GetValue() == 75.0); + + amEngine->SetRtpcValue(rtpc2->GetId(), 75); + REQUIRE_FALSE(rtpc2->GetValue() == 75.0); + amEngine->WaitUntilFrames(35); + REQUIRE(std::abs(rtpc2->GetValue() - 75.0) < kEpsilon); + } + + AND_THEN("engine can change its value by name") + { + amEngine->SetRtpcValue(rtpc1->GetName(), 80); + REQUIRE(rtpc1->GetValue() == 80.0); + + amEngine->SetRtpcValue(rtpc2->GetId(), 75000); + REQUIRE_FALSE(rtpc2->GetValue() == 75000.0); + amEngine->WaitUntilFrames(65); + REQUIRE(std::abs(rtpc2->GetValue() - 75000.0) < kEpsilon); + } + + AND_THEN("engine can change its value by handle") + { + amEngine->SetRtpcValue(rtpc1, 90); + REQUIRE(rtpc1->GetValue() == 90.0); + + amEngine->SetRtpcValue(rtpc2->GetId(), 90); + REQUIRE_FALSE(rtpc2->GetValue() == 90.0); + amEngine->WaitUntilFrames(35); + REQUIRE(std::abs(rtpc2->GetValue() - 90.0) < kEpsilon); + } + } + + THEN("it cannot set values higher than max") + { + rtpc1->SetValue(rtpc1->GetMaxValue() * 2); + REQUIRE(rtpc1->GetValue() == rtpc1->GetMaxValue()); + } + + THEN("it cannot set values lower than min") + { + rtpc1->SetValue(rtpc1->GetMinValue() * -2); + REQUIRE(rtpc1->GetValue() == rtpc1->GetMinValue()); + } + } } } } diff --git a/tests/thread.cpp b/tests/thread.cpp index 6beab9fa..a966c257 100644 --- a/tests/thread.cpp +++ b/tests/thread.cpp @@ -103,7 +103,7 @@ TEST_CASE("Thread Tests", "[thread][amplitude]") SECTION("can correctly sleep a thread for a duration") { const auto start = Thread::GetTimeMillis(); - Thread::Sleep(100); + Thread::Sleep(105); const auto end = Thread::GetTimeMillis(); REQUIRE((end - start) >= 100); // Should at least run for 100ms