You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2296 lines
97 KiB
C++
2296 lines
97 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
|
|
#include <ATL.h>
|
|
|
|
#if !defined(AUDIO_RELEASE)
|
|
#include <AzCore/Math/Color.h>
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
#include <AzCore/Debug/Profiler.h>
|
|
#include <AzCore/StringFunc/StringFunc.h>
|
|
|
|
#include <SoundCVars.h>
|
|
#include <AudioProxy.h>
|
|
#include <ATLAudioObject.h>
|
|
#include <IAudioSystemImplementation.h>
|
|
|
|
#include <ISystem.h>
|
|
#include <IPhysics.h>
|
|
#include <IRenderAuxGeom.h>
|
|
|
|
namespace Audio
|
|
{
|
|
extern CAudioLogger g_audioLogger;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline EAudioRequestResult ConvertToRequestResult(const EAudioRequestStatus eAudioRequestStatus)
|
|
{
|
|
EAudioRequestResult eResult;
|
|
|
|
switch (eAudioRequestStatus)
|
|
{
|
|
case eARS_SUCCESS:
|
|
{
|
|
eResult = eARR_SUCCESS;
|
|
break;
|
|
}
|
|
case eARS_FAILURE:
|
|
case eARS_FAILURE_INVALID_OBJECT_ID:
|
|
case eARS_FAILURE_INVALID_CONTROL_ID:
|
|
case eARS_FAILURE_INVALID_REQUEST:
|
|
case eARS_PARTIAL_SUCCESS:
|
|
{
|
|
eResult = eARR_FAILURE;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "Invalid AudioRequestStatus '%u'. Cannot be converted to an AudioRequestResult. ", eAudioRequestStatus);
|
|
AZ_Assert(false, "Invalid AudioRequestStatus '%u'. Cannot be converted to and AudioRequestResult.", eAudioRequestStatus);
|
|
eResult = eARR_FAILURE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CAudioTranslationLayer::CAudioTranslationLayer()
|
|
: m_pGlobalAudioObject(nullptr)
|
|
, m_nGlobalAudioObjectID(GLOBAL_AUDIO_OBJECT_ID)
|
|
, m_nTriggerInstanceIDCounter(1)
|
|
, m_nextSourceId(INVALID_AUDIO_SOURCE_ID)
|
|
, m_oAudioEventMgr()
|
|
, m_oAudioObjectMgr(m_oAudioEventMgr)
|
|
, m_oAudioListenerMgr()
|
|
, m_oFileCacheMgr(m_cPreloadRequests)
|
|
, m_oAudioEventListenerMgr()
|
|
, m_oXmlProcessor(m_cTriggers, m_cRtpcs, m_cSwitches, m_cEnvironments, m_cPreloadRequests, m_oFileCacheMgr)
|
|
, m_nFlags(eAIS_NONE)
|
|
{
|
|
gEnv->pSystem->GetISystemEventDispatcher()->RegisterListener(this);
|
|
|
|
#if !defined(AUDIO_RELEASE)
|
|
m_oAudioEventMgr.SetDebugNameStore(&m_oDebugNameStore);
|
|
m_oAudioObjectMgr.SetDebugNameStore(&m_oDebugNameStore);
|
|
m_oXmlProcessor.SetDebugNameStore(&m_oDebugNameStore);
|
|
#endif // !AUDIO_RELEASE
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CAudioTranslationLayer::~CAudioTranslationLayer()
|
|
{
|
|
// By the time ATL is being destroyed, ReleaseImplComponent should have been called already
|
|
// to release the implementation object. See CAudioSystem::Release().
|
|
|
|
gEnv->pSystem->GetISystemEventDispatcher()->RemoveListener(this);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CAudioTranslationLayer::Initialize()
|
|
{
|
|
|
|
m_lastUpdateTime = AZStd::chrono::system_clock::now();
|
|
return true;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CAudioTranslationLayer::ShutDown()
|
|
{
|
|
|
|
return true;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::ProcessRequest(CAudioRequestInternal& rRequest)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_NONE;
|
|
|
|
switch (rRequest.pData->eRequestType)
|
|
{
|
|
case eART_AUDIO_OBJECT_REQUEST:
|
|
{
|
|
eResult = ProcessAudioObjectRequest(rRequest);
|
|
break;
|
|
}
|
|
case eART_AUDIO_LISTENER_REQUEST:
|
|
{
|
|
eResult = ProcessAudioListenerRequest(rRequest);
|
|
break;
|
|
}
|
|
case eART_AUDIO_CALLBACK_MANAGER_REQUEST:
|
|
{
|
|
eResult = ProcessAudioCallbackManagerRequest(rRequest.pData);
|
|
break;
|
|
}
|
|
case eART_AUDIO_MANAGER_REQUEST:
|
|
{
|
|
eResult = ProcessAudioManagerRequest(rRequest);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "Unknown audio request type: %d", static_cast<int>(rRequest.pData->eRequestType));
|
|
break;
|
|
}
|
|
}
|
|
|
|
rRequest.eStatus = eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::Update()
|
|
{
|
|
AZ_PROFILE_FUNCTION(Audio);
|
|
|
|
auto current = AZStd::chrono::system_clock::now();
|
|
m_elapsedTime = AZStd::chrono::duration_cast<duration_ms>(current - m_lastUpdateTime);
|
|
m_lastUpdateTime = current;
|
|
float elapsedMs = m_elapsedTime.count();
|
|
|
|
UpdateSharedData();
|
|
|
|
m_oAudioEventMgr.Update(elapsedMs);
|
|
m_oAudioObjectMgr.Update(elapsedMs, m_oSharedData.m_oActiveListenerPosition);
|
|
m_oAudioListenerMgr.Update(elapsedMs);
|
|
m_oFileCacheMgr.Update();
|
|
|
|
AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::Update, elapsedMs);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
TAudioControlID CAudioTranslationLayer::GetAudioTriggerID(const char* const audioTriggerName) const
|
|
{
|
|
auto triggerId = AudioStringToID<TAudioControlID>(audioTriggerName);
|
|
auto it = m_cTriggers.find(triggerId);
|
|
if (it == m_cTriggers.end())
|
|
{
|
|
return INVALID_AUDIO_CONTROL_ID;
|
|
}
|
|
|
|
return triggerId;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
TAudioControlID CAudioTranslationLayer::GetAudioRtpcID(const char* const audioRtpcName) const
|
|
{
|
|
auto rtpcId = AudioStringToID<TAudioControlID>(audioRtpcName);
|
|
auto it = m_cRtpcs.find(rtpcId);
|
|
if (it == m_cRtpcs.end())
|
|
{
|
|
return INVALID_AUDIO_CONTROL_ID;
|
|
}
|
|
|
|
return rtpcId;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
TAudioControlID CAudioTranslationLayer::GetAudioSwitchID(const char* const audioStateName) const
|
|
{
|
|
auto switchId = AudioStringToID<TAudioControlID>(audioStateName);
|
|
auto it = m_cSwitches.find(switchId);
|
|
if (it == m_cSwitches.end())
|
|
{
|
|
return INVALID_AUDIO_CONTROL_ID;
|
|
}
|
|
|
|
return switchId;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
TAudioSwitchStateID CAudioTranslationLayer::GetAudioSwitchStateID(const TAudioControlID switchId, const char* const audioSwitchStateName) const
|
|
{
|
|
auto stateId = AudioStringToID<TAudioSwitchStateID>(audioSwitchStateName);
|
|
auto itSwitch = m_cSwitches.find(switchId);
|
|
if (itSwitch != m_cSwitches.end())
|
|
{
|
|
auto itState = itSwitch->second->cStates.find(stateId);
|
|
if (itState == itSwitch->second->cStates.end())
|
|
{
|
|
return INVALID_AUDIO_SWITCH_STATE_ID;
|
|
}
|
|
}
|
|
|
|
return stateId;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
TAudioPreloadRequestID CAudioTranslationLayer::GetAudioPreloadRequestID(const char* const audioPreloadRequestName) const
|
|
{
|
|
auto preloadRequestId = AudioStringToID<TAudioPreloadRequestID>(audioPreloadRequestName);
|
|
auto it = m_cPreloadRequests.find(preloadRequestId);
|
|
if (it == m_cPreloadRequests.end())
|
|
{
|
|
return INVALID_AUDIO_PRELOAD_REQUEST_ID;
|
|
}
|
|
|
|
return preloadRequestId;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
TAudioEnvironmentID CAudioTranslationLayer::GetAudioEnvironmentID(const char* const audioEnvironmentName) const
|
|
{
|
|
auto environmentId = AudioStringToID<TAudioEnvironmentID>(audioEnvironmentName);
|
|
auto it = m_cEnvironments.find(environmentId);
|
|
if (it == m_cEnvironments.end())
|
|
{
|
|
return INVALID_AUDIO_ENVIRONMENT_ID;
|
|
}
|
|
|
|
return environmentId;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CAudioTranslationLayer::ReserveAudioObjectID(TAudioObjectID& rAudioObjectID)
|
|
{
|
|
return m_oAudioObjectMgr.ReserveID(rAudioObjectID);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CAudioTranslationLayer::ReleaseAudioObjectID(const TAudioObjectID nAudioObjectID)
|
|
{
|
|
const bool bSuccess = m_oAudioObjectMgr.ReleaseID(nAudioObjectID);
|
|
|
|
#if !defined(AUDIO_RELEASE)
|
|
if (bSuccess)
|
|
{
|
|
m_oDebugNameStore.RemoveAudioObject(nAudioObjectID);
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CAudioTranslationLayer::ReserveAudioListenerID(TAudioObjectID& rAudioObjectID)
|
|
{
|
|
return m_oAudioListenerMgr.ReserveID(rAudioObjectID);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CAudioTranslationLayer::ReleaseAudioListenerID(const TAudioObjectID nAudioObjectID)
|
|
{
|
|
return m_oAudioListenerMgr.ReleaseID(nAudioObjectID);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CAudioTranslationLayer::SetAudioListenerOverrideID(const TAudioObjectID nAudioObjectID)
|
|
{
|
|
return m_oAudioListenerMgr.SetOverrideListenerID(nAudioObjectID);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::AddRequestListener(const SAudioEventListener& listener)
|
|
{
|
|
m_oAudioEventListenerMgr.AddRequestListener(listener);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::RemoveRequestListener(const SAudioEventListener& listener)
|
|
{
|
|
m_oAudioEventListenerMgr.RemoveRequestListener(listener);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ParseControlsData(const char* const pConfigFolderPath, const EATLDataScope eDataScope)
|
|
{
|
|
m_oXmlProcessor.ParseControlsData(pConfigFolderPath, eDataScope);
|
|
return eARS_SUCCESS;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ParsePreloadsData(const char* const pConfigFolderPath, const EATLDataScope eDataScope)
|
|
{
|
|
m_oXmlProcessor.ParsePreloadsData(pConfigFolderPath, eDataScope);
|
|
return eARS_SUCCESS;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ClearControlsData(const EATLDataScope eDataScope)
|
|
{
|
|
m_oXmlProcessor.ClearControlsData(eDataScope);
|
|
return eARS_SUCCESS;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ClearPreloadsData(const EATLDataScope eDataScope)
|
|
{
|
|
m_oXmlProcessor.ClearPreloadsData(eDataScope);
|
|
return eARS_SUCCESS;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
const AZStd::string& CAudioTranslationLayer::GetControlsImplSubPath() const
|
|
{
|
|
return m_implSubPath;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
TAudioSourceId CAudioTranslationLayer::CreateAudioSource(const SAudioInputConfig& sourceConfig)
|
|
{
|
|
AZ_Assert(sourceConfig.m_sourceId == INVALID_AUDIO_SOURCE_ID, "ATL - Request to CreateAudioSource already contains a valid source Id.\n");
|
|
|
|
TAudioSourceId sourceId = ++m_nextSourceId;
|
|
SAudioRequest request;
|
|
SAudioManagerRequestData<eAMRT_CREATE_SOURCE> requestData(sourceConfig);
|
|
requestData.m_sourceConfig.m_sourceId = sourceId;
|
|
request.nFlags = (eARF_PRIORITY_HIGH | eARF_EXECUTE_BLOCKING);
|
|
request.pData = &requestData;
|
|
|
|
AudioSystemRequestBus::Broadcast(&AudioSystemRequestBus::Events::PushRequestBlocking, request);
|
|
return sourceId;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::DestroyAudioSource(TAudioSourceId sourceId)
|
|
{
|
|
SAudioRequest request;
|
|
SAudioManagerRequestData<eAMRT_DESTROY_SOURCE> requestData(sourceId);
|
|
request.nFlags = (eARF_PRIORITY_NORMAL);
|
|
request.pData = &requestData;
|
|
|
|
AudioSystemRequestBus::Broadcast(&AudioSystemRequestBus::Events::PushRequest, request);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::NotifyListener(const CAudioRequestInternal& rRequest)
|
|
{
|
|
// This should always be the main thread!
|
|
TATLEnumFlagsType nSpecificAudioRequest = INVALID_AUDIO_ENUM_FLAG_TYPE;
|
|
TAudioControlID nAudioControlID = INVALID_AUDIO_CONTROL_ID;
|
|
TAudioEventID audioEventID = INVALID_AUDIO_EVENT_ID;
|
|
|
|
switch (rRequest.pData->eRequestType)
|
|
{
|
|
case eART_AUDIO_MANAGER_REQUEST:
|
|
{
|
|
auto const pRequestDataBase = static_cast<const SAudioManagerRequestDataInternalBase*>(rRequest.pData.get());
|
|
nSpecificAudioRequest = static_cast<TATLEnumFlagsType>(pRequestDataBase->eType);
|
|
break;
|
|
}
|
|
case eART_AUDIO_CALLBACK_MANAGER_REQUEST:
|
|
{
|
|
auto const pRequestDataBase = static_cast<const SAudioCallbackManagerRequestDataInternalBase*>(rRequest.pData.get());
|
|
nSpecificAudioRequest = static_cast<TATLEnumFlagsType>(pRequestDataBase->eType);
|
|
switch (pRequestDataBase->eType)
|
|
{
|
|
case eACMRT_REPORT_FINISHED_TRIGGER_INSTANCE:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioCallbackManagerRequestDataInternal<eACMRT_REPORT_FINISHED_TRIGGER_INSTANCE>*>(pRequestDataBase);
|
|
nAudioControlID = pRequestData->nAudioTriggerID;
|
|
break;
|
|
}
|
|
case eACMRT_REPORT_STARTED_EVENT:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioCallbackManagerRequestDataInternal<eACMRT_REPORT_STARTED_EVENT>*>(pRequestDataBase);
|
|
audioEventID = pRequestData->nEventID;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case eART_AUDIO_OBJECT_REQUEST:
|
|
{
|
|
auto const pRequestDataBase = static_cast<const SAudioObjectRequestDataInternalBase*>(rRequest.pData.get());
|
|
nSpecificAudioRequest = static_cast<TATLEnumFlagsType>(pRequestDataBase->eType);
|
|
|
|
switch (pRequestDataBase->eType)
|
|
{
|
|
case eAORT_EXECUTE_TRIGGER:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_EXECUTE_TRIGGER>*>(pRequestDataBase);
|
|
nAudioControlID = pRequestData->nTriggerID;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case eART_AUDIO_LISTENER_REQUEST:
|
|
{
|
|
auto const pRequestDataBase = static_cast<const SAudioListenerRequestDataInternalBase*>(rRequest.pData.get());
|
|
nSpecificAudioRequest = static_cast<TATLEnumFlagsType>(pRequestDataBase->eType);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ASSERT, "Unknown request type during CAudioTranslationLayer::NotifyListener!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
const SAudioRequestInfo oResult(
|
|
ConvertToRequestResult(rRequest.eStatus),
|
|
rRequest.pOwner,
|
|
rRequest.pUserData,
|
|
rRequest.pUserDataOwner,
|
|
rRequest.pData->eRequestType,
|
|
nSpecificAudioRequest,
|
|
nAudioControlID,
|
|
rRequest.nAudioObjectID,
|
|
audioEventID);
|
|
|
|
m_oAudioEventListenerMgr.NotifyListener(&oResult);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ProcessAudioManagerRequest(const CAudioRequestInternal& rRequest)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
|
|
if (rRequest.pData)
|
|
{
|
|
auto const pRequestDataBase = static_cast<const SAudioManagerRequestDataInternalBase*>(rRequest.pData.get());
|
|
|
|
switch (pRequestDataBase->eType)
|
|
{
|
|
case eAMRT_RESERVE_AUDIO_OBJECT_ID:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_RESERVE_AUDIO_OBJECT_ID>*>(rRequest.pData.get());
|
|
#if !defined(AUDIO_RELEASE)
|
|
eResult = BoolToARS(ReserveAudioObjectID(*pRequestData->pObjectID, pRequestData->sObjectName.c_str()));
|
|
#else
|
|
eResult = BoolToARS(ReserveAudioObjectID(*pRequestData->pObjectID));
|
|
#endif // !AUDIO_RELEASE
|
|
break;
|
|
}
|
|
case eAMRT_CREATE_SOURCE:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_CREATE_SOURCE>*>(rRequest.pData.get());
|
|
bool result = false;
|
|
AudioSystemImplementationRequestBus::BroadcastResult(result, &AudioSystemImplementationRequestBus::Events::CreateAudioSource, pRequestData->m_sourceConfig);
|
|
eResult = BoolToARS(result);
|
|
break;
|
|
}
|
|
case eAMRT_DESTROY_SOURCE:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_DESTROY_SOURCE>*>(rRequest.pData.get());
|
|
AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DestroyAudioSource, pRequestData->m_sourceId);
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
case eAMRT_INIT_AUDIO_IMPL:
|
|
{
|
|
eResult = InitializeImplComponent();
|
|
|
|
// Initializing the implementation failed, immediately release it...
|
|
if (eResult != eARS_SUCCESS)
|
|
{
|
|
ReleaseImplComponent();
|
|
}
|
|
break;
|
|
}
|
|
case eAMRT_RELEASE_AUDIO_IMPL:
|
|
{
|
|
ReleaseImplComponent();
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
case eAMRT_REFRESH_AUDIO_SYSTEM:
|
|
{
|
|
#if !defined(AUDIO_RELEASE)
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_REFRESH_AUDIO_SYSTEM>*>(rRequest.pData.get());
|
|
eResult = RefreshAudioSystem(pRequestData->m_controlsPath.c_str(), pRequestData->m_levelName.c_str(), pRequestData->m_levelPreloadId);
|
|
#else
|
|
eResult = eARS_FAILURE_INVALID_REQUEST;
|
|
#endif // !AUDIO_RELEASE
|
|
break;
|
|
}
|
|
case eAMRT_LOSE_FOCUS:
|
|
{
|
|
#if !defined(AUDIO_RELEASE)
|
|
if (!Audio::CVars::s_IgnoreWindowFocus && (m_nFlags & eAIS_IS_MUTED) == 0)
|
|
#endif // !AUDIO_RELEASE
|
|
{
|
|
auto it = m_cTriggers.find(ATLInternalControlIDs::LoseFocusTriggerID);
|
|
if (it != m_cTriggers.end())
|
|
{
|
|
eResult = ActivateTrigger(m_pGlobalAudioObject, it->second, 0.0f);
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL - Trigger not found for: ATLInternalControlIDs::LoseFocusTriggerID");
|
|
}
|
|
|
|
AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemLoseFocus);
|
|
}
|
|
break;
|
|
}
|
|
case eAMRT_GET_FOCUS:
|
|
{
|
|
#if !defined(AUDIO_RELEASE)
|
|
if (!Audio::CVars::s_IgnoreWindowFocus && (m_nFlags & eAIS_IS_MUTED) == 0)
|
|
#endif // !AUDIO_RELEASE
|
|
{
|
|
AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemGetFocus);
|
|
|
|
auto it = m_cTriggers.find(ATLInternalControlIDs::GetFocusTriggerID);
|
|
if (it != m_cTriggers.end())
|
|
{
|
|
eResult = ActivateTrigger(m_pGlobalAudioObject, it->second, 0.0f);
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL - Trigger not found for: ATLInternalControlIDs::GetFocusTriggerID");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case eAMRT_MUTE_ALL:
|
|
{
|
|
eResult = MuteAll();
|
|
break;
|
|
}
|
|
case eAMRT_UNMUTE_ALL:
|
|
{
|
|
eResult = UnmuteAll();
|
|
break;
|
|
}
|
|
case eAMRT_STOP_ALL_SOUNDS:
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::StopAllSounds);
|
|
break;
|
|
}
|
|
case eAMRT_PARSE_CONTROLS_DATA:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_PARSE_CONTROLS_DATA>*>(rRequest.pData.get());
|
|
eResult = ParseControlsData(pRequestData->sControlsPath.c_str(), pRequestData->eDataScope);
|
|
break;
|
|
}
|
|
case eAMRT_PARSE_PRELOADS_DATA:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_PARSE_PRELOADS_DATA>*>(rRequest.pData.get());
|
|
eResult = ParsePreloadsData(pRequestData->sControlsPath.c_str(), pRequestData->eDataScope);
|
|
break;
|
|
}
|
|
case eAMRT_CLEAR_CONTROLS_DATA:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_CLEAR_CONTROLS_DATA>*>(rRequest.pData.get());
|
|
eResult = ClearControlsData(pRequestData->eDataScope);
|
|
break;
|
|
}
|
|
case eAMRT_CLEAR_PRELOADS_DATA:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_CLEAR_PRELOADS_DATA>*>(rRequest.pData.get());
|
|
eResult = ClearPreloadsData(pRequestData->eDataScope);
|
|
break;
|
|
}
|
|
case eAMRT_PRELOAD_SINGLE_REQUEST:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_PRELOAD_SINGLE_REQUEST>*>(rRequest.pData.get());
|
|
eResult = m_oFileCacheMgr.TryLoadRequest(pRequestData->nPreloadRequest, ((rRequest.nFlags & eARF_EXECUTE_BLOCKING) != 0), pRequestData->bAutoLoadOnly);
|
|
break;
|
|
}
|
|
case eAMRT_UNLOAD_SINGLE_REQUEST:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_UNLOAD_SINGLE_REQUEST>*>(rRequest.pData.get());
|
|
eResult = m_oFileCacheMgr.TryUnloadRequest(pRequestData->nPreloadRequest);
|
|
break;
|
|
}
|
|
case eAMRT_UNLOAD_AFCM_DATA_BY_SCOPE:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_UNLOAD_AFCM_DATA_BY_SCOPE>*>(rRequest.pData.get());
|
|
eResult = m_oFileCacheMgr.UnloadDataByScope(pRequestData->eDataScope);
|
|
break;
|
|
}
|
|
case eAMRT_CHANGE_LANGUAGE:
|
|
{
|
|
SetImplLanguage();
|
|
|
|
m_oFileCacheMgr.UpdateLocalizedFileCacheEntries();
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
case eAMRT_SET_AUDIO_PANNING_MODE:
|
|
{
|
|
auto const requestData = static_cast<const SAudioManagerRequestDataInternal<eAMRT_SET_AUDIO_PANNING_MODE>*>(rRequest.pData.get());
|
|
AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::SetPanningMode, requestData->m_panningMode);
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
case eAMRT_DRAW_DEBUG_INFO:
|
|
{
|
|
#if !defined(AUDIO_RELEASE)
|
|
DrawAudioSystemDebugInfo();
|
|
eResult = eARS_SUCCESS;
|
|
#endif // !AUDIO_RELEASE
|
|
break;
|
|
}
|
|
case eAMRT_NONE:
|
|
{
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL received an unknown AudioManager request: %u", pRequestDataBase->eType);
|
|
eResult = eARS_FAILURE_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ProcessAudioCallbackManagerRequest(const SAudioRequestDataInternal* pPassedRequestData)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
|
|
if (pPassedRequestData)
|
|
{
|
|
auto const pRequestDataBase = static_cast<const SAudioCallbackManagerRequestDataInternalBase*>(pPassedRequestData);
|
|
|
|
switch (pRequestDataBase->eType)
|
|
{
|
|
case eACMRT_REPORT_STARTED_EVENT:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioCallbackManagerRequestDataInternal<eACMRT_REPORT_STARTED_EVENT>*>(pPassedRequestData);
|
|
CATLEvent* const pEvent = m_oAudioEventMgr.LookupID(pRequestData->nEventID);
|
|
|
|
if (pEvent)
|
|
{
|
|
pEvent->m_audioEventState = eAES_PLAYING_DELAYED;
|
|
|
|
if (pEvent->m_nObjectID != m_nGlobalAudioObjectID)
|
|
{
|
|
m_oAudioObjectMgr.ReportStartedEvent(pEvent);
|
|
}
|
|
else
|
|
{
|
|
m_pGlobalAudioObject->ReportStartedEvent(pEvent);
|
|
}
|
|
}
|
|
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
case eACMRT_REPORT_FINISHED_EVENT:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioCallbackManagerRequestDataInternal<eACMRT_REPORT_FINISHED_EVENT>*>(pPassedRequestData);
|
|
CATLEvent* const pEvent = m_oAudioEventMgr.LookupID(pRequestData->nEventID);
|
|
|
|
if (pEvent)
|
|
{
|
|
if (pEvent->m_nObjectID != m_nGlobalAudioObjectID)
|
|
{
|
|
m_oAudioObjectMgr.ReportFinishedEvent(pEvent, pRequestData->bSuccess);
|
|
}
|
|
else if (m_pGlobalAudioObject)
|
|
{ // safety-net check to prevent crash if a finished callback is received very late
|
|
m_pGlobalAudioObject->ReportFinishedEvent(pEvent, pRequestData->bSuccess);
|
|
}
|
|
|
|
m_oAudioEventMgr.ReleaseEvent(pEvent);
|
|
}
|
|
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
case eACMRT_REPORT_FINISHED_TRIGGER_INSTANCE:
|
|
case eACMRT_NONE:
|
|
{
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_REQUEST;
|
|
g_audioLogger.Log(eALT_WARNING, "ATL received an unknown AudioCallbackManager request: %u", pRequestDataBase->eType);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ProcessAudioObjectRequest(const CAudioRequestInternal& rRequest)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
CATLAudioObjectBase* pObject = static_cast<CATLAudioObjectBase*>(m_pGlobalAudioObject);
|
|
|
|
if (rRequest.nAudioObjectID != INVALID_AUDIO_OBJECT_ID)
|
|
{
|
|
pObject = static_cast<CATLAudioObjectBase*>(m_oAudioObjectMgr.LookupID(rRequest.nAudioObjectID));
|
|
}
|
|
|
|
if (pObject)
|
|
{
|
|
const SAudioRequestDataInternal* const pPassedRequestData = rRequest.pData;
|
|
|
|
if (pPassedRequestData)
|
|
{
|
|
auto const pBaseRequestData = static_cast<const SAudioObjectRequestDataInternalBase*>(pPassedRequestData);
|
|
|
|
switch (pBaseRequestData->eType)
|
|
{
|
|
case eAORT_PREPARE_TRIGGER:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_PREPARE_TRIGGER>*>(pPassedRequestData);
|
|
|
|
auto it = m_cTriggers.find(pRequestData->nTriggerID);
|
|
if (it != m_cTriggers.end())
|
|
{
|
|
eResult = PrepUnprepTriggerAsync(pObject, it->second, true);
|
|
}
|
|
else
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_CONTROL_ID;
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_UNPREPARE_TRIGGER:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_UNPREPARE_TRIGGER>*>(pPassedRequestData);
|
|
|
|
auto it = m_cTriggers.find(pRequestData->nTriggerID);
|
|
if (it != m_cTriggers.end())
|
|
{
|
|
eResult = PrepUnprepTriggerAsync(pObject, it->second, false);
|
|
}
|
|
else
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_CONTROL_ID;
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_EXECUTE_TRIGGER:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_EXECUTE_TRIGGER>*>(pPassedRequestData);
|
|
|
|
auto it = m_cTriggers.find(pRequestData->nTriggerID);
|
|
if (it != m_cTriggers.end())
|
|
{
|
|
eResult = ActivateTrigger(
|
|
pObject,
|
|
it->second,
|
|
pRequestData->fTimeUntilRemovalInMS,
|
|
rRequest.pOwner,
|
|
rRequest.pUserData,
|
|
rRequest.pUserDataOwner,
|
|
rRequest.nFlags);
|
|
}
|
|
else
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_CONTROL_ID;
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_STOP_TRIGGER:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_STOP_TRIGGER>*>(pPassedRequestData);
|
|
|
|
auto it = m_cTriggers.find(pRequestData->nTriggerID);
|
|
if (it != m_cTriggers.end())
|
|
{
|
|
eResult = StopTrigger(pObject, it->second);
|
|
}
|
|
else
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_CONTROL_ID;
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_STOP_ALL_TRIGGERS:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_STOP_ALL_TRIGGERS>*>(pPassedRequestData);
|
|
|
|
if (pRequestData->m_filterByOwner)
|
|
{
|
|
StopAllTriggers(pObject, rRequest.pOwner);
|
|
}
|
|
else
|
|
{
|
|
StopAllTriggers(pObject);
|
|
}
|
|
|
|
// Why not return the result of StopAllTriggers call?
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
case eAORT_SET_POSITION:
|
|
{
|
|
if (pObject->HasPosition())
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_SET_POSITION>*>(pPassedRequestData);
|
|
|
|
auto const pPositionedObject = static_cast<CATLAudioObject*>(pObject);
|
|
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::SetPosition,
|
|
pPositionedObject->GetImplDataPtr(),
|
|
pRequestData->oPosition);
|
|
|
|
if (eResult == eARS_SUCCESS)
|
|
{
|
|
pPositionedObject->SetPosition(pRequestData->oPosition);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL received a request to set a position on a global object");
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_SET_RTPC_VALUE:
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_CONTROL_ID;
|
|
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_SET_RTPC_VALUE>*>(pPassedRequestData);
|
|
|
|
auto it = m_cRtpcs.find(pRequestData->nControlID);
|
|
if (it != m_cRtpcs.end())
|
|
{
|
|
eResult = SetRtpc(pObject, it->second, pRequestData->fValue);
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_SET_SWITCH_STATE:
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_CONTROL_ID;
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_SET_SWITCH_STATE>*>(pPassedRequestData);
|
|
|
|
auto itSwitch = m_cSwitches.find(pRequestData->nSwitchID);
|
|
if (itSwitch != m_cSwitches.end())
|
|
{
|
|
auto itState = itSwitch->second->cStates.find(pRequestData->nStateID);
|
|
if (itState != itSwitch->second->cStates.end())
|
|
{
|
|
eResult = SetSwitchState(pObject, itState->second);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_SET_ENVIRONMENT_AMOUNT:
|
|
{
|
|
if (pObject->HasPosition())
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_CONTROL_ID;
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_SET_ENVIRONMENT_AMOUNT>*>(pPassedRequestData);
|
|
|
|
auto it = m_cEnvironments.find(pRequestData->nEnvironmentID);
|
|
if (it != m_cEnvironments.end())
|
|
{
|
|
eResult = SetEnvironment(pObject, it->second, pRequestData->fAmount);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL received a request to set an environment on a global object");
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_RESET_ENVIRONMENTS:
|
|
{
|
|
eResult = ResetEnvironments(pObject);
|
|
break;
|
|
}
|
|
case eAORT_RESET_RTPCS:
|
|
{
|
|
eResult = ResetRtpcs(pObject);
|
|
break;
|
|
}
|
|
case eAORT_RELEASE_OBJECT:
|
|
{
|
|
eResult = eARS_FAILURE;
|
|
|
|
const TAudioObjectID nObjectID = pObject->GetID();
|
|
|
|
if (nObjectID != m_nGlobalAudioObjectID)
|
|
{
|
|
if (ReleaseAudioObjectID(nObjectID))
|
|
{
|
|
eResult = eARS_SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL received a request to release the GlobalAudioObject");
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_EXECUTE_SOURCE_TRIGGER:
|
|
{
|
|
eResult = eARS_FAILURE;
|
|
auto const requestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_EXECUTE_SOURCE_TRIGGER>*>(pPassedRequestData);
|
|
|
|
auto it = m_cTriggers.find(requestData->m_triggerId);
|
|
if (it != m_cTriggers.end())
|
|
{
|
|
SATLSourceData sourceData(requestData->m_sourceInfo);
|
|
eResult = ActivateTrigger(
|
|
pObject,
|
|
it->second,
|
|
0.f,
|
|
rRequest.pOwner,
|
|
rRequest.pUserData,
|
|
rRequest.pUserDataOwner,
|
|
rRequest.nFlags,
|
|
&sourceData
|
|
);
|
|
}
|
|
else
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_CONTROL_ID;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case eAORT_SET_MULTI_POSITIONS:
|
|
{
|
|
if (pObject->HasPosition())
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioObjectRequestDataInternal<eAORT_SET_MULTI_POSITIONS>*>(pPassedRequestData);
|
|
|
|
auto const pPositionedObject = static_cast<CATLAudioObject*>(pObject);
|
|
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::SetMultiplePositions,
|
|
pPositionedObject->GetImplDataPtr(),
|
|
pRequestData->m_params);
|
|
|
|
if (eResult == eARS_SUCCESS)
|
|
{
|
|
pPositionedObject->SetPosition(SATLWorldPosition());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL received a request to set multiple positions on a global object");
|
|
}
|
|
break;
|
|
}
|
|
case eAORT_NONE:
|
|
{
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_REQUEST;
|
|
g_audioLogger.Log(eALT_WARNING, "ATL received an unknown AudioObject request type: %u", pBaseRequestData->eType);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL received a request to a non-existent AudioObject: %u", rRequest.nAudioObjectID);
|
|
eResult = eARS_FAILURE_INVALID_OBJECT_ID;
|
|
}
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ProcessAudioListenerRequest(const CAudioRequestInternal& rRequest)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
TAudioObjectID listenerID = INVALID_AUDIO_OBJECT_ID;
|
|
|
|
// Check for an Audio Listener Override.
|
|
TAudioObjectID overrideListenerID = m_oAudioListenerMgr.GetOverrideListenerID();
|
|
if (overrideListenerID != INVALID_AUDIO_OBJECT_ID)
|
|
{
|
|
if (rRequest.nAudioObjectID == overrideListenerID)
|
|
{
|
|
// Have an override set, and the ID in the request matches the override.
|
|
// Reroute to the default listener.
|
|
listenerID = m_oAudioListenerMgr.GetDefaultListenerID();
|
|
}
|
|
else if (rRequest.nAudioObjectID != INVALID_AUDIO_OBJECT_ID)
|
|
{
|
|
// Override is set, but the request specified a different listener ID, allow it.
|
|
listenerID = rRequest.nAudioObjectID;
|
|
}
|
|
else
|
|
{
|
|
// Override is set, but no listener ID specified. Typically this would go
|
|
// to the default listener, but with overrides we explicitly ignore this.
|
|
return eResult;
|
|
}
|
|
}
|
|
else if (rRequest.nAudioObjectID == INVALID_AUDIO_OBJECT_ID)
|
|
{
|
|
listenerID = m_oAudioListenerMgr.GetDefaultListenerID();
|
|
}
|
|
else
|
|
{
|
|
listenerID = rRequest.nAudioObjectID;
|
|
}
|
|
|
|
CATLListenerObject* const pListener = m_oAudioListenerMgr.LookupID(listenerID);
|
|
if (pListener)
|
|
{
|
|
if (rRequest.pData)
|
|
{
|
|
auto const pBaseRequestData = static_cast<const SAudioListenerRequestDataInternalBase*>(rRequest.pData.get());
|
|
|
|
switch (pBaseRequestData->eType)
|
|
{
|
|
case eALRT_SET_POSITION:
|
|
{
|
|
auto const pRequestData = static_cast<const SAudioListenerRequestDataInternal<eALRT_SET_POSITION>*>(rRequest.pData.get());
|
|
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::SetListenerPosition,
|
|
pListener->m_pImplData,
|
|
pRequestData->oNewPosition);
|
|
|
|
if (eResult == eARS_SUCCESS)
|
|
{
|
|
pListener->oPosition = pRequestData->oNewPosition;
|
|
}
|
|
break;
|
|
}
|
|
case eALRT_NONE:
|
|
{
|
|
eResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
eResult = eARS_FAILURE_INVALID_REQUEST;
|
|
g_audioLogger.Log(eALT_WARNING, "ATL received an unknown AudioListener request type: %u", pBaseRequestData->eType);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_COMMENT, "Could not find listener with ID: %u", listenerID);
|
|
}
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::InitializeImplComponent()
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::Initialize);
|
|
if (eResult == eARS_SUCCESS)
|
|
{
|
|
IATLAudioObjectData* pGlobalObjectData = nullptr;
|
|
AudioSystemImplementationRequestBus::BroadcastResult(pGlobalObjectData, &AudioSystemImplementationRequestBus::Events::NewGlobalAudioObjectData, m_nGlobalAudioObjectID);
|
|
|
|
m_pGlobalAudioObject = azcreate(CATLGlobalAudioObject, (m_nGlobalAudioObjectID, pGlobalObjectData), Audio::AudioSystemAllocator, "ATLGlobalAudioObject");
|
|
|
|
m_oAudioObjectMgr.Initialize();
|
|
m_oAudioEventMgr.Initialize();
|
|
m_oAudioListenerMgr.Initialize();
|
|
m_oXmlProcessor.Initialize();
|
|
m_oFileCacheMgr.Initialize();
|
|
|
|
SetImplLanguage();
|
|
|
|
// Update the implementation subpath for locating ATL controls...
|
|
AudioSystemImplementationRequestBus::BroadcastResult(m_implSubPath, &AudioSystemImplementationRequestBus::Events::GetImplSubPath);
|
|
}
|
|
|
|
#if !defined(AUDIO_RELEASE)
|
|
else
|
|
{
|
|
const char* implementationName = nullptr;
|
|
AudioSystemImplementationRequestBus::BroadcastResult(implementationName, &AudioSystemImplementationRequestBus::Events::GetImplementationNameString);
|
|
g_audioLogger.Log(eALT_ERROR, "Failed to Initialize the AudioSystemImplementationComponent '%s'\n", implementationName);
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::ReleaseImplComponent()
|
|
{
|
|
// During audio middleware shutdown we do not allow for any new requests originating from the "dying" audio middleware!
|
|
m_nFlags |= eAIS_AUDIO_MIDDLEWARE_SHUTTING_DOWN;
|
|
|
|
m_oXmlProcessor.ClearControlsData(eADS_ALL);
|
|
m_oXmlProcessor.ClearPreloadsData(eADS_ALL);
|
|
|
|
if (m_pGlobalAudioObject)
|
|
{
|
|
AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioObjectData, m_pGlobalAudioObject->GetImplDataPtr());
|
|
azdestroy(m_pGlobalAudioObject, Audio::AudioSystemAllocator);
|
|
m_pGlobalAudioObject = nullptr;
|
|
}
|
|
|
|
m_oAudioObjectMgr.Release();
|
|
m_oAudioListenerMgr.Release();
|
|
m_oAudioEventMgr.Release();
|
|
m_oFileCacheMgr.Release();
|
|
m_oXmlProcessor.Release();
|
|
|
|
m_implSubPath.clear();
|
|
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::ShutDown);
|
|
|
|
// If we allow developers to change the audio implementation module at run-time, these should be at Warning level.
|
|
// If we ever revoke that functionality, these should be promoted to Asserts.
|
|
AZ_Warning("ATL", eResult == eARS_SUCCESS, "ATL ReleaseImplComponent - Shutting down the audio implementation failed!");
|
|
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::Release);
|
|
AZ_Warning("ATL", eResult == eARS_SUCCESS, "ATL ReleaseImplComponent - Releasing the audio implementation failed!");
|
|
|
|
m_nFlags &= ~eAIS_AUDIO_MIDDLEWARE_SHUTTING_DOWN;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::PrepUnprepTriggerAsync(
|
|
CATLAudioObjectBase* const pAudioObject,
|
|
const CATLTrigger* const pTrigger,
|
|
const bool bPrepare)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
|
|
const TAudioObjectID nATLObjectID = pAudioObject->GetID();
|
|
const TAudioControlID nATLTriggerID = pTrigger->GetID();
|
|
const TObjectTriggerImplStates& rTriggerImplStates = pAudioObject->GetTriggerImpls();
|
|
|
|
for (auto const triggerImpl : pTrigger->m_cImplPtrs)
|
|
{
|
|
TATLEnumFlagsType nTriggerImplFlags = INVALID_AUDIO_ENUM_FLAG_TYPE;
|
|
TObjectTriggerImplStates::const_iterator iPlace = rTriggerImplStates.end();
|
|
if (FindPlaceConst(rTriggerImplStates, triggerImpl->m_nATLID, iPlace))
|
|
{
|
|
nTriggerImplFlags = iPlace->second.nFlags;
|
|
}
|
|
|
|
const EATLSubsystem eReceiver = triggerImpl->GetReceiver();
|
|
CATLEvent* pEvent = m_oAudioEventMgr.GetEvent(eReceiver);
|
|
|
|
EAudioRequestStatus ePrepUnprepResult = eARS_FAILURE;
|
|
|
|
switch (eReceiver)
|
|
{
|
|
case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
|
|
{
|
|
if (bPrepare)
|
|
{
|
|
if (((nTriggerImplFlags & eATS_PREPARED) == 0) && ((nTriggerImplFlags & eATS_LOADING) == 0))
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(ePrepUnprepResult, &AudioSystemImplementationRequestBus::Events::PrepareTriggerAsync,
|
|
pAudioObject->GetImplDataPtr(),
|
|
triggerImpl->m_pImplData,
|
|
pEvent->m_pImplData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (((nTriggerImplFlags & eATS_PREPARED) != 0) && ((nTriggerImplFlags & eATS_UNLOADING) == 0))
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(ePrepUnprepResult, &AudioSystemImplementationRequestBus::Events::UnprepareTriggerAsync,
|
|
pAudioObject->GetImplDataPtr(),
|
|
triggerImpl->m_pImplData,
|
|
pEvent->m_pImplData);
|
|
}
|
|
}
|
|
|
|
if (ePrepUnprepResult == eARS_SUCCESS)
|
|
{
|
|
pEvent->m_nObjectID = nATLObjectID;
|
|
pEvent->m_nTriggerID = triggerImpl->m_nATLID;
|
|
pEvent->m_nTriggerImplID = triggerImpl->m_nATLID;
|
|
|
|
pEvent->m_audioEventState = bPrepare ? eAES_LOADING : eAES_UNLOADING;
|
|
}
|
|
break;
|
|
}
|
|
case eAS_ATL_INTERNAL:
|
|
{
|
|
//TODO: handle this
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "Unknown ATL Recipient");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ePrepUnprepResult == eARS_SUCCESS)
|
|
{
|
|
pEvent->SetDataScope(pTrigger->GetDataScope());
|
|
pAudioObject->ReportStartedEvent(pEvent);
|
|
pAudioObject->IncrementRefCount();
|
|
eResult = eARS_SUCCESS; // if at least one event fires, it is a success
|
|
}
|
|
else
|
|
{
|
|
m_oAudioEventMgr.ReleaseEvent(pEvent);
|
|
}
|
|
}
|
|
|
|
#if !defined(AUDIO_RELEASE)
|
|
if (eResult != eARS_SUCCESS)
|
|
{
|
|
// No TriggerImpl produced an active event.
|
|
g_audioLogger.Log(eALT_WARNING, "PrepUnprepTriggerAsync failed on AudioObject \"%s\" (ID: %u)", m_oDebugNameStore.LookupAudioObjectName(nATLObjectID), nATLObjectID);
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ActivateTrigger(
|
|
CATLAudioObjectBase* const pAudioObject,
|
|
const CATLTrigger* const pTrigger,
|
|
[[maybe_unused]] const float fTimeUntilRemovalMS,
|
|
void* const pOwner /* = nullptr */,
|
|
void* const pUserData /* = nullptr */,
|
|
void* const pUserDataOwner /* = nullptr */,
|
|
const TATLEnumFlagsType nFlags /* = INVALID_AUDIO_ENUM_FLAG_TYPE */,
|
|
const SATLSourceData* pSourceData /* = nullptr */)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
|
|
if (pAudioObject->HasPosition())
|
|
{
|
|
// If the AudioObject uses Obstruction/Occlusion then set the values before activating the trigger.
|
|
auto const pPositionedAudioObject = static_cast<CATLAudioObject*>(pAudioObject);
|
|
|
|
if (pPositionedAudioObject->CanRunRaycasts() && !pPositionedAudioObject->HasActiveEvents())
|
|
{
|
|
pPositionedAudioObject->RunRaycasts(m_oSharedData.m_oActiveListenerPosition);
|
|
}
|
|
}
|
|
|
|
const TAudioControlID nATLTriggerID = pTrigger->GetID();
|
|
|
|
// Sets eATS_STARTING on this TriggerInstance to avoid
|
|
// reporting TriggerFinished while the events are being started.
|
|
pAudioObject->ReportStartingTriggerInstance(m_nTriggerInstanceIDCounter, nATLTriggerID);
|
|
|
|
for (auto const triggerImpl : pTrigger->m_cImplPtrs)
|
|
{
|
|
const EATLSubsystem eReceiver = triggerImpl->GetReceiver();
|
|
CATLEvent* const pEvent = m_oAudioEventMgr.GetEvent(eReceiver);
|
|
pEvent->m_pImplData->m_triggerId = nATLTriggerID;
|
|
|
|
EAudioRequestStatus eActivateResult = eARS_FAILURE;
|
|
|
|
switch (eReceiver)
|
|
{
|
|
case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eActivateResult, &AudioSystemImplementationRequestBus::Events::ActivateTrigger,
|
|
pAudioObject->GetImplDataPtr(),
|
|
triggerImpl->m_pImplData,
|
|
pEvent->m_pImplData,
|
|
pSourceData);
|
|
break;
|
|
}
|
|
case eAS_ATL_INTERNAL:
|
|
{
|
|
eActivateResult = ActivateInternalTrigger(
|
|
pAudioObject,
|
|
triggerImpl->m_pImplData,
|
|
pEvent->m_pImplData);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "Unknown ATL Recipient");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (eActivateResult == eARS_SUCCESS || eActivateResult == eARS_PENDING)
|
|
{
|
|
pEvent->m_nObjectID = pAudioObject->GetID();
|
|
pEvent->m_nTriggerID = nATLTriggerID;
|
|
pEvent->m_nTriggerImplID = triggerImpl->m_nATLID;
|
|
pEvent->m_nTriggerInstanceID = m_nTriggerInstanceIDCounter;
|
|
pEvent->SetDataScope(pTrigger->GetDataScope());
|
|
|
|
if (eActivateResult == eARS_SUCCESS)
|
|
{
|
|
pEvent->m_audioEventState = eAES_PLAYING;
|
|
}
|
|
else if (eActivateResult == eARS_PENDING)
|
|
{
|
|
pEvent->m_audioEventState = eAES_LOADING;
|
|
}
|
|
|
|
pAudioObject->ReportStartedEvent(pEvent);
|
|
pAudioObject->IncrementRefCount();
|
|
|
|
// If at least one event fires, it is a success: the trigger has been activated.
|
|
eResult = eARS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
m_oAudioEventMgr.ReleaseEvent(pEvent);
|
|
}
|
|
}
|
|
|
|
// Either removes the eATS_STARTING flag on this trigger instance or removes it if no event was started.
|
|
pAudioObject->ReportStartedTriggerInstance(m_nTriggerInstanceIDCounter++, pOwner, pUserData, pUserDataOwner, nFlags);
|
|
|
|
#if !defined(AUDIO_RELEASE)
|
|
if (eResult != eARS_SUCCESS)
|
|
{
|
|
// No TriggerImpl generated an active event.
|
|
g_audioLogger.Log(eALT_WARNING, "Trigger \"%s\" failed on AudioObject \"%s\" (ID: %u)", m_oDebugNameStore.LookupAudioTriggerName(nATLTriggerID), m_oDebugNameStore.LookupAudioObjectName(pAudioObject->GetID()), pAudioObject->GetID());
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::StopTrigger(
|
|
CATLAudioObjectBase* const pAudioObject,
|
|
const CATLTrigger* const pTrigger)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
|
|
const TAudioObjectID nATLObjectID = pAudioObject->GetID();
|
|
const TAudioControlID nATLTriggerID = pTrigger->GetID();
|
|
|
|
TObjectEventSet rEvents = pAudioObject->GetActiveEvents();
|
|
|
|
for (auto eventId : rEvents)
|
|
{
|
|
const CATLEvent* const pEvent = m_oAudioEventMgr.LookupID(eventId);
|
|
|
|
if (pEvent && pEvent->IsPlaying() && (pEvent->m_nTriggerID == nATLTriggerID))
|
|
{
|
|
switch (pEvent->m_eSender)
|
|
{
|
|
case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::StopEvent,
|
|
pAudioObject->GetImplDataPtr(),
|
|
pEvent->m_pImplData);
|
|
break;
|
|
}
|
|
case eAS_ATL_INTERNAL:
|
|
{
|
|
eResult = StopInternalEvent(pAudioObject, pEvent->m_pImplData);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "ATL - StopTrigger: Unknown ATL Recipient");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::StopAllTriggers(CATLAudioObjectBase* const pAudioObject, void* const pOwner /* = nullptr*/)
|
|
{
|
|
if (!pOwner)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::StopAllEvents, pAudioObject->GetImplDataPtr());
|
|
return eResult;
|
|
}
|
|
else
|
|
{
|
|
EAudioRequestStatus eResult = eARS_SUCCESS;
|
|
|
|
auto triggerInstances = pAudioObject->GetTriggerInstancesByOwner(pOwner);
|
|
|
|
auto activeEvents = pAudioObject->GetActiveEvents();
|
|
|
|
for (auto eventId : activeEvents)
|
|
{
|
|
const CATLEvent* const atlEvent = m_oAudioEventMgr.LookupID(eventId);
|
|
|
|
if (atlEvent && triggerInstances.find(atlEvent->m_nTriggerInstanceID) != triggerInstances.end())
|
|
{
|
|
EAudioRequestStatus eSingleResult = eARS_FAILURE;
|
|
|
|
switch (atlEvent->m_eSender)
|
|
{
|
|
case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eSingleResult, &AudioSystemImplementationRequestBus::Events::StopEvent,
|
|
pAudioObject->GetImplDataPtr(),
|
|
atlEvent->m_pImplData);
|
|
break;
|
|
}
|
|
|
|
case eAS_ATL_INTERNAL:
|
|
{
|
|
eSingleResult = StopInternalEvent(pAudioObject, atlEvent->m_pImplData);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "ATL - StopAllTriggersFiltered: Unknown ATL Recipient");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (eSingleResult != eARS_SUCCESS)
|
|
{
|
|
eResult = eARS_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return eResult;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::SetSwitchState(
|
|
CATLAudioObjectBase* const pAudioObject,
|
|
const CATLSwitchState* const pState)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
|
|
for (auto switchStateImpl : pState->m_cImplPtrs)
|
|
{
|
|
const EATLSubsystem eReceiver = switchStateImpl->GetReceiver();
|
|
EAudioRequestStatus eSetStateResult = eARS_FAILURE;
|
|
|
|
switch (eReceiver)
|
|
{
|
|
case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eSetStateResult, &AudioSystemImplementationRequestBus::Events::SetSwitchState,
|
|
pAudioObject->GetImplDataPtr(),
|
|
switchStateImpl->m_pImplData);
|
|
break;
|
|
}
|
|
case eAS_ATL_INTERNAL:
|
|
{
|
|
eSetStateResult = SetInternalSwitchState(pAudioObject, switchStateImpl->m_pImplData);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "Unknown ATL Recipient");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (eSetStateResult == eARS_SUCCESS)
|
|
{
|
|
eResult = eARS_SUCCESS;// if at least one of the implementations is set successfully, it is a success
|
|
}
|
|
}
|
|
|
|
if (eResult == eARS_SUCCESS)
|
|
{
|
|
pAudioObject->SetSwitchState(pState->GetParentID(), pState->GetID());
|
|
}
|
|
#if !defined(AUDIO_RELEASE)
|
|
else
|
|
{
|
|
const char* const sSwitchName = m_oDebugNameStore.LookupAudioSwitchName(pState->GetParentID());
|
|
const char* const sSwitchStateName = m_oDebugNameStore.LookupAudioSwitchStateName(pState->GetParentID(), pState->GetID());
|
|
const char* const sAudioObjectName = m_oDebugNameStore.LookupAudioObjectName(pAudioObject->GetID());
|
|
g_audioLogger.Log(eALT_WARNING, "Failed to set the ATLSwitch \"%s\" to ATLSwitchState \"%s\" on AudioObject \"%s\" (ID: %u)", sSwitchName, sSwitchStateName, sAudioObjectName, pAudioObject->GetID());
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::SetRtpc(
|
|
CATLAudioObjectBase* const pAudioObject,
|
|
const CATLRtpc* const pRtpc,
|
|
const float fValue)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
|
|
for (auto rtpcImpl : pRtpc->m_cImplPtrs)
|
|
{
|
|
const EATLSubsystem eReceiver = rtpcImpl->GetReceiver();
|
|
EAudioRequestStatus eSetRtpcResult = eARS_FAILURE;
|
|
|
|
switch (eReceiver)
|
|
{
|
|
case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eSetRtpcResult, &AudioSystemImplementationRequestBus::Events::SetRtpc,
|
|
pAudioObject->GetImplDataPtr(),
|
|
rtpcImpl->m_pImplData,
|
|
fValue);
|
|
break;
|
|
}
|
|
case eAS_ATL_INTERNAL:
|
|
{
|
|
eSetRtpcResult = SetInternalRtpc(pAudioObject, rtpcImpl->m_pImplData, fValue);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "Unknown ATL Recipient");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (eSetRtpcResult == eARS_SUCCESS)
|
|
{
|
|
eResult = eARS_SUCCESS;// if at least one of the implementations is set successfully, it is a success
|
|
}
|
|
}
|
|
|
|
if (eResult == eARS_SUCCESS)
|
|
{
|
|
pAudioObject->SetRtpc(pRtpc->GetID(), fValue);
|
|
}
|
|
#if !defined(AUDIO_RELEASE)
|
|
else
|
|
{
|
|
const char* const sRtpcName = m_oDebugNameStore.LookupAudioRtpcName(pRtpc->GetID());
|
|
const char* const sAudioObjectName = m_oDebugNameStore.LookupAudioObjectName(pAudioObject->GetID());
|
|
g_audioLogger.Log(eALT_WARNING, "Failed to set the ATLRtpc \"%s\" to %f on AudioObject \"%s\" (ID: %u)", sRtpcName, fValue, sAudioObjectName, pAudioObject->GetID());
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ResetRtpcs(CATLAudioObjectBase* const pAudioObject)
|
|
{
|
|
const TObjectRtpcMap rRtpcs = pAudioObject->GetRtpcs();
|
|
EAudioRequestStatus eResult = eARS_SUCCESS;
|
|
|
|
for (auto& rtpcPair : rRtpcs)
|
|
{
|
|
auto it = m_cRtpcs.find(rtpcPair.first);
|
|
if (it != m_cRtpcs.end())
|
|
{
|
|
for (auto rtpcImpl : it->second->m_cImplPtrs)
|
|
{
|
|
EAudioRequestStatus eResetRtpcResult = eARS_FAILURE;
|
|
switch (rtpcImpl->GetReceiver())
|
|
{
|
|
case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResetRtpcResult, &AudioSystemImplementationRequestBus::Events::ResetRtpc,
|
|
pAudioObject->GetImplDataPtr(),
|
|
rtpcImpl->m_pImplData);
|
|
break;
|
|
}
|
|
|
|
case eAS_ATL_INTERNAL:
|
|
{
|
|
// Implement internal Rtpcs later
|
|
eResetRtpcResult = eARS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "ATL - ResetRtpc: Unknown ATL Recipient");
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If any reset failed, consider it an overall failure
|
|
if (eResetRtpcResult != eARS_SUCCESS)
|
|
{
|
|
eResult = eARS_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (eResult == eARS_SUCCESS)
|
|
{
|
|
pAudioObject->ClearRtpcs();
|
|
}
|
|
#if !defined(AUDIO_RELEASE)
|
|
else
|
|
{
|
|
const TAudioObjectID objectId = pAudioObject->GetID();
|
|
|
|
g_audioLogger.Log(eALT_WARNING,
|
|
"Failed to Reset Rtpcs on AudioObject \"%s\" (ID: %u)",
|
|
m_oDebugNameStore.LookupAudioObjectName(objectId),
|
|
objectId);
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::SetEnvironment(
|
|
CATLAudioObjectBase* const pAudioObject,
|
|
const CATLAudioEnvironment* const pEnvironment,
|
|
const float fAmount)
|
|
{
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
|
|
for (auto environmentImpl : pEnvironment->m_cImplPtrs)
|
|
{
|
|
const EATLSubsystem eReceiver = environmentImpl->GetReceiver();
|
|
EAudioRequestStatus eSetEnvResult = eARS_FAILURE;
|
|
|
|
switch (eReceiver)
|
|
{
|
|
case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
|
|
{
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eSetEnvResult, &AudioSystemImplementationRequestBus::Events::SetEnvironment,
|
|
pAudioObject->GetImplDataPtr(),
|
|
environmentImpl->m_pImplData,
|
|
fAmount);
|
|
break;
|
|
}
|
|
case eAS_ATL_INTERNAL:
|
|
{
|
|
eSetEnvResult = SetInternalEnvironment(pAudioObject, environmentImpl->m_pImplData, fAmount);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "Unknown ATL Recipient");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (eSetEnvResult == eARS_SUCCESS)
|
|
{
|
|
eResult = eARS_SUCCESS;// if at least one of the implementations is set successfully, it is a success
|
|
}
|
|
}
|
|
|
|
if (eResult == eARS_SUCCESS)
|
|
{
|
|
pAudioObject->SetEnvironmentAmount(pEnvironment->GetID(), fAmount);
|
|
}
|
|
#if !defined(AUDIO_RELEASE)
|
|
else
|
|
{
|
|
const char* const sEnvironmentName = m_oDebugNameStore.LookupAudioEnvironmentName(pEnvironment->GetID());
|
|
const char* const sAudioObjectName = m_oDebugNameStore.LookupAudioObjectName(pAudioObject->GetID());
|
|
g_audioLogger.Log(eALT_WARNING, "Failed to set the ATLAudioEnvironment \"%s\" to %f on AudioObject \"%s\" (ID: %u)", sEnvironmentName, fAmount, sAudioObjectName, pAudioObject->GetID());
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ResetEnvironments(CATLAudioObjectBase* const pAudioObject)
|
|
{
|
|
const TObjectEnvironmentMap rEnvironments = pAudioObject->GetEnvironments();
|
|
|
|
EAudioRequestStatus eResult = eARS_SUCCESS;
|
|
|
|
for (auto& environmentAmountPair : rEnvironments)
|
|
{
|
|
auto it = m_cEnvironments.find(environmentAmountPair.first);
|
|
if (it != m_cEnvironments.end())
|
|
{
|
|
const EAudioRequestStatus eSetEnvResult = SetEnvironment(pAudioObject, it->second, 0.0f);
|
|
|
|
if (eSetEnvResult != eARS_SUCCESS)
|
|
{
|
|
// If setting at least one Environment fails, we consider this a failure.
|
|
eResult = eARS_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (eResult == eARS_SUCCESS)
|
|
{
|
|
pAudioObject->ClearEnvironments();
|
|
}
|
|
#if !defined(AUDIO_RELEASE)
|
|
else
|
|
{
|
|
const TAudioObjectID nObjectID = pAudioObject->GetID();
|
|
|
|
g_audioLogger.Log(
|
|
eALT_WARNING,
|
|
"Failed to Reset AudioEnvironments on AudioObject \"%s\" (ID: %u)",
|
|
m_oDebugNameStore.LookupAudioObjectName(nObjectID),
|
|
nObjectID);
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
|
|
return eResult;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::ActivateInternalTrigger(
|
|
[[maybe_unused]] CATLAudioObjectBase* const pAudioObject,
|
|
[[maybe_unused]] const IATLTriggerImplData* const pTriggerData,
|
|
[[maybe_unused]] IATLEventData* const pEventData)
|
|
{
|
|
//TODO implement
|
|
return eARS_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::StopInternalEvent(
|
|
[[maybe_unused]] CATLAudioObjectBase* const pAudioObject,
|
|
[[maybe_unused]] const IATLEventData* const pEventData)
|
|
{
|
|
//TODO implement
|
|
return eARS_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::StopAllInternalEvents([[maybe_unused]] CATLAudioObjectBase* const pAudioObject)
|
|
{
|
|
//TODO implement
|
|
return eARS_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::SetInternalRtpc(
|
|
[[maybe_unused]] CATLAudioObjectBase* const pAudioObject,
|
|
[[maybe_unused]] const IATLRtpcImplData* const pRtpcData,
|
|
[[maybe_unused]] const float fValue)
|
|
{
|
|
//TODO implement
|
|
return eARS_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::SetInternalSwitchState(
|
|
CATLAudioObjectBase* const pAudioObject,
|
|
const IATLSwitchStateImplData* const pSwitchStateData)
|
|
{
|
|
auto const pInternalStateData = static_cast<const SATLSwitchStateImplData_internal*>(pSwitchStateData);
|
|
|
|
//TODO: once there is more than one internal switch, a more sensible approach needs to be developed
|
|
if (pInternalStateData->nATLInternalSwitchID == ATLInternalControlIDs::ObstructionOcclusionCalcSwitchID)
|
|
{
|
|
if (pAudioObject->HasPosition())
|
|
{
|
|
auto const pPositionedAudioObject = static_cast<CATLAudioObject*>(pAudioObject);
|
|
|
|
if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OOCStateIDs[eAOOCT_IGNORE])
|
|
{
|
|
SATLSoundPropagationData oPropagationData;
|
|
pPositionedAudioObject->SetRaycastCalcType(eAOOCT_IGNORE);
|
|
pPositionedAudioObject->GetObstOccData(oPropagationData);
|
|
|
|
AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::SetObstructionOcclusion,
|
|
pPositionedAudioObject->GetImplDataPtr(),
|
|
oPropagationData.fObstruction,
|
|
oPropagationData.fOcclusion);
|
|
}
|
|
else if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OOCStateIDs[eAOOCT_SINGLE_RAY])
|
|
{
|
|
pPositionedAudioObject->SetRaycastCalcType(eAOOCT_SINGLE_RAY);
|
|
}
|
|
else if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OOCStateIDs[eAOOCT_MULTI_RAY])
|
|
{
|
|
pPositionedAudioObject->SetRaycastCalcType(eAOOCT_MULTI_RAY);
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "SetInternalSwitchState - Unknown value specified for SetObstructionOcclusionCalc");
|
|
}
|
|
}
|
|
}
|
|
else if (pInternalStateData->nATLInternalSwitchID == ATLInternalControlIDs::ObjectVelocityTrackingSwitchID)
|
|
{
|
|
if (pAudioObject->HasPosition())
|
|
{
|
|
auto const pPositionedAudioObject = static_cast<CATLAudioObject*>(pAudioObject);
|
|
if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OVTOnStateID)
|
|
{
|
|
pPositionedAudioObject->SetVelocityTracking(true);
|
|
}
|
|
else if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OVTOffStateID)
|
|
{
|
|
pPositionedAudioObject->SetVelocityTracking(false);
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "SetInternalSwitchState - Unknown value specified for SetVelocityTracking (ly-fixit update this name!)");
|
|
}
|
|
}
|
|
}
|
|
|
|
return eARS_SUCCESS;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::SetInternalEnvironment(
|
|
[[maybe_unused]] CATLAudioObjectBase* const pAudioObject,
|
|
[[maybe_unused]] const IATLEnvironmentImplData* const pEnvironmentImplData,
|
|
[[maybe_unused]] const float fAmount)
|
|
{
|
|
// TODO: implement
|
|
return eARS_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::MuteAll()
|
|
{
|
|
EAudioRequestStatus result = eARS_FAILURE;
|
|
const CATLTrigger* const trigger = stl::find_in_map(m_cTriggers, ATLInternalControlIDs::MuteAllTriggerID, nullptr);
|
|
|
|
if (trigger)
|
|
{
|
|
result = ActivateTrigger(m_pGlobalAudioObject, trigger, 0.0f);
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL - Trigger not found for: ATLInternalControlIDs::MuteAllTriggerID");
|
|
}
|
|
|
|
if (result == eARS_SUCCESS)
|
|
{
|
|
m_nFlags |= eAIS_IS_MUTED;
|
|
}
|
|
|
|
AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemMuteAll);
|
|
return result;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::UnmuteAll()
|
|
{
|
|
EAudioRequestStatus result = eARS_FAILURE;
|
|
const CATLTrigger* const trigger = stl::find_in_map(m_cTriggers, ATLInternalControlIDs::UnmuteAllTriggerID, nullptr);
|
|
|
|
if (trigger)
|
|
{
|
|
result = ActivateTrigger(m_pGlobalAudioObject, trigger, 0.0f);
|
|
}
|
|
else
|
|
{
|
|
g_audioLogger.Log(eALT_WARNING, "ATL - Trigger not found for: ATLInternalControlIDs::UnmuteAllTriggerID");
|
|
}
|
|
|
|
if (result == eARS_SUCCESS)
|
|
{
|
|
m_nFlags &= ~eAIS_IS_MUTED;
|
|
}
|
|
|
|
AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemUnmuteAll);
|
|
return result;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::UpdateSharedData()
|
|
{
|
|
m_oAudioListenerMgr.GetDefaultListenerPosition(m_oSharedData.m_oActiveListenerPosition);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::SetImplLanguage()
|
|
{
|
|
if (auto console = AZ::Interface<AZ::IConsole>::Get(); console != nullptr)
|
|
{
|
|
AZ::CVarFixedString languageAudio;
|
|
if (auto result = console->GetCvarValue("g_languageAudio", languageAudio); result == AZ::GetValueResult::Success)
|
|
{
|
|
AudioSystemImplementationRequestBus::Broadcast(
|
|
&AudioSystemImplementationRequestBus::Events::SetLanguage, languageAudio.data());
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, [[maybe_unused]] UINT_PTR lparam)
|
|
{
|
|
switch (event)
|
|
{
|
|
case ESYSTEM_EVENT_LEVEL_UNLOAD:
|
|
RaycastProcessor::s_raycastsEnabled = false;
|
|
break;
|
|
case ESYSTEM_EVENT_LEVEL_GAMEPLAY_START:
|
|
case ESYSTEM_EVENT_LEVEL_PRECACHE_START:
|
|
RaycastProcessor::s_raycastsEnabled = true;
|
|
break;
|
|
case ESYSTEM_EVENT_EDITOR_GAME_MODE_CHANGED:
|
|
RaycastProcessor::s_raycastsEnabled = (wparam != 0);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if !defined(AUDIO_RELEASE)
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
EAudioRequestStatus CAudioTranslationLayer::RefreshAudioSystem(const char* const controlsPath, const char* const levelName, TAudioPreloadRequestID levelPreloadId)
|
|
{
|
|
g_audioLogger.Log(eALT_ALWAYS, "$8Beginning to refresh the AudioSystem!");
|
|
|
|
if (!controlsPath || controlsPath[0] == '\0')
|
|
{
|
|
g_audioLogger.Log(eALT_ERROR, "ATL RefreshAudioSystem - Controls path is null, can't complete the refresh!");
|
|
return eARS_FAILURE;
|
|
}
|
|
|
|
EAudioRequestStatus eResult = eARS_FAILURE;
|
|
AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::StopAllSounds);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to StopAllSounds!");
|
|
|
|
eResult = m_oFileCacheMgr.UnloadDataByScope(eADS_LEVEL_SPECIFIC);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to unload old level data!");
|
|
|
|
eResult = m_oFileCacheMgr.UnloadDataByScope(eADS_GLOBAL);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to unload old global data!");
|
|
|
|
eResult = ClearControlsData(eADS_ALL);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to clear old controls data!");
|
|
|
|
eResult = ClearPreloadsData(eADS_ALL);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to clear old preloads data!");
|
|
|
|
AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemRefresh);
|
|
|
|
SetImplLanguage();
|
|
|
|
eResult = ParseControlsData(controlsPath, eADS_GLOBAL);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to parse fresh global controls data!");
|
|
|
|
eResult = ParsePreloadsData(controlsPath, eADS_GLOBAL);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to parse fresh global preloads data!");
|
|
|
|
eResult = m_oFileCacheMgr.TryLoadRequest(ATLInternalControlIDs::GlobalPreloadRequestID, true, true);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to load fresh global preloads!");
|
|
|
|
if (levelName && levelName[0] != '\0')
|
|
{
|
|
AZStd::string levelControlsPath(controlsPath);
|
|
levelControlsPath.append("levels/");
|
|
levelControlsPath.append(levelName);
|
|
AZ::StringFunc::RelativePath::Normalize(levelControlsPath);
|
|
|
|
eResult = ParseControlsData(levelControlsPath.c_str(), eADS_LEVEL_SPECIFIC);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to parse fresh level controls data!");
|
|
|
|
eResult = ParsePreloadsData(levelControlsPath.c_str(), eADS_LEVEL_SPECIFIC);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to parse fresh level preloads data!");
|
|
|
|
if (levelPreloadId != INVALID_AUDIO_PRELOAD_REQUEST_ID)
|
|
{
|
|
eResult = m_oFileCacheMgr.TryLoadRequest(levelPreloadId, true, true);
|
|
AZ_Error("AudioTranslationLayer", eResult == eARS_SUCCESS, "ATL RefreshAudioSystem - Failed to load fresh level preloads!");
|
|
}
|
|
}
|
|
|
|
if (m_nFlags & eAIS_IS_MUTED)
|
|
{
|
|
// restore the muted state...
|
|
MuteAll();
|
|
}
|
|
|
|
g_audioLogger.Log(eALT_ALWAYS, "$3Done refreshing the AudioSystem!");
|
|
|
|
return eARS_SUCCESS;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CAudioTranslationLayer::ReserveAudioObjectID(TAudioObjectID& rAudioObjectID, const char* const sAudioObjectName)
|
|
{
|
|
const bool bSuccess = m_oAudioObjectMgr.ReserveID(rAudioObjectID, sAudioObjectName);
|
|
|
|
if (bSuccess)
|
|
{
|
|
m_oDebugNameStore.AddAudioObject(rAudioObjectID, sAudioObjectName);
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::DrawAudioSystemDebugInfo()
|
|
{
|
|
AZ_PROFILE_FUNCTION(Audio);
|
|
|
|
// ToDo: Update to work with Atom? LYN-3677
|
|
/*if (CVars::s_debugDrawOptions.GetRawFlags() != 0)
|
|
{
|
|
DrawAudioObjectDebugInfo(*pAuxGeom); // needs to be called first so that the rest of the labels are printed
|
|
// on top (Draw2dLabel doesn't provide a way set which labels are printed on top)
|
|
|
|
const size_t nPrimaryPoolSize = AZ::AllocatorInstance<Audio::AudioSystemAllocator>::Get().Capacity();
|
|
const size_t nPrimaryPoolUsedSize = nPrimaryPoolSize - AZ::AllocatorInstance<Audio::AudioSystemAllocator>::Get().GetUnAllocatedMemory();
|
|
|
|
float fPosX = 0.0f;
|
|
float fPosY = 4.0f;
|
|
|
|
const float fColor[4] = { 1.0f, 1.0f, 1.0f, 0.9f };
|
|
const float fColorRed[4] = { 1.0f, 0.0f, 0.0f, 0.7f };
|
|
const float fColorGreen[4] = { 0.0f, 1.0f, 0.0f, 0.7f };
|
|
const float fColorBlue[4] = { 0.4f, 0.4f, 1.0f, 1.0f };
|
|
|
|
const char* implementationName = nullptr;
|
|
AudioSystemImplementationRequestBus::BroadcastResult(implementationName, &AudioSystemImplementationRequestBus::Events::GetImplementationNameString);
|
|
pAuxGeom->Draw2dLabel(fPosX, fPosY, 1.6f, fColorBlue, false, "AudioTranslationLayer with %s", implementationName);
|
|
|
|
fPosX += 20.0f;
|
|
fPosY += 17.0f;
|
|
|
|
pAuxGeom->Draw2dLabel(fPosX, fPosY, 1.35f, fColor, false,
|
|
"AudioSystem Memory: %.2f / %.2f MiB",
|
|
(nPrimaryPoolUsedSize / 1024) / 1024.f,
|
|
(nPrimaryPoolSize / 1024) / 1024.f
|
|
);
|
|
|
|
|
|
float const fLineHeight = 13.0f;
|
|
|
|
SAudioImplMemoryInfo oMemoryInfo;
|
|
AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::GetMemoryInfo, oMemoryInfo);
|
|
|
|
fPosY += fLineHeight;
|
|
pAuxGeom->Draw2dLabel(fPosX, fPosY, 1.35f, fColor, false,
|
|
"AudioImpl Memory: %.2f / %.2f MiB",
|
|
(oMemoryInfo.nPrimaryPoolUsedSize / 1024) / 1024.f,
|
|
(oMemoryInfo.nPrimaryPoolSize / 1024) / 1024.f
|
|
);
|
|
|
|
static const float SMOOTHING_ALPHA = 0.2f;
|
|
|
|
const AZ::Vector3 vPos = m_oSharedData.m_oActiveListenerPosition.GetPositionVec();
|
|
const AZ::Vector3 vFwd = m_oSharedData.m_oActiveListenerPosition.GetForwardVec();
|
|
const size_t nNumAudioObjects = m_oAudioObjectMgr.GetNumAudioObjects();
|
|
const size_t nNumActiveAudioObjects = m_oAudioObjectMgr.GetNumActiveAudioObjects();
|
|
const size_t nEvents = m_oAudioEventMgr.GetNumActive();
|
|
const size_t nListeners = m_oAudioListenerMgr.GetNumActive();
|
|
const size_t nNumEventListeners = m_oAudioEventListenerMgr.GetNumEventListeners();
|
|
|
|
|
|
const bool bActive = true;
|
|
const float fColorListener[4] =
|
|
{
|
|
bActive ? fColorGreen[0] : fColorRed[0],
|
|
bActive ? fColorGreen[1] : fColorRed[1],
|
|
bActive ? fColorGreen[2] : fColorRed[2],
|
|
1.0f
|
|
};
|
|
|
|
const float* fColorNumbers = fColorBlue;
|
|
|
|
TAudioObjectID activeListenerID = INVALID_AUDIO_OBJECT_ID;
|
|
if (CATLListenerObject* overrideListener = m_oAudioListenerMgr.LookupID(m_oAudioListenerMgr.GetOverrideListenerID()))
|
|
{
|
|
activeListenerID = overrideListener->GetID();
|
|
}
|
|
else if (CATLListenerObject* defaultListener = m_oAudioListenerMgr.LookupID(m_oAudioListenerMgr.GetDefaultListenerID()))
|
|
{
|
|
activeListenerID = defaultListener->GetID();
|
|
}
|
|
|
|
fPosY += fLineHeight;
|
|
pAuxGeom->Draw2dLabel(fPosX, fPosY, 1.35f, fColorListener, false,
|
|
"Listener <%llu> PosXYZ: %.2f %.2f %.2f FwdXYZ: %.2f %.2f %.2f",
|
|
activeListenerID,
|
|
static_cast<float>(vPos.GetX()), static_cast<float>(vPos.GetY()), static_cast<float>(vPos.GetZ()),
|
|
static_cast<float>(vFwd.GetX()), static_cast<float>(vFwd.GetY()), static_cast<float>(vFwd.GetZ()));
|
|
|
|
fPosY += fLineHeight;
|
|
pAuxGeom->Draw2dLabel(fPosX, fPosY, 1.35f, fColorNumbers, false,
|
|
"Objects: %3zu/%3zu | Events: %3zu EventListeners %3zu | Listeners: %zu",
|
|
nNumActiveAudioObjects, nNumAudioObjects, nEvents, nNumEventListeners, nListeners);
|
|
|
|
fPosY += fLineHeight;
|
|
DrawATLComponentDebugInfo(*pAuxGeom, fPosX, fPosY);
|
|
|
|
pAuxGeom->Commit(7);
|
|
}*/
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::DrawATLComponentDebugInfo(IRenderAuxGeom& auxGeom, float fPosX, const float fPosY)
|
|
{
|
|
m_oFileCacheMgr.DrawDebugInfo(auxGeom, fPosX, fPosY);
|
|
|
|
if (CVars::s_debugDrawOptions.AreAllFlagsActive(DebugDraw::Options::MemoryInfo))
|
|
{
|
|
DrawImplMemoryPoolDebugInfo(auxGeom, fPosX, fPosY);
|
|
}
|
|
|
|
if (CVars::s_debugDrawOptions.AreAllFlagsActive(DebugDraw::Options::ActiveObjects))
|
|
{
|
|
m_oAudioObjectMgr.DrawDebugInfo(auxGeom, fPosX, fPosY);
|
|
fPosX += 800.0f;
|
|
}
|
|
|
|
if (CVars::s_debugDrawOptions.AreAllFlagsActive(DebugDraw::Options::ActiveEvents))
|
|
{
|
|
m_oAudioEventMgr.DrawDebugInfo(auxGeom, fPosX, fPosY);
|
|
}
|
|
|
|
if (CVars::s_debugDrawOptions.AreAllFlagsActive(DebugDraw::Options::DrawListener))
|
|
{
|
|
m_oAudioListenerMgr.DrawDebugInfo(auxGeom);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void BytesToString(AZ::u64 bytes, char* buffer, size_t bufLength)
|
|
{
|
|
if (bytes < (1 << 10))
|
|
{
|
|
azsnprintf(buffer, bufLength, "%" PRIu64 " B", bytes);
|
|
}
|
|
else if (bytes < (1 << 20))
|
|
{
|
|
azsnprintf(buffer, bufLength, "%.2f KB", static_cast<double>(bytes) / static_cast<double>(1 << 10));
|
|
}
|
|
else
|
|
{
|
|
azsnprintf(buffer, bufLength, "%.2f MB", static_cast<double>(bytes) / static_cast<double>(1 << 20));
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::DrawImplMemoryPoolDebugInfo(IRenderAuxGeom& auxGeom, float fPosX, float fPosY)
|
|
{
|
|
const float colorMax = 0.9f;
|
|
const float colorMin = 0.1f;
|
|
const float textSize = 1.5f;
|
|
const float lineHeight = 15.f;
|
|
float color[4] = { colorMax, colorMax, colorMax, 0.9f };
|
|
|
|
const AZ::Color whiteColor(colorMax, colorMax, colorMax, 0.9f);
|
|
const AZ::Color greenColor(colorMin, colorMax, colorMin, 0.9f);
|
|
const AZ::Color yellowColor(colorMax, colorMax, colorMin, 0.9f);
|
|
const AZ::Color redColor(colorMax, colorMin, colorMin, 0.9f);
|
|
|
|
constexpr const char* tableHeaderNames[] = {
|
|
"ID",
|
|
"Name",
|
|
"Curr Used",
|
|
"Peak Used",
|
|
"%% of Used",
|
|
"Allocs",
|
|
"Frees",
|
|
};
|
|
constexpr size_t numColumns = AZStd::size(tableHeaderNames);
|
|
constexpr float xTablePositions[numColumns] = { 0.f, 40.f, 300.f, 400.f, 500.f, 600.f, 700.f };
|
|
|
|
float posY = fPosY;
|
|
|
|
// Draw the header info:
|
|
for (int column = 0; column < numColumns; ++column)
|
|
{
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[column], posY, textSize, color, false, tableHeaderNames[column]);
|
|
}
|
|
|
|
// Get the memory pool information...
|
|
AZStd::vector<AudioImplMemoryPoolInfo> poolInfos;
|
|
AudioSystemImplementationRequestBus::BroadcastResult(poolInfos, &AudioSystemImplementationRequestBus::Events::GetMemoryPoolInfo);
|
|
|
|
if (!poolInfos.empty())
|
|
{
|
|
const AudioImplMemoryPoolInfo& globalInfo = poolInfos.back();
|
|
AZ_Assert(globalInfo.m_poolId == -1, "Global memory info doesn't have the expected ID.\n");
|
|
poolInfos.pop_back();
|
|
|
|
AZ::u64 totalPeak = 0;
|
|
AZ::u64 totalAllocs = 0;
|
|
AZ::u64 totalFrees = 0;
|
|
constexpr size_t bufferSize = 32;
|
|
char buffer[bufferSize] = { 0 };
|
|
|
|
for (auto& poolInfo : poolInfos)
|
|
{
|
|
posY += lineHeight;
|
|
|
|
totalPeak += poolInfo.m_peakUsed;
|
|
totalAllocs += poolInfo.m_numAllocs;
|
|
totalFrees += poolInfo.m_numFrees;
|
|
float percentUsed = static_cast<float>(poolInfo.m_memoryUsed) / static_cast<float>(globalInfo.m_memoryUsed);
|
|
|
|
// Calculate a color (green->-yellow->-red) based on percentage.
|
|
AZ::Color percentColor;
|
|
if (percentUsed < 0.5f)
|
|
{
|
|
percentColor = greenColor.Lerp(yellowColor, percentUsed * 2.f);
|
|
}
|
|
else
|
|
{
|
|
percentColor = yellowColor.Lerp(redColor, (percentUsed * 2.f) - 1.f);
|
|
}
|
|
percentColor.StoreToFloat4(color);
|
|
percentUsed *= 100.f;
|
|
|
|
// ID
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[0], posY, textSize, color, false, "%d", poolInfo.m_poolId);
|
|
|
|
// Name
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[1], posY, textSize, color, false, poolInfo.m_poolName);
|
|
|
|
// Current Used (bytes)
|
|
BytesToString(poolInfo.m_memoryUsed, buffer, bufferSize);
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[2], posY, textSize, color, false, buffer);
|
|
|
|
// Peak Used (bytes)
|
|
BytesToString(poolInfo.m_peakUsed, buffer, bufferSize);
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[3], posY, textSize, color, false, buffer);
|
|
|
|
// % of Used (percent)
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[4], posY, textSize, color, false, "%.1f %%", percentUsed);
|
|
|
|
// Allocs
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[5], posY, textSize, color, false, "%u", poolInfo.m_numAllocs);
|
|
|
|
// Frees
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[6], posY, textSize, color, false, "%u", poolInfo.m_numFrees);
|
|
}
|
|
|
|
whiteColor.StoreToFloat4(color);
|
|
posY += (2.f * lineHeight);
|
|
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[1], posY, textSize, color, false, tableHeaderNames[1]);
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[1], posY + lineHeight, textSize, color, false, globalInfo.m_poolName);
|
|
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[2], posY, textSize, color, false, "Total Used");
|
|
BytesToString(globalInfo.m_memoryUsed, buffer, bufferSize);
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[2], posY + lineHeight, textSize, color, false, buffer);
|
|
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[3], posY, textSize, color, false, "Total Peak");
|
|
BytesToString(totalPeak, buffer, bufferSize);
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[3], posY + lineHeight, textSize, color, false, buffer);
|
|
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[4], posY, textSize, color, false, "Total Size");
|
|
BytesToString(globalInfo.m_memoryReserved, buffer, bufferSize);
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[4], posY + lineHeight, textSize, color, false, buffer);
|
|
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[5], posY, textSize, color, false, "Total Allocs");
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[5], posY + lineHeight, textSize, color, false, "%" PRIu64, totalAllocs);
|
|
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[6], posY, textSize, color, false, "Total Frees");
|
|
auxGeom.Draw2dLabel(fPosX + xTablePositions[6], posY + lineHeight, textSize, color, false, "%" PRIu64, totalFrees);
|
|
}
|
|
else
|
|
{
|
|
auxGeom.Draw2dLabel(
|
|
fPosX, posY + lineHeight, textSize, color, false, "No memory pool information is available for display!");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CAudioTranslationLayer::DrawAudioObjectDebugInfo(IRenderAuxGeom& auxGeom)
|
|
{
|
|
SATLWorldPosition oListenerPosition;
|
|
m_oAudioListenerMgr.GetDefaultListenerPosition(oListenerPosition);
|
|
m_oAudioObjectMgr.DrawPerObjectDebugInfo(auxGeom, oListenerPosition.GetPositionVec());
|
|
}
|
|
#endif // !AUDIO_RELEASE
|
|
} // namespace Audio
|