Files
arcattackandClaude Opus 4.8 ba3040ea09 Audio: footstep-chain diagnostics -- every link verified except the final trigger fire (task #50)
Instrumentation (all BT_AUDIO_LOG/BT_AUDIO_SPATIAL-gated): mech watcher-poll
probe (delayed flag + socket count via new Simulation::DebugAudioWatcherCount),
per-sim audio-socket size in ExecuteWatchers, trigger notifications (val>0),
watcher poll-rate/change probes, footstep pulse address trace.

VERIFIED working: FootStep binds to the real member (pulse addr == bound ptr,
same run); pulses fire per stride (40/run); the watcher registers on the mech
(audioWatchers=20 after audio-object creation); the mech's poll runs
(delayed=0, simFlags=0x1110); Logical == int (STYLE.H:132) matches the member
type.  The idle<->moving engine crossfade (AudioMotionScale on LocalVelocity
through the restored watcher poll) is CONFIRMED audible in play.

REMAINING: the FootFall transient still doesn't reach SetupPatch -- next probe
is the trigger's streamed threshold/inverse config and the speed-scaled
transient volume at the renderer drop gate (LowAudioVolumeThreshold=0.3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 23:16:27 -05:00

391 lines
9.0 KiB
C++

#pragma once
#include "state.h"
#include "receiver.h"
#include "time.h"
#include "resource.h"
class Simulation__SharedData;
class Simulation__IndexData;
struct Simulation__IndexEntry;
class Simulation__AttributeIndexSet;
class MemoryStream;
//##########################################################################
//################# Simulation::UpdateRecord #########################
//##########################################################################
struct Simulation__UpdateRecord
{
public:
size_t recordLength;
Word subsystemID;
Word recordID;
Time timeStamp;
Enumeration simulationState;
};
//##########################################################################
//####################### Simulation #################################
//##########################################################################
class Simulation:
public Receiver
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
typedef Simulation__SharedData SharedData;
SharedData*
GetSharedData();
static Derivation *GetClassDerivations();
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction Support
//
protected:
Simulation(
ClassID class_ID,
SharedData &shared_data
);
public:
~Simulation();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support
//
public:
typedef Enumeration AttributeID;
typedef Simulation__IndexData IndexData;
typedef Simulation__IndexEntry IndexEntry;
typedef Simulation__AttributeIndexSet AttributeIndexSet;
typedef int Simulation::*AttributePointer;
enum {
AnyAttributeID = 0,
SimulationStateAttributeID,
NextAttributeID
};
static const AttributePointer NullAttribute;
void*
GetAttributePointer(AttributeID attribute);
void*
GetAttributePointer(const char* attribute_name);
private:
static const IndexEntry AttributePointers[];
protected:
//static AttributeIndexSet AttributeIndex
static AttributeIndexSet& GetAttributeIndex();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Simulation Support
//
public:
typedef void
(Simulation::*Performance)(Scalar time_slice);
typedef void
(Simulation::*Encore)();
typedef Simulation__UpdateRecord UpdateRecord;
void
SetPerformance(Performance performance)
{Check(this); activePerformance = performance;}
void
Perform(Scalar time_slice)
{
Check(this);
(this->*activePerformance)(time_slice);
}
virtual void
PerformAndWatch(
const Time& till,
MemoryStream *update_stream
);
void
DoNothingOnce(Scalar time_slice);
void
DoNothing(Scalar time_slice);
void
SetLastPerformance(const Time& when)
{Check(this); Check(&when); lastPerformance = when;}
void
RequestEncore(Encore encore);
virtual void
ReadUpdateRecord(UpdateRecord *message);
virtual void
WriteUpdateRecord(
UpdateRecord *message,
int update_model
);
void
WriteSimulationUpdate(MemoryStream *update_stream);
enum {
DefaultUpdateModelBit=0,
NextUpdateModelBit
};
enum {
DefaultUpdateModelFlag = 1<<DefaultUpdateModelBit
};
void
ForceUpdate(Word model=DefaultUpdateModelFlag)
{Check(this); updateModel |= model;}
protected:
Time
lastPerformance;
Time
lastUpdate;
Word
updateModel;
Performance
activePerformance;
//##########################################################################
// Flag Support
//
public:
enum {
DelayWatchersBit,
DontExecuteBit,
NextBit
};
enum {
DelayWatchersFlag = 1<<DelayWatchersBit,
DontExecuteFlag = 1<<DontExecuteBit
};
LWord simulationFlags;
void
SetWatcherDelay()
{Check(this); simulationFlags |= DelayWatchersFlag;}
void
ClearWatcherDelay()
{Check(this); simulationFlags &= ~DelayWatchersFlag;}
Logical
AreWatchersDelayed()
{Check(this); return (simulationFlags & DelayWatchersFlag) != 0;}
void
NeverExecute()
{Check(this); simulationFlags |= DontExecuteFlag;}
void
ExecuteOnUpdate()
{Check(this); simulationFlags |= DontExecuteFlag;}
void
AlwaysExecute()
{Check(this); simulationFlags &= ~DontExecuteFlag;}
Logical
IsReplicantExecutable()
{
Check(this);
return
(simulationFlags&DontExecuteFlag) == 0
|| lastUpdate >= lastPerformance;
}
Logical
IsNonReplicantExecutable()
{Check(this); return (simulationFlags&DontExecuteFlag) == 0;}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// State support
//
public:
enum {
DefaultState = 0,
StateCount
};
unsigned
GetSimulationState()
{Check(this); return simulationState.GetState();}
unsigned
GetOldSimulationState()
{Check(this); return simulationState.GetOldState();}
void
SetSimulationState(unsigned new_state)
{Check(this); simulationState.SetState(new_state);}
StateIndicator
simulationState;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Watcher Support
//
public:
void
AddAudioWatcher(Component *watcher)
{Check(&audioWatcherSocket);audioWatcherSocket.Add(watcher);}
void
AddVideoWatcher(Component *watcher)
{Check(&videoWatcherSocket);videoWatcherSocket.Add(watcher);}
void
AddGaugeWatcher(Component *watcher)
{Check(&gaugeWatcherSocket);gaugeWatcherSocket.Add(watcher);}
void
AddEffectWatcher(Component *watcher)
{Check(&effectWatcherSocket); effectWatcherSocket.Add(watcher);}
void
ExecuteWatchers();
int // DEBUG (BT_AUDIO_LOG): how many audio watchers are registered on this sim
DebugAudioWatcherCount();
private:
SChainOf<Component*>
audioWatcherSocket;
SChainOf<Component*>
videoWatcherSocket;
SChainOf<Component*>
gaugeWatcherSocket;
SChainOf<Component*>
effectWatcherSocket;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test Support
//
public:
Logical
TestInstance() const;
static Logical
TestClass();
};
//##########################################################################
//################### Simulation::IndexEntry #########################
//##########################################################################
struct Simulation__IndexEntry
{
Enumeration
entryID;
const char *
entryName;
Simulation::AttributePointer
entryAddress;
};
#define ATTRIBUTE_ENTRY(class,name,attribute)\
{\
class::name##AttributeID,\
#name,\
(Simulation::AttributePointer) &class::attribute\
}
//##########################################################################
//################# Simulation::AttributeIndexSet ####################
//##########################################################################
class Simulation__AttributeIndexSet:
public Receiver::InheritanceSet
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
Simulation__AttributeIndexSet(
Simulation::AttributeID count,
const Simulation::IndexEntry index_table[],
const Simulation::AttributeIndexSet &inheritance
)
{Build(count, index_table, &inheritance);}
Simulation__AttributeIndexSet(
Simulation::AttributeID count,
const Simulation::IndexEntry index_table[]
)
{Build(count, index_table, NULL);}
Simulation__AttributeIndexSet()
{attributeIndex = NULL; entryCount = 0;}
~Simulation__AttributeIndexSet();
protected:
void
Build(
Simulation::AttributeID count,
const Simulation::IndexEntry index_table[],
const Simulation::AttributeIndexSet *inheritance
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AttributeIndexSet Functionality
//
protected:
Simulation::IndexEntry
*attributeIndex;
public:
Simulation::AttributePointer
Find(Simulation::AttributeID attribute) const
{
Check(this);
Verify(attribute > 0);
if (attribute<=entryCount)
return attributeIndex[attribute-1].entryAddress;
else
return Simulation::NullAttribute;
}
Simulation::AttributePointer
Find(const char* attribute_name) const;
const Simulation::IndexEntry*
FindEntry(const char* attribute_name) const;
static const Simulation::AttributeIndexSet
NullSet;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test Support
//
public:
static Logical
TestClass();
};
//##########################################################################
//################### Simulation::SharedData #########################
//##########################################################################
class Simulation__SharedData:
public Receiver::SharedData
{
public:
Simulation__SharedData(
Derivation* derivation,
Receiver::MessageHandlerSet &message_handlers,
Simulation::AttributeIndexSet &attribute_index,
int state_count
):
Receiver::SharedData(derivation, message_handlers),
activeAttributeIndex(&attribute_index),
stateCount(state_count)
{}
Simulation::AttributeIndexSet* activeAttributeIndex;
int stateCount;
};
inline Simulation::SharedData*
Simulation::GetSharedData()
{return Cast_Object(SharedData*,sharedData);}