From 343610ece52503b8338c25b7d092204c14cada7f Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 27 Mar 2026 15:30:23 -0700 Subject: [PATCH] Fix phoneme playback and lower background audio during animations PhonemePlayer resolved ROIs by name, but multiplayer participants have unique ROI names (e.g. pepper_mp_8) that don't match the animation actor name in the SI phoneme track (pepper). Pass actor-name-to-ROI aliases from SetupROIs through to PhonemePlayer::Init so it can resolve participant ROIs correctly. Also lower/raise background audio volume for the duration of scene animations. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../multiplayer/animation/phonemeplayer.h | 7 ++++- .../multiplayer/animation/sceneplayer.h | 3 ++ .../multiplayer/animation/phonemeplayer.cpp | 28 +++++++++++++++---- .../src/multiplayer/animation/sceneplayer.cpp | 9 +++++- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/extensions/include/extensions/multiplayer/animation/phonemeplayer.h b/extensions/include/extensions/multiplayer/animation/phonemeplayer.h index b8d2cb4a..86260589 100644 --- a/extensions/include/extensions/multiplayer/animation/phonemeplayer.h +++ b/extensions/include/extensions/multiplayer/animation/phonemeplayer.h @@ -22,7 +22,12 @@ struct PhonemeState { class PhonemePlayer { public: - void Init(const std::vector& p_tracks, LegoROI** p_roiMap, MxU32 p_roiMapSize); + void Init( + const std::vector& p_tracks, + LegoROI** p_roiMap, + MxU32 p_roiMapSize, + const std::vector>& p_actorAliases + ); void Tick(float p_elapsedMs, const std::vector& p_tracks); void Cleanup(); diff --git a/extensions/include/extensions/multiplayer/animation/sceneplayer.h b/extensions/include/extensions/multiplayer/animation/sceneplayer.h index 07cd3e87..71d75ecd 100644 --- a/extensions/include/extensions/multiplayer/animation/sceneplayer.h +++ b/extensions/include/extensions/multiplayer/animation/sceneplayer.h @@ -85,6 +85,9 @@ class ScenePlayer { LegoROI** m_roiMap; MxU32 m_roiMapSize; + // Actor name → ROI aliases (participant ROIs whose names differ from animation actor names) + std::vector> m_actorAliases; + // Props created for the animation (cloned characters and prop models) std::vector m_propROIs; diff --git a/extensions/src/multiplayer/animation/phonemeplayer.cpp b/extensions/src/multiplayer/animation/phonemeplayer.cpp index c9542fa2..4597ca16 100644 --- a/extensions/src/multiplayer/animation/phonemeplayer.cpp +++ b/extensions/src/multiplayer/animation/phonemeplayer.cpp @@ -12,13 +12,26 @@ using namespace Multiplayer::Animation; -// Find the ROI matching a phoneme track's roiName in the roiMap. -static LegoROI* FindTrackROI(const std::string& p_roiName, LegoROI** p_roiMap, MxU32 p_roiMapSize) +// Find the ROI matching a phoneme track's roiName. +// Check actor aliases first (participant ROIs whose names differ from animation actor names), +// then fall back to a direct name search in the roiMap. +static LegoROI* FindTrackROI( + const std::string& p_roiName, + LegoROI** p_roiMap, + MxU32 p_roiMapSize, + const std::vector>& p_actorAliases +) { if (p_roiName.empty() || !p_roiMap) { return nullptr; } + for (const auto& alias : p_actorAliases) { + if (!SDL_strcasecmp(p_roiName.c_str(), alias.first.c_str())) { + return alias.second; + } + } + for (MxU32 i = 1; i < p_roiMapSize; i++) { if (p_roiMap[i] && p_roiMap[i]->GetName() && !SDL_strcasecmp(p_roiName.c_str(), p_roiMap[i]->GetName())) { return p_roiMap[i]; @@ -27,7 +40,12 @@ static LegoROI* FindTrackROI(const std::string& p_roiName, LegoROI** p_roiMap, M return nullptr; } -void PhonemePlayer::Init(const std::vector& p_tracks, LegoROI** p_roiMap, MxU32 p_roiMapSize) +void PhonemePlayer::Init( + const std::vector& p_tracks, + LegoROI** p_roiMap, + MxU32 p_roiMapSize, + const std::vector>& p_actorAliases +) { for (auto& track : p_tracks) { PhonemeState state; @@ -37,8 +55,8 @@ void PhonemePlayer::Init(const std::vector& p_track state.bitmap = nullptr; state.currentFrame = -1; - // Resolve the target ROI from the track's roiName via the roiMap - LegoROI* targetROI = FindTrackROI(track.roiName, p_roiMap, p_roiMapSize); + // Resolve the target ROI from the track's roiName via aliases or roiMap + LegoROI* targetROI = FindTrackROI(track.roiName, p_roiMap, p_roiMapSize, p_actorAliases); if (!targetROI) { m_states.push_back(state); continue; diff --git a/extensions/src/multiplayer/animation/sceneplayer.cpp b/extensions/src/multiplayer/animation/sceneplayer.cpp index 19463a56..1b5a8d77 100644 --- a/extensions/src/multiplayer/animation/sceneplayer.cpp +++ b/extensions/src/multiplayer/animation/sceneplayer.cpp @@ -11,6 +11,7 @@ #include "legoworld.h" #include "misc.h" #include "misc/legotree.h" +#include "mxbackgroundaudiomanager.h" #include "mxgeometry/mxgeometry3d.h" #include "realtime/realtime.h" #include "roi/legoroi.h" @@ -85,6 +86,7 @@ void ScenePlayer::SetupROIs(const AnimInfo* p_animInfo) auto addAlias = [&](const std::string& p_name, LegoROI* p_roi) { aliasNames.push_back(p_name); aliases.push_back({aliasNames.back().c_str(), p_roi}); + m_actorAliases.push_back({p_name, p_roi}); }; auto createProp = [&](const std::string& p_name, const char* p_lodName) -> LegoROI* { @@ -292,7 +294,7 @@ void ScenePlayer::Play( } ResolvePtAtCamROIs(); - m_phonemePlayer.Init(data->phonemeTracks, m_roiMap, m_roiMapSize); + m_phonemePlayer.Init(data->phonemeTracks, m_roiMap, m_roiMapSize, m_actorAliases); m_audioPlayer.Init(data->audioTracks); // Observers don't get camera control — they watch the animation from their own viewpoint @@ -310,6 +312,8 @@ void ScenePlayer::Play( m_startTime = 0; m_playing = true; + + BackgroundAudioManager()->LowerVolume(); } void ScenePlayer::ComputeRebaseMatrix() @@ -547,7 +551,10 @@ void ScenePlayer::Stop() } m_participants.clear(); + BackgroundAudioManager()->RaiseVolume(); + m_ptAtCamROIs.clear(); + m_actorAliases.clear(); m_playing = false; m_rebaseComputed = false; m_currentData = nullptr;