Merge pull request #61 from SHADE-DP/SP3-129-AudioSystem

Added AudioSystem

added audio system with banks
change the Dependencies to clone fmod
change premake to include fmode
space to play sound
Currently audiosystem is commented out due to causing the raccoon to not be rendered
This commit is contained in:
XiaoQiDigipen 2022-09-28 18:36:13 +08:00 committed by GitHub
commit fa6175256f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 900 additions and 10 deletions

BIN
Assets/Audio/Master.bank Normal file

Binary file not shown.

Binary file not shown.

BIN
Assets/Audio/footsteps.bank Normal file

Binary file not shown.

View File

@ -15,3 +15,4 @@ IncludeDir["SDL"] = "%{wks.location}\\Dependencies\\SDL"
IncludeDir["VULKAN"] = "$(VULKAN_SDK)" IncludeDir["VULKAN"] = "$(VULKAN_SDK)"
IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet" IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet"
IncludeDir["tinyddsloader"] = "%{wks.location}\\Dependencies\\tinyddsloader" IncludeDir["tinyddsloader"] = "%{wks.location}\\Dependencies\\tinyddsloader"
IncludeDir["fmod"] = "%{wks.location}\\Dependencies\\fmod"

View File

@ -34,8 +34,9 @@ project "SHADE_Application"
"%{IncludeDir.VULKAN}/include", "%{IncludeDir.VULKAN}/include",
"%{IncludeDir.VMA}/include", "%{IncludeDir.VMA}/include",
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect", "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
"%{IncludeDir.RTTR}/include", "%{IncludeDir.tinyddsloader}",
"%{IncludeDir.tinyddsloader}" "%{IncludeDir.fmod}/include",
"%{IncludeDir.RTTR}\\include"
} }
externalwarnings "Off" externalwarnings "Off"

View File

@ -25,6 +25,7 @@
#include "Math/Transform/SHTransformSystem.h" #include "Math/Transform/SHTransformSystem.h"
#include "Input/SHInputManagerSystem.h" #include "Input/SHInputManagerSystem.h"
#include "FRC/SHFramerateController.h" #include "FRC/SHFramerateController.h"
//#include "AudioSystem/SHAudioSystem.h"
#include "Scenes/SBTestScene.h" #include "Scenes/SBTestScene.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
@ -56,6 +57,7 @@ namespace Sandbox
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>()); SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
SHADE::SHSystemManager::CreateSystem<SHADE::SHInputManagerSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHInputManagerSystem>();
//SHADE::SHSystemManager::CreateSystem<SHADE::SHAudioSystem>();
// Create Routines // Create Routines
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>();
@ -84,6 +86,8 @@ namespace Sandbox
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds"); SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
//TODO: REMOVE AFTER PRESENTATION //TODO: REMOVE AFTER PRESENTATION
//SHADE::SHSystemManager::RegisterRoutine<SHADE::SHAudioSystem, SHADE::SHAudioSystem::AudioRoutine>();
// Set up graphics system and windows // Set up graphics system and windows
graphicsSystem->SetWindow(&window); graphicsSystem->SetWindow(&window);

View File

@ -42,7 +42,8 @@ project "SHADE_Engine"
"%{IncludeDir.VULKAN}\\include", "%{IncludeDir.VULKAN}\\include",
"%{IncludeDir.VULKAN}\\Source\\SPIRV-Reflect", "%{IncludeDir.VULKAN}\\Source\\SPIRV-Reflect",
"%{IncludeDir.dotnet}\\include", "%{IncludeDir.dotnet}\\include",
"%{IncludeDir.tinyddsloader}" "%{IncludeDir.tinyddsloader}",
"%{IncludeDir.fmod}\\include"
} }
externalwarnings "Off" externalwarnings "Off"
@ -55,7 +56,8 @@ project "SHADE_Engine"
"%{IncludeDir.assimp}/lib/Release", "%{IncludeDir.assimp}/lib/Release",
"%{IncludeDir.RTTR}/lib", "%{IncludeDir.RTTR}/lib",
"%{IncludeDir.SDL}/lib", "%{IncludeDir.SDL}/lib",
"%{IncludeDir.spdlog}/lib" "%{IncludeDir.spdlog}/lib",
"%{IncludeDir.fmod}/lib",
} }
links links
@ -122,7 +124,7 @@ project "SHADE_Engine"
symbols "On" symbols "On"
defines {"_DEBUG", "SHEDITOR"} defines {"_DEBUG", "SHEDITOR"}
links{"assimp-vc142-mtd.lib", "librttr_core_d.lib", "spdlogd.lib"} 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" filter "configurations:Release"
optimize "On" optimize "On"
@ -140,4 +142,4 @@ project "SHADE_Engine"
"%{prj.location}/src/Editor/**.h", "%{prj.location}/src/Editor/**.h",
"%{prj.location}/src/Editor/**.hpp", "%{prj.location}/src/Editor/**.hpp",
} }
--links{"fmodstudio_vc.lib", "fmod_vc.lib"} links{"fmodstudio_vc.lib", "fmod_vc.lib"}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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<SHAudioSystem>()->PlaySFX(id, GetEID(),loop,spatial, min, max);
}
void SHAudioSourceComponent::PlaySoundBGM(EntityID id, bool loop, bool spatial, float min, float max)
{
SHSystemManager::GetSystem<SHAudioSystem>()->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<SHAudioSystem>()->StopSound(id);
}
/**
* @brief Mute the sound
*
* @param index where the sound is in the index
*/
void SHAudioSourceComponent::SetMute(EntityID id, bool mute)
{
SHSystemManager::GetSystem<SHAudioSystem>()->SetMute(id, mute);
}
}

View File

@ -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

View File

@ -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 <iostream>
#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 <FMOD/fmod_errors.h>
#include <FMOD/fmod.hpp>
#include <FMOD/fmod_studio.hpp>
#include <SDL_keyboard.h>
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::SHAudioSourceComponent>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHAudioListenerComponent>();
denseListener = &SHComponentManager::GetDense<SHAudioListenerComponent>();
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<void>(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<SHTransformComponent>(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<SHAudioSystem*>(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<SHTransformComponent>(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<SHTransformComponent>(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<SHTransformComponent>(eid))
{
SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(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<SHTransformComponent>(eid))
{
SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(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<FMOD_GUID> 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<const char*> SHAudioSystem::GetAllEvents()
//{
// int count{};
// stringsBank->getEventCount(&count);
// std::vector<FMOD::Studio::EventDescription*> events(count);
// auto eventData = events.data();
// int finalCount{};
// stringsBank->getEventList(eventData, count, &finalCount);
// std::vector<const char*> 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<SHTransformComponent>(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<SHTransformComponent>(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<FMOD::Studio::EventInstance*> 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<SHTransformComponent>(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<FMOD::Studio::EventDescription*> 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<SHADE::SHAudioSystem>();
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<SHADE::SHAudioSystem>();
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)

View File

@ -0,0 +1,110 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <set>
#include <unordered_map>
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "ECS_Base/SHECSMacros.h"
#include "Math/SHMath.h"
#include <optional>
#include <FMOD/fmod_studio.hpp>
#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<SHSound>::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<FMOD_GUID> GetEventGUID(const char* path);
AudioClip* CreateAudioClip(const char* path);
//std::vector<const char*> 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<EntityID, SHSound> soundList;
//std::unordered_map<ResourceID, SHBank> bankMap;
std::unordered_map<std::string, SHBank> bankMap;
std::unordered_map<std::string, FMOD::Studio::EventDescription*> eventMap;
std::unordered_map<AudioClipID, AudioClip> 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<SHAudioListenerComponent>* denseListener;
AudioClipID clipID = 0;
};
}

View File

@ -13,6 +13,9 @@
#include "SHEditorComponentView.hpp" #include "SHEditorComponentView.hpp"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "AudioSystem/SHAudioSystem.h"
namespace SHADE namespace SHADE
{ {
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true> template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>