prime/src/Kyoto/Audio/CSfxManager.cpp

352 lines
12 KiB
C++

#include "Kyoto/Alloc/CMemory.hpp"
#include "Kyoto/Audio/CAudioSys.hpp"
#include "Kyoto/Audio/CSfxHandle.hpp"
#include "dolphin/types.h"
#include "musyx/musyx.h"
#include "rstl/vector.hpp"
#include <Kyoto/Audio/CSfxManager.hpp>
static int lbl_805A8770 = -1;
static int lbl_805A8774 = -1;
CSfxManager::CSfxChannel CSfxManager::mChannels[4];
CSfxManager::ESfxChannels CSfxManager::mCurrentChannel = kSC_Default;
rstl::vector< short >* CSfxManager::mTranslationTable;
rstl::auto_ptr< CToken > CSfxManager::mTranslationTableTok;
rstl::reserved_vector< CSfxManager::CSfxEmitterWrapper, 64 > CSfxManager::mEmitterWrapperPool;
rstl::reserved_vector< CSfxManager::CSfxWrapper, 64 > CSfxManager::mWrapperPool;
CSfxManager::CBaseSfxWrapper::CBaseSfxWrapper(const bool looped, const short prio,
const CSfxHandle handle, const bool useAcoustics,
const int area)
: x4_timeRemaining(15.f)
, 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_isReleased(false)
, x14_29_useAcoustics(useAcoustics) {}
const bool CSfxManager::CBaseSfxWrapper::Available() const { return x14_28_isReleased; }
void CSfxManager::CBaseSfxWrapper::Release() {
x14_28_isReleased = true;
x4_timeRemaining = 15.f;
}
const float CSfxManager::CBaseSfxWrapper::GetTimeRemaining() { return x4_timeRemaining; }
void CSfxManager::CBaseSfxWrapper::SetTimeRemaining(float t) { x4_timeRemaining = t; }
void CSfxManager::CBaseSfxWrapper::SetActive(bool v) { x14_24_isActive = v; }
void CSfxManager::CBaseSfxWrapper::SetPlaying(bool v) { x14_25_isPlaying = v; }
void CSfxManager::CBaseSfxWrapper::SetInArea(bool v) { x14_27_inArea = v; }
void CSfxManager::CBaseSfxWrapper::SetRank(short v) { x8_rank = v; }
const bool CSfxManager::CBaseSfxWrapper::IsLooped() const { return x14_26_looped; }
const bool CSfxManager::CBaseSfxWrapper::IsInArea() const { return x14_27_inArea; }
bool CSfxManager::CBaseSfxWrapper::IsPlaying() const { return x14_25_isPlaying; }
const bool CSfxManager::CBaseSfxWrapper::IsActive() const { return x14_24_isActive; }
const bool CSfxManager::CBaseSfxWrapper::UseAcoustics() const { return x14_29_useAcoustics; }
const short CSfxManager::CBaseSfxWrapper::GetRank() const { return x8_rank; }
const short CSfxManager::CBaseSfxWrapper::GetPriority() const { return xa_prio; }
const CSfxHandle CSfxManager::CBaseSfxWrapper::GetSfxHandle() const { return xc_handle; }
const int CSfxManager::CBaseSfxWrapper::GetArea() const { return x10_area; }
CSfxManager::CSfxEmitterWrapper::CSfxEmitterWrapper(const bool looped, const short prio,
CAudioSys::C3DEmitterParmData& emitterData,
const CSfxHandle handle,
const bool useAcoustics, const int area)
: CBaseSfxWrapper(looped, prio, handle, useAcoustics, area)
, x24_emitterData(emitterData)
, x50_emitterHandle(SND_ID_ERROR)
, x54_ready(true) {}
void CSfxManager::CSfxEmitterWrapper::SetReverb(const char rev) {
if (CSfxManager::IsAuxProcessingEnabled() && UseAcoustics()) {
x18_para.paraData.value7 = rev;
}
}
void CSfxManager::CSfxEmitterWrapper::Play() {
x1c_parameterInfo.numPara = 1;
x1c_parameterInfo.paraArray = &x18_para;
x18_para.ctrl = SND_MIDICTRL_REVERB;
if (CSfxManager::IsAuxProcessingEnabled() && UseAcoustics()) {
x18_para.paraData.value7 = CSfxManager::GetReverbAmount();
} else {
x18_para.paraData.value7 = 0;
}
x50_emitterHandle = CAudioSys::S3dAddEmitterParaEx(x24_emitterData, GetSfxHandle().GetIndex(),
&x1c_parameterInfo);
if (x50_emitterHandle != SND_ID_ERROR) {
SetPlaying(true);
}
x54_ready = false;
}
const SND_FXID CSfxManager::CSfxEmitterWrapper::GetSfxId() { return x24_emitterData.x24_sfxId; }
void CSfxManager::CSfxEmitterWrapper::Stop() {
if (x50_emitterHandle != SND_ID_ERROR) {
CAudioSys::S3dRemoveEmitter(x50_emitterHandle);
SetPlaying(false);
x50_emitterHandle = SND_ID_ERROR;
}
}
const CAudioSys::C3DEmitterParmData& CSfxManager::CSfxEmitterWrapper::GetEmitter() {
return x24_emitterData;
}
const SND_VOICEID CSfxManager::CSfxEmitterWrapper::GetHandle() const { return x50_emitterHandle; }
bool CSfxManager::CSfxEmitterWrapper::IsPlaying() const {
if (!IsLooped()) {
bool ret = false;
if (CBaseSfxWrapper::IsPlaying() && CAudioSys::S3dCheckEmitter(x50_emitterHandle)) {
ret = true;
}
return ret;
}
return CBaseSfxWrapper::IsPlaying();
}
const bool CSfxManager::CSfxEmitterWrapper::Ready() { return IsLooped() || x54_ready; }
short CSfxManager::CSfxEmitterWrapper::GetAudible(const CVector3f& vec) {
float magSq = (x24_emitterData.x0_pos - vec).MagSquared();
float maxDist = x24_emitterData.x18_maxDist * x24_emitterData.x18_maxDist;
if (magSq < maxDist * 0.25f)
return kSA_Aud3;
else if (magSq < maxDist * 0.5f)
return kSA_Aud2;
else if (magSq < maxDist)
return kSA_Aud1;
return kSA_Aud0;
}
const SND_VOICEID CSfxManager::CSfxEmitterWrapper::GetVoice() const {
return IsPlaying() ? CAudioSys::S3dEmitterVoiceID(x50_emitterHandle) : SND_ID_ERROR;
}
void CSfxManager::CSfxEmitterWrapper::UpdateEmitterSilent() {
x55_cachedMaxVol = x24_emitterData.x26_maxVol;
CAudioSys::S3dUpdateEmitter(x50_emitterHandle, x24_emitterData.x0_pos, x24_emitterData.xc_dir, 1);
}
void CSfxManager::CSfxEmitterWrapper::UpdateEmitter() {
CAudioSys::S3dUpdateEmitter(x50_emitterHandle, x24_emitterData.x0_pos, x24_emitterData.xc_dir,
x55_cachedMaxVol);
}
CSfxManager::CSfxWrapper::CSfxWrapper(const bool looped, const short prio, const ushort sfxId,
const short vol, const short pan, const CSfxHandle handle,
const bool useAcoustics, const int area)
: CBaseSfxWrapper(looped, prio, handle, useAcoustics, area)
, x18_sfxId(sfxId)
, x1c_voiceHandle(SND_ID_ERROR)
, x20_vol(vol)
, x22_pan(pan)
, x24_ready(true) {}
void CSfxManager::CSfxWrapper::SetReverb(const char rev) {
if (CSfxManager::IsAuxProcessingEnabled() && UseAcoustics()) {
CAudioSys::SfxCtrl(x1c_voiceHandle, SND_MIDICTRL_REVERB, rev);
}
}
void CSfxManager::CSfxWrapper::Play() {
x1c_voiceHandle = CAudioSys::SfxStart(x18_sfxId, x20_vol, x22_pan, 0);
if (x1c_voiceHandle != SND_ID_ERROR) {
if (CSfxManager::IsAuxProcessingEnabled() && UseAcoustics()) {
CAudioSys::SfxCtrl(x1c_voiceHandle, SND_MIDICTRL_REVERB, CSfxManager::GetReverbAmount());
}
SetPlaying(true);
}
x24_ready = false;
}
const SND_FXID CSfxManager::CSfxWrapper::GetSfxId() { return x18_sfxId; }
void CSfxManager::CSfxWrapper::Stop() {
if (x1c_voiceHandle != SND_ID_ERROR) {
CAudioSys::SfxStop(x1c_voiceHandle);
SetPlaying(false);
x1c_voiceHandle = SND_ID_ERROR;
}
}
bool CSfxManager::CSfxWrapper::IsPlaying() const {
return CBaseSfxWrapper::IsPlaying() && CAudioSys::SfxCheck(x1c_voiceHandle) != SND_ID_ERROR;
}
const bool CSfxManager::CSfxWrapper::Ready() { return IsLooped() || x24_ready; }
short CSfxManager::CSfxWrapper::GetAudible(const CVector3f&) { return kSA_Aud3; }
const SND_VOICEID CSfxManager::CSfxWrapper::GetVoice() const { return x1c_voiceHandle; }
void CSfxManager::CSfxWrapper::SetVolume(const short vol) { x20_vol = vol; }
void CSfxManager::CSfxWrapper::UpdateEmitterSilent() { CAudioSys::SfxVolume(x1c_voiceHandle, 1); }
void CSfxManager::CSfxWrapper::UpdateEmitter() { CAudioSys::SfxVolume(x1c_voiceHandle, x20_vol); }
CSfxManager::CSfxEmitterWrapper::~CSfxEmitterWrapper() {}
void CSfxManager::Shutdown() {
delete mTranslationTable;
mTranslationTable = nullptr;
StopAndRemoveAllEmitters();
if (lbl_805A8770 != -1) {
DisableAuxCallback();
}
}
void CSfxManager::StopAndRemoveAllEmitters() {
for (int i = 0; i < 4; ++i) {
CSfxChannel* channel = &mChannels[i];
for (int j = 0; j < channel->x48_.size(); ++j) {
if (channel->x48_[j] != nullptr) {
if (channel->x48_[j]->IsPlaying()) {
channel->x48_[j]->Stop();
}
channel->x48_[j]->Release();
channel->x48_[j] = nullptr;
}
}
}
}
void CSfxManager::AddListener(ESfxChannels channel, const CVector3f& pos, const CVector3f& dir,
const CVector3f& vec1, const CVector3f& vec2, const float f1,
const float f2, const float f3, const uint w1,
const uchar maxVolume) {
CSfxChannel* chan = &mChannels[channel];
chan->x0_listener = CSfxListener(pos, dir, vec1, vec2, f1, f2, f3, w1, maxVolume);
chan->x44_ = true;
CAudioSys::S3dAddListener(pos, dir, vec1, vec2, f1, f2, f3, w1, maxVolume);
}
void CSfxManager::UpdateListener(const CVector3f& pos, const CVector3f& dir, const CVector3f& vec1,
const CVector3f& vec2, const uchar maxVolume) {
CSfxChannel* chan = &mChannels[mCurrentChannel];
chan->x0_listener.x0_ = pos;
chan->x0_listener.xc_ = dir;
chan->x0_listener.x18_ = vec1;
chan->x0_listener.x24_ = vec2;
chan->x0_listener.x40_ = maxVolume;
chan->x44_ = true;
CAudioSys::S3dUpdateListener(pos, dir, vec1, vec2, maxVolume);
}
CSfxHandle CSfxManager::AddEmitter(const SND_FXID id, const CVector3f& pos, const CVector3f& dir,
const bool useAcoustics, const bool looped, const short prio,
const int areaId) {
CAudioSys::C3DEmitterParmData emitterParm;
emitterParm.x24_sfxId = id;
emitterParm.x29_prio = prio;
emitterParm.x0_pos = pos;
emitterParm.xc_dir = dir;
return AddEmitter(emitterParm, useAcoustics, prio, looped, areaId);
}
CSfxHandle CSfxManager::AddEmitter(const SND_FXID id, const CVector3f& pos, const CVector3f& dir,
const uchar vol, const bool useAcoustics, const bool looped,
const short prio, const int areaId) {
CAudioSys::C3DEmitterParmData emitterParm(150.f, 0.1f, 1, vol > 20 ? vol : 21);
emitterParm.x0_pos = pos;
emitterParm.xc_dir = dir;
emitterParm.x24_sfxId = id;
return AddEmitter(emitterParm, useAcoustics, looped, prio, areaId);
}
CSfxHandle CSfxManager::AddEmitter(CAudioSys::C3DEmitterParmData& parmData, const bool useAcoustics,
const short prio, const bool looped, const int areaId) {}
void CSfxManager::UpdateEmitter(CSfxHandle handle, const CVector3f& pos, const CVector3f& dir,
uchar maxVol) {}
void CSfxManager::RemoveEmitter(CSfxHandle handle) { StopSound(handle); }
CSfxHandle CSfxManager::SfxStart(ushort id, short vol, short pan, bool useAcoustics, short prio,
bool looped, int areaId) {}
void CSfxManager::SfxStop(CSfxHandle handle) { StopSound(handle); }
void CSfxManager::SfxVolume(CSfxHandle handle, uchar volume) {
if (handle.GetIndex() > mChannels[mCurrentChannel].x48_.size()) {
} else {
CSfxWrapper* wrapper = (CSfxWrapper*)mChannels[mCurrentChannel].x48_[handle.GetIndex()];
if (wrapper == nullptr || wrapper->GetSfxHandle() != handle) {
return;
}
wrapper->SetVolume(volume);
if (wrapper->IsPlaying()) {
CAudioSys::SfxVolume(wrapper->GetVoice(), volume);
}
}
}
void CSfxManager::SfxSpan(CSfxHandle handle, uchar span) {}
void CSfxManager::KillAll(ESfxChannels channel) {
CSfxChannel& chan = mChannels[channel];
for (int i = 0; i < chan.x48_.size(); ++i) {
CBaseSfxWrapper* wrapper = chan.x48_[i];
if (wrapper != NULL && wrapper->IsPlaying()) {
wrapper->Stop();
}
if (wrapper) {
wrapper->Release();
}
chan.x48_[i] = nullptr;
}
}
ushort CSfxManager::TranslateSFXID(ushort id) {
if (mTranslationTable == nullptr || id >= mTranslationTable->size()) {
return -1;
}
short ret = (*mTranslationTable)[id];
if (ret < 0) {
return -1;
}
return ret;
}
#pragma inline_max_size(250)
CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& obj, CInputStream& in,
const CVParamTransfer& xfer) {
return rs_new rstl::vector< short >(in);
}
CSfxManager::CSfxWrapper::~CSfxWrapper() {}