From 99757a947dce919a96c859362120e7116a362b3c Mon Sep 17 00:00:00 2001 From: arcattack Date: Thu, 16 Jul 2026 00:25:18 -0500 Subject: [PATCH] Audio: footstep chain traced to the END -- gait VINDICATED; audio clock 18x unit mismatch found (task #50) MAJOR RESULT -- THE GAIT IS CORRECT, the enum was mislabeled: LoadLocomotionClips (binary-verified slot map) proves namedClip==&animationClips[5]: clips 6/7 = wwr/wwl (WALK cycle), 12/13 = rrr/rrl (RUN cycle -- what autodrive uses at full throttle), 10/11 = wrr/wrl, 14/15 = rwr/rwl, 16-21 = reverse set. The mech2.cpp "MechAnimationState" enum (0x3c-stride name table) does NOT match the runtime clip ids -- it is the mislabel (12/13 are NOT StandToReverse). The authored AudioStateTriggers on AnimationState (statecfg dump: states 1,2,5,8,9,10,11,14,15,16,17,20,21,22,23,26,27 -> Start) align EXACTLY with the TRANSITION clips under the true map; the CYCLING strides (6/7, 12/13) have no state triggers because the FootStep pulse attribute serves them -- our FootStep reconstruction is the authentic design. DO NOT renumber the gait. Footstep chain, fully mapped (all empirtical): pulse -> AudioMatchOf(match=1) -> Start on the FootFall DirectPatchSource -> DROPPED at volume 0. Volume path: an AudioControlMixer (2 inputs, never fed) <- an AudioControlSplitter <- AudioControlSequence timeline events. The sequences DO fire -- but only value-0 events (the tick-0 initializers); the later (real-volume) events never land. NEW ROOT-CAUSE CANDIDATE [T3]: audio clock unit mismatch. The renderer is constructed with DefaultRendererRate=30 (calibrationRate: Seconds_To_Frames = s*30) but AudioHead::Execute sets audioFrameCount = Now().ticks which advances ~550/s (measured via the [audioclock] probe) -- sequence event scheduling runs ~18x off the authored timing. Fix candidate: calibrate the audio renderer to the actual Now().ticks rate (or drive audioFrameCount at the calibrated 30/s). Also corrected en route: FUN_004b9550/95b8 are MechWeapon ConfigureMappables/ ChooseButton (mapper EnterConfiguration +0x38), NOT Myomers::ConnectToMover; +0x31c there is fireImpulse. Myomers::speedEffect has NO binary writer found beyond the ctor 1.0f (its 'mover coupling' stand-in is spurious). Diagnostics added: [statecfg] AudioStateTrigger ctor dump, [split] splitter forwards, [seqev] sequence timeline events, [audioclock] frame-rate probe. Co-Authored-By: Claude Opus 4.8 (1M context) --- engine/MUNGA/AUDCMP.cpp | 3 +++ engine/MUNGA/AUDIO.cpp | 3 +++ engine/MUNGA/AUDSEQ.cpp | 4 ++++ engine/MUNGA/AUDWTHR.cpp | 8 ++++++++ 4 files changed, 18 insertions(+) diff --git a/engine/MUNGA/AUDCMP.cpp b/engine/MUNGA/AUDCMP.cpp index f83597e..362f97c 100644 --- a/engine/MUNGA/AUDCMP.cpp +++ b/engine/MUNGA/AUDCMP.cpp @@ -473,6 +473,9 @@ void while ((audio_component = iterator.ReadAndNext()) != NULL) { Check(audio_component); + if (getenv("BT_AUDIO_SPATIAL")) { static int s_sp2=0; if (s_sp2++<200) + DEBUG_STREAM << "[split] " << (void*)this << " -> tgt=" << (void*)audio_component + << " ctl=" << (int)control_ID << "/" << control_value << "\n" << std::flush; } audio_component->ReceiveControl(control_ID, control_value); } } diff --git a/engine/MUNGA/AUDIO.cpp b/engine/MUNGA/AUDIO.cpp index b017424..f2d96e0 100644 --- a/engine/MUNGA/AUDIO.cpp +++ b/engine/MUNGA/AUDIO.cpp @@ -1,3 +1,4 @@ +#include #include "munga.h" #pragma hdrstop @@ -133,6 +134,8 @@ void // audioFrameCount = Now().ticks; Verify(audioFrameCount < LONG_MAX); + if (getenv("BT_AUDIO_SPATIAL")) { static long s_hx=0; if ((++s_hx % 300)==0) + DEBUG_STREAM << "[audioclock] frame=" << audioFrameCount << " execs=" << s_hx << "\n" << std::flush; } //set current listener orientation Vector3D headVelocity; diff --git a/engine/MUNGA/AUDSEQ.cpp b/engine/MUNGA/AUDSEQ.cpp index 24a6d73..3d0f802 100644 --- a/engine/MUNGA/AUDSEQ.cpp +++ b/engine/MUNGA/AUDSEQ.cpp @@ -1,3 +1,4 @@ +#include #include "munga.h" #pragma hdrstop @@ -67,6 +68,9 @@ void { Check(this); Check(audio_component); + if (getenv("BT_AUDIO_SPATIAL")) { static int s_ev=0; if (s_ev++<200) + DEBUG_STREAM << "[seqev] tgt=" << (void*)audio_component + << " ctl=" << (int)audioControlID << "/" << audioControlValue << "\n" << std::flush; } audio_component->ReceiveControl(audioControlID, audioControlValue); } diff --git a/engine/MUNGA/AUDWTHR.cpp b/engine/MUNGA/AUDWTHR.cpp index 1f3c0e0..e4acd62 100644 --- a/engine/MUNGA/AUDWTHR.cpp +++ b/engine/MUNGA/AUDWTHR.cpp @@ -962,6 +962,14 @@ AudioStateTrigger::AudioStateTrigger( MemoryStream_Read(stream, &excludeTransition); MemoryStream_Read(stream, &excludeState); + if (getenv("BT_ATTRBIND_LOG")) { static int s_stc=0; if (s_stc++<120) + DEBUG_STREAM << "[statecfg] attrPtr=" << (void*)attributePointer + << " comp=" << (void*)audioComponentSocket.GetCurrent() + << " trigState=" << triggerState << " inv=" << (int)inverseTrigger + << " ctl=" << (int)controlID << "/" << controlValue + << " excl=" << (int)excludeTransition << "/" << excludeState + << "\n" << std::flush; } + PrimeWatcher(); }