diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index c314ebe9..28dc2197 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -20001,10 +20001,10 @@ fn_8035F770 = .text:0x8035F770; // type:function size:0xDC calc__22dSndControlPlayerMgr_cFv = .text:0x8035F850; // type:function size:0x3C executeControls__22dSndControlPlayerMgr_cFv = .text:0x8035F890; // type:function size:0xAC calcVolumes__22dSndControlPlayerMgr_cFv = .text:0x8035F940; // type:function size:0x168 -fn_8035FAB0 = .text:0x8035FAB0; // type:function size:0x318 -fn_8035FDD0 = .text:0x8035FDD0; // type:function size:0xE0 -fn_8035FEB0 = .text:0x8035FEB0; // type:function size:0x11C -fn_8035FFD0 = .text:0x8035FFD0; // type:function size:0xE0 +calcMuteFlags__22dSndControlPlayerMgr_cFv = .text:0x8035FAB0; // type:function size:0x318 +__cl__21EventMuteFlagsApplierFRQ34nw4r3snd11SoundHandle = .text:0x8035FDD0; // type:function size:0xE0 +__cl__21SmallMuteFlagsApplierFRQ34nw4r3snd11SoundHandle = .text:0x8035FEB0; // type:function size:0x11C +__cl__23FanfareMuteFlagsApplierFRQ34nw4r3snd11SoundHandle = .text:0x8035FFD0; // type:function size:0xE0 getPlayer1__22dSndControlPlayerMgr_cCFUl = .text:0x803600B0; // type:function size:0x70 getPlayer2__22dSndControlPlayerMgr_cCFUl = .text:0x80360120; // type:function size:0x34 fn_80360160 = .text:0x80360160; // type:function size:0xBC @@ -20023,17 +20023,17 @@ getControlTarget__22dSndControlPlayerMgr_cCFQ222dSndControlPlayerMgr_c12PlayerCt fn_80360710 = .text:0x80360710; // type:function size:0x78 fn_80360790 = .text:0x80360790; // type:function size:0x5C fn_803607F0 = .text:0x803607F0; // type:function size:0x60 -setShortParameterTo5__22dSndControlPlayerMgr_cFll = .text:0x80360850; // type:function size:0x2C -fn_80360880 = .text:0x80360880; // type:function size:0x64 +setGroupVolumeFlag__22dSndControlPlayerMgr_cFQ222dSndControlPlayerMgr_c18VolumeControlGroupQ222dSndControlPlayerMgr_c9MuteLevel = .text:0x80360850; // type:function size:0x2C +setPlayerVolumeInternal__22dSndControlPlayerMgr_cFUlf = .text:0x80360880; // type:function size:0x64 fn_803608F0 = .text:0x803608F0; // type:function size:0x50 -fn_80360940 = .text:0x80360940; // type:function size:0x5C +setBgmMuteVolume__22dSndControlPlayerMgr_cFf = .text:0x80360940; // type:function size:0x5C fn_803609A0 = .text:0x803609A0; // type:function size:0x5C -fn_80360A00 = .text:0x80360A00; // type:function size:0x5C -fn_80360A60 = .text:0x80360A60; // type:function size:0x6C -fn_80360AD0 = .text:0x80360AD0; // type:function size:0x5C -fn_80360B30 = .text:0x80360B30; // type:function size:0x5C -fn_80360B90 = .text:0x80360B90; // type:function size:0x64 -fn_80360C00 = .text:0x80360C00; // type:function size:0x28 +setBgmVolumeDecreaseSpeed__22dSndControlPlayerMgr_cFf = .text:0x80360A00; // type:function size:0x5C +setStageEffectsVolume__22dSndControlPlayerMgr_cFfl = .text:0x80360A60; // type:function size:0x6C +setStageEffectsMuteVolume__22dSndControlPlayerMgr_cFf = .text:0x80360AD0; // type:function size:0x5C +setEnemyMuteVolume__22dSndControlPlayerMgr_cFf = .text:0x80360B30; // type:function size:0x5C +setObjectMuteVolume__22dSndControlPlayerMgr_cFf = .text:0x80360B90; // type:function size:0x64 +__sinit_\d_snd_control_player_mgr_cpp = .text:0x80360C00; // type:function size:0x28 __dt__33SndMgrDisposer<15dSnd3DManager_c>Fv = .text:0x80360C30; // type:function size:0x78 scope:weak create__33SndMgrDisposer<15dSnd3DManager_c>Fv = .text:0x80360CB0; // type:function size:0x48 scope:weak remove__33SndMgrDisposer<15dSnd3DManager_c>Fv = .text:0x80360D00; // type:function size:0x10 scope:weak @@ -37641,9 +37641,9 @@ lbl_80548758 = .data:0x80548758; // type:object size:0x14 data:string lbl_8054876C = .data:0x8054876C; // type:object size:0x14 data:string __vt__15dSndPlayerMgr_c = .data:0x80548780; // type:object size:0x10 __vt__33SndMgrDisposer<15dSndPlayerMgr_c> = .data:0x80548790; // type:object size:0xC -lbl_805487A0 = .data:0x805487A0; // type:object size:0xC -lbl_805487AC = .data:0x805487AC; // type:object size:0xC -lbl_805487B8 = .data:0x805487B8; // type:object size:0xC +__vt__21EventMuteFlagsApplier = .data:0x805487A0; // type:object size:0xC +__vt__21SmallMuteFlagsApplier = .data:0x805487AC; // type:object size:0xC +__vt__23FanfareMuteFlagsApplier = .data:0x805487B8; // type:object size:0xC __vt__40SndMgrDisposer<22dSndControlPlayerMgr_c> = .data:0x805487C4; // type:object size:0xC __vt__33SndMgrDisposer<15dSnd3DManager_c> = .data:0x805487D0; // type:object size:0xC scope:weak lbl_805487E0 = .data:0x805487E0; // type:object size:0xAC @@ -49198,7 +49198,7 @@ lbl_8057E5C0 = .sdata2:0x8057E5C0; // type:object size:0x4 data:4byte lbl_8057E5C4 = .sdata2:0x8057E5C4; // type:object size:0x4 align:4 data:float sNumPlayers__22dSndControlPlayerMgr_c = .sdata2:0x8057E5C8; // type:object size:0x4 data:4byte lbl_8057E5CC = .sdata2:0x8057E5CC; // type:object size:0x4 data:4byte -lbl_8057E5D0 = .sdata2:0x8057E5D0; // type:object size:0x8 data:4byte +sEventMuteFlagsMask__15dSndPlayerMgr_c = .sdata2:0x8057E5D0; // type:object size:0x8 data:4byte lbl_8057E5D8 = .sdata2:0x8057E5D8; // type:object size:0x4 align:4 data:float lbl_8057E5DC = .sdata2:0x8057E5DC; // type:object size:0x4 align:4 data:float lbl_8057E5E0 = .sdata2:0x8057E5E0; // type:object size:0x8 align:8 data:double diff --git a/include/d/snd/d_snd_control_player_mgr.h b/include/d/snd/d_snd_control_player_mgr.h index d3b7654e..d7e3097b 100644 --- a/include/d/snd/d_snd_control_player_mgr.h +++ b/include/d/snd/d_snd_control_player_mgr.h @@ -6,32 +6,6 @@ #include "nw4r/snd/snd_SoundPlayer.h" #include "nw4r/ut/ut_list.h" -/* -Num players: 0x15 = 21 -Notes on player groups: -0, 1 - -9, 10, 11 - -12, 13, 14, 16, 17 - -17, 18, 19, 20 - - -0: BGM - -3: UI Sfx, confirmation, pointer reset -4: UI SFX, get fruit -5, 7: Player walk -8: Player Equipment - -12: bomb explode, refresh fruit sprout -13: environmental sound effects (wind), bomb fuse -14: enemies/bugs - -17: TgSound -*/ - SND_DISPOSER_FORWARD_DECL(dSndControlPlayerMgr_c); class dSndControlPlayerMgr_c { @@ -39,11 +13,11 @@ class dSndControlPlayerMgr_c { public: enum PlayerCtrl_e { - CTRL_VOLUME, - CTRL_LPF_FREQ, - CTRL_FX_SEND, + CTRL_VOLUME = 0, + CTRL_LPF_FREQ = 1, + CTRL_FX_SEND = 2, - CTRL_MAX, + CTRL_MAX = 3, }; dSndControlPlayerMgr_c(); @@ -63,11 +37,43 @@ public: void overrideVolume(u32 playerIdx, f32 volume, s32 frames); void restoreVolume(u32 playerIdx, s32 frames); - void setShortParameterTo5(s32 idx1, s32 idx2); + void muteAllWorldSounds(s32 fadeFrames); + void unmuteAllWorldSounds(s32 fadeFrames); + + enum MuteLevel { + MUTE_FULL = 0, + MUTE_PARTIAL = 1, + + MUTE_MAX = 2, + }; + + enum VolumeControlGroup { + /** PLAYER_BGM, PLAYER_BGM_BOSS */ + CTRL_GROUP_BGM = 0, + /** PLAYER_TG_SOUND - PLAYER_AREA_IN_WATER_LV */ + CTRL_GROUP_STAGE_EFFECTS = 1, + /** PLAYER_ENEMY - PLAYER_ENEMY_FOOTSTEP */ + CTRL_GROUP_ENEMY = 2, + /* PLAYER_OBJECT_1 - PLAYER_TG_SOUND, but not PLAYER_NPC_VOICE */ + CTRL_GROUP_OBJECTS = 3, + + CTRL_GROUP_MAX = 4, + }; + void setGroupVolumeFlag(VolumeControlGroup group, MuteLevel level); + + void setBgmVolumeDecreaseSpeed(f32 speed); + void setStageEffectsVolume(f32 volume, s32 fadeFrames); private: + void setBgmMuteVolume(f32 volume); + void setStageEffectsMuteVolume(f32 volume); + void setEnemyMuteVolume(f32 volume); + void setObjectMuteVolume(f32 volume); + void setPlayerVolumeInternal(u32 playerIdx, f32 volume); + void resetControls(); void calcVolumes(); + void calcMuteFlags(); void executeControls(); void linkCtrl(dSndControlPlayer_c *); void unlinkCtrl(dSndControlPlayer_c *); @@ -82,7 +88,7 @@ private: /* 0x28 */ f32 *mpSavedVolumes; /* 0x2C */ u32 mOverrideVolumeMask; /* 0x30 */ nw4r::ut::List mActiveControls; - /* 0x3C */ s16 field_0x3C[4][2]; + /* 0x3C */ s16 mTimersForGroupVolume[4][2]; }; #endif diff --git a/include/d/snd/d_snd_player_mgr.h b/include/d/snd/d_snd_player_mgr.h index 81ea7e61..d5c877eb 100644 --- a/include/d/snd/d_snd_player_mgr.h +++ b/include/d/snd/d_snd_player_mgr.h @@ -1,6 +1,7 @@ #ifndef D_SND_PLAYER_MGR_H #define D_SND_PLAYER_MGR_H +#include "d/snd/d_snd_mgr.h" #include "d/snd/d_snd_util.h" #include "nw4r/snd/snd_MemorySoundArchive.h" #include "nw4r/snd/snd_SoundArchivePlayer.h" @@ -35,6 +36,86 @@ public: return mFlags & mask; } + u32 getEventMuteMask(u32 id) { + nw4r::snd::SoundArchive *archive; + if (mSoundArchivePlayer.IsAvailable()) { + archive = &mSoundArchive; + } else { + archive = dSndMgr_c::GetInstance()->getArchive(); + } + return archive->GetSoundUserParam(id) & sEventMuteFlagsMask; + } + + enum FanfareUnmuteParam_e { + FANFARE_UNMUTE_BGM = 0x10000, + FANFARE_UNMUTE_STAGE_EFFECTS = 0x20000, + FANFARE_UNMUTE_ENEMY = 0x40000, + FANFARE_UNMUTE_OBJECTS = 0x80000, + }; + + // seem to be used for Small and Event sounds + enum UserParamEventSmall_e { + MUTE_BGM_PART = 0x10000, + MUTE_BGM_FULL = 0x20000, + MUTE_STAGE_EFFECTS_PART = 0x40000, + MUTE_STAGE_EFFECTS_FULL = 0x80000, + MUTE_ENEMY_PART = 0x100000, + MUTE_ENEMY_FULL = 0x200000, + MUTE_OBJECTS_PART = 0x400000, + MUTE_OBJECTS_FULL = 0x800000, + }; + + static const u32 sEventMuteFlagsMask; + + // For a full overview over which sounds are played by which players, + // see https://gist.github.com/robojumper/f81a55857cebed2c79cf3cf3c1ec8f04 + enum PlayerIndex_e { + /** Background music */ + PLAYER_BGM = 0, + /** Background music, boss battle */ + PLAYER_BGM_BOSS = 1, + /** "fanfare?" */ + PLAYER_FAN = 2, + /** small sound effects, only a few (UI navigation related) */ + PLAYER_SMALL_IMPORTANT = 3, + /** small sound, often UI related */ + PLAYER_SMALL_NORMAL = 4, + /** hit, roll attack, cloth, sink */ + PLAYER_LINK_BODY = 5, + /** Link voice */ + PLAYER_LINK_VOICE = 6, + /** Link footstep, swimming */ + PLAYER_LINK_FOOTSTEP = 7, + /** Sword, beetle, ... */ + PLAYER_LINK_EQUIPMENT = 8, + /** Enemy sound effects */ + PLAYER_ENEMY = 9, + /** Enemy voices */ + PLAYER_ENEMY_VOICE = 10, + /** Enemy footstep */ + PLAYER_ENEMY_FOOTSTEP = 11, + /** Misc objects */ + PLAYER_OBJECT_1 = 12, + /** Misc objects */ + PLAYER_OBJECT_2 = 13, + /** NPC footsteps */ + PLAYER_NPC_FOOTSTEP = 14, + /** NPC voices */ + PLAYER_NPC_VOICE = 15, + /** leaves, grass */ + PLAYER_FOLIAGE = 16, + /** misc TgSound environmental effects */ + PLAYER_TG_SOUND = 17, + /** area sound effects (Faron birds...) */ + PLAYER_AREA = 18, + /** not sure, only SE_A_IN_WATER_LV */ + PLAYER_AREA_IN_WATER_LV = 19, + /** event */ + PLAYER_EVENT = 20, + /** not sure */ + PLAYER_UNK_21 = 21, + }; + private: /* 0x010 */ u8 field_0x010; /* 0x011 */ u8 field_0x011; @@ -45,8 +126,9 @@ private: virtual nw4r::snd::SoundStartable::StartResult startSound(nw4r::snd::SoundHandle *pHandle, u32 soundId, const nw4r::snd::SoundStartable::StartInfo *pStartInfo); - virtual nw4r::snd::SoundStartable::StartResult - startSound(nw4r::snd::SoundHandle *pHandle, const char *soundLabel, const nw4r::snd::SoundStartable::StartInfo *pStartInfo); + virtual nw4r::snd::SoundStartable::StartResult startSound( + nw4r::snd::SoundHandle *pHandle, const char *soundLabel, const nw4r::snd::SoundStartable::StartInfo *pStartInfo + ); /* 0x028 */ nw4r::snd::MemorySoundArchive mSoundArchive; /* 0x178 */ nw4r::snd::SoundArchivePlayer mSoundArchivePlayer; diff --git a/include/nw4r/snd/snd_SoundPlayer.h b/include/nw4r/snd/snd_SoundPlayer.h index dfdcded2..90b56ed0 100644 --- a/include/nw4r/snd/snd_SoundPlayer.h +++ b/include/nw4r/snd/snd_SoundPlayer.h @@ -69,6 +69,35 @@ namespace nw4r { namespace snd void detail_FreePlayerHeap(detail::BasicSound *sound); void detail_AppendPlayerHeap(detail::PlayerHeap *heap); + // Apparently exists, needed in d/snd + template + TForEachFunc ForEachSound(TForEachFunc pFunc, bool reverse) { + if (reverse) { + detail::BasicSound::SoundPlayerPlayLinkList::ReverseIterator it = mSoundList.GetBeginReverseIter(); + + while (it != mSoundList.GetEndReverseIter()) { + detail::BasicSound::SoundPlayerPlayLinkList::ReverseIterator curr = it; + + SoundHandle handle; + handle.detail_AttachSoundAsTempHandle(&*curr); + pFunc(handle); + + if (handle.IsAttachedSound()) { + ++it; + } + } + } else { + NW4R_RANGE_FOR_NO_AUTO_INC(it, mSoundList) { + decltype(it) curItr = it++; + SoundHandle handle; + handle.detail_AttachSoundAsTempHandle(&*curItr); + pFunc(handle); + } + } + + return pFunc; + } + // members private: detail::BasicSound::SoundPlayerPlayLinkList mSoundList; // size 0x0c, offset 0x00 diff --git a/include/toBeSorted/music_mgrs.h b/include/toBeSorted/music_mgrs.h index fd498ac8..1efa7fe0 100644 --- a/include/toBeSorted/music_mgrs.h +++ b/include/toBeSorted/music_mgrs.h @@ -43,5 +43,6 @@ extern "C" bool fn_80373550(void *, u32); extern "C" void fn_80372920(void *); extern "C" void fn_803738B0(void *, dSndSound_c *sound); extern "C" void fn_80373900(void *, dSndSound_c *sound); +extern "C" bool fn_803733B0(void*, u32); #endif diff --git a/src/d/snd/d_snd_control_player_mgr.cpp b/src/d/snd/d_snd_control_player_mgr.cpp index 3f79e49c..75fa02d1 100644 --- a/src/d/snd/d_snd_control_player_mgr.cpp +++ b/src/d/snd/d_snd_control_player_mgr.cpp @@ -2,7 +2,125 @@ #include "common.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 "nw4r/snd/snd_SoundHandle.h" #include "nw4r/ut/ut_list.h" +#include "toBeSorted/music_mgrs.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 (fn_803733B0(FANFARE_SOUND_MGR, 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 (fn_80364DA0(ENEMY_SOUND_MGR)) { + 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); @@ -20,7 +138,11 @@ dSndControlPlayerMgr_c::dSndControlPlayerMgr_c() : mOverrideVolumeMask(0) { mpMaxVolumeIncreases = new f32[sNumPlayers]; } -void dSndControlPlayerMgr_c::calc() {} +void dSndControlPlayerMgr_c::calc() { + calcMuteFlags(); + calcVolumes(); + executeControls(); +} void dSndControlPlayerMgr_c::executeControls() { dSndControlPlayer_c *next; @@ -42,8 +164,7 @@ void dSndControlPlayerMgr_c::calcVolumes() { // overridden volume mpTargetVolumes[i] = mpSavedVolumes[i]; } else { - // not overridden. The effect of this is that - // something will set the targetValue to a specific value + // not overridden. f32 currentVolume = getAppliedPlayerVolume(i); f32 targetVolume = mpTargetVolumes[i]; f32 maxVolumeDecrease = mpMaxVolumeDecreases[i]; @@ -66,6 +187,43 @@ void dSndControlPlayerMgr_c::calcVolumes() { } } +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; @@ -97,7 +255,7 @@ void dSndControlPlayerMgr_c::setVolume(u32 playerIdx, f32 value, s32 frames) { 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); @@ -181,14 +339,65 @@ f32 dSndControlPlayerMgr_c::getControlTarget(PlayerCtrl_e ctrlType, u32 playerId return mpCtrls[ctrlType][playerIdx].getTargetValue(); } -void dSndControlPlayerMgr_c::setShortParameterTo5(s32 idx1, s32 idx2) { - if (idx1 >= 4) { +void dSndControlPlayerMgr_c::setGroupVolumeFlag(VolumeControlGroup group, MuteLevel level) { + if (group >= CTRL_GROUP_MAX) { return; } - if (idx2 >= 2) { + if (level >= MUTE_MAX) { return; } - field_0x3C[idx1][idx2] = 5; + mTimersForGroupVolume[group][level] = 5; +} + +void dSndControlPlayerMgr_c::setPlayerVolumeInternal(u32 playerIdx, f32 volume) { + if (playerIdx >= sNumPlayers) { + return; + } + // @bug not actually clamped + 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_BOSS + 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); + } + } }