diff --git a/Assets/Audio/Master.bank b/Assets/Audio/Master.bank new file mode 100644 index 00000000..a1b4e563 Binary files /dev/null and b/Assets/Audio/Master.bank differ diff --git a/Assets/Audio/Master.strings.bank b/Assets/Audio/Master.strings.bank new file mode 100644 index 00000000..ecad89fe Binary files /dev/null and b/Assets/Audio/Master.strings.bank differ diff --git a/Assets/Audio/footsteps.bank b/Assets/Audio/footsteps.bank new file mode 100644 index 00000000..ce53111e Binary files /dev/null and b/Assets/Audio/footsteps.bank differ diff --git a/Dependencies.lua b/Dependencies.lua index 9ae406f0..6dd7a711 100644 --- a/Dependencies.lua +++ b/Dependencies.lua @@ -15,3 +15,4 @@ IncludeDir["SDL"] = "%{wks.location}\\Dependencies\\SDL" IncludeDir["VULKAN"] = "$(VULKAN_SDK)" IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet" IncludeDir["tinyddsloader"] = "%{wks.location}\\Dependencies\\tinyddsloader" +IncludeDir["fmod"] = "%{wks.location}\\Dependencies\\fmod" \ No newline at end of file diff --git a/SHADE_Application/premake5.lua b/SHADE_Application/premake5.lua index b34b06fa..2119808d 100644 --- a/SHADE_Application/premake5.lua +++ b/SHADE_Application/premake5.lua @@ -30,12 +30,13 @@ project "SHADE_Application" externalincludedirs { - "%{IncludeDir.spdlog}/include", - "%{IncludeDir.VULKAN}/include", - "%{IncludeDir.VMA}/include", - "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect", - "%{IncludeDir.RTTR}/include", - "%{IncludeDir.tinyddsloader}" + "%{IncludeDir.spdlog}/include", + "%{IncludeDir.VULKAN}/include", + "%{IncludeDir.VMA}/include", + "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect", + "%{IncludeDir.tinyddsloader}", + "%{IncludeDir.fmod}/include", + "%{IncludeDir.RTTR}\\include" } externalwarnings "Off" @@ -81,4 +82,4 @@ project "SHADE_Application" filter "configurations:Publish" optimize "On" - defines{"_RELEASE"} + defines{"_RELEASE", "_PUBLISH"} diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 20aa3b5a..28b38940 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -24,6 +24,8 @@ #include "Scene/SHSceneManager.h" #include "Math/Transform/SHTransformSystem.h" #include "Input/SHInputManagerSystem.h" +#include "FRC/SHFramerateController.h" +//#include "AudioSystem/SHAudioSystem.h" #include "Scenes/SBTestScene.h" #include "Math/Transform/SHTransformComponent.h" @@ -55,6 +57,7 @@ namespace Sandbox SHADE::SHSystemManager::CreateSystem(); SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); SHADE::SHSystemManager::CreateSystem(); + //SHADE::SHSystemManager::CreateSystem(); // Create Routines SHADE::SHSystemManager::RegisterRoutine(); @@ -83,6 +86,8 @@ namespace Sandbox SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds"); //TODO: REMOVE AFTER PRESENTATION + //SHADE::SHSystemManager::RegisterRoutine(); + // Set up graphics system and windows graphicsSystem->SetWindow(&window); @@ -95,6 +100,7 @@ namespace Sandbox #endif SHSceneManager::InitSceneManager("TestScene"); + SHFrameRateController::UpdateFRC(); } void SBApplication::Update(void) @@ -103,6 +109,7 @@ namespace Sandbox //TODO: Change true to window is open while (!window.WindowShouldClose()) { + SHFrameRateController::UpdateFRC(); SHSceneManager::UpdateSceneManager(); SHSceneManager::SceneUpdate(1/60.0f); //#ifdef SHEDITOR diff --git a/SHADE_Engine/premake5.lua b/SHADE_Engine/premake5.lua index 7de741b7..289dfd30 100644 --- a/SHADE_Engine/premake5.lua +++ b/SHADE_Engine/premake5.lua @@ -42,7 +42,8 @@ project "SHADE_Engine" "%{IncludeDir.VULKAN}\\include", "%{IncludeDir.VULKAN}\\Source\\SPIRV-Reflect", "%{IncludeDir.dotnet}\\include", - "%{IncludeDir.tinyddsloader}" + "%{IncludeDir.tinyddsloader}", + "%{IncludeDir.fmod}\\include" } externalwarnings "Off" @@ -55,7 +56,8 @@ project "SHADE_Engine" "%{IncludeDir.assimp}/lib/Release", "%{IncludeDir.RTTR}/lib", "%{IncludeDir.SDL}/lib", - "%{IncludeDir.spdlog}/lib" + "%{IncludeDir.spdlog}/lib", + "%{IncludeDir.fmod}/lib", } links @@ -113,13 +115,16 @@ project "SHADE_Engine" filter "configurations:Release" postbuildcommands {"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""} + filter "configurations:Publish" + postbuildcommands {"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""} + warnings 'Extra' filter "configurations:Debug" symbols "On" defines {"_DEBUG", "SHEDITOR"} links{"assimp-vc142-mtd.lib", "librttr_core_d.lib", "spdlogd.lib"} - --links{"fmodstudioL_vc.lib", "fmodL_vc.lib"} + links{"fmodstudioL_vc.lib", "fmodL_vc.lib"} filter "configurations:Release" optimize "On" @@ -129,7 +134,7 @@ project "SHADE_Engine" filter "configurations:Publish" optimize "On" - defines{"_RELEASE"} + defines{"_RELEASE", "_PUBLISH"} links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"} excludes { @@ -137,4 +142,4 @@ project "SHADE_Engine" "%{prj.location}/src/Editor/**.h", "%{prj.location}/src/Editor/**.hpp", } - --links{"fmodstudio_vc.lib", "fmod_vc.lib"} \ No newline at end of file + links{"fmodstudio_vc.lib", "fmod_vc.lib"} \ No newline at end of file diff --git a/SHADE_Engine/src/AudioSystem/SHAudioListenerComponent.cpp b/SHADE_Engine/src/AudioSystem/SHAudioListenerComponent.cpp new file mode 100644 index 00000000..988b2781 --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioListenerComponent.cpp @@ -0,0 +1,58 @@ +/********************************************************************* +* \file SHAudioListenerComponent.cpp +* \author Glence Low +* \brief Definition of the SHAudioListenerComponent class. +* +* \copyright Copyright (c) 2021 DigiPen Institute of Technology. Reproduction + or disclosure of this file or its contents without the prior written + consent of DigiPen Institute of Technology is prohibited. +*********************************************************************/ + +#include "SHpch.h" +#include "SHAudioListenerComponent.h" +#include "ECS_Base/Managers/SHSystemManager.h" + +namespace SHADE +{ + const SHVec3 SHAudioListenerComponent::GetPos() const + { + return pos; + } + + const SHVec3 SHAudioListenerComponent::GetVel() const + { + return vel; + } + + const SHVec3 SHAudioListenerComponent::GetForward() const + { + return forward; + } + + const SHVec3 SHAudioListenerComponent::GetUp() const + { + return up; + } + + void SHAudioListenerComponent::SetPos(const SHVec3 p) + { + pos = p; + } + + void SHAudioListenerComponent::SetVel(const SHVec3 v) + { + vel = v; + } + + void SHAudioListenerComponent::SetForward(const SHVec3 f) + { + forward = f; + } + + void SHAudioListenerComponent::SetUp(const SHVec3 u) + { + up = u; + } + +} + diff --git a/SHADE_Engine/src/AudioSystem/SHAudioListenerComponent.h b/SHADE_Engine/src/AudioSystem/SHAudioListenerComponent.h new file mode 100644 index 00000000..e0fa8104 --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioListenerComponent.h @@ -0,0 +1,41 @@ +#pragma once +/********************************************************************* + * \file SHAudioListenerComponent.h + * \author Glence Low + * \brief Declaration of the SHAudioListenerComponent class. + * + * \copyright Copyright (c) 2021 DigiPen Institute of Technology. Reproduction + or disclosure of this file or its contents without the prior written + consent of DigiPen Institute of Technology is prohibited. +*********************************************************************/ + +#pragma once +#include "ECS_Base/Components/SHComponent.h" +#include "Math/SHMath.h" + +namespace SHADE +{ + class SHAudioListenerComponent : public SHComponent + { + friend class SHAudioSystem; + public: + + SHAudioListenerComponent() = default; + ~SHAudioListenerComponent() = default; + + const SHVec3 GetPos() const; + void SetPos(const SHVec3 p); + + const SHVec3 GetVel() const; + const SHVec3 GetForward() const; + const SHVec3 GetUp() const; + + void SetVel(const SHVec3 v); + void SetForward(const SHVec3 f); + void SetUp(const SHVec3 u); + + private: + SHVec3 pos{}, vel{}, forward{}, up{ 0.f,1.f,0.f }; + }; +}//namespace SHADE + diff --git a/SHADE_Engine/src/AudioSystem/SHAudioSourceComponent.cpp b/SHADE_Engine/src/AudioSystem/SHAudioSourceComponent.cpp new file mode 100644 index 00000000..2d623ede --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioSourceComponent.cpp @@ -0,0 +1,53 @@ +/********************************************************************* +* \file SHAudioSourceComponet.cpp +* \author Glence Low +* \brief Definition of the SHAudioSourceComponet class. +* +* \copyright Copyright (c) 2021 DigiPen Institute of Technology. Reproduction + or disclosure of this file or its contents without the prior written + consent of DigiPen Institute of Technology is prohibited. +*********************************************************************/ + +#include "SHpch.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "AudioSystem/SHAudioSystem.h" +#include "SHAudioSourceComponent.h" + +namespace SHADE +{ + /** + * @brief play the sound + * + * @param index where the sound is in the index + */ + void SHAudioSourceComponent::PlaySoundSFX(EntityID id, bool loop, bool spatial, float min , float max ) + { + SHSystemManager::GetSystem()->PlaySFX(id, GetEID(),loop,spatial, min, max); + } + + void SHAudioSourceComponent::PlaySoundBGM(EntityID id, bool loop, bool spatial, float min, float max) + { + SHSystemManager::GetSystem()->PlayBGM(id, GetEID(), loop, spatial, min, max); + } + + /** + * @brief Stop the sound + * + * @param index where the sound is in the index + */ + void SHAudioSourceComponent::StopSound(EntityID id) + { + SHSystemManager::GetSystem()->StopSound(id); + } + + /** + * @brief Mute the sound + * + * @param index where the sound is in the index + */ + void SHAudioSourceComponent::SetMute(EntityID id, bool mute) + { + SHSystemManager::GetSystem()->SetMute(id, mute); + } +} + diff --git a/SHADE_Engine/src/AudioSystem/SHAudioSourceComponent.h b/SHADE_Engine/src/AudioSystem/SHAudioSourceComponent.h new file mode 100644 index 00000000..987dc3d4 --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioSourceComponent.h @@ -0,0 +1,60 @@ +/********************************************************************* + * \file SHAudioSourceComponet.h + * \author Glence Low + * \brief Declaration of the SHAudioSourceComponet class. + * + * \copyright Copyright (c) 2021 DigiPen Institute of Technology. Reproduction + or disclosure of this file or its contents without the prior written + consent of DigiPen Institute of Technology is prohibited. +*********************************************************************/ + +#pragma once +#include "ECS_Base/Components/SHComponent.h" +#include "ECS_Base/SHECSMacros.h" + +namespace SHADE +{ + class SHAudioSourceComponent : public SHComponent + { + public: + /** + * @brief default constructor for the component + * + */ + SHAudioSourceComponent() = default; + + + /** + * @brief default destructor for the component + * + */ + ~SHAudioSourceComponent() = default; + + /** + * @brief play the sound + * + * @param index where the sound is in the index + */ + void PlaySoundSFX(EntityID id, bool loop = false, bool spatial = false, float min = 5.0f, float max = 1000.f); + + void PlaySoundBGM(EntityID id, bool loop = false, bool spatial = false, float min = 5.0f, float max = 1000.f); + + /** + * @brief Stop the sound + * + * @param index where the sound is in the index + */ + void StopSound(EntityID id); + + /** + * @brief Mute the sound + * + * @param index where the sound is in the index + */ + void SetMute(EntityID id, bool mute); + + private: + + }; +}//namespace SHADE + diff --git a/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp b/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp new file mode 100644 index 00000000..be9ee832 --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp @@ -0,0 +1,557 @@ +#include "SHpch.h" +#include "SHAudioSystem.h" +#include "Scene/SHSceneManager.h" +#include "ECS_Base/Managers/SHComponentManager.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" + +#include + +#include "AudioSystem/SHAudioListenerComponent.h" +#include "AudioSystem/SHAudioSourceComponent.h" +#include "Math/Transform/SHTransformComponent.h" +#pragma warning(push) +#pragma warning(disable:26812) //disable warning about preference of enum class over enum as ImGuizmo uses enums +#include +#include +#include +#include + +namespace SHADE +{ + SHAudioSystem::SHAudioSystem() + : fmodStudioSystem(nullptr) + , extraDriverData(nullptr) + , soundList() + , bgmChannelGroup(nullptr) + , sfxChannelGroup(nullptr) + , masterGroup(nullptr) + , audioChannels() + , result(FMOD_RESULT_FORCEINT) + , bgmVolume(1.F) + , sfxVolume(1.F) + , masterVolume(1.0F) + , version(0) + , speakerMode(FMOD_SPEAKERMODE_5POINT1) + , paused(false) + { + result = FMOD::Studio::System::create(&fmodStudioSystem); + ErrorCheck(); + } + + SHAudioSystem::~SHAudioSystem() + { + } + + void SHADE::SHAudioSystem::Init() + { + + SHADE::SHComponentManager::CreateComponentSparseSet(); + SHADE::SHComponentManager::CreateComponentSparseSet(); + + denseListener = &SHComponentManager::GetDense(); + fmodStudioSystem->getCoreSystem(&fmodSystem); + + result = fmodStudioSystem->initialize(AUDIO_SYS_MAX_CHANNELS, AUDIO_SYS_MAX_CHANNELS, FMOD_STUDIO_INIT_NORMAL, extraDriverData); + ErrorCheck(); + + fmodSystem->setSoftwareFormat(0, speakerMode, 0); + + result = fmodSystem->createChannelGroup("SFX", &sfxChannelGroup); + ErrorCheck(); + + result = fmodSystem->createChannelGroup("BGM", &bgmChannelGroup); + ErrorCheck(); + + result = fmodSystem->getMasterChannelGroup(&masterGroup); + ErrorCheck(); + + result = masterGroup->addGroup(bgmChannelGroup); + ErrorCheck(); + + result = masterGroup->addGroup(sfxChannelGroup); + ErrorCheck(); + + bgmChannelGroup->setVolume(bgmVolume); + sfxChannelGroup->setVolume(sfxVolume); + masterGroup->setVolume(masterVolume); + + //SHResourceManager::LoadAllAudio(system, soundList); + + + LoadBank("../../Assets/Audio/Master.bank"); + LoadBank("../../Assets/Audio/Master.strings.bank"); + //LoadBank("../../Assets/Audio/Music.bank"); + LoadBank("../../Assets/Audio/footsteps.bank"); + + //auto clip = CreateAudioClip("event:/Characters/sfx_footsteps_human"); + //clip->Play(); + //PlayEventOnce("event:/Characters/sfx_footsteps_raccoon"); + //PlayEventOnce("event:/SFX/Dawn/Dawn_Attack"); + } + + void SHADE::SHAudioSystem::Run(float dt) + { + static_cast(dt); + if (GetKeyState(VK_SPACE) & 0x8000) + PlayEventOnce("event:/Characters/sfx_footsteps_raccoon"); + + fmodStudioSystem->update(); + if (!denseListener->empty()) + { + SHAudioListenerComponent& listener = denseListener->at(0); + SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s(listener.GetEID()); + if (listenerTransform) + { + listener.SetPos(listenerTransform->GetLocalPosition()); + listener.SetForward({ (listenerTransform->GetLocalScale()[0] > 0.f) ? 1.f : -1.f, 0.f, 0.f }); + FMOD_VECTOR pos = { listener.pos[0] ,listener.pos[1] ,0.f }; + FMOD_VECTOR forward = { listener.forward[0] ,listener.forward[1] ,listener.forward[2] }; + FMOD_VECTOR up = { listener.up[0] ,listener.up[1] ,listener.up[2] }; + fmodSystem->set3DListenerAttributes(0, &pos, nullptr, &forward, &up); + } + } + } + + SHAudioSystem::AudioRoutine::AudioRoutine() + : SHSystemRoutine("Audio Routine", false) {} + + void SHAudioSystem::AudioRoutine::Execute(double dt) noexcept + { + reinterpret_cast(system)->Run(dt); + } + + void SHADE::SHAudioSystem::Exit() + { + for (auto& event : eventMap) + { + result = event.second->releaseAllInstances(); + ErrorCheck(); + } + + for (auto& bank : bankMap) + { + result = bank.second->unload(); + ErrorCheck(); + } + + for (auto& sound : soundList) + { + result = sound.second->release(); + ErrorCheck(); + } + + if (bgmChannelGroup) + { + result = bgmChannelGroup->release(); + ErrorCheck(); + } + + if (sfxChannelGroup) + { + result = sfxChannelGroup->release(); + ErrorCheck(); + } + + if (fmodStudioSystem) + { + result = fmodStudioSystem->release(); + ErrorCheck(); + } + } + + void SHAudioSystem::ErrorCheck() const + { + if (result != FMOD_OK) + std::cerr << "Audio system error: " << FMOD_ErrorString(result) << std::endl; + } + + void SHAudioSystem::PlayEventOnce(const char* path, bool isSFX, EntityID eid, bool spatial) + { + if (paused) + return; + auto it = eventMap.find(path); + if (it != eventMap.end()) + { + FMOD::Studio::EventInstance* event = nullptr; + it->second->createInstance(&event); + if (event) + { + + event->setVolume(masterVolume * (isSFX ? sfxVolume : bgmVolume)); + if (spatial) + { + if (SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s(eid)) + { + FMOD_3D_ATTRIBUTES attributes{ {} }; + attributes.forward.z = 1.0f; + attributes.up.y = 1.0f; + SHAudioListenerComponent& listener = denseListener->at(0); + SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s(listener.GetEID()); + if (listenerTransform) + { + attributes.position.z = listenerTransform->GetLocalPosition()[2]; + } + attributes.position.x = audioTransform->GetLocalPosition()[0]; + attributes.position.y = audioTransform->GetLocalPosition()[1]; + event->set3DAttributes(&attributes); + } + } + event->start(); + event->release(); + } + } + } + + void SHAudioSystem::PlaySFX(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min, float max) + { + SHSound sound = soundList[id]; + int index = GetAvailableChannelIndex(); + if (index >= 0) + { + unsigned int mode{}; + mode |= (loop ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); + mode |= (spatial ? FMOD_3D : FMOD_2D); + sound->setMode(mode); + result = fmodSystem->playSound(sound, sfxChannelGroup, false, &audioChannels[index]); + if (spatial && SHComponentManager::HasComponent(eid)) + { + SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s(eid); + FMOD_VECTOR fpos{ audioTransform->GetLocalPosition()[0],audioTransform->GetLocalPosition()[1] ,0.f}; + audioChannels[index]->set3DAttributes(&fpos, nullptr); + audioChannels[index]->setMode(mode); + audioChannels[index]->set3DMinMaxDistance(min, max); + } + ErrorCheck(); + } + } + + void SHAudioSystem::PlayBGM(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min, float max) + { + SHSound sound = soundList[id]; + int index = GetAvailableChannelIndex(); + if (index >= 0) + { + unsigned int mode{}; + mode |= (loop ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); + mode |= (spatial ? FMOD_3D : FMOD_2D); + sound->setMode(mode); + result = fmodSystem->playSound(sound, bgmChannelGroup, false, &audioChannels[index]); + if (spatial && SHComponentManager::HasComponent(eid)) + { + SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s(eid); + FMOD_VECTOR fpos{ audioTransform->GetLocalPosition()[0],audioTransform->GetLocalPosition()[1] ,0.f }; + audioChannels[index]->set3DAttributes(&fpos, nullptr); + audioChannels[index]->setMode(mode); + audioChannels[index]->set3DMinMaxDistance(min, max); + } + ErrorCheck(); + } + } + + void SHAudioSystem::SetMute(EntityID id, bool mute) + { + SHSound sound; + for (auto& channel : audioChannels) + { + channel->getCurrentSound(&sound); + if (soundList.find(id)->second == sound) // tbc + { + channel->setMute(mute); + } + } + } + + void SHAudioSystem::StopSound(EntityID id) + { + SHSound sound; + for (auto& channel : audioChannels) + { + channel->getCurrentSound(&sound); + if (soundList.find(id)->second == sound) // tbc + { + channel->stop(); + } + } + } + + void SHAudioSystem::StopAllSounds() + { + for (auto& channel : audioChannels) + { + bool isPlaying{ false }; + if (channel->isPlaying(&isPlaying) == FMOD_OK && isPlaying) + channel->stop(); + } + } + + std::optional SHAudioSystem::GetEventGUID(const char* path) + { + FMOD_GUID guid; + FMOD::Studio::EventDescription* event; + result = fmodStudioSystem->getEvent(path, &event); + ErrorCheck(); + if (result == FMOD_OK) + { + result = event->getID(&guid); + ErrorCheck(); + if (result == FMOD_OK) + { + return guid; + } + } + return std::nullopt; + } + + AudioClip* SHAudioSystem::CreateAudioClip(const char* path) + { + AudioClipID newID{}; + AudioClip* clip = nullptr; + auto it = eventMap.find(path); + if (it != eventMap.end()) + { + FMOD::Studio::EventInstance* event = nullptr; + it->second->createInstance(&event); + if (event) + { + //event->start(); + newID = clipID; + clipID++; + eventInstances.emplace(newID, AudioClip(newID, event)); + clip = &eventInstances[newID]; + } + } + return clip; + } + + //std::vector SHAudioSystem::GetAllEvents() + //{ + // int count{}; + // stringsBank->getEventCount(&count); + + // std::vector events(count); + // auto eventData = events.data(); + // int finalCount{}; + // stringsBank->getEventList(eventData, count, &finalCount); + // std::vector eventNames; + // std::transform(events.begin(), events.end(), std::back_inserter(eventNames), [](FMOD::Studio::EventDescription* event) + // { + // char path[256]; + // event->getPath(path, 256, nullptr); + // return path; + // }); + // return eventNames; + //} + + //void SHAudioSystem::PlayEventInstance(FMOD::Studio::EventInstance* instance, bool isSFX, EntityID eid, bool spatial) + //{ + // instance->setVolume(masterVolume * (isSFX ? sfxVolume : bgmVolume)); + // FMOD::ChannelGroup* channelGroup; + // if (spatial) + // { + // if (SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s(eid)) + // { + // FMOD_3D_ATTRIBUTES attributes{ {} }; + // attributes.forward.z = 1.0f; + // attributes.up.y = 1.0f; + // SHAudioListenerComponent& listener = denseListener->at(0); + // SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s(listener.GetEID()); + // if (listenerTransform) + // { + // attributes.position.z = listenerTransform->GetTranslation()[2]; + // } + // attributes.position.x = audioTransform->GetTranslation()[0]; + // attributes.position.y = audioTransform->GetTranslation()[1]; + // instance->set3DAttributes(&attributes); + // } + // } + // instance->start(); + //} + + int SHAudioSystem::GetAvailableChannelIndex() + { + bool isPlaying = false; + for (int i = 0; i < AUDIO_SYS_MAX_CHANNELS; ++i) + { + audioChannels[i]->isPlaying(&isPlaying); + if (!isPlaying) + return i; + } + return -1; + } + + float SHAudioSystem::GetBgmVolume() + { + return bgmVolume; + } + float SHAudioSystem::GetSfxVolume() + { + return sfxVolume; + } + float SHAudioSystem::GetMasterVolume() + { + return masterVolume; + } + void SHAudioSystem::SetBgmVolume(float const bgmvol) + { + bgmChannelGroup->setVolume(bgmvol); + } + void SHAudioSystem::SetSfxVolume(float const sfxvol) + { + sfxChannelGroup->setVolume(sfxvol); + } + void SHAudioSystem::SetMasterVolume(float const mastervol) + { + masterGroup->setVolume(mastervol); + } + + void SHAudioSystem::SetPaused(bool pause) + { + paused = pause; + for (auto const& channel : audioChannels) + { + channel->setPaused(paused); + } + for (auto const& event : eventMap) + { + int instanceCount = 0; + event.second->getInstanceCount(&instanceCount); + std::vector instances(instanceCount); + event.second->getInstanceList(instances.data(), instances.size(), &instanceCount); + for (auto const& instance : instances) + { + instance->setPaused(pause); + } + } + } + + bool SHAudioSystem::GetPaused() const + { + return paused; + } + + SHVec3 SHAudioSystem::GetListenerPosition() + { + auto &listener = denseListener->at(0); + SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s(listener.GetEID()); + if (listenerTransform) + { + return listenerTransform->GetLocalPosition(); + } + return {}; + } + + void SHAudioSystem::LoadBank(const char* path) + { + FMOD::Studio::Bank* bank = nullptr; + result = fmodStudioSystem->loadBankFile(path, FMOD_STUDIO_LOAD_BANK_NORMAL, &bank); + ErrorCheck(); + if (result != FMOD_OK) + return; + bankMap.emplace(path, bank); + bank->loadSampleData(); + int numOfEvents; + bank->getEventCount(&numOfEvents); + if (numOfEvents > 0) + { + std::vector events(numOfEvents); + bank->getEventList(events.data(), numOfEvents, &numOfEvents); + char eventName[512]; + for (int i{}; i < numOfEvents; ++i) + { + FMOD::Studio::EventDescription* event = events[i]; + event->getPath(eventName, 512, nullptr); + eventMap.emplace(eventName, event); + } + } + } + + AudioClip::AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst) + :instance(inst), id(clipID) + { + } + + AudioClip::~AudioClip() + { + } + + void AudioClip::Play(bool isSfx) + { + if (!instance) + return; + instance->start(); + auto audioSystem = SHSystemManager::GetSystem(); + instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume())); + } + + void AudioClip::Play(SHVec3 position, bool isSfx) + { + if (!instance) + return; + instance->start(); + FMOD_3D_ATTRIBUTES attributes{ {} }; + attributes.forward.z = 1.0f; + attributes.up.y = 1.0f; + + auto audioSystem = SHSystemManager::GetSystem(); + SHVec3 listenerPos = audioSystem->GetListenerPosition(); + attributes.position.x = position[0]; + attributes.position.y = position[1]; + attributes.position.z = listenerPos[2]; + instance->set3DAttributes(&attributes); + instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume())); + } + + void AudioClip::Stop(bool fadeOut) + { + if (!instance) + return; + instance->stop(fadeOut ? FMOD_STUDIO_STOP_ALLOWFADEOUT : FMOD_STUDIO_STOP_IMMEDIATE); + } + + void AudioClip::SetPause(bool pause) + { + if (!instance) + return; + instance->setPaused(pause); + } + + bool AudioClip::IsPaused() + { + if (!instance) + return true; + + bool paused{}; + instance->getPaused(&paused); + return paused; + } + + + void AudioClip::SetParameter(const char* paramName, float value) + { + if (!instance) + return; + instance->setParameterByName(paramName, value); + } + + void AudioClip::SetParameterLabel(const char* paramName, const char* label) + { + if (!instance) + return; + instance->setParameterByNameWithLabel(paramName, label); + } + + float AudioClip::GetParameterValue(const char* paramName) + { + if (!instance) + return {}; + float value{}; + instance->getParameterByName(paramName, &value); + return value; + } + +} + +#pragma warning(pop) + + diff --git a/SHADE_Engine/src/AudioSystem/SHAudioSystem.h b/SHADE_Engine/src/AudioSystem/SHAudioSystem.h new file mode 100644 index 00000000..04fad1f0 --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioSystem.h @@ -0,0 +1,110 @@ +#pragma once +#include +#include +#include +#include +#include +#include "ECS_Base/System/SHSystem.h" +#include "ECS_Base/System/SHSystemRoutine.h" +#include "ECS_Base/SHECSMacros.h" +#include "Math/SHMath.h" +#include +#include +#include "SH_API.h" +#define AUDIO_SYS_MAX_CHANNELS 1024 + +namespace SHADE +{ + typedef FMOD::Sound* SHSound; + typedef FMOD::Studio::Bank* SHBank; + + class SHAudioListenerComponent; + + typedef uint64_t AudioClipID; + + class AudioClip + { + public: + AudioClip() = default; + AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst); + ~AudioClip(); + void Play(bool isSfx = true); + void Play(SHVec3 position, bool isSfx = true); + void Stop(bool fadeOut = true); + + void SetPause(bool pause); + bool IsPaused(); + void SetParameter(const char* paramName, float value); + void SetParameterLabel(const char* paramName, const char* label); + float GetParameterValue(const char* paramName); + friend class SHAudioSystem; + private: + FMOD::Studio::EventInstance* instance; + AudioClipID id; + }; + + class SH_API SHAudioSystem : public SHSystem + { + public: + SHAudioSystem(); + ~SHAudioSystem(); + + void Init(); + void Run(float dt); + class SH_API AudioRoutine final : public SHSystemRoutine + { + public: + AudioRoutine(); + void Execute(double dt) noexcept override final; + }; + void Exit(); + + int GetAvailableChannelIndex(); + /*std::vector::size_type CreateSound(const char* filepath, bool loop = false);*/ + void PlaySFX(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f); + void PlayBGM(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f); + void PlayEventOnce(const char* path, bool isSFX = true, EntityID eid = MAX_EID, bool spatial = false); + void SetMute(EntityID id, bool); + void StopSound(EntityID id); + void StopAllSounds(); + + std::optional GetEventGUID(const char* path); + AudioClip* CreateAudioClip(const char* path); + //std::vector GetAllEvents(); + + float GetBgmVolume(); + float GetSfxVolume(); + float GetMasterVolume(); + void SetBgmVolume(float const bgmvol); + void SetSfxVolume(float const sfxvol); + void SetMasterVolume(float const mastervol); + void SetPaused(bool pause); + bool GetPaused() const; + SHVec3 GetListenerPosition(); + void LoadBank(const char* path); + private: + FMOD::Studio::System* fmodStudioSystem; + FMOD::System* fmodSystem; + bool paused; + void ErrorCheck() const; + + void* extraDriverData; + std::unordered_map soundList; + //std::unordered_map bankMap; + std::unordered_map bankMap; + std::unordered_map eventMap; + std::unordered_map eventInstances; + FMOD::ChannelGroup* bgmChannelGroup, * sfxChannelGroup, * masterGroup; + FMOD::Channel* audioChannels[AUDIO_SYS_MAX_CHANNELS]; + FMOD_RESULT result; + float bgmVolume, sfxVolume, masterVolume; + unsigned int version; + FMOD_SPEAKERMODE speakerMode; + SHBank masterBank, stringsBank, musicBank, sfxBank; //To do: change to map of banks loaded by resource manager + + std::vector* denseListener; + AudioClipID clipID = 0; + }; + +} + diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index 0fb5b926..7ba0c609 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -14,6 +14,9 @@ #include "ECS_Base/UnitTesting/SHTestComponents.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "AudioSystem/SHAudioSystem.h" + namespace SHADE { template, bool> = true> diff --git a/SHADE_Engine/src/FRC/SHFramerateController.cpp b/SHADE_Engine/src/FRC/SHFramerateController.cpp index d64c6336..0791d628 100644 --- a/SHADE_Engine/src/FRC/SHFramerateController.cpp +++ b/SHADE_Engine/src/FRC/SHFramerateController.cpp @@ -9,12 +9,31 @@ consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ + +//TODO Legacy code. Delete soon + #include #include #include #include "SHFramerateController.h" #include "../Tools/SHLogger.h" +namespace SHADE +{ + double SHFrameRateController::rawDeltaTime = 0.0; + std::chrono::steady_clock::time_point SHFrameRateController::prevFrameTime = std::chrono::high_resolution_clock::now(); + + void SHFrameRateController::UpdateFRC() noexcept + { + std::chrono::duration deltaTime; + deltaTime = std::chrono::high_resolution_clock::now() - prevFrameTime; + prevFrameTime = std::chrono::high_resolution_clock::now(); + rawDeltaTime = deltaTime.count(); + } +} + +//TODO Legacy code. Delete soon +#if 0 namespace SHADE { //Init statics @@ -131,4 +150,5 @@ namespace SHADE currentScene = nextScene; } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/SHADE_Engine/src/FRC/SHFramerateController.h b/SHADE_Engine/src/FRC/SHFramerateController.h index 26f276d8..b9637cf2 100644 --- a/SHADE_Engine/src/FRC/SHFramerateController.h +++ b/SHADE_Engine/src/FRC/SHFramerateController.h @@ -13,6 +13,38 @@ #define SH_FRAMERATECONTROLLER_H #pragma once +#include +#include "Tools/SHLogger.h" +#include "SH_API.h" + +namespace SHADE +{ + class SH_API SHFrameRateController + { + private: + //Varying delta time. The actual time it took for every frame + static double rawDeltaTime; + static std::chrono::steady_clock::time_point prevFrameTime; + + + public: + //Gets the raw delta time + static inline double GetRawDeltaTime() noexcept + { + return rawDeltaTime; + } + + //Updates the raw delta time accordingly + static void UpdateFRC() noexcept; + + }; + +} + + + +//TODO Legacy code. Delete soon +#if 0 #include "../Scene/SHScene.h" namespace SHADE @@ -56,7 +88,19 @@ namespace SHADE //halt execution of the current scene and prepare //execution of the next static inline void SetNextScene(SHScene* const next) { nextScene = next; } + + + }; + + + } +#endif + + + + + #endif \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Vector/SHVec2.cpp b/SHADE_Engine/src/Math/Vector/SHVec2.cpp index 2d2eafd2..545492cb 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec2.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec2.cpp @@ -165,7 +165,7 @@ namespace SHADE return XMVector2NotEqual(V1, V2); } - float SHVec2::operator[](int index) + float& SHVec2::operator[](int index) { if (index >= SIZE || index < 0) throw std::invalid_argument("Index out of range!"); @@ -174,11 +174,10 @@ namespace SHADE { case 0: return x; case 1: return y; - default: return 0.0f; } } - float SHVec2::operator[](size_t index) + float& SHVec2::operator[](size_t index) { if (index >= SIZE) throw std::invalid_argument("Index out of range!"); @@ -187,7 +186,6 @@ namespace SHADE { case 0: return x; case 1: return y; - default: return 0.0f; } } @@ -200,7 +198,6 @@ namespace SHADE { case 0: return x; case 1: return y; - default: return 0.0f; } } @@ -213,7 +210,6 @@ namespace SHADE { case 0: return x; case 1: return y; - default: return 0.0f; } } diff --git a/SHADE_Engine/src/Math/Vector/SHVec2.h b/SHADE_Engine/src/Math/Vector/SHVec2.h index 3e6287aa..17642126 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec2.h +++ b/SHADE_Engine/src/Math/Vector/SHVec2.h @@ -81,8 +81,8 @@ namespace SHADE [[nodiscard]] bool operator== (const SHVec2& rhs) const noexcept; [[nodiscard]] bool operator!= (const SHVec2& rhs) const noexcept; - [[nodiscard]] float operator[] (int index); - [[nodiscard]] float operator[] (size_t index); + [[nodiscard]] float& operator[] (int index); + [[nodiscard]] float& operator[] (size_t index); [[nodiscard]] float operator[] (int index) const; [[nodiscard]] float operator[] (size_t index) const; diff --git a/SHADE_Engine/src/Math/Vector/SHVec3.cpp b/SHADE_Engine/src/Math/Vector/SHVec3.cpp index 194f7964..1bcb47b3 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec3.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec3.cpp @@ -171,7 +171,7 @@ namespace SHADE return XMVector3NotEqual(V1, V2); } - float SHVec3::operator[](int index) + float& SHVec3::operator[](int index) { if (index >= SIZE || index < 0) throw std::invalid_argument("Index out of range!"); @@ -181,11 +181,10 @@ namespace SHADE case 0: return x; case 1: return y; case 2: return z; - default: return 0.0f; } } - float SHVec3::operator[](size_t index) + float& SHVec3::operator[](size_t index) { if (index >= SIZE) throw std::invalid_argument("Index out of range!"); @@ -195,7 +194,6 @@ namespace SHADE case 0: return x; case 1: return y; case 2: return z; - default: return 0.0f; } } @@ -209,7 +207,6 @@ namespace SHADE case 0: return x; case 1: return y; case 2: return z; - default: return 0.0f; } } @@ -223,7 +220,6 @@ namespace SHADE case 0: return x; case 1: return y; case 2: return z; - default: return 0.0f; } } diff --git a/SHADE_Engine/src/Math/Vector/SHVec3.h b/SHADE_Engine/src/Math/Vector/SHVec3.h index 476d7b0f..cc0e043e 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec3.h +++ b/SHADE_Engine/src/Math/Vector/SHVec3.h @@ -86,8 +86,8 @@ namespace SHADE [[nodiscard]] bool operator== (const SHVec3& rhs) const noexcept; [[nodiscard]] bool operator!= (const SHVec3& rhs) const noexcept; - [[nodiscard]] float operator[] (int index); - [[nodiscard]] float operator[] (size_t index); + [[nodiscard]] float& operator[] (int index); + [[nodiscard]] float& operator[] (size_t index); [[nodiscard]] float operator[] (int index) const; [[nodiscard]] float operator[] (size_t index) const; diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.cpp b/SHADE_Engine/src/Math/Vector/SHVec4.cpp index 5d75af33..d1c87865 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec4.cpp @@ -161,7 +161,7 @@ namespace SHADE return XMVector4NotEqual(V1, V2); } - float SHVec4::operator[](int index) + float& SHVec4::operator[](int index) { if (index >= SIZE || index < 0) throw std::invalid_argument("Index out of range!"); @@ -172,11 +172,10 @@ namespace SHADE case 1: return y; case 2: return z; case 3: return w; - default: return 0.0f; } } - float SHVec4::operator[](size_t index) + float& SHVec4::operator[](size_t index) { if (index >= SIZE) throw std::invalid_argument("Index out of range!"); @@ -187,7 +186,6 @@ namespace SHADE case 1: return y; case 2: return z; case 3: return w; - default: return 0.0f; } } @@ -202,7 +200,6 @@ namespace SHADE case 1: return y; case 2: return z; case 3: return w; - default: return 0.0f; } } @@ -217,7 +214,6 @@ namespace SHADE case 1: return y; case 2: return z; case 3: return w; - default: return 0.0f; } } diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.h b/SHADE_Engine/src/Math/Vector/SHVec4.h index a4a5208a..59038065 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.h +++ b/SHADE_Engine/src/Math/Vector/SHVec4.h @@ -80,8 +80,8 @@ namespace SHADE [[nodiscard]] bool operator== (const SHVec4& rhs) const noexcept; [[nodiscard]] bool operator!= (const SHVec4& rhs) const noexcept; - [[nodiscard]] float operator[] (int index); - [[nodiscard]] float operator[] (size_t index); + [[nodiscard]] float& operator[] (int index); + [[nodiscard]] float& operator[] (size_t index); [[nodiscard]] float operator[] (int index) const; [[nodiscard]] float operator[] (size_t index) const; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 39afbb31..3f3ebf92 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -99,7 +99,7 @@ namespace SHADE using EntityNodeMap = std::unordered_map; - using UnaryPredicate = void (*)(SHSceneNode*); + using UnaryPredicate = std::function; /*---------------------------------------------------------------------------------*/