Files
RP412/MUNGA/AUDIO.h
T
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet',
built on the MUNGA engine and its L4 (Win32/DirectX) platform layer:

- MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend
- RP / RP_L4: Red Planet game logic and Win32 application
- DivLoader, Setup1: asset loader and installer project
- lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies

Removed stale Subversion metadata and added .gitignore/.gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:59:51 -05:00

656 lines
14 KiB
C++

#pragma once
#include "style.h"
#include "entity.h"
#include "sphere.h"
#include "slot.h"
#include "table.h"
class PlugStream;
//
//--------------------------------------------------------------------------
// Support types
//--------------------------------------------------------------------------
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef long AudioTick;
typedef long AudioDivisionsPerBeat;
typedef long AudioTempo;
typedef long AudioFrameCount;
const AudioFrameCount NullAudioFrameCount = -1;
const AudioFrameCount DefaultAudioFrameDelay = 2;
extern const Scalar AudioDoubleTriggerCutoff;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Resource types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef int AudioResourceID;
typedef int AudioVoiceCount;
typedef Scalar AudioRadiationProfile;
typedef Scalar AudioPitchCents;
enum AudioRenderType
{
TransientAudioRenderType = 0,
SustainedAudioRenderType = 1
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Source types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
enum AudioRepresentation
{
InternalAudioRepresentation = 0,
ExternalAudioRepresentation = 1
};
#define AUDIO_SOURCE_PRIORITY_COUNT (5)
enum AudioSourcePriority
{
MinAudioSourcePriority = 0,
LowAudioSourcePriority = 1,
MedAudioSourcePriority = 2,
HighAudioSourcePriority = 3,
MaxAudioSourcePriority = 4
};
enum AudioSourceState
{
StoppedAudioSourceState = 0,
DormantAudioSourceState = 1,
RunningAudioSourceState = 2,
SuspendedAudioSourceState = 3
};
enum AudioSourceMixPresence
{
ManualAudioSourceMixPresence = 0,
MaxAudioSourceMixPresence = 1,
HighAudioSourceMixPresence = 2,
MedAudioSourceMixPresence = 3,
LowAudioSourceMixPresence = 4,
MinAudioSourceMixPresence = 5
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Control types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
enum AudioControlID
{
NullAudioControlID = 0,
StartAudioControlID,
StopAudioControlID,
VolumeAudioControlID,
PitchAudioControlID,
BrightnessAudioControlID,
AttackVolumeAudioControlID,
AttackTimeAudioControlID,
NoteAudioControlID,
IdleAudioControlID,
DurationAudioControlID,
FlushMessagesAudioControlID,
TempoAudioControlID,
AudioControlIDCount
};
typedef Scalar AudioControlValue;
extern const AudioControlValue MaxAudioVolume;
extern const AudioControlValue MinAudioVolume;
extern const AudioControlValue LowAudioVolumeThreshold;
extern const AudioControlValue MaxAudioBrightness;
extern const AudioControlValue MinAudioBrightness;
extern const AudioControlValue MaxAudioAttack;
extern const AudioControlValue MinAudioAttack;
#if 0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioClippingSphere ~~~~~~~~~~~~~~~~~~~~~~~~~~
class AudioClippingSphere SIGNATURED
{
public:
AudioClippingSphere();
~AudioClippingSphere();
void
SetReferenceRadius(Scalar radius);
void
SetCurrentOrigin(const Point3D &origin);
void
SetCurrentScale(Scalar scale);
Logical
Contains(const Point3D &point) const;
private:
Scalar
referenceRadius;
Sphere
currentSphere;
};
//~~~~~~~~~~~~~~~~~~~~~~~ AudioClippingSphere inlines ~~~~~~~~~~~~~~~~~~~~~~
inline AudioClippingSphere::AudioClippingSphere():
referenceRadius(100.0f),
currentSphere(0.0f, 0.0f, 0.0f, 100.0f)
{
}
inline AudioClippingSphere::~AudioClippingSphere()
{
}
inline void
AudioClippingSphere::SetReferenceRadius(Scalar radius)
{
Check(this);
referenceRadius = radius;
currentSphere.radius = radius;
}
inline void
AudioClippingSphere::SetCurrentOrigin(const Point3D &origin)
{
Check(this);
currentSphere.center = origin;
}
inline void
AudioClippingSphere::SetCurrentScale(Scalar scale)
{
Check(this);
currentSphere.radius = scale * referenceRadius;
}
inline Logical
AudioClippingSphere::Contains(const Point3D &point) const
{
Check(this);
return currentSphere.Contains(point);
}
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class AudioSource;
class AudioHead SIGNATURED
{
public:
//
//-----------------------------------------------------------------------
// Construction, Destruction, Testing
//-----------------------------------------------------------------------
//
AudioHead();
~AudioHead();
Logical
TestInstance() const;
//
//-----------------------------------------------------------------------
// Get current frame of audio simulation
//-----------------------------------------------------------------------
//
AudioFrameCount
GetAudioFrameCount()
{return audioFrameCount;}
//
//-----------------------------------------------------------------------
// Sets the location and orientation of the head
//-----------------------------------------------------------------------
//
virtual void
LinkToEntity(Entity *entity);
Entity*
GetHeadEntity();
//
//-----------------------------------------------------------------------
// Get the ear to world linear matrix
//-----------------------------------------------------------------------
//
virtual LinearMatrix
GetEarToWorld();
//
//-----------------------------------------------------------------------
// Execute
//-----------------------------------------------------------------------
//
virtual void
Execute();
//
//-----------------------------------------------------------------------
// Sets the distance between ears. Expressed in meters.
//-----------------------------------------------------------------------
//
void
SetDistanceBetweenEars(Scalar distance)
{distanceBetweenEars = distance;}
Scalar
GetDistanceBetweenEars()
{return distanceBetweenEars;}
//
//-----------------------------------------------------------------------
// Controls Doppler effects
//-----------------------------------------------------------------------
//
void
ControlDopplerEffect(
Scalar doppler_constant,
Scalar sound_speed
);
Scalar
GetAudioSoundSpeed()
{return audioSoundSpeed;}
AudioPitchCents
GetAudioDopplerConstant()
{return audioDopplerConstant;}
//
//-----------------------------------------------------------------------
// Reverb scaling
//-----------------------------------------------------------------------
//
void
SetReverbToDryRatio(Scalar ratio)
{reverbToDryRatio = ratio;}
Scalar
GetReverbToDryRatio()
{return reverbToDryRatio;}
// HACK
void
SetGlobalReverbScale(Scalar global_reverb_scale)
{globalReverbScale = global_reverb_scale;}
Scalar
GetGlobalReverbScale()
{return globalReverbScale;}
//
//-----------------------------------------------------------------------
// Controls the attenuation of an audio source with respect to its
// distance from the head.
//-----------------------------------------------------------------------
//
void
ControlAmplitudeRollOff(
Scalar exponent,
Scalar amplitude_rolloff_knee,
Scalar distance_scale
);
Scalar
GetAmplitudeRollOffExponent()
{return amplitudeRollOffExponent;}
Scalar
GetAmplitudeRollOffKnee()
{return amplitudeRollOffKnee;}
Scalar
GetAmplitudeRollOffDistanceScale()
{return amplitudeRollOffDistanceScale;}
//
//-----------------------------------------------------------------------
// Controls the attenuation of the high frequencies
// of an audio source with respect to its distance from
// the head.
//-----------------------------------------------------------------------
//
void
ControlHighFrequencyRollOff(
Scalar exponent,
Scalar high_frequency_rolloff_knee,
Scalar distance_scale
);
Scalar
GetHighFrequencyRollOffExponent()
{return highFrequencyRollOffExponent;}
Scalar
GetHighFrequencyRollOffKnee()
{return highFrequencyRollOffKnee;}
Scalar
GetHighFrequencyRollOffDistanceScale()
{return highFrequencyRollOffDistanceScale;}
//
//-----------------------------------------------------------------------
// Controls source compression
//-----------------------------------------------------------------------
//
void
ControlSourceCompression(
Scalar exponent,
Scalar scale
);
Scalar
GetSourceCompressionExponent()
{return sourceCompressionExponent;}
Scalar
GetSourceCompressionScale()
{return sourceCompressionScale;}
//
//-----------------------------------------------------------------------
// Defines the audio clipping sphere
//-----------------------------------------------------------------------
//
void
DefineClippingSphere(Scalar radius);
Logical
IsPointClipped(const Point3D &point);
Scalar
GetClippingRadius()
{return clippingRadius;}
//
//-----------------------------------------------------------------------
// ITD Difference
//-----------------------------------------------------------------------
//
void
SetITDDifference(Scalar itd_difference)
{itdDifference = itd_difference;}
Scalar
GetITDDifference()
{return itdDifference;}
//
//-----------------------------------------------------------------------
// The SetPositionalCulling method allows the rendering process to
// not play audio locations whose positions are masked by other
// audio sources. This has found to be useful for controlling
// audio when resources are limited, but must be
// selectable globally or on a per audio effect basis.
//-----------------------------------------------------------------------
//
void
SetPositionalCulling(Logical turn_on);
private:
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
AudioFrameCount
audioFrameCount;
SlotOf<Entity*>
headEntitySocket;
Scalar
clippingRadius;
Scalar
distanceBetweenEars;
Scalar
amplitudeRollOffExponent,
amplitudeRollOffKnee,
amplitudeRollOffDistanceScale;
Scalar
highFrequencyRollOffExponent,
highFrequencyRollOffKnee,
highFrequencyRollOffDistanceScale;
Scalar
reverbToDryRatio;
Scalar
audioSoundSpeed;
Scalar
audioDopplerConstant;
Scalar
sourceCompressionExponent,
sourceCompressionScale;
Scalar
itdDifference;
Scalar
globalReverbScale;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead inlines ~~~~~~~~~~~~~~~~~~~~~~~~~
inline Entity*
AudioHead::GetHeadEntity()
{
Check(this);
return headEntitySocket.GetCurrent();
}
//##########################################################################
//######################### AudioComponent ###########################
//##########################################################################
class AudioComponent__ReceiveControlMessage;
class AudioComponent:
public Component
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, Testing
//
public:
AudioComponent(
PlugStream *stream,
SharedData &shared_data = DefaultData
);
~AudioComponent();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Audio Component Methods
//
public:
void
AddWatcher(Component *component);
void
ExecuteWatchers();
void
Execute();
virtual void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
void
PostReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
enum {
ReceiveControlMessageID = Component::NextMessageID,
NextMessageID
};
typedef AudioComponent__ReceiveControlMessage
ReceiveControlMessage;
static const HandlerEntry
MessageHandlerEntries[];
//static MessageHandlerSet MessageHandlers;
static MessageHandlerSet& GetMessageHandlers();
void
ReceiveControlMessageHandler(
ReceiveControlMessage *message
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
static Derivation *GetClassDerivations();
static SharedData
DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private Data
//
private:
AudioFrameCount
nextExecuteWatcherFrame;
ChainOf<Component*>
audioWatcherSocket;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioComponent inlines ~~~~~~~~~~~~~~~~~~~~~~~~
inline void
AudioComponent::AddWatcher(Component *component)
{
Check(component);
Check(&audioWatcherSocket);
audioWatcherSocket.Add(component);
}
//~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage ~~~~~~~~~~~~~~~~~
class AudioComponent__ReceiveControlMessage:
public Receiver::Message
{
friend class AudioComponent;
public:
AudioComponent__ReceiveControlMessage(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
AudioControlID
controlID;
AudioControlValue
controlValue;
};
//~~~~~~~~~~~~~~~~~~~~~~~~ Resource type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioRenderType *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioRenderType *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioRepresentation *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioRepresentation *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Source type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioSourceState *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioSourceState *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioSourcePriority *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioSourcePriority *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioSourceMixPresence *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioSourceMixPresence *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Control type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioControlID *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioControlID *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}