Added Scripting interface for AudioClips #320

Merged
srishamharan merged 7 commits from AudioScripting into main 2023-01-30 17:08:39 +08:00
7 changed files with 365 additions and 71 deletions

View File

@ -4,6 +4,7 @@ using System;
public class SoundsBoard : Script public class SoundsBoard : Script
{ {
AudioClipHandler test;
protected override void awake() protected override void awake()
{ {
/* /*
@ -31,13 +32,21 @@ event:/Homeowner/homeowner_humming
event:/Homeowner/homeowner_footsteps event:/Homeowner/homeowner_footsteps
event:/Homeowner/homeowner_detect_raccoon event:/Homeowner/homeowner_detect_raccoon
*/ */
test = Audio.CreateAudioClip("event:/Music/player_undetected");
Audio.AddAudioClipToSFXChannelGroup(test);
}
protected override void start()
{
test.Play();
} }
protected override void update() protected override void update()
{ {
if (Input.GetKeyDown(Input.KeyCode.Q)) if (Input.GetKeyDown(Input.KeyCode.Q))
Audio.PlayBGMOnce2D("event:/UI/mouse_down_element"); test.Play();
if (Input.GetKeyDown(Input.KeyCode.W)) if (Input.GetKeyDown(Input.KeyCode.W))
Audio.PlayBGMOnce2D("event:/UI/mouse_down_empty"); test.Stop(true);
if (Input.GetKeyDown(Input.KeyCode.E)) if (Input.GetKeyDown(Input.KeyCode.E))
Audio.PlayBGMOnce2D("event:/UI/mouse_enter_element"); Audio.PlayBGMOnce2D("event:/UI/mouse_enter_element");
if (Input.GetKeyDown(Input.KeyCode.R)) if (Input.GetKeyDown(Input.KeyCode.R))

View File

@ -125,14 +125,29 @@ namespace SHADE
SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID()); SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
if (listenerTransform) if (listenerTransform)
{ {
listener.SetPos(listenerTransform->GetLocalPosition()); listener.SetPos(listenerTransform->GetWorldPosition()); // TODO: Clean up listener
listener.SetForward({ (listenerTransform->GetLocalScale()[0] > 0.f) ? 1.f : -1.f, 0.f, 0.f }); listener.SetForward({ (listenerTransform->GetLocalScale()[0] > 0.f) ? 1.f : -1.f, 0.f, 0.f }); //TODO: USE CORRECT FORWARD
FMOD_VECTOR pos = { listener.pos[0] ,listener.pos[1] ,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 forward = { listener.forward[0] ,listener.forward[1] ,listener.forward[2] };
FMOD_VECTOR up = { listener.up[0] ,listener.up[1] ,listener.up[2] }; FMOD_VECTOR up = { listener.up[0] ,listener.up[1] ,listener.up[2] };
fmodSystem->set3DListenerAttributes(0, &pos, nullptr, &forward, &up); fmodSystem->set3DListenerAttributes(0, &pos, nullptr, &forward, &up);
} }
} }
auto [begin, end] = audioClipLibrary.GetDenseAccess();
for(auto it = begin; it != end; ++it)
{
if(it->instance && (it->transformRef != MAX_EID))
{
if(SHTransformComponent* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(it->transformRef))
{
FMOD_3D_ATTRIBUTES attribs{}; //TODO: Set other attribs
auto pos = transformComponent->GetWorldPosition();
attribs.position = {pos.x, pos.y, pos.z};
it->instance->set3DAttributes(&attribs);
}
}
}
} }
SHAudioSystem::AudioRoutine::AudioRoutine() SHAudioSystem::AudioRoutine::AudioRoutine()
@ -325,27 +340,83 @@ namespace SHADE
return std::nullopt; return std::nullopt;
} }
AudioClip* SHAudioSystem::CreateAudioClip(const char* path) Handle<AudioClip> SHAudioSystem::CreateAudioClip(const char* path)
{ {
AudioClipID newID{}; Handle<AudioClip> audioClipHandle{};
AudioClip* clip = nullptr;
auto it = eventMap.find(path); if(auto it = eventMap.find(path); it != eventMap.end())
if (it != eventMap.end())
{ {
FMOD::Studio::EventInstance* event = nullptr; audioClipHandle = audioClipLibrary.Create();
it->second->createInstance(&event); it->second->createInstance(&audioClipHandle->instance);
if (event) }
return audioClipHandle;
}
void SHAudioSystem::AddAudioClipToBGMChannelGroup(Handle<AudioClip> handle)
{ {
//event->start(); if(!handle->instance)
newID = clipID; return;
clipID++; FMOD::ChannelGroup* channelGroup;
eventInstances.emplace(newID, AudioClip(newID, event)); handle->instance->getChannelGroup(&channelGroup);
clip = &eventInstances[newID];
if(!channelGroup)
{
SHLOG_ERROR("Event instance has no channel group")
return;
}
bgmChannelGroup->addGroup(channelGroup);
}
void SHAudioSystem::AddAudioClipToSFXChannelGroup(Handle<AudioClip> handle)
{
if (!handle->instance)
return;
FMOD::ChannelGroup* channelGroup;
handle->instance->getChannelGroup(&channelGroup);
if (!channelGroup)
{
SHLOG_ERROR("Event instance has no channel group")
return;
}
sfxChannelGroup->addGroup(channelGroup);
}
void SHAudioSystem::AttachAudioClipToObject(Handle<AudioClip> handle, EntityID eid)
{
if (auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
{
handle->transformRef = eid;
} }
} }
return clip;
void SHAudioSystem::DetachAudioClipFromObject(Handle<AudioClip> handle)
{
handle->transformRef = MAX_EID;
} }
//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() //std::vector<const char*> SHAudioSystem::GetAllEvents()
//{ //{
// int count{}; // int count{};
@ -489,41 +560,39 @@ namespace SHADE
} }
} }
AudioClip::AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst) void AudioClip::Play()
:instance(inst), id(clipID)
{
}
AudioClip::~AudioClip()
{
}
void AudioClip::Play(bool isSfx)
{ {
if(!instance) if(!instance)
return; return;
instance->start(); instance->start();
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
} }
void AudioClip::Play(SHVec3 position, bool isSfx) //void AudioClip::Play(bool isSfx)
{ //{
if (!instance) // if (!instance)
return; // return;
instance->start(); // instance->start();
FMOD_3D_ATTRIBUTES attributes{ {} }; // auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
attributes.forward.z = 1.0f; // instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
attributes.up.y = 1.0f; //}
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>(); //void AudioClip::Play(SHVec3 position, bool isSfx)
SHVec3 listenerPos = audioSystem->GetListenerPosition(); //{
attributes.position.x = position[0]; // if (!instance)
attributes.position.y = position[1]; // return;
attributes.position.z = listenerPos[2]; // instance->start();
instance->set3DAttributes(&attributes); // FMOD_3D_ATTRIBUTES attributes{ {} };
instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume())); // 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) void AudioClip::Stop(bool fadeOut)
{ {
@ -557,12 +626,12 @@ namespace SHADE
instance->setParameterByName(paramName, value); instance->setParameterByName(paramName, value);
} }
void AudioClip::SetParameterLabel(const char* paramName, const char* label) //void AudioClip::SetParameterLabel(const char* paramName, const char* label)
{ //{
if (!instance) // if (!instance)
return; // return;
instance->setParameterByNameWithLabel(paramName, label); // instance->setParameterByNameWithLabel(paramName, label);
} //}
float AudioClip::GetParameterValue(const char* paramName) float AudioClip::GetParameterValue(const char* paramName)
{ {

View File

@ -13,6 +13,7 @@
#include "Events/SHEvent.h" #include "Events/SHEvent.h"
#include "SH_API.h" #include "SH_API.h"
#include <Resource/SHResourceLibrary.h>
#define AUDIO_SYS_MAX_CHANNELS 1024 #define AUDIO_SYS_MAX_CHANNELS 1024
namespace SHADE namespace SHADE
@ -22,27 +23,22 @@ namespace SHADE
class SHAudioListenerComponent; class SHAudioListenerComponent;
typedef uint64_t AudioClipID; class SH_API AudioClip
class AudioClip
{ {
public: public:
AudioClip() = default; void Play();
AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst); //void Play(SHVec3 position);
~AudioClip();
void Play(bool isSfx = true);
void Play(SHVec3 position, bool isSfx = true);
void Stop(bool fadeOut = true); void Stop(bool fadeOut = true);
void SetPause(bool pause); void SetPause(bool pause);
bool IsPaused(); bool IsPaused();
void SetParameter(const char* paramName, float value); void SetParameter(const char* paramName, float value);
void SetParameterLabel(const char* paramName, const char* label); //void SetParameterLabel(const char* paramName, const char* label);
float GetParameterValue(const char* paramName); float GetParameterValue(const char* paramName);
friend class SHAudioSystem; friend class SHAudioSystem;
private: private:
FMOD::Studio::EventInstance* instance; FMOD::Studio::EventInstance* instance = nullptr;
AudioClipID id; EntityID transformRef = MAX_EID;
}; };
class SH_API SHAudioSystem : public SHSystem class SH_API SHAudioSystem : public SHSystem
@ -62,7 +58,7 @@ namespace SHADE
void Exit(); void Exit();
int GetAvailableChannelIndex(); 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 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 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 PlayEventOnce(const char* path, bool isSFX = true, EntityID eid = MAX_EID, bool spatial = false);
@ -71,9 +67,15 @@ namespace SHADE
void StopAllSounds(); void StopAllSounds();
std::optional<FMOD_GUID> GetEventGUID(const char* path); std::optional<FMOD_GUID> GetEventGUID(const char* path);
AudioClip* CreateAudioClip(const char* path); //AudioClip* CreateAudioClip(const char* path);
//std::vector<const char*> GetAllEvents(); //AUDIO CLIP
Handle<AudioClip> CreateAudioClip(const char* path);
void AddAudioClipToBGMChannelGroup(Handle<AudioClip> handle);
void AddAudioClipToSFXChannelGroup(Handle<AudioClip> handle);
void AttachAudioClipToObject(Handle<AudioClip> handle, EntityID eid);
void DetachAudioClipFromObject(Handle<AudioClip> handle);
///
float GetBgmVolume(); float GetBgmVolume();
float GetSfxVolume(); float GetSfxVolume();
float GetMasterVolume(); float GetMasterVolume();
@ -84,6 +86,7 @@ namespace SHADE
bool GetPaused() const; bool GetPaused() const;
SHVec3 GetListenerPosition(); SHVec3 GetListenerPosition();
void LoadBank(const char* path); void LoadBank(const char* path);
private: private:
FMOD::Studio::System* fmodStudioSystem; FMOD::Studio::System* fmodStudioSystem;
FMOD::System* fmodSystem; FMOD::System* fmodSystem;
@ -95,7 +98,9 @@ namespace SHADE
//std::unordered_map<ResourceID, SHBank> bankMap; //std::unordered_map<ResourceID, SHBank> bankMap;
std::unordered_map<std::string, SHBank> bankMap; std::unordered_map<std::string, SHBank> bankMap;
std::unordered_map<std::string, FMOD::Studio::EventDescription*> eventMap; std::unordered_map<std::string, FMOD::Studio::EventDescription*> eventMap;
std::unordered_map<AudioClipID, AudioClip> eventInstances; //std::unordered_map<AudioClipID, AudioClip> eventInstances;
SHResourceLibrary<AudioClip> audioClipLibrary{};
FMOD::ChannelGroup* bgmChannelGroup, * sfxChannelGroup, * masterGroup; FMOD::ChannelGroup* bgmChannelGroup, * sfxChannelGroup, * masterGroup;
FMOD::Channel* audioChannels[AUDIO_SYS_MAX_CHANNELS]; FMOD::Channel* audioChannels[AUDIO_SYS_MAX_CHANNELS];
FMOD_RESULT result; FMOD_RESULT result;
@ -105,7 +110,6 @@ namespace SHADE
SHBank masterBank, stringsBank, musicBank, sfxBank; //To do: change to map of banks loaded by resource manager SHBank masterBank, stringsBank, musicBank, sfxBank; //To do: change to map of banks loaded by resource manager
std::vector<SHAudioListenerComponent>* denseListener; std::vector<SHAudioListenerComponent>* denseListener;
AudioClipID clipID = 0;
SHEventHandle onPlay(SHEventPtr onStopEvent); SHEventHandle onPlay(SHEventPtr onStopEvent);
SHEventHandle onStop(SHEventPtr onStopEvent); SHEventHandle onStop(SHEventPtr onStopEvent);

View File

@ -98,4 +98,35 @@ namespace SHADE
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>(); auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->StopAllSounds(); audioSys->StopAllSounds();
} }
AudioClipHandler Audio::CreateAudioClip(System::String^ path)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
return AudioClipHandler(audioSys->CreateAudioClip(Convert::ToNative(path).data()));
}
void Audio::AddAudioClipToBGMChannelGroup(AudioClipHandler handle)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->AddAudioClipToBGMChannelGroup(handle.NativeObject);
}
void Audio::AddAudioClipToSFXChannelGroup(AudioClipHandler handle)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->AddAudioClipToSFXChannelGroup(handle.NativeObject);
}
void Audio::AttachAudioClipToObject(AudioClipHandler handle, EntityID eid)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->AttachAudioClipToObject(handle.NativeObject, eid);
}
void Audio::DetachAudioClipFromObject(AudioClipHandler handle)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->DetachAudioClipFromObject(handle.NativeObject);
}
} }

View File

@ -13,6 +13,7 @@ of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/ *//*************************************************************************************/
#pragma once #pragma once
#include "Engine/GameObject.hxx" #include "Engine/GameObject.hxx"
#include "Audio/AudioClip.hxx"
namespace SHADE namespace SHADE
{ {
@ -99,5 +100,13 @@ namespace SHADE
/// Stops playback of all sound effects and music. /// Stops playback of all sound effects and music.
/// </summary> /// </summary>
static void StopAllSounds(); static void StopAllSounds();
//to comment ltr
static AudioClipHandler CreateAudioClip(System::String^ path);
static void AddAudioClipToBGMChannelGroup(AudioClipHandler handle);
static void AddAudioClipToSFXChannelGroup(AudioClipHandler handle);
static void AttachAudioClipToObject(AudioClipHandler handle, EntityID eid);
static void DetachAudioClipFromObject(AudioClipHandler handle);
}; };
} }

View File

@ -0,0 +1,89 @@
/************************************************************************************//*!
\file AudioClip.cxx
\author Glence Low
\par email: glence.low\@digipen.edu
\date Jan 16, 2023
\brief Contains the implementation of the functions in managed AudioClip
Note: This file is written in C++17/CLI.
Copyright (C) 2022 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.
*//*************************************************************************************/
// Precompiled Headers
#include "SHpch.h"
// Primary Header
#include "AudioClip.hxx"
// Standard Library
#include <stdexcept>
// Project Includes
#include "Utility/Convert.hxx"
#include "Resource/SHResourceManagerInterface.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
Handle<AudioClip> AudioClipHandler::NativeObject::get()
try
{
return Handle<AudioClip>(Convert::ToNative(audioClipInstHandle));
}
catch (const BadHandleCastException&)
{
return Handle<AudioClip>();
}
GenericHandle AudioClipHandler::NativeObjectHandle::get()
{
return audioClipInstHandle;
}
AssetID AudioClipHandler::NativeAssetID::get()
{
return SHResourceManagerInterface::GetAssetID(Convert::ToNative(audioClipInstHandle)).value_or(INVALID_ASSET_ID);
}
/*---------------------------------------------------------------------------------*/
/* Constructors/Destructor */
/*---------------------------------------------------------------------------------*/
AudioClipHandler::AudioClipHandler(Handle<AudioClip> audioClip)
: audioClipInstHandle{ Handle<void>(audioClip) }
{}
/*---------------------------------------------------------------------------------*/
/* AudioClip Properties Functions */
/*---------------------------------------------------------------------------------*/
void AudioClipHandler::Play()
{
NativeObject->Play();
}
void AudioClipHandler::Stop(bool fadeOut)
{
NativeObject->Stop(fadeOut);
}
void AudioClipHandler::SetPause(bool pause)
{
NativeObject->SetPause(pause);
}
bool AudioClipHandler::IsPaused()
{
return NativeObject->IsPaused();
}
void AudioClipHandler::SetParameter(System::String^ paramName, float value)
{
NativeObject->SetParameter(Convert::ToNative(paramName).data(), value);
}
float AudioClipHandler::GetParameterValue(System::String^ paramName)
{
return NativeObject->GetParameterValue(Convert::ToNative(paramName).data());
}
}

View File

@ -0,0 +1,83 @@
/************************************************************************************//*!
\file AudioClip.hxx
\author Glence Low
\par email: glence.low\@digipen.edu
\date Jan 16, 2023
\brief Contains the definition of the managed Audio Clip class.
Note: This file is written in C++17/CLI.
Copyright (C) 2022 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
// External Dependencies
#include "Resource/SHHandle.h"
#include "AudioSystem/SHAudioSystem.h"
#include "Assets/SHAssetMacros.h"
// Project Includes
#include "Engine/GenericHandle.hxx"
namespace SHADE
{
/// <summary>
/// Managed counterpart of the AudioSystem containing Audioclip
/// that can be fed to Audioscripting for creating clips.
/// </summary>
public value struct AudioClipHandler
{
internal:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Copy of the Handle to the native object.
/// </summary>
property Handle<AudioClip> NativeObject
{
Handle<AudioClip> get();
}
/// <summary>
/// Generic handle for the native object
/// </summary>
property GenericHandle NativeObjectHandle
{
GenericHandle get();
}
/// <summary>
/// The raw asset ID of the asset.
/// </summary>
property AssetID NativeAssetID
{
AssetID get();
}
/*-----------------------------------------------------------------------------*/
/* Constructors/Destructor */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Constructor for the AudioClip
/// </summary>
/// <param name="AudioClip">Handle to the native material object.</param>
AudioClipHandler(Handle<AudioClip> audioclip);
public:
//to comment ltr
void Play();
void Stop(bool fadeOut);
void SetPause(bool pause);
bool IsPaused();
void SetParameter(System::String^ paramName, float value);
float GetParameterValue(System::String^ paramName);
protected:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
GenericHandle audioClipInstHandle;
};
}