Working SFX playback

This commit is contained in:
Jack Andersen 2017-01-22 21:22:17 -10:00
parent 9701907a3a
commit afd852f1a4
13 changed files with 664 additions and 55 deletions

View File

@ -82,4 +82,27 @@ void CAudioSys::SysRemoveGroupFromAmuse(const std::string& name)
RemoveAudioGroup(set->GetAudioGroupData()); 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;
}
} }

View File

@ -19,9 +19,6 @@ CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStre
class CAudioSys class CAudioSys
{ {
static CAudioSys* g_SharedSys;
boo::IAudioVoiceEngine* m_voiceEngine;
amuse::Engine m_engine;
public: public:
enum class ESurroundModes enum class ESurroundModes
{ {
@ -30,6 +27,12 @@ public:
Surround Surround
}; };
private:
static CAudioSys* g_SharedSys;
boo::IAudioVoiceEngine* m_voiceEngine;
amuse::Engine m_engine;
public:
struct C3DEmitterParmData struct C3DEmitterParmData
{ {
zeus::CVector3f x0_pos; zeus::CVector3f x0_pos;
@ -40,7 +43,8 @@ public:
u16 x24_sfxId; u16 x24_sfxId;
float x26_maxVol; float x26_maxVol;
float x27_minVol; float x27_minVol;
u8 x28_extra[2]; u8 x28_;
u8 x29_;
}; };
CAudioSys(boo::IAudioVoiceEngine* voiceEngine, CAudioSys(boo::IAudioVoiceEngine* voiceEngine,
amuse::IBackendVoiceAllocator& backend, u8,u8,u8,u8,u32) amuse::IBackendVoiceAllocator& backend, u8,u8,u8,u8,u32)
@ -81,6 +85,11 @@ public:
static bool SysIsGroupSetLoaded(const std::string& name); static bool SysIsGroupSetLoaded(const std::string& name);
static void SysAddGroupIntoAmuse(const std::string& name); static void SysAddGroupIntoAmuse(const std::string& name);
static void SysRemoveGroupFromAmuse(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);
}; };
} }

View File

@ -6,6 +6,16 @@ namespace urde
static TLockedToken<std::vector<s16>> mpSfxTranslationTableTok; static TLockedToken<std::vector<s16>> mpSfxTranslationTableTok;
std::vector<s16>* CSfxManager::mpSfxTranslationTable = nullptr; 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, CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStream& in,
const CVParamTransfer& vparms, const CVParamTransfer& vparms,
CObjectReference* selfRef) CObjectReference* selfRef)
@ -20,14 +30,14 @@ CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStre
} }
CSfxManager::CSfxChannel CSfxManager::m_channels[4]; CSfxManager::CSfxChannel CSfxManager::m_channels[4];
rstl::reserved_vector<std::shared_ptr<CSfxManager::CSfxEmitterWrapper>, 128> CSfxManager::m_emitterWrapperPool; CSfxManager::ESfxChannels CSfxManager::m_currentChannel = CSfxManager::ESfxChannels::Default;
rstl::reserved_vector<std::shared_ptr<CSfxManager::CSfxWrapper>, 128> CSfxManager::m_wrapperPool;
CSfxManager::ESfxChannels CSfxManager::m_currentChannel;
bool CSfxManager::m_doUpdate; bool CSfxManager::m_doUpdate;
void* CSfxManager::m_usedSounds; void* CSfxManager::m_usedSounds;
bool CSfxManager::m_muted; bool CSfxManager::m_muted;
bool CSfxManager::m_auxProcessingEnabled; bool CSfxManager::m_auxProcessingEnabled = false;
float CSfxManager::m_reverbAmount = 1.f; 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::kMaxPriority;
u16 CSfxManager::kMedPriority; u16 CSfxManager::kMedPriority;
@ -38,10 +48,10 @@ bool CSfxManager::LoadTranslationTable(CSimplePool* pool, const SObjectTag* tag)
{ {
if (!tag) if (!tag)
return false; return false;
mpSfxTranslationTable = nullptr;
mpSfxTranslationTableTok = pool->GetObj(*tag); mpSfxTranslationTableTok = pool->GetObj(*tag);
if (!mpSfxTranslationTableTok) if (!mpSfxTranslationTableTok)
return false; return false;
mpSfxTranslationTable = mpSfxTranslationTableTok.GetObj();
return true; return true;
} }
@ -81,6 +91,27 @@ bool CSfxManager::CSfxWrapper::Ready()
return x24_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 bool CSfxManager::CSfxEmitterWrapper::IsPlaying() const
{ {
if (IsLooped()) if (IsLooped())
@ -138,10 +169,86 @@ CSfxManager::ESfxAudibility CSfxManager::CSfxEmitterWrapper::GetAudible(const ze
return ESfxAudibility::Aud0; return ESfxAudibility::Aud0;
} }
CSfxManager::CSfxManager() u16 CSfxManager::CSfxEmitterWrapper::GetSfxId() const
{ {
m_emitterWrapperPool.resize(128); return x24_parmData.x24_sfxId;
m_wrapperPool.resize(128); }
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, 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) u16 CSfxManager::TranslateSFXID(u16 id)
{ {
if (mpSfxTranslationTable == nullptr) if (mpSfxTranslationTable == nullptr)
@ -172,10 +320,19 @@ u16 CSfxManager::TranslateSFXID(u16 id)
return ret; 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) void CSfxManager::SfxStop(const CSfxHandle& handle)
{ {
if (handle) StopSound(handle);
handle->Stop();
} }
CSfxHandle CSfxManager::SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId) 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) if (m_muted || id == 0xffff)
return {}; return {};
std::shared_ptr<CSfxWrapper>* wrapper = AllocateCSfxWrapper(); m_doUpdate = true;
if (!wrapper) CSfxHandle wrapper = std::make_shared<CSfxWrapper>(looped, prio, id, vol, pan, useAcoustics, areaId);
return {}; CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
chanObj.x48_handles.insert(wrapper);
*wrapper = std::make_shared<CSfxWrapper>(looped, prio, id, vol, pan, useAcoustics, areaId); return wrapper;
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;
} }
void CSfxManager::StopAndRemoveAllEmitters() 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() void CSfxManager::Shutdown()
@ -219,7 +567,7 @@ void CSfxManager::Shutdown()
mpSfxTranslationTable = nullptr; mpSfxTranslationTable = nullptr;
mpSfxTranslationTableTok = TLockedToken<std::vector<s16>>{}; mpSfxTranslationTableTok = TLockedToken<std::vector<s16>>{};
StopAndRemoveAllEmitters(); StopAndRemoveAllEmitters();
DisableAuxCallbacks(); DisableAuxCallback();
} }
} }

View File

@ -13,12 +13,13 @@ class CSfxManager
{ {
static std::vector<s16>* mpSfxTranslationTable; static std::vector<s16>* mpSfxTranslationTable;
public: public:
CSfxManager();
enum class ESfxChannels enum class ESfxChannels
{ {
Zero, Invalid = -1,
One Default = 0,
Game,
PauseScreen
}; };
enum class ESfxAudibility enum class ESfxAudibility
@ -29,16 +30,37 @@ public:
Aud3 Aud3
}; };
class CSfxChannel enum class EAuxEffect
{ {
None = -1,
ReverbHi = 0,
Chorus,
ReverbStd,
Delay
}; };
class CBaseSfxWrapper; class CBaseSfxWrapper;
using CSfxHandle = std::shared_ptr<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> class CBaseSfxWrapper : public std::enable_shared_from_this<CBaseSfxWrapper>
{ {
float x4_ = 15.f; float x4_timeRemaining = 15.f;
s16 x8_rank = 0; s16 x8_rank = 0;
s16 xa_prio; s16 xa_prio;
//CSfxHandle xc_handle; //CSfxHandle xc_handle;
@ -76,10 +98,17 @@ public:
virtual bool Ready()=0; virtual bool Ready()=0;
virtual ESfxAudibility GetAudible(const zeus::CVector3f&)=0; virtual ESfxAudibility GetAudible(const zeus::CVector3f&)=0;
virtual const std::shared_ptr<amuse::Voice>& GetVoice() const=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; } 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) 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), : 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) {} 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; CAudioSys::C3DEmitterParmData x24_parmData;
std::shared_ptr<amuse::Emitter> x50_emitterHandle; std::shared_ptr<amuse::Emitter> x50_emitterHandle;
bool x54_ready = true; bool x54_ready = true;
float x55_cachedMaxVol;
public: public:
bool IsPlaying() const; bool IsPlaying() const;
void Play(); void Play();
@ -98,6 +128,10 @@ public:
bool Ready(); bool Ready();
ESfxAudibility GetAudible(const zeus::CVector3f&); ESfxAudibility GetAudible(const zeus::CVector3f&);
const std::shared_ptr<amuse::Voice>& GetVoice() const { return x50_emitterHandle->getVoice(); } 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; } const std::shared_ptr<amuse::Emitter>& GetHandle() const { return x50_emitterHandle; }
@ -120,6 +154,10 @@ public:
bool Ready(); bool Ready();
ESfxAudibility GetAudible(const zeus::CVector3f&) { return ESfxAudibility::Aud3; } ESfxAudibility GetAudible(const zeus::CVector3f&) { return ESfxAudibility::Aud3; }
const std::shared_ptr<amuse::Voice>& GetVoice() const { return x1c_voiceHandle; } 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; } void SetVolume(s16 vol) { x20_vol = vol; }
@ -130,14 +168,14 @@ public:
}; };
static CSfxChannel m_channels[4]; 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 ESfxChannels m_currentChannel;
static bool m_doUpdate; static bool m_doUpdate;
static void* m_usedSounds; static void* m_usedSounds;
static bool m_muted; static bool m_muted;
static bool m_auxProcessingEnabled; static bool m_auxProcessingEnabled;
static float m_reverbAmount; static float m_reverbAmount;
static EAuxEffect m_activeEffect;
static EAuxEffect m_nextEffect;
static u16 kMaxPriority; static u16 kMaxPriority;
static u16 kMedPriority; static u16 kMedPriority;
@ -146,9 +184,10 @@ public:
static bool LoadTranslationTable(CSimplePool* pool, const SObjectTag* tag); static bool LoadTranslationTable(CSimplePool* pool, const SObjectTag* tag);
static bool IsAuxProcessingEnabled() { return m_auxProcessingEnabled; } static bool IsAuxProcessingEnabled() { return m_auxProcessingEnabled; }
static void SetChannel(ESfxChannels) {} static void SetChannel(ESfxChannels);
static void KillAll(ESfxChannels) {} static void KillAll(ESfxChannels) {}
static void TurnOnChannel(ESfxChannels) {} static void TurnOnChannel(ESfxChannels);
static void TurnOffChannel(ESfxChannels);
static ESfxChannels GetCurrentChannel() {return m_currentChannel;} static ESfxChannels GetCurrentChannel() {return m_currentChannel;}
static void AddListener(ESfxChannels, static void AddListener(ESfxChannels,
const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CVector3f& pos, const zeus::CVector3f& dir,
@ -159,19 +198,26 @@ public:
const zeus::CVector3f& heading, const zeus::CVector3f& up, const zeus::CVector3f& heading, const zeus::CVector3f& up,
u8 vol); 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 RemoveEmitter(const CSfxHandle&) {}
static void PitchBend(const CSfxHandle&, s32) {} static void PitchBend(const CSfxHandle&, s32) {}
static u16 TranslateSFXID(u16); static u16 TranslateSFXID(u16);
static void SfxStop(const CSfxHandle& handle); static void SfxStop(const CSfxHandle& handle);
static CSfxHandle SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId); static CSfxHandle SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId);
static void StopAndRemoveAllEmitters(); 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(); static void Shutdown();
private:
static std::shared_ptr<CSfxWrapper>* AllocateCSfxWrapper();
}; };
using CSfxHandle = CSfxManager::CSfxHandle; using CSfxHandle = CSfxManager::CSfxHandle;

View File

@ -24,7 +24,7 @@ float CCameraManager::sThirdPersonFOV = 60.f;
CCameraManager::CCameraManager(TUniqueId curCameraId) : x0_curCameraId(curCameraId) 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); {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); sAspect = float(gViewport.x8_width / gViewport.xc_height);
sFirstPersonFOV = g_tweakGame->GetFirstPersonFOV(); sFirstPersonFOV = g_tweakGame->GetFirstPersonFOV();

View File

@ -18,16 +18,16 @@ CIOWin::EMessageReturn CAudioStateWin::OnMessage(const CArchitectureMessage& msg
const EArchMsgType msgType = msg.GetType(); const EArchMsgType msgType = msg.GetType();
if (msgType == EArchMsgType::SetGameState) if (msgType == EArchMsgType::SetGameState)
{ {
CSfxManager::KillAll(CSfxManager::ESfxChannels::One); CSfxManager::KillAll(CSfxManager::ESfxChannels::Game);
CSfxManager::TurnOnChannel(CSfxManager::ESfxChannels::One); CSfxManager::TurnOnChannel(CSfxManager::ESfxChannels::Game);
} }
else if (msgType == EArchMsgType::QuitGameplay) else if (msgType == EArchMsgType::QuitGameplay)
{ {
if (g_GameState->GetWorldTransitionManager()->GetTransType() == CWorldTransManager::ETransType::Disabled || if (g_GameState->GetWorldTransitionManager()->GetTransType() == CWorldTransManager::ETransType::Disabled ||
m->GetFlowState() != EFlowState::Zero) m->GetFlowState() != EFlowState::Zero)
{ {
CSfxManager::SetChannel(CSfxManager::ESfxChannels::Zero); CSfxManager::SetChannel(CSfxManager::ESfxChannels::Default);
CSfxManager::KillAll(CSfxManager::ESfxChannels::One); CSfxManager::KillAll(CSfxManager::ESfxChannels::Game);
} }
} }
return EMessageReturn::Normal; return EMessageReturn::Normal;

View File

@ -39,6 +39,10 @@ CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoi
g_GuiSys = &x44_guiSys; g_GuiSys = &x44_guiSys;
x30_inputGenerator.startScanning(); x30_inputGenerator.startScanning();
CAudioSys::SysSetVolume(0x7f);
CAudioSys::SetDefaultVolumeScale(0x75);
CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale());
CStreamAudioManager::Initialize(); CStreamAudioManager::Initialize();
m->ResetGameState(); m->ResetGameState();
@ -267,6 +271,7 @@ bool CMain::Proc()
CGBASupport::GlobalPoll(); CGBASupport::GlobalPoll();
x164_archSupport->UpdateTicks(); x164_archSupport->UpdateTicks();
x164_archSupport->Update(); x164_archSupport->Update();
CSfxManager::Update(1.f / 60.f);
CStreamAudioManager::Update(1.f / 60.f); CStreamAudioManager::Update(1.f / 60.f);
return x160_24_finished; return x160_24_finished;
} }

View File

@ -84,6 +84,7 @@ set(WORLD_SOURCES
CScriptMazeNode.hpp CScriptMazeNode.cpp CScriptMazeNode.hpp CScriptMazeNode.cpp
CScriptShadowProjector.hpp CScriptShadowProjector.cpp CScriptShadowProjector.hpp CScriptShadowProjector.cpp
CScriptStreamedMusic.hpp CScriptStreamedMusic.cpp CScriptStreamedMusic.hpp CScriptStreamedMusic.cpp
CScriptRoomAcoustics.hpp CScriptRoomAcoustics.cpp
CGrappleParameters.hpp CGrappleParameters.hpp
CActorParameters.hpp CActorParameters.hpp
CLightParameters.hpp CLightParameters.hpp

View File

@ -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);
}
}

View File

@ -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__

View File

@ -61,6 +61,7 @@
#include "MP1/CSpacePirate.hpp" #include "MP1/CSpacePirate.hpp"
#include "CScriptShadowProjector.hpp" #include "CScriptShadowProjector.hpp"
#include "CScriptStreamedMusic.hpp" #include "CScriptStreamedMusic.hpp"
#include "CScriptRoomAcoustics.hpp"
#include "CPatternedInfo.hpp" #include "CPatternedInfo.hpp"
#include "CSimplePool.hpp" #include "CSimplePool.hpp"
#include "Collision/CCollidableOBBTreeGroup.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) CEntity* ScriptLoader::LoadRoomAcoustics(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
{ {
return nullptr; 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) CEntity* ScriptLoader::LoadColorModulate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)

2
amuse

@ -1 +1 @@
Subproject commit ecd990e94e4b0e6da071cb5f0ada4f65953dda44 Subproject commit 2e7345f11d73219d77d345f3c7a039ab68be0e57

2
hecl

@ -1 +1 @@
Subproject commit e84a639ed1c213fa9e50f4f15ea43f8eb391986e Subproject commit df935c31c1f5c21519ed432c128dd7b1541cd972