Archival snapshot of the Virtual World Entertainment Tesla cockpit software, 1994-1996: MUNGA engine and L4 pod layer source (Borland C++ 5.0), BT/RP game code, and game content (models, audio, maps, gauges, Division renderer data). Includes third-party libraries: Division dVS/DPL graphics, HMI SOS audio, WATTCP networking. Files are preserved byte-for-byte (.gitattributes disables all line-ending conversion). README.md documents the layout, target hardware, and toolchain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
489 lines
12 KiB
C++
489 lines
12 KiB
C++
//===========================================================================//
|
|
// File: audio.hh //
|
|
// Project: MUNGA Brick: Audio manager //
|
|
// Contents: //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 01/30/95 ECH Initial coding. //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include <munga.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(AUDIO_HPP)
|
|
# include <audio.hpp>
|
|
#endif
|
|
|
|
#if !defined(AUDREND_HPP)
|
|
# include <audrend.hpp>
|
|
#endif
|
|
|
|
#if !defined(APP_HPP)
|
|
#include <app.hpp>
|
|
#endif
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Audio Constants ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
const Scalar AudioDoubleTriggerCutoff = 0.2f;
|
|
|
|
const AudioControlValue MaxAudioVolume = 1.0f;
|
|
const AudioControlValue MinAudioVolume = 0.0f;
|
|
const AudioControlValue LowAudioVolumeThreshold = 0.3f;
|
|
|
|
const AudioControlValue MaxAudioBrightness = 1.0f;
|
|
const AudioControlValue MinAudioBrightness = 0.0f;
|
|
|
|
const AudioControlValue MaxAudioAttack = 1.0f;
|
|
const AudioControlValue MinAudioAttack = 0.0f;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioHead::AudioHead():
|
|
headEntitySocket(NULL)
|
|
{
|
|
//
|
|
// Start frame counter at 0, other counts should be at
|
|
// NullAudioFrameCount
|
|
//
|
|
audioFrameCount = 0;
|
|
|
|
//
|
|
// Other audio parameters
|
|
//
|
|
clippingRadius = 100.0f;
|
|
distanceBetweenEars = 1.0f;
|
|
amplitudeRollOffExponent = 1.0f;
|
|
amplitudeRollOffKnee = 10.0f,
|
|
amplitudeRollOffDistanceScale = 0.05f;
|
|
highFrequencyRollOffExponent = 0.5f;
|
|
highFrequencyRollOffKnee = 10.0f;
|
|
highFrequencyRollOffDistanceScale = 0.05f;
|
|
reverbToDryRatio = 0.1f;
|
|
audioSoundSpeed = 345.0f;
|
|
audioDopplerConstant = 20.0f;
|
|
sourceCompressionExponent = 0.5f;
|
|
sourceCompressionScale = 0.5f;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioHead::~AudioHead()
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Logical
|
|
AudioHead::TestInstance() const
|
|
{
|
|
Check(&headEntitySocket);
|
|
return True;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioHead::LinkToEntity(Entity *entity)
|
|
{
|
|
Check(this);
|
|
Check(entity);
|
|
|
|
//
|
|
// Remove existing entity, add new one
|
|
//
|
|
if (headEntitySocket.GetCurrent() != NULL)
|
|
{
|
|
headEntitySocket.Remove();
|
|
}
|
|
headEntitySocket.Add(entity);
|
|
|
|
#if 0
|
|
//
|
|
// Make the new clipping sphere
|
|
//
|
|
clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
LinearMatrix
|
|
AudioHead::GetEarToWorld()
|
|
{
|
|
Check(this);
|
|
|
|
Entity *entity = headEntitySocket.GetCurrent();
|
|
Check(entity);
|
|
return entity->localToWorld;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioHead::Execute()
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
// Increment frame counter
|
|
//
|
|
audioFrameCount++;
|
|
Verify(audioFrameCount < LONG_MAX);
|
|
|
|
#if 0
|
|
//
|
|
// Get the entity
|
|
//
|
|
Entity *entity = headEntitySocket.GetCurrent();
|
|
Check(entity);
|
|
|
|
//
|
|
// Make the new clipping sphere
|
|
//
|
|
clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioHead::DefineClippingSphere(Scalar radius)
|
|
{
|
|
Check(this);
|
|
|
|
clippingRadius = radius;
|
|
|
|
#if 0
|
|
//
|
|
// Get entity position
|
|
//
|
|
Entity *entity;
|
|
Point3D position(0.0f, 0.0f, 0.0f);
|
|
|
|
if ((entity = headEntitySocket.GetCurrent()) != NULL)
|
|
{
|
|
Check(entity);
|
|
position = entity->localOrigin.linearPosition;
|
|
}
|
|
|
|
//
|
|
// Make the new clipping sphere
|
|
//
|
|
clippingSphere.SetCurrentOrigin(position);
|
|
clippingSphere.SetReferenceRadius(radius);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Logical
|
|
AudioHead::IsPointClipped(const Point3D &point)
|
|
{
|
|
Check(this);
|
|
|
|
Entity
|
|
*entity;
|
|
Vector3D
|
|
difference;
|
|
|
|
entity = headEntitySocket.GetCurrent();
|
|
Check(entity);
|
|
difference.Subtract(entity->localOrigin.linearPosition, point);
|
|
return difference.LengthSquared() > clippingRadius*clippingRadius;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioHead::ControlDopplerEffect(
|
|
Scalar doppler_constant,
|
|
Scalar sound_speed
|
|
)
|
|
{
|
|
Check(this);
|
|
audioDopplerConstant = doppler_constant;
|
|
audioSoundSpeed = sound_speed;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioHead::ControlAmplitudeRollOff(
|
|
Scalar exponent,
|
|
Scalar amplitude_rolloff_knee,
|
|
Scalar distance_scale
|
|
)
|
|
{
|
|
Check(this);
|
|
amplitudeRollOffExponent = exponent;
|
|
amplitudeRollOffKnee = amplitude_rolloff_knee;
|
|
amplitudeRollOffDistanceScale = distance_scale;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioHead::ControlHighFrequencyRollOff(
|
|
Scalar exponent,
|
|
Scalar high_frequency_rolloff_knee,
|
|
Scalar distance_scale
|
|
)
|
|
{
|
|
Check(this);
|
|
highFrequencyRollOffExponent = exponent;
|
|
highFrequencyRollOffKnee = high_frequency_rolloff_knee;
|
|
highFrequencyRollOffDistanceScale = distance_scale;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioHead::ControlSourceCompression(
|
|
Scalar exponent,
|
|
Scalar scale
|
|
)
|
|
{
|
|
Check(this);
|
|
sourceCompressionExponent = exponent;
|
|
sourceCompressionScale = scale;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioHead::SetPositionalCulling(Logical)
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioComponent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
const Receiver::HandlerEntry
|
|
AudioComponent::MessageHandlerEntries[]=
|
|
{
|
|
{
|
|
AudioComponent::ReceiveControlMessageID,
|
|
"ReceiveControl",
|
|
(AudioComponent::Handler)&AudioComponent::ReceiveControlMessageHandler
|
|
}
|
|
};
|
|
|
|
AudioComponent::MessageHandlerSet
|
|
AudioComponent::MessageHandlers(
|
|
ELEMENTS(AudioComponent::MessageHandlerEntries),
|
|
AudioComponent::MessageHandlerEntries,
|
|
Component::MessageHandlers
|
|
);
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Derivation
|
|
AudioComponent::ClassDerivations(
|
|
Component::ClassDerivations,
|
|
"AudioComponent"
|
|
);
|
|
|
|
AudioComponent::SharedData
|
|
AudioComponent::DefaultData(
|
|
AudioComponent::ClassDerivations,
|
|
AudioComponent::MessageHandlers
|
|
);
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioComponent::AudioComponent(
|
|
PlugStream *stream,
|
|
SharedData &shared_data
|
|
):
|
|
Component(stream, shared_data),
|
|
audioWatcherSocket(NULL)
|
|
{
|
|
nextExecuteWatcherFrame = NullAudioFrameCount;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioComponent::~AudioComponent()
|
|
{
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Logical
|
|
AudioComponent::TestInstance() const
|
|
{
|
|
if (!IsDerivedFrom(ClassDerivations))
|
|
{
|
|
return False;
|
|
}
|
|
Check(&audioWatcherSocket);
|
|
return True;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioComponent::ExecuteWatchers()
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
// Execute watchers if this is the next watcher frame
|
|
//
|
|
AudioFrameCount
|
|
audio_frame_count;
|
|
|
|
Check(application);
|
|
Check(application->GetAudioRenderer());
|
|
audio_frame_count = application->GetAudioRenderer()->GetAudioFrameCount();
|
|
if (nextExecuteWatcherFrame <= audio_frame_count)
|
|
{
|
|
nextExecuteWatcherFrame = audio_frame_count + DefaultAudioFrameDelay;
|
|
|
|
//
|
|
// Execute watchers
|
|
//
|
|
ChainIteratorOf<Component*>
|
|
iterator(&audioWatcherSocket);
|
|
Component
|
|
*component;
|
|
|
|
while ((component = iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(component);
|
|
component->Execute();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioComponent::Execute()
|
|
{
|
|
Check(this);
|
|
ExecuteWatchers();
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioComponent::ReceiveControl(
|
|
AudioControlID,
|
|
AudioControlValue
|
|
)
|
|
{
|
|
Fail("AudioComponent::ReceiveControl - Should never reach here");
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioComponent::PostReceiveControl(
|
|
AudioControlID control_ID,
|
|
AudioControlValue control_value
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
ReceiveControlMessage
|
|
message(control_ID, control_value);
|
|
|
|
Check(application);
|
|
// ECH 1/26/96 - application->Post(HighEventPriority, this, &message);
|
|
application->Post(DefaultEventPriority, this, &message);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioComponent::ReceiveControlMessageHandler(ReceiveControlMessage *message)
|
|
{
|
|
Check(this);
|
|
Check(message);
|
|
ReceiveControl(message->controlID, message->controlValue);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage ~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
AudioComponent__ReceiveControlMessage::AudioComponent__ReceiveControlMessage(
|
|
AudioControlID control_ID,
|
|
AudioControlValue control_value
|
|
):
|
|
Receiver::Message(
|
|
AudioComponent::ReceiveControlMessageID,
|
|
sizeof(AudioComponent__ReceiveControlMessage)
|
|
)
|
|
{
|
|
controlID = control_ID;
|
|
controlValue = control_value;
|
|
}
|
|
|