Audio Phase 3 (AUDIO_FIDELITY F9/F11/F12): EFX lowpass + reverb split + cockpit placement

New L4AUDEFX bridge (OpenAL Soft ALC_EXT_EFX): one EAXReverb aux slot at the
authentic AUDIO.INI global_reverb_scale (0.3) + a scratch AL_FILTER_LOWPASS
(params copied at attach).

F9 filters (was: computed then thrown away -- everything full-bright at all
distances): Dynamic3D ExecuteModel drives GAINHF from highFreqCutoffScale x
brightnessScale x maxMIDIFilterCutoff, UNGATED (decomp part_008.c:7496,
7589-7604 -- every moving 3D sound dulls with distance per the AUDIO.INI
knee-60/exp-2.0 model); Static3D from brightness x max (:7831-7884); Direct
inside its existing gated NRPN-rate block.  AWE 100-8000 Hz curve -> EFX
5 kHz-reference gainhf via a 2-pole approximation [T3 curve, endpoints exact].

F11 reverb (was: bone-dry everywhere): 3D patch sources attach an aux send at
Start, exactly where the original sent CC91 = global_reverb_scale
(part_008.c:7278-7394); Direct cockpit sources keep CC91=0 -- dry.  The
wet-exterior vs dry-cockpit contrast is back.

F12 placement (was: every cockpit sound dead-center): DirectPatchSource
Start places sources by the authored 6-value position enum (front/rear card
+ pan CC10, decomp @00463848/@004638a8) as listener-relative directions,
composed with the zone L/C/R pan.  New PatchResource GetBankID/GetPatchID
pass-throughs (the LOD accessor is protected).

Regression (35s drive+fire): EFX READY, stable, deliveries unregressed, no AL
errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-16 11:59:39 -05:00
co-authored by Claude Opus 4.8
parent aa004eb7b8
commit 0ca7d269d2
7 changed files with 266 additions and 0 deletions
+62
View File
@@ -5,6 +5,7 @@
#include "l4audio.h"
#include "l4audlvl.h"
#include "l4audefx.h"
#include "l4app.h"
#include "l4audrnd.h"
#include "..\munga\namelist.h"
@@ -964,6 +965,31 @@ void
channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE);
break;
}*/
// (task #50, AUDIO_FIDELITY F12) the original routed each Direct cockpit
// source by its authored 6-value position enum (front/rear CARD + pan
// CC10 left/center/right). Reproduce as a listener-relative placement;
// a zone's own L/R pan (stereo-pair presets) offsets on top. The
// distance model is AL_NONE, so this affects direction only, never gain.
{
float px = 0.0f, pz = -1.0f; // Front, centered
switch (audioPosition)
{
case FrontDirectPatchPosition: px = 0.0f; pz = -1.0f; break;
case RearDirectPatchPosition: px = 0.0f; pz = 1.0f; break;
case FrontLeftDirectPatchPosition: px = -0.7f; pz = -0.7f; break;
case FrontRightDirectPatchPosition: px = 0.7f; pz = -0.7f; break;
case RearLeftDirectPatchPosition: px = -0.7f; pz = 0.7f; break;
case RearRightDirectPatchPosition: px = 0.7f; pz = 0.7f; break;
}
for (int _i = 0; _i < channelSet.count; ++_i)
{
SAMPLEINFO zinfo = PRESET_getSampleInfo(
patch_resource->GetBankID(), patch_resource->GetPatchID(), _i);
float pan_x = (zinfo.chan == CHANNEL_LEFT) ? -0.5f :
(zinfo.chan == CHANNEL_RIGHT) ? 0.5f : 0.0f;
alSource3f(channelSet.sources[_i], AL_POSITION, px + pan_x, 0.0f, pz);
}
}
//
// Set midi history to default control values
@@ -1082,6 +1108,13 @@ void
if (Abs(filter_difference) >= filter_resolution)
{
lastMIDIFilterCutoff = midi_filter_cutoff;
// (task #50, AUDIO_FIDELITY F9) the original sent this cutoff as
// AWE NRPN 21; the EFX lowpass is the modern sink (was a dead
// bookkeeping write -- ctl-5 Brightness played full-bright).
float gainhf = EFX_CutoffScaleToGainHF(
(float)lastMIDIFilterCutoff / (float)MIDI_MAX_CONTROL_VALUE);
for (int _i = 0; _i < channelSet.count; ++_i)
EFX_SetSourceLowpassGainHF(channelSet.sources[_i], gainhf);
}
}
@@ -1260,6 +1293,12 @@ void
channel->SendController(MIDI_REVERB_CONTROL, midi_reverb_level);
channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE);
}*/
// (task #50, AUDIO_FIDELITY F11) the CC91 send above is the authentic
// wet-exterior contrast (global_reverb_scale on every 3D channel, decomp
// part_008.c:7278-7394); the EFX aux slot is the modern sink. Cockpit
// Direct sources stay dry (their CC91 was 0).
for (int _i = 0; _i < channelSet.count; ++_i)
EFX_AttachReverbSend(channelSet.sources[_i]);
//
// Set the channels to correct pan
@@ -1459,11 +1498,22 @@ void
<< " loc=(" << locationPosition.x << "," << locationPosition.z << ")"
<< " dist=" << posMag << " vol=" << volume_scale << "\n" << std::flush; }
// (task #50, AUDIO_FIDELITY F9) the original drove the AWE filter cutoff
// from highFreqCutoffScale x brightnessScale on this dynamic path --
// UNGATED, all channels (part_008.c:7496,7589-7604): every moving 3D
// sound gets duller with distance (AUDIO.INI knee 60 / exponent 2.0).
float dyn_gainhf = EFX_CutoffScaleToGainHF(
(float)(GetAudioLocation()->GetHighFreqCutoffScale()
* CalculateSourceBrightnessScale()
* (Scalar)patch_resource->GetMaxMIDIFilterCutoff()
/ (Scalar)MIDI_MAX_CONTROL_VALUE));
for (int i=0; i < channelSet.count; i++)
{
alSource3f(channelSet.sources[i],AL_POSITION,pos.x,pos.y,pos.z);
alSourcef(channelSet.sources[i], AL_GAIN, volume_scale * volume_scale); // FIDELITY F4: CC7 squared law (linear was ~+6 dB at mid volumes)
alSource3f(channelSet.sources[i],AL_VELOCITY,-relative_velocity.x,-relative_velocity.y,-relative_velocity.z);
EFX_SetSourceLowpassGainHF(channelSet.sources[i], dyn_gainhf);
}
}
@@ -1786,6 +1836,10 @@ void
channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE);
}
}*/
// (task #50, AUDIO_FIDELITY F11) static 3D sources are wet like the
// dynamic ones (the CC91 block above); Direct cockpit stays dry.
for (int _i = 0; _i < channelSet.count; ++_i)
EFX_AttachReverbSend(channelSet.sources[_i]);
//
// Set the channels to correct pan
@@ -2006,11 +2060,19 @@ void
relative_position = audio_location->GetVectorToSource();
}
// (task #50, AUDIO_FIDELITY F9) static sources: brightness-driven cutoff
// only (part_008.c:7831-7884 -- the NRPN block commented below).
float static_gainhf = EFX_CutoffScaleToGainHF(
(float)(CalculateSourceBrightnessScale()
* (Scalar)patch_resource->GetMaxMIDIFilterCutoff()
/ (Scalar)MIDI_MAX_CONTROL_VALUE));
//Static models have their position freely available as relative positions and stand still
for (int i=0; i < channelSet.count; i++)
{
alSourcef(channelSet.sources[i], AL_GAIN, volume_scale * volume_scale); // FIDELITY F4: CC7 squared law (linear was ~+6 dB at mid volumes)
alSource3f(channelSet.sources[i],AL_POSITION,relative_position.x,relative_position.y,relative_position.z);
EFX_SetSourceLowpassGainHF(channelSet.sources[i], static_gainhf);
}
//