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/ATLUtils.h

231 lines
6.6 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 <AudioAllocators.h>
#include <AudioLogger.h>
#include <AzCore/Math/Random.h>
#include <AzCore/std/string/string_view.h>
#include <AzCore/std/typetraits/is_integral.h>
#include <AzCore/std/typetraits/is_unsigned.h>
#define ATL_FLOAT_EPSILON (1.0e-6)
namespace Audio
{
extern CAudioLogger g_audioLogger;
///////////////////////////////////////////////////////////////////////////////////////////////////
inline float frand_symm()
{
static AZ::SimpleLcgRandom rand(AZStd::GetTimeNowMicroSecond());
// return random float [-1.f, 1.f)
return rand.GetRandomFloat() * 2.f - 1.f;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
template<typename TMap, typename TKey>
bool FindPlace(TMap& map, const TKey& key, typename TMap::iterator& iPlace)
{
iPlace = map.find(key);
return (iPlace != map.end());
}
///////////////////////////////////////////////////////////////////////////////////////////////////
template<typename TMap, typename TKey>
bool FindPlaceConst(const TMap& map, const TKey& key, typename TMap::const_iterator& iPlace)
{
iPlace = map.find(key);
return (iPlace != map.end());
}
#if !defined(AUDIO_RELEASE)
bool AudioDebugDrawFilter(const AZStd::string_view objectName, const AZStd::string_view filter);
#endif // !AUDIO_RELEASE
///////////////////////////////////////////////////////////////////////////////////////////////////
template <typename ObjType, typename IDType = size_t>
class CInstanceManager
{
public:
~CInstanceManager() {}
using TPointerContainer = AZStd::vector<ObjType*, Audio::AudioSystemStdAllocator>;
TPointerContainer m_cReserved;
IDType m_nIDCounter;
const size_t m_nReserveSize;
const IDType m_nMinCounterValue;
CInstanceManager(const size_t nReserveSize, const IDType nMinCounterValue)
: m_nIDCounter(nMinCounterValue)
, m_nReserveSize(nReserveSize)
, m_nMinCounterValue(nMinCounterValue)
{
m_cReserved.reserve(m_nReserveSize);
}
IDType GetNextID()
{
if (m_nIDCounter >= m_nMinCounterValue)
{
return m_nIDCounter++;
}
else
{
g_audioLogger.Log(eALT_ERROR, "An AudioSystem InstanceManager ID counter wrapped around.");
m_nIDCounter = m_nMinCounterValue;
return m_nIDCounter;
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class CSmoothFloat
{
public:
explicit CSmoothFloat(const float smoothFactor, const float precision, const float initialValue = 0.0f)
: m_value(initialValue)
, m_target(initialValue)
, m_isActive(false)
, m_smoothFactor(AZ::GetAbs(smoothFactor))
, m_precision(AZ::GetAbs(precision))
{}
~CSmoothFloat() {}
void Update(const float smoothFactorOverride = -1.f)
{
if (m_isActive)
{
if (AZ::GetAbs(m_target - m_value) > m_precision)
{
// still haven't reached the target within the specified precision, smooth towards it.
const float smoothFactor = (smoothFactorOverride < 0.f) ? m_smoothFactor : smoothFactorOverride;
m_value += (m_target - m_value) / (smoothFactor * smoothFactor + 1.f);
}
else
{
// reached the target (within precision) this update, disable smoothing until a new target is set.
m_value = m_target;
m_isActive = false;
}
}
}
float GetCurrent() const
{
return m_value;
}
void SetNewTarget(const float newTarget, const bool reset = false)
{
if (reset)
{
Reset(newTarget);
}
else if (AZ::GetAbs(newTarget - m_target) > m_precision)
{
m_target = newTarget;
m_isActive = true;
}
}
void Reset(const float initialValue = 0.0f)
{
m_value = m_target = initialValue;
m_isActive = false;
}
private:
float m_value;
float m_target;
bool m_isActive;
const float m_smoothFactor;
const float m_precision;
};
/*!
* Flags
* Used for storing, checking, setting, and clearing related bits together.
*/
template<typename StoredType,
typename = AZStd::enable_if_t<AZStd::is_integral<StoredType>::value
&& AZStd::is_unsigned<StoredType>::value>>
class Flags
{
public:
Flags(const StoredType flags = 0)
: m_storedFlags(flags)
{}
void AddFlags(const StoredType flags)
{
m_storedFlags |= flags;
}
void ClearFlags(const StoredType flags)
{
m_storedFlags &= ~flags;
}
bool AreAllFlagsActive(const StoredType flags) const
{
return (m_storedFlags & flags) == flags;
}
bool AreAnyFlagsActive(const StoredType flags) const
{
return (m_storedFlags & flags) != 0;
}
bool AreMultipleFlagsActive() const
{
return (m_storedFlags & (m_storedFlags - 1)) != 0;
}
bool IsOneFlagActive() const
{
return m_storedFlags != 0 && !AreMultipleFlagsActive();
}
void ClearAllFlags()
{
m_storedFlags = 0;
}
void SetFlags(StoredType flags, const bool enable)
{
enable ? AddFlags(flags) : ClearFlags(flags);
}
StoredType GetRawFlags() const
{
return m_storedFlags;
}
bool operator==(const Flags& other) const
{
return m_storedFlags == other.m_storedFlags;
}
bool operator!=(const Flags& other) const
{
return m_storedFlags != other.m_storedFlags;
}
private:
StoredType m_storedFlags = 0;
};
} // namespace Audio