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.
o3de/Gems/AudioSystem/Code/Source/Engine/ATLEntities.h

525 lines
18 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
*
*/
#pragma once
#include <AzCore/IO/IStreamer.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/containers/unordered_set.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#if !defined(AUDIO_RELEASE)
#include <AzCore/std/chrono/chrono.h>
#endif // !AUDIO_RELEASE
#include <IAudioSystem.h>
#include <ATLCommon.h>
#include <ATLEntityData.h>
#include <ATLUtils.h>
#include <AudioAllocators.h>
#include <platform.h>
namespace Audio
{
template <typename KeyType, typename ValueType>
using ATLMapLookupType = AZStd::unordered_map<KeyType, ValueType, AZStd::hash<KeyType>, AZStd::equal_to<KeyType>, AudioSystemStdAllocator>;
template <typename KeyType>
using ATLSetLookupType = AZStd::unordered_set<KeyType, AZStd::hash<KeyType>, AZStd::equal_to<KeyType>, AudioSystemStdAllocator>;
// Forward declarations.
struct IAudioSystemImplementation;
class CATLCallbackManager;
struct IATLAudioObjectData;
struct IATLListenerData;
struct IATLTriggerImplData;
struct IATLRtpcImplData;
struct IATLSwitchStateImplData;
struct IATLEnvironmentImplData;
struct IATLEventData;
struct IATLAudioFileEntryData;
///////////////////////////////////////////////////////////////////////////////////////////////////
enum EATLObjectFlags : TATLEnumFlagsType
{
eAOF_NONE = 0,
eAOF_TRACK_VELOCITY = AUDIO_BIT(0),
};
///////////////////////////////////////////////////////////////////////////////////////////////////
enum EATLSubsystem : TATLEnumFlagsType
{
eAS_NONE = 0,
eAS_AUDIO_SYSTEM_IMPLEMENTATION,
eAS_ATL_INTERNAL,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
enum EAudioFileFlags : TATLEnumFlagsType
{
eAFF_NOTFOUND = AUDIO_BIT(0),
eAFF_CACHED = AUDIO_BIT(1),
eAFF_MEMALLOCFAIL = AUDIO_BIT(2),
eAFF_REMOVABLE = AUDIO_BIT(3),
eAFF_LOADING = AUDIO_BIT(4),
eAFF_USE_COUNTED = AUDIO_BIT(5),
eAFF_NEEDS_RESET_TO_MANUAL_LOADING = AUDIO_BIT(6),
eAFF_LOCALIZED = AUDIO_BIT(7),
};
///////////////////////////////////////////////////////////////////////////////////////////////////
template <typename IDType>
class CATLEntity
{
public:
explicit CATLEntity(const IDType nID, const EATLDataScope eDataScope)
: m_nID(nID)
, m_eDataScope(eDataScope)
{}
virtual ~CATLEntity() {}
virtual IDType GetID() const
{
return m_nID;
}
virtual EATLDataScope GetDataScope() const
{
return m_eDataScope;
}
protected:
EATLDataScope m_eDataScope;
private:
const IDType m_nID;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
struct SATLSoundPropagationData
{
SATLSoundPropagationData()
: fObstruction(0.0f)
, fOcclusion(0.0f)
{}
~SATLSoundPropagationData() {}
float fObstruction;
float fOcclusion;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLListenerObject
: public CATLEntity<TAudioObjectID>
{
public:
explicit CATLListenerObject(const TAudioObjectID nID, IATLListenerData* const pImplData = nullptr)
: CATLEntity<TAudioObjectID>(nID, eADS_NONE)
, m_pImplData(pImplData)
{}
~CATLListenerObject() override {}
SATLWorldPosition oPosition;
IATLListenerData* const m_pImplData;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLControlImpl
{
public:
CATLControlImpl()
: m_eReceiver(eAS_NONE)
{}
explicit CATLControlImpl(const EATLSubsystem receiver)
: m_eReceiver(receiver)
{}
virtual ~CATLControlImpl() {}
EATLSubsystem GetReceiver() const
{
return m_eReceiver;
}
protected:
EATLSubsystem m_eReceiver;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLTriggerImpl
: public CATLControlImpl
{
public:
explicit CATLTriggerImpl(
const TAudioTriggerImplID nID,
const TAudioControlID nTriggerID,
const EATLSubsystem eReceiver,
IATLTriggerImplData* const pImplData = nullptr)
: CATLControlImpl(eReceiver)
, m_nATLID(nID)
, m_nATLTriggerID(nTriggerID)
, m_pImplData(pImplData)
{}
~CATLTriggerImpl() override {}
const TAudioTriggerImplID m_nATLID;
const TAudioControlID m_nATLTriggerID;
IATLTriggerImplData* const m_pImplData;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLTrigger
: public CATLEntity<TAudioControlID>
{
public:
using TImplPtrVec = AZStd::vector<CATLTriggerImpl*, Audio::AudioSystemStdAllocator>;
CATLTrigger(const TAudioControlID nID, const EATLDataScope eDataScope, const TImplPtrVec& rImplPtrs)
: CATLEntity<TAudioControlID>(nID, eDataScope)
, m_cImplPtrs(rImplPtrs)
{}
~CATLTrigger() override {}
TImplPtrVec m_cImplPtrs;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLRtpcImpl
: public CATLControlImpl
{
public:
CATLRtpcImpl(const EATLSubsystem eReceiver, IATLRtpcImplData* const pImplData = nullptr)
: CATLControlImpl(eReceiver)
, m_pImplData(pImplData)
{}
~CATLRtpcImpl() override {}
IATLRtpcImplData* const m_pImplData;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLRtpc
: public CATLEntity<TAudioControlID>
{
public:
using TImplPtrVec = AZStd::vector<CATLRtpcImpl*, Audio::AudioSystemStdAllocator>;
CATLRtpc(const TAudioControlID nID, const EATLDataScope eDataScope, const TImplPtrVec& cImplPtrs)
: CATLEntity<TAudioControlID>(nID, eDataScope)
, m_cImplPtrs(cImplPtrs)
{}
~CATLRtpc() override {}
TImplPtrVec m_cImplPtrs;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLSwitchStateImpl
: public CATLControlImpl
{
public:
explicit CATLSwitchStateImpl(const EATLSubsystem eReceiver, IATLSwitchStateImplData* const pImplData = nullptr)
: CATLControlImpl(eReceiver)
, m_pImplData(pImplData)
{}
~CATLSwitchStateImpl() override {}
IATLSwitchStateImplData* const m_pImplData;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLSwitchState
{
public:
using TImplPtrVec = AZStd::vector<CATLSwitchStateImpl*, Audio::AudioSystemStdAllocator>;
CATLSwitchState(
const TAudioControlID nSwitchID,
const TAudioSwitchStateID nStateID,
const TImplPtrVec& cImplPtrs)
: m_nID(nStateID)
, m_nSwitchID(nSwitchID)
, m_cImplPtrs(cImplPtrs)
{}
~CATLSwitchState() {}
TAudioSwitchStateID GetID() const
{
return m_nID;
}
TAudioSwitchStateID GetParentID() const
{
return m_nSwitchID;
}
TImplPtrVec m_cImplPtrs;
private:
const TAudioSwitchStateID m_nID;
const TAudioControlID m_nSwitchID;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLSwitch
: public CATLEntity<TAudioControlID>
{
public:
explicit CATLSwitch(const TAudioControlID nID, const EATLDataScope eDataScope)
: CATLEntity<TAudioControlID>(nID, eDataScope)
{}
~CATLSwitch() override {}
using TStateMap = ATLMapLookupType<TAudioSwitchStateID, CATLSwitchState*>;
TStateMap cStates;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLEnvironmentImpl
: public CATLControlImpl
{
public:
explicit CATLEnvironmentImpl(const EATLSubsystem eReceiver, IATLEnvironmentImplData* const pImplData = nullptr)
: CATLControlImpl(eReceiver)
, m_pImplData(pImplData)
{}
~CATLEnvironmentImpl() override {}
IATLEnvironmentImplData* const m_pImplData;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLAudioEnvironment
: public CATLEntity<TAudioEnvironmentID>
{
public:
using TImplPtrVec = AZStd::vector<CATLEnvironmentImpl*, Audio::AudioSystemStdAllocator>;
explicit CATLAudioEnvironment(const TAudioEnvironmentID nID, const EATLDataScope eDataScope, const TImplPtrVec& rImplPtrs)
: CATLEntity<TAudioEnvironmentID>(nID, eDataScope)
, m_cImplPtrs(rImplPtrs)
{}
~CATLAudioEnvironment() override {}
TImplPtrVec m_cImplPtrs;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLEvent
: public CATLEntity<TAudioEventID>
{
public:
explicit CATLEvent(const TAudioEventID nID, const EATLSubsystem eSender, IATLEventData* const pImplData)
: CATLEntity<TAudioEventID>(nID, eADS_NONE)
, m_nObjectID(INVALID_AUDIO_OBJECT_ID)
, m_nTriggerID(INVALID_AUDIO_CONTROL_ID)
, m_nTriggerImplID(INVALID_AUDIO_TRIGGER_IMPL_ID)
, m_nTriggerInstanceID(INVALID_AUDIO_TRIGGER_INSTANCE_ID)
, m_audioEventState(eAES_NONE)
, m_eSender(eSender)
, m_pImplData(pImplData)
{}
~CATLEvent() override {}
CATLEvent(const CATLEvent&) = delete; // copy protection!
CATLEvent& operator=(const CATLEvent&) = delete; // copy protection!
void SetDataScope(const EATLDataScope eDataScope)
{
m_eDataScope = eDataScope;
}
bool IsPlaying() const
{
return m_audioEventState == eAES_PLAYING || m_audioEventState == eAES_PLAYING_DELAYED;
}
void Clear()
{
m_eDataScope = eADS_NONE;
m_nObjectID = INVALID_AUDIO_OBJECT_ID;
m_nTriggerID = INVALID_AUDIO_CONTROL_ID;
m_nTriggerImplID = INVALID_AUDIO_TRIGGER_IMPL_ID;
m_nTriggerInstanceID = INVALID_AUDIO_TRIGGER_INSTANCE_ID;
m_audioEventState = eAES_NONE;
}
TAudioObjectID m_nObjectID;
TAudioControlID m_nTriggerID;
TAudioTriggerImplID m_nTriggerImplID;
TAudioTriggerInstanceID m_nTriggerInstanceID;
EAudioEventState m_audioEventState;
const EATLSubsystem m_eSender;
IATLEventData* m_pImplData;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLAudioFileEntry
{
public:
explicit CATLAudioFileEntry(const char* const filePath = nullptr, IATLAudioFileEntryData* const implData = nullptr)
: m_filePath(filePath)
, m_fileSize(0)
, m_useCount(0)
, m_memoryBlockAlignment(AUDIO_MEMORY_ALIGNMENT)
, m_flags(eAFF_NOTFOUND)
, m_dataScope(eADS_ALL)
, m_memoryBlock(nullptr)
, m_implData(implData)
{
}
~CATLAudioFileEntry() = default;
AZStd::string m_filePath;
size_t m_fileSize;
size_t m_useCount;
size_t m_memoryBlockAlignment;
Flags<TATLEnumFlagsType> m_flags;
EATLDataScope m_dataScope;
void* m_memoryBlock;
AZ::IO::FileRequestPtr m_asyncStreamRequest;
IATLAudioFileEntryData* m_implData;
#if !defined(AUDIO_RELEASE)
AZStd::chrono::system_clock::time_point m_timeCached;
#endif // !AUDIO_RELEASE
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLPreloadRequest
: public CATLEntity<TAudioPreloadRequestID>
{
public:
using TFileEntryIDs = AZStd::vector<TAudioFileEntryID, Audio::AudioSystemStdAllocator>;
explicit CATLPreloadRequest(
const TAudioPreloadRequestID nID,
const EATLDataScope eDataScope,
const bool bAutoLoad,
const TFileEntryIDs& cFileEntryIDs)
: CATLEntity<TAudioPreloadRequestID>(nID, eDataScope)
, m_bAutoLoad(bAutoLoad)
, m_cFileEntryIDs(cFileEntryIDs)
, m_allLoaded(false)
{}
~CATLPreloadRequest() override {}
const bool m_bAutoLoad;
TFileEntryIDs m_cFileEntryIDs;
bool m_allLoaded;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
using TATLTriggerLookup = ATLMapLookupType<TAudioControlID, CATLTrigger*>;
using TATLRtpcLookup = ATLMapLookupType<TAudioControlID, CATLRtpc*>;
using TATLSwitchLookup = ATLMapLookupType<TAudioControlID, CATLSwitch*>;
using TATLPreloadRequestLookup = ATLMapLookupType<TAudioPreloadRequestID, CATLPreloadRequest*>;
using TATLEnvironmentLookup = ATLMapLookupType<TAudioEnvironmentID, CATLAudioEnvironment*>;
///////////////////////////////////////////////////////////////////////////////////////////////////
struct SATLSwitchStateImplData_internal
: public IATLSwitchStateImplData
{
SATLSwitchStateImplData_internal(const TAudioControlID nSwitchID, const TAudioSwitchStateID nSwitchStateID)
: nATLInternalSwitchID(nSwitchID)
, nATLInternalStateID(nSwitchStateID)
{}
~SATLSwitchStateImplData_internal() override {}
const TAudioControlID nATLInternalSwitchID;
const TAudioSwitchStateID nATLInternalStateID;
};
#if !defined(AUDIO_RELEASE)
///////////////////////////////////////////////////////////////////////////////////////////////////
class CATLDebugNameStore
{
public:
CATLDebugNameStore();
~CATLDebugNameStore();
void SyncChanges(const CATLDebugNameStore& rOtherNameStore);
void AddAudioObject(const TAudioObjectID nObjectID, const char* const sName);
void AddAudioTrigger(const TAudioControlID nTriggerID, const char* const sName);
void AddAudioRtpc(const TAudioControlID nRtpcID, const char* const sName);
void AddAudioSwitch(const TAudioControlID nSwitchID, const char* const sName);
void AddAudioSwitchState(const TAudioControlID nSwitchID, const TAudioSwitchStateID nStateID, const char* const sName);
void AddAudioPreloadRequest(const TAudioPreloadRequestID nRequestID, const char* const sName);
void AddAudioEnvironment(const TAudioEnvironmentID nEnvironmentID, const char* const sName);
void RemoveAudioObject(const TAudioObjectID nObjectID);
void RemoveAudioTrigger(const TAudioControlID nTriggerID);
void RemoveAudioRtpc(const TAudioControlID nRtpcID);
void RemoveAudioSwitch(const TAudioControlID nSwitchID);
void RemoveAudioSwitchState(const TAudioControlID nSwitchID, const TAudioSwitchStateID nStateID);
void RemoveAudioPreloadRequest(const TAudioPreloadRequestID nRequestID);
void RemoveAudioEnvironment(const TAudioEnvironmentID nEnvironmentID);
bool AudioObjectsChanged() const { return m_bATLObjectsChanged; }
bool AudioTriggersChanged() const { return m_bATLTriggersChanged; }
bool AudioRtpcsChanged() const { return m_bATLRtpcsChanged; }
bool AudioSwitchesChanged() const { return m_bATLSwitchesChanged; }
bool AudioPreloadsChanged() const { return m_bATLPreloadsChanged; }
bool AudioEnvironmentsChanged() const { return m_bATLEnvironmentsChanged; }
const char* LookupAudioObjectName(const TAudioObjectID nObjectID) const;
const char* LookupAudioTriggerName(const TAudioControlID nTriggerID) const;
const char* LookupAudioRtpcName(const TAudioControlID nRtpcID) const;
const char* LookupAudioSwitchName(const TAudioControlID nSwitchID) const;
const char* LookupAudioSwitchStateName(const TAudioControlID nSwitchID, const TAudioSwitchStateID nStateID) const;
const char* LookupAudioPreloadRequestName(const TAudioPreloadRequestID nRequestID) const;
const char* LookupAudioEnvironmentName(const TAudioEnvironmentID nEnvironmentID) const;
private:
using TAudioObjectMap = ATLMapLookupType<TAudioObjectID, AZStd::string>;
using TAudioControlMap = ATLMapLookupType<TAudioControlID, AZStd::string>;
using TAudioSwitchStateMap = ATLMapLookupType<TAudioSwitchStateID, AZStd::string>;
using TAudioSwitchMap = ATLMapLookupType<TAudioControlID, AZStd::pair<AZStd::string, TAudioSwitchStateMap>>;
using TAudioPreloadRequestsMap = ATLMapLookupType<TAudioPreloadRequestID, AZStd::string>;
using TAudioEnvironmentMap = ATLMapLookupType<TAudioEnvironmentID, AZStd::string>;
TAudioObjectMap m_cATLObjectNames;
TAudioControlMap m_cATLTriggerNames;
TAudioControlMap m_cATLRtpcNames;
TAudioSwitchMap m_cATLSwitchNames;
TAudioPreloadRequestsMap m_cATLPreloadRequestNames;
TAudioEnvironmentMap m_cATLEnvironmentNames;
mutable bool m_bATLObjectsChanged;
mutable bool m_bATLTriggersChanged;
mutable bool m_bATLRtpcsChanged;
mutable bool m_bATLSwitchesChanged;
mutable bool m_bATLPreloadsChanged;
mutable bool m_bATLEnvironmentsChanged;
};
#endif // !AUDIO_RELEASE
} // namespace Audio