From 57dc840d6140e4351e488730e199c5f7f2b331ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= <159546+serprex@users.noreply.github.com> Date: Mon, 12 Oct 2026 23:04:07 +0000 Subject: [PATCH] Audio editor: support setting track to None (#7372) --- .../Enhancements/audio/AudioCollection.cpp | 3 +- soh/soh/Enhancements/audio/AudioEditor.cpp | 45 ++++++++++++++----- soh/src/code/code_800F7260.c | 3 ++ 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/soh/soh/Enhancements/audio/AudioCollection.cpp b/soh/soh/Enhancements/audio/AudioCollection.cpp index f76c3cc24c..a27b8e09bf 100644 --- a/soh/soh/Enhancements/audio/AudioCollection.cpp +++ b/soh/soh/Enhancements/audio/AudioCollection.cpp @@ -389,7 +389,8 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) { const auto& sequenceInfo = sequenceMap.at(seqId); const std::string cvarKey = GetCvarKey(sequenceInfo.sfxKey); int replacementSeq = CVarGetInteger(cvarKey.c_str(), seqId); - if (!sequenceMap.contains(replacementSeq)) { + // NA_BGM_DISABLED means the music was set to "None". No sequence has that id, so nothing plays. + if (replacementSeq != NA_BGM_DISABLED && !sequenceMap.contains(replacementSeq)) { replacementSeq = seqId; } return static_cast(replacementSeq); diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index d223b55b37..20ae9d9492 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -22,6 +22,7 @@ extern "C" { #include #include "z64save.h" extern SaveContext gSaveContext; +extern ActiveSequence gActiveSeqs[4]; } Vec3f pos = { 0.0f, 0.0f, 0.0f }; @@ -93,10 +94,16 @@ static const std::map audioRandomizerModes = { { RANDOMIZE_ON_FILE_LOAD_SEEDED, "On File Load (Seeded)" }, }; +// The last BGM sequence the game asked for. Unlike func_800FA0B4 this still works when the area's music is set +// to "None", where the sequence player sits idle because nothing loaded. +static u16 GetCurrentBGM() { + return gActiveSeqs[SEQ_PLAYER_BGM_MAIN].seqId; +} + // Grabs the current BGM sequence ID and replays it // which will lookup the proper override, or reset back to vanilla void ReplayCurrentBGM() { - u16 curSeqId = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); + u16 curSeqId = GetCurrentBGM(); // TODO: replace with Audio_StartSeq when the macro is shared // The fade time and audio player flags will always be 0 in the case of replaying the BGM, so they are not set here Audio_QueueSeqCmd(0x00000000 | curSeqId); @@ -109,7 +116,7 @@ void UpdateCurrentBGM(u16 seqKey, SeqType seqType) { return; } - u16 curSeqId = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); + u16 curSeqId = GetCurrentBGM(); if (curSeqId == seqKey) { ReplayCurrentBGM(); } @@ -265,7 +272,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN ImGui::SeparatorText(tabName.c_str()); if (UIWidgets::Button(resetAllButton.c_str(), UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { - auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); + auto currentBGM = GetCurrentBGM(); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); ResetGroup(map, type); Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); @@ -277,7 +284,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN ImGui::SameLine(); if (UIWidgets::Button(randomizeAllButton.c_str(), UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { - auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); + auto currentBGM = GetCurrentBGM(); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); RandomizeGroup(type); Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); @@ -289,7 +296,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN ImGui::SameLine(); if (UIWidgets::Button(lockAllButton.c_str(), UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { - auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); + auto currentBGM = GetCurrentBGM(); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); LockGroup(map, type); Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); @@ -301,7 +308,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN ImGui::SameLine(); if (UIWidgets::Button(unlockAllButton.c_str(), UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { - auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); + auto currentBGM = GetCurrentBGM(); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); UnlockGroup(map, type); Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); @@ -312,7 +319,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN } auto playingFromMenu = CVarGetInteger(CVAR_AUDIO("Playing"), 0); - auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); + auto currentBGM = GetCurrentBGM(); // Longest text in Audio Editor ImVec2 columnSize = ImGui::CalcTextSize("Navi - Look/Hey/Watchout (Target Enemy)"); @@ -353,11 +360,22 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN ImGui::TableNextColumn(); ImGui::PushItemWidth(-FLT_MIN); const int initialValue = map.contains(currentValue) ? currentValue : defaultValue; + const bool isNone = currentValue == NA_BGM_DISABLED; UIWidgets::PushStyleCombobox(THEME_COLOR); - if (ImGui::BeginCombo(hiddenKey.c_str(), map.at(initialValue).label.c_str())) { + if (ImGui::BeginCombo(hiddenKey.c_str(), isNone ? "None" : map.at(initialValue).label.c_str())) { + if (type == SEQ_BGM_WORLD || type == SEQ_SFX || type == SEQ_VOICE) { + if (ImGui::Selectable("None")) { + CVarSetInteger(cvarKey.c_str(), NA_BGM_DISABLED); + Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + UpdateCurrentBGM(defaultValue, type); + } + if (isNone) { + ImGui::SetItemDefaultFocus(); + } + } + for (const auto& [value, seqData] : map) { - // If excluded as a replacement sequence, don't show in other dropdowns except the effect's own - // dropdown. + // If excluded as a replacement sequence, don't show in other dropdowns except effect's dropdown. if (~(seqData.category) & type || (!seqData.canBeUsedAsReplacement && initialSfxKey != seqData.sfxKey)) { continue; @@ -379,9 +397,12 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN UIWidgets::PopStyleCombobox(); ImGui::TableNextColumn(); ImGui::PushItemWidth(-FLT_MIN); - DrawPreviewButton((type == SEQ_SFX || type == SEQ_VOICE || type == SEQ_INSTRUMENT) ? defaultValue - : currentValue, + // Nothing to preview when set to "None" + ImGui::BeginDisabled(isNone); + DrawPreviewButton((type == SEQ_SFX || type == SEQ_VOICE || type == SEQ_INSTRUMENT || isNone) ? defaultValue + : currentValue, seqData.sfxKey, type); + ImGui::EndDisabled(); auto locked = CVarGetInteger(cvarLockKey.c_str(), 0) == 1; ImGui::SameLine(); ImGui::PushItemWidth(-FLT_MIN); diff --git a/soh/src/code/code_800F7260.c b/soh/src/code/code_800F7260.c index f06c13e668..4cd7ab55ef 100644 --- a/soh/src/code/code_800F7260.c +++ b/soh/src/code/code_800F7260.c @@ -222,6 +222,9 @@ void Audio_ProcessSoundRequest(void) { return; } u16 newSfxId = AudioEditor_GetReplacementSeq(req->sfxId); + if (newSfxId == NA_BGM_DISABLED) { + return; + } if (req->sfxId != newSfxId) { gAudioContext.seqReplaced[SEQ_PLAYER_SFX] = 1; req->sfxId = newSfxId;