Files
RP412/MUNGA_L4/L4AUDRND.h
T
CydandClaude Opus 5 4e8392fcfb PageUp and PageDown are the volume knob
The cabinets had no volume control - they ran at unity and left level to an
external amplifier - so a player without that hardware had nowhere to turn
it down but environ.ini and a restart. PageUp and PageDown now step the
master volume by 0.05 while you play, from silent to double, and whatever
you leave it on is written to volume.cfg beside the exe and used from then
on. The environ.ini figure decides where a machine that has never been
touched starts out; the keys are the knob, and a knob stays where it was
left.

Page keys because they produce no typed character, so they cannot collide
with the character-keyed commands the engine already answers to, nothing
else in RP binds them, and they are on every keyboard including tenkeyless.

They are polled rather than read off the key-message path, which is worth
recording because the message path looked like the obvious home for them
and was tried first. RP's keyboard pump only takes WM_KEYUP, WM_SYSKEYUP
and WM_CHAR off the front of the queue, and the front end runs message
loops of its own, so key messages get raced for and lost: six deliberate,
well-spaced presses arrived as two. Fine for the abort chord, useless for
something you tap repeatedly to find a level. Reading key state directly
costs nothing and cannot be dropped. That losses figure is a pre-existing
property of the input path, not something this change introduced, and is
worth knowing before anything else gets bound there.

Builds clean, runs, and does not fire unprompted. The step function itself
is proven - it was driven end to end through the message path before the
switch, stepping the right way, clamping, and persisting. What I could not
test from here is the polling trigger, because Windows would not hand the
game foreground and injecting keys without it would have sprayed them
across whatever else was open.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 00:00:36 -05:00

216 lines
5.1 KiB
C++

#pragma once
#include "..\munga\audrend.h"
#include "l4audhdw.h"
#include "l4audio.h"
#include "l4audres.h"
#include "openal/al.h"
//
// Master volume, standing in for the amplifier the cabinets had. Stepped by
// PgUp/PgDn (L4APP.cpp) and persisted to volume.cfg; see L4AUDRND.cpp.
//
extern float gRPMasterVolume;
void RPAudioMasterVolumeStep(int direction);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class L4AudioRenderer:
public AudioRenderer
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, Testing
//
public:
L4AudioRenderer(
RendererRate render_rate,
Logical mission_review_mode
);
~L4AudioRenderer();
Logical
TestInstance() const;
virtual void ReleaseSourceSet(SourceSet &sourceSet);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Renderer support
//
public:
void
Initialize();
public:
void
NotifyOfNewInterestingEntity(Entity *interesting_entity);
void
NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity);
protected:
void
ExecuteImplementation(
RendererComplexity complexity_update,
RendererOrigin::InterestingEntityIterator *iterator
);
private:
void
LoadMissionImplementation(Mission *mission);
void
ShutdownImplementation();
void
SuspendImplementation();
void
ResumeImplementation();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Audio hardware accessors
//
public:
/* AudioCard*
GetFrontCard();
AudioCard*
GetRearCard();*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Audio Source support
//
public:
void
StartRequest(L4AudioSource *audio_source);
void
StopRequest(L4AudioSource *audio_source);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods
//
private:
void
CalculateMix();
void
RunningSourceCheckup();
//void
// RunningAudioSourceSort();
void
DormantSourceCheckup();
void
AudioSourceStopMaintenance(L4AudioSource *source);
void
AudioSourceSuspendMaintenance(L4AudioSource *source);
Logical
RequestAudioResources(
L4AudioSource *audio_source,
SourceSet *source_result
);
Logical
RequestAudioChannels(
AudioVoiceCount voices_requested,
SourceSet *source_request
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
Logical
missionReviewMode;
/* AudioHardware
audioHardware;*/
L4AudioResourceManager
audioResourceManager;
AudioFrameCount
nextCalculateMixFrame;
typedef VChainOf<L4AudioSource*, AudioWeighting>
RunningSourceSocket;
typedef VChainIteratorOf<L4AudioSource*, AudioWeighting>
RunningSourceIterator;
RunningSourceSocket
runningAudioSourceSocket;
typedef ChainOf<L4AudioSource*>
DormantSourceSocket;
typedef ChainIteratorOf<L4AudioSource*>
DormantSourceIterator;
DormantSourceSocket
dormantAudioSourceSocket;
typedef VChainOf<L4AudioSource*, Enumeration>
MixingSourceSocket;
typedef VChainIteratorOf<L4AudioSource*, Enumeration>
MixingSourceIterator;
MixingSourceSocket
mixingAudioSourceSocket;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer inlines ~~~~~~~~~~~~~~~~~~~~~~~~
/*inline AudioCard*
L4AudioRenderer::GetFrontCard()
{
Check(this);
return audioHardware.GetFrontCard();
}
inline AudioCard*
L4AudioRenderer::GetRearCard()
{
Check(this);
return audioHardware.GetRearCard();
}*/
//~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer profile macros ~~~~~~~~~~~~~~~~~~~~
#if defined(TRACE_AUDIO_RENDERER_RUNNING_SOURCES)
extern BitTrace Audio_Renderer_Running_Sources;
#define SET_AUDIO_RUNNING_SOURCES() Audio_Renderer_Running_Sources.Set()
#define CLEAR_AUDIO_RUNNING_SOURCES() Audio_Renderer_Running_Sources.Clear()
#else
#define SET_AUDIO_RUNNING_SOURCES()
#define CLEAR_AUDIO_RUNNING_SOURCES()
#endif
#if defined(TRACE_AUDIO_RENDERER_RUNNING_SORT)
extern BitTrace Audio_Renderer_Running_Sort;
#define SET_AUDIO_RUNNING_SORT() Audio_Renderer_Running_Sort.Set()
#define CLEAR_AUDIO_RUNNING_SORT() Audio_Renderer_Running_Sort.Clear()
#else
#define SET_AUDIO_RUNNING_SORT()
#define CLEAR_AUDIO_RUNNING_SORT()
#endif
#if defined(TRACE_AUDIO_RENDERER_CALCULATE_MIX)
extern BitTrace Audio_Renderer_Calculate_Mix;
#define SET_AUDIO_CALCULATE_MIX() Audio_Renderer_Calculate_Mix.Set()
#define CLEAR_AUDIO_CALCULATE_MIX() Audio_Renderer_Calculate_Mix.Clear()
#else
#define SET_AUDIO_CALCULATE_MIX()
#define CLEAR_AUDIO_CALCULATE_MIX()
#endif
#if defined(TRACE_AUDIO_RENDERER_EXECUTE_SOURCES)
extern BitTrace Audio_Renderer_Execute_Sources;
#define SET_AUDIO_EXECUTE_SOURCES() Audio_Renderer_Execute_Sources.Set()
#define CLEAR_AUDIO_EXECUTE_SOURCES() Audio_Renderer_Execute_Sources.Clear()
#else
#define SET_AUDIO_EXECUTE_SOURCES()
#define CLEAR_AUDIO_EXECUTE_SOURCES()
#endif
#if defined(TRACE_AUDIO_RENDERER_DORMANT_SOURCES)
extern BitTrace Audio_Renderer_Dormant_Sources;
#define SET_AUDIO_DORMANT_SOURCES() Audio_Renderer_Dormant_Sources.Set()
#define CLEAR_AUDIO_DORMANT_SOURCES() Audio_Renderer_Dormant_Sources.Clear()
#else
#define SET_AUDIO_DORMANT_SOURCES()
#define CLEAR_AUDIO_DORMANT_SOURCES()
#endif