mirror of https://github.com/AxioDL/metaforce.git
Working SFX playback
This commit is contained in:
parent
9701907a3a
commit
afd852f1a4
|
@ -82,4 +82,27 @@ void CAudioSys::SysRemoveGroupFromAmuse(const std::string& name)
|
|||
RemoveAudioGroup(set->GetAudioGroupData());
|
||||
}
|
||||
|
||||
void CAudioSys::SysSetVolume(u8 volume)
|
||||
{
|
||||
GetAmuseEngine().setVolume(volume / 127.f);
|
||||
}
|
||||
|
||||
static s16 s_VolumeScale = 0x7f;
|
||||
static s16 s_DefaultVolumeScale = 0x7f;
|
||||
|
||||
s16 CAudioSys::GetDefaultVolumeScale()
|
||||
{
|
||||
return s_DefaultVolumeScale;
|
||||
}
|
||||
|
||||
void CAudioSys::SetDefaultVolumeScale(s16 scale)
|
||||
{
|
||||
s_DefaultVolumeScale = scale;
|
||||
}
|
||||
|
||||
void CAudioSys::SetVolumeScale(s16 scale)
|
||||
{
|
||||
s_VolumeScale = scale;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,9 +19,6 @@ CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStre
|
|||
|
||||
class CAudioSys
|
||||
{
|
||||
static CAudioSys* g_SharedSys;
|
||||
boo::IAudioVoiceEngine* m_voiceEngine;
|
||||
amuse::Engine m_engine;
|
||||
public:
|
||||
enum class ESurroundModes
|
||||
{
|
||||
|
@ -30,6 +27,12 @@ public:
|
|||
Surround
|
||||
};
|
||||
|
||||
private:
|
||||
static CAudioSys* g_SharedSys;
|
||||
boo::IAudioVoiceEngine* m_voiceEngine;
|
||||
amuse::Engine m_engine;
|
||||
|
||||
public:
|
||||
struct C3DEmitterParmData
|
||||
{
|
||||
zeus::CVector3f x0_pos;
|
||||
|
@ -40,7 +43,8 @@ public:
|
|||
u16 x24_sfxId;
|
||||
float x26_maxVol;
|
||||
float x27_minVol;
|
||||
u8 x28_extra[2];
|
||||
u8 x28_;
|
||||
u8 x29_;
|
||||
};
|
||||
CAudioSys(boo::IAudioVoiceEngine* voiceEngine,
|
||||
amuse::IBackendVoiceAllocator& backend, u8,u8,u8,u8,u32)
|
||||
|
@ -81,6 +85,11 @@ public:
|
|||
static bool SysIsGroupSetLoaded(const std::string& name);
|
||||
static void SysAddGroupIntoAmuse(const std::string& name);
|
||||
static void SysRemoveGroupFromAmuse(const std::string& name);
|
||||
static void SysSetVolume(u8 volume);
|
||||
|
||||
static s16 GetDefaultVolumeScale();
|
||||
static void SetDefaultVolumeScale(s16 scale);
|
||||
static void SetVolumeScale(s16 scale);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,16 @@ namespace urde
|
|||
static TLockedToken<std::vector<s16>> mpSfxTranslationTableTok;
|
||||
std::vector<s16>* CSfxManager::mpSfxTranslationTable = nullptr;
|
||||
|
||||
static amuse::EffectReverbHiInfo s_ReverbHiQueued;
|
||||
static amuse::EffectChorusInfo s_ChorusQueued;
|
||||
static amuse::EffectReverbStdInfo s_ReverbStdQueued;
|
||||
static amuse::EffectDelayInfo s_DelayQueued;
|
||||
|
||||
static amuse::EffectReverbHi* s_ReverbHiState = nullptr;
|
||||
static amuse::EffectChorus* s_ChorusState = nullptr;
|
||||
static amuse::EffectReverbStd* s_ReverbStdState = nullptr;
|
||||
static amuse::EffectDelay* s_DelayState = nullptr;
|
||||
|
||||
CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStream& in,
|
||||
const CVParamTransfer& vparms,
|
||||
CObjectReference* selfRef)
|
||||
|
@ -20,14 +30,14 @@ CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStre
|
|||
}
|
||||
|
||||
CSfxManager::CSfxChannel CSfxManager::m_channels[4];
|
||||
rstl::reserved_vector<std::shared_ptr<CSfxManager::CSfxEmitterWrapper>, 128> CSfxManager::m_emitterWrapperPool;
|
||||
rstl::reserved_vector<std::shared_ptr<CSfxManager::CSfxWrapper>, 128> CSfxManager::m_wrapperPool;
|
||||
CSfxManager::ESfxChannels CSfxManager::m_currentChannel;
|
||||
CSfxManager::ESfxChannels CSfxManager::m_currentChannel = CSfxManager::ESfxChannels::Default;
|
||||
bool CSfxManager::m_doUpdate;
|
||||
void* CSfxManager::m_usedSounds;
|
||||
bool CSfxManager::m_muted;
|
||||
bool CSfxManager::m_auxProcessingEnabled;
|
||||
bool CSfxManager::m_auxProcessingEnabled = false;
|
||||
float CSfxManager::m_reverbAmount = 1.f;
|
||||
CSfxManager::EAuxEffect CSfxManager::m_activeEffect = CSfxManager::EAuxEffect::None;
|
||||
CSfxManager::EAuxEffect CSfxManager::m_nextEffect = CSfxManager::EAuxEffect::None;
|
||||
|
||||
u16 CSfxManager::kMaxPriority;
|
||||
u16 CSfxManager::kMedPriority;
|
||||
|
@ -38,10 +48,10 @@ bool CSfxManager::LoadTranslationTable(CSimplePool* pool, const SObjectTag* tag)
|
|||
{
|
||||
if (!tag)
|
||||
return false;
|
||||
mpSfxTranslationTable = nullptr;
|
||||
mpSfxTranslationTableTok = pool->GetObj(*tag);
|
||||
if (!mpSfxTranslationTableTok)
|
||||
return false;
|
||||
mpSfxTranslationTable = mpSfxTranslationTableTok.GetObj();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -81,6 +91,27 @@ bool CSfxManager::CSfxWrapper::Ready()
|
|||
return x24_ready;
|
||||
}
|
||||
|
||||
u16 CSfxManager::CSfxWrapper::GetSfxId() const
|
||||
{
|
||||
return x18_sfxId;
|
||||
}
|
||||
|
||||
void CSfxManager::CSfxWrapper::UpdateEmitterSilent()
|
||||
{
|
||||
x1c_voiceHandle->setVolume(1.f / 127.f);
|
||||
}
|
||||
|
||||
void CSfxManager::CSfxWrapper::UpdateEmitter()
|
||||
{
|
||||
x1c_voiceHandle->setVolume(x20_vol);
|
||||
}
|
||||
|
||||
void CSfxManager::CSfxWrapper::SetReverb(float rev)
|
||||
{
|
||||
if (IsAuxProcessingEnabled() && UseAcoustics())
|
||||
x1c_voiceHandle->setReverbVol(rev);
|
||||
}
|
||||
|
||||
bool CSfxManager::CSfxEmitterWrapper::IsPlaying() const
|
||||
{
|
||||
if (IsLooped())
|
||||
|
@ -138,10 +169,86 @@ CSfxManager::ESfxAudibility CSfxManager::CSfxEmitterWrapper::GetAudible(const ze
|
|||
return ESfxAudibility::Aud0;
|
||||
}
|
||||
|
||||
CSfxManager::CSfxManager()
|
||||
u16 CSfxManager::CSfxEmitterWrapper::GetSfxId() const
|
||||
{
|
||||
m_emitterWrapperPool.resize(128);
|
||||
m_wrapperPool.resize(128);
|
||||
return x24_parmData.x24_sfxId;
|
||||
}
|
||||
|
||||
void CSfxManager::CSfxEmitterWrapper::UpdateEmitterSilent()
|
||||
{
|
||||
x50_emitterHandle->setPos(x24_parmData.x0_pos.v);
|
||||
x50_emitterHandle->setDir(x24_parmData.xc_dir.v);
|
||||
x50_emitterHandle->setMaxVol(1.f / 127.f);
|
||||
x55_cachedMaxVol = x24_parmData.x26_maxVol;
|
||||
}
|
||||
|
||||
void CSfxManager::CSfxEmitterWrapper::UpdateEmitter()
|
||||
{
|
||||
x50_emitterHandle->setPos(x24_parmData.x0_pos.v);
|
||||
x50_emitterHandle->setDir(x24_parmData.xc_dir.v);
|
||||
x50_emitterHandle->setMaxVol(x55_cachedMaxVol);
|
||||
}
|
||||
|
||||
void CSfxManager::CSfxEmitterWrapper::SetReverb(float rev)
|
||||
{
|
||||
if (IsAuxProcessingEnabled() && UseAcoustics())
|
||||
x1a_reverb = rev;
|
||||
}
|
||||
|
||||
void CSfxManager::SetChannel(ESfxChannels chan)
|
||||
{
|
||||
if (m_currentChannel == chan)
|
||||
return;
|
||||
if (m_currentChannel != ESfxChannels::Invalid)
|
||||
TurnOffChannel(m_currentChannel);
|
||||
TurnOnChannel(chan);
|
||||
m_currentChannel = chan;
|
||||
}
|
||||
|
||||
void CSfxManager::TurnOnChannel(ESfxChannels chan)
|
||||
{
|
||||
CSfxChannel& chanObj = m_channels[int(chan)];
|
||||
m_currentChannel = chan;
|
||||
m_doUpdate = true;
|
||||
if (chanObj.x44_listenerActive)
|
||||
{
|
||||
for (const CSfxHandle& handle : chanObj.x48_handles)
|
||||
{
|
||||
handle->UpdateEmitter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSfxManager::TurnOffChannel(ESfxChannels chan)
|
||||
{
|
||||
CSfxChannel& chanObj = m_channels[int(chan)];
|
||||
for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;)
|
||||
{
|
||||
const CSfxHandle& handle = *it;
|
||||
if (handle->IsLooped())
|
||||
{
|
||||
handle->UpdateEmitterSilent();
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->Stop();
|
||||
it = chanObj.x48_handles.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;)
|
||||
{
|
||||
const CSfxHandle& handle = *it;
|
||||
if (!handle->IsLooped())
|
||||
{
|
||||
handle->Release();
|
||||
it = chanObj.x48_handles.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void CSfxManager::AddListener(ESfxChannels,
|
||||
|
@ -157,6 +264,47 @@ void CSfxManager::UpdateListener(const zeus::CVector3f& pos, const zeus::CVector
|
|||
{
|
||||
}
|
||||
|
||||
s16 CSfxManager::GetRank(CBaseSfxWrapper* sfx)
|
||||
{
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
if (!sfx->IsInArea())
|
||||
return 0;
|
||||
|
||||
s16 rank = sfx->GetPriority() / 4;
|
||||
if (sfx->IsPlaying())
|
||||
++rank;
|
||||
|
||||
if (sfx->IsLooped())
|
||||
rank -= 2;
|
||||
|
||||
if (sfx->Ready() && !sfx->IsPlaying())
|
||||
rank += 3;
|
||||
|
||||
if (chanObj.x44_listenerActive)
|
||||
{
|
||||
ESfxAudibility aud = sfx->GetAudible(chanObj.x0_pos);
|
||||
if (aud == ESfxAudibility::Aud0)
|
||||
return 0;
|
||||
rank += int(aud) / 2;
|
||||
}
|
||||
|
||||
return rank;
|
||||
}
|
||||
|
||||
void CSfxManager::ApplyReverb()
|
||||
{
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
for (const CSfxHandle& handle : chanObj.x48_handles)
|
||||
{
|
||||
handle->SetReverb(m_reverbAmount);
|
||||
}
|
||||
}
|
||||
|
||||
float CSfxManager::GetReverbAmount()
|
||||
{
|
||||
return m_reverbAmount;
|
||||
}
|
||||
|
||||
u16 CSfxManager::TranslateSFXID(u16 id)
|
||||
{
|
||||
if (mpSfxTranslationTable == nullptr)
|
||||
|
@ -172,10 +320,19 @@ u16 CSfxManager::TranslateSFXID(u16 id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void CSfxManager::StopSound(const CSfxHandle& handle)
|
||||
{
|
||||
m_doUpdate = true;
|
||||
if (handle->IsPlaying())
|
||||
handle->Stop();
|
||||
handle->Release();
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
chanObj.x48_handles.erase(handle);
|
||||
}
|
||||
|
||||
void CSfxManager::SfxStop(const CSfxHandle& handle)
|
||||
{
|
||||
if (handle)
|
||||
handle->Stop();
|
||||
StopSound(handle);
|
||||
}
|
||||
|
||||
CSfxHandle CSfxManager::SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId)
|
||||
|
@ -183,35 +340,226 @@ CSfxHandle CSfxManager::SfxStart(u16 id, float vol, float pan, bool useAcoustics
|
|||
if (m_muted || id == 0xffff)
|
||||
return {};
|
||||
|
||||
std::shared_ptr<CSfxWrapper>* wrapper = AllocateCSfxWrapper();
|
||||
if (!wrapper)
|
||||
return {};
|
||||
|
||||
*wrapper = std::make_shared<CSfxWrapper>(looped, prio, id, vol, pan, useAcoustics, areaId);
|
||||
return std::static_pointer_cast<CBaseSfxWrapper>(*wrapper);
|
||||
}
|
||||
|
||||
std::shared_ptr<CSfxManager::CSfxWrapper>* CSfxManager::AllocateCSfxWrapper()
|
||||
{
|
||||
for (std::shared_ptr<CSfxWrapper>& existing : m_wrapperPool)
|
||||
if (!existing || existing->Available())
|
||||
return &existing;
|
||||
return nullptr;
|
||||
m_doUpdate = true;
|
||||
CSfxHandle wrapper = std::make_shared<CSfxWrapper>(looped, prio, id, vol, pan, useAcoustics, areaId);
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
chanObj.x48_handles.insert(wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
void CSfxManager::StopAndRemoveAllEmitters()
|
||||
{
|
||||
|
||||
for (int i=0 ; i<4 ; ++i)
|
||||
{
|
||||
CSfxChannel& chanObj = m_channels[i];
|
||||
for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;)
|
||||
{
|
||||
const CSfxHandle& handle = *it;
|
||||
if (handle->IsPlaying())
|
||||
handle->Stop();
|
||||
handle->Release();
|
||||
it = chanObj.x48_handles.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSfxManager::DisableAuxCallbacks()
|
||||
void CSfxManager::EnableAuxCallback()
|
||||
{
|
||||
m_reverbAmount = 0.f;
|
||||
ApplyReverb();
|
||||
if (m_activeEffect != EAuxEffect::None)
|
||||
DisableAuxCallback();
|
||||
|
||||
auto studio = CAudioSys::GetAmuseEngine().getDefaultStudio();
|
||||
amuse::Submix& smix = studio->getAuxA();
|
||||
|
||||
m_activeEffect = m_nextEffect;
|
||||
switch (m_activeEffect)
|
||||
{
|
||||
case EAuxEffect::ReverbHi:
|
||||
s_ReverbHiState = &smix.makeReverbHi(s_ReverbHiQueued);
|
||||
break;
|
||||
case EAuxEffect::Chorus:
|
||||
s_ChorusState = &smix.makeChorus(s_ChorusQueued);
|
||||
break;
|
||||
case EAuxEffect::ReverbStd:
|
||||
s_ReverbStdState = &smix.makeReverbStd(s_ReverbStdQueued);
|
||||
break;
|
||||
case EAuxEffect::Delay:
|
||||
s_DelayState = &smix.makeDelay(s_DelayQueued);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_auxProcessingEnabled = true;
|
||||
}
|
||||
|
||||
void CSfxManager::Update()
|
||||
void CSfxManager::PrepareDelayCallback(const amuse::EffectDelayInfo& info)
|
||||
{
|
||||
DisableAuxProcessing();
|
||||
s_DelayQueued = info;
|
||||
m_nextEffect = EAuxEffect::Delay;
|
||||
if (m_reverbAmount == 0.f)
|
||||
EnableAuxCallback();
|
||||
}
|
||||
|
||||
void CSfxManager::PrepareReverbStdCallback(const amuse::EffectReverbStdInfo& info)
|
||||
{
|
||||
DisableAuxProcessing();
|
||||
s_ReverbStdQueued = info;
|
||||
m_nextEffect = EAuxEffect::ReverbStd;
|
||||
if (m_reverbAmount == 0.f)
|
||||
EnableAuxCallback();
|
||||
}
|
||||
|
||||
void CSfxManager::PrepareChorusCallback(const amuse::EffectChorusInfo& info)
|
||||
{
|
||||
DisableAuxProcessing();
|
||||
s_ChorusQueued = info;
|
||||
m_nextEffect = EAuxEffect::Chorus;
|
||||
if (m_reverbAmount == 0.f)
|
||||
EnableAuxCallback();
|
||||
}
|
||||
|
||||
void CSfxManager::PrepareReverbHiCallback(const amuse::EffectReverbHiInfo& info)
|
||||
{
|
||||
DisableAuxProcessing();
|
||||
s_ReverbHiQueued = info;
|
||||
m_nextEffect = EAuxEffect::ReverbHi;
|
||||
if (m_reverbAmount == 0.f)
|
||||
EnableAuxCallback();
|
||||
}
|
||||
|
||||
void CSfxManager::DisableAuxCallback()
|
||||
{
|
||||
auto studio = CAudioSys::GetAmuseEngine().getDefaultStudio();
|
||||
studio->getAuxA().clearEffects();
|
||||
|
||||
switch (m_activeEffect)
|
||||
{
|
||||
case EAuxEffect::ReverbHi:
|
||||
s_ReverbHiState = nullptr;
|
||||
break;
|
||||
case EAuxEffect::Chorus:
|
||||
s_ChorusState = nullptr;
|
||||
break;
|
||||
case EAuxEffect::ReverbStd:
|
||||
s_ReverbStdState = nullptr;
|
||||
break;
|
||||
case EAuxEffect::Delay:
|
||||
s_DelayState = nullptr;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_activeEffect = EAuxEffect::None;
|
||||
}
|
||||
|
||||
void CSfxManager::DisableAuxProcessing()
|
||||
{
|
||||
m_nextEffect = EAuxEffect::None;
|
||||
m_auxProcessingEnabled = false;
|
||||
}
|
||||
|
||||
void CSfxManager::Update(float dt)
|
||||
{
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
|
||||
for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;)
|
||||
{
|
||||
const CSfxHandle& handle = *it;
|
||||
if (!handle->IsLooped())
|
||||
{
|
||||
float timeRem = handle->GetTimeRemaining();
|
||||
handle->SetTimeRemaining(timeRem - dt);
|
||||
if (timeRem < 0.f)
|
||||
{
|
||||
handle->Stop();
|
||||
m_doUpdate = true;
|
||||
it = chanObj.x48_handles.erase(it);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
if (m_doUpdate)
|
||||
{
|
||||
std::vector<CSfxHandle> rankedSfx;
|
||||
rankedSfx.reserve(chanObj.x48_handles.size());
|
||||
for (const CSfxHandle& handle : chanObj.x48_handles)
|
||||
{
|
||||
rankedSfx.push_back(handle);
|
||||
handle->SetRank(GetRank(handle.get()));
|
||||
}
|
||||
|
||||
std::sort(rankedSfx.begin(), rankedSfx.end(),
|
||||
[](const CSfxHandle& a, const CSfxHandle& b) -> bool
|
||||
{
|
||||
return a->GetRank() < b->GetRank();
|
||||
});
|
||||
|
||||
for (int i=48 ; i<rankedSfx.size() ; ++i)
|
||||
{
|
||||
const CSfxHandle& handle = rankedSfx[i];
|
||||
if (handle->IsPlaying())
|
||||
{
|
||||
handle->Stop();
|
||||
chanObj.x48_handles.erase(handle);
|
||||
}
|
||||
}
|
||||
|
||||
for (const CSfxHandle& handle : rankedSfx)
|
||||
{
|
||||
if (handle->IsPlaying() && !handle->IsInArea())
|
||||
{
|
||||
handle->Stop();
|
||||
chanObj.x48_handles.erase(handle);
|
||||
}
|
||||
}
|
||||
|
||||
for (const CSfxHandle& handle : chanObj.x48_handles)
|
||||
{
|
||||
if (handle->IsPlaying())
|
||||
continue;
|
||||
if (handle->Ready() && handle->IsInArea())
|
||||
handle->Play();
|
||||
}
|
||||
|
||||
m_doUpdate = false;
|
||||
}
|
||||
|
||||
for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;)
|
||||
{
|
||||
const CSfxHandle& handle = *it;
|
||||
if (!handle->IsPlaying() && !handle->IsLooped())
|
||||
{
|
||||
handle->Release();
|
||||
m_doUpdate = true;
|
||||
it = chanObj.x48_handles.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
if (m_auxProcessingEnabled && m_reverbAmount < 1.f)
|
||||
{
|
||||
m_reverbAmount = std::min(1.f, dt / 0.1f + m_reverbAmount);
|
||||
ApplyReverb();
|
||||
}
|
||||
else if (!m_auxProcessingEnabled && m_reverbAmount > 0.f)
|
||||
{
|
||||
m_reverbAmount = std::max(0.f, m_reverbAmount - dt / (2.f * 0.1f));
|
||||
ApplyReverb();
|
||||
if (m_reverbAmount == 0.f)
|
||||
{
|
||||
DisableAuxCallback();
|
||||
EnableAuxCallback();
|
||||
}
|
||||
}
|
||||
|
||||
if (mpSfxTranslationTableTok.IsLoaded() && !mpSfxTranslationTable)
|
||||
mpSfxTranslationTable = mpSfxTranslationTableTok.GetObj();
|
||||
}
|
||||
|
||||
void CSfxManager::Shutdown()
|
||||
|
@ -219,7 +567,7 @@ void CSfxManager::Shutdown()
|
|||
mpSfxTranslationTable = nullptr;
|
||||
mpSfxTranslationTableTok = TLockedToken<std::vector<s16>>{};
|
||||
StopAndRemoveAllEmitters();
|
||||
DisableAuxCallbacks();
|
||||
DisableAuxCallback();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,12 +13,13 @@ class CSfxManager
|
|||
{
|
||||
static std::vector<s16>* mpSfxTranslationTable;
|
||||
public:
|
||||
CSfxManager();
|
||||
|
||||
enum class ESfxChannels
|
||||
{
|
||||
Zero,
|
||||
One
|
||||
Invalid = -1,
|
||||
Default = 0,
|
||||
Game,
|
||||
PauseScreen
|
||||
};
|
||||
|
||||
enum class ESfxAudibility
|
||||
|
@ -29,16 +30,37 @@ public:
|
|||
Aud3
|
||||
};
|
||||
|
||||
class CSfxChannel
|
||||
enum class EAuxEffect
|
||||
{
|
||||
None = -1,
|
||||
ReverbHi = 0,
|
||||
Chorus,
|
||||
ReverbStd,
|
||||
Delay
|
||||
};
|
||||
|
||||
class CBaseSfxWrapper;
|
||||
using CSfxHandle = std::shared_ptr<CBaseSfxWrapper>;
|
||||
|
||||
class CSfxChannel
|
||||
{
|
||||
friend class CSfxManager;
|
||||
zeus::CVector3f x0_pos;
|
||||
zeus::CVector3f xc_;
|
||||
zeus::CVector3f x18_;
|
||||
zeus::CVector3f x24_;
|
||||
float x30_ = 0.f;
|
||||
float x34_ = 0.f;
|
||||
float x38_ = 0.f;
|
||||
u32 x3c_ = 0;
|
||||
bool x40_ = false;
|
||||
bool x44_listenerActive = false;
|
||||
std::unordered_set<CSfxHandle> x48_handles;
|
||||
};
|
||||
|
||||
class CBaseSfxWrapper : public std::enable_shared_from_this<CBaseSfxWrapper>
|
||||
{
|
||||
float x4_ = 15.f;
|
||||
float x4_timeRemaining = 15.f;
|
||||
s16 x8_rank = 0;
|
||||
s16 xa_prio;
|
||||
//CSfxHandle xc_handle;
|
||||
|
@ -76,10 +98,17 @@ public:
|
|||
virtual bool Ready()=0;
|
||||
virtual ESfxAudibility GetAudible(const zeus::CVector3f&)=0;
|
||||
virtual const std::shared_ptr<amuse::Voice>& GetVoice() const=0;
|
||||
virtual u16 GetSfxId() const=0;
|
||||
virtual void UpdateEmitterSilent()=0;
|
||||
virtual void UpdateEmitter()=0;
|
||||
virtual void SetReverb(float rev)=0;
|
||||
|
||||
void Release() { x14_28_available = true; }
|
||||
void Release() { x14_28_available = true; x4_timeRemaining = 15.f; }
|
||||
bool Available() const { return x14_28_available; }
|
||||
|
||||
float GetTimeRemaining() const { return x4_timeRemaining; }
|
||||
void SetTimeRemaining(float t) { x4_timeRemaining = t; }
|
||||
|
||||
CBaseSfxWrapper(bool looped, s16 prio, /*const CSfxHandle& handle,*/ bool useAcoustics, TAreaId area)
|
||||
: x8_rank(0), xa_prio(prio), /*xc_handle(handle),*/ x10_area(area), x14_24_isActive(true), x14_25_isPlaying(false),
|
||||
x14_26_looped(looped), x14_27_inArea(true), x14_28_available(false), x14_29_useAcoustics(useAcoustics) {}
|
||||
|
@ -91,6 +120,7 @@ public:
|
|||
CAudioSys::C3DEmitterParmData x24_parmData;
|
||||
std::shared_ptr<amuse::Emitter> x50_emitterHandle;
|
||||
bool x54_ready = true;
|
||||
float x55_cachedMaxVol;
|
||||
public:
|
||||
bool IsPlaying() const;
|
||||
void Play();
|
||||
|
@ -98,6 +128,10 @@ public:
|
|||
bool Ready();
|
||||
ESfxAudibility GetAudible(const zeus::CVector3f&);
|
||||
const std::shared_ptr<amuse::Voice>& GetVoice() const { return x50_emitterHandle->getVoice(); }
|
||||
u16 GetSfxId() const;
|
||||
void UpdateEmitterSilent();
|
||||
void UpdateEmitter();
|
||||
void SetReverb(float rev);
|
||||
|
||||
const std::shared_ptr<amuse::Emitter>& GetHandle() const { return x50_emitterHandle; }
|
||||
|
||||
|
@ -120,6 +154,10 @@ public:
|
|||
bool Ready();
|
||||
ESfxAudibility GetAudible(const zeus::CVector3f&) { return ESfxAudibility::Aud3; }
|
||||
const std::shared_ptr<amuse::Voice>& GetVoice() const { return x1c_voiceHandle; }
|
||||
u16 GetSfxId() const;
|
||||
void UpdateEmitterSilent();
|
||||
void UpdateEmitter();
|
||||
void SetReverb(float rev);
|
||||
|
||||
void SetVolume(s16 vol) { x20_vol = vol; }
|
||||
|
||||
|
@ -130,14 +168,14 @@ public:
|
|||
};
|
||||
|
||||
static CSfxChannel m_channels[4];
|
||||
static rstl::reserved_vector<std::shared_ptr<CSfxEmitterWrapper>, 128> m_emitterWrapperPool;
|
||||
static rstl::reserved_vector<std::shared_ptr<CSfxWrapper>, 128> m_wrapperPool;
|
||||
static ESfxChannels m_currentChannel;
|
||||
static bool m_doUpdate;
|
||||
static void* m_usedSounds;
|
||||
static bool m_muted;
|
||||
static bool m_auxProcessingEnabled;
|
||||
static float m_reverbAmount;
|
||||
static EAuxEffect m_activeEffect;
|
||||
static EAuxEffect m_nextEffect;
|
||||
|
||||
static u16 kMaxPriority;
|
||||
static u16 kMedPriority;
|
||||
|
@ -146,9 +184,10 @@ public:
|
|||
|
||||
static bool LoadTranslationTable(CSimplePool* pool, const SObjectTag* tag);
|
||||
static bool IsAuxProcessingEnabled() { return m_auxProcessingEnabled; }
|
||||
static void SetChannel(ESfxChannels) {}
|
||||
static void SetChannel(ESfxChannels);
|
||||
static void KillAll(ESfxChannels) {}
|
||||
static void TurnOnChannel(ESfxChannels) {}
|
||||
static void TurnOnChannel(ESfxChannels);
|
||||
static void TurnOffChannel(ESfxChannels);
|
||||
static ESfxChannels GetCurrentChannel() {return m_currentChannel;}
|
||||
static void AddListener(ESfxChannels,
|
||||
const zeus::CVector3f& pos, const zeus::CVector3f& dir,
|
||||
|
@ -159,19 +198,26 @@ public:
|
|||
const zeus::CVector3f& heading, const zeus::CVector3f& up,
|
||||
u8 vol);
|
||||
|
||||
static void StopSound(const CSfxHandle& handle);
|
||||
static s16 GetRank(CBaseSfxWrapper* sfx);
|
||||
static void ApplyReverb();
|
||||
static float GetReverbAmount();
|
||||
static void RemoveEmitter(const CSfxHandle&) {}
|
||||
static void PitchBend(const CSfxHandle&, s32) {}
|
||||
static u16 TranslateSFXID(u16);
|
||||
static void SfxStop(const CSfxHandle& handle);
|
||||
static CSfxHandle SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId);
|
||||
static void StopAndRemoveAllEmitters();
|
||||
static void DisableAuxCallbacks();
|
||||
static void DisableAuxCallback();
|
||||
static void EnableAuxCallback();
|
||||
static void PrepareDelayCallback(const amuse::EffectDelayInfo& info);
|
||||
static void PrepareReverbStdCallback(const amuse::EffectReverbStdInfo& info);
|
||||
static void PrepareChorusCallback(const amuse::EffectChorusInfo& info);
|
||||
static void PrepareReverbHiCallback(const amuse::EffectReverbHiInfo& info);
|
||||
static void DisableAuxProcessing();
|
||||
|
||||
static void Update();
|
||||
static void Update(float dt);
|
||||
static void Shutdown();
|
||||
|
||||
private:
|
||||
static std::shared_ptr<CSfxWrapper>* AllocateCSfxWrapper();
|
||||
};
|
||||
|
||||
using CSfxHandle = CSfxManager::CSfxHandle;
|
||||
|
|
|
@ -24,7 +24,7 @@ float CCameraManager::sThirdPersonFOV = 60.f;
|
|||
|
||||
CCameraManager::CCameraManager(TUniqueId curCameraId) : x0_curCameraId(curCameraId)
|
||||
{
|
||||
CSfxManager::AddListener(CSfxManager::ESfxChannels::One, zeus::CVector3f::skZero, zeus::CVector3f::skZero,
|
||||
CSfxManager::AddListener(CSfxManager::ESfxChannels::Game, zeus::CVector3f::skZero, zeus::CVector3f::skZero,
|
||||
{1.f, 0.f, 0.f}, {0.f, 0.f, 1.f}, 50.f, 50.f, 1000.f, 1, 0x7f);
|
||||
sAspect = float(gViewport.x8_width / gViewport.xc_height);
|
||||
sFirstPersonFOV = g_tweakGame->GetFirstPersonFOV();
|
||||
|
|
|
@ -18,16 +18,16 @@ CIOWin::EMessageReturn CAudioStateWin::OnMessage(const CArchitectureMessage& msg
|
|||
const EArchMsgType msgType = msg.GetType();
|
||||
if (msgType == EArchMsgType::SetGameState)
|
||||
{
|
||||
CSfxManager::KillAll(CSfxManager::ESfxChannels::One);
|
||||
CSfxManager::TurnOnChannel(CSfxManager::ESfxChannels::One);
|
||||
CSfxManager::KillAll(CSfxManager::ESfxChannels::Game);
|
||||
CSfxManager::TurnOnChannel(CSfxManager::ESfxChannels::Game);
|
||||
}
|
||||
else if (msgType == EArchMsgType::QuitGameplay)
|
||||
{
|
||||
if (g_GameState->GetWorldTransitionManager()->GetTransType() == CWorldTransManager::ETransType::Disabled ||
|
||||
m->GetFlowState() != EFlowState::Zero)
|
||||
{
|
||||
CSfxManager::SetChannel(CSfxManager::ESfxChannels::Zero);
|
||||
CSfxManager::KillAll(CSfxManager::ESfxChannels::One);
|
||||
CSfxManager::SetChannel(CSfxManager::ESfxChannels::Default);
|
||||
CSfxManager::KillAll(CSfxManager::ESfxChannels::Game);
|
||||
}
|
||||
}
|
||||
return EMessageReturn::Normal;
|
||||
|
|
|
@ -39,6 +39,10 @@ CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoi
|
|||
|
||||
g_GuiSys = &x44_guiSys;
|
||||
x30_inputGenerator.startScanning();
|
||||
|
||||
CAudioSys::SysSetVolume(0x7f);
|
||||
CAudioSys::SetDefaultVolumeScale(0x75);
|
||||
CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale());
|
||||
CStreamAudioManager::Initialize();
|
||||
m->ResetGameState();
|
||||
|
||||
|
@ -267,6 +271,7 @@ bool CMain::Proc()
|
|||
CGBASupport::GlobalPoll();
|
||||
x164_archSupport->UpdateTicks();
|
||||
x164_archSupport->Update();
|
||||
CSfxManager::Update(1.f / 60.f);
|
||||
CStreamAudioManager::Update(1.f / 60.f);
|
||||
return x160_24_finished;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ set(WORLD_SOURCES
|
|||
CScriptMazeNode.hpp CScriptMazeNode.cpp
|
||||
CScriptShadowProjector.hpp CScriptShadowProjector.cpp
|
||||
CScriptStreamedMusic.hpp CScriptStreamedMusic.cpp
|
||||
CScriptRoomAcoustics.hpp CScriptRoomAcoustics.cpp
|
||||
CGrappleParameters.hpp
|
||||
CActorParameters.hpp
|
||||
CLightParameters.hpp
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
#include "CScriptRoomAcoustics.hpp"
|
||||
#include "TCastTo.hpp"
|
||||
#include "Audio/CSfxManager.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
static TAreaId s_ActiveAcousticsAreaId = kInvalidAreaId;
|
||||
|
||||
CScriptRoomAcoustics::CScriptRoomAcoustics(TUniqueId uid, const std::string& name,
|
||||
const CEntityInfo& info, bool active, u32 volScale,
|
||||
bool revHi, bool revHiDis, float revHiColoration, float revHiMix,
|
||||
float revHiTime, float revHiDamping, float revHiPreDelay, float revHiCrosstalk,
|
||||
bool chorus, float baseDelay, float variation, float period,
|
||||
bool revStd, bool revStdDis, float revStdColoration, float revStdMix,
|
||||
float revStdTime, float revStdDamping, float revStdPreDelay,
|
||||
bool delay, u32 delayL, u32 delayR, u32 delayS,
|
||||
u32 feedbackL, u32 feedbackR, u32 feedbackS,
|
||||
u32 outputL, u32 outputR, u32 outputS)
|
||||
: CEntity(uid, info, active, name), x34_volumeScale(volScale),
|
||||
x38_revHi(revHi), x39_revHiDis(revHiDis),
|
||||
x3c_revHiInfo(revHiColoration, revHiMix, revHiTime, revHiDamping, revHiPreDelay, revHiCrosstalk),
|
||||
x54_chorus(chorus), x58_chorusInfo(baseDelay, variation, period),
|
||||
x64_revStd(revStd), x65_revStdDis(revStdDis),
|
||||
x68_revStdInfo(revStdColoration, revStdMix, revStdTime, revStdDamping, revStdPreDelay),
|
||||
x7c_delay(delay), x80_delayInfo(delayL, delayR, delayS, feedbackL, feedbackR, feedbackS, outputL, outputR, outputS)
|
||||
{}
|
||||
|
||||
void CScriptRoomAcoustics::DisableAuxCallbacks()
|
||||
{
|
||||
CSfxManager::DisableAuxProcessing();
|
||||
s_ActiveAcousticsAreaId = kInvalidAreaId;
|
||||
CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale());
|
||||
}
|
||||
|
||||
void CScriptRoomAcoustics::EnableAuxCallbacks()
|
||||
{
|
||||
if (!x30_24_active)
|
||||
return;
|
||||
|
||||
bool applied = true;
|
||||
if (x38_revHi)
|
||||
CSfxManager::PrepareReverbHiCallback(x3c_revHiInfo);
|
||||
else if (x54_chorus)
|
||||
CSfxManager::PrepareChorusCallback(x58_chorusInfo);
|
||||
else if (x64_revStd)
|
||||
CSfxManager::PrepareReverbStdCallback(x68_revStdInfo);
|
||||
else if (x7c_delay)
|
||||
CSfxManager::PrepareDelayCallback(x80_delayInfo);
|
||||
else
|
||||
applied = false;
|
||||
|
||||
if (applied)
|
||||
CAudioSys::SetVolumeScale(x34_volumeScale);
|
||||
s_ActiveAcousticsAreaId = x4_areaId;
|
||||
}
|
||||
|
||||
void CScriptRoomAcoustics::Think(float dt, CStateManager& stateMgr)
|
||||
{
|
||||
/* Intentionally empty */
|
||||
}
|
||||
|
||||
void CScriptRoomAcoustics::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr)
|
||||
{
|
||||
CEntity::AcceptScriptMsg(msg, objId, stateMgr);
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case EScriptObjectMessage::Activate:
|
||||
EnableAuxCallbacks();
|
||||
break;
|
||||
case EScriptObjectMessage::Deactivate:
|
||||
if (s_ActiveAcousticsAreaId == x4_areaId)
|
||||
{
|
||||
s_ActiveAcousticsAreaId = kInvalidAreaId;
|
||||
CSfxManager::DisableAuxProcessing();
|
||||
CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale());
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void CScriptRoomAcoustics::Accept(IVisitor& visitor)
|
||||
{
|
||||
visitor.Visit(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef __URDE_CSCRIPTROOMACOUSTICS_HPP__
|
||||
#define __URDE_CSCRIPTROOMACOUSTICS_HPP__
|
||||
|
||||
#include "CEntity.hpp"
|
||||
#include "amuse/EffectChorus.hpp"
|
||||
#include "amuse/EffectDelay.hpp"
|
||||
#include "amuse/EffectReverb.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
class CScriptRoomAcoustics : public CEntity
|
||||
{
|
||||
u32 x34_volumeScale;
|
||||
|
||||
bool x38_revHi, x39_revHiDis;
|
||||
amuse::EffectReverbHiInfo x3c_revHiInfo;
|
||||
|
||||
bool x54_chorus;
|
||||
amuse::EffectChorusInfo x58_chorusInfo;
|
||||
|
||||
bool x64_revStd, x65_revStdDis;
|
||||
amuse::EffectReverbStdInfo x68_revStdInfo;
|
||||
|
||||
bool x7c_delay;
|
||||
amuse::EffectDelayInfo x80_delayInfo;
|
||||
|
||||
void EnableAuxCallbacks();
|
||||
|
||||
public:
|
||||
CScriptRoomAcoustics(TUniqueId uid, const std::string& name,
|
||||
const CEntityInfo& info, bool active, u32 volScale,
|
||||
bool revHi, bool revHiDis, float revHiColoration, float revHiMix,
|
||||
float revHiTime, float revHiDamping, float revHiPreDelay, float revHiCrosstalk,
|
||||
bool chorus, float baseDelay, float variation, float period,
|
||||
bool revStd, bool revStdDis, float revStdColoration, float revStdMix,
|
||||
float revStdTime, float revStdDamping, float revStdPreDelay,
|
||||
bool delay, u32 delayL, u32 delayR, u32 delayS,
|
||||
u32 feedbackL, u32 feedbackR, u32 feedbackS,
|
||||
u32 outputL, u32 outputR, u32 outputS);
|
||||
void Think(float dt, CStateManager& stateMgr);
|
||||
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr);
|
||||
void Accept(IVisitor& visitor);
|
||||
|
||||
static void DisableAuxCallbacks();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __URDE_CSCRIPTROOMACOUSTICS_HPP__
|
|
@ -61,6 +61,7 @@
|
|||
#include "MP1/CSpacePirate.hpp"
|
||||
#include "CScriptShadowProjector.hpp"
|
||||
#include "CScriptStreamedMusic.hpp"
|
||||
#include "CScriptRoomAcoustics.hpp"
|
||||
#include "CPatternedInfo.hpp"
|
||||
#include "CSimplePool.hpp"
|
||||
#include "Collision/CCollidableOBBTreeGroup.hpp"
|
||||
|
@ -1761,7 +1762,44 @@ CEntity* ScriptLoader::LoadFlaahgraTentacle(CStateManager& mgr, CInputStream& in
|
|||
|
||||
CEntity* ScriptLoader::LoadRoomAcoustics(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
||||
{
|
||||
if (!EnsurePropertyCount(propCount, 32, "RoomAcoustics"))
|
||||
return nullptr;
|
||||
|
||||
std::string name = mgr.HashInstanceName(in);
|
||||
bool a = in.readBool();
|
||||
u32 b = in.readUint32Big();
|
||||
bool c = in.readBool();
|
||||
bool d = in.readBool();
|
||||
float e = in.readFloatBig();
|
||||
float f = in.readFloatBig();
|
||||
float g = in.readFloatBig();
|
||||
float h = in.readFloatBig();
|
||||
float i = in.readFloatBig();
|
||||
float j = in.readFloatBig();
|
||||
bool k = in.readBool();
|
||||
float l = in.readFloatBig();
|
||||
float m = in.readFloatBig();
|
||||
float n = in.readFloatBig();
|
||||
bool o = in.readBool();
|
||||
bool p = in.readBool();
|
||||
float q = in.readFloatBig();
|
||||
float r = in.readFloatBig();
|
||||
float s = in.readFloatBig();
|
||||
float t = in.readFloatBig();
|
||||
float u = in.readFloatBig();
|
||||
bool v = in.readBool();
|
||||
u32 w = in.readUint32Big();
|
||||
u32 x = in.readUint32Big();
|
||||
u32 y = in.readUint32Big();
|
||||
u32 z = in.readUint32Big();
|
||||
u32 _a = in.readUint32Big();
|
||||
u32 _b = in.readUint32Big();
|
||||
u32 _c = in.readUint32Big();
|
||||
u32 _d = in.readUint32Big();
|
||||
u32 _e = in.readUint32Big();
|
||||
|
||||
return new CScriptRoomAcoustics(mgr.AllocateUniqueId(), name, info, a, b, c, d, e, f, g, h, i, j,
|
||||
k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, _a, _b, _c, _d, _e);
|
||||
}
|
||||
|
||||
CEntity* ScriptLoader::LoadColorModulate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
||||
|
|
2
amuse
2
amuse
|
@ -1 +1 @@
|
|||
Subproject commit ecd990e94e4b0e6da071cb5f0ada4f65953dda44
|
||||
Subproject commit 2e7345f11d73219d77d345f3c7a039ab68be0e57
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit e84a639ed1c213fa9e50f4f15ea43f8eb391986e
|
||||
Subproject commit df935c31c1f5c21519ed432c128dd7b1541cd972
|
Loading…
Reference in New Issue