From 3d50c252969907debfeb107d04bf00daa9386bba Mon Sep 17 00:00:00 2001 From: Pirulax Date: Wed, 17 Jul 2024 16:51:27 +0200 Subject: [PATCH 01/22] Refactor `PlayGoggleSound` --- .../Audio/entities/AEWeaponAudioEntity.cpp | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp index 033f4e0bb2..58fd194c60 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp @@ -280,30 +280,21 @@ void CAEWeaponAudioEntity::PlayGunSounds(CPhysical* entity, int16 emptySfxId, in // 0x503500 void CAEWeaponAudioEntity::PlayGoggleSound(int16 sfxId, eAudioEvents event) { - const auto volume = GetDefaultVolume(event); if (!AEAudioHardware.IsSoundBankLoaded(143u, 5)) { if (!AudioEngine.IsLoadingTuneActive()) { AEAudioHardware.LoadSoundBank(143, 5); } return; } - - const auto [speed0, speed1] = [] { - if (CAEAudioUtility::ResolveProbability(0.5f)) { - return std::make_pair(1.1892101f, 1.0f); - } else { - return std::make_pair(1.0f, 1.1892101f); - } - }(); - const auto vol = volume - 9.0f; - - m_tempSound.Initialise(5, sfxId, this, { -1.0f, 0.0f, 0.0f }, vol, 1.0f, speed0, 1.0f, 0, SOUND_DEFAULT); - m_tempSound.m_nEnvironmentFlags = SOUND_FRONT_END | SOUND_FORCED_FRONT; - AESoundManager.RequestNewSound(&m_tempSound); - - m_tempSound.Initialise(5, sfxId, this, { +1.0f, 0.0f, 0.0f }, vol, 1.0f, speed1, 1.0f, 0, SOUND_DEFAULT); - m_tempSound.m_nEnvironmentFlags = SOUND_FRONT_END | SOUND_FORCED_FRONT; - AESoundManager.RequestNewSound(&m_tempSound); + const auto PlaySound = [&](float offsetX, float speed) { + CAESound s; + s.Initialise(5, sfxId, this, { offsetX, 0.0f, 0.0f }, GetDefaultVolume(event) - 9.f, 1.0f, speed, 1.0f, 0, SOUND_DEFAULT); + s.m_nEnvironmentFlags = SOUND_FRONT_END | SOUND_FORCED_FRONT; + AESoundManager.RequestNewSound(&s); + }; + const auto r = CAEAudioUtility::ResolveProbability(0.5f); + PlaySound(-1.0f, r ? 1.1892101f : 1.f); + PlaySound(+1.0f, r ? 1.f : 1.1892101f); } // 0x504470 From afb327820aea346bc63baa0f35726f2da3495ac5 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Wed, 17 Jul 2024 16:51:44 +0200 Subject: [PATCH 02/22] `PlayMiniGunFireSounds` --- .../Audio/entities/AEWeaponAudioEntity.cpp | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp index 58fd194c60..02e2b61517 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp @@ -268,8 +268,52 @@ void CAEWeaponAudioEntity::PlayMiniGunStopSound(CPhysical* entity) { } // 0x5047C0 -void CAEWeaponAudioEntity::PlayMiniGunFireSounds(CPhysical* entity, int32 audioEventId) { - plugin::CallMethod<0x5047C0, CAEWeaponAudioEntity*, CPhysical*, int32>(this, entity, audioEventId); +void CAEWeaponAudioEntity::PlayMiniGunFireSounds(CPhysical* entity, eAudioEvents audioEvent) { + const auto PlayMiniGunFireSound = [&](eAudioEvents gunFireAE) { + m_MiniGunState = eMiniGunState::FIRING; + if (!std::exchange(m_IsMiniGunFireActive, true)) { + PlayGunSounds(entity, 15, 16, 11, 12, 13, gunFireAE, 0.f, 1.f, 1.f); + } + }; + switch (audioEvent) { + case AE_WEAPON_FIRE: + case AE_WEAPON_FIRE_MINIGUN_AMMO: { // 0x504912 + return PlayMiniGunFireSound(AE_WEAPON_FIRE_MINIGUN_AMMO); + } + case AE_WEAPON_FIRE_PLANE: { // 0x5047E6 + return PlayMiniGunFireSound(AE_WEAPON_FIRE_MINIGUN_PLANE); + } + case AE_WEAPON_FIRE_MINIGUN_NO_AMMO: { // 0x5048FC + if (!m_IsMiniGunSpinActive) { + if (!AEAudioHardware.IsSoundBankLoaded(143, 5)) { // SND_BANK_GENRL_WEAPONS, SND_BANK_SLOT_WEAPON_GEN + if (!AudioEngine.IsLoadingTuneActive()) { + AEAudioHardware.LoadSoundBank(143, 5); + } + break; + } + CAESound s; + s.Initialise( + 5, + 14, + this, + entity->GetPosition(), + GetDefaultVolume(AE_WEAPON_FIRE_MINIGUN_NO_AMMO), + 2.f / 3.f, + 1.f, + 0.f, + 0, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); + s.m_nEvent = AE_FRONTEND_NOISE_TEST; + s.RegisterWithPhysicalEntity(entity); + AESoundManager.RequestNewSound(&s); + m_IsMiniGunSpinActive = true; + } + m_MiniGunState = eMiniGunState::SPINNING; + break; + } + } + m_LastMiniGunFireTimeMs = CTimer::GetTimeInMS(); } // 0x503CE0 From 693e3d759c6b7b9bca88a61ebf6873e48149e38c Mon Sep 17 00:00:00 2001 From: Pirulax Date: Wed, 17 Jul 2024 16:51:56 +0200 Subject: [PATCH 03/22] Refactor `PlayWeaponLoopSound` --- .../Audio/entities/AEWeaponAudioEntity.cpp | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp index 02e2b61517..2b943fa2fd 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp @@ -234,12 +234,11 @@ void CAEWeaponAudioEntity::PlayWeaponLoopSound(CPhysical* entity, int16 sfxId, e // 0x504960 void CAEWeaponAudioEntity::PlayMiniGunStopSound(CPhysical* entity) { if (!entity) { - m_nState = 3; + m_MiniGunState = eMiniGunState::STOPPED; return; } - if (m_nState == 2) { // todo: figure out what is that - m_nState = 2; + if (m_MiniGunState == eMiniGunState::STOPPING) { return; } @@ -250,21 +249,30 @@ void CAEWeaponAudioEntity::PlayMiniGunStopSound(CPhysical* entity) { return; } - const auto [distMult, speed] = [&] { - if (entity->IsVehicle() && entity->AsVehicle()->IsSubPlane()) { - return std::make_pair(1.8f, 0.7937f); - } else { - return std::make_pair(1.0f, 1.0f); - } - }(); - const auto dist = distMult * 0.66f; - const auto volume = CAEAudioEntity::GetDefaultVolume(AE_WEAPON_FIRE_MINIGUN_STOP); - const auto flags = static_cast(SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES); - m_tempSound.Initialise(5, 63, this, entity->GetPosition(), volume, dist, speed, 1.0f, 0, flags); - m_tempSound.RegisterWithPhysicalEntity(entity); - m_tempSound.m_nEvent = AE_FRONTEND_PICKUP_HEALTH; - AESoundManager.RequestNewSound(&m_tempSound); - m_nState = 2; + const auto PlayMiniGunFireStopSound = [&](float speed, float maxDist) { + CAESound s; + s.Initialise( + 5, + 63, + this, + entity->GetPosition(), + GetDefaultVolume(AE_WEAPON_FIRE_MINIGUN_STOP), + maxDist * 2.f / 3.f, // *0.66....f + speed, + 1.0f, + 0, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); + s.RegisterWithPhysicalEntity(entity); + s.m_nEvent = AE_FRONTEND_PICKUP_HEALTH; // ??? + AESoundManager.RequestNewSound(&s); + }; + if (entity->IsVehicle() && entity->AsVehicle()->IsSubPlane()) { + PlayMiniGunFireStopSound(1.8f, 0.7937f); + } else { + PlayMiniGunFireStopSound(1.f, 1.f); + } + m_MiniGunState = eMiniGunState::STOPPING; } // 0x5047C0 From f6109eb692181ff83ba91e84139f48cf24848a9f Mon Sep 17 00:00:00 2001 From: Pirulax Date: Wed, 17 Jul 2024 16:52:09 +0200 Subject: [PATCH 04/22] Refactor class var names, etc --- source/game_sa/Audio/AESound.cpp | 2 +- source/game_sa/Audio/AESound.h | 2 +- .../Audio/entities/AEWeaponAudioEntity.cpp | 93 ++++++++++--------- .../Audio/entities/AEWeaponAudioEntity.h | 55 ++++++----- 4 files changed, 80 insertions(+), 72 deletions(-) diff --git a/source/game_sa/Audio/AESound.cpp b/source/game_sa/Audio/AESound.cpp index 4b438ea2ed..79e391a657 100644 --- a/source/game_sa/Audio/AESound.cpp +++ b/source/game_sa/Audio/AESound.cpp @@ -298,7 +298,7 @@ void CAESound::CalculateVolume() { // 0x4EFE50 void CAESound::Initialise(int16 bankSlotId, int16 sfxId, CAEAudioEntity* baseAudio, CVector posn, float volume, float maxDistance, float speed, float timeScale, - uint8 ignoredServiceCycles, eSoundEnvironment environmentFlags, float speedVariability, int16 currPlayPosn) + uint8 ignoredServiceCycles, uint32 environmentFlags, float speedVariability, int16 currPlayPosn) { UnregisterWithPhysicalEntity(); diff --git a/source/game_sa/Audio/AESound.h b/source/game_sa/Audio/AESound.h index 89695d9b98..e45bf74407 100644 --- a/source/game_sa/Audio/AESound.h +++ b/source/game_sa/Audio/AESound.h @@ -103,7 +103,7 @@ class CAESound { float speed = 1.0f, float timeScale = 1.0f, uint8 ignoredServiceCycles = 0, - eSoundEnvironment environmentFlags = static_cast(0), + /*eSoundEnvironment*/ uint32 environmentFlags = static_cast(0), float speedVariability = 0, int16 currPlayPosn = 0); diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp index 2b943fa2fd..e1378ddc2b 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp @@ -13,6 +13,33 @@ #include "AEAudioHardware.h" #include "AEAudioUtility.h" +void CAEWeaponAudioEntity::InjectHooks() { + RH_ScopedClass(CAEWeaponAudioEntity); + RH_ScopedCategory("Audio/Entities"); + + RH_ScopedInstall(Constructor, 0x5DE990); + RH_ScopedInstall(Destructor, 0x507560); + RH_ScopedInstall(Initialise, 0x503450); + RH_ScopedInstall(Reset, 0x503490); + RH_ScopedInstall(Terminate, 0x503480); + RH_ScopedInstall(WeaponFire, 0x504F80); + RH_ScopedInstall(WeaponReload, 0x503690); + RH_ScopedInstall(PlayChainsawStopSound, 0x504AA0); + RH_ScopedInstall(PlayMiniGunStopSound, 0x504960); + RH_ScopedInstall(PlayMiniGunFireSounds, 0x5047C0); + RH_ScopedInstall(PlayCameraSound, 0x5046F0); + RH_ScopedInstall(PlayWeaponLoopSound, 0x504610); + RH_ScopedInstall(PlayFlameThrowerSounds, 0x504470, { .reversed = false }); + RH_ScopedInstall(PlayGunSounds, 0x503CE0, { .reversed = false }); + RH_ScopedInstall(ReportStealthKill, 0x503B20); + RH_ScopedInstall(ReportChainsawEvent, 0x503910, { .reversed = false }); + RH_ScopedInstall(PlayFlameThrowerIdleGasLoop, 0x503870); + RH_ScopedInstall(PlayGoggleSound, 0x503500); + RH_ScopedInstall(StopFlameThrowerIdleGasLoop, 0x5034E0); + RH_ScopedInstall(UpdateParameters, 0x504B70, { .reversed = false }); + +} + // 0x507560 CAEWeaponAudioEntity::CAEWeaponAudioEntity() { Clear(); @@ -20,8 +47,8 @@ CAEWeaponAudioEntity::CAEWeaponAudioEntity() { // 0x503450 void CAEWeaponAudioEntity::Initialise() { - m_nState = 3; - m_nChainsawSoundState = 4; + m_MiniGunState = eMiniGunState::STOPPED; + m_ChainsawState = 4; if (!AudioEngine.IsLoadingTuneActive()) { AEAudioHardware.LoadSoundBank(143, 5); } @@ -40,8 +67,9 @@ void CAEWeaponAudioEntity::Reset() { // 0x504F80 void CAEWeaponAudioEntity::WeaponFire(eWeaponType type, CPhysical* entity, eAudioEvents audioEventId) { - if (!entity) + if (!entity) { return; + } switch (type) { case WEAPON_PISTOL: @@ -80,9 +108,9 @@ void CAEWeaponAudioEntity::WeaponFire(eWeaponType type, CPhysical* entity, eAudi return PlayGunSounds(entity, 52, 53, 26, 27, 23, audioEventId, 0.0f, 1.0f, 1.0f); case WEAPON_FLAMETHROWER: - if (!m_nFlameThrowerLastPlayedTime) + if (!m_FlameThrowerLastPlayedTimeMs) PlayFlameThrowerSounds(entity, 83, 26, audioEventId, -14.0f, 1.0f); - m_nFlameThrowerLastPlayedTime = CTimer::GetTimeInMS(); + m_FlameThrowerLastPlayedTimeMs = CTimer::GetTimeInMS(); break; case WEAPON_MINIGUN: @@ -92,17 +120,17 @@ void CAEWeaponAudioEntity::WeaponFire(eWeaponType type, CPhysical* entity, eAudi return PlayGunSounds(entity, 49, -1, -1, -1, -1, audioEventId, -14.0f, 1.0f, 1.0f); case WEAPON_SPRAYCAN: - if (!m_nSpraycanLastPlayedTime) + if (!m_LastSprayCanFireTimeMs) { PlayWeaponLoopSound(entity, 28, audioEventId, -20.0f, 1.0f, AE_FRONTEND_HIGHLIGHT); - - m_nSpraycanLastPlayedTime = CTimer::GetTimeInMS(); + } + m_LastSprayCanFireTimeMs = CTimer::GetTimeInMS(); break; case WEAPON_EXTINGUISHER: - if (!m_nExtinguisherLastPlayedTime) + if (!m_LastFireExtFireTimeMs) PlayWeaponLoopSound(entity, 9, audioEventId, -20.0f, 0.79369998f, AE_FRONTEND_ERROR); - m_nExtinguisherLastPlayedTime = CTimer::GetTimeInMS(); + m_LastFireExtFireTimeMs = CTimer::GetTimeInMS(); break; case WEAPON_CAMERA: @@ -356,28 +384,28 @@ void CAEWeaponAudioEntity::PlayFlameThrowerSounds(CPhysical* entity, int16 sfx1, // 0x503870 void CAEWeaponAudioEntity::PlayFlameThrowerIdleGasLoop(CPhysical* entity) { - if (m_FlameThrowerSound != nullptr) + if (m_FlameThrowerIdleGasLoopSound != nullptr) return; const auto volume = GetDefaultVolume(AE_FLAMETHROWER_IDLE); const auto flags = static_cast(SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES); m_tempSound.Initialise(5, 10, this, entity->GetPosition(), volume, 0.66f, 1.0f, 1.0f, 0, flags); m_tempSound.RegisterWithPhysicalEntity(entity); - m_FlameThrowerSound = AESoundManager.RequestNewSound(&m_tempSound); + m_FlameThrowerIdleGasLoopSound = AESoundManager.RequestNewSound(&m_tempSound); } // 0x5034E0 void CAEWeaponAudioEntity::StopFlameThrowerIdleGasLoop() { - if (m_FlameThrowerSound) { - m_FlameThrowerSound->StopSoundAndForget(); - m_FlameThrowerSound = nullptr; + if (m_FlameThrowerIdleGasLoopSound) { + m_FlameThrowerIdleGasLoopSound->StopSoundAndForget(); + m_FlameThrowerIdleGasLoopSound = nullptr; } } // 0x504AA0 void CAEWeaponAudioEntity::PlayChainsawStopSound(CPhysical* entity) { if (entity && AEAudioHardware.IsSoundBankLoaded(0x24u, 40)) { - if (m_nChainsawSoundState != 3) { + if (m_ChainsawState != 3) { const auto volume = GetDefaultVolume(AE_WEAPON_CHAINSAW_ACTIVE); const auto flags = static_cast(SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES); m_tempSound.Initialise(40, 2, this, entity->GetPosition(), volume, 0.66f, 1.0f, 1.0f, 0, flags); @@ -385,9 +413,9 @@ void CAEWeaponAudioEntity::PlayChainsawStopSound(CPhysical* entity) { m_tempSound.m_nEvent = AE_FRONTEND_PICKUP_DRUGS; AESoundManager.RequestNewSound(&m_tempSound); } - m_nChainsawSoundState = 3; + m_ChainsawState = 3; } else { - m_nChainsawSoundState = 4; + m_ChainsawState = 4; } } @@ -412,33 +440,6 @@ void CAEWeaponAudioEntity::UpdateParameters(CAESound *sound, int16 curPlayPos) { plugin::CallMethod<0x504B70, CAEWeaponAudioEntity*, CAESound*, int16>(this, sound, curPlayPos); } -void CAEWeaponAudioEntity::InjectHooks() { - RH_ScopedClass(CAEWeaponAudioEntity); - RH_ScopedCategory("Audio/Entities"); - - RH_ScopedInstall(Constructor, 0x5DE990); - RH_ScopedInstall(Destructor, 0x507560); - RH_ScopedInstall(Initialise, 0x503450); - RH_ScopedInstall(Reset, 0x503490); - RH_ScopedInstall(Terminate, 0x503480); - RH_ScopedInstall(WeaponFire, 0x504F80); - RH_ScopedInstall(WeaponReload, 0x503690); - RH_ScopedInstall(PlayChainsawStopSound, 0x504AA0); - RH_ScopedInstall(PlayMiniGunStopSound, 0x504960); - RH_ScopedInstall(PlayMiniGunFireSounds, 0x5047C0, { .reversed = false }); - RH_ScopedInstall(PlayCameraSound, 0x5046F0); - RH_ScopedInstall(PlayWeaponLoopSound, 0x504610); - RH_ScopedInstall(PlayFlameThrowerSounds, 0x504470, { .reversed = false }); - RH_ScopedInstall(PlayGunSounds, 0x503CE0, { .reversed = false }); - RH_ScopedInstall(ReportStealthKill, 0x503B20); - RH_ScopedInstall(ReportChainsawEvent, 0x503910, { .reversed = false }); - RH_ScopedInstall(PlayFlameThrowerIdleGasLoop, 0x503870); - RH_ScopedInstall(PlayGoggleSound, 0x503500); - RH_ScopedInstall(StopFlameThrowerIdleGasLoop, 0x5034E0); - RH_ScopedInstall(UpdateParameters, 0x504B70, { .reversed = false }); - -} - CAEWeaponAudioEntity* CAEWeaponAudioEntity::Constructor() { this->CAEWeaponAudioEntity::CAEWeaponAudioEntity(); return this; @@ -449,4 +450,4 @@ CAEWeaponAudioEntity* CAEWeaponAudioEntity::Destructor() { return this; } -// 0x504B70 \ No newline at end of file +// 0x504B70 diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.h b/source/game_sa/Audio/entities/AEWeaponAudioEntity.h index 811b17da3f..70457d46f8 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.h +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.h @@ -15,19 +15,12 @@ class CPhysical; class CPed; class NOTSA_EXPORT_VTABLE CAEWeaponAudioEntity : public CAEAudioEntity { -public: - bool m_bPlayedMiniGunFireSound; - bool field_7D; // see PlayMiniGunFireSounds - uint8 field_7E; // see PlayGunSounds, gfWeaponPlaneFrequencyVariations - int8 m_nState; - uint8 m_nChainsawSoundState; - uint32 m_nFlameThrowerLastPlayedTime; - uint32 m_nSpraycanLastPlayedTime; - uint32 m_nExtinguisherLastPlayedTime; - uint32 m_nMiniGunFireSoundPlayedTime; - uint32 m_nTimeChainsaw; - uint32 m_nTimeLastFired; - CAESound* m_FlameThrowerSound; + enum class eMiniGunState : int8 { + SPINNING = 0x0, + FIRING = 0x1, + STOPPING = 0x2, + STOPPED = 0x3, + }; public: CAEWeaponAudioEntity(); @@ -50,7 +43,7 @@ class NOTSA_EXPORT_VTABLE CAEWeaponAudioEntity : public CAEAudioEntity { void PlayWeaponLoopSound(CPhysical* entity, int16 sfxId, eAudioEvents startEvent, float audability, float speed, eAudioEvents endEvent); - void PlayMiniGunFireSounds(CPhysical* entity, int32 audioEventId); + void PlayMiniGunFireSounds(CPhysical* entity, eAudioEvents audioEventId); void PlayMiniGunStopSound(CPhysical* entity); void PlayFlameThrowerSounds(CPhysical* entity, int16 sfx1, int16 sfx2, int32 audioEventId, float audability, float speed); @@ -62,19 +55,33 @@ class NOTSA_EXPORT_VTABLE CAEWeaponAudioEntity : public CAEAudioEntity { void UpdateParameters(CAESound* sound, int16 curPlayPos) override; void Clear() { - m_nFlameThrowerLastPlayedTime = 0; - m_nSpraycanLastPlayedTime = 0; - m_nExtinguisherLastPlayedTime = 0; - m_FlameThrowerSound = nullptr; - field_7E = 0; - m_nMiniGunFireSoundPlayedTime = 0; - m_bPlayedMiniGunFireSound = false; - field_7D = false; - m_nTimeChainsaw = 0; - m_nTimeLastFired = 0; + m_FlameThrowerLastPlayedTimeMs = 0; + m_LastSprayCanFireTimeMs = 0; + m_LastFireExtFireTimeMs = 0; + m_FlameThrowerIdleGasLoopSound = nullptr; + m_LastWeaponPlaneFrequencyIndex = 0; + m_LastMiniGunFireTimeMs = 0; + m_IsMiniGunSpinActive = false; + m_IsMiniGunFireActive = false; + m_LastChainsawEventTimeMs = 0; + m_LastGunFireTimeMs = 0; } private: + bool m_IsMiniGunSpinActive; + bool m_IsMiniGunFireActive; // see PlayMiniGunFireSounds + uint8 m_LastWeaponPlaneFrequencyIndex; // see PlayGunSounds, gfWeaponPlaneFrequencyVariations + eMiniGunState m_MiniGunState; + uint8 m_ChainsawState; + uint32 m_FlameThrowerLastPlayedTimeMs; + uint32 m_LastSprayCanFireTimeMs; + uint32 m_LastFireExtFireTimeMs; + uint32 m_LastMiniGunFireTimeMs; + uint32 m_LastChainsawEventTimeMs; + uint32 m_LastGunFireTimeMs; + CAESound* m_FlameThrowerIdleGasLoopSound; + +private: // Hook stuff friend void InjectHooksMain(); static void InjectHooks(); From 905faa487804b24c55fb87424b278d01e35ff737 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Thu, 18 Jul 2024 11:20:14 +0200 Subject: [PATCH 05/22] Fix `CAEAudioUtility::AudioLog10` --- source/game_sa/Audio/AEAudioUtility.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/game_sa/Audio/AEAudioUtility.cpp b/source/game_sa/Audio/AEAudioUtility.cpp index 7b1763ec85..7b6a56d28c 100644 --- a/source/game_sa/Audio/AEAudioUtility.cpp +++ b/source/game_sa/Audio/AEAudioUtility.cpp @@ -65,7 +65,9 @@ float CAEAudioUtility::GetPiecewiseLinear(float x, int16 dataCount, float (*data // 0x4d9e50 float CAEAudioUtility::AudioLog10(float p) { - return 0.00001f <= p ? std::log10f(p) : -5.0f; + return p >= 0.00001f + ? std::log10f(p) + : -5.0f; } // REFACTORED From dcaff181c17c457280884ba13e8ee6baf4fb9840 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Thu, 18 Jul 2024 11:20:50 +0200 Subject: [PATCH 06/22] Fix `CAEAudioUtility::GetCurrentTimeInMS` --- source/game_sa/Audio/AEAudioUtility.cpp | 15 +++++++++++---- source/game_sa/Audio/AEAudioUtility.h | 1 - 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/source/game_sa/Audio/AEAudioUtility.cpp b/source/game_sa/Audio/AEAudioUtility.cpp index 7b6a56d28c..e692de91ae 100644 --- a/source/game_sa/Audio/AEAudioUtility.cpp +++ b/source/game_sa/Audio/AEAudioUtility.cpp @@ -4,7 +4,8 @@ #include "AEAudioUtility.h" -uint64& CAEAudioUtility::startTimeMs = *reinterpret_cast(0xb610f8); +auto& Frequency = StaticRef(0xB610F0); +uint64& startTimeMs = *reinterpret_cast(0xb610f8); float (&CAEAudioUtility::m_sfLogLookup)[50][2] = *reinterpret_cast(0xb61100); // NOTE: Not sure about the size. @@ -74,9 +75,14 @@ float CAEAudioUtility::AudioLog10(float p) { // 0x4d9e80 uint64 CAEAudioUtility::GetCurrentTimeInMS() { using namespace std::chrono; - auto nowMs = time_point_cast(high_resolution_clock::now()); - auto value = duration_cast(nowMs.time_since_epoch()); - return static_cast(value.count()); + const auto nowMs = time_point_cast(high_resolution_clock::now()); + const auto value = duration_cast(nowMs.time_since_epoch()); + return static_cast(value.count()) - startTimeMs; + + //For some reason this doesn't work (original code): + //LARGE_INTEGER counter; + //QueryPerformanceCounter(&counter); + //return counter.QuadPart / Frequency.QuadPart * 1000 - startTimeMs; } // 0x4d9ef0 @@ -105,6 +111,7 @@ void CAEAudioUtility::StaticInitialise() { m_sfLogLookup[1][1] = log10f(v); } + VERIFY(QueryPerformanceFrequency(&Frequency)); startTimeMs = GetCurrentTimeInMS(); } diff --git a/source/game_sa/Audio/AEAudioUtility.h b/source/game_sa/Audio/AEAudioUtility.h index 7b4cc80377..2505368123 100644 --- a/source/game_sa/Audio/AEAudioUtility.h +++ b/source/game_sa/Audio/AEAudioUtility.h @@ -27,7 +27,6 @@ class CAEAudioUtility { } private: - static uint64& startTimeMs; static float (&m_sfLogLookup)[50][2]; private: From 2a1691a2fe1991eaf90c68b2edfda8a3218e7763 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Thu, 18 Jul 2024 11:21:12 +0200 Subject: [PATCH 07/22] Refactor `CAEAudioEnvironment::GetPositionRelativeToCamera` --- source/game_sa/Audio/AEAudioEnvironment.cpp | 59 ++++++++++----------- source/game_sa/Audio/AEAudioEnvironment.h | 8 ++- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/source/game_sa/Audio/AEAudioEnvironment.cpp b/source/game_sa/Audio/AEAudioEnvironment.cpp index 62082d500f..39ae42f689 100644 --- a/source/game_sa/Audio/AEAudioEnvironment.cpp +++ b/source/game_sa/Audio/AEAudioEnvironment.cpp @@ -95,38 +95,37 @@ void CAEAudioEnvironment::GetReverbEnvironmentAndDepth(int8* reverbEnv, int32* d } // 0x4D80B0 -void CAEAudioEnvironment::GetPositionRelativeToCamera(CVector* vecOut, const CVector* vecPos) { - static const float fFirstPersonMult = 2.0F; - if (!vecPos) - return; - - const auto camMode = CCamera::GetActiveCamera().m_nMode; - if (camMode == eCamMode::MODE_SNIPER || camMode == eCamMode::MODE_ROCKETLAUNCHER || camMode == eCamMode::MODE_1STPERSON) { - const auto& tempMat = TheCamera.m_mCameraMatrix; - const auto& vecCamPos = TheCamera.GetPosition(); - const auto vecOffset = *vecPos - (vecCamPos - tempMat.GetForward() * fFirstPersonMult); - - vecOut->x = -DotProduct(vecOffset, tempMat.GetRight()); - vecOut->y = DotProduct(vecOffset, tempMat.GetForward()); - vecOut->z = DotProduct(vecOffset, tempMat.GetUp()); - return; +void CAEAudioEnvironment::GetPositionRelativeToCamera(CVector& out, const CVector* vecPos) { + assert(vecPos); + //if (!vecPos) + // return {0.f, 0.f, 0.f}; + + const auto& camMat = TheCamera.m_mCameraMatrix; + const auto Calculate = [&](CVector offset) { + const auto pos = *vecPos - TheCamera.GetPosition() + offset; + out = CVector{ // matrix inverse vector transform, with x negated + -DotProduct(pos, camMat.GetRight()), + DotProduct(pos, camMat.GetForward()), + DotProduct(pos, camMat.GetUp()) + }; + }; + switch (CCamera::GetActiveCamera().m_nMode) { + case eCamMode::MODE_SNIPER: + case eCamMode::MODE_ROCKETLAUNCHER: + case eCamMode::MODE_1STPERSON: { + return Calculate(-camMat.GetForward() * 2.f); + } + default: { + const auto* player = FindPlayerPed(); + const auto camDist = player + ? std::clamp(CVector::Dist(TheCamera.GetPosition(), player->GetPosition()), 0.0F, 0.5F) + : 0.f; + return Calculate(camMat.GetForward() * camDist); + } } - - auto fMult = 0.0F; - auto* player = FindPlayerPed(); - if (player) - fMult = std::clamp(DistanceBetweenPoints(TheCamera.GetPosition(), player->GetPosition()), 0.0F, 0.5F); - - const auto& tempMat = TheCamera.m_mCameraMatrix; - const auto& vecCamPos = TheCamera.GetPosition(); - const auto vecOffset = *vecPos - (vecCamPos + tempMat.GetForward() * fMult); - - vecOut->x = -DotProduct(vecOffset, tempMat.GetRight()); - vecOut->y = DotProduct(vecOffset, tempMat.GetForward()); - vecOut->z = DotProduct(vecOffset, tempMat.GetUp()); } // 0x4D8340 -void CAEAudioEnvironment::GetPositionRelativeToCamera(CVector* vecOut, CPlaceable* placeable) { - return CAEAudioEnvironment::GetPositionRelativeToCamera(vecOut, &placeable->GetPosition()); +void CAEAudioEnvironment::GetPositionRelativeToCamera(CVector& out, CPlaceable* placeable) { + CAEAudioEnvironment::GetPositionRelativeToCamera(out, &placeable->GetPosition()); } diff --git a/source/game_sa/Audio/AEAudioEnvironment.h b/source/game_sa/Audio/AEAudioEnvironment.h index c7d7c5afd0..fd2bd63497 100644 --- a/source/game_sa/Audio/AEAudioEnvironment.h +++ b/source/game_sa/Audio/AEAudioEnvironment.h @@ -17,8 +17,12 @@ class CAEAudioEnvironment { static float GetDistanceAttenuation(float dist); static float GetDirectionalMikeAttenuation(const CVector& soundDir); static void GetReverbEnvironmentAndDepth(int8* reverbEnv, int32* depth); - static void GetPositionRelativeToCamera(CVector* vecOut, const CVector* vecPos); - static void GetPositionRelativeToCamera(CVector* vecOut, CPlaceable* placeable); + + static void GetPositionRelativeToCamera(CVector& out, const CVector* vecPos); + static CVector GetPositionRelativeToCamera(const CVector& pos) { CVector o; GetPositionRelativeToCamera(o, &pos); return o; } + + static void GetPositionRelativeToCamera(CVector& out, CPlaceable* placeable); + static CVector GetPositionRelativeToCamera(CPlaceable* placeable) { CVector o; GetPositionRelativeToCamera(o, placeable); return o; } }; static constexpr int32 NUM_AUDIO_ENVIRONMENTS = 68; From bb0e9a90706bb9ea9b8c0418817f8eea27b0a029 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Thu, 18 Jul 2024 11:21:32 +0200 Subject: [PATCH 08/22] Refactor `CAEAudioEnvironment::GetDistanceAttenuation` --- source/game_sa/Audio/AEAudioEnvironment.cpp | 153 ++++++++++++++++++-- source/game_sa/Audio/AEAudioEnvironment.h | 3 - 2 files changed, 142 insertions(+), 14 deletions(-) diff --git a/source/game_sa/Audio/AEAudioEnvironment.cpp b/source/game_sa/Audio/AEAudioEnvironment.cpp index 39ae42f689..c86eb43267 100644 --- a/source/game_sa/Audio/AEAudioEnvironment.cpp +++ b/source/game_sa/Audio/AEAudioEnvironment.cpp @@ -2,7 +2,139 @@ #include "AEAudioEnvironment.h" sReverbEnvironment (&gAudioZoneToReverbEnvironmentMap)[NUM_AUDIO_ENVIRONMENTS] = *(sReverbEnvironment(*)[NUM_AUDIO_ENVIRONMENTS])0x8AD670; -float (&gSoundDistAttenuationTable)[NUM_SOUND_DIST_ATTENUATION_ENTRIES] = *(float(*)[NUM_SOUND_DIST_ATTENUATION_ENTRIES])0x8AC270; + +constexpr auto ATTENUATION_TABLE_RESOLUTION = 0.1f; +constexpr auto ATTENUATION_TABLE_MAX_DIST = 128.f; +constexpr std::array gSoundDistAttenuationTable{ + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0-1 + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 1 + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 2 + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 3 + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 4 + -0.38f, -0.75999999f, -1.13f, -1.49f, -1.86f, -2.21f, -2.5599999f, -2.9100001f, -3.25f, -3.5799999f, // 5 + -3.9100001f, -4.2399998f, -4.5599999f, -4.8800001f, -5.1999998f, -5.5100002f, -5.8200002f, -6.1199999f, -6.4200001f, -6.7199998f, // 6 + -7.0100002f, -7.3000002f, -7.5900002f, -7.8699999f, -8.1499996f, -8.4300003f, -8.71f, -8.9799995f, -9.25f, -9.5100002f, // 7 + -9.7799997f, -10.04f, -10.3f, -10.55f, -10.81f, -11.06f, -11.31f, -11.55f, -11.8f, -12.04f, // 8 + -12.28f, -12.52f, -12.75f, -12.99f, -13.22f, -13.45f, -13.68f, -13.9f, -14.13f, -14.35f, // 9 + -14.57f, -14.79f, -15.01f, -15.22f, -15.44f, -15.65f, -15.86f, -16.07f, -16.27f, -16.48f, // 10 + -16.68f, -16.889999f, -17.09f, -17.290001f, -17.49f, -17.68f, -17.879999f, -18.07f, -18.27f, -18.459999f, // 11 + -18.65f, -18.84f, -19.02f, -19.209999f, -19.389999f, -19.58f, -19.76f, -19.940001f, -20.120001f, -20.299999f, // 12 + -20.48f, -20.66f, -20.83f, -21.01f, -21.18f, -21.360001f, -21.530001f, -21.700001f, -21.870001f, -22.040001f, // 13 + -22.200001f, -22.370001f, -22.540001f, -22.700001f, -22.860001f, -23.030001f, -23.190001f, -23.35f, -23.51f, -23.67f, // 14 + -23.83f, -23.99f, -24.139999f, -24.299999f, -24.450001f, -24.610001f, -24.76f, -24.91f, -25.07f, -25.219999f, // 15 + -25.370001f, -25.52f, -25.66f, -25.809999f, -25.959999f, -26.110001f, -26.25f, -26.4f, -26.540001f, -26.68f, // 16 + -26.83f, -26.969999f, -27.110001f, -27.25f, -27.389999f, -27.530001f, -27.67f, -27.809999f, -27.950001f, -28.08f, // 17 + -28.219999f, -28.35f, -28.49f, -28.620001f, -28.76f, -28.889999f, -29.02f, -29.16f, -29.290001f, -29.42f, // 18 + -29.549999f, -29.68f, -29.809999f, -29.940001f, -30.059999f, -30.190001f, -30.32f, -30.440001f, -30.57f, -30.700001f, // 19 + -30.82f, -30.940001f, -31.07f, -31.190001f, -31.309999f, -31.440001f, -31.559999f, -31.68f, -31.799999f, -31.92f, // 20 + -32.040001f, -32.16f, -32.279999f, -32.400002f, -32.52f, -32.630001f, -32.75f, -32.869999f, -32.98f, -33.099998f, // 21 + -33.209999f, -33.330002f, -33.439999f, -33.560001f, -33.669998f, -33.779999f, -33.900002f, -34.009998f, -34.119999f, -34.23f, // 22 + -34.34f, -34.450001f, -34.560001f, -34.669998f, -34.779999f, -34.889999f, -35.0f, -35.110001f, -35.220001f, -35.330002f, // 23 + -35.43f, -35.540001f, -35.650002f, -35.75f, -35.860001f, -35.959999f, -36.07f, -36.169998f, -36.279999f, -36.380001f, // 24 + -36.490002f, -36.59f, -36.689999f, -36.790001f, -36.900002f, -37.0f, -37.099998f, -37.200001f, -37.299999f, -37.400002f, // 25 + -37.5f, -37.599998f, -37.700001f, -37.799999f, -37.900002f, -38.0f, -38.099998f, -38.200001f, -38.290001f, -38.389999f, // 26 + -38.490002f, -38.580002f, -38.68f, -38.779999f, -38.869999f, -38.970001f, -39.060001f, -39.16f, -39.25f, -39.349998f, // 27 + -39.439999f, -39.540001f, -39.630001f, -39.720001f, -39.82f, -39.91f, -40.0f, -40.09f, -40.189999f, -40.279999f, // 28 + -40.369999f, -40.459999f, -40.549999f, -40.639999f, -40.73f, -40.82f, -40.91f, -41.0f, -41.09f, -41.18f, // 29 + -41.27f, -41.360001f, -41.450001f, -41.529999f, -41.619999f, -41.709999f, -41.799999f, -41.889999f, -41.970001f, -42.060001f, // 30 + -42.150002f, -42.23f, -42.32f, -42.400002f, -42.490002f, -42.57f, -42.66f, -42.740002f, -42.830002f, -42.91f, // 31 + -43.0f, -43.080002f, -43.16f, -43.25f, -43.330002f, -43.41f, -43.5f, -43.580002f, -43.66f, -43.740002f, // 32 + -43.830002f, -43.91f, -43.990002f, -44.07f, -44.150002f, -44.23f, -44.310001f, -44.389999f, -44.48f, -44.560001f, // 33 + -44.639999f, -44.720001f, -44.790001f, -44.869999f, -44.950001f, -45.029999f, -45.110001f, -45.189999f, -45.27f, -45.349998f, // 34 + -45.419998f, -45.5f, -45.580002f, -45.66f, -45.73f, -45.810001f, -45.889999f, -45.970001f, -46.040001f, -46.119999f, // 35 + -46.189999f, -46.27f, -46.349998f, -46.419998f, -46.5f, -46.57f, -46.650002f, -46.720001f, -46.799999f, -46.869999f, // 36 + -46.950001f, -47.02f, -47.09f, -47.169998f, -47.240002f, -47.32f, -47.389999f, -47.459999f, -47.540001f, -47.610001f, // 37 + -47.68f, -47.75f, -47.830002f, -47.900002f, -47.970001f, -48.040001f, -48.110001f, -48.189999f, -48.259998f, -48.330002f, // 38 + -48.400002f, -48.470001f, -48.540001f, -48.610001f, -48.68f, -48.75f, -48.82f, -48.889999f, -48.959999f, -49.029999f, // 39 + -49.099998f, -49.169998f, -49.240002f, -49.310001f, -49.380001f, -49.450001f, -49.52f, -49.59f, -49.66f, -49.720001f, // 40 + -49.790001f, -49.860001f, -49.93f, -50.0f, -50.060001f, -50.130001f, -50.200001f, -50.27f, -50.330002f, -50.400002f, // 41 + -50.470001f, -50.529999f, -50.599998f, -50.669998f, -50.73f, -50.799999f, -50.869999f, -50.93f, -51.0f, -51.060001f, // 42 + -51.130001f, -51.189999f, -51.259998f, -51.32f, -51.389999f, -51.450001f, -51.52f, -51.580002f, -51.650002f, -51.709999f, // 43 + -51.779999f, -51.84f, -51.900002f, -51.970001f, -52.029999f, -52.099998f, -52.16f, -52.220001f, -52.290001f, -52.349998f, // 44 + -52.41f, -52.470001f, -52.540001f, -52.599998f, -52.66f, -52.720001f, -52.790001f, -52.849998f, -52.91f, -52.970001f, // 45 + -53.040001f, -53.099998f, -53.16f, -53.220001f, -53.279999f, -53.34f, -53.400002f, -53.470001f, -53.529999f, -53.59f, // 46 + -53.650002f, -53.709999f, -53.77f, -53.830002f, -53.889999f, -53.950001f, -54.009998f, -54.07f, -54.130001f, -54.189999f, // 47 + -54.25f, -54.310001f, -54.369999f, -54.43f, -54.490002f, -54.549999f, -54.599998f, -54.66f, -54.720001f, -54.779999f, // 48 + -54.84f, -54.900002f, -54.959999f, -55.009998f, -55.07f, -55.130001f, -55.189999f, -55.25f, -55.299999f, -55.360001f, // 49 + -55.419998f, -55.48f, -55.529999f, -55.59f, -55.650002f, -55.709999f, -55.759998f, -55.82f, -55.880001f, -55.93f, // 50 + -55.990002f, -56.049999f, -56.099998f, -56.16f, -56.220001f, -56.27f, -56.330002f, -56.380001f, -56.439999f, -56.5f, // 51 + -56.549999f, -56.610001f, -56.66f, -56.720001f, -56.77f, -56.830002f, -56.880001f, -56.939999f, -56.990002f, -57.049999f, // 52 + -57.099998f, -57.16f, -57.209999f, -57.27f, -57.32f, -57.380001f, -57.43f, -57.48f, -57.540001f, -57.59f, // 53 + -57.650002f, -57.700001f, -57.75f, -57.810001f, -57.860001f, -57.91f, -57.970001f, -58.02f, -58.07f, -58.130001f, // 54 + -58.18f, -58.23f, -58.290001f, -58.34f, -58.389999f, -58.450001f, -58.5f, -58.549999f, -58.599998f, -58.66f, // 55 + -58.709999f, -58.759998f, -58.810001f, -58.860001f, -58.919998f, -58.970001f, -59.02f, -59.07f, -59.119999f, -59.169998f, // 56 + -59.23f, -59.279999f, -59.330002f, -59.380001f, -59.43f, -59.48f, -59.529999f, -59.580002f, -59.630001f, -59.689999f, // 57 + -59.740002f, -59.790001f, -59.84f, -59.889999f, -59.939999f, -59.990002f, -60.040001f, -60.09f, -60.139999f, -60.189999f, // 58 + -60.240002f, -60.290001f, -60.34f, -60.389999f, -60.439999f, -60.490002f, -60.540001f, -60.59f, -60.639999f, -60.689999f, // 59 + -60.740002f, -60.779999f, -60.830002f, -60.880001f, -60.93f, -60.98f, -61.029999f, -61.080002f, -61.130001f, -61.18f, // 60 + -61.220001f, -61.27f, -61.32f, -61.369999f, -61.419998f, -61.470001f, -61.509998f, -61.560001f, -61.610001f, -61.66f, // 61 + -61.709999f, -61.75f, -61.799999f, -61.849998f, -61.900002f, -61.939999f, -61.990002f, -62.040001f, -62.09f, -62.130001f, // 62 + -62.18f, -62.23f, -62.279999f, -62.32f, -62.369999f, -62.419998f, -62.459999f, -62.509998f, -62.560001f, -62.599998f, // 63 + -62.650002f, -62.700001f, -62.740002f, -62.790001f, -62.84f, -62.880001f, -62.93f, -62.970001f, -63.02f, -63.07f, // 64 + -63.110001f, -63.16f, -63.200001f, -63.25f, -63.299999f, -63.34f, -63.389999f, -63.43f, -63.48f, -63.52f, // 65 + -63.57f, -63.610001f, -63.66f, -63.709999f, -63.75f, -63.799999f, -63.84f, -63.889999f, -63.93f, -63.98f, // 66 + -64.019997f, -64.059998f, -64.110001f, -64.150002f, -64.199997f, -64.239998f, -64.290001f, -64.330002f, -64.379997f, -64.419998f, // 67 + -64.459999f, -64.510002f, -64.550003f, -64.599998f, -64.639999f, -64.690002f, -64.730003f, -64.769997f, -64.82f, -64.860001f, // 68 + -64.900002f, -64.949997f, -64.989998f, -65.029999f, -65.080002f, -65.120003f, -65.169998f, -65.209999f, -65.25f, -65.290001f, // 69 + -65.339996f, -65.379997f, -65.419998f, -65.470001f, -65.510002f, -65.550003f, -65.599998f, -65.639999f, -65.68f, -65.720001f, // 70 + -65.769997f, -65.809998f, -65.849998f, -65.889999f, -65.940002f, -65.980003f, -66.019997f, -66.059998f, -66.110001f, -66.150002f, // 71 + -66.190002f, -66.230003f, -66.269997f, -66.32f, -66.360001f, -66.400002f, -66.440002f, -66.480003f, -66.519997f, -66.57f, // 72 + -66.610001f, -66.650002f, -66.690002f, -66.730003f, -66.769997f, -66.82f, -66.860001f, -66.900002f, -66.940002f, -66.980003f, // 73 + -67.019997f, -67.059998f, -67.099998f, -67.139999f, -67.190002f, -67.230003f, -67.269997f, -67.309998f, -67.349998f, -67.389999f, // 74 + -67.43f, -67.470001f, -67.510002f, -67.550003f, -67.589996f, -67.629997f, -67.669998f, -67.709999f, -67.75f, -67.790001f, // 75 + -67.830002f, -67.870003f, -67.910004f, -67.949997f, -67.989998f, -68.029999f, -68.07f, -68.110001f, -68.150002f, -68.190002f, // 76 + -68.230003f, -68.269997f, -68.309998f, -68.349998f, -68.389999f, -68.43f, -68.470001f, -68.510002f, -68.550003f, -68.589996f, // 77 + -68.629997f, -68.669998f, -68.709999f, -68.75f, -68.790001f, -68.82f, -68.860001f, -68.900002f, -68.940002f, -68.980003f, // 78 + -69.019997f, -69.059998f, -69.099998f, -69.139999f, -69.169998f, -69.209999f, -69.25f, -69.290001f, -69.330002f, -69.370003f, // 79 + -69.410004f, -69.440002f, -69.480003f, -69.519997f, -69.559998f, -69.599998f, -69.639999f, -69.669998f, -69.709999f, -69.75f, // 80 + -69.790001f, -69.830002f, -69.860001f, -69.900002f, -69.940002f, -69.980003f, -70.010002f, -70.050003f, -70.089996f, -70.129997f, // 81 + -70.169998f, -70.199997f, -70.239998f, -70.279999f, -70.32f, -70.349998f, -70.389999f, -70.43f, -70.470001f, -70.5f, // 82 + -70.540001f, -70.580002f, -70.610001f, -70.650002f, -70.690002f, -70.730003f, -70.760002f, -70.800003f, -70.839996f, -70.870003f, // 83 + -70.910004f, -70.949997f, -70.980003f, -71.019997f, -71.059998f, -71.089996f, -71.129997f, -71.169998f, -71.199997f, -71.239998f, // 84 + -71.279999f, -71.309998f, -71.349998f, -71.389999f, -71.419998f, -71.459999f, -71.489998f, -71.529999f, -71.57f, -71.599998f, // 85 + -71.639999f, -71.68f, -71.709999f, -71.75f, -71.779999f, -71.82f, -71.860001f, -71.889999f, -71.93f, -71.959999f, // 86 + -72.0f, -72.029999f, -72.07f, -72.110001f, -72.139999f, -72.18f, -72.209999f, -72.25f, -72.279999f, -72.32f, // 87 + -72.349998f, -72.389999f, -72.419998f, -72.459999f, -72.5f, -72.529999f, -72.57f, -72.599998f, -72.639999f, -72.669998f, // 88 + -72.709999f, -72.739998f, -72.779999f, -72.809998f, -72.849998f, -72.879997f, -72.919998f, -72.949997f, -72.989998f, -73.019997f, // 89 + -73.050003f, -73.089996f, -73.120003f, -73.160004f, -73.190002f, -73.230003f, -73.260002f, -73.300003f, -73.330002f, -73.370003f, // 90 + -73.400002f, -73.43f, -73.470001f, -73.5f, -73.540001f, -73.57f, -73.610001f, -73.639999f, -73.669998f, -73.709999f, // 91 + -73.739998f, -73.779999f, -73.809998f, -73.839996f, -73.879997f, -73.910004f, -73.949997f, -73.980003f, -74.010002f, -74.050003f, // 92 + -74.080002f, -74.110001f, -74.150002f, -74.18f, -74.220001f, -74.25f, -74.279999f, -74.32f, -74.349998f, -74.379997f, // 93 + -74.419998f, -74.449997f, -74.480003f, -74.519997f, -74.550003f, -74.580002f, -74.620003f, -74.650002f, -74.68f, -74.720001f, // 94 + -74.75f, -74.779999f, -74.82f, -74.849998f, -74.879997f, -74.910004f, -74.949997f, -74.980003f, -75.010002f, -75.050003f, // 95 + -75.080002f, -75.110001f, -75.139999f, -75.18f, -75.209999f, -75.239998f, -75.279999f, -75.309998f, -75.339996f, -75.370003f, // 96 + -75.410004f, -75.440002f, -75.470001f, -75.5f, -75.540001f, -75.57f, -75.599998f, -75.629997f, -75.669998f, -75.699997f, // 97 + -75.730003f, -75.760002f, -75.790001f, -75.830002f, -75.860001f, -75.889999f, -75.919998f, -75.949997f, -75.989998f, -76.019997f, // 98 + -76.050003f, -76.080002f, -76.110001f, -76.150002f, -76.18f, -76.209999f, -76.239998f, -76.269997f, -76.309998f, -76.339996f, // 99 + -76.370003f, -76.400002f, -76.43f, -76.459999f, -76.5f, -76.529999f, -76.559998f, -76.589996f, -76.620003f, -76.650002f, // 100 + -76.68f, -76.720001f, -76.75f, -76.779999f, -76.809998f, -76.839996f, -76.870003f, -76.900002f, -76.93f, -76.970001f, // 101 + -77.0f, -77.029999f, -77.059998f, -77.089996f, -77.120003f, -77.150002f, -77.18f, -77.209999f, -77.239998f, -77.279999f, // 102 + -77.309998f, -77.339996f, -77.370003f, -77.400002f, -77.43f, -77.459999f, -77.489998f, -77.519997f, -77.550003f, -77.580002f, // 103 + -77.610001f, -77.639999f, -77.68f, -77.709999f, -77.739998f, -77.769997f, -77.800003f, -77.830002f, -77.860001f, -77.889999f, // 104 + -77.919998f, -77.949997f, -77.980003f, -78.010002f, -78.040001f, -78.07f, -78.099998f, -78.129997f, -78.160004f, -78.190002f, // 105 + -78.220001f, -78.25f, -78.279999f, -78.309998f, -78.339996f, -78.370003f, -78.400002f, -78.43f, -78.459999f, -78.489998f, // 106 + -78.519997f, -78.550003f, -78.580002f, -78.610001f, -78.639999f, -78.669998f, -78.699997f, -78.730003f, -78.760002f, -78.790001f, // 107 + -78.82f, -78.849998f, -78.879997f, -78.910004f, -78.940002f, -78.970001f, -79.0f, -79.029999f, -79.050003f, -79.080002f, // 108 + -79.110001f, -79.139999f, -79.169998f, -79.199997f, -79.230003f, -79.260002f, -79.290001f, -79.32f, -79.349998f, -79.379997f, // 109 + -79.410004f, -79.440002f, -79.459999f, -79.489998f, -79.519997f, -79.550003f, -79.580002f, -79.610001f, -79.639999f, -79.669998f, // 110 + -79.699997f, -79.730003f, -79.75f, -79.779999f, -79.809998f, -79.839996f, -79.870003f, -79.900002f, -79.93f, -79.959999f, // 111 + -79.980003f, -80.010002f, -80.040001f, -80.07f, -80.099998f, -80.129997f, -80.160004f, -80.18f, -80.209999f, -80.239998f, // 112 + -80.269997f, -80.300003f, -80.330002f, -80.360001f, -80.379997f, -80.410004f, -80.440002f, -80.470001f, -80.5f, -80.529999f, // 113 + -80.550003f, -80.580002f, -80.610001f, -80.639999f, -80.669998f, -80.699997f, -80.720001f, -80.75f, -80.779999f, -80.809998f, // 114 + -80.839996f, -80.860001f, -80.889999f, -80.919998f, -80.949997f, -80.980003f, -81.0f, -81.029999f, -81.059998f, -81.089996f, // 115 + -81.120003f, -81.139999f, -81.169998f, -81.199997f, -81.230003f, -81.25f, -81.279999f, -81.309998f, -81.339996f, -81.360001f, // 116 + -81.389999f, -81.419998f, -81.449997f, -81.480003f, -81.5f, -81.529999f, -81.559998f, -81.589996f, -81.610001f, -81.639999f, // 117 + -81.669998f, -81.699997f, -81.720001f, -81.75f, -81.779999f, -81.800003f, -81.830002f, -81.860001f, -81.889999f, -81.910004f, // 118 + -81.940002f, -81.970001f, -82.0f, -82.019997f, -82.050003f, -82.080002f, -82.099998f, -82.129997f, -82.160004f, -82.190002f, // 119 + -82.209999f, -82.239998f, -82.269997f, -82.290001f, -82.32f, -82.349998f, -82.370003f, -82.400002f, -82.43f, -82.449997f, // 120 + -82.480003f, -82.510002f, -82.540001f, -82.559998f, -82.589996f, -82.620003f, -82.639999f, -82.669998f, -82.699997f, -82.720001f, // 121 + -82.75f, -82.779999f, -82.800003f, -82.830002f, -82.860001f, -82.879997f, -82.910004f, -82.93f, -82.959999f, -82.989998f, // 122 + -83.010002f, -83.040001f, -83.07f, -83.089996f, -83.120003f, -83.150002f, -83.169998f, -83.199997f, -83.230003f, -83.25f, // 123 + -83.279999f, -83.300003f, -83.330002f, -83.360001f, -83.379997f, -83.410004f, -83.440002f, -83.459999f, -83.489998f, -83.510002f, // 124 + -83.540001f, -83.57f, -83.589996f, -83.620003f, -83.639999f, -83.669998f, -83.699997f, -83.720001f, -83.75f, -83.769997f, // 125 + -83.800003f, -83.830002f, -83.849998f, -83.879997f, -83.900002f, -83.93f, -83.949997f, -83.980003f, -84.010002f, -84.029999f, // 126 + -84.059998f, -84.080002f, -84.110001f, -84.129997f, -84.160004f, -84.190002f, -84.209999f, -84.239998f, -84.260002f, -84.290001f, // 127 +}; void CAEAudioEnvironment::InjectHooks() { RH_ScopedClass(CAEAudioEnvironment); @@ -12,20 +144,20 @@ void CAEAudioEnvironment::InjectHooks() { RH_ScopedInstall(GetDistanceAttenuation, 0x4D7F20); RH_ScopedInstall(GetDirectionalMikeAttenuation, 0x4D7F60); RH_ScopedInstall(GetReverbEnvironmentAndDepth, 0x4D8010); - RH_ScopedOverloadedInstall(GetPositionRelativeToCamera, "vec", 0x4D80B0, void(*)(CVector*, const CVector*)); - RH_ScopedOverloadedInstall(GetPositionRelativeToCamera, "placeable", 0x4D8340, void(*)(CVector*, CPlaceable*)); + RH_ScopedOverloadedInstall(GetPositionRelativeToCamera, "vec", 0x4D80B0, void(*)(CVector&, const CVector*)); + RH_ScopedOverloadedInstall(GetPositionRelativeToCamera, "placeable", 0x4D8340, void(*)(CVector&, CPlaceable*)); } // 0x4D7E40 float CAEAudioEnvironment::GetDopplerRelativeFrequency(float prevDist, float curDist, uint32 prevTime, uint32 curTime, float timeScale) { - const auto fDistDiff = curDist - prevDist; + const auto deltaDist = curDist - prevDist; if (TheCamera.Get_Just_Switched_Status()) return 1.0F; - if (timeScale == 0.0F || fDistDiff == 0.0F || curTime <= prevTime) + if (timeScale == 0.0F || deltaDist == 0.0F || curTime <= prevTime) return 1.0F; - const auto fDoppler = fDistDiff * 1000.0F / static_cast(curTime - prevTime) * timeScale; + const auto fDoppler = deltaDist * 1000.0F / static_cast(curTime - prevTime) * timeScale; if (std::fabs(fDoppler) >= 340.0F) return 1.0F; @@ -35,11 +167,10 @@ float CAEAudioEnvironment::GetDopplerRelativeFrequency(float prevDist, float cur // 0x4D7F20 float CAEAudioEnvironment::GetDistanceAttenuation(float dist) { - if (dist >= 128.0F) - return -100.0F; - - auto iArrIndex = static_cast(std::floor(dist * 10.0F)); - return gSoundDistAttenuationTable[iArrIndex]; + assert(dist >= 0.f); + return dist < ATTENUATION_TABLE_MAX_DIST + ? gSoundDistAttenuationTable[(uint32)std::floor(dist / ATTENUATION_TABLE_RESOLUTION)] + : -100.f; } // 0x4D7F60 diff --git a/source/game_sa/Audio/AEAudioEnvironment.h b/source/game_sa/Audio/AEAudioEnvironment.h index fd2bd63497..80d76d995e 100644 --- a/source/game_sa/Audio/AEAudioEnvironment.h +++ b/source/game_sa/Audio/AEAudioEnvironment.h @@ -27,6 +27,3 @@ class CAEAudioEnvironment { static constexpr int32 NUM_AUDIO_ENVIRONMENTS = 68; extern sReverbEnvironment (&gAudioZoneToReverbEnvironmentMap)[NUM_AUDIO_ENVIRONMENTS]; - -static constexpr int32 NUM_SOUND_DIST_ATTENUATION_ENTRIES = 1280; -extern float (&gSoundDistAttenuationTable)[NUM_SOUND_DIST_ATTENUATION_ENTRIES]; From de6e8a9f8a08baeb6985829d76e86ff82e4daf88 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Thu, 18 Jul 2024 11:21:49 +0200 Subject: [PATCH 09/22] Fix initialization order bug --- source/game_sa/Audio/AudioEngine.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/game_sa/Audio/AudioEngine.cpp b/source/game_sa/Audio/AudioEngine.cpp index 31b2ba33c8..640a725f22 100644 --- a/source/game_sa/Audio/AudioEngine.cpp +++ b/source/game_sa/Audio/AudioEngine.cpp @@ -105,6 +105,9 @@ void CAudioEngine::InjectHooks() { bool CAudioEngine::Initialise() { CLoadingScreen::Pause(); + // NOTSA: Initialize AudioUtility before `AEAudioHardware` to avoid crash (Division by zero in `GetCurrentTimeInMS`) + CAEAudioUtility::StaticInitialise(); + if (!AEAudioHardware.Initialise()) { NOTSA_LOG_ERR("Failed to initialise Audio Hardware"); return false; @@ -138,7 +141,7 @@ bool CAudioEngine::Initialise() { m_FrontendAE.Initialise(); CAudioEngine::SetEffectsFaderScalingFactor(0.0f); - CAEAudioUtility::StaticInitialise(); + //CAEAudioUtility::StaticInitialise(); // Initialized above CAEPedAudioEntity::StaticInitialise(); CAEPedSpeechAudioEntity::StaticInitialise(); CAEVehicleAudioEntity::StaticInitialise(); From 8f6370a0cb763f4db7de2b0bfddec222b4ec76e5 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Thu, 18 Jul 2024 11:21:58 +0200 Subject: [PATCH 10/22] `PlayGunSounds` --- source/game_sa/Audio/AESound.cpp | 44 +++-- source/game_sa/Audio/AESound.h | 35 +++- .../Audio/entities/AEExplosionAudioEntity.cpp | 6 +- .../Audio/entities/AEWeaponAudioEntity.cpp | 174 +++++++++++++++++- .../Audio/entities/AEWeaponAudioEntity.h | 13 +- .../Audio/managers/AEAmbienceTrackManager.cpp | 4 +- 6 files changed, 227 insertions(+), 49 deletions(-) diff --git a/source/game_sa/Audio/AESound.cpp b/source/game_sa/Audio/AESound.cpp index 79e391a657..2593eab9c0 100644 --- a/source/game_sa/Audio/AESound.cpp +++ b/source/game_sa/Audio/AESound.cpp @@ -22,7 +22,7 @@ void CAESound::InjectHooks() { RH_ScopedInstall(StopSound, 0x4EF1C0); RH_ScopedInstall(SetIndividualEnvironment, 0x4EF2B0); RH_ScopedInstall(UpdatePlayTime, 0x4EF2E0); - RH_ScopedOverloadedInstall(GetRelativePosition, "OG", 0x4EF350, void(CAESound::*)(CVector&) const); + RH_ScopedInstall(GetRelativePosition, 0x4EF350); RH_ScopedInstall(CalculateFrequency, 0x4EF390); RH_ScopedInstall(UpdateFrequency, 0x4EF3E0); RH_ScopedInstall(GetRelativePlaybackFrequencyWithDoppler, 0x4EF400); @@ -193,11 +193,10 @@ void CAESound::UpdatePlayTime(int16 soundLength, int16 loopStartTime, int16 play } // 0x4EF350 -void CAESound::GetRelativePosition(CVector& out) const { - if (!GetFrontEnd()) { - CAEAudioEnvironment::GetPositionRelativeToCamera(&out, &m_vecCurrPosn); - } - out = m_vecCurrPosn; +CVector CAESound::GetRelativePosition() const { + return GetFrontEnd() + ? CAEAudioEnvironment::GetPositionRelativeToCamera(m_vecCurrPosn) + : m_vecCurrPosn; } // 0x4EF390 @@ -288,43 +287,42 @@ void CAESound::CalculateVolume() { if (GetFrontEnd()) m_fFinalVolume = m_fVolume - m_fSoundHeadRoom; else { - CVector relativePos; - CAEAudioEnvironment::GetPositionRelativeToCamera(&relativePos, &m_vecCurrPosn); - const auto fDist = relativePos.Magnitude() / m_fSoundDistance; - const auto fAttenuation = CAEAudioEnvironment::GetDistanceAttenuation(fDist); - m_fFinalVolume = CAEAudioEnvironment::GetDirectionalMikeAttenuation(relativePos) + fAttenuation + m_fVolume - m_fSoundHeadRoom; + const auto relPos = CAEAudioEnvironment::GetPositionRelativeToCamera(m_vecCurrPosn); + const auto att = CAEAudioEnvironment::GetDistanceAttenuation(relPos.Magnitude() / m_fSoundDistance); + m_fFinalVolume = CAEAudioEnvironment::GetDirectionalMikeAttenuation(relPos) + att + m_fVolume - m_fSoundHeadRoom; } } // 0x4EFE50 -void CAESound::Initialise(int16 bankSlotId, int16 sfxId, CAEAudioEntity* baseAudio, CVector posn, float volume, float maxDistance, float speed, float timeScale, - uint8 ignoredServiceCycles, uint32 environmentFlags, float speedVariability, int16 currPlayPosn) +void CAESound::Initialise( + int16 bankSlotId, int16 soundID, CAEAudioEntity* audioEntity, CVector pos, float volume, float rollOffFactor, float relativeFrequency, float doppler, + uint8 frameDelay, uint32 flags, float frequencyVariance, int16 playTime) { UnregisterWithPhysicalEntity(); - m_nSoundIdInSlot = sfxId; + m_nSoundIdInSlot = soundID; m_nBankSlotId = bankSlotId; - m_pBaseAudio = baseAudio; + m_pBaseAudio = audioEntity; m_fVolume = volume; - m_fSoundDistance = maxDistance; - m_fSpeed = speed; - m_fSpeedVariability = speedVariability; + m_fSoundDistance = rollOffFactor; + m_fSpeed = relativeFrequency; + m_fSpeedVariability = frequencyVariance; m_vecPrevPosn .Set(0.0F, 0.0F, 0.0F); m_nEvent = AE_UNDEFINED; m_fMaxVolume = -1.0F; m_nLastFrameUpdate = 0; - SetPosition(posn); + SetPosition(pos); - m_fTimeScale = timeScale; + m_fTimeScale = doppler; m_nSoundLength = -1; m_nHasStarted = 0; m_nPlayingState = eSoundState::SOUND_ACTIVE; m_fSoundHeadRoom = 0.0F; - m_nIgnoredServiceCycles = ignoredServiceCycles; - m_nEnvironmentFlags = environmentFlags; + m_nIgnoredServiceCycles = frameDelay; + m_nEnvironmentFlags = flags; m_nIsUsed = 1; - m_nCurrentPlayPosition = currPlayPosn; + m_nCurrentPlayPosition = playTime; m_fFinalVolume = -100.0F; m_fFrequency = 1.0F; } diff --git a/source/game_sa/Audio/AESound.h b/source/game_sa/Audio/AESound.h index e45bf74407..aeffd1e403 100644 --- a/source/game_sa/Audio/AESound.h +++ b/source/game_sa/Audio/AESound.h @@ -98,14 +98,30 @@ class CAESound { CAESound& operator=(const CAESound& sound); - void Initialise(int16 bankSlotId, int16 sfxId, CAEAudioEntity* baseAudio, CVector posn, float volume, - float maxDistance = 1.0f, - float speed = 1.0f, - float timeScale = 1.0f, - uint8 ignoredServiceCycles = 0, - /*eSoundEnvironment*/ uint32 environmentFlags = static_cast(0), - float speedVariability = 0, - int16 currPlayPosn = 0); + void Initialise( + int16 bankSlotId, + int16 soundID, + CAEAudioEntity* audioEntity, + CVector pos, + float volume, + float rollOffFactor = 1.f, + float relativeFrequency = 1.f, // Speed + float doppler = 1.f, + uint8 frameDelay = 0, + uint32 flags = 0, + float frequencyVariance = 0.f, + int16 playTime = 0 + ); + //int16 bankSlotId, + //int16 sfxId, + //CAEAudioEntity* baseAudio, CVector posn, float volume, + // float maxDistance = 1.0f, + // float speed = 1.0f, + // float timeScale = 1.0f, + // uint8 ignoredServiceCycles = 0, + // /*eSoundEnvironment*/ uint32 environmentFlags = static_cast(0), + // float speedVariability = 0, + // int16 currPlayPosn = 0); void UnregisterWithPhysicalEntity(); void StopSound(); @@ -124,8 +140,7 @@ class CAESound { bool GetForcedFront() const { return m_bForcedFront; } void SetIndividualEnvironment(uint16 envFlag, uint16 bEnabled); // pass eSoundEnvironment as envFlag void UpdatePlayTime(int16 soundLength, int16 loopStartTime, int16 playProgress); - void GetRelativePosition(CVector& out) const; - CVector GetRelativePosition() const { CVector out; GetRelativePosition(out); return out; } // NOTSA + CVector GetRelativePosition() const; void CalculateFrequency(); void UpdateFrequency(); float GetRelativePlaybackFrequencyWithDoppler(); diff --git a/source/game_sa/Audio/entities/AEExplosionAudioEntity.cpp b/source/game_sa/Audio/entities/AEExplosionAudioEntity.cpp index 0d5448d325..4d47d7f07d 100644 --- a/source/game_sa/Audio/entities/AEExplosionAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEExplosionAudioEntity.cpp @@ -50,9 +50,7 @@ void CAEExplosionAudioEntity::AddAudioEvent(eAudioEvents audioEvent, CVector& po speed_b = gfExplosionFrequencyVariations[m_Speed] * sqrt(sqrt(2.0f)); } - CVector relPos; - CAEAudioEnvironment::GetPositionRelativeToCamera(&relPos, &posn); - auto vol1 = CAEAudioEnvironment::GetDistanceAttenuation(relPos.Magnitude() * (1.0f / 12.0f)) + vol0 - 3.0f; + auto vol1 = CAEAudioEnvironment::GetDistanceAttenuation(CAEAudioEnvironment::GetPositionRelativeToCamera(posn).Magnitude() * (1.0f / 12.0f)) + vol0 - 3.0f; auto flags = static_cast(SOUND_FORCED_FRONT | SOUND_ROLLED_OFF | SOUND_REQUEST_UPDATES | SOUND_FRONT_END); sound.Initialise(4, 1, this, { -1.0f, 0.0f, 0.0f }, vol1, 12.0f, speed_a, 1.0f, 0, flags, 0.0f, 0); @@ -78,4 +76,4 @@ void CAEExplosionAudioEntity::InjectHooks() { RH_ScopedInstall(StaticInitialise, 0x5B9A60); RH_ScopedInstall(AddAudioEvent, 0x4DCBE0); RH_ScopedVMTInstall(UpdateParameters, 0x4DCB90); -} \ No newline at end of file +} diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp index e1378ddc2b..d442116564 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp @@ -8,11 +8,13 @@ #include "StdInc.h" #include "AEWeaponAudioEntity.h" - +#include "AEAudioEnvironment.h" #include "AESoundManager.h" #include "AEAudioHardware.h" #include "AEAudioUtility.h" +constexpr std::array gfWeaponPlaneFrequencyVariations{ 1.08f, 1.0f }; + void CAEWeaponAudioEntity::InjectHooks() { RH_ScopedClass(CAEWeaponAudioEntity); RH_ScopedCategory("Audio/Entities"); @@ -30,7 +32,7 @@ void CAEWeaponAudioEntity::InjectHooks() { RH_ScopedInstall(PlayCameraSound, 0x5046F0); RH_ScopedInstall(PlayWeaponLoopSound, 0x504610); RH_ScopedInstall(PlayFlameThrowerSounds, 0x504470, { .reversed = false }); - RH_ScopedInstall(PlayGunSounds, 0x503CE0, { .reversed = false }); + RH_ScopedInstall(PlayGunSounds, 0x503CE0); RH_ScopedInstall(ReportStealthKill, 0x503B20); RH_ScopedInstall(ReportChainsawEvent, 0x503910, { .reversed = false }); RH_ScopedInstall(PlayFlameThrowerIdleGasLoop, 0x503870); @@ -314,12 +316,14 @@ void CAEWeaponAudioEntity::PlayMiniGunFireSounds(CPhysical* entity, eAudioEvents switch (audioEvent) { case AE_WEAPON_FIRE: case AE_WEAPON_FIRE_MINIGUN_AMMO: { // 0x504912 - return PlayMiniGunFireSound(AE_WEAPON_FIRE_MINIGUN_AMMO); + PlayMiniGunFireSound(AE_WEAPON_FIRE_MINIGUN_AMMO); + break; } case AE_WEAPON_FIRE_PLANE: { // 0x5047E6 - return PlayMiniGunFireSound(AE_WEAPON_FIRE_MINIGUN_PLANE); + PlayMiniGunFireSound(AE_WEAPON_FIRE_MINIGUN_PLANE); + break; } - case AE_WEAPON_FIRE_MINIGUN_NO_AMMO: { // 0x5048FC + case AE_WEAPON_FIRE_MINIGUN_NO_AMMO: { // 0x5048FC - Minigun is just spinning if (!m_IsMiniGunSpinActive) { if (!AEAudioHardware.IsSoundBankLoaded(143, 5)) { // SND_BANK_GENRL_WEAPONS, SND_BANK_SLOT_WEAPON_GEN if (!AudioEngine.IsLoadingTuneActive()) { @@ -353,9 +357,163 @@ void CAEWeaponAudioEntity::PlayMiniGunFireSounds(CPhysical* entity, eAudioEvents } // 0x503CE0 -void CAEWeaponAudioEntity::PlayGunSounds(CPhysical* entity, int16 emptySfxId, int16 farSfxId2, int16 highPitchSfxId3, int16 lowPitchSfxId4, int16 echoSfxId5, int32 audioEventId, float volumeChange, float speed1, float speed2) { - plugin::CallMethod<0x503CE0, CAEWeaponAudioEntity*, CPhysical*, int16, int16, int16, int16, int16, int32, float, float, float>( - this, entity, emptySfxId, farSfxId2, highPitchSfxId3, lowPitchSfxId4, echoSfxId5, audioEventId, volumeChange, speed1, speed2); +void CAEWeaponAudioEntity::PlayGunSounds( + CPhysical* entity, + int16 dryFireSfxID, + int16 subSfxID, + int16 mainLeftSfxID, + int16 mainRightSfxID, + int16 tailSfxID, + eAudioEvents audioEvent, + float volumeOffsetdB, + float primarySpeed, + float tailFrequencyScalingFactor +) { + if (!AEAudioHardware.IsSoundBankLoaded(143u, 5)) { + if (!AudioEngine.IsLoadingTuneActive()) { + AEAudioHardware.LoadSoundBank(143, 5); + } + return; + } + + if (CTimer::GetTimeInMS() < m_LastGunFireTimeMs + 25) { + return; + } + m_LastGunFireTimeMs = CTimer::GetTimeInMS(); + + auto baseVolume = GetDefaultVolume(audioEvent) + volumeOffsetdB; + auto [baseRollOffFactor, baseSpeed] = [&]() -> std::pair { + switch (audioEvent) { + case AE_WEAPON_FIRE_PLANE: { + m_LastWeaponPlaneFrequencyIndex = (m_LastWeaponPlaneFrequencyIndex + 1) % 2; + return {1.6f, gfWeaponPlaneFrequencyVariations[m_LastWeaponPlaneFrequencyIndex] * primarySpeed * 0.7937f}; + } + case AE_WEAPON_FIRE_MINIGUN_PLANE: { + return {1.8f, primarySpeed * 0.7937f}; + } + default: { + return {1.f, primarySpeed}; + } + } + }(); + + const auto PlaySound = [&](int16 sfxID, CVector pos, float volume, float rollOffFactor, float speed, uint32 flags, eAudioEvents audioEventOverride = AE_UNDEFINED) { + CAESound s; + s.Initialise( + 5, + sfxID, + this, + pos, + volume, + rollOffFactor, + speed, + 0.f, + 0, + flags + ); + if (flags & SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY) { + s.RegisterWithPhysicalEntity(entity); + } + if (audioEventOverride == AE_UNDEFINED) { + switch (audioEvent) { + case AE_WEAPON_FIRE_MINIGUN_PLANE: + case AE_WEAPON_FIRE_MINIGUN_AMMO: + s.m_nEvent = AE_FRONTEND_PICKUP_WEAPON; + } + } else { + s.m_nEvent = audioEventOverride; + } + AESoundManager.RequestNewSound(&s); + }; + + if (dryFireSfxID != -1) { // 0x503DFF + PlaySound( + dryFireSfxID, + entity->GetPosition(), + baseVolume, + baseRollOffFactor * (2.f / 3.f), + baseSpeed, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); + } + if (subSfxID != -1) { // 0x503E93 + PlaySound( + subSfxID, + entity->GetPosition(), + baseVolume, + baseRollOffFactor * 0.9f, + baseSpeed, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); + } + + // 0x503F21 + float frontEndVolume = -100.f; + if (!notsa::contains({ AE_WEAPON_FIRE_PLANE, AE_WEAPON_FIRE_MINIGUN_PLANE }, audioEvent)) { + const auto dist = CAEAudioEnvironment::GetPositionRelativeToCamera(entity).Magnitude() / (baseRollOffFactor * 1.25f); + if (dist < (5.f / baseRollOffFactor)) { // Inverted + baseVolume -= 3.f; + frontEndVolume = baseVolume + CAEAudioEnvironment::GetDistanceAttenuation(dist); + } else if (dist < (12.f / baseRollOffFactor)) { + const auto t = ((12.f / baseRollOffFactor) - dist) / (12.f / baseRollOffFactor) - (5.f / baseRollOffFactor); + frontEndVolume = baseVolume + CAEAudioEnvironment::GetDistanceAttenuation(dist) + std::log10f(t * (SQRT_2 / 2.f)) * 20.f; + baseVolume += std::log10f(((1.f - t) * 0.2929f) + (SQRT_2 / 2.f)) * 20.f; + } + } + + const auto PlayMainSound = [ + &, + mainSoundSpeed = (CAEAudioUtility::GetRandomNumberInRange(-0.02f, 0.02f) + 1.f) * baseSpeed + ](int16 sfxID, bool isRight) { + PlaySound( + sfxID, + CVector{isRight ? 1.f : -1.f, 0.f, 0.f}, + frontEndVolume, + baseRollOffFactor * 1.25f, + mainSoundSpeed, + SOUND_FORCED_FRONT | SOUND_REQUEST_UPDATES | SOUND_FRONT_END + ); + PlaySound( + sfxID, + entity->GetPosition(), + baseVolume, + baseRollOffFactor * 1.25f, + mainSoundSpeed, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); + }; + if (mainLeftSfxID != -1) { // 0x5040DC + 0x5041DF + PlayMainSound(mainLeftSfxID, false); + } + if (mainRightSfxID != -1) { // 0x504153 + 0x504218 + PlayMainSound(mainRightSfxID, true); + } + + if (tailSfxID != -1 && !notsa::contains({AE_WEAPON_FIRE_PLANE, AE_WEAPON_FIRE_MINIGUN_PLANE}, audioEvent)) { + const auto tailSoundRollOff = baseRollOffFactor * 3.5f; + const auto tailSoundVolume = CAEAudioEnvironment::GetDistanceAttenuation(CAEAudioEnvironment::GetPositionRelativeToCamera(entity).Magnitude() / tailSoundRollOff) + baseVolume - 20.f; + const auto tailSoundAudioEvent = audioEvent == AE_WEAPON_FIRE_MINIGUN_AMMO + ? AE_FRONTEND_PICKUP_MONEY + : AE_FRONTEND_SELECT; + const auto PlayTailSound = [&](bool isRight, float speedMult) { + PlaySound( + tailSfxID, + CVector{ isRight ? 1.f : -1, 0.f, 0.f }, + tailSoundVolume, + tailSoundRollOff, + tailFrequencyScalingFactor * speedMult, + SOUND_FORCED_FRONT | SOUND_ROLLED_OFF | SOUND_REQUEST_UPDATES | SOUND_FRONT_END, + tailSoundAudioEvent + ); + }; + float speedMultA = 1.f, + speedMultB = 1.1892101f; + if (CAEAudioUtility::ResolveProbability(0.5f)) { + std::swap(speedMultA, speedMultB); + } + PlayTailSound(false, speedMultA); + PlayTailSound(true, speedMultB); + } } // 0x503500 diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.h b/source/game_sa/Audio/entities/AEWeaponAudioEntity.h index 70457d46f8..e67219e44a 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.h +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.h @@ -33,7 +33,18 @@ class NOTSA_EXPORT_VTABLE CAEWeaponAudioEntity : public CAEAudioEntity { void WeaponFire(eWeaponType type, CPhysical* entity, eAudioEvents audioEventId); void WeaponReload(eWeaponType type, CPhysical* entity, eAudioEvents event); - void PlayGunSounds(CPhysical* entity, int16 emptySfxId, int16 farSfxId2, int16 highPitchSfxId3, int16 lowPitchSfxId4, int16 echoSfxId5, int32 audioEventId, float volumeChange, float speed1, float speed2); + void PlayGunSounds( + CPhysical* entity, + int16 dryFireSfxID, + int16 subSfxID, + int16 mainLeftSfxID, + int16 mainRightSfxID, + int16 tailSfxID, + eAudioEvents audioEvent, + float volumeOffsetDecibels, + float primaryFrequencyScalingFactor, + float tailFrequencyScalingFactor + ); void PlayGoggleSound(int16 sfxId, eAudioEvents event); void ReportStealthKill(eWeaponType type, CPhysical* entity, eAudioEvents event); diff --git a/source/game_sa/Audio/managers/AEAmbienceTrackManager.cpp b/source/game_sa/Audio/managers/AEAmbienceTrackManager.cpp index 13ec8e2705..f95f1822ac 100644 --- a/source/game_sa/Audio/managers/AEAmbienceTrackManager.cpp +++ b/source/game_sa/Audio/managers/AEAmbienceTrackManager.cpp @@ -99,9 +99,7 @@ void CAEAmbienceTrackManager::UpdateAmbienceTrackAndVolume() { } const auto GetVolumeByAuZoDist = [&] { - CVector relPos; - CAEAudioEnvironment::GetPositionRelativeToCamera(&relPos, &activeAuZoPos); - return CAEAudioEnvironment::GetDistanceAttenuation(relPos.Magnitude() * 0.2f) - 6.f; + return CAEAudioEnvironment::GetDistanceAttenuation(CAEAudioEnvironment::GetPositionRelativeToCamera(activeAuZoPos).Magnitude() * 0.2f) - 6.f; }; switch (activeAuZoIdx) { From 8c1d06ff45fe422f9256d21048a04d168db51217 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Thu, 18 Jul 2024 23:55:40 +0200 Subject: [PATCH 11/22] `ReportChainsawEvent` --- source/game_sa/Audio/AESound.h | 2 +- .../Audio/entities/AEWeaponAudioEntity.cpp | 177 +++++++++++++++--- .../Audio/entities/AEWeaponAudioEntity.h | 57 ++++-- 3 files changed, 190 insertions(+), 46 deletions(-) diff --git a/source/game_sa/Audio/AESound.h b/source/game_sa/Audio/AESound.h index aeffd1e403..d90a596e91 100644 --- a/source/game_sa/Audio/AESound.h +++ b/source/game_sa/Audio/AESound.h @@ -39,7 +39,7 @@ class CAESound { int16 m_nSoundIdInSlot; CAEAudioEntity* m_pBaseAudio; CEntity* m_pPhysicalEntity; - eAudioEvents m_nEvent; + int32 m_nEvent; // Not necessarily `eAudioEvents`, for ex. see `CAEWeaponAudioEntity` float m_fMaxVolume; float m_fVolume; float m_fSoundDistance; diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp index d442116564..344d69b757 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp @@ -31,15 +31,14 @@ void CAEWeaponAudioEntity::InjectHooks() { RH_ScopedInstall(PlayMiniGunFireSounds, 0x5047C0); RH_ScopedInstall(PlayCameraSound, 0x5046F0); RH_ScopedInstall(PlayWeaponLoopSound, 0x504610); - RH_ScopedInstall(PlayFlameThrowerSounds, 0x504470, { .reversed = false }); + RH_ScopedInstall(PlayFlameThrowerSounds, 0x504470); RH_ScopedInstall(PlayGunSounds, 0x503CE0); RH_ScopedInstall(ReportStealthKill, 0x503B20); - RH_ScopedInstall(ReportChainsawEvent, 0x503910, { .reversed = false }); + RH_ScopedInstall(ReportChainsawEvent, 0x503910); RH_ScopedInstall(PlayFlameThrowerIdleGasLoop, 0x503870); RH_ScopedInstall(PlayGoggleSound, 0x503500); RH_ScopedInstall(StopFlameThrowerIdleGasLoop, 0x5034E0); RH_ScopedInstall(UpdateParameters, 0x504B70, { .reversed = false }); - } // 0x507560 @@ -50,7 +49,7 @@ CAEWeaponAudioEntity::CAEWeaponAudioEntity() { // 0x503450 void CAEWeaponAudioEntity::Initialise() { m_MiniGunState = eMiniGunState::STOPPED; - m_ChainsawState = 4; + m_ChainsawState = eChainsawState::STOPPED; if (!AudioEngine.IsLoadingTuneActive()) { AEAudioHardware.LoadSoundBank(143, 5); } @@ -110,9 +109,9 @@ void CAEWeaponAudioEntity::WeaponFire(eWeaponType type, CPhysical* entity, eAudi return PlayGunSounds(entity, 52, 53, 26, 27, 23, audioEventId, 0.0f, 1.0f, 1.0f); case WEAPON_FLAMETHROWER: - if (!m_FlameThrowerLastPlayedTimeMs) + if (!m_LastFlameThrowerFireTimeMs) PlayFlameThrowerSounds(entity, 83, 26, audioEventId, -14.0f, 1.0f); - m_FlameThrowerLastPlayedTimeMs = CTimer::GetTimeInMS(); + m_LastFlameThrowerFireTimeMs = CTimer::GetTimeInMS(); break; case WEAPON_MINIGUN: @@ -123,14 +122,14 @@ void CAEWeaponAudioEntity::WeaponFire(eWeaponType type, CPhysical* entity, eAudi case WEAPON_SPRAYCAN: if (!m_LastSprayCanFireTimeMs) { - PlayWeaponLoopSound(entity, 28, audioEventId, -20.0f, 1.0f, AE_FRONTEND_HIGHLIGHT); + PlayWeaponLoopSound(entity, 28, audioEventId, -20.0f, 1.0f, AE_WEAPON_SOUND_CAT_SPRAY); } m_LastSprayCanFireTimeMs = CTimer::GetTimeInMS(); break; case WEAPON_EXTINGUISHER: if (!m_LastFireExtFireTimeMs) - PlayWeaponLoopSound(entity, 9, audioEventId, -20.0f, 0.79369998f, AE_FRONTEND_ERROR); + PlayWeaponLoopSound(entity, 9, audioEventId, -20.0f, 0.79369998f, AE_WEAPON_SOUND_CAT_EXT); m_LastFireExtFireTimeMs = CTimer::GetTimeInMS(); break; @@ -222,7 +221,7 @@ void CAEWeaponAudioEntity::ReportStealthKill(eWeaponType type, CPhysical* entity } m_tempSound.Initialise(5, 81, this, entity->GetPosition(), vol - 6.0f, 1.0f, 0.0f, 1.0f, 0); m_tempSound.RegisterWithPhysicalEntity(entity); - m_tempSound.m_nEvent = AE_FRONTEND_PICKUP_COLLECTABLE1; + m_tempSound.m_nEvent = AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_IN; m_tempSound.m_fMaxVolume = (float)CTimer::m_snTimeInMilliseconds; AESoundManager.RequestNewSound(&m_tempSound); @@ -234,18 +233,84 @@ void CAEWeaponAudioEntity::ReportStealthKill(eWeaponType type, CPhysical* entity } m_tempSound.Initialise(2, 47, this, entity->GetPosition(), vol, 1.0f, 0.0f, 1.0f, 0, flags); m_tempSound.RegisterWithPhysicalEntity(entity); - m_tempSound.m_nEvent = AE_FRONTEND_CAR_NO_CASH; + m_tempSound.m_nEvent = AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_OUT; m_tempSound.m_fMaxVolume = (float)CTimer::GetTimeInMS(); AESoundManager.RequestNewSound(&m_tempSound); } // 0x503910 -void CAEWeaponAudioEntity::ReportChainsawEvent(CPhysical* entity, int32 audioEventId) { - plugin::CallMethod<0x503910, CAEWeaponAudioEntity*, CPhysical*, int32>(this, entity, audioEventId); +void CAEWeaponAudioEntity::ReportChainsawEvent(CPhysical* entity, eAudioEvents audioEvent) { + if (!AEAudioHardware.IsSoundBankLoaded(36, 40)) { + if (AESoundManager.AreSoundsPlayingInBankSlot(40)) { + AESoundManager.CancelSoundsInBankSlot(40, false); + } + AEAudioHardware.LoadSoundBank(36, 40); + return; + } + + const auto PlaySoundIfNotPlaying = [&](int16 sfxID, float rollOffFactor, eWeaponSoundCategories soundCat) { + if (AESoundManager.AreSoundsOfThisEventPlayingForThisEntity(soundCat, this) != SOUND_NOT_PLAYING) { + return; + } + CAESound s; + s.Initialise( + 40, + sfxID, + this, + entity->GetPosition(), + GetDefaultVolume(audioEvent), + rollOffFactor, + 1.f, + 0.f, + 0, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); + s.m_nEvent = soundCat; + s.RegisterWithPhysicalEntity(entity); + AESoundManager.RequestNewSound(&s); + }; + + switch (audioEvent) { + case AE_WEAPON_CHAINSAW_IDLE: { // 0x503A6E + switch (m_ChainsawState) { + case eChainsawState::STOPPED: + case eChainsawState::IDLE: { + PlaySoundIfNotPlaying(1, 2.f / 3.f, AE_WEAPON_SOUND_CAT_CHAINSAW_IDLE); + + m_ChainsawState = eChainsawState::IDLE; + m_LastChainsawEventTimeMs = CTimer::GetTimeInMS(); + } + } + break; + } + case AE_WEAPON_CHAINSAW_ACTIVE: { // 0x5039C0 + switch (m_ChainsawState) { + case eChainsawState::STOPPING: + case eChainsawState::ACTIVE: + case eChainsawState::IDLE: { + PlaySoundIfNotPlaying(0, 1.25f, AE_WEAPON_SOUND_CAT_CHAINSAW_ACTIVE); + + m_ChainsawState = eChainsawState::ACTIVE; + m_LastChainsawEventTimeMs = CTimer::GetTimeInMS(); + } + } + break; + } + case AE_WEAPON_CHAINSAW_CUTTING: { // 0x503996 + switch (m_ChainsawState) { + case eChainsawState::ACTIVE: + case eChainsawState::CUTTING: { + m_ChainsawState = eChainsawState::CUTTING; + m_LastChainsawEventTimeMs = CTimer::GetTimeInMS(); + } + } + break; + } + } } // 0x504610 -void CAEWeaponAudioEntity::PlayWeaponLoopSound(CPhysical* entity, int16 sfxId, eAudioEvents startEvent, float audability, float speed, eAudioEvents endEvent) { +void CAEWeaponAudioEntity::PlayWeaponLoopSound(CPhysical* entity, int16 sfxId, eAudioEvents startEvent, float audability, float speed, eWeaponSoundCategories soundCat) { if (!AEAudioHardware.IsSoundBankLoaded(143u, 5)) { if (!AudioEngine.IsLoadingTuneActive()) { AEAudioHardware.LoadSoundBank(143, 5); @@ -257,7 +322,7 @@ void CAEWeaponAudioEntity::PlayWeaponLoopSound(CPhysical* entity, int16 sfxId, e const auto flags = static_cast(SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_START_PERCENTAGE | SOUND_REQUEST_UPDATES); m_tempSound.Initialise(5, sfxId, this, entity->GetPosition(), volume, 1.0f, speed, 1.0f, 0, flags); m_tempSound.RegisterWithPhysicalEntity(entity); - m_tempSound.m_nEvent = endEvent; + m_tempSound.m_nEvent = soundCat; AESoundManager.RequestNewSound(&m_tempSound); } @@ -536,8 +601,56 @@ void CAEWeaponAudioEntity::PlayGoggleSound(int16 sfxId, eAudioEvents event) { } // 0x504470 -void CAEWeaponAudioEntity::PlayFlameThrowerSounds(CPhysical* entity, int16 sfx1, int16 sfx2, int32 audioEventId, float audability, float speed) { - plugin::CallMethod<0x504470, CAEWeaponAudioEntity*, CPhysical*, int16, int16, int32, float, float>(this, entity, sfx1, sfx2, audioEventId, audability, speed); +void CAEWeaponAudioEntity::PlayFlameThrowerSounds(CPhysical* entity, int16 dryFireSfxID, int16 flameSfxID, eAudioEvents audioEvent, float volumeOffsetdB, float speed) { + const auto PlaySound = [&](int16 bankSlotID, int16 sfxID, float sfxVolumeOffsetdB, float rollOffFactor, float sfxSpeed, float sfxFreqVariance, eAudioEvents sfxAE) { + CAESound s; + s.Initialise( + bankSlotID, + sfxID, + this, + entity->GetPosition(), + GetDefaultVolume(audioEvent) + volumeOffsetdB + sfxVolumeOffsetdB, + rollOffFactor, + sfxSpeed, + 1.f, + 0, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY|SOUND_REQUEST_UPDATES, + sfxFreqVariance + ); + s.m_nEvent = sfxAE; + s.RegisterWithPhysicalEntity(entity); + AESoundManager.RequestNewSound(&s); + }; + + if (!AEAudioHardware.IsSoundBankLoaded(143u, 5)) { + if (!AudioEngine.IsLoadingTuneActive()) { + AEAudioHardware.LoadSoundBank(143, 5); + } + return; + } + PlaySound( + 5, + dryFireSfxID, + -6.f, + 2.f / 3.f, + speed, + 0.02f, + AE_UNDEFINED + ); + + if (!AEAudioHardware.IsSoundBankLoaded(138, 19)) { + AEAudioHardware.LoadSoundBank(138, 19); + return; + } + PlaySound( + 19, + flameSfxID, + -20.f, + 2.f, + speed * 0.79369998f, + 0.f, + AE_FRONTEND_BACK + ); } // 0x503870 @@ -554,26 +667,34 @@ void CAEWeaponAudioEntity::PlayFlameThrowerIdleGasLoop(CPhysical* entity) { // 0x5034E0 void CAEWeaponAudioEntity::StopFlameThrowerIdleGasLoop() { - if (m_FlameThrowerIdleGasLoopSound) { - m_FlameThrowerIdleGasLoopSound->StopSoundAndForget(); - m_FlameThrowerIdleGasLoopSound = nullptr; + if (auto* const s = std::exchange(m_FlameThrowerIdleGasLoopSound, nullptr)) { + s->StopSoundAndForget(); } } // 0x504AA0 void CAEWeaponAudioEntity::PlayChainsawStopSound(CPhysical* entity) { - if (entity && AEAudioHardware.IsSoundBankLoaded(0x24u, 40)) { - if (m_ChainsawState != 3) { - const auto volume = GetDefaultVolume(AE_WEAPON_CHAINSAW_ACTIVE); - const auto flags = static_cast(SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES); - m_tempSound.Initialise(40, 2, this, entity->GetPosition(), volume, 0.66f, 1.0f, 1.0f, 0, flags); + if (entity && AEAudioHardware.IsSoundBankLoaded(36, 40)) { + if (m_ChainsawState != eChainsawState::STOPPING) { + m_tempSound.Initialise( + 40, + 2, + this, + entity->GetPosition(), + GetDefaultVolume(AE_WEAPON_CHAINSAW_ACTIVE), + 2.f / 3.f, + 1.0f, + 1.0f, + 0, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); m_tempSound.RegisterWithPhysicalEntity(entity); - m_tempSound.m_nEvent = AE_FRONTEND_PICKUP_DRUGS; + m_tempSound.m_nEvent = AE_WEAPON_SOUND_CAT_CHAINSAW_STOP; AESoundManager.RequestNewSound(&m_tempSound); } - m_ChainsawState = 3; + m_ChainsawState = eChainsawState::STOPPING; } else { - m_ChainsawState = 4; + m_ChainsawState = eChainsawState::STOPPED; } } @@ -607,5 +728,3 @@ CAEWeaponAudioEntity* CAEWeaponAudioEntity::Destructor() { this->CAEWeaponAudioEntity::~CAEWeaponAudioEntity(); return this; } - -// 0x504B70 diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.h b/source/game_sa/Audio/entities/AEWeaponAudioEntity.h index e67219e44a..4ad76af801 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.h +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.h @@ -22,6 +22,31 @@ class NOTSA_EXPORT_VTABLE CAEWeaponAudioEntity : public CAEAudioEntity { STOPPED = 0x3, }; + enum eChainsawState : int8 { + IDLE = 0x0, + ACTIVE = 0x1, + CUTTING = 0x2, + STOPPING = 0x3, + STOPPED = 0x4, + }; + + enum eWeaponSoundCategories { + AE_WEAPON_SOUND_CAT_TAIL = 1, // 0x1 + AE_WEAPON_SOUND_CAT_FLAME = 2, // 0x2 + AE_WEAPON_SOUND_CAT_SPRAY = 3, // 0x3 + AE_WEAPON_SOUND_CAT_EXT = 4, // 0x4 + AE_WEAPON_SOUND_CAT_MINIGUN_SPIN = 5, // 0x5 + AE_WEAPON_SOUND_CAT_MINIGUN_FIRE = 6, // 0x6 + AE_WEAPON_SOUND_CAT_MINIGUN_TAIL = 7, // 0x7 + AE_WEAPON_SOUND_CAT_MINIGUN_STOP = 8, // 0x8 + AE_WEAPON_SOUND_CAT_CHAINSAW_IDLE = 9, // 0x9 + AE_WEAPON_SOUND_CAT_CHAINSAW_ACTIVE = 10, // 0xA + AE_WEAPON_SOUND_CAT_CHAINSAW_CUTTING = 11, // 0xB + AE_WEAPON_SOUND_CAT_CHAINSAW_STOP = 12, // 0xC + AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_IN = 13, // 0xD + AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_OUT = 14, // 0xE + }; + public: CAEWeaponAudioEntity(); ~CAEWeaponAudioEntity() = default; @@ -49,15 +74,15 @@ class NOTSA_EXPORT_VTABLE CAEWeaponAudioEntity : public CAEAudioEntity { void ReportStealthKill(eWeaponType type, CPhysical* entity, eAudioEvents event); - void ReportChainsawEvent(CPhysical* entity, int32 audioEventId); + void ReportChainsawEvent(CPhysical* entity, eAudioEvents audioEvent); void PlayChainsawStopSound(CPhysical* entity); - void PlayWeaponLoopSound(CPhysical* entity, int16 sfxId, eAudioEvents startEvent, float audability, float speed, eAudioEvents endEvent); + void PlayWeaponLoopSound(CPhysical* entity, int16 sfxId, eAudioEvents startEvent, float audability, float speed, eWeaponSoundCategories endEvent); void PlayMiniGunFireSounds(CPhysical* entity, eAudioEvents audioEventId); void PlayMiniGunStopSound(CPhysical* entity); - void PlayFlameThrowerSounds(CPhysical* entity, int16 sfx1, int16 sfx2, int32 audioEventId, float audability, float speed); + void PlayFlameThrowerSounds(CPhysical* entity, int16 sfx1, int16 sfx2, eAudioEvents audioEventId, float audability, float speed); void PlayFlameThrowerIdleGasLoop(CPhysical* entity); void StopFlameThrowerIdleGasLoop(); @@ -66,7 +91,7 @@ class NOTSA_EXPORT_VTABLE CAEWeaponAudioEntity : public CAEAudioEntity { void UpdateParameters(CAESound* sound, int16 curPlayPos) override; void Clear() { - m_FlameThrowerLastPlayedTimeMs = 0; + m_LastFlameThrowerFireTimeMs = 0; m_LastSprayCanFireTimeMs = 0; m_LastFireExtFireTimeMs = 0; m_FlameThrowerIdleGasLoopSound = nullptr; @@ -79,18 +104,18 @@ class NOTSA_EXPORT_VTABLE CAEWeaponAudioEntity : public CAEAudioEntity { } private: - bool m_IsMiniGunSpinActive; - bool m_IsMiniGunFireActive; // see PlayMiniGunFireSounds - uint8 m_LastWeaponPlaneFrequencyIndex; // see PlayGunSounds, gfWeaponPlaneFrequencyVariations - eMiniGunState m_MiniGunState; - uint8 m_ChainsawState; - uint32 m_FlameThrowerLastPlayedTimeMs; - uint32 m_LastSprayCanFireTimeMs; - uint32 m_LastFireExtFireTimeMs; - uint32 m_LastMiniGunFireTimeMs; - uint32 m_LastChainsawEventTimeMs; - uint32 m_LastGunFireTimeMs; - CAESound* m_FlameThrowerIdleGasLoopSound; + bool m_IsMiniGunSpinActive; + bool m_IsMiniGunFireActive; // see PlayMiniGunFireSounds + uint8 m_LastWeaponPlaneFrequencyIndex; // see PlayGunSounds, gfWeaponPlaneFrequencyVariations + eMiniGunState m_MiniGunState; + eChainsawState m_ChainsawState; + uint32 m_LastFlameThrowerFireTimeMs; + uint32 m_LastSprayCanFireTimeMs; + uint32 m_LastFireExtFireTimeMs; + uint32 m_LastMiniGunFireTimeMs; + uint32 m_LastChainsawEventTimeMs; + uint32 m_LastGunFireTimeMs; + CAESound* m_FlameThrowerIdleGasLoopSound; private: // Hook stuff friend void InjectHooksMain(); From 7ce3713f0281c1dd18d9b597d741705478f32dd0 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Sun, 21 Jul 2024 16:22:04 +0200 Subject: [PATCH 12/22] `UpdateParameters` --- source/game_sa/Audio/AESound.cpp | 8 +- source/game_sa/Audio/AESound.h | 2 +- .../Audio/entities/AECollisionAudioEntity.cpp | 4 +- .../Audio/entities/AEFireAudioEntity.cpp | 6 +- .../Audio/entities/AEPedAudioEntity.cpp | 2 +- .../entities/AEPoliceScannerAudioEntity.cpp | 2 +- .../Audio/entities/AEWeaponAudioEntity.cpp | 140 +++++++++++++++++- 7 files changed, 145 insertions(+), 19 deletions(-) diff --git a/source/game_sa/Audio/AESound.cpp b/source/game_sa/Audio/AESound.cpp index 2593eab9c0..b249c2d5c6 100644 --- a/source/game_sa/Audio/AESound.cpp +++ b/source/game_sa/Audio/AESound.cpp @@ -42,7 +42,7 @@ CAESound::CAESound(CAESound& sound) { m_nSoundIdInSlot = sound.m_nSoundIdInSlot; m_pBaseAudio = sound.m_pBaseAudio; m_nEvent = sound.m_nEvent; - m_fMaxVolume = sound.m_fMaxVolume; + m_ClientVariable = sound.m_ClientVariable; m_fVolume = sound.m_fVolume; m_fSoundDistance = sound.m_fSoundDistance; m_fSpeed = sound.m_fSpeed; @@ -80,7 +80,7 @@ CAESound::CAESound(int16 bankSlotId, int16 sfxId, CAEAudioEntity* baseAudio, CVe m_pBaseAudio = baseAudio; m_vecPrevPosn = CVector(0.0f, 0.0f, 0.0f); m_pPhysicalEntity = nullptr; - m_fMaxVolume = -1.0F; + m_ClientVariable = -1.0F; m_nEvent = AE_UNDEFINED; m_nLastFrameUpdate = 0; @@ -116,7 +116,7 @@ CAESound& CAESound::operator=(const CAESound& sound) { m_nSoundIdInSlot = sound.m_nSoundIdInSlot; m_pBaseAudio = sound.m_pBaseAudio; m_nEvent = sound.m_nEvent; - m_fMaxVolume = sound.m_fMaxVolume; + m_ClientVariable = sound.m_ClientVariable; m_fVolume = sound.m_fVolume; m_fSoundDistance = sound.m_fSoundDistance; m_fSpeed = sound.m_fSpeed; @@ -309,7 +309,7 @@ void CAESound::Initialise( m_fSpeedVariability = frequencyVariance; m_vecPrevPosn .Set(0.0F, 0.0F, 0.0F); m_nEvent = AE_UNDEFINED; - m_fMaxVolume = -1.0F; + m_ClientVariable = -1.0F; m_nLastFrameUpdate = 0; SetPosition(pos); diff --git a/source/game_sa/Audio/AESound.h b/source/game_sa/Audio/AESound.h index d90a596e91..eb6c81094a 100644 --- a/source/game_sa/Audio/AESound.h +++ b/source/game_sa/Audio/AESound.h @@ -40,7 +40,7 @@ class CAESound { CAEAudioEntity* m_pBaseAudio; CEntity* m_pPhysicalEntity; int32 m_nEvent; // Not necessarily `eAudioEvents`, for ex. see `CAEWeaponAudioEntity` - float m_fMaxVolume; + float m_ClientVariable; float m_fVolume; float m_fSoundDistance; float m_fSpeed; diff --git a/source/game_sa/Audio/entities/AECollisionAudioEntity.cpp b/source/game_sa/Audio/entities/AECollisionAudioEntity.cpp index a619061130..920d69a8e4 100644 --- a/source/game_sa/Audio/entities/AECollisionAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AECollisionAudioEntity.cpp @@ -205,7 +205,7 @@ void CAECollisionAudioEntity::ReportGlassCollisionEvent(eAudioEvents glassSoundT if (time) { auto& snd = m_tempSound; - snd.m_fMaxVolume = (float)(time + CTimer::GetTimeInMS()); + snd.m_ClientVariable = (float)(time + CTimer::GetTimeInMS()); snd.m_nEvent = glassSoundType; snd.m_bRequestUpdates = true; } @@ -248,7 +248,7 @@ void CAECollisionAudioEntity::ReportWaterSplash(CVector posn, float volume) { SOUND_REQUEST_UPDATES ); m_tempSound.m_nEvent = AE_FRONTEND_BACK; - m_tempSound.m_fMaxVolume = static_cast(CTimer::GetTimeInMS() + 166); + m_tempSound.m_ClientVariable = static_cast(CTimer::GetTimeInMS() + 166); } // 0x4DAE40 diff --git a/source/game_sa/Audio/entities/AEFireAudioEntity.cpp b/source/game_sa/Audio/entities/AEFireAudioEntity.cpp index ab0c56c01c..357c2c4ad1 100644 --- a/source/game_sa/Audio/entities/AEFireAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEFireAudioEntity.cpp @@ -77,7 +77,7 @@ void CAEFireAudioEntity::PlayFireSounds(eAudioEvents audioId, CVector& posn) { 0.0f, 0 ); - sound.m_fMaxVolume = volume + 3.0f; + sound.m_ClientVariable = volume + 3.0f; sound.m_nEvent = AE_FRONTEND_SELECT; AESoundManager.RequestNewSound(&sound); } @@ -117,10 +117,10 @@ void CAEFireAudioEntity::UpdateParameters(CAESound* sound, int16 curPlayPos) { switch (sound->m_nEvent) { case AE_FRONTEND_SELECT: - if (sound->m_fVolume >= sound->m_fMaxVolume) { + if (sound->m_fVolume >= sound->m_ClientVariable) { sound->m_nEvent = AE_FRONTEND_BACK; } else { - sound->m_fVolume = std::min(sound->m_fVolume + 2.0f, sound->m_fMaxVolume); + sound->m_fVolume = std::min(sound->m_fVolume + 2.0f, sound->m_ClientVariable); } break; case AE_FRONTEND_BACK: diff --git a/source/game_sa/Audio/entities/AEPedAudioEntity.cpp b/source/game_sa/Audio/entities/AEPedAudioEntity.cpp index 122a0dfebe..427d6f01de 100644 --- a/source/game_sa/Audio/entities/AEPedAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEPedAudioEntity.cpp @@ -309,7 +309,7 @@ void CAEPedAudioEntity::UpdateParameters(CAESound* sound, int16 curPlayPos) { case AE_PED_JACKED_CAR_KICK: case AE_PED_JACKED_BIKE: case AE_PED_JACKED_DOZER: - if (CTimer::GetTimeInMS() < (uint32)sound->m_fMaxVolume) + if (CTimer::GetTimeInMS() < (uint32)sound->m_ClientVariable) return; sound->m_fSpeed = 1.0f; return; diff --git a/source/game_sa/Audio/entities/AEPoliceScannerAudioEntity.cpp b/source/game_sa/Audio/entities/AEPoliceScannerAudioEntity.cpp index 84cd3e65d3..f87cd2ce7b 100644 --- a/source/game_sa/Audio/entities/AEPoliceScannerAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEPoliceScannerAudioEntity.cpp @@ -204,7 +204,7 @@ void CAEPoliceScannerAudioEntity::PlayLoadedDialogue() { auto volume = GetDefaultVolume(AE_CRIME_COMMITTED) + s_fVolumeOffset; CAESound sound; sound.Initialise(i + 33, s_pCurrentSlots[i].sfxId, this, { 0.0, 1.0f, 0.0f }, volume, 1.0f, 1.0f, 1.0f, 0, SOUND_DEFAULT, 0.0f, 0); - sound.m_fMaxVolume = (float)i; + sound.m_ClientVariable = (float)i; sound.m_nEnvironmentFlags = SOUND_FRONT_END | SOUND_UNCANCELLABLE | SOUND_REQUEST_UPDATES | SOUND_UNDUCKABLE; sound.m_nEvent = AE_CRIME_COMMITTED; diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp index 344d69b757..e4c6b0368d 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp @@ -38,7 +38,7 @@ void CAEWeaponAudioEntity::InjectHooks() { RH_ScopedInstall(PlayFlameThrowerIdleGasLoop, 0x503870); RH_ScopedInstall(PlayGoggleSound, 0x503500); RH_ScopedInstall(StopFlameThrowerIdleGasLoop, 0x5034E0); - RH_ScopedInstall(UpdateParameters, 0x504B70, { .reversed = false }); + RH_ScopedInstall(UpdateParameters, 0x504B70); } // 0x507560 @@ -222,7 +222,7 @@ void CAEWeaponAudioEntity::ReportStealthKill(eWeaponType type, CPhysical* entity m_tempSound.Initialise(5, 81, this, entity->GetPosition(), vol - 6.0f, 1.0f, 0.0f, 1.0f, 0); m_tempSound.RegisterWithPhysicalEntity(entity); m_tempSound.m_nEvent = AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_IN; - m_tempSound.m_fMaxVolume = (float)CTimer::m_snTimeInMilliseconds; + m_tempSound.m_ClientVariable = (float)CTimer::GetTimeInMS(); AESoundManager.RequestNewSound(&m_tempSound); if (!AEAudioHardware.IsSoundBankLoaded(39, 2)) { @@ -234,7 +234,7 @@ void CAEWeaponAudioEntity::ReportStealthKill(eWeaponType type, CPhysical* entity m_tempSound.Initialise(2, 47, this, entity->GetPosition(), vol, 1.0f, 0.0f, 1.0f, 0, flags); m_tempSound.RegisterWithPhysicalEntity(entity); m_tempSound.m_nEvent = AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_OUT; - m_tempSound.m_fMaxVolume = (float)CTimer::GetTimeInMS(); + m_tempSound.m_ClientVariable = (float)CTimer::GetTimeInMS(); AESoundManager.RequestNewSound(&m_tempSound); } @@ -715,16 +715,142 @@ void CAEWeaponAudioEntity::PlayCameraSound(CPhysical* entity, eAudioEvents event } // 0x504B70 -void CAEWeaponAudioEntity::UpdateParameters(CAESound *sound, int16 curPlayPos) { - plugin::CallMethod<0x504B70, CAEWeaponAudioEntity*, CAESound*, int16>(this, sound, curPlayPos); +void CAEWeaponAudioEntity::UpdateParameters(CAESound* sound, int16 curPlayPos) { + if (curPlayPos == -1) { + if (sound == m_FlameThrowerIdleGasLoopSound) { + m_FlameThrowerIdleGasLoopSound = nullptr; + } else if (sound->m_nEvent == AE_WEAPON_SOUND_CAT_MINIGUN_STOP && m_MiniGunState == eMiniGunState::STOPPING) { + m_MiniGunState = eMiniGunState::STOPPED; + } + return; + } + + switch (sound->m_nEvent) { + case AE_WEAPON_SOUND_CAT_TAIL: { // 0x504BAA + if (!CGame::CanSeeOutSideFromCurrArea()) { + sound->m_fVolume -= 1.f; + } + break; + } + case AE_WEAPON_SOUND_CAT_FLAME: { // 0x504BC3 + if (m_LastFlameThrowerFireTimeMs + 300 >= CTimer::GetTimeInMS()) { + sound->m_fVolume = std::max(GetDefaultVolume(AE_WEAPON_FIRE), sound->m_fVolume + 2.f); // TODO: Use TimeStep + } else { + sound->StopSoundAndForget(); + m_LastFlameThrowerFireTimeMs = 0; + } + break; + } + case AE_WEAPON_SOUND_CAT_SPRAY: { // 0x504C38 + if (m_LastSprayCanFireTimeMs + 300 < CTimer::GetTimeInMS()) { + sound->StopSoundAndForget(); + m_LastSprayCanFireTimeMs = 0; + } + break; + } + case AE_WEAPON_SOUND_CAT_EXT: { // 0x504C5F + if (m_LastFireExtFireTimeMs + 300 >= CTimer::GetTimeInMS()) { + sound->m_fSpeed = std::max(0.85f, sound->m_fSpeed + 0.01f); // TODO: Use TimeStep + } else { + sound->StopSoundAndForget(); + m_LastFireExtFireTimeMs = 0; + } + break; + } + case AE_WEAPON_SOUND_CAT_MINIGUN_SPIN: { // 0x504CBC + if (m_LastMiniGunFireTimeMs + 300 < CTimer::GetTimeInMS()) { + PlayMiniGunStopSound(sound->m_pPhysicalEntity->AsPhysical()); + } + switch (m_MiniGunState) { + case eMiniGunState::STOPPING: + case eMiniGunState::STOPPED: { + sound->StopSoundAndForget(); + m_IsMiniGunSpinActive = 0; + } + } + break; + } + case AE_WEAPON_SOUND_CAT_MINIGUN_FIRE: { // 0x504CFB + if (m_LastMiniGunFireTimeMs + 300 < CTimer::GetTimeInMS()) { + PlayMiniGunStopSound(sound->m_pPhysicalEntity->AsPhysical()); + } + if (m_MiniGunState != eMiniGunState::FIRING) { + sound->StopSoundAndForget(); + m_IsMiniGunFireActive = 0; + } + break; + } + case AE_WEAPON_SOUND_CAT_MINIGUN_TAIL: { // 0x504D31 + if (m_MiniGunState != eMiniGunState::FIRING) { + if (sound->m_fVolume <= -30.0) { + sound->StopSoundAndForget(); + } else { + sound->m_fVolume -= 1.5f; + } + } + break; + } + case AE_WEAPON_SOUND_CAT_CHAINSAW_IDLE: { // 0x504D6B + if (m_LastChainsawEventTimeMs + 300 < CTimer::GetTimeInMS()) { + m_ChainsawState = eChainsawState::STOPPED; + } + if (m_ChainsawState != eChainsawState::IDLE) { + sound->StopSoundAndForget(); + } + break; + } + case AE_WEAPON_SOUND_CAT_CHAINSAW_ACTIVE: { // 0x504D9B + switch (m_ChainsawState) { + case eChainsawState::CUTTING: { // 0x504DA5 + if (m_LastChainsawEventTimeMs + 400 >= CTimer::m_snTimeInMilliseconds) { + sound->m_fSpeed = std::max(0.85f, sound->m_fSpeed - 0.15f); // TODO: Use TimeStep + } else { + m_LastChainsawEventTimeMs = CTimer::m_snTimeInMilliseconds; + m_ChainsawState = eChainsawState::ACTIVE; + } + break; + } + case eChainsawState::ACTIVE: { // 0x504E0E + sound->m_fSpeed = std::min(1.f, sound->m_fSpeed + 0.03f); // TODO: Use TimeStep + if (m_LastChainsawEventTimeMs + 300 < CTimer::GetTimeInMS()) { + PlayChainsawStopSound(sound->m_pPhysicalEntity->AsPhysical()); + } + break; + } + default: { + sound->StopSoundAndForget(); + break; + } + } + case AE_WEAPON_SOUND_CAT_CHAINSAW_STOP: // 0x504E66 + if (m_ChainsawState == eChainsawState::STOPPING && curPlayPos > 1'000) { + m_ChainsawState = eChainsawState::IDLE; + } + break; + case AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_IN: // 0x504E8B + if ((uint32)sound->m_ClientVariable + 820 < CTimer::GetTimeInMS()) { + sound->m_fSpeed = 0.84f; + } + break; + case AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_OUT: // 0x504EBF + if ((uint32)sound->m_ClientVariable + 2200 < CTimer::GetTimeInMS()) { + sound->m_fSpeed = 1.f; + } + break; + } + default: { // 0x504ECD + sound->m_fVolume = std::max(0.f, sound->m_fVolume - 2.5f); + break; + } + } } CAEWeaponAudioEntity* CAEWeaponAudioEntity::Constructor() { - this->CAEWeaponAudioEntity::CAEWeaponAudioEntity(); + CAEWeaponAudioEntity::CAEWeaponAudioEntity(); return this; } CAEWeaponAudioEntity* CAEWeaponAudioEntity::Destructor() { - this->CAEWeaponAudioEntity::~CAEWeaponAudioEntity(); + CAEWeaponAudioEntity::~CAEWeaponAudioEntity(); return this; } From e6c6a6cca513d4067b1fad6f910e18855e38e2f3 Mon Sep 17 00:00:00 2001 From: Pirulax Date: Sun, 21 Jul 2024 19:28:44 +0200 Subject: [PATCH 13/22] Finishing touches --- source/game_sa/Audio/AESound.h | 12 +- source/game_sa/Audio/Enums/SoundIDs.h | 96 +++ .../Audio/entities/AEWeaponAudioEntity.cpp | 729 +++++++++++------- .../Audio/entities/AEWeaponAudioEntity.h | 44 +- .../game_sa/Audio/managers/AESoundManager.cpp | 27 + .../game_sa/Audio/managers/AESoundManager.h | 25 + 6 files changed, 596 insertions(+), 337 deletions(-) create mode 100644 source/game_sa/Audio/Enums/SoundIDs.h diff --git a/source/game_sa/Audio/AESound.h b/source/game_sa/Audio/AESound.h index eb6c81094a..1e3cfa2546 100644 --- a/source/game_sa/Audio/AESound.h +++ b/source/game_sa/Audio/AESound.h @@ -11,6 +11,8 @@ class CAEAudioEntity; class CEntity; +using tSoundID = int16; + enum eSoundEnvironment : uint16 { SOUND_DEFAULT = 0x0, SOUND_FRONT_END = 0x1, @@ -112,16 +114,6 @@ class CAESound { float frequencyVariance = 0.f, int16 playTime = 0 ); - //int16 bankSlotId, - //int16 sfxId, - //CAEAudioEntity* baseAudio, CVector posn, float volume, - // float maxDistance = 1.0f, - // float speed = 1.0f, - // float timeScale = 1.0f, - // uint8 ignoredServiceCycles = 0, - // /*eSoundEnvironment*/ uint32 environmentFlags = static_cast(0), - // float speedVariability = 0, - // int16 currPlayPosn = 0); void UnregisterWithPhysicalEntity(); void StopSound(); diff --git a/source/game_sa/Audio/Enums/SoundIDs.h b/source/game_sa/Audio/Enums/SoundIDs.h new file mode 100644 index 0000000000..ef9884d37b --- /dev/null +++ b/source/game_sa/Audio/Enums/SoundIDs.h @@ -0,0 +1,96 @@ +#pragma once + +using tSoundID = int16; + +enum eGenrlWeaponSoundID : tSoundID { // GENRL_WEAPONS + SND_GENRL_WEAPONS_UNK = -1, + SND_GENRL_WEAPONS_9MM1SHOT_L = 0x0, + SND_GENRL_WEAPONS_9MM1SHOT_R = 0x1, + SND_GENRL_WEAPONS_9MM1TAIL = 0x2, + SND_GENRL_WEAPONS_AK_SHOT_L = 0x3, + SND_GENRL_WEAPONS_AK_SHOT_R = 0x4, + SND_GENRL_WEAPONS_AK_TAIL_L = 0x5, + SND_GENRL_WEAPONS_EAGLE_SHOT_L = 0x6, + SND_GENRL_WEAPONS_EAGLE_SHOT_R = 0x7, + SND_GENRL_WEAPONS_EAGLE_TAIL_L = 0x8, + SND_GENRL_WEAPONS_FIRE_EXT = 0x9, + SND_GENRL_WEAPONS_GAS_LOOP = 0xA, + SND_GENRL_WEAPONS_MINIGUN_SHOT_L = 0xB, + SND_GENRL_WEAPONS_MINIGUN_SHOT_R = 0xC, + SND_GENRL_WEAPONS_MINIGUN_TAIL = 0xD, + SND_GENRL_WEAPONS_MINIGUNEMPTY = 0xE, + SND_GENRL_WEAPONS_MINIGUNHIGHS = 0xF, + SND_GENRL_WEAPONS_MINIGUNLOWS = 0x10, + SND_GENRL_WEAPONS_MP5SHOT_L = 0x11, + SND_GENRL_WEAPONS_MP5SHOT_R = 0x12, + SND_GENRL_WEAPONS_PARACHUTE_WIND_LOOP_A = 0x13, + SND_GENRL_WEAPONS_PARACHUTE_WIND_LOOP_B = 0x14, + SND_GENRL_WEAPONS_SHOTGUN_SHOT_L = 0x15, + SND_GENRL_WEAPONS_SHOTGUN_SHOT_R = 0x16, + SND_GENRL_WEAPONS_SHOTGUN_TAIL_R = 0x17, + SND_GENRL_WEAPONS_SILENCED_SHOT_L = 0x18, + SND_GENRL_WEAPONS_SILENCED_SHOT_R = 0x19, + SND_GENRL_WEAPONS_SNIPER_SHOT_L = 0x1A, + SND_GENRL_WEAPONS_SNIPER_SHOT_R = 0x1B, + SND_GENRL_WEAPONS_SPRAY_PAINT = 0x1C, + SND_GENRL_WEAPONS_9MM1DRY = 0x1D, + SND_GENRL_WEAPONS_9MM1LOWS = 0x1E, + SND_GENRL_WEAPONS_AK_A = 0x1F, + SND_GENRL_WEAPONS_AK_B = 0x20, + SND_GENRL_WEAPONS_AK_DRYFIRE = 0x21, + SND_GENRL_WEAPONS_BASEBALL_BAT = 0x22, + SND_GENRL_WEAPONS_BAT_STRIKE = 0x23, + SND_GENRL_WEAPONS_BODY_PUNCH1 = 0x24, + SND_GENRL_WEAPONS_BODY_PUNCH2 = 0x25, + SND_GENRL_WEAPONS_BODY_PUNCH3 = 0x26, + SND_GENRL_WEAPONS_BODY_PUNCH4 = 0x27, + SND_GENRL_WEAPONS_BOX_FACE1 = 0x28, + SND_GENRL_WEAPONS_BOX_FACE2 = 0x29, + SND_GENRL_WEAPONS_BOX_FACE3 = 0x2A, + SND_GENRL_WEAPONS_BOX_FACE4 = 0x2B, + SND_GENRL_WEAPONS_BRASS_KNUCKLES = 0x2C, + SND_GENRL_WEAPONS_CAMERA = 0x2D, + SND_GENRL_WEAPONS_CANE_STRIKE = 0x2E, + SND_GENRL_WEAPONS_CANE_SWISH = 0x2F, + SND_GENRL_WEAPONS_CLUB_STRIKE = 0x30, + SND_GENRL_WEAPONS_DETONATOR_BEEP = 0x31, + SND_GENRL_WEAPONS_DILDO = 0x32, + SND_GENRL_WEAPONS_EAGLE_B = 0x33, + SND_GENRL_WEAPONS_EAGLE_DRYFIRE = 0x34, + SND_GENRL_WEAPONS_EAGLE_LOWS = 0x35, + SND_GENRL_WEAPONS_FLOWER_STRIKE = 0x36, + SND_GENRL_WEAPONS_HANDGUN_A = 0x37, + SND_GENRL_WEAPONS_KATANA_SWORD = 0x38, + SND_GENRL_WEAPONS_KNIFE = 0x39, + SND_GENRL_WEAPONS_KNUCKLE = 0x3A, + SND_GENRL_WEAPONS_MARTIAL_STRIKE1 = 0x3B, + SND_GENRL_WEAPONS_MARTIAL_STRIKE2 = 0x3C, + SND_GENRL_WEAPONS_MARTIAL_STRIKE3 = 0x3D, + SND_GENRL_WEAPONS_MARTIAL_STRIKE4 = 0x3E, + SND_GENRL_WEAPONS_MINIGUNOFF = 0x3F, + SND_GENRL_WEAPONS_NIGHT_VISION = 0x40, + SND_GENRL_WEAPONS_PARACHUTE_OPEN = 0x41, + SND_GENRL_WEAPONS_PISTOL_B = 0x42, + SND_GENRL_WEAPONS_POOLCUE = 0x43, + SND_GENRL_WEAPONS_ROCKET_LAUNCH = 0x44, + SND_GENRL_WEAPONS_SAWNOFF_A = 0x45, + SND_GENRL_WEAPONS_SAWNOFF_B = 0x46, + SND_GENRL_WEAPONS_SHOTGUN_A = 0x47, + SND_GENRL_WEAPONS_SHOTGUN_B = 0x48, + SND_GENRL_WEAPONS_SHOTGUN_DRYFIRE = 0x49, + SND_GENRL_WEAPONS_SHOTGUN_LOWS = 0x4A, + SND_GENRL_WEAPONS_SHOVEL = 0x4B, + SND_GENRL_WEAPONS_SILENCED_DRYFIRE = 0x4C, + SND_GENRL_WEAPONS_SILENCED_LOWS = 0x4D, + SND_GENRL_WEAPONS_SMACK_1 = 0x4E, + SND_GENRL_WEAPONS_SMACK_2 = 0x4F, + SND_GENRL_WEAPONS_SMACK_3 = 0x50, + SND_GENRL_WEAPONS_STAB = 0x51, + SND_GENRL_WEAPONS_STOMP1 = 0x52, + SND_GENRL_WEAPONS_TRIGGER = 0x53, + SND_GENRL_WEAPONS_UZI_A = 0x54, + SND_GENRL_WEAPONS_UZI_B = 0x55, + SND_GENRL_WEAPONS_WEAPON_SWIPE = 0x56, + SND_GENRL_WEAPONS_WEAPON_SWIPE_FIST = 0x57, + SND_GENRL_WEAPONS_WEAPON_SWIPE_METAL = 0x58, +}; diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp index e4c6b0368d..d2887cea87 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.cpp @@ -48,7 +48,7 @@ CAEWeaponAudioEntity::CAEWeaponAudioEntity() { // 0x503450 void CAEWeaponAudioEntity::Initialise() { - m_MiniGunState = eMiniGunState::STOPPED; + m_MiniGunState = eMiniGunState::STOPPED; m_ChainsawState = eChainsawState::STOPPED; if (!AudioEngine.IsLoadingTuneActive()) { AEAudioHardware.LoadSoundBank(143, 5); @@ -67,82 +67,194 @@ void CAEWeaponAudioEntity::Reset() { } // 0x504F80 -void CAEWeaponAudioEntity::WeaponFire(eWeaponType type, CPhysical* entity, eAudioEvents audioEventId) { - if (!entity) { +void CAEWeaponAudioEntity::WeaponFire(eWeaponType weaponType, CPhysical* parent, eAudioEvents audioEvent) { + if (!parent) { return; } - switch (type) { + switch (weaponType) { case WEAPON_PISTOL: - return PlayGunSounds(entity, 52, 53, 6, 7, 8, audioEventId, 0.0f, 1.41421f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_EAGLE_DRYFIRE, + SND_GENRL_WEAPONS_EAGLE_LOWS, + SND_GENRL_WEAPONS_EAGLE_SHOT_L, + SND_GENRL_WEAPONS_EAGLE_SHOT_R, + SND_GENRL_WEAPONS_EAGLE_TAIL_L, + audioEvent, + 0.0f, + 1.41421f + ); case WEAPON_PISTOL_SILENCED: - return PlayGunSounds(entity, 76, 77, 24, 24, -1, audioEventId, -7.0f, 1.0f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_SILENCED_DRYFIRE, + SND_GENRL_WEAPONS_SILENCED_LOWS, + SND_GENRL_WEAPONS_SILENCED_SHOT_L, + SND_GENRL_WEAPONS_SILENCED_SHOT_L, + SND_GENRL_WEAPONS_UNK, + audioEvent, + -7.f + ); case WEAPON_DESERT_EAGLE: - return PlayGunSounds(entity, 52, 53, 6, 7, 8, audioEventId, 0.0f, 0.94387001f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_EAGLE_DRYFIRE, + SND_GENRL_WEAPONS_EAGLE_LOWS, + SND_GENRL_WEAPONS_EAGLE_SHOT_L, + SND_GENRL_WEAPONS_EAGLE_SHOT_R, + SND_GENRL_WEAPONS_EAGLE_TAIL_L, + audioEvent, + 0.f, + 0.94387001f + ); case WEAPON_SHOTGUN: case WEAPON_SPAS12_SHOTGUN: - return PlayGunSounds(entity, 73, 74, 21, 22, 23, audioEventId, 0.0f, 1.0f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_SHOTGUN_DRYFIRE, + SND_GENRL_WEAPONS_SHOTGUN_LOWS, + SND_GENRL_WEAPONS_SHOTGUN_SHOT_L, + SND_GENRL_WEAPONS_SHOTGUN_SHOT_R, + SND_GENRL_WEAPONS_SHOTGUN_TAIL_R, + audioEvent, + 0.f + ); case WEAPON_SAWNOFF_SHOTGUN: - return PlayGunSounds(entity, 73, 74, 21, 22, 23, audioEventId, 0.0f, 0.79369998f, 0.93f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_SHOTGUN_DRYFIRE, + SND_GENRL_WEAPONS_SHOTGUN_LOWS, + SND_GENRL_WEAPONS_SHOTGUN_SHOT_L, + SND_GENRL_WEAPONS_SHOTGUN_SHOT_R, + SND_GENRL_WEAPONS_SHOTGUN_TAIL_R, + audioEvent, + 0.0f, + 0.79369998f, + 0.93f + ); case WEAPON_MICRO_UZI: - return PlayGunSounds(entity, 29, 30, 0, 1, 2, audioEventId, 0.0f, 1.0f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_9MM1DRY, + SND_GENRL_WEAPONS_9MM1LOWS, + SND_GENRL_WEAPONS_9MM1SHOT_L, + SND_GENRL_WEAPONS_9MM1SHOT_R, + SND_GENRL_WEAPONS_9MM1TAIL, + audioEvent + ); case WEAPON_MP5: - return PlayGunSounds(entity, 29, 30, 17, 18, 2, audioEventId, 0.0f, 1.0f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_9MM1DRY, + SND_GENRL_WEAPONS_9MM1LOWS, + SND_GENRL_WEAPONS_MP5SHOT_L, + SND_GENRL_WEAPONS_MP5SHOT_R, + SND_GENRL_WEAPONS_9MM1TAIL, + audioEvent + ); case WEAPON_AK47: case WEAPON_M4: - return PlayGunSounds(entity, 33, 53, 3, 4, 5, audioEventId, 0.0f, 1.0f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_AK_DRYFIRE, + SND_GENRL_WEAPONS_EAGLE_LOWS, + SND_GENRL_WEAPONS_AK_SHOT_L, + SND_GENRL_WEAPONS_AK_SHOT_R, + SND_GENRL_WEAPONS_AK_TAIL_L, + audioEvent + ); case WEAPON_TEC9: - return PlayGunSounds(entity, 29, 30, 0, 1, 2, audioEventId, 0.0f, 1.25992f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_9MM1DRY, + SND_GENRL_WEAPONS_9MM1LOWS, + SND_GENRL_WEAPONS_9MM1SHOT_L, + SND_GENRL_WEAPONS_9MM1SHOT_R, + SND_GENRL_WEAPONS_9MM1TAIL, + audioEvent, + 0.0f, + 1.25992f + ); case WEAPON_COUNTRYRIFLE: - return PlayGunSounds(entity, 52, 53, 26, 27, 23, audioEventId, 0.0f, 0.89f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_EAGLE_DRYFIRE, + SND_GENRL_WEAPONS_EAGLE_LOWS, + SND_GENRL_WEAPONS_SNIPER_SHOT_L, + SND_GENRL_WEAPONS_SNIPER_SHOT_R, + SND_GENRL_WEAPONS_SHOTGUN_TAIL_R, + audioEvent, + 0.0f, + 0.89f + ); case WEAPON_SNIPERRIFLE: - return PlayGunSounds(entity, 52, 53, 26, 27, 23, audioEventId, 0.0f, 1.0f, 1.0f); - - case WEAPON_FLAMETHROWER: - if (!m_LastFlameThrowerFireTimeMs) - PlayFlameThrowerSounds(entity, 83, 26, audioEventId, -14.0f, 1.0f); - m_LastFlameThrowerFireTimeMs = CTimer::GetTimeInMS(); + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_EAGLE_DRYFIRE, + SND_GENRL_WEAPONS_EAGLE_LOWS, + SND_GENRL_WEAPONS_SNIPER_SHOT_L, + SND_GENRL_WEAPONS_SNIPER_SHOT_R, + SND_GENRL_WEAPONS_SHOTGUN_TAIL_R, + audioEvent + ); + case WEAPON_FLAMETHROWER: { + if (!std::exchange(m_LastFlameThrowerFireTimeMs, CTimer::GetTimeInMS())) { + PlayFlameThrowerSounds( + parent, + SND_GENRL_WEAPONS_TRIGGER, + SND_GENRL_WEAPONS_SNIPER_SHOT_L, + audioEvent, + -14.f, + 1.f + ); + } break; - + } case WEAPON_MINIGUN: - return PlayMiniGunFireSounds(entity, audioEventId); - + return PlayMiniGunFireSounds(parent, audioEvent); case WEAPON_DETONATOR: - return PlayGunSounds(entity, 49, -1, -1, -1, -1, audioEventId, -14.0f, 1.0f, 1.0f); - + return PlayGunSounds( + parent, + SND_GENRL_WEAPONS_DETONATOR_BEEP, + SND_GENRL_WEAPONS_UNK, + SND_GENRL_WEAPONS_UNK, + SND_GENRL_WEAPONS_UNK, + SND_GENRL_WEAPONS_UNK, + audioEvent, + -14.0f + ); case WEAPON_SPRAYCAN: - if (!m_LastSprayCanFireTimeMs) { - PlayWeaponLoopSound(entity, 28, audioEventId, -20.0f, 1.0f, AE_WEAPON_SOUND_CAT_SPRAY); + if (!std::exchange(m_LastSprayCanFireTimeMs, CTimer::GetTimeInMS())) { + PlayWeaponLoopSound( + parent, + SND_GENRL_WEAPONS_SPRAY_PAINT, + audioEvent, + -20.0, + 1.0f, + AE_WEAPON_SOUND_CAT_SPRAY + ); } - m_LastSprayCanFireTimeMs = CTimer::GetTimeInMS(); break; - case WEAPON_EXTINGUISHER: - if (!m_LastFireExtFireTimeMs) - PlayWeaponLoopSound(entity, 9, audioEventId, -20.0f, 0.79369998f, AE_WEAPON_SOUND_CAT_EXT); - - m_LastFireExtFireTimeMs = CTimer::GetTimeInMS(); + if (!std::exchange(m_LastFireExtFireTimeMs, CTimer::GetTimeInMS())) { + PlayWeaponLoopSound( + parent, + SND_GENRL_WEAPONS_FIRE_EXT, + audioEvent, + -20.0, + 0.79369998f, + AE_WEAPON_SOUND_CAT_EXT + ); + } break; - case WEAPON_CAMERA: - return PlayCameraSound(entity, audioEventId, -14.0); - + return PlayCameraSound(parent, audioEvent, -14.0); case WEAPON_NIGHTVISION: case WEAPON_INFRARED: - return PlayGoggleSound(64, audioEventId); - + return PlayGoggleSound(SND_GENRL_WEAPONS_NIGHT_VISION, audioEvent); default: - return; + NOTSA_UNREACHABLE(); } } @@ -158,60 +270,233 @@ void CAEWeaponAudioEntity::WeaponReload(eWeaponType type, CPhysical* entity, eAu return; } - int16 soundType; - float volumeOffset = 0.0f; + const auto PlaySound = [&](tSoundID soundID, float volumeOffsetdB = 0.f) { + CAESound s; + s.Initialise( + 5, + soundID, + this, + entity->GetPosition(), + GetDefaultVolume(event) + volumeOffsetdB, + 2.f / 3.f, + 1.0f, + 1.0f, + 0, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY + ); + s.RegisterWithPhysicalEntity(entity); + AESoundManager.RequestNewSound(&s); + }; switch (type) { case WEAPON_PISTOL: case WEAPON_PISTOL_SILENCED: - soundType = event != AE_WEAPON_RELOAD_A ? 66 : 55; - break; + return PlaySound(event == AE_WEAPON_RELOAD_A ? 55 : 66); case WEAPON_DESERT_EAGLE: - soundType = 4 * (event == AE_WEAPON_RELOAD_A) + 51; - break; + return PlaySound(event == AE_WEAPON_RELOAD_A ? 55 : 51); case WEAPON_SHOTGUN: case WEAPON_SPAS12_SHOTGUN: - soundType = (event != AE_WEAPON_RELOAD_A) + 71; - break; + return PlaySound(event == AE_WEAPON_RELOAD_A ? 72 : 71); case WEAPON_SAWNOFF_SHOTGUN: - soundType = (event != AE_WEAPON_RELOAD_A) + 69; - break; + return PlaySound(event == AE_WEAPON_RELOAD_A ? 70 : 69); case WEAPON_MICRO_UZI: case WEAPON_MP5: case WEAPON_TEC9: - soundType = (event != AE_WEAPON_RELOAD_A) + 84; - break; + return PlaySound(event == AE_WEAPON_RELOAD_A ? 85 : 84); case WEAPON_AK47: case WEAPON_M4: - soundType = (event != AE_WEAPON_RELOAD_A) + 31; - break; + return PlaySound(event == AE_WEAPON_RELOAD_A ? 32 : 31); case WEAPON_COUNTRYRIFLE: - if (event != AE_WEAPON_RELOAD_A) - return; - soundType = 32; - volumeOffset = -6.0f; + if (event == AE_WEAPON_RELOAD_A) { + return PlaySound(32, -6.f); + } break; case WEAPON_SNIPERRIFLE: - soundType = event != AE_WEAPON_RELOAD_A ? 32 : 55; - break; - default: + return PlaySound(event == AE_WEAPON_RELOAD_A ? 55 : 32); + } +} + + +// 0x503CE0 +void CAEWeaponAudioEntity::PlayGunSounds( + CPhysical* entity, + int16 dryFireSfxID, + int16 subSfxID, + int16 mainLeftSfxID, + int16 mainRightSfxID, + int16 tailSfxID, + eAudioEvents audioEvent, + float volumeOffsetdB, + float primarySpeed, + float tailFrequencyScalingFactor +) { + if (!AEAudioHardware.IsSoundBankLoaded(143u, 5)) { + if (!AudioEngine.IsLoadingTuneActive()) { + AEAudioHardware.LoadSoundBank(143, 5); + } + return; + } + + if (CTimer::GetTimeInMS() < m_LastGunFireTimeMs + 25) { return; } + m_LastGunFireTimeMs = CTimer::GetTimeInMS(); + + auto baseVolume = GetDefaultVolume(audioEvent) + volumeOffsetdB; + auto [baseRollOffFactor, baseSpeed] = [&]() -> std::pair { + switch (audioEvent) { + case AE_WEAPON_FIRE_PLANE: { + m_LastWeaponPlaneFrequencyIndex = (m_LastWeaponPlaneFrequencyIndex + 1) % 2; + return {1.6f, gfWeaponPlaneFrequencyVariations[m_LastWeaponPlaneFrequencyIndex] * primarySpeed * 0.7937f}; + } + case AE_WEAPON_FIRE_MINIGUN_PLANE: { + return {1.8f, primarySpeed * 0.7937f}; + } + default: { + return {1.f, primarySpeed}; + } + } + }(); + + const auto PlaySound = [&](int16 sfxID, CVector pos, float volume, float rollOffFactor, float speed, uint32 flags, eAudioEvents audioEventOverride = AE_UNDEFINED) { + CAESound s; + s.Initialise( + 5, + sfxID, + this, + pos, + volume, + rollOffFactor, + speed, + 0.f, + 0, + flags + ); + if (flags & SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY) { + s.RegisterWithPhysicalEntity(entity); + } + if (audioEventOverride == AE_UNDEFINED) { + switch (audioEvent) { + case AE_WEAPON_FIRE_MINIGUN_PLANE: + case AE_WEAPON_FIRE_MINIGUN_AMMO: + s.m_nEvent = AE_FRONTEND_PICKUP_WEAPON; + } + } else { + s.m_nEvent = audioEventOverride; + } + AESoundManager.RequestNewSound(&s); + }; + + if (dryFireSfxID != -1) { // 0x503DFF + PlaySound( + dryFireSfxID, + entity->GetPosition(), + baseVolume, + baseRollOffFactor * (2.f / 3.f), + baseSpeed, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); + } + if (subSfxID != -1) { // 0x503E93 + PlaySound( + subSfxID, + entity->GetPosition(), + baseVolume, + baseRollOffFactor * 0.9f, + baseSpeed, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); + } - const auto volume = GetDefaultVolume(event) + volumeOffset; + // 0x503F21 + float frontEndVolume = -100.f; + if (!notsa::contains({ AE_WEAPON_FIRE_PLANE, AE_WEAPON_FIRE_MINIGUN_PLANE }, audioEvent)) { + const auto dist = CAEAudioEnvironment::GetPositionRelativeToCamera(entity).Magnitude() / (baseRollOffFactor * 1.25f); + if (dist < (5.f / baseRollOffFactor)) { // Inverted + baseVolume -= 3.f; + frontEndVolume = baseVolume + CAEAudioEnvironment::GetDistanceAttenuation(dist); + } else if (dist < (12.f / baseRollOffFactor)) { + const auto t = ((12.f / baseRollOffFactor) - dist) / (12.f / baseRollOffFactor) - (5.f / baseRollOffFactor); + frontEndVolume = baseVolume + CAEAudioEnvironment::GetDistanceAttenuation(dist) + std::log10f(t * (SQRT_2 / 2.f)) * 20.f; + baseVolume += std::log10f(((1.f - t) * 0.2929f) + (SQRT_2 / 2.f)) * 20.f; + } + } - m_tempSound.Initialise(5, soundType, this, entity->GetPosition(), volume, 0.66f, 1.0f, 1.0f, 0, SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY, 0.0f, 0); - m_tempSound.RegisterWithPhysicalEntity(entity); - AESoundManager.RequestNewSound(&m_tempSound); + const auto PlayMainSound = [ + &, + mainSoundSpeed = (CAEAudioUtility::GetRandomNumberInRange(-0.02f, 0.02f) + 1.f) * baseSpeed + ](int16 sfxID, bool isRight) { + PlaySound( + sfxID, + CVector{isRight ? 1.f : -1.f, 0.f, 0.f}, + frontEndVolume, + baseRollOffFactor * 1.25f, + mainSoundSpeed, + SOUND_FORCED_FRONT | SOUND_REQUEST_UPDATES | SOUND_FRONT_END + ); + PlaySound( + sfxID, + entity->GetPosition(), + baseVolume, + baseRollOffFactor * 1.25f, + mainSoundSpeed, + SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES + ); + }; + if (mainLeftSfxID != -1) { // 0x5040DC + 0x5041DF + PlayMainSound(mainLeftSfxID, false); + } + if (mainRightSfxID != -1) { // 0x504153 + 0x504218 + PlayMainSound(mainRightSfxID, true); + } + + if (tailSfxID != -1 && !notsa::contains({AE_WEAPON_FIRE_PLANE, AE_WEAPON_FIRE_MINIGUN_PLANE}, audioEvent)) { + const auto tailSoundRollOff = baseRollOffFactor * 3.5f; + const auto tailSoundVolume = CAEAudioEnvironment::GetDistanceAttenuation(CAEAudioEnvironment::GetPositionRelativeToCamera(entity).Magnitude() / tailSoundRollOff) + baseVolume - 20.f; + const auto tailSoundAudioEvent = audioEvent == AE_WEAPON_FIRE_MINIGUN_AMMO + ? AE_FRONTEND_PICKUP_MONEY + : AE_FRONTEND_SELECT; + const auto PlayTailSound = [&](bool isRight, float speedMult) { + PlaySound( + tailSfxID, + CVector{ isRight ? 1.f : -1, 0.f, 0.f }, + tailSoundVolume, + tailSoundRollOff, + tailFrequencyScalingFactor * speedMult, + SOUND_FORCED_FRONT | SOUND_ROLLED_OFF | SOUND_REQUEST_UPDATES | SOUND_FRONT_END, + tailSoundAudioEvent + ); + }; + float speedMultA = 1.f, + speedMultB = 1.1892101f; + if (CAEAudioUtility::ResolveProbability(0.5f)) { + std::swap(speedMultA, speedMultB); + } + PlayTailSound(false, speedMultA); + PlayTailSound(true, speedMultB); + } } // 0x503B20 void CAEWeaponAudioEntity::ReportStealthKill(eWeaponType type, CPhysical* entity, eAudioEvents event) { - if (type != WEAPON_KNIFE) + if (type != WEAPON_KNIFE) { return; + } - const auto vol = GetDefaultVolume(event); - const auto flags = static_cast(SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES); + const auto PlayStealthKillSound = [&](int16 bankSlotID, tSoundID soundID, float volumeOffsetdB, int32 eventID) { + AESoundManager.PlaySound({ + .BankSlotID = bankSlotID, + .SoundID = soundID, + .AudioEntity = this, + .Pos = entity->GetPosition(), + .Volume = GetDefaultVolume(event) - volumeOffsetdB, + .Speed = 0.0f, // ??? + .Flags = SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES, + .RegisterWithEntity = entity, + .EventID = eventID, + .ClientVariable = (float)CTimer::GetTimeInMS(), + }); + }; if (!AEAudioHardware.IsSoundBankLoaded(143, 5)) { if (!AudioEngine.IsLoadingTuneActive()) { @@ -219,11 +504,7 @@ void CAEWeaponAudioEntity::ReportStealthKill(eWeaponType type, CPhysical* entity } return; } - m_tempSound.Initialise(5, 81, this, entity->GetPosition(), vol - 6.0f, 1.0f, 0.0f, 1.0f, 0); - m_tempSound.RegisterWithPhysicalEntity(entity); - m_tempSound.m_nEvent = AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_IN; - m_tempSound.m_ClientVariable = (float)CTimer::GetTimeInMS(); - AESoundManager.RequestNewSound(&m_tempSound); + PlayStealthKillSound(5, 81, -6.f, AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_IN); if (!AEAudioHardware.IsSoundBankLoaded(39, 2)) { if (!AudioEngine.IsLoadingTuneActive()) { @@ -231,11 +512,7 @@ void CAEWeaponAudioEntity::ReportStealthKill(eWeaponType type, CPhysical* entity } return; } - m_tempSound.Initialise(2, 47, this, entity->GetPosition(), vol, 1.0f, 0.0f, 1.0f, 0, flags); - m_tempSound.RegisterWithPhysicalEntity(entity); - m_tempSound.m_nEvent = AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_OUT; - m_tempSound.m_ClientVariable = (float)CTimer::GetTimeInMS(); - AESoundManager.RequestNewSound(&m_tempSound); + PlayStealthKillSound(2, 471, 0.f, AE_WEAPON_SOUND_CAT_STEALTH_KNIFE_OUT); } // 0x503910 @@ -310,20 +587,24 @@ void CAEWeaponAudioEntity::ReportChainsawEvent(CPhysical* entity, eAudioEvents a } // 0x504610 -void CAEWeaponAudioEntity::PlayWeaponLoopSound(CPhysical* entity, int16 sfxId, eAudioEvents startEvent, float audability, float speed, eWeaponSoundCategories soundCat) { +void CAEWeaponAudioEntity::PlayWeaponLoopSound(CPhysical* entity, int16 sfxId, eAudioEvents startEvent, float volumeOffsetdB, float speed, eWeaponSoundCategories soundCat) { if (!AEAudioHardware.IsSoundBankLoaded(143u, 5)) { if (!AudioEngine.IsLoadingTuneActive()) { AEAudioHardware.LoadSoundBank(143, 5); } return; } - - const auto volume = GetDefaultVolume(startEvent) + audability; - const auto flags = static_cast(SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_START_PERCENTAGE | SOUND_REQUEST_UPDATES); - m_tempSound.Initialise(5, sfxId, this, entity->GetPosition(), volume, 1.0f, speed, 1.0f, 0, flags); - m_tempSound.RegisterWithPhysicalEntity(entity); - m_tempSound.m_nEvent = soundCat; - AESoundManager.RequestNewSound(&m_tempSound); + AESoundManager.PlaySound({ + .BankSlotID = 5, + .SoundID = sfxId, + .AudioEntity = this, + .Pos = entity->GetPosition(), + .Volume = GetDefaultVolume(startEvent) + volumeOffsetdB, + .Speed = speed, + .Flags = SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_START_PERCENTAGE | SOUND_REQUEST_UPDATES, + .RegisterWithEntity = entity, + .EventID = soundCat, + }); } // 0x504960 @@ -352,7 +633,7 @@ void CAEWeaponAudioEntity::PlayMiniGunStopSound(CPhysical* entity) { this, entity->GetPosition(), GetDefaultVolume(AE_WEAPON_FIRE_MINIGUN_STOP), - maxDist * 2.f / 3.f, // *0.66....f + maxDist * 2.f / 3.f, // *0.66f....f speed, 1.0f, 0, @@ -396,22 +677,19 @@ void CAEWeaponAudioEntity::PlayMiniGunFireSounds(CPhysical* entity, eAudioEvents } break; } - CAESound s; - s.Initialise( - 5, - 14, - this, - entity->GetPosition(), - GetDefaultVolume(AE_WEAPON_FIRE_MINIGUN_NO_AMMO), - 2.f / 3.f, - 1.f, - 0.f, - 0, - SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES - ); - s.m_nEvent = AE_FRONTEND_NOISE_TEST; - s.RegisterWithPhysicalEntity(entity); - AESoundManager.RequestNewSound(&s); + AESoundManager.PlaySound({ + .BankSlotID = 5, + .SoundID = 14, + .AudioEntity = this, + .Pos = entity->GetPosition(), + .Volume = GetDefaultVolume(AE_WEAPON_FIRE_MINIGUN_NO_AMMO), + .RollOffFactor = 2.f / 3.f, + .Speed = 1.f, + .Doppler = 0.f, + .Flags = SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES, + .RegisterWithEntity = entity, + .EventID = AE_WEAPON_SOUND_CAT_MINIGUN_SPIN + }); m_IsMiniGunSpinActive = true; } m_MiniGunState = eMiniGunState::SPINNING; @@ -421,166 +699,6 @@ void CAEWeaponAudioEntity::PlayMiniGunFireSounds(CPhysical* entity, eAudioEvents m_LastMiniGunFireTimeMs = CTimer::GetTimeInMS(); } -// 0x503CE0 -void CAEWeaponAudioEntity::PlayGunSounds( - CPhysical* entity, - int16 dryFireSfxID, - int16 subSfxID, - int16 mainLeftSfxID, - int16 mainRightSfxID, - int16 tailSfxID, - eAudioEvents audioEvent, - float volumeOffsetdB, - float primarySpeed, - float tailFrequencyScalingFactor -) { - if (!AEAudioHardware.IsSoundBankLoaded(143u, 5)) { - if (!AudioEngine.IsLoadingTuneActive()) { - AEAudioHardware.LoadSoundBank(143, 5); - } - return; - } - - if (CTimer::GetTimeInMS() < m_LastGunFireTimeMs + 25) { - return; - } - m_LastGunFireTimeMs = CTimer::GetTimeInMS(); - - auto baseVolume = GetDefaultVolume(audioEvent) + volumeOffsetdB; - auto [baseRollOffFactor, baseSpeed] = [&]() -> std::pair { - switch (audioEvent) { - case AE_WEAPON_FIRE_PLANE: { - m_LastWeaponPlaneFrequencyIndex = (m_LastWeaponPlaneFrequencyIndex + 1) % 2; - return {1.6f, gfWeaponPlaneFrequencyVariations[m_LastWeaponPlaneFrequencyIndex] * primarySpeed * 0.7937f}; - } - case AE_WEAPON_FIRE_MINIGUN_PLANE: { - return {1.8f, primarySpeed * 0.7937f}; - } - default: { - return {1.f, primarySpeed}; - } - } - }(); - - const auto PlaySound = [&](int16 sfxID, CVector pos, float volume, float rollOffFactor, float speed, uint32 flags, eAudioEvents audioEventOverride = AE_UNDEFINED) { - CAESound s; - s.Initialise( - 5, - sfxID, - this, - pos, - volume, - rollOffFactor, - speed, - 0.f, - 0, - flags - ); - if (flags & SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY) { - s.RegisterWithPhysicalEntity(entity); - } - if (audioEventOverride == AE_UNDEFINED) { - switch (audioEvent) { - case AE_WEAPON_FIRE_MINIGUN_PLANE: - case AE_WEAPON_FIRE_MINIGUN_AMMO: - s.m_nEvent = AE_FRONTEND_PICKUP_WEAPON; - } - } else { - s.m_nEvent = audioEventOverride; - } - AESoundManager.RequestNewSound(&s); - }; - - if (dryFireSfxID != -1) { // 0x503DFF - PlaySound( - dryFireSfxID, - entity->GetPosition(), - baseVolume, - baseRollOffFactor * (2.f / 3.f), - baseSpeed, - SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES - ); - } - if (subSfxID != -1) { // 0x503E93 - PlaySound( - subSfxID, - entity->GetPosition(), - baseVolume, - baseRollOffFactor * 0.9f, - baseSpeed, - SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES - ); - } - - // 0x503F21 - float frontEndVolume = -100.f; - if (!notsa::contains({ AE_WEAPON_FIRE_PLANE, AE_WEAPON_FIRE_MINIGUN_PLANE }, audioEvent)) { - const auto dist = CAEAudioEnvironment::GetPositionRelativeToCamera(entity).Magnitude() / (baseRollOffFactor * 1.25f); - if (dist < (5.f / baseRollOffFactor)) { // Inverted - baseVolume -= 3.f; - frontEndVolume = baseVolume + CAEAudioEnvironment::GetDistanceAttenuation(dist); - } else if (dist < (12.f / baseRollOffFactor)) { - const auto t = ((12.f / baseRollOffFactor) - dist) / (12.f / baseRollOffFactor) - (5.f / baseRollOffFactor); - frontEndVolume = baseVolume + CAEAudioEnvironment::GetDistanceAttenuation(dist) + std::log10f(t * (SQRT_2 / 2.f)) * 20.f; - baseVolume += std::log10f(((1.f - t) * 0.2929f) + (SQRT_2 / 2.f)) * 20.f; - } - } - - const auto PlayMainSound = [ - &, - mainSoundSpeed = (CAEAudioUtility::GetRandomNumberInRange(-0.02f, 0.02f) + 1.f) * baseSpeed - ](int16 sfxID, bool isRight) { - PlaySound( - sfxID, - CVector{isRight ? 1.f : -1.f, 0.f, 0.f}, - frontEndVolume, - baseRollOffFactor * 1.25f, - mainSoundSpeed, - SOUND_FORCED_FRONT | SOUND_REQUEST_UPDATES | SOUND_FRONT_END - ); - PlaySound( - sfxID, - entity->GetPosition(), - baseVolume, - baseRollOffFactor * 1.25f, - mainSoundSpeed, - SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES - ); - }; - if (mainLeftSfxID != -1) { // 0x5040DC + 0x5041DF - PlayMainSound(mainLeftSfxID, false); - } - if (mainRightSfxID != -1) { // 0x504153 + 0x504218 - PlayMainSound(mainRightSfxID, true); - } - - if (tailSfxID != -1 && !notsa::contains({AE_WEAPON_FIRE_PLANE, AE_WEAPON_FIRE_MINIGUN_PLANE}, audioEvent)) { - const auto tailSoundRollOff = baseRollOffFactor * 3.5f; - const auto tailSoundVolume = CAEAudioEnvironment::GetDistanceAttenuation(CAEAudioEnvironment::GetPositionRelativeToCamera(entity).Magnitude() / tailSoundRollOff) + baseVolume - 20.f; - const auto tailSoundAudioEvent = audioEvent == AE_WEAPON_FIRE_MINIGUN_AMMO - ? AE_FRONTEND_PICKUP_MONEY - : AE_FRONTEND_SELECT; - const auto PlayTailSound = [&](bool isRight, float speedMult) { - PlaySound( - tailSfxID, - CVector{ isRight ? 1.f : -1, 0.f, 0.f }, - tailSoundVolume, - tailSoundRollOff, - tailFrequencyScalingFactor * speedMult, - SOUND_FORCED_FRONT | SOUND_ROLLED_OFF | SOUND_REQUEST_UPDATES | SOUND_FRONT_END, - tailSoundAudioEvent - ); - }; - float speedMultA = 1.f, - speedMultB = 1.1892101f; - if (CAEAudioUtility::ResolveProbability(0.5f)) { - std::swap(speedMultA, speedMultB); - } - PlayTailSound(false, speedMultA); - PlayTailSound(true, speedMultB); - } -} - // 0x503500 void CAEWeaponAudioEntity::PlayGoggleSound(int16 sfxId, eAudioEvents event) { if (!AEAudioHardware.IsSoundBankLoaded(143u, 5)) { @@ -655,14 +773,19 @@ void CAEWeaponAudioEntity::PlayFlameThrowerSounds(CPhysical* entity, int16 dryFi // 0x503870 void CAEWeaponAudioEntity::PlayFlameThrowerIdleGasLoop(CPhysical* entity) { - if (m_FlameThrowerIdleGasLoopSound != nullptr) + if (m_FlameThrowerIdleGasLoopSound != nullptr) { return; - - const auto volume = GetDefaultVolume(AE_FLAMETHROWER_IDLE); - const auto flags = static_cast(SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES); - m_tempSound.Initialise(5, 10, this, entity->GetPosition(), volume, 0.66f, 1.0f, 1.0f, 0, flags); - m_tempSound.RegisterWithPhysicalEntity(entity); - m_FlameThrowerIdleGasLoopSound = AESoundManager.RequestNewSound(&m_tempSound); + } + m_FlameThrowerIdleGasLoopSound = AESoundManager.PlaySound({ + .BankSlotID = 5, + .SoundID = 10, + .AudioEntity = this, + .Pos = entity->GetPosition(), + .Volume = GetDefaultVolume(AE_FLAMETHROWER_IDLE), + .RollOffFactor = 2.f / 3.f, + .Flags = SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES, + .RegisterWithEntity = entity + }); } // 0x5034E0 @@ -676,21 +799,17 @@ void CAEWeaponAudioEntity::StopFlameThrowerIdleGasLoop() { void CAEWeaponAudioEntity::PlayChainsawStopSound(CPhysical* entity) { if (entity && AEAudioHardware.IsSoundBankLoaded(36, 40)) { if (m_ChainsawState != eChainsawState::STOPPING) { - m_tempSound.Initialise( - 40, - 2, - this, - entity->GetPosition(), - GetDefaultVolume(AE_WEAPON_CHAINSAW_ACTIVE), - 2.f / 3.f, - 1.0f, - 1.0f, - 0, - SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES - ); - m_tempSound.RegisterWithPhysicalEntity(entity); - m_tempSound.m_nEvent = AE_WEAPON_SOUND_CAT_CHAINSAW_STOP; - AESoundManager.RequestNewSound(&m_tempSound); + AESoundManager.PlaySound({ + .BankSlotID = 40, + .SoundID = 2, + .AudioEntity = this, + .Pos = entity->GetPosition(), + .Volume = GetDefaultVolume(AE_WEAPON_CHAINSAW_ACTIVE), + .RollOffFactor = 2.f / 3.f, + .Flags = SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_REQUEST_UPDATES, + .RegisterWithEntity = entity, + .EventID = AE_WEAPON_SOUND_CAT_CHAINSAW_STOP + }); } m_ChainsawState = eChainsawState::STOPPING; } else { @@ -706,12 +825,17 @@ void CAEWeaponAudioEntity::PlayCameraSound(CPhysical* entity, eAudioEvents event } return; } - - const auto vol = GetDefaultVolume(event) + audability; - const auto flags = static_cast(SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_UNPAUSABLE); - m_tempSound.Initialise(5, 45, this, entity->GetPosition(), vol, 0.66f, 1.0f, 1.0f, 0, flags); - m_tempSound.RegisterWithPhysicalEntity(entity); - AESoundManager.RequestNewSound(&m_tempSound); + AESoundManager.PlaySound({ + .BankSlotID = 5, + .SoundID = 45, + .AudioEntity = this, + .Pos = entity->GetPosition(), + .Volume = GetDefaultVolume(event), + .RollOffFactor = 2.f / 3.f, + .Flags = SOUND_LIFESPAN_TIED_TO_PHYSICAL_ENTITY | SOUND_UNPAUSABLE, // NOTE/BUG: `UNPAUSABLE` typo? + .RegisterWithEntity = entity, + .EventID = AE_WEAPON_SOUND_CAT_CHAINSAW_STOP + }); } // 0x504B70 @@ -821,6 +945,7 @@ void CAEWeaponAudioEntity::UpdateParameters(CAESound* sound, int16 curPlayPos) { sound->StopSoundAndForget(); break; } + break; } case AE_WEAPON_SOUND_CAT_CHAINSAW_STOP: // 0x504E66 if (m_ChainsawState == eChainsawState::STOPPING && curPlayPos > 1'000) { @@ -845,6 +970,10 @@ void CAEWeaponAudioEntity::UpdateParameters(CAESound* sound, int16 curPlayPos) { } } +void CAEWeaponAudioEntity::Clear() { + *this = CAEWeaponAudioEntity{}; +} + CAEWeaponAudioEntity* CAEWeaponAudioEntity::Constructor() { CAEWeaponAudioEntity::CAEWeaponAudioEntity(); return this; diff --git a/source/game_sa/Audio/entities/AEWeaponAudioEntity.h b/source/game_sa/Audio/entities/AEWeaponAudioEntity.h index 4ad76af801..5b0c1c09e7 100644 --- a/source/game_sa/Audio/entities/AEWeaponAudioEntity.h +++ b/source/game_sa/Audio/entities/AEWeaponAudioEntity.h @@ -8,6 +8,7 @@ #include "AEAudioEntity.h" #include "AESound.h" +#include