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>
45 lines
1.9 KiB
C
45 lines
1.9 KiB
C
#pragma once
|
|
//###########################################################################
|
|
//
|
|
// L4AUDEFX.h -- OpenAL EFX bridge for the authored filter/reverb chains
|
|
// (task #50, AUDIO_FIDELITY F9/F11).
|
|
//
|
|
// The original drove the AWE32 initial-filter-cutoff NRPN per frame
|
|
// (brightness x distance HF rolloff) and sent CC91 reverb on the 3D
|
|
// channels (global_reverb_scale=0.3, AUDIO.INI) while keeping the cockpit
|
|
// Direct channels dry. This bridge reproduces both through OpenAL Soft's
|
|
// EFX extension: one EAXReverb aux slot + a scratch AL_FILTER_LOWPASS
|
|
// whose parameters are copied at attach time.
|
|
//
|
|
//###########################################################################
|
|
|
|
#include "openal/al.h"
|
|
|
|
// Load the EFX entry points, create the reverb slot (gain = the authentic
|
|
// global_reverb_scale) and the scratch lowpass. Call once, with the AL
|
|
// context current. Returns false (and stays inert) without ALC_EXT_EFX.
|
|
bool EFX_Initialize(float global_reverb_scale);
|
|
|
|
bool EFX_Available();
|
|
|
|
// Per-frame direct-path lowpass: gainhf is the linear HF gain at the EFX
|
|
// 5 kHz reference. Callers map the AWE cutoff (100 + scale*7900/127 Hz)
|
|
// through EFX_CutoffScaleToGainHF below.
|
|
void EFX_SetSourceLowpassGainHF(ALuint source, float gainhf);
|
|
|
|
// AWE NRPN 21 curve -> EFX gainhf: cutoff_scale in [0,1] of the 100-8000 Hz
|
|
// span; approximated as the attenuation of a 2-pole lowpass at the 5 kHz
|
|
// reference [T3 -- curve shape approximate, endpoints exact].
|
|
inline float EFX_CutoffScaleToGainHF(float cutoff_scale)
|
|
{
|
|
if (cutoff_scale < 0.0f) cutoff_scale = 0.0f;
|
|
if (cutoff_scale > 1.0f) cutoff_scale = 1.0f;
|
|
float cutoff_hz = 100.0f + cutoff_scale * 7900.0f;
|
|
float g = (cutoff_hz / 5000.0f) * (cutoff_hz / 5000.0f);
|
|
return (g > 1.0f) ? 1.0f : ((g < 0.001f) ? 0.001f : g);
|
|
}
|
|
|
|
// Wet-exterior routing: attach the source's aux send to the reverb slot
|
|
// (Dynamic3D/Static3D). Direct cockpit sources stay dry by default.
|
|
void EFX_AttachReverbSend(ALuint source);
|