#include "d/snd/d_snd_control_player_mgr.h" #include "common.h" #include "d/snd/d_snd_bgm_mgr.h" #include "d/snd/d_snd_control_player.h" #include "d/snd/d_snd_mgr.h" #include "d/snd/d_snd_player_mgr.h" #include "d/snd/d_snd_state_mgr.h" #include "nw4r/snd/snd_SoundHandle.h" #include "nw4r/ut/ut_list.h" struct FanfareMuteFlagsApplier { ~FanfareMuteFlagsApplier() {} virtual void operator()(nw4r::snd::SoundHandle &handle) { // The logic here is inverted compared to the others - Fanfares seem to // mute things by default unless otherwise speciefied u32 id = handle.GetId(); if (dSndBgmMgr_c::GetInstance()->getSoundHandleCurrentlyPlayingFanSound(id)) { u32 userParam = dSndMgr_c::GetInstance()->getArchive()->GetSoundUserParam(id); if (!(userParam & dSndPlayerMgr_c::FANFARE_UNMUTE_BGM)) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_BGM, dSndControlPlayerMgr_c::MUTE_FULL ); dSndControlPlayerMgr_c::GetInstance()->setBgmVolumeDecreaseSpeed(0.2f); } if (dSndStateMgr_c::GetInstance()->isInEvent()) { if (!(userParam & dSndPlayerMgr_c::FANFARE_UNMUTE_STAGE_EFFECTS)) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_STAGE_EFFECTS, dSndControlPlayerMgr_c::MUTE_FULL ); } if (!(userParam & dSndPlayerMgr_c::FANFARE_UNMUTE_ENEMY)) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_ENEMY, dSndControlPlayerMgr_c::MUTE_FULL ); } if (!(userParam & dSndPlayerMgr_c::FANFARE_UNMUTE_OBJECTS)) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_OBJECTS, dSndControlPlayerMgr_c::MUTE_FULL ); } } } }; }; struct SmallMuteFlagsApplier { ~SmallMuteFlagsApplier() {} virtual void operator()(nw4r::snd::SoundHandle &handle) { u32 userParam = dSndMgr_c::GetInstance()->getArchive()->GetSoundUserParam(handle.GetId()); if (userParam & dSndPlayerMgr_c::MUTE_BGM_FULL) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_BGM, dSndControlPlayerMgr_c::MUTE_FULL ); } else if (userParam & dSndPlayerMgr_c::MUTE_BGM_PART) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_BGM, dSndControlPlayerMgr_c::MUTE_PARTIAL ); } if (userParam & dSndPlayerMgr_c::MUTE_STAGE_EFFECTS_FULL) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_STAGE_EFFECTS, dSndControlPlayerMgr_c::MUTE_FULL ); } else if (userParam & dSndPlayerMgr_c::MUTE_STAGE_EFFECTS_PART) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_STAGE_EFFECTS, dSndControlPlayerMgr_c::MUTE_PARTIAL ); } if (userParam & dSndPlayerMgr_c::MUTE_ENEMY_FULL) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_ENEMY, dSndControlPlayerMgr_c::MUTE_FULL ); } else if (userParam & dSndPlayerMgr_c::MUTE_ENEMY_PART) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_ENEMY, dSndControlPlayerMgr_c::MUTE_PARTIAL ); } if (userParam & dSndPlayerMgr_c::MUTE_OBJECTS_FULL) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_OBJECTS, dSndControlPlayerMgr_c::MUTE_FULL ); } else if (userParam & dSndPlayerMgr_c::MUTE_OBJECTS_PART) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_OBJECTS, dSndControlPlayerMgr_c::MUTE_PARTIAL ); } }; }; struct EventMuteFlagsApplier { ~EventMuteFlagsApplier() {} virtual void operator()(nw4r::snd::SoundHandle &handle) { u32 userParam = dSndPlayerMgr_c::GetInstance()->getEventMuteMask(handle.GetId()); if (userParam & dSndPlayerMgr_c::MUTE_BGM_FULL) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_BGM, dSndControlPlayerMgr_c::MUTE_FULL ); } else if (userParam & dSndPlayerMgr_c::MUTE_BGM_PART) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_BGM, dSndControlPlayerMgr_c::MUTE_PARTIAL ); } if (userParam & dSndPlayerMgr_c::MUTE_STAGE_EFFECTS_FULL) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_STAGE_EFFECTS, dSndControlPlayerMgr_c::MUTE_FULL ); } else if (userParam & dSndPlayerMgr_c::MUTE_STAGE_EFFECTS_PART) { dSndControlPlayerMgr_c::GetInstance()->setGroupVolumeFlag( dSndControlPlayerMgr_c::CTRL_GROUP_STAGE_EFFECTS, dSndControlPlayerMgr_c::MUTE_PARTIAL ); } }; }; static FanfareMuteFlagsApplier fanfareApplier; static SmallMuteFlagsApplier smallApplier; static EventMuteFlagsApplier eventApplier; SND_DISPOSER_DEFINE(dSndControlPlayerMgr_c); dSndControlPlayerMgr_c::dSndControlPlayerMgr_c() : mOverrideVolumeMask(0) { // TODO offsetof nw4r::ut::List_Init(&mActiveControls, 0x24); mpCtrls[CTRL_VOLUME] = new dSndControlPlayerVolume_c[sNumPlayers](); mpCtrls[CTRL_LPF_FREQ] = new dSndControlPlayerLpfFreq_c[sNumPlayers](); mpCtrls[CTRL_FX_SEND] = new dSndControlPlayerFxSend_c[sNumPlayers](); mpSavedVolumes = new f32[sNumPlayers]; mpTargetVolumes = new f32[sNumPlayers]; mpMaxVolumeDecreases = new f32[sNumPlayers]; mpMaxVolumeIncreases = new f32[sNumPlayers]; } void dSndControlPlayerMgr_c::calc() { calcMuteFlags(); calcVolumes(); executeControls(); } void dSndControlPlayerMgr_c::executeControls() { dSndControlPlayer_c *next; dSndControlPlayer_c *iter = static_cast(nw4r::ut::List_GetFirst(&mActiveControls)); while (iter != nullptr) { next = static_cast(nw4r::ut::List_GetNext(&mActiveControls, iter)); iter->calc(); iter->apply(); if (iter->isFinished()) { unlinkCtrl(iter); } iter = next; } } void dSndControlPlayerMgr_c::calcVolumes() { for (int i = 0; i < sNumPlayers; i++) { if ((mOverrideVolumeMask & (1 << i)) != 0) { // overridden volume mpTargetVolumes[i] = mpSavedVolumes[i]; } else { // not overridden. f32 currentVolume = getAppliedPlayerVolume(i); f32 targetVolume = mpTargetVolumes[i]; f32 maxVolumeDecrease = mpMaxVolumeDecreases[i]; f32 maxVolumeIncrease = mpMaxVolumeIncreases[i]; if (currentVolume != targetVolume) { if (currentVolume - targetVolume > maxVolumeDecrease) { targetVolume = currentVolume - maxVolumeDecrease; } else if (targetVolume - currentVolume > maxVolumeIncrease) { targetVolume = currentVolume + maxVolumeIncrease; } // @bug not actually clamped (void)nw4r::ut::Clamp(targetVolume, 0.0f, 2.0f); setVolume(i, targetVolume, 0); } mpTargetVolumes[i] = 1.0f; mpMaxVolumeDecreases[i] = 0.1f; mpMaxVolumeIncreases[i] = 0.025f; } } } void dSndControlPlayerMgr_c::calcMuteFlags() { getPlayer1(dSndPlayerMgr_c::PLAYER_FAN)->ForEachSound(fanfareApplier, false); getPlayer1(dSndPlayerMgr_c::PLAYER_SMALL_IMPORTANT)->ForEachSound(smallApplier, false); getPlayer1(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL)->ForEachSound(smallApplier, false); getPlayer1(dSndPlayerMgr_c::PLAYER_EVENT)->ForEachSound(eventApplier, false); f32 volumesByGroup[CTRL_GROUP_MAX]; for (int i = 0; i < CTRL_GROUP_MAX; i++) { volumesByGroup[i] = 1.0f; if (mTimersForGroupVolume[i][MUTE_PARTIAL] > 0) { mTimersForGroupVolume[i][MUTE_PARTIAL]--; volumesByGroup[i] = 0.3f; } if (mTimersForGroupVolume[i][MUTE_FULL] > 0) { mTimersForGroupVolume[i][MUTE_FULL]--; volumesByGroup[i] = 0.0f; } } if (volumesByGroup[CTRL_GROUP_BGM] < 1.0f) { setBgmMuteVolume(volumesByGroup[CTRL_GROUP_BGM]); } if (volumesByGroup[CTRL_GROUP_STAGE_EFFECTS] < 1.0f) { setStageEffectsMuteVolume(volumesByGroup[CTRL_GROUP_STAGE_EFFECTS]); } if (volumesByGroup[CTRL_GROUP_ENEMY] < 1.0f) { setEnemyMuteVolume(volumesByGroup[CTRL_GROUP_ENEMY]); } if (volumesByGroup[CTRL_GROUP_OBJECTS] < 1.0f) { setObjectMuteVolume(volumesByGroup[CTRL_GROUP_OBJECTS]); } } void dSndControlPlayerMgr_c::linkCtrl(dSndControlPlayer_c *ctrl) { if (ctrl == nullptr) { return; } if (ctrl->isLinked()) { return; } ctrl->setLinked(true); nw4r::ut::List_Append(&mActiveControls, ctrl); } void dSndControlPlayerMgr_c::unlinkCtrl(dSndControlPlayer_c *ctrl) { if (ctrl == nullptr) { return; } if (!ctrl->isLinked()) { return; } ctrl->setLinked(false); nw4r::ut::List_Remove(&mActiveControls, ctrl); } void dSndControlPlayerMgr_c::setVolume(u32 playerIdx, f32 value, s32 frames) { if (playerIdx >= sNumPlayers) { return; } u32 mask = (1 << playerIdx); if ((mOverrideVolumeMask & mask) != 0) { // Volume is overridden, set saved volume as to not interrupt override mpSavedVolumes[playerIdx] = value; setPlayerVolumeInternal(playerIdx, value); } else { // Volume is not overridden, set volume normally setControlValue(CTRL_VOLUME, playerIdx, value, frames); mpSavedVolumes[playerIdx] = getControlTarget(CTRL_VOLUME, playerIdx); } } void dSndControlPlayerMgr_c::overrideVolume(u32 playerIdx, f32 volume, s32 frames) { if (playerIdx >= sNumPlayers) { return; } u32 mask = (1 << playerIdx); if ((mOverrideVolumeMask & mask) == 0) { mpSavedVolumes[playerIdx] = getControlTarget(CTRL_VOLUME, playerIdx); mOverrideVolumeMask |= mask; } setControlValue(CTRL_VOLUME, playerIdx, volume, frames); } void dSndControlPlayerMgr_c::restoreVolume(u32 playerIdx, s32 frames) { if (playerIdx >= sNumPlayers) { return; } u32 mask = (1 << playerIdx); if ((mOverrideVolumeMask & mask) == 0) { return; } mOverrideVolumeMask &= ~mask; setControlValue(CTRL_VOLUME, playerIdx, mpSavedVolumes[playerIdx], frames); } void dSndControlPlayerMgr_c::setLpfFreq(u32 playerIdx, f32 value, s32 frames) { if (playerIdx < sNumPlayers) { setControlValue(CTRL_LPF_FREQ, playerIdx, value, frames); } } void dSndControlPlayerMgr_c::setFxSend(u32 playerIdx, f32 value, s32 frames) { if (playerIdx < sNumPlayers) { setControlValue(CTRL_FX_SEND, playerIdx, value, frames); } } void dSndControlPlayerMgr_c::setControlValue(PlayerCtrl_e ctrlType, u32 playerIdx, f32 value, s32 frames) { if (ctrlType < CTRL_MAX && playerIdx < sNumPlayers) { dSndControlPlayer_c *ctrl = &mpCtrls[ctrlType][playerIdx]; ctrl->set(value, frames); if (ctrl->isFinished()) { unlinkCtrl(ctrl); } else { linkCtrl(ctrl); } ctrl->apply(); } } void dSndControlPlayerMgr_c::resetControls() { for (s32 i = 0; i < sNumPlayers; i++) { for (s32 ty = 0; ty < CTRL_MAX; ty++) { mpCtrls[ty][i].reset(); } mpSavedVolumes[i] = 1.0f; } mOverrideVolumeMask = 0; } f32 dSndControlPlayerMgr_c::getAppliedPlayerVolume(u32 playerIdx) const { if (playerIdx >= sNumPlayers) { return 0.0f; } return getPlayer1(playerIdx)->GetVolume(); } f32 dSndControlPlayerMgr_c::getControlTarget(PlayerCtrl_e ctrlType, u32 playerIdx) const { if (ctrlType >= CTRL_MAX) { return 1.0f; } if (playerIdx >= sNumPlayers) { return 1.0f; } return mpCtrls[ctrlType][playerIdx].getTargetValue(); } // TODO - not sure what this actually does void dSndControlPlayerMgr_c::unmutePlayer(u32 idx, s32 frames) { if (idx >= sNumPlayers) { return; } restoreVolume(idx, 0); overrideVolume(idx, 0.0f, 0); restoreVolume(idx, frames); } void dSndControlPlayerMgr_c::unmuteScenePlayers(s32 frames) { for (u32 i = dSndPlayerMgr_c::PLAYER_ENEMY; i < dSndPlayerMgr_c::PLAYER_AREA; i++) { unmutePlayer(i, frames); } } void dSndControlPlayerMgr_c::muteScenePlayers(s32 frames) { for (u32 i = dSndPlayerMgr_c::PLAYER_ENEMY; i < dSndPlayerMgr_c::PLAYER_AREA; i++) { overrideVolume(i, 0.0f, frames); } } void dSndControlPlayerMgr_c::setGroupVolumeFlag(VolumeControlGroup group, MuteLevel level) { if (group >= CTRL_GROUP_MAX) { return; } if (level >= MUTE_MAX) { return; } mTimersForGroupVolume[group][level] = 5; } void dSndControlPlayerMgr_c::setPlayerVolumeInternal(u32 playerIdx, f32 volume) { if (playerIdx >= sNumPlayers) { return; } // @bug not actually clamped (void)nw4r::ut::Clamp(volume, 0.0f, 2.0f); if (mpTargetVolumes[playerIdx] > volume) { mpTargetVolumes[playerIdx] = volume; } u32 mask = (1 << playerIdx); if ((mOverrideVolumeMask & mask) != 0) { mpSavedVolumes[playerIdx] = mpTargetVolumes[playerIdx]; } } void dSndControlPlayerMgr_c::setBgmMuteVolume(f32 volume) { for (u32 i = dSndPlayerMgr_c::PLAYER_BGM; i < dSndPlayerMgr_c::PLAYER_BGM_BATTLE + 1; i++) { setPlayerVolumeInternal(i, volume); } } void dSndControlPlayerMgr_c::setBgmVolumeDecreaseSpeed(f32 decrease) {} void dSndControlPlayerMgr_c::setStageEffectsVolume(f32 volume, s32 fadeFrames) { for (u32 i = dSndPlayerMgr_c::PLAYER_TG_SOUND; i <= dSndPlayerMgr_c::PLAYER_AREA_IN_WATER_LV; i++) { setVolume(i, volume, fadeFrames); } } void dSndControlPlayerMgr_c::setStageEffectsMuteVolume(f32 volume) { for (u32 i = dSndPlayerMgr_c::PLAYER_TG_SOUND; i <= dSndPlayerMgr_c::PLAYER_AREA_IN_WATER_LV; i++) { setPlayerVolumeInternal(i, volume); } } void dSndControlPlayerMgr_c::setEnemyMuteVolume(f32 volume) { for (u32 i = dSndPlayerMgr_c::PLAYER_ENEMY; i < dSndPlayerMgr_c::PLAYER_ENEMY_FOOTSTEP + 1; i++) { setPlayerVolumeInternal(i, volume); } } void dSndControlPlayerMgr_c::setObjectMuteVolume(f32 volume) { for (u32 i = dSndPlayerMgr_c::PLAYER_OBJECT_1; i < dSndPlayerMgr_c::PLAYER_TG_SOUND + 1; i++) { if (i != dSndPlayerMgr_c::PLAYER_NPC_VOICE) { setPlayerVolumeInternal(i, volume); } } }