Files
TeslaRel410/restoration/source410/MUNGA/AUDCMP.CPP
T
CydandClaude Fable 5 5b35eb973c 4.10 reconstruction: BTL4OPT.EXE links clean and BOOTS to the first staged brick
The reconstructed tree now produces a runnable binary with the authentic
1995 toolchain (BC4.52 / tlink32 / DPMI32):

- BTL4.CPP main TU reconstructed from the 4.11 Ghidra decomp (FUN_0040109c)
  + the 4.10 binary's own string pool + surviving RPL4TOOL.CPP house style;
  probe_main.cpp scaffold retired (BTL4.NOTES.md documents every decoded call)
- L4NET.CPP staged: L4NetworkManager ctor/dtor + 10 vtable-pulled virtuals
  (standalone-benign ones no-op, network ones Fail loudly) + NetNub client
  globals (Net_Common_Ptr=NULL routes L4File to its plain-DOS path)
- build410.sh: libs now built in the AUTHENTIC makefile member order
  (MUNGA.MAK / mungal4.mak / BT.MAK / BTL4.MAK). Order is load-bearing:
  tlink emits static-init records in module pull order, and alphabetical
  order booted into a null-vptr crash (IcomManager::ClassDerivations
  constructing before parent NetworkClient::ClassDerivations). Also fixed
  stage_link to the proven 32-bit lib set (SOSDBXC+SOSMBXC, no WATTCPLG)
- BOXTREE.HPP MemoryBlock unify, BTL4GRND notify stubs, remaining engine
  backfills (audio/gauge/resource/stream TUs) that closed the deep ledger

Smoke test (DOSBox-X + 32RTM, copy of the pod BT tree, our exe swapped in):
  BattleTech v4.10
  BTL4Application::BTL4Application
  l4net.cpp(22): L4NetworkManager -- l4net.cpp not yet reconstructed
Static init, main, -egg parse, BTL4.RES load (version 1.0.6 check passes),
ApplicationManager and the BTL4Application ctor chain all execute real
reconstructed code; boot halts at the first staged Fail() as designed.
Next brick: the real l4net.cpp body.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:05:53 -05:00

1565 lines
41 KiB
C++

# if !defined(MUNGA_HPP)
# include <munga.hpp>
# endif
#pragma hdrstop
# if !defined(AUDCMP_HPP)
# include <audcmp.hpp>
# endif
# if !defined(AUDSRC_HPP)
# include <audsrc.hpp>
# endif
# if !defined(RANDOM_HPP)
# include <random.hpp>
# endif
# if !defined(CONTROLS_HPP)
# include <controls.hpp>
# endif
# if !defined(OBJSTRM_HPP)
# include <objstrm.hpp>
# endif
# if !defined(SUBSYSTM_HPP)
# include <subsystm.hpp>
# endif
# if !defined(NAMELIST_HPP)
# include <namelist.hpp>
# endif
//#############################################################################
//######################### AudioMessageWatcher #########################
//#############################################################################
//
//#############################################################################
//#############################################################################
//
AudioMessageWatcher::AudioMessageWatcher(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
audioComponentSocket(NULL),
messageTap(NULL)
{
Check(stream);
Check(entity);
//
// HACK - Get simulation pointer using names
//
Simulation *simulation;
CString subsystem_name;
MemoryStream_Read(stream, &subsystem_name);
if ((simulation = entity->FindSubsystem(subsystem_name)) == NULL)
{
#if DEBUG_LEVEL>0
{
CString entity_name("Entity");
if (!(subsystem_name == entity_name))
{
Dump(subsystem_name);
}
Verify(subsystem_name == entity_name);
}
#else
{
CString entity_name("Entity");
if (!(subsystem_name == entity_name))
{
DEBUG_STREAM <<
"MessageWatcher::MessageWatcher - subsystem " <<
subsystem_name <<
"\n";
Fail("MessageWatcher::MessageWatcher - subsystem not found\n");
}
}
#endif
simulation = entity;
}
Check(simulation);
//
// Get message id
//
Receiver::MessageID message_ID;
MemoryStream_Read(stream, &message_ID);
//
// Get audio component, control ID, control value
//
AudioComponent *audio_component;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
MemoryStream_Read(stream, &controlID);
MemoryStream_Read(stream, &controlValue);
audioComponentSocket.Add(audio_component);
//
// Make the message tap
//
messageTap =
MakeMessageTap(
simulation->GetDerivation(),
(ScanCallback)&AudioMessageWatcher::MessageTapScanCallback,
message_ID,
simulation
);
Register_Object(messageTap);
entity->AddAudioComponent(this);
#if DEBUG_LEVEL>0
verifyReceiver = simulation;
verifyMessageID = message_ID;
#endif
}
//
//#############################################################################
//#############################################################################
//
AudioMessageWatcher::~AudioMessageWatcher()
{
Unregister_Object(messageTap);
delete messageTap;
}
//
//#############################################################################
//#############################################################################
//
void
AudioMessageWatcher::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// HACK - Store simulation pointer using names
//
MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, subsystem);
//
// Store message ID
//
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, message_ID);
//
// Store audio_component, control ID, control value
//
CString audio_component_name("audio_component");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, control_value);
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioMessageWatcher::TestInstance() const
{
Component::TestInstance();
if (messageTap != NULL)
{
Check(messageTap);
}
Check(&audioComponentSocket);
return True;
}
//
//#############################################################################
//#############################################################################
//
#if DEBUG_LEVEL>0
void
AudioMessageWatcher::MessageTapScanCallback(
Receiver::Message *message,
Receiver *receiver
)
#else
void
AudioMessageWatcher::MessageTapScanCallback(
Receiver::Message *message,
Receiver*
)
#endif
{
Check(this);
Check(message);
Check(receiver);
Verify(verifyReceiver == receiver);
Verify(verifyMessageID == message->messageID);
//
// Send the audio control message
//
if (DoesMessageMatch(message))
{
Check(audioComponentSocket.GetCurrent());
#if 1
audioComponentSocket.GetCurrent()->ReceiveControl(
controlID,
controlValue
);
#else
audioComponentSocket.GetCurrent()->PostReceiveControl(
controlID,
controlValue
);
#endif
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioMessageWatcher::ReceiveControl(
AudioControlID,
AudioControlValue
)
{
}
//#############################################################################
//################# AudioControlsButtonMessageWatcher ###################
//#############################################################################
//
//#############################################################################
//#############################################################################
//
AudioControlsButtonMessageWatcher::AudioControlsButtonMessageWatcher(
PlugStream *stream,
Entity *entity
):
AudioMessageWatcher(stream, entity)
{
}
//
//#############################################################################
//#############################################################################
//
AudioControlsButtonMessageWatcher::~AudioControlsButtonMessageWatcher()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioControlsButtonMessageWatcher::DoesMessageMatch(
Receiver::Message *message
)
{
Check(this);
Check(message);
ReceiverDataMessageOf<ControlsButton> *controls_button_message =
Cast_Object(
ReceiverDataMessageOf<ControlsButton>*,
message
);
Check(controls_button_message);
return (controls_button_message->dataContents > 0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlSend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioControlSend::~AudioControlSend()
{
}
//
//#############################################################################
//#############################################################################
//
AudioControlSend::AudioControlSend(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream)
{
AudioComponent *audio_component;
AudioControlID control_ID;
AudioControlValue control_value;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
MemoryStream_Read(stream, &control_ID);
MemoryStream_Read(stream, &control_value);
if (getenv("BT_ATTRBIND_LOG")) { static int s_sd=0; if (s_sd++<80)
DEBUG_STREAM << "[sendcfg] tgt=" << (void*)audio_component
<< " ctl=" << (int)control_ID << "/" << control_value
<< " entity=" << (void*)entity << "\n" << flush; }
Check(entity);
entity->AddAudioComponent(this);
Check(audio_component);
#if 1
audio_component->ReceiveControl(control_ID, control_value);
#else
audio_component->PostReceiveControl(control_ID, control_value);
#endif
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSend::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store fields
//
CString audio_component_name("audio_component");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, control_value);
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSend::ReceiveControl(
AudioControlID,
AudioControlValue
)
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlSplitter ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioControlSplitter::AudioControlSplitter(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
audioComponentSocket(NULL)
{
int i, number_of_entries;
MemoryStream_Read(stream, &number_of_entries);
for (i = 0; i < number_of_entries; i++)
{
AudioComponent *audio_component;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
Check(audio_component);
audioComponentSocket.Add(audio_component);
audio_component->AddWatcher(this);
}
Check(entity);
entity->AddAudioComponent(this);
}
//
//#############################################################################
//#############################################################################
//
AudioControlSplitter::~AudioControlSplitter()
{
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSplitter::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Count number of entries
//
int number_of_entries = 0;
NameList::Entry *entry;
Check(name_list);
entry = name_list->GetFirstEntry();
while (entry != NULL)
{
Check(entry);
if (entry->IsName("audio_component"))
number_of_entries++;
entry = entry->GetNextEntry();
}
//
// Store entries
//
MemoryStream_Write(stream, &number_of_entries);
Check(name_list);
entry = name_list->GetFirstEntry();
while (entry != NULL)
{
Check(entry);
if (entry->IsName("audio_component"))
{
CString object_name;
ObjectID object_ID;
Check_Pointer(entry->GetChar());
object_name = entry->GetChar();
Check(stream);
object_ID = stream->FindObjectID(object_name);
if (object_ID == NullObjectID)
{
cout << "AudioControlSplitter::BuildFromPage - object_name == ";
cout << object_name << "\n";
Fail("AudioControlSplitter::BuildFromPage - object_ID == NullObjectID");
}
Verify(object_ID != NullObjectID);
MemoryStream_Write(stream, &object_ID);
}
entry = entry->GetNextEntry();
}
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioControlSplitter::TestInstance() const
{
AudioComponent::TestInstance();
Check(&audioComponentSocket);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSplitter::ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
)
{
Check(this);
//
// Send to all of the components in the socket
//
SChainIteratorOf<AudioComponent*> iterator(&audioComponentSocket);
AudioComponent *audio_component;
Check(&iterator);
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" << flush; }
audio_component->ReceiveControl(control_ID, control_value);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlMixer ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioControlMixer::~AudioControlMixer()
{
}
//
//#############################################################################
//#############################################################################
//
AudioControlMixer::AudioControlMixer(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
audioComponentSocket(NULL)
{
AudioComponent *audio_component;
AudioControlID first_input_control_ID;
AudioControlID last_input_control_ID;
AudioControlID output_control_ID;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
MemoryStream_Read(stream, &first_input_control_ID);
MemoryStream_Read(stream, &last_input_control_ID);
MemoryStream_Read(stream, &output_control_ID);
AudioControlMixerX(
audio_component,
entity,
first_input_control_ID,
last_input_control_ID,
output_control_ID
);
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlMixer::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store fields
//
CString audio_component_name("audio_component");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, first_input_control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, last_input_control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, output_control_ID);
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlMixer::AudioControlMixerX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID first_input_control_ID,
AudioControlID last_input_control_ID,
AudioControlID output_control_ID
)
{
//
// Set up the control mix parameters
//
firstInputControlID = first_input_control_ID;
outputControlID = output_control_ID;
Verify(last_input_control_ID > first_input_control_ID);
numberOfInputs = last_input_control_ID - first_input_control_ID + 1;
Verify(numberOfInputs <= AUDIO_CONTROL_MIXER_MAX_CONTROLS);
for (int i = 0; i < numberOfInputs; i++)
{
Verify(i >= 0 && i < AUDIO_CONTROL_MIXER_MAX_CONTROLS);
controlValueArray[i] = 0.0f;
}
//
// Remember the audio component to mix to and add this
// component to the entity
//
Check(audio_component);
audioComponentSocket.Add(audio_component);
audio_component->AddWatcher(this);
Check(entity);
entity->AddAudioComponent(this);
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioControlMixer::TestInstance() const
{
AudioComponent::TestInstance();
Check(&audioComponentSocket);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlMixer::ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
)
{
Check(this);
//
// Index the controller into the mix table
//
int index = control_ID - firstInputControlID;
if (index >= 0 && index < numberOfInputs)
{
//
// Set the control value
//
Verify(index >= 0 && index < AUDIO_CONTROL_MIXER_MAX_CONTROLS);
controlValueArray[index] = control_value;
//
// Mix the new control value
//
AudioControlValue mixed_value = 0.0f;
for (int i = 0; i < numberOfInputs; i++)
{
Verify(i >= 0 && i < AUDIO_CONTROL_MIXER_MAX_CONTROLS);
mixed_value += controlValueArray[i];
}
Check(audioComponentSocket.GetCurrent());
if (getenv("BT_AUDIO_SPATIAL")) { static int s_mix=0; if (s_mix++<80)
DEBUG_STREAM << "[mix] mixer=" << (void*)this << " -> tgt=" << (void*)audioComponentSocket.GetCurrent()
<< " outCtl=" << (int)outputControlID << " in[" << index << "]=" << control_value
<< " sum=" << mixed_value << "\n" << flush; }
audioComponentSocket.GetCurrent()->ReceiveControl(
outputControlID,
mixed_value
);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlMultiplier ~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioControlMultiplier::~AudioControlMultiplier()
{
}
//
//#############################################################################
//#############################################################################
//
AudioControlMultiplier::AudioControlMultiplier(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
audioComponentSocket(NULL)
{
AudioComponent *audio_component;
AudioControlID first_input_control_ID;
AudioControlID last_input_control_ID;
AudioControlID output_control_ID;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
MemoryStream_Read(stream, &first_input_control_ID);
MemoryStream_Read(stream, &last_input_control_ID);
MemoryStream_Read(stream, &output_control_ID);
AudioControlMultiplierX(
audio_component,
entity,
first_input_control_ID,
last_input_control_ID,
output_control_ID
);
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlMultiplier::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store fields
//
CString audio_component_name("audio_component");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, first_input_control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, last_input_control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, output_control_ID);
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlMultiplier::AudioControlMultiplierX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID first_input_control_ID,
AudioControlID last_input_control_ID,
AudioControlID output_control_ID
)
{
//
// Set up the control mix parameters
//
firstInputControlID = first_input_control_ID;
outputControlID = output_control_ID;
Verify(last_input_control_ID > first_input_control_ID);
numberOfInputs = last_input_control_ID - first_input_control_ID + 1;
Verify(numberOfInputs <= AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS);
for (int i = 0; i < numberOfInputs; i++)
{
Verify(i >= 0 && i < AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS);
controlValueArray[i] = 1.0f;
}
//
// Remember the audio component to mix to and add this
// component to the entity
//
Check(audio_component);
audioComponentSocket.Add(audio_component);
audio_component->AddWatcher(this);
Check(entity);
entity->AddAudioComponent(this);
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioControlMultiplier::TestInstance() const
{
AudioComponent::TestInstance();
Check(&audioComponentSocket);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlMultiplier::ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
)
{
Check(this);
//
// Index the controller into the mix table
//
int index = control_ID - firstInputControlID;
if (index >= 0 && index < numberOfInputs)
{
//
// Set the control value
//
Verify(index >= 0 && index < AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS);
controlValueArray[index] = control_value;
//
// Multiply the new control value
//
AudioControlValue mult_value = 1.0f;
for (int i = 0; i < numberOfInputs; i++)
{
Verify(i >= 0 && i < AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS);
mult_value *= controlValueArray[i];
}
Check(audioComponentSocket.GetCurrent());
if (getenv("BT_AUDIO_SPATIAL") && mult_value <= 0.0f) { static int s_mx=0; if (s_mx++<300)
DEBUG_STREAM << "[mult0] mult=" << (void*)this << " -> tgt=" << (void*)audioComponentSocket.GetCurrent()
<< " in[" << index << "]=" << control_value << " product=" << mult_value << "\n" << flush; }
audioComponentSocket.GetCurrent()->ReceiveControl(
outputControlID,
mult_value
);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlSmoother ~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioControlSmoother::~AudioControlSmoother()
{
}
//
//#############################################################################
//#############################################################################
//
AudioControlSmoother::AudioControlSmoother(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
audioComponentSocket(NULL)
{
//
// Get audio component
//
AudioComponent *audio_component;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
//
// Get audio control id, sample size, and initial fill value
//
size_t number_of_samples;
AudioControlValue initial_fill_value;
AudioControlID control_ID;
MemoryStream_Read(stream, &control_ID);
MemoryStream_Read(stream, &number_of_samples);
MemoryStream_Read(stream, &initial_fill_value);
audioControlAverage.SetSize(number_of_samples, initial_fill_value);
if (getenv("BT_ATTRBIND_LOG")) { static int s_sm=0; if (s_sm++<40)
DEBUG_STREAM << "[smoothcfg] this=" << (void*)this << " ctlID=" << (int)control_ID
<< " samples=" << (int)number_of_samples << " fill=" << initial_fill_value
<< "\n" << flush; }
AudioControlSmootherX(
audio_component,
entity,
control_ID
);
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSmoother::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store audio component
//
CString audio_component_name("audio_component");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name);
//
// Store audio control id, sample size, and initial fill value
//
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, size_t, number_of_samples);
AudioControlValue initial_fill_value = 0.0f;
if (name_list->FindData("initial_fill_value") != NULL)
{
Check_Pointer(name_list->FindData("initial_fill_value"));
Convert_From_Ascii(
(const char *)name_list->FindData("initial_fill_value"),
&initial_fill_value
);
}
MemoryStream_Write(stream, &initial_fill_value);
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSmoother::AudioControlSmootherX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID control_ID
)
{
controlID = control_ID;
//
// Remember the audio component and add this
// component to the entity
//
Check(audio_component);
audioComponentSocket.Add(audio_component);
audio_component->AddWatcher(this);
Check(entity);
entity->AddAudioComponent(this);
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioControlSmoother::TestInstance() const
{
AudioComponent::TestInstance();
Check(&audioComponentSocket);
Check(&audioControlAverage);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSmoother::ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
)
{
Check(this);
if (control_ID == controlID)
{
audioControlAverage.Add(control_value);
Check(audioComponentSocket.GetCurrent());
audioComponentSocket.GetCurrent()->ReceiveControl(
controlID,
audioControlAverage.CalculateOlympicAverage()
);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResourceSelector ~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioResourceSelector::~AudioResourceSelector()
{
}
//
//#############################################################################
//#############################################################################
//
AudioResourceSelector::AudioResourceSelector(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
audioSourceSocket(NULL)
{
AudioSource *audio_source;
AudioResourceIndex *audio_resource_index;
AudioControlID control_ID;
AudioControlValue min_control_value;
AudioControlValue max_control_value;
Logical dump_value;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_source);
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_resource_index);
MemoryStream_Read(stream, &control_ID);
MemoryStream_Read(stream, &min_control_value);
MemoryStream_Read(stream, &max_control_value);
MemoryStream_Read(stream, &dump_value);
AudioResourceSelectorX(
audio_source,
entity,
audio_resource_index,
control_ID,
min_control_value,
max_control_value,
dump_value
);
}
//
//#############################################################################
//#############################################################################
//
void
AudioResourceSelector::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store fields
//
CString audio_source_name("audio_source");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_source_name);
CString audio_resource_index_name("audio_resource_index");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_resource_index_name);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, min_control_value);
MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, max_control_value);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, dump_value);
}
//
//#############################################################################
//#############################################################################
//
void
AudioResourceSelector::AudioResourceSelectorX(
AudioSource *audio_source,
Entity *entity,
AudioResourceIndex *audio_resource_index,
AudioControlID control_ID,
AudioControlValue min_control_value,
AudioControlValue max_control_value,
Logical dump_value
)
{
controlID = control_ID;
minControlValue = min_control_value;
maxControlValue = max_control_value;
dumpValue = dump_value;
Check(audio_resource_index);
audioResourceIndex = audio_resource_index;
Check(audio_source);
audioSourceSocket.Add(audio_source);
audio_source->AddWatcher(this);
Check(entity);
entity->AddAudioComponent(this);
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioResourceSelector::TestInstance() const
{
AudioComponent::TestInstance();
Check(&audioSourceSocket);
Check(audioResourceIndex);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioResourceSelector::ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
)
{
Check(this);
if (control_ID == controlID)
{
AudioComponent *audio_component;
AudioSource *audio_source;
audio_component = audioSourceSocket.GetCurrent();
audio_source = Cast_Object(AudioSource*, audio_component);
Check(audio_source);
if (audio_source->GetAudioSourceState() == StoppedAudioSourceState)
{
AudioResource *audio_resource;
int index;
Clamp(control_value, minControlValue, maxControlValue);
Verify(!Small_Enough(maxControlValue - minControlValue));
index =
( ((Scalar)audioResourceIndex->GetSize()-1.0f) *
(control_value - minControlValue) /
(maxControlValue - minControlValue) ) + 0.5f;
#if DEBUG_LEVEL>0
if (!(index >= 0 && index < audioResourceIndex->GetSize()))
{
Dump(control_value);
Dump(index);
Dump(audioResourceIndex->GetSize());
}
#endif
Verify(index >= 0 && index < audioResourceIndex->GetSize());
#if DEBUG_LEVEL>0
if (dumpValue)
{
Tell("index:" << index);
Tell("; size: " << audioResourceIndex->GetSize() << "\n");
}
#endif
audio_resource = audioResourceIndex->GetAudioResource(index);
Check(audio_resource);
audio_source->SetAudioResource(audio_resource);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSampleAndHold ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioSampleAndHold::AudioSampleAndHold(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
audioComponentSocket(NULL)
{
AudioComponent *audio_component;
AudioControlID control_ID;
Scalar seconds;
AudioTime sample_duration;
Scalar min_value;
Scalar max_value;
//
// audio_component
//
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
//
// control_ID, sample_duration
//
MemoryStream_Read(stream, &control_ID);
MemoryStream_Read(stream, &seconds);
sample_duration = seconds;
//
// min_value, max_value
//
MemoryStream_Read(stream, &min_value);
MemoryStream_Read(stream, &max_value);
AudioSampleAndHoldX(
audio_component,
entity,
control_ID,
sample_duration,
min_value,
max_value
);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSampleAndHold::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// audio_component
//
CString audio_component_name("audio_component");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name);
//
// control_ID, sample_duration
//
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, sample_duration);
//
// min_value, max_value
//
Scalar min_value = 0.0f;
Scalar max_value = 1.0f;
if (name_list->FindData("min_value") != NULL)
{
Convert_From_Ascii(
(const char *)name_list->FindData("min_value"),
&min_value
);
}
if (name_list->FindData("max_value") != NULL)
{
Convert_From_Ascii(
(const char *)name_list->FindData("max_value"),
&max_value
);
}
Verify(max_value > min_value);
MemoryStream_Write(stream, &min_value);
MemoryStream_Write(stream, &max_value);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSampleAndHold::AudioSampleAndHoldX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID audio_control_ID,
const AudioTime &sample_duration,
Scalar min_value,
Scalar max_value
)
{
audioControlID = audio_control_ID;
currentValue = 0.0f;
nextSampleTime = AudioTime::Now();
sampleDuration = sample_duration;
Verify(max_value > min_value);
minValue = min_value;
maxValue = max_value;
Check(audio_component);
audioComponentSocket.Add(audio_component);
audio_component->AddWatcher(this);
Check(entity);
entity->AddAudioComponent(this);
}
//
//#############################################################################
//#############################################################################
//
AudioSampleAndHold::~AudioSampleAndHold()
{
}
//
//#############################################################################
//#############################################################################
//
void
AudioSampleAndHold::Execute()
{
Check(this);
AudioComponent::Execute();
if (AudioTime::Now() > nextSampleTime)
{
SampleAndHold();
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioSampleAndHold::ReceiveControl(
AudioControlID control_ID,
AudioControlValue
)
{
Check(this);
if (control_ID == StartAudioControlID)
{
SampleAndHold();
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioSampleAndHold::SampleAndHold()
{
Check(this);
Scalar random_sample = Random;
Verify(0.0f <= random_sample && random_sample <= 1.0f);
Verify(maxValue > minValue);
currentValue = minValue + random_sample * (maxValue - minValue);
nextSampleTime = AudioTime::Now();
nextSampleTime += sampleDuration;
Check(audioComponentSocket.GetCurrent());
if (getenv("BT_AUDIO_SPATIAL")) { static int s_sh=0; if (s_sh++<60)
DEBUG_STREAM << "[snh] this=" << (void*)this << " -> tgt=" << (void*)audioComponentSocket.GetCurrent()
<< " ctlID=" << (int)audioControlID << " val=" << currentValue
<< " range=[" << minValue << "," << maxValue << "]\n" << flush; }
audioComponentSocket.GetCurrent()->ReceiveControl(
audioControlID,
currentValue
);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLFO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioLFO::AudioLFO(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
audioComponentSocket(NULL)
{
AudioComponent *audio_component;
AudioControlID control_ID;
AudioLFOWaveForm wave_form;
Scalar the_period;
AudioControlValue min_value;
AudioControlValue max_value;
Logical dump_value;
//
// audio_component
//
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
//
// control_ID, wave_form, period
//
MemoryStream_Read(stream, &control_ID);
MemoryStream_Read(stream, &wave_form);
MemoryStream_Read(stream, &the_period);
//
// min_value, max_value, dump_value
//
MemoryStream_Read(stream, &min_value);
MemoryStream_Read(stream, &max_value);
MemoryStream_Read(stream, &dump_value);
AudioLFOX(
audio_component,
entity,
control_ID,
wave_form,
the_period,
min_value,
max_value,
dump_value
);
}
//
//#############################################################################
//#############################################################################
//
void
AudioLFO::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// audio_component
//
CString audio_component_name("audio_component");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name);
//
// control_ID, wave_form, period
//
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, wave_form);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, period);
//
// min_value, max_value
//
MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, min_value);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, max_value);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, dump_value);
}
//
//#############################################################################
//#############################################################################
//
void
AudioLFO::AudioLFOX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID audio_control_ID,
AudioLFOWaveForm wave_form,
Scalar the_period,
AudioControlValue min_value,
AudioControlValue max_value,
Logical dump_value
)
{
Check(audio_component);
audioComponentSocket.Add(audio_component);
audio_component->AddWatcher(this);
audioControlID = audio_control_ID;
waveForm = wave_form;
minValue = min_value;
maxValue = max_value;
Verify(max_value > min_value);
period = the_period;
startTime = AudioTime::Now();
dumpValue = dump_value;
Check(entity);
entity->AddAudioComponent(this);
}
//
//#############################################################################
//#############################################################################
//
AudioLFO::~AudioLFO()
{
}
//
//#############################################################################
//#############################################################################
//
void
AudioLFO::Execute()
{
Check(this);
AudioComponent::Execute();
Generate();
}
//
//#############################################################################
//#############################################################################
//
void
AudioLFO::ReceiveControl(
AudioControlID control_ID,
AudioControlValue
)
{
Check(this);
if (control_ID == StartAudioControlID)
{
Generate();
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioLFO::Generate()
{
Check(this);
//
// HACK - For now, everything is sinusoidal
//
// res = sin( (now-start) * (PI/period) )
// val = min + ( 0.5 * (res+1) ) * (max - min)
//
Scalar time_factor;
Scalar sample;
Scalar current_value;
time_factor = AudioTime::Now();
Verify(!Small_Enough((Scalar)period));
time_factor = (time_factor - (Scalar)startTime) / (Scalar)period;
sample = (sin(time_factor * PI) + 1.0f) * 0.5f;
Verify(0.0f <= sample && sample <= 1.0f);
Verify(maxValue > minValue);
current_value = minValue + sample * (maxValue - minValue);
#if DEBUG_LEVEL>0
if (dumpValue)
{
Dump(current_value);
}
#endif
Check(audioComponentSocket.GetCurrent());
audioComponentSocket.GetCurrent()->ReceiveControl(
audioControlID,
current_value
);
}