Files
BT411/engine/MUNGA/AUDWTHR.h
T
arcattackandClaude Opus 4.8 c4be8d3a07 Audio: footstep volume chain FULLY mapped -- blocked on gait-state id mismatch (task #50)
Chain (every hop verified live): FootStep pulse (SetBodyAnimation, decay in
PerformAndWatch) -> AudioMatchOf match=1 -> Start(2.0) on the FootFall
DirectPatchSource... which the renderer DROPS because its volume is 0:
an AudioControlMixer (outCtl=3/Volume + a second outCtl=5 mixer) feeds the
source, and BOTH mixer inputs are 0 -- nothing ever sends them.

Eliminated as senders (all traced): AudioScaleOf scales (29 total, none target
the mixer), AudioControlMultiplier (one instance, other target), Random/
AudioSampleAndHold (RNG verified WORKING -- varied samples; RANDOM.cpp is in
the build, the self-init ctor runs).

HYPOTHESIS [T4, next session]: the mixer inputs are fed by AudioStateTriggers
on AnimationState keyed to the AUTHORED gait-clip ids (walk 2/3, run 8/9 =
per-gait footstep volume).  Our runtime body SM walks in states 12<->13 --
which the recovered MechAnimationState enum names RightStandToReverse/
LeftStandToReverse.  If the authored audio expects 2/3 for forward walk, the
runtime clip NUMBERING in the reconstructed gait SM is offset from the
authentic ids -- a locomotion-layer mismatch with implications beyond audio
(the audio config is an independent witness to the true clip numbering).
Verify via the AudioStateTrigger configs on the AnimationState watcher
(trigcfg dump exists) and cross-check the SetBodyAnimation clip table.

New diagnostics: [snh] SampleAndHold sends, [mix] mixer forwards with input
index + sum, [scalecfg] authored scale bindings/boundaries, [volset].

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

1591 lines
40 KiB
C++

#pragma once
#include <cstdlib>
#include "watcher.h"
#include "audio.h"
#include "simulate.h"
#include "objstrm.h"
#include "controls.h"
#include "motion.h"
//##########################################################################
//######################## AudioIdleWatcher ##########################
//##########################################################################
class AudioIdleWatcher:
public Component
{
public:
//
//-----------------------------------------------------------------------
// Constructor, Destructor, Testing
//-----------------------------------------------------------------------
//
AudioIdleWatcher(
PlugStream *stream,
Entity *entity
);
void
AudioIdleWatcherX(
AudioComponent *audio_component,
Entity *entity
);
~AudioIdleWatcher();
Logical
TestInstance() const;
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//-----------------------------------------------------------------------
// ReleaseLinkHandler
//-----------------------------------------------------------------------
//
void
ReleaseLinkHandler(
Socket *socket,
Plug *plug
);
//
//-----------------------------------------------------------------------
// Execute
//-----------------------------------------------------------------------
//
void
Execute();
protected:
//
//-----------------------------------------------------------------------
// Protected data
//-----------------------------------------------------------------------
//
SlotOf<AudioComponent*>
audioComponentSocket;
};
//##########################################################################
//########################### AudioWatcherOf #########################
//##########################################################################
template <class T> class AudioWatcherOf:
public AttributeWatcherOf<T>
{
public:
//
//--------------------------------------------------------------------
// Constructor, Destructor, Testing
//--------------------------------------------------------------------
//
AudioWatcherOf(
PlugStream *stream,
Entity *entity
);
~AudioWatcherOf();
Logical
TestInstance() const;
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//--------------------------------------------------------------------
// ReleaseLinkHandler
//--------------------------------------------------------------------
//
void
ReleaseLinkHandler(
Socket *socket,
Plug *plug
);
protected:
//
//--------------------------------------------------------------------
// Protected data
//--------------------------------------------------------------------
//
SlotOf<AudioComponent*>
audioComponentSocket;
};
//~~~~~~~~~~~~~~~~~~~~~~~~ AudioWatcherOf templates ~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioWatcherOf<T>::AudioWatcherOf(
PlugStream *stream,
Entity *entity
):
AttributeWatcherOf<T>(stream, entity),
audioComponentSocket(this)
{
//
// Get audio component
//
AudioComponent *audio_component;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
Check(audio_component);
audioComponentSocket.Add(audio_component);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioWatcherOf<T>::~AudioWatcherOf()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioWatcherOf<T>::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AttributeWatcherOf<T>::BuildFromPage(
stream, name_list, class_ID, object_ID
);
//
// Store audio_component object ID
//
CString audio_component_name("audio_component");
PlugStream_FindEntryAndWriteObjectID(
stream, name_list, audio_component_name
);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> Logical
AudioWatcherOf<T>::TestInstance() const
{
AttributeWatcherOf<T>::TestInstance();
Check(&audioComponentSocket);
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioWatcherOf<T>::ReleaseLinkHandler(
Socket *socket,
Plug *plug
)
{
if (socket == &audioComponentSocket)
{
Check(&audioComponentSocket);
Check(socket);
Unregister_Object(this);
delete this;
}
else
{
AttributeWatcherOf<T>::ReleaseLinkHandler(socket, plug);
}
}
//##########################################################################
//########################### AudioTriggerOf #########################
//##########################################################################
template <class T> class AudioTriggerOf:
public AudioWatcherOf<T>
{
public:
//
//--------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------
//
AudioTriggerOf(
PlugStream *stream,
Entity *entity
);
~AudioTriggerOf();
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//--------------------------------------------------------------------
// SendNotificationOfChange
//--------------------------------------------------------------------
//
void
SendNotificationOfChange();
//
//--------------------------------------------------------------------
// ExtractInterestingValue
//--------------------------------------------------------------------
//
virtual AudioControlValue
ExtractInterestingValue(const T *attribute_ptr);
private:
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
Scalar
attributeValueThreshold;
Logical
inverseTrigger;
AudioControlID
controlIDOn,
controlIDOff;
AudioControlValue
controlValueOn,
controlValueOff;
Logical
triggerOn;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioTriggerOf templates ~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioTriggerOf<T>::AudioTriggerOf(
PlugStream *stream,
Entity *entity
):
AudioWatcherOf<T>(stream, entity)
{
Check(simulation);
simulation->AddAudioWatcher(this);
//
// Get other fields
//
MemoryStream_Read(stream, &attributeValueThreshold);
MemoryStream_Read(stream, &inverseTrigger);
MemoryStream_Read(stream, &controlIDOn);
MemoryStream_Read(stream, &controlIDOff);
MemoryStream_Read(stream, &controlValueOn);
MemoryStream_Read(stream, &controlValueOff);
triggerOn = False;
if (getenv("BT_ATTRBIND_LOG")) { static int s_tc=0; if (s_tc++<80)
DEBUG_STREAM << "[trigcfg] attrPtr=" << (void*)attributePointer
<< " thresh=" << attributeValueThreshold
<< " inverse=" << (int)inverseTrigger
<< " onID=" << (int)controlIDOn << "/" << controlValueOn
<< " offID=" << (int)controlIDOff << "/" << controlValueOff
<< "\n" << std::flush; }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioTriggerOf<T>::~AudioTriggerOf()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioTriggerOf<T>::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioWatcherOf<T>::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store other fields
//
MEM_STRM_WRITE_ENTRY(
*stream, name_list, AudioControlValue, attribute_value_threshold
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, Logical, inverse_trigger
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, Enumeration, control_ID_on
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, Enumeration, control_ID_off
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, AudioControlValue, control_value_on
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, AudioControlValue, control_value_off
);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioTriggerOf<T>::SendNotificationOfChange()
{
//
// Get current value
//
T *attribute_ptr = GetCurrentPointer();
Check_Pointer(attribute_ptr);
Scalar current_value = ExtractInterestingValue(attribute_ptr);
if (getenv("BT_AUDIO_SPATIAL") && current_value > 0.0f) { static int s_tg=0; if (s_tg++<120)
DEBUG_STREAM << "[trigger] attrPtr=" << (void*)attributePointer
<< " val=" << current_value << " thresh=" << attributeValueThreshold
<< " armed=" << (int)!triggerOn << "\n" << std::flush; }
if (triggerOn)
{
if (
(!inverseTrigger && current_value <= attributeValueThreshold) ||
(inverseTrigger && current_value >= attributeValueThreshold)
)
{
Check(&audioComponentSocket);
Check(audioComponentSocket.GetCurrent());
#if 1
audioComponentSocket.GetCurrent()->ReceiveControl(
controlIDOff,
controlValueOff
);
#else
audioComponentSocket.GetCurrent()->PostReceiveControl(
controlIDOff,
controlValueOff
);
#endif
triggerOn = False;
}
}
else
{
if (
(!inverseTrigger && current_value > attributeValueThreshold) ||
(inverseTrigger && current_value < attributeValueThreshold)
)
{
Check(&audioComponentSocket);
Check(audioComponentSocket.GetCurrent());
#if 1
audioComponentSocket.GetCurrent()->ReceiveControl(
controlIDOn,
controlValueOn
);
#else
audioComponentSocket.GetCurrent()->PostReceiveControl(
controlIDOn,
controlValueOn
);
#endif
triggerOn = True;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> AudioControlValue
AudioTriggerOf<T>::ExtractInterestingValue(const T*)
{
Fail("AudioTriggerOf<T>::ExtractInterestingValue - Should never reach here");
return 0;
}
//##########################################################################
//########################### AudioScaleOf ###########################
//##########################################################################
template <class T> class AudioScaleOf:
public AudioWatcherOf<T>
{
public:
//
//--------------------------------------------------------------------
// Constructor, Destructor
//--------------------------------------------------------------------
//
AudioScaleOf(
PlugStream *stream,
Entity *entity
);
~AudioScaleOf();
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//--------------------------------------------------------------------
// SendNotificationOfChange
//--------------------------------------------------------------------
//
void
SendNotificationOfChange();
//
//--------------------------------------------------------------------
// ExtractInterestingValue
//--------------------------------------------------------------------
//
virtual AudioControlValue
ExtractInterestingValue(const T *attribute_ptr);
private:
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
Scalar
attributeValueBoundary1,
attributeValueBoundary2;
AudioControlID
controlID;
AudioControlValue
controlValueBoundary1,
controlValueBoundary2;
Scalar
exponent;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioScaleOf templates ~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioScaleOf<T>::AudioScaleOf(
PlugStream *stream,
Entity *entity
):
AudioWatcherOf<T>(stream, entity)
{
//
// Get audio component
//
AudioComponent *audio_component = audioComponentSocket.GetCurrent();
Check(audio_component);
audio_component->AddWatcher(this);
//
// Get other fields
//
MemoryStream_Read(stream, &attributeValueBoundary1);
MemoryStream_Read(stream, &attributeValueBoundary2);
MemoryStream_Read(stream, &controlID);
MemoryStream_Read(stream, &controlValueBoundary1);
MemoryStream_Read(stream, &controlValueBoundary2);
MemoryStream_Read(stream, &exponent);
if (getenv("BT_ATTRBIND_LOG")) { static int s_scf=0; if (s_scf++<160)
DEBUG_STREAM << "[scalecfg] attrPtr=" << (void*)attributePointer
<< " comp=" << (void*)audioComponentSocket.GetCurrent()
<< " ctlID=" << (int)controlID
<< " aB=[" << attributeValueBoundary1 << "," << attributeValueBoundary2 << "]"
<< " cB=[" << controlValueBoundary1 << "," << controlValueBoundary2 << "]\n" << std::flush; }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioScaleOf<T>::~AudioScaleOf()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioScaleOf<T>::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioWatcherOf<T>::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store other fields
//
MEM_STRM_WRITE_ENTRY(
*stream, name_list, Scalar, attribute_value_boundary1
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, Scalar, attribute_value_boundary2
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, Enumeration, control_ID
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, AudioControlValue, control_value_boundary1
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, AudioControlValue, control_value_boundary2
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, Scalar, exponent
);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioScaleOf<T>::SendNotificationOfChange()
{
//
// Get current value
//
T *attribute_ptr = GetCurrentPointer();
Check_Pointer(attribute_ptr);
Scalar current_value = ExtractInterestingValue(attribute_ptr);
//
// Clamp value within range
//
Scalar min_attribute_boundary =
Min(attributeValueBoundary1, attributeValueBoundary2);
Scalar max_attribute_boundary =
Max(attributeValueBoundary1, attributeValueBoundary2);
Clamp(current_value, min_attribute_boundary, max_attribute_boundary);
Verify(
current_value >= min_attribute_boundary &&
current_value <= max_attribute_boundary
);
//
// Calculate scale
//
Verify(!Small_Enough(attributeValueBoundary2 - attributeValueBoundary1));
Scalar current_scale =
(current_value - attributeValueBoundary1) /
(attributeValueBoundary2 - attributeValueBoundary1);
Verify(current_scale >= -1.0f && current_scale <= 1.0f);
//
// Apply exponent
//
if (exponent != 1.0f)
{
Scalar old_scale = current_scale; // HACK - for debugging
current_scale = pow(old_scale, exponent);
#if DEBUG_LEVEL>0
if (!(current_scale >= -1.0f && current_scale <= 1.0f))
{
Dump(old_scale);
Dump(exponent);
Dump(current_scale);
}
#endif
}
Verify(current_scale >= -1.0f && current_scale <= 1.0f);
//
// Calculate control value
//
AudioControlValue control_value =
current_scale * (controlValueBoundary2 - controlValueBoundary1) +
controlValueBoundary1;
#if DEBUG_LEVEL>0
AudioControlValue min_control_boundary =
Min(controlValueBoundary1, controlValueBoundary2);
AudioControlValue max_control_boundary =
Max(controlValueBoundary1, controlValueBoundary2);
Verify(
control_value >= min_control_boundary &&
control_value <= max_control_boundary
);
#endif
Check(&audioComponentSocket);
Check(audioComponentSocket.GetCurrent());
if (getenv("BT_AUDIO_SPATIAL") && control_value <= 0.0f) {
static int s_sc=0; if (s_sc++<400)
DEBUG_STREAM << "[spatial] scale->0 attrPtr=" << (void*)attributePointer << " comp=" << (void*)audioComponentSocket.GetCurrent() << " raw=" << current_value << " ctlID=" << (int)controlID << " ctl=" << control_value << " aB=[" << attributeValueBoundary1 << "," << attributeValueBoundary2 << "]" << " cB=[" << controlValueBoundary1 << "," << controlValueBoundary2 << "]\n" << std::flush; }
audioComponentSocket.GetCurrent()->ReceiveControl(
controlID,
control_value
);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> AudioControlValue
AudioScaleOf<T>::ExtractInterestingValue(const T*)
{
Fail("AudioScaleOf<T>::ExtractInterestingValue - Should never reach here");
return 0;
}
//##########################################################################
//########################## AudioMatchOf ############################
//##########################################################################
template <class T> class AudioMatchOf:
public AudioWatcherOf<T>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioMatchOf(
PlugStream *stream,
Entity *entity
);
~AudioMatchOf();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//-----------------------------------------------------------------------
// SendNotificationOfChange
//-----------------------------------------------------------------------
//
void
SendNotificationOfChange();
//
//-----------------------------------------------------------------------
// ExtractInterestingValue
//-----------------------------------------------------------------------
//
virtual int
ExtractInterestingValue(const T *attribute_ptr);
private:
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
int
attributeMatchValue;
AudioControlID
controlID;
AudioControlValue
controlValue;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioMatchOf templates ~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioMatchOf<T>::AudioMatchOf(
PlugStream *stream,
Entity *entity
):
AudioWatcherOf<T>(stream, entity)
{
Check(simulation);
simulation->AddAudioWatcher(this);
//
// Get other fields
//
MemoryStream_Read(stream, &attributeMatchValue);
MemoryStream_Read(stream, &controlID);
MemoryStream_Read(stream, &controlValue);
if (getenv("BT_ATTRBIND_LOG")) { static int s_mc=0; if (s_mc++<80)
DEBUG_STREAM << "[matchcfg] attrPtr=" << (void*)attributePointer
<< " match=" << attributeMatchValue
<< " ctlID=" << (int)controlID << " ctlVal=" << controlValue
<< "\n" << std::flush; }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioMatchOf<T>::~AudioMatchOf()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioMatchOf<T>::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioWatcherOf<T>::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store other fields
//
MEM_STRM_WRITE_ENTRY(
*stream, name_list, int, attribute_match_value
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, Enumeration, control_ID
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, AudioControlValue, control_value
);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioMatchOf<T>::SendNotificationOfChange()
{
//
// Get current value
//
T *attribute_ptr = GetCurrentPointer();
Check_Pointer(attribute_ptr);
int current_value = ExtractInterestingValue(attribute_ptr);
if (current_value == attributeMatchValue)
{
if (getenv("BT_AUDIO_SPATIAL")) { static int s_mf=0; if (s_mf++<40)
DEBUG_STREAM << "[matchfire] attrPtr=" << (void*)attributePointer << " comp=" << (void*)audioComponentSocket.GetCurrent() << " compClass=" << (int)audioComponentSocket.GetCurrent()->GetClassID()
<< " val=" << current_value << " -> ctl " << (int)controlID
<< "/" << controlValue << "\n" << std::flush; }
Check(&audioComponentSocket);
Check(audioComponentSocket.GetCurrent());
#if 1
audioComponentSocket.GetCurrent()->ReceiveControl(
controlID,
controlValue
);
#else
audioComponentSocket.GetCurrent()->PostReceiveControl(
controlID,
controlValue
);
#endif
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> int
AudioMatchOf<T>::ExtractInterestingValue(const T*)
{
Fail("AudioMatchOf<T>::ExtractInterestingValue - Should never reach here");
return 0;
}
//##########################################################################
//########################## AudioDeltaOf ############################
//##########################################################################
template <class T> class AudioDeltaOf:
public AudioWatcherOf<T>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioDeltaOf(
PlugStream *stream,
Entity *entity
);
~AudioDeltaOf();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//-----------------------------------------------------------------------
// SendNotificationOfChange
//-----------------------------------------------------------------------
//
void
SendNotificationOfChange();
private:
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
T
lastValue;
T
deltaTrigger;
AudioControlID
controlID;
AudioControlValue
controlValue;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioDeltaOf templates ~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioDeltaOf<T>::AudioDeltaOf(
PlugStream *stream,
Entity *entity
):
AudioWatcherOf<T>(stream, entity)
{
Check(simulation);
simulation->AddAudioWatcher(this);
MemoryStream_Read(stream, &controlID);
MemoryStream_Read(stream, &controlValue);
MemoryStream_Read(stream, &deltaTrigger);
lastValue = GetCurrentValue();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AudioDeltaOf<T>::~AudioDeltaOf()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioDeltaOf<T>::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioWatcherOf<T>::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// control_ID, control_value
//
MEM_STRM_WRITE_ENTRY(
*stream, name_list, Enumeration, control_ID
);
MEM_STRM_WRITE_ENTRY(
*stream, name_list, AudioControlValue, control_value
);
//
// delta_value
//
T delta_trigger = SMALL;
if (name_list->FindData("delta_trigger") != NULL)
{
Convert_From_Ascii(
(const char *)name_list->FindData("delta_trigger"),
&delta_trigger
);
}
MemoryStream_Write(stream, &delta_trigger);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AudioDeltaOf<T>::SendNotificationOfChange()
{
T *attribute_ptr;
T delta_change;
attribute_ptr = GetCurrentPointer();
Check_Pointer(attribute_ptr);
delta_change = *attribute_ptr - lastValue;
if (Abs(delta_change) >= deltaTrigger)
{
lastValue = *attribute_ptr;
Check(&audioComponentSocket);
Check(audioComponentSocket.GetCurrent());
#if 1
audioComponentSocket.GetCurrent()->ReceiveControl(
controlID,
controlValue
);
#else
audioComponentSocket.GetCurrent()->PostReceiveControl(
controlID,
controlValue
);
#endif
}
}
//##########################################################################
//########################### AudioMotionTrigger #####################
//##########################################################################
enum MotionType
{
LinearMotionType = 0,
AngularMotionType = 1
};
inline MemoryStream&
MemoryStream_Read(
MemoryStream *stream,
MotionType *ptr
)
{return stream->ReadBytes(ptr, sizeof(*ptr));}
inline MemoryStream&
MemoryStream_Write(
MemoryStream *stream,
const MotionType *ptr
)
{return stream->WriteBytes(ptr, sizeof(*ptr));}
enum MotionValue
{
XMotionValue = 0,
YMotionValue = 1,
ZMotionValue = 2,
LengthMotionValue = 3
};
inline MemoryStream&
MemoryStream_Read(
MemoryStream *stream,
MotionValue *ptr
)
{return stream->ReadBytes(ptr, sizeof(*ptr));}
inline MemoryStream&
MemoryStream_Write(
MemoryStream *stream,
const MotionValue *ptr
)
{return stream->WriteBytes(ptr, sizeof(*ptr));}
class AudioMotionTrigger:
public AudioTriggerOf<Motion>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioMotionTrigger(
PlugStream *stream,
Entity *entity
);
~AudioMotionTrigger();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//-----------------------------------------------------------------------
// ExtractInterestingValue
//-----------------------------------------------------------------------
//
AudioControlValue
ExtractInterestingValue(const Motion *attribute_ptr);
private:
//
//-----------------------------------------------------------------------
// DumpValue
//-----------------------------------------------------------------------
//
void
DumpValue(const Motion *attribute_ptr);
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
MotionType
motionType;
MotionValue
motionValue;
};
//##########################################################################
//########################### AudioMotionScale #######################
//##########################################################################
class AudioMotionScale:
public AudioScaleOf<Motion>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioMotionScale(
PlugStream *stream,
Entity *entity
);
~AudioMotionScale();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//-----------------------------------------------------------------------
// ExtractInterestingValue
//-----------------------------------------------------------------------
//
AudioControlValue
ExtractInterestingValue(const Motion *attribute_ptr);
private:
//
//-----------------------------------------------------------------------
// DumpValue
//-----------------------------------------------------------------------
//
void
DumpValue(const Motion *attribute_ptr);
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
MotionType
motionType;
MotionValue
motionValue;
};
//##########################################################################
//########################### AudioHingeScale #########################
//##########################################################################
class AudioHingeScale:
public AudioScaleOf<Hinge>
{
public:
//
//--------------------------------------------------------------------
// Constructor, Destructor, Testing
//--------------------------------------------------------------------
//
AudioHingeScale(
PlugStream *stream,
Entity *entity
);
~AudioHingeScale();
protected:
//
//--------------------------------------------------------------------
// ExtractInterestingValue
//--------------------------------------------------------------------
//
AudioControlValue
ExtractInterestingValue(const Hinge *attribute_ptr);
private:
//
//-----------------------------------------------------------------------
// DumpValue
//-----------------------------------------------------------------------
//
void
DumpValue(const Hinge *attribute_ptr);
};
//##########################################################################
//########################### AudioScalarTrigger #####################
//##########################################################################
class AudioScalarTrigger:
public AudioTriggerOf<Scalar>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioScalarTrigger(
PlugStream *stream,
Entity *entity
);
~AudioScalarTrigger();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//-----------------------------------------------------------------------
// ExtractInterestingValue
//-----------------------------------------------------------------------
//
AudioControlValue
ExtractInterestingValue(const Scalar *attribute_ptr);
};
//##########################################################################
//###################### AudioScalarDeltaTrigger #####################
//##########################################################################
class AudioScalarDeltaTrigger:
public AudioDeltaOf<Scalar>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioScalarDeltaTrigger(
PlugStream *stream,
Entity *entity
);
~AudioScalarDeltaTrigger();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
};
//##########################################################################
//########################### AudioScalarScale ########################
//##########################################################################
class AudioScalarScale:
public AudioScaleOf<Scalar>
{
public:
//
//--------------------------------------------------------------------
// Constructor, Destructor, Testing
//--------------------------------------------------------------------
//
AudioScalarScale(
PlugStream *stream,
Entity *entity
);
~AudioScalarScale();
protected:
//
//--------------------------------------------------------------------
// ExtractInterestingValue
//--------------------------------------------------------------------
//
AudioControlValue
ExtractInterestingValue(const Scalar *attribute_ptr);
};
//##########################################################################
//######################## AudioLogicalTrigger #######################
//##########################################################################
class AudioLogicalTrigger:
public AudioMatchOf<Logical>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioLogicalTrigger(
PlugStream *stream,
Entity *entity
);
~AudioLogicalTrigger();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//-----------------------------------------------------------------------
// ExtractInterestingValue
//-----------------------------------------------------------------------
//
int
ExtractInterestingValue(const Logical *attribute_ptr);
};
//##########################################################################
//###################### AudioEnumerationTrigger #####################
//##########################################################################
class AudioEnumerationTrigger:
public AudioMatchOf<Enumeration>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioEnumerationTrigger(
PlugStream *stream,
Entity *entity
);
~AudioEnumerationTrigger();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//-----------------------------------------------------------------------
// ExtractInterestingValue
//-----------------------------------------------------------------------
//
int
ExtractInterestingValue(const Enumeration *attribute_ptr);
};
//##########################################################################
//################### AudioEnumerationDeltaTrigger ###################
//##########################################################################
class AudioEnumerationDeltaTrigger:
public AudioDeltaOf<Enumeration>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioEnumerationDeltaTrigger(
PlugStream *stream,
Entity *entity
);
~AudioEnumerationDeltaTrigger();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
};
//##########################################################################
//####################### AudioIntegerTrigger ########################
//##########################################################################
class AudioIntegerTrigger:
public AudioTriggerOf<int>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioIntegerTrigger(
PlugStream *stream,
Entity *entity
);
~AudioIntegerTrigger();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//-----------------------------------------------------------------------
// ExtractInterestingValue
//-----------------------------------------------------------------------
//
AudioControlValue
ExtractInterestingValue(const int *attribute_ptr);
};
//##########################################################################
//################### AudioControlsButtonTrigger #####################
//##########################################################################
class AudioControlsButtonTrigger:
public AudioTriggerOf<ControlsButton>
{
public:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
AudioControlsButtonTrigger(
PlugStream *stream,
Entity *entity
);
~AudioControlsButtonTrigger();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//-----------------------------------------------------------------------
// ExtractInterestingValue
//-----------------------------------------------------------------------
//
AudioControlValue
ExtractInterestingValue(const ControlsButton *attribute_ptr);
};
//##########################################################################
//######################## AudioStateWatcher #########################
//##########################################################################
class AudioStateWatcher:
public AudioWatcherOf<StateIndicator>
{
public:
//
//--------------------------------------------------------------------
// Destructor
//--------------------------------------------------------------------
//
~AudioStateWatcher();
protected:
//
//--------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------
//
AudioStateWatcher(
PlugStream *stream,
Entity *entity
);
//
//--------------------------------------------------------------------
// SendNotificationOfChange
//--------------------------------------------------------------------
//
void
SendNotificationOfChange();
//
//--------------------------------------------------------------------
// StateChanged
//--------------------------------------------------------------------
//
virtual void
StateChanged(
Enumeration old_state,
Enumeration new_state
);
};
//##########################################################################
//########################### AudioStateTrigger ######################
//##########################################################################
class AudioStateTrigger:
public AudioStateWatcher
{
public:
//
//--------------------------------------------------------------------
// Constructor, Destructor
//--------------------------------------------------------------------
//
AudioStateTrigger(
PlugStream *stream,
Entity *entity
);
~AudioStateTrigger();
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
protected:
//
//--------------------------------------------------------------------
// StateChanged
//--------------------------------------------------------------------
//
void
StateChanged(
Enumeration old_state,
Enumeration new_state
);
private:
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
Enumeration
triggerState;
Logical
inverseTrigger;
AudioControlID
controlID;
AudioControlValue
controlValue;
Logical
excludeTransition;
Enumeration
excludeState;
};