diff --git a/Dependencies.lua b/Dependencies.lua index 824b512d..8e8df730 100644 --- a/Dependencies.lua +++ b/Dependencies.lua @@ -14,3 +14,4 @@ IncludeDir["reactphysics3d"] = "%{wks.location}\\Dependencies\\reactphysics3d" IncludeDir["SDL"] = "%{wks.location}\\Dependencies\\SDL" IncludeDir["VULKAN"] = "$(VULKAN_SDK)" IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet" +IncludeDir["fmod"] = "%{wks.location}\\Dependencies\\fmod" \ No newline at end of file diff --git a/SHADE_Engine/premake5.lua b/SHADE_Engine/premake5.lua index 84acd8fa..00415139 100644 --- a/SHADE_Engine/premake5.lua +++ b/SHADE_Engine/premake5.lua @@ -41,6 +41,7 @@ project "SHADE_Engine" "%{IncludeDir.VULKAN}\\include", "%{IncludeDir.VULKAN}\\Source\\SPIRV-Reflect", "%{IncludeDir.dotnet}\\include", + "%{IncludeDir.fmod}\\include", } externalwarnings "Off" @@ -53,7 +54,8 @@ project "SHADE_Engine" "%{IncludeDir.assimp}/lib/Release", "%{IncludeDir.RTTR}/lib", "%{IncludeDir.SDL}/lib", - "%{IncludeDir.spdlog}/lib" + "%{IncludeDir.spdlog}/lib", + "%{IncludeDir.fmod}/lib", } links @@ -111,10 +113,10 @@ project "SHADE_Engine" symbols "On" defines {"_DEBUG"} 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" defines{"_RELEASE"} links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"} - --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..c496ff07 --- /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/System/SHSystemManager.h" + +namespace SHADE +{ + const SHMathVec3f SHAudioListenerComponent::GetPos() const + { + return pos; + } + + const SHMathVec3f SHAudioListenerComponent::GetVel() const + { + return vel; + } + + const SHMathVec3f SHAudioListenerComponent::GetForward() const + { + return forward; + } + + const SHMathVec3f SHAudioListenerComponent::GetUp() const + { + return up; + } + + void SHAudioListenerComponent::SetPos(SHMathVec3f p) + { + pos = p; + } + + void SHAudioListenerComponent::SetVel(SHMathVec3f v) + { + vel = v; + } + + void SHAudioListenerComponent::SetForward(SHMathVec3f f) + { + forward = f; + } + + void SHAudioListenerComponent::SetUp(SHMathVec3f 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..4b024e79 --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioListenerComponent.h @@ -0,0 +1,42 @@ +#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/SHMathVec.h" + +namespace SHADE +{ + class SHAudioListenerComponent : public SHComponent + { + friend class SHAudioSystem; + public: + + SHAudioListenerComponent() = default; + ~SHAudioListenerComponent() = default; + + const SHMathVec3f GetPos() const; + const SHMathVec3f GetVel() const; + const SHMathVec3f GetForward() const; + const SHMathVec3f GetUp() const; + + void SetPos(SHMathVec3f p); + void SetVel(SHMathVec3f v); + void SetForward(SHMathVec3f f); + void SetUp(SHMathVec3f u); + + + + private: + SHMathVec3f 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..9d216439 --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioSourceComponent.cpp @@ -0,0 +1,89 @@ +/********************************************************************* +* \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) + { + SHSystemManager::GetSystem()->PlaySFX(id, GetEID(),loop,spatial); + } + + //void SHAudioSourceComponent::PlayOneShot(const char* path, bool isSFX, bool spatial) + //{ + // auto AudioSystem = dynamic_cast(SHSystemManager::GetSystem("Audio")); + // AudioSystem->PlayEventOnce(path, isSFX, spatial ? GetEID() : MAX_EID, spatial); + //} + + //void SHAudioSourceComponent::PlayEvent(const char* path, bool isSFX, bool spatial) + //{ + // auto AudioSystem = dynamic_cast(SHSystemManager::GetSystem("Audio")); + + // auto guid = AudioSystem->GetEventGUID(path); + // if (guid.has_value()) + // { + // if (FMOD::Studio::EventInstance* instance = AudioSystem->CreateEventInstance(guid.value())) + // { + // eventInstances.push_back(instance); + // AudioSystem->PlayEventInstance(instance, isSFX, GetEID(), spatial); + // } + // } + //} + + void SHAudioSourceComponent::PlaySoundBGM(EntityID id, bool loop, bool spatial) + { + SHSystemManager::GetSystem()->PlayBGM(id, GetEID(), loop, spatial); + } + + /** + * @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); + } + + //void SHAudioSourceComponent::PlayEventInstance(size_t index, bool isSFX, bool spatial) + //{ + // if (index < eventInstances.size()) + // { + // eventInstances[index]->start(); + // dynamic_cast(SHSystemManager::GetSystem("Audio"))->PlayEventInstance(eventInstances[index], isSFX, GetEID(), spatial); + // } + //} + + //void SHAudioSourceComponent::StopEventInstance(size_t index) + //{ + // if(index < eventInstances.size()) + // eventInstances[index]->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT); + //} +} + diff --git a/SHADE_Engine/src/AudioSystem/SHAudioSourceComponent.h b/SHADE_Engine/src/AudioSystem/SHAudioSourceComponent.h new file mode 100644 index 00000000..98459b7e --- /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); + + void PlaySoundBGM(EntityID id, bool loop = false, bool spatial = false); + + /** + * @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..43301457 --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp @@ -0,0 +1,563 @@ +#include "SHpch.h" +//#include "ECS_Base/System/SHSystemManager.h" +#include "SHAudioSystem.h" +#include "Scene/SHSceneManager.h" +#include "ECS_Base/Managers/SHComponentManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" + +#include + +//#include "Components/SHAudioListenerComponent.h" +//#include "Components/SHAudioSourceComponent.h" +//#include "ECS_Base/System/SHComponentManager.h" +//#include "Resource Manager/SHResourceManager.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 "fmod_errors.h" +//#include "fmod.hpp" +//#include "fmod_studio.hpp" +#include +#include +#include +namespace SHADE +{ + SHAudioSystem::SHAudioSystem() + : system(nullptr) + , extraDriverData(nullptr) + , soundList() + , bgmChannelGroup(nullptr) + , sfxChannelGroup(nullptr) + , masterGroup(nullptr) + , audioChannels() + , result(FMOD_RESULT_FORCEINT) + , bgmVolume(0.5F) + , sfxVolume(1.F) + , masterVolume(1.0F) + , version(0) + , speakerMode(FMOD_SPEAKERMODE_5POINT1) + , paused(false) + { + result = FMOD::Studio::System::create(&system); + ErrorCheck(); + } + + SHAudioSystem::~SHAudioSystem() + { + } + + void SHADE::SHAudioSystem::Init() + { + + //SHComponentManager::CreateComponentSparseSet(); + //SHComponentManager::CreateComponentSparseSet(); + + denseListener = &SHComponentManager::GetDense(); + system->getCoreSystem(&coreSystem); + //result = coreSystem->getVersion(&version); + //ErrorCheck(); + //if (version < FMOD_VERSION) + //{ + // std::cout << "VERISION" << version << "\n"; + // std::cerr << "FMOD version mismatch." << std::endl; + //} + + result = system->initialize(AUDIO_SYS_MAX_CHANNELS, AUDIO_SYS_MAX_CHANNELS, FMOD_STUDIO_INIT_NORMAL, extraDriverData); + ErrorCheck(); + + coreSystem->setSoftwareFormat(0, speakerMode, 0); + + result = coreSystem->createChannelGroup("SFX", &sfxChannelGroup); + ErrorCheck(); + + result = coreSystem->createChannelGroup("BGM", &bgmChannelGroup); + ErrorCheck(); + + result = coreSystem->getMasterChannelGroup(&masterGroup); + ErrorCheck(); + + result = masterGroup->addGroup(bgmChannelGroup); + ErrorCheck(); + + result = masterGroup->addGroup(sfxChannelGroup); + ErrorCheck(); + + //TODO: GET VOLUME DATA FROM FILE + bgmChannelGroup->setVolume(bgmVolume); + sfxChannelGroup->setVolume(sfxVolume); + masterGroup->setVolume(masterVolume); + + SHResourceManager::LoadAllAudio(system, soundList); + + //TODO: Move to SHResourceManager (LoadAllAudio to load all .bank files and store SHBanks in bankMap) + //result = system->loadBankFile("resources/audio/banks/Master.bank", FMOD_STUDIO_LOAD_BANK_NORMAL, &masterBank); + //ErrorCheck(); + //result = system->loadBankFile("resources/audio/banks/Master.strings.bank", FMOD_STUDIO_LOAD_BANK_NORMAL, &stringsBank); + //ErrorCheck(); + //result = system->loadBankFile("resources/audio/banks/Music.bank", FMOD_STUDIO_LOAD_BANK_NORMAL, &musicBank); + //ErrorCheck(); + //result = system->loadBankFile("resources/audio/banks/SFX.bank", FMOD_STUDIO_LOAD_BANK_NORMAL, &sfxBank); + //ErrorCheck(); + //LoadBank("resources/audio/banks/Master.bank"); + //LoadBank("resources/audio/banks/Master.strings.bank"); + //LoadBank("resources/audio/banks/Music.bank"); + //LoadBank("resources/audio/banks/SFX.bank"); + //auto clip = CreateAudioClip("event:/SFX/Dawn/Dawn_Attack"); + //clip->Play(); + //PlayEventOnce("event:/SFX/Dawn/Dawn_Attack"); + } + + void SHADE::SHAudioSystem::Run(float dt) + { + static_cast(dt); + system->update(); + if (!denseListener->empty()) + { + SHAudioListenerComponent& listener = denseListener->at(0); + SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s(listener.GetEID()); + listener.SetPos(listenerTransform->GetLocalPosition()); + listener.SetForward({ (listenerTransform->GetScale()[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] }; + coreSystem->set3DListenerAttributes(0, &pos, nullptr, &forward, &up); + } + //int channels; + //system->getChannelsPlaying(&channels); + //std::cout << "ACTIVE CHANNELS: " << channels << std::endl; + } + + 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 (system) + { + result = system->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(ResourceID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f) + { + 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 = coreSystem->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(ResourceID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f) + { + 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 = coreSystem->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(ResourceID 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(ResourceID 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 = system->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 = system->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 = dynamic_cast(SHSystemManager::GetSystem("Audio")); + 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; + + SHVec3 listenerPos = dynamic_cast(SHSystemManager::GetSystem("Audio"))->GetListenerPosition(); + attributes.position.x = position[0]; + attributes.position.y = position[1]; + attributes.position.z = listenerPos[2]; + instance->set3DAttributes(&attributes); + auto audioSystem = dynamic_cast(SHSystemManager::GetSystem("Audio")); + 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..f459d57c --- /dev/null +++ b/SHADE_Engine/src/AudioSystem/SHAudioSystem.h @@ -0,0 +1,100 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "ECS_Base/System/SHSystem.h" +#include "ECS_Base/SHECSMacros.h" +#include "Math/SHMath.h" +#include +#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 SHAudioSystem : public SHSystem + { + public: + SHAudioSystem(); + ~SHAudioSystem(); + + void Init(); + void Run(float dt); + 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: + bool paused; + void ErrorCheck() const; + FMOD::Studio::System* system; + FMOD::System* coreSystem; + + 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; + }; + +} +