The obnoxious always-on clicking was the cockpit CONFIGURE-MODE ticker: an
authored looped sequence gated by an AudioIntegerTrigger with threshold -1 on
<subsystem>.ConfigureActivePress (the held-configure-button index; -1 = none).
The attribute was one of the inert-pad redirects -- the pad reads 0 = "button 0
held forever" -> the ticker Start-fired at load and pulsed 2.7/s eternally.
Found via [sendcfg]/[seqstart] traces: the first seq start immediately follows
the trigcfg(thresh=-1, onID=Start) construction on the pad address.
Fix: real int configureActivePress = -1 APPENDED to Sensor ("Avionics") and
Myomers, registered in their attribute tables. Both classes are byte-exact
factory allocs, so the sizeof locks AND the placement-new alloc constants are
bumped TOGETHER (Sensor 0x328->0x32C, Myomers 0x358->0x35C) -- the tripwire
caught a mid-layout insert (seekVoltage@0x330 shift) and a fixed-alloc overrun
before they shipped; member moved to the true tail. Wiring the live value
(EnterConfiguration/ExitConfiguration sets/clears the index) restores the
authored hold-to-configure tick later; idle -1 is the correct silent state.
VERIFIED: ProgramButton01 plays ZERO times (was the 2.7/s chirp);
ConfigureActivePress binds real (vtbl=FFFFFFFF = the -1); FootFallInt at 0.98
gain; stable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1544 lines
39 KiB
C++
1544 lines
39 KiB
C++
#include <cstdlib>
|
|
#include "munga.h"
|
|
#pragma hdrstop
|
|
|
|
#include "audcmp.h"
|
|
#include "audsrc.h"
|
|
#include "random.h"
|
|
#include "controls.h"
|
|
#include "objstrm.h"
|
|
#include "subsystm.h"
|
|
#include "namelist.h"
|
|
|
|
//#############################################################################
|
|
//######################### 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" << std::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)
|
|
{
|
|
std::cout << "AudioControlSplitter::BuildFromPage - object_name == ";
|
|
std::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" << std::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" << std::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" << std::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);
|
|
|
|
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" << std::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
|
|
);
|
|
}
|