diff options
Diffstat (limited to 'al/eax')
-rw-r--r-- | al/eax/api.cpp | 1213 | ||||
-rw-r--r-- | al/eax/api.h | 1557 | ||||
-rw-r--r-- | al/eax/eax_call.cpp | 323 | ||||
-rw-r--r-- | al/eax/eax_call.h | 117 | ||||
-rw-r--r-- | al/eax/effect.cpp | 3 | ||||
-rw-r--r-- | al/eax/effect.h | 44 | ||||
-rw-r--r-- | al/eax/exception.cpp | 62 | ||||
-rw-r--r-- | al/eax/exception.h | 25 | ||||
-rw-r--r-- | al/eax/fx_slot_index.cpp | 71 | ||||
-rw-r--r-- | al/eax/fx_slot_index.h | 41 | ||||
-rw-r--r-- | al/eax/fx_slots.cpp | 83 | ||||
-rw-r--r-- | al/eax/fx_slots.h | 53 | ||||
-rw-r--r-- | al/eax/globals.cpp | 21 | ||||
-rw-r--r-- | al/eax/globals.h | 22 | ||||
-rw-r--r-- | al/eax/utils.cpp | 36 | ||||
-rw-r--r-- | al/eax/utils.h | 132 | ||||
-rw-r--r-- | al/eax/x_ram.cpp | 3 | ||||
-rw-r--r-- | al/eax/x_ram.h | 38 |
18 files changed, 3844 insertions, 0 deletions
diff --git a/al/eax/api.cpp b/al/eax/api.cpp new file mode 100644 index 00000000..f859a1c4 --- /dev/null +++ b/al/eax/api.cpp @@ -0,0 +1,1213 @@ +// +// EAX API. +// +// Based on headers `eax[2-5].h` included in Doom 3 source code: +// https://github.com/id-Software/DOOM-3/tree/master/neo/openal/include +// + +#include "config.h" + +#include <algorithm> + +#include "api.h" + + +const GUID DSPROPSETID_EAX_ReverbProperties = +{ + 0x4A4E6FC1, + 0xC341, + 0x11D1, + {0xB7, 0x3A, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} +}; + +const GUID DSPROPSETID_EAXBUFFER_ReverbProperties = +{ + 0x4A4E6FC0, + 0xC341, + 0x11D1, + {0xB7, 0x3A, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} +}; + +const GUID DSPROPSETID_EAX20_ListenerProperties = +{ + 0x306A6A8, + 0xB224, + 0x11D2, + {0x99, 0xE5, 0x00, 0x00, 0xE8, 0xD8, 0xC7, 0x22} +}; + +const GUID DSPROPSETID_EAX20_BufferProperties = +{ + 0x306A6A7, + 0xB224, + 0x11D2, + {0x99, 0xE5, 0x00, 0x00, 0xE8, 0xD8, 0xC7, 0x22} +}; + +const GUID DSPROPSETID_EAX30_ListenerProperties = +{ + 0xA8FA6882, + 0xB476, + 0x11D3, + {0xBD, 0xB9, 0x00, 0xC0, 0xF0, 0x2D, 0xDF, 0x87} +}; + +const GUID DSPROPSETID_EAX30_BufferProperties = +{ + 0xA8FA6881, + 0xB476, + 0x11D3, + {0xBD, 0xB9, 0x00, 0xC0, 0xF0, 0x2D, 0xDF, 0x87} +}; + +const GUID EAX_NULL_GUID = +{ + 0x00000000, + 0x0000, + 0x0000, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +const GUID EAX_PrimaryFXSlotID = +{ + 0xF317866D, + 0x924C, + 0x450C, + {0x86, 0x1B, 0xE6, 0xDA, 0xA2, 0x5E, 0x7C, 0x20} +}; + +const GUID EAXPROPERTYID_EAX40_Context = +{ + 0x1D4870AD, + 0xDEF, + 0x43C0, + {0xA4, 0xC, 0x52, 0x36, 0x32, 0x29, 0x63, 0x42} +}; + +const GUID EAXPROPERTYID_EAX50_Context = +{ + 0x57E13437, + 0xB932, + 0x4AB2, + {0xB8, 0xBD, 0x52, 0x66, 0xC1, 0xA8, 0x87, 0xEE} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot0 = +{ + 0xC4D79F1E, + 0xF1AC, + 0x436B, + {0xA8, 0x1D, 0xA7, 0x38, 0xE7, 0x04, 0x54, 0x69} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot0 = +{ + 0x91F9590F, + 0xC388, + 0x407A, + {0x84, 0xB0, 0x1B, 0xAE, 0xE, 0xF7, 0x1A, 0xBC} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot1 = +{ + 0x8C00E96, + 0x74BE, + 0x4491, + {0x93, 0xAA, 0xE8, 0xAD, 0x35, 0xA4, 0x91, 0x17} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot1 = +{ + 0x8F5F7ACA, + 0x9608, + 0x4965, + {0x81, 0x37, 0x82, 0x13, 0xC7, 0xB9, 0xD9, 0xDE} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot2 = +{ + 0x1D433B88, + 0xF0F6, + 0x4637, + {0x91, 0x9F, 0x60, 0xE7, 0xE0, 0x6B, 0x5E, 0xDD} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot2 = +{ + 0x3C0F5252, + 0x9834, + 0x46F0, + {0xA1, 0xD8, 0x5B, 0x95, 0xC4, 0xA0, 0xA, 0x30} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot3 = +{ + 0xEFFF08EA, + 0xC7D8, + 0x44AB, + {0x93, 0xAD, 0x6D, 0xBD, 0x5F, 0x91, 0x00, 0x64} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot3 = +{ + 0xE2EB0EAA, + 0xE806, + 0x45E7, + {0x9F, 0x86, 0x06, 0xC1, 0x57, 0x1A, 0x6F, 0xA3} +}; + +const GUID EAXPROPERTYID_EAX40_Source = +{ + 0x1B86B823, + 0x22DF, + 0x4EAE, + {0x8B, 0x3C, 0x12, 0x78, 0xCE, 0x54, 0x42, 0x27} +}; + +const GUID EAXPROPERTYID_EAX50_Source = +{ + 0x5EDF82F0, + 0x24A7, + 0x4F38, + {0x8E, 0x64, 0x2F, 0x09, 0xCA, 0x05, 0xDE, 0xE1} +}; + +const GUID EAX_REVERB_EFFECT = +{ + 0xCF95C8F, + 0xA3CC, + 0x4849, + {0xB0, 0xB6, 0x83, 0x2E, 0xCC, 0x18, 0x22, 0xDF} +}; + +const GUID EAX_AGCCOMPRESSOR_EFFECT = +{ + 0xBFB7A01E, + 0x7825, + 0x4039, + {0x92, 0x7F, 0x03, 0xAA, 0xBD, 0xA0, 0xC5, 0x60} +}; + +const GUID EAX_AUTOWAH_EFFECT = +{ + 0xEC3130C0, + 0xAC7A, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_CHORUS_EFFECT = +{ + 0xDE6D6FE0, + 0xAC79, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_DISTORTION_EFFECT = +{ + 0x975A4CE0, + 0xAC7E, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_ECHO_EFFECT = +{ + 0xE9F1BC0, + 0xAC82, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_EQUALIZER_EFFECT = +{ + 0x65F94CE0, + 0x9793, + 0x11D3, + {0x93, 0x9D, 0x00, 0xC0, 0xF0, 0x2D, 0xD6, 0xF0} +}; + +const GUID EAX_FLANGER_EFFECT = +{ + 0xA70007C0, + 0x7D2, + 0x11D3, + {0x9B, 0x1E, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_FREQUENCYSHIFTER_EFFECT = +{ + 0xDC3E1880, + 0x9212, + 0x11D3, + {0x93, 0x9D, 0x00, 0xC0, 0xF0, 0x2D, 0xD6, 0xF0} +}; + +const GUID EAX_VOCALMORPHER_EFFECT = +{ + 0xE41CF10C, + 0x3383, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_PITCHSHIFTER_EFFECT = +{ + 0xE7905100, + 0xAFB2, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_RINGMODULATOR_EFFECT = +{ + 0xB89FE60, + 0xAFB5, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + + +bool operator==( + const EAX40CONTEXTPROPERTIES& lhs, + const EAX40CONTEXTPROPERTIES& rhs) noexcept +{ + return + lhs.guidPrimaryFXSlotID == rhs.guidPrimaryFXSlotID && + lhs.flDistanceFactor == rhs.flDistanceFactor && + lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF && + lhs.flHFReference == rhs.flHFReference; +} + +bool operator==( + const EAX50CONTEXTPROPERTIES& lhs, + const EAX50CONTEXTPROPERTIES& rhs) noexcept +{ + return + static_cast<const EAX40CONTEXTPROPERTIES&>(lhs) == static_cast<const EAX40CONTEXTPROPERTIES&>(rhs) && + lhs.flMacroFXFactor == rhs.flMacroFXFactor; +} + + +const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0; + +bool operator==( + const EAX40FXSLOTPROPERTIES& lhs, + const EAX40FXSLOTPROPERTIES& rhs) noexcept +{ + return + lhs.guidLoadEffect == rhs.guidLoadEffect && + lhs.lVolume == rhs.lVolume && + lhs.lLock == rhs.lLock && + lhs.ulFlags == rhs.ulFlags; +} + +bool operator==( + const EAX50FXSLOTPROPERTIES& lhs, + const EAX50FXSLOTPROPERTIES& rhs) noexcept +{ + return + static_cast<const EAX40FXSLOTPROPERTIES&>(lhs) == static_cast<const EAX40FXSLOTPROPERTIES&>(rhs) && + lhs.lOcclusion == rhs.lOcclusion && + lhs.flOcclusionLFRatio == rhs.flOcclusionLFRatio; +} + +const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS +{{ + EAX_NULL_GUID, + EAXPROPERTYID_EAX40_FXSlot0, +}}; + +bool operator==( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept +{ + return std::equal( + std::cbegin(lhs.guidActiveFXSlots), + std::cend(lhs.guidActiveFXSlots), + std::begin(rhs.guidActiveFXSlots)); +} + +bool operator!=( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept +{ + return !(lhs == rhs); +} + + +const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS +{{ + EAX_NULL_GUID, + EAX_PrimaryFXSlotID, + EAX_NULL_GUID, + EAX_NULL_GUID, +}}; + + +const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS +{{ + EAX_NULL_GUID, + EAX_NULL_GUID, + EAX_NULL_GUID, + EAX_NULL_GUID, +}}; + +bool operator==( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept +{ + return + lhs.ulEnvironment == rhs.ulEnvironment && + lhs.flEnvironmentSize == rhs.flEnvironmentSize && + lhs.flEnvironmentDiffusion == rhs.flEnvironmentDiffusion && + lhs.lRoom == rhs.lRoom && + lhs.lRoomHF == rhs.lRoomHF && + lhs.lRoomLF == rhs.lRoomLF && + lhs.flDecayTime == rhs.flDecayTime && + lhs.flDecayHFRatio == rhs.flDecayHFRatio && + lhs.flDecayLFRatio == rhs.flDecayLFRatio && + lhs.lReflections == rhs.lReflections && + lhs.flReflectionsDelay == rhs.flReflectionsDelay && + lhs.vReflectionsPan == rhs.vReflectionsPan && + lhs.lReverb == rhs.lReverb && + lhs.flReverbDelay == rhs.flReverbDelay && + lhs.vReverbPan == rhs.vReverbPan && + lhs.flEchoTime == rhs.flEchoTime && + lhs.flEchoDepth == rhs.flEchoDepth && + lhs.flModulationTime == rhs.flModulationTime && + lhs.flModulationDepth == rhs.flModulationDepth && + lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF && + lhs.flHFReference == rhs.flHFReference && + lhs.flLFReference == rhs.flLFReference && + lhs.flRoomRolloffFactor == rhs.flRoomRolloffFactor && + lhs.ulFlags == rhs.ulFlags; +} + +bool operator!=( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept +{ + return !(lhs == rhs); +} + + +namespace { + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_GENERIC = +{ + EAXREVERB_DEFAULTENVIRONMENT, + EAXREVERB_DEFAULTENVIRONMENTSIZE, + EAXREVERB_DEFAULTENVIRONMENTDIFFUSION, + EAXREVERB_DEFAULTROOM, + EAXREVERB_DEFAULTROOMHF, + EAXREVERB_DEFAULTROOMLF, + EAXREVERB_DEFAULTDECAYTIME, + EAXREVERB_DEFAULTDECAYHFRATIO, + EAXREVERB_DEFAULTDECAYLFRATIO, + EAXREVERB_DEFAULTREFLECTIONS, + EAXREVERB_DEFAULTREFLECTIONSDELAY, + EAXREVERB_DEFAULTREFLECTIONSPAN, + EAXREVERB_DEFAULTREVERB, + EAXREVERB_DEFAULTREVERBDELAY, + EAXREVERB_DEFAULTREVERBPAN, + EAXREVERB_DEFAULTECHOTIME, + EAXREVERB_DEFAULTECHODEPTH, + EAXREVERB_DEFAULTMODULATIONTIME, + EAXREVERB_DEFAULTMODULATIONDEPTH, + EAXREVERB_DEFAULTAIRABSORPTIONHF, + EAXREVERB_DEFAULTHFREFERENCE, + EAXREVERB_DEFAULTLFREFERENCE, + EAXREVERB_DEFAULTROOMROLLOFFFACTOR, + EAXREVERB_DEFAULTFLAGS, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PADDEDCELL = +{ + EAX_ENVIRONMENT_PADDEDCELL, + 1.4F, + 1.0F, + -1'000L, + -6'000L, + 0L, + 0.17F, + 0.10F, + 1.0F, + -1'204L, + 0.001F, + EAXVECTOR{}, + 207L, + 0.002F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_ROOM = +{ + EAX_ENVIRONMENT_ROOM, + 1.9F, + 1.0F, + -1'000L, + -454L, + 0L, + 0.40F, + 0.83F, + 1.0F, + -1'646L, + 0.002F, + EAXVECTOR{}, + 53L, + 0.003F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_BATHROOM = +{ + EAX_ENVIRONMENT_BATHROOM, + 1.4F, + 1.0F, + -1'000L, + -1'200L, + 0L, + 1.49F, + 0.54F, + 1.0F, + -370L, + 0.007F, + EAXVECTOR{}, + 1'030L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_LIVINGROOM = +{ + EAX_ENVIRONMENT_LIVINGROOM, + 2.5F, + 1.0F, + -1'000L, + -6'000L, + 0L, + 0.50F, + 0.10F, + 1.0F, + -1'376, + 0.003F, + EAXVECTOR{}, + -1'104L, + 0.004F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_STONEROOM = +{ + EAX_ENVIRONMENT_STONEROOM, + 11.6F, + 1.0F, + -1'000L, + -300L, + 0L, + 2.31F, + 0.64F, + 1.0F, + -711L, + 0.012F, + EAXVECTOR{}, + 83L, + 0.017F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_AUDITORIUM = +{ + EAX_ENVIRONMENT_AUDITORIUM, + 21.6F, + 1.0F, + -1'000L, + -476L, + 0L, + 4.32F, + 0.59F, + 1.0F, + -789L, + 0.020F, + EAXVECTOR{}, + -289L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CONCERTHALL = +{ + EAX_ENVIRONMENT_CONCERTHALL, + 19.6F, + 1.0F, + -1'000L, + -500L, + 0L, + 3.92F, + 0.70F, + 1.0F, + -1'230L, + 0.020F, + EAXVECTOR{}, + -2L, + 0.029F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CAVE = +{ + EAX_ENVIRONMENT_CAVE, + 14.6F, + 1.0F, + -1'000L, + 0L, + 0L, + 2.91F, + 1.30F, + 1.0F, + -602L, + 0.015F, + EAXVECTOR{}, + -302L, + 0.022F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_ARENA = +{ + EAX_ENVIRONMENT_ARENA, + 36.2F, + 1.0F, + -1'000L, + -698L, + 0L, + 7.24F, + 0.33F, + 1.0F, + -1'166L, + 0.020F, + EAXVECTOR{}, + 16L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_HANGAR = +{ + EAX_ENVIRONMENT_HANGAR, + 50.3F, + 1.0F, + -1'000L, + -1'000L, + 0L, + 10.05F, + 0.23F, + 1.0F, + -602L, + 0.020F, + EAXVECTOR{}, + 198L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CARPETTEDHALLWAY = +{ + EAX_ENVIRONMENT_CARPETEDHALLWAY, + 1.9F, + 1.0F, + -1'000L, + -4'000L, + 0L, + 0.30F, + 0.10F, + 1.0F, + -1'831L, + 0.002F, + EAXVECTOR{}, + -1'630L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_HALLWAY = +{ + EAX_ENVIRONMENT_HALLWAY, + 1.8F, + 1.0F, + -1'000L, + -300L, + 0L, + 1.49F, + 0.59F, + 1.0F, + -1'219L, + 0.007F, + EAXVECTOR{}, + 441L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_STONECORRIDOR = +{ + EAX_ENVIRONMENT_STONECORRIDOR, + 13.5F, + 1.0F, + -1'000L, + -237L, + 0L, + 2.70F, + 0.79F, + 1.0F, + -1'214L, + 0.013F, + EAXVECTOR{}, + 395L, + 0.020F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_ALLEY = +{ + EAX_ENVIRONMENT_ALLEY, + 7.5F, + 0.300F, + -1'000L, + -270L, + 0L, + 1.49F, + 0.86F, + 1.0F, + -1'204L, + 0.007F, + EAXVECTOR{}, + -4L, + 0.011F, + EAXVECTOR{}, + 0.125F, + 0.950F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_FOREST = +{ + EAX_ENVIRONMENT_FOREST, + 38.0F, + 0.300F, + -1'000L, + -3'300L, + 0L, + 1.49F, + 0.54F, + 1.0F, + -2'560L, + 0.162F, + EAXVECTOR{}, + -229L, + 0.088F, + EAXVECTOR{}, + 0.125F, + 1.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CITY = +{ + EAX_ENVIRONMENT_CITY, + 7.5F, + 0.500F, + -1'000L, + -800L, + 0L, + 1.49F, + 0.67F, + 1.0F, + -2'273L, + 0.007F, + EAXVECTOR{}, + -1'691L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_MOUNTAINS = +{ + EAX_ENVIRONMENT_MOUNTAINS, + 100.0F, + 0.270F, + -1'000L, + -2'500L, + 0L, + 1.49F, + 0.21F, + 1.0F, + -2'780L, + 0.300F, + EAXVECTOR{}, + -1'434L, + 0.100F, + EAXVECTOR{}, + 0.250F, + 1.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_QUARRY = +{ + EAX_ENVIRONMENT_QUARRY, + 17.5F, + 1.0F, + -1'000L, + -1'000L, + 0L, + 1.49F, + 0.83F, + 1.0F, + -10'000L, + 0.061F, + EAXVECTOR{}, + 500L, + 0.025F, + EAXVECTOR{}, + 0.125F, + 0.700F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PLAIN = +{ + EAX_ENVIRONMENT_PLAIN, + 42.5F, + 0.210F, + -1'000L, + -2'000L, + 0L, + 1.49F, + 0.50F, + 1.0F, + -2'466L, + 0.179F, + EAXVECTOR{}, + -1'926L, + 0.100F, + EAXVECTOR{}, + 0.250F, + 1.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PARKINGLOT = +{ + EAX_ENVIRONMENT_PARKINGLOT, + 8.3F, + 1.0F, + -1'000L, + 0L, + 0L, + 1.65F, + 1.50F, + 1.0F, + -1'363L, + 0.008F, + EAXVECTOR{}, + -1'153L, + 0.012F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_SEWERPIPE = +{ + EAX_ENVIRONMENT_SEWERPIPE, + 1.7F, + 0.800F, + -1'000L, + -1'000L, + 0L, + 2.81F, + 0.14F, + 1.0F, + 429L, + 0.014F, + EAXVECTOR{}, + 1'023L, + 0.021F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_UNDERWATER = +{ + EAX_ENVIRONMENT_UNDERWATER, + 1.8F, + 1.0F, + -1'000L, + -4'000L, + 0L, + 1.49F, + 0.10F, + 1.0F, + -449L, + 0.007F, + EAXVECTOR{}, + 1'700L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 1.180F, + 0.348F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_DRUGGED = +{ + EAX_ENVIRONMENT_DRUGGED, + 1.9F, + 0.500F, + -1'000L, + 0L, + 0L, + 8.39F, + 1.39F, + 1.0F, + -115L, + 0.002F, + EAXVECTOR{}, + 985L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 1.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_DIZZY = +{ + EAX_ENVIRONMENT_DIZZY, + 1.8F, + 0.600F, + -1'000L, + -400L, + 0L, + 17.23F, + 0.56F, + 1.0F, + -1'713L, + 0.020F, + EAXVECTOR{}, + -613L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 1.0F, + 0.810F, + 0.310F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PSYCHOTIC = +{ + EAX_ENVIRONMENT_PSYCHOTIC, + 1.0F, + 0.500F, + -1'000L, + -151L, + 0L, + 7.56F, + 0.91F, + 1.0F, + -626L, + 0.020F, + EAXVECTOR{}, + 774L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 4.0F, + 1.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +} // namespace + +const EaxReverbPresets EAXREVERB_PRESETS{{ + EAXREVERB_PRESET_GENERIC, + EAXREVERB_PRESET_PADDEDCELL, + EAXREVERB_PRESET_ROOM, + EAXREVERB_PRESET_BATHROOM, + EAXREVERB_PRESET_LIVINGROOM, + EAXREVERB_PRESET_STONEROOM, + EAXREVERB_PRESET_AUDITORIUM, + EAXREVERB_PRESET_CONCERTHALL, + EAXREVERB_PRESET_CAVE, + EAXREVERB_PRESET_ARENA, + EAXREVERB_PRESET_HANGAR, + EAXREVERB_PRESET_CARPETTEDHALLWAY, + EAXREVERB_PRESET_HALLWAY, + EAXREVERB_PRESET_STONECORRIDOR, + EAXREVERB_PRESET_ALLEY, + EAXREVERB_PRESET_FOREST, + EAXREVERB_PRESET_CITY, + EAXREVERB_PRESET_MOUNTAINS, + EAXREVERB_PRESET_QUARRY, + EAXREVERB_PRESET_PLAIN, + EAXREVERB_PRESET_PARKINGLOT, + EAXREVERB_PRESET_SEWERPIPE, + EAXREVERB_PRESET_UNDERWATER, + EAXREVERB_PRESET_DRUGGED, + EAXREVERB_PRESET_DIZZY, + EAXREVERB_PRESET_PSYCHOTIC, +}}; + +namespace { +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_GENERIC = {EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PADDEDCELL = {EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ROOM = {EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_BATHROOM = {EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_LIVINGROOM = {EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONEROOM = {EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_AUDITORIUM = {EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CONCERTHALL = {EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CAVE = {EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ARENA = {EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HANGAR = {EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CARPETTEDHALLWAY = {EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HALLWAY = {EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONECORRIDOR = {EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ALLEY = {EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_FOREST = {EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CITY = {EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_MOUNTAINS = {EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_QUARRY = {EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PLAIN = {EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PARKINGLOT = {EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_SEWERPIPE = {EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_UNDERWATER = {EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DRUGGED = {EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DIZZY = {EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PSYCHOTIC = {EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F}; +} // namespace + +const Eax1ReverbPresets EAX1REVERB_PRESETS{{ + EAX1REVERB_PRESET_GENERIC, + EAX1REVERB_PRESET_PADDEDCELL, + EAX1REVERB_PRESET_ROOM, + EAX1REVERB_PRESET_BATHROOM, + EAX1REVERB_PRESET_LIVINGROOM, + EAX1REVERB_PRESET_STONEROOM, + EAX1REVERB_PRESET_AUDITORIUM, + EAX1REVERB_PRESET_CONCERTHALL, + EAX1REVERB_PRESET_CAVE, + EAX1REVERB_PRESET_ARENA, + EAX1REVERB_PRESET_HANGAR, + EAX1REVERB_PRESET_CARPETTEDHALLWAY, + EAX1REVERB_PRESET_HALLWAY, + EAX1REVERB_PRESET_STONECORRIDOR, + EAX1REVERB_PRESET_ALLEY, + EAX1REVERB_PRESET_FOREST, + EAX1REVERB_PRESET_CITY, + EAX1REVERB_PRESET_MOUNTAINS, + EAX1REVERB_PRESET_QUARRY, + EAX1REVERB_PRESET_PLAIN, + EAX1REVERB_PRESET_PARKINGLOT, + EAX1REVERB_PRESET_SEWERPIPE, + EAX1REVERB_PRESET_UNDERWATER, + EAX1REVERB_PRESET_DRUGGED, + EAX1REVERB_PRESET_DIZZY, + EAX1REVERB_PRESET_PSYCHOTIC, +}}; diff --git a/al/eax/api.h b/al/eax/api.h new file mode 100644 index 00000000..d0737d1d --- /dev/null +++ b/al/eax/api.h @@ -0,0 +1,1557 @@ +#ifndef EAX_API_INCLUDED +#define EAX_API_INCLUDED + + +// +// EAX API. +// +// Based on headers `eax[2-5].h` included in Doom 3 source code: +// https://github.com/id-Software/DOOM-3/tree/master/neo/openal/include +// + + +#include <cfloat> +#include <cstdint> +#include <cstring> + +#include <array> + +#include "AL/al.h" + + +#ifndef GUID_DEFINED +#define GUID_DEFINED +typedef struct _GUID +{ + std::uint32_t Data1; + std::uint16_t Data2; + std::uint16_t Data3; + std::uint8_t Data4[8]; +} GUID; + +inline bool operator==(const GUID& lhs, const GUID& rhs) noexcept +{ + return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; +} + +inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept +{ + return !(lhs == rhs); +} +#endif // GUID_DEFINED + + +extern const GUID DSPROPSETID_EAX_ReverbProperties; + +enum DSPROPERTY_EAX_REVERBPROPERTY : unsigned int +{ + DSPROPERTY_EAX_ALL, + DSPROPERTY_EAX_ENVIRONMENT, + DSPROPERTY_EAX_VOLUME, + DSPROPERTY_EAX_DECAYTIME, + DSPROPERTY_EAX_DAMPING, +}; // DSPROPERTY_EAX_REVERBPROPERTY + +struct EAX_REVERBPROPERTIES +{ + unsigned long environment; + float fVolume; + float fDecayTime_sec; + float fDamping; +}; // EAX_REVERBPROPERTIES + +inline bool operator==(const EAX_REVERBPROPERTIES& lhs, const EAX_REVERBPROPERTIES& rhs) noexcept +{ + return std::memcmp(&lhs, &rhs, sizeof(EAX_REVERBPROPERTIES)) == 0; +} + +extern const GUID DSPROPSETID_EAXBUFFER_ReverbProperties; + +enum DSPROPERTY_EAXBUFFER_REVERBPROPERTY : unsigned int +{ + DSPROPERTY_EAXBUFFER_ALL, + DSPROPERTY_EAXBUFFER_REVERBMIX, +}; // DSPROPERTY_EAXBUFFER_REVERBPROPERTY + +struct EAXBUFFER_REVERBPROPERTIES +{ + float fMix; +}; + +inline bool operator==(const EAXBUFFER_REVERBPROPERTIES& lhs, const EAXBUFFER_REVERBPROPERTIES& rhs) noexcept +{ + return lhs.fMix == rhs.fMix; +} + +constexpr auto EAX_BUFFER_MINREVERBMIX = 0.0F; +constexpr auto EAX_BUFFER_MAXREVERBMIX = 1.0F; +constexpr auto EAX_REVERBMIX_USEDISTANCE = -1.0F; + + +extern const GUID DSPROPSETID_EAX20_ListenerProperties; + +enum DSPROPERTY_EAX20_LISTENERPROPERTY : + unsigned int +{ + DSPROPERTY_EAX20LISTENER_NONE, + DSPROPERTY_EAX20LISTENER_ALLPARAMETERS, + DSPROPERTY_EAX20LISTENER_ROOM, + DSPROPERTY_EAX20LISTENER_ROOMHF, + DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR, + DSPROPERTY_EAX20LISTENER_DECAYTIME, + DSPROPERTY_EAX20LISTENER_DECAYHFRATIO, + DSPROPERTY_EAX20LISTENER_REFLECTIONS, + DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY, + DSPROPERTY_EAX20LISTENER_REVERB, + DSPROPERTY_EAX20LISTENER_REVERBDELAY, + DSPROPERTY_EAX20LISTENER_ENVIRONMENT, + DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE, + DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION, + DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF, + DSPROPERTY_EAX20LISTENER_FLAGS +}; // DSPROPERTY_EAX20_LISTENERPROPERTY + +struct EAX20LISTENERPROPERTIES +{ + long lRoom; // room effect level at low frequencies + long lRoomHF; // room effect high-frequency level re. low frequency level + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + float flDecayTime; // reverberation decay time at low frequencies + float flDecayHFRatio; // high-frequency to low-frequency decay time ratio + long lReflections; // early reflections level relative to room effect + float flReflectionsDelay; // initial reflection delay time + long lReverb; // late reverberation level relative to room effect + float flReverbDelay; // late reverberation delay time relative to initial reflection + unsigned long dwEnvironment; // sets all listener properties + float flEnvironmentSize; // environment size in meters + float flEnvironmentDiffusion; // environment diffusion + float flAirAbsorptionHF; // change in level per meter at 5 kHz + unsigned long dwFlags; // modifies the behavior of properties +}; // EAX20LISTENERPROPERTIES + + +extern const GUID DSPROPSETID_EAX20_BufferProperties; + + +enum DSPROPERTY_EAX20_BUFFERPROPERTY : + unsigned int +{ + DSPROPERTY_EAX20BUFFER_NONE, + DSPROPERTY_EAX20BUFFER_ALLPARAMETERS, + DSPROPERTY_EAX20BUFFER_DIRECT, + DSPROPERTY_EAX20BUFFER_DIRECTHF, + DSPROPERTY_EAX20BUFFER_ROOM, + DSPROPERTY_EAX20BUFFER_ROOMHF, + DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR, + DSPROPERTY_EAX20BUFFER_OBSTRUCTION, + DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO, + DSPROPERTY_EAX20BUFFER_OCCLUSION, + DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO, + DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO, + DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF, + DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR, + DSPROPERTY_EAX20BUFFER_FLAGS +}; // DSPROPERTY_EAX20_BUFFERPROPERTY + + +struct EAX20BUFFERPROPERTIES +{ + long lDirect; // direct path level + long lDirectHF; // direct path level at high frequencies + long lRoom; // room effect level + long lRoomHF; // room effect level at high frequencies + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + long lObstruction; // main obstruction control (attenuation at high frequencies) + float flObstructionLFRatio; // obstruction low-frequency level re. main control + long lOcclusion; // main occlusion control (attenuation at high frequencies) + float flOcclusionLFRatio; // occlusion low-frequency level re. main control + float flOcclusionRoomRatio; // occlusion room effect level re. main control + long lOutsideVolumeHF; // outside sound cone level at high frequencies + float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF + unsigned long dwFlags; // modifies the behavior of properties +}; // EAX20BUFFERPROPERTIES + + +extern const GUID DSPROPSETID_EAX30_ListenerProperties; + +extern const GUID DSPROPSETID_EAX30_BufferProperties; + + +constexpr auto EAX_MAX_FXSLOTS = 4; + +constexpr auto EAX40_MAX_ACTIVE_FXSLOTS = 2; +constexpr auto EAX50_MAX_ACTIVE_FXSLOTS = 4; + + +constexpr auto EAX_OK = 0L; +constexpr auto EAXERR_INVALID_OPERATION = -1L; +constexpr auto EAXERR_INVALID_VALUE = -2L; +constexpr auto EAXERR_NO_EFFECT_LOADED = -3L; +constexpr auto EAXERR_UNKNOWN_EFFECT = -4L; +constexpr auto EAXERR_INCOMPATIBLE_SOURCE_TYPE = -5L; +constexpr auto EAXERR_INCOMPATIBLE_EAX_VERSION = -6L; + + +extern const GUID EAX_NULL_GUID; + +extern const GUID EAX_PrimaryFXSlotID; + + +struct EAXVECTOR +{ + float x; + float y; + float z; +}; // EAXVECTOR + +inline bool operator==(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept +{ return std::memcmp(&lhs, &rhs, sizeof(EAXVECTOR)) == 0; } + +inline bool operator!=(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept +{ return !(lhs == rhs); } + + +extern const GUID EAXPROPERTYID_EAX40_Context; + +extern const GUID EAXPROPERTYID_EAX50_Context; + +// EAX50 +enum : + unsigned long +{ + HEADPHONES = 0, + SPEAKERS_2, + SPEAKERS_4, + SPEAKERS_5, // 5.1 speakers + SPEAKERS_6, // 6.1 speakers + SPEAKERS_7, // 7.1 speakers +}; + +// EAX50 +enum : + unsigned long +{ + EAX_40 = 5, // EAX 4.0 + EAX_50 = 6, // EAX 5.0 +}; + +constexpr auto EAXCONTEXT_MINEAXSESSION = EAX_40; +constexpr auto EAXCONTEXT_MAXEAXSESSION = EAX_50; +constexpr auto EAXCONTEXT_DEFAULTEAXSESSION = EAX_40; + +constexpr auto EAXCONTEXT_MINMAXACTIVESENDS = 2UL; +constexpr auto EAXCONTEXT_MAXMAXACTIVESENDS = 4UL; +constexpr auto EAXCONTEXT_DEFAULTMAXACTIVESENDS = 2UL; + +// EAX50 +struct EAXSESSIONPROPERTIES +{ + unsigned long ulEAXVersion; + unsigned long ulMaxActiveSends; +}; // EAXSESSIONPROPERTIES + +enum EAXCONTEXT_PROPERTY : + unsigned int +{ + EAXCONTEXT_NONE = 0, + EAXCONTEXT_ALLPARAMETERS, + EAXCONTEXT_PRIMARYFXSLOTID, + EAXCONTEXT_DISTANCEFACTOR, + EAXCONTEXT_AIRABSORPTIONHF, + EAXCONTEXT_HFREFERENCE, + EAXCONTEXT_LASTERROR, + + // EAX50 + EAXCONTEXT_SPEAKERCONFIG, + EAXCONTEXT_EAXSESSION, + EAXCONTEXT_MACROFXFACTOR, +}; // EAXCONTEXT_PROPERTY + +struct EAX40CONTEXTPROPERTIES +{ + GUID guidPrimaryFXSlotID; + float flDistanceFactor; + float flAirAbsorptionHF; + float flHFReference; +}; // EAX40CONTEXTPROPERTIES + +struct EAX50CONTEXTPROPERTIES : + public EAX40CONTEXTPROPERTIES +{ + float flMacroFXFactor; +}; // EAX40CONTEXTPROPERTIES + + +bool operator==( + const EAX40CONTEXTPROPERTIES& lhs, + const EAX40CONTEXTPROPERTIES& rhs) noexcept; + +bool operator==( + const EAX50CONTEXTPROPERTIES& lhs, + const EAX50CONTEXTPROPERTIES& rhs) noexcept; + + +constexpr auto EAXCONTEXT_MINDISTANCEFACTOR = FLT_MIN; +constexpr auto EAXCONTEXT_MAXDISTANCEFACTOR = FLT_MAX; +constexpr auto EAXCONTEXT_DEFAULTDISTANCEFACTOR = 1.0F; + +constexpr auto EAXCONTEXT_MINAIRABSORPTIONHF = -100.0F; +constexpr auto EAXCONTEXT_MAXAIRABSORPTIONHF = 0.0F; +constexpr auto EAXCONTEXT_DEFAULTAIRABSORPTIONHF = -5.0F; + +constexpr auto EAXCONTEXT_MINHFREFERENCE = 1000.0F; +constexpr auto EAXCONTEXT_MAXHFREFERENCE = 20000.0F; +constexpr auto EAXCONTEXT_DEFAULTHFREFERENCE = 5000.0F; + +constexpr auto EAXCONTEXT_MINMACROFXFACTOR = 0.0F; +constexpr auto EAXCONTEXT_MAXMACROFXFACTOR = 1.0F; +constexpr auto EAXCONTEXT_DEFAULTMACROFXFACTOR = 0.0F; + + +extern const GUID EAXPROPERTYID_EAX40_FXSlot0; + +extern const GUID EAXPROPERTYID_EAX50_FXSlot0; + +extern const GUID EAXPROPERTYID_EAX40_FXSlot1; + +extern const GUID EAXPROPERTYID_EAX50_FXSlot1; + +extern const GUID EAXPROPERTYID_EAX40_FXSlot2; + +extern const GUID EAXPROPERTYID_EAX50_FXSlot2; + +extern const GUID EAXPROPERTYID_EAX40_FXSlot3; + +extern const GUID EAXPROPERTYID_EAX50_FXSlot3; + +extern const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID; + +enum EAXFXSLOT_PROPERTY : + unsigned int +{ + EAXFXSLOT_PARAMETER = 0, + + EAXFXSLOT_NONE = 0x10000, + EAXFXSLOT_ALLPARAMETERS, + EAXFXSLOT_LOADEFFECT, + EAXFXSLOT_VOLUME, + EAXFXSLOT_LOCK, + EAXFXSLOT_FLAGS, + + // EAX50 + EAXFXSLOT_OCCLUSION, + EAXFXSLOT_OCCLUSIONLFRATIO, +}; // EAXFXSLOT_PROPERTY + +constexpr auto EAXFXSLOTFLAGS_ENVIRONMENT = 0x00000001UL; +// EAX50 +constexpr auto EAXFXSLOTFLAGS_UPMIX = 0x00000002UL; + +constexpr auto EAX40FXSLOTFLAGS_RESERVED = 0xFFFFFFFEUL; // reserved future use +constexpr auto EAX50FXSLOTFLAGS_RESERVED = 0xFFFFFFFCUL; // reserved future use + + +constexpr auto EAXFXSLOT_MINVOLUME = -10'000L; +constexpr auto EAXFXSLOT_MAXVOLUME = 0L; +constexpr auto EAXFXSLOT_DEFAULTVOLUME = 0L; + +constexpr auto EAXFXSLOT_MINLOCK = 0L; +constexpr auto EAXFXSLOT_MAXLOCK = 1L; + +enum : + long +{ + EAXFXSLOT_UNLOCKED = 0, + EAXFXSLOT_LOCKED = 1 +}; + +constexpr auto EAXFXSLOT_MINOCCLUSION = -10'000L; +constexpr auto EAXFXSLOT_MAXOCCLUSION = 0L; +constexpr auto EAXFXSLOT_DEFAULTOCCLUSION = 0L; + +constexpr auto EAXFXSLOT_MINOCCLUSIONLFRATIO = 0.0F; +constexpr auto EAXFXSLOT_MAXOCCLUSIONLFRATIO = 1.0F; +constexpr auto EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO = 0.25F; + +constexpr auto EAX40FXSLOT_DEFAULTFLAGS = EAXFXSLOTFLAGS_ENVIRONMENT; + +constexpr auto EAX50FXSLOT_DEFAULTFLAGS = + EAXFXSLOTFLAGS_ENVIRONMENT | + EAXFXSLOTFLAGS_UPMIX; // ignored for reverb; + +struct EAX40FXSLOTPROPERTIES +{ + GUID guidLoadEffect; + long lVolume; + long lLock; + unsigned long ulFlags; +}; // EAX40FXSLOTPROPERTIES + +struct EAX50FXSLOTPROPERTIES : + public EAX40FXSLOTPROPERTIES +{ + long lOcclusion; + float flOcclusionLFRatio; +}; // EAX50FXSLOTPROPERTIES + +bool operator==( + const EAX40FXSLOTPROPERTIES& lhs, + const EAX40FXSLOTPROPERTIES& rhs) noexcept; + +bool operator==( + const EAX50FXSLOTPROPERTIES& lhs, + const EAX50FXSLOTPROPERTIES& rhs) noexcept; + +extern const GUID EAXPROPERTYID_EAX40_Source; + +extern const GUID EAXPROPERTYID_EAX50_Source; + +// Source object properties +enum EAXSOURCE_PROPERTY : + unsigned int +{ + // EAX30 + + EAXSOURCE_NONE, + EAXSOURCE_ALLPARAMETERS, + EAXSOURCE_OBSTRUCTIONPARAMETERS, + EAXSOURCE_OCCLUSIONPARAMETERS, + EAXSOURCE_EXCLUSIONPARAMETERS, + EAXSOURCE_DIRECT, + EAXSOURCE_DIRECTHF, + EAXSOURCE_ROOM, + EAXSOURCE_ROOMHF, + EAXSOURCE_OBSTRUCTION, + EAXSOURCE_OBSTRUCTIONLFRATIO, + EAXSOURCE_OCCLUSION, + EAXSOURCE_OCCLUSIONLFRATIO, + EAXSOURCE_OCCLUSIONROOMRATIO, + EAXSOURCE_OCCLUSIONDIRECTRATIO, + EAXSOURCE_EXCLUSION, + EAXSOURCE_EXCLUSIONLFRATIO, + EAXSOURCE_OUTSIDEVOLUMEHF, + EAXSOURCE_DOPPLERFACTOR, + EAXSOURCE_ROLLOFFFACTOR, + EAXSOURCE_ROOMROLLOFFFACTOR, + EAXSOURCE_AIRABSORPTIONFACTOR, + EAXSOURCE_FLAGS, + + // EAX40 + + EAXSOURCE_SENDPARAMETERS, + EAXSOURCE_ALLSENDPARAMETERS, + EAXSOURCE_OCCLUSIONSENDPARAMETERS, + EAXSOURCE_EXCLUSIONSENDPARAMETERS, + EAXSOURCE_ACTIVEFXSLOTID, + + // EAX50 + + EAXSOURCE_MACROFXFACTOR, + EAXSOURCE_SPEAKERLEVELS, + EAXSOURCE_ALL2DPARAMETERS, +}; // EAXSOURCE_PROPERTY + + +constexpr auto EAXSOURCEFLAGS_DIRECTHFAUTO = 0x00000001UL; // relates to EAXSOURCE_DIRECTHF +constexpr auto EAXSOURCEFLAGS_ROOMAUTO = 0x00000002UL; // relates to EAXSOURCE_ROOM +constexpr auto EAXSOURCEFLAGS_ROOMHFAUTO = 0x00000004UL; // relates to EAXSOURCE_ROOMHF +// EAX50 +constexpr auto EAXSOURCEFLAGS_3DELEVATIONFILTER = 0x00000008UL; +// EAX50 +constexpr auto EAXSOURCEFLAGS_UPMIX = 0x00000010UL; +// EAX50 +constexpr auto EAXSOURCEFLAGS_APPLYSPEAKERLEVELS = 0x00000020UL; + +constexpr auto EAX20SOURCEFLAGS_RESERVED = 0xFFFFFFF8UL; // reserved future use +constexpr auto EAX50SOURCEFLAGS_RESERVED = 0xFFFFFFC0UL; // reserved future use + + +constexpr auto EAXSOURCE_MINSEND = -10'000L; +constexpr auto EAXSOURCE_MAXSEND = 0L; +constexpr auto EAXSOURCE_DEFAULTSEND = 0L; + +constexpr auto EAXSOURCE_MINSENDHF = -10'000L; +constexpr auto EAXSOURCE_MAXSENDHF = 0L; +constexpr auto EAXSOURCE_DEFAULTSENDHF = 0L; + +constexpr auto EAXSOURCE_MINDIRECT = -10'000L; +constexpr auto EAXSOURCE_MAXDIRECT = 1'000L; +constexpr auto EAXSOURCE_DEFAULTDIRECT = 0L; + +constexpr auto EAXSOURCE_MINDIRECTHF = -10'000L; +constexpr auto EAXSOURCE_MAXDIRECTHF = 0L; +constexpr auto EAXSOURCE_DEFAULTDIRECTHF = 0L; + +constexpr auto EAXSOURCE_MINROOM = -10'000L; +constexpr auto EAXSOURCE_MAXROOM = 1'000L; +constexpr auto EAXSOURCE_DEFAULTROOM = 0L; + +constexpr auto EAXSOURCE_MINROOMHF = -10'000L; +constexpr auto EAXSOURCE_MAXROOMHF = 0L; +constexpr auto EAXSOURCE_DEFAULTROOMHF = 0L; + +constexpr auto EAXSOURCE_MINOBSTRUCTION = -10'000L; +constexpr auto EAXSOURCE_MAXOBSTRUCTION = 0L; +constexpr auto EAXSOURCE_DEFAULTOBSTRUCTION = 0L; + +constexpr auto EAXSOURCE_MINOBSTRUCTIONLFRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOBSTRUCTIONLFRATIO = 1.0F; +constexpr auto EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO = 0.0F; + +constexpr auto EAXSOURCE_MINOCCLUSION = -10'000L; +constexpr auto EAXSOURCE_MAXOCCLUSION = 0L; +constexpr auto EAXSOURCE_DEFAULTOCCLUSION = 0L; + +constexpr auto EAXSOURCE_MINOCCLUSIONLFRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOCCLUSIONLFRATIO = 1.0F; +constexpr auto EAXSOURCE_DEFAULTOCCLUSIONLFRATIO = 0.25F; + +constexpr auto EAXSOURCE_MINOCCLUSIONROOMRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOCCLUSIONROOMRATIO = 10.0F; +constexpr auto EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO = 1.5F; + +constexpr auto EAXSOURCE_MINOCCLUSIONDIRECTRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOCCLUSIONDIRECTRATIO = 10.0F; +constexpr auto EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO = 1.0F; + +constexpr auto EAXSOURCE_MINEXCLUSION = -10'000L; +constexpr auto EAXSOURCE_MAXEXCLUSION = 0L; +constexpr auto EAXSOURCE_DEFAULTEXCLUSION = 0L; + +constexpr auto EAXSOURCE_MINEXCLUSIONLFRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXEXCLUSIONLFRATIO = 1.0F; +constexpr auto EAXSOURCE_DEFAULTEXCLUSIONLFRATIO = 1.0F; + +constexpr auto EAXSOURCE_MINOUTSIDEVOLUMEHF = -10'000L; +constexpr auto EAXSOURCE_MAXOUTSIDEVOLUMEHF = 0L; +constexpr auto EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF = 0L; + +constexpr auto EAXSOURCE_MINDOPPLERFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXDOPPLERFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTDOPPLERFACTOR = 1.0F; + +constexpr auto EAXSOURCE_MINROLLOFFFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXROLLOFFFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTROLLOFFFACTOR = 0.0F; + +constexpr auto EAXSOURCE_MINROOMROLLOFFFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXROOMROLLOFFFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTROOMROLLOFFFACTOR = 0.0F; + +constexpr auto EAXSOURCE_MINAIRABSORPTIONFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXAIRABSORPTIONFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR = 0.0F; + +// EAX50 + +constexpr auto EAXSOURCE_MINMACROFXFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXMACROFXFACTOR = 1.0F; +constexpr auto EAXSOURCE_DEFAULTMACROFXFACTOR = 1.0F; + +// EAX50 + +constexpr auto EAXSOURCE_MINSPEAKERLEVEL = -10'000L; +constexpr auto EAXSOURCE_MAXSPEAKERLEVEL = 0L; +constexpr auto EAXSOURCE_DEFAULTSPEAKERLEVEL = -10'000L; + +constexpr auto EAXSOURCE_DEFAULTFLAGS = + EAXSOURCEFLAGS_DIRECTHFAUTO | + EAXSOURCEFLAGS_ROOMAUTO | + EAXSOURCEFLAGS_ROOMHFAUTO; + +enum : + long +{ + EAXSPEAKER_FRONT_LEFT = 1, + EAXSPEAKER_FRONT_CENTER = 2, + EAXSPEAKER_FRONT_RIGHT = 3, + EAXSPEAKER_SIDE_RIGHT = 4, + EAXSPEAKER_REAR_RIGHT = 5, + EAXSPEAKER_REAR_CENTER = 6, + EAXSPEAKER_REAR_LEFT = 7, + EAXSPEAKER_SIDE_LEFT = 8, + EAXSPEAKER_LOW_FREQUENCY = 9 +}; + +// EAXSOURCEFLAGS_DIRECTHFAUTO, EAXSOURCEFLAGS_ROOMAUTO and EAXSOURCEFLAGS_ROOMHFAUTO are ignored for 2D sources +// EAXSOURCEFLAGS_UPMIX is ignored for 3D sources +constexpr auto EAX50SOURCE_DEFAULTFLAGS = + EAXSOURCEFLAGS_DIRECTHFAUTO | + EAXSOURCEFLAGS_ROOMAUTO | + EAXSOURCEFLAGS_ROOMHFAUTO | + EAXSOURCEFLAGS_UPMIX; + +struct EAX30SOURCEPROPERTIES +{ + long lDirect; // direct path level (at low and mid frequencies) + long lDirectHF; // relative direct path level at high frequencies + long lRoom; // room effect level (at low and mid frequencies) + long lRoomHF; // relative room effect level at high frequencies + long lObstruction; // main obstruction control (attenuation at high frequencies) + float flObstructionLFRatio; // obstruction low-frequency level re. main control + long lOcclusion; // main occlusion control (attenuation at high frequencies) + float flOcclusionLFRatio; // occlusion low-frequency level re. main control + float flOcclusionRoomRatio; // relative occlusion control for room effect + float flOcclusionDirectRatio; // relative occlusion control for direct path + long lExclusion; // main exlusion control (attenuation at high frequencies) + float flExclusionLFRatio; // exclusion low-frequency level re. main control + long lOutsideVolumeHF; // outside sound cone level at high frequencies + float flDopplerFactor; // like DS3D flDopplerFactor but per source + float flRolloffFactor; // like DS3D flRolloffFactor but per source + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + float flAirAbsorptionFactor; // multiplies EAXREVERB_AIRABSORPTIONHF + unsigned long ulFlags; // modifies the behavior of properties +}; // EAX30SOURCEPROPERTIES + +struct EAX50SOURCEPROPERTIES : + public EAX30SOURCEPROPERTIES +{ + float flMacroFXFactor; +}; // EAX50SOURCEPROPERTIES + +struct EAXSOURCEALLSENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lSend; // send level (at low and mid frequencies) + long lSendHF; // relative send level at high frequencies + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; + long lExclusion; + float flExclusionLFRatio; +}; // EAXSOURCEALLSENDPROPERTIES + +struct EAXSOURCE2DPROPERTIES +{ + long lDirect; // direct path level (at low and mid frequencies) + long lDirectHF; // relative direct path level at high frequencies + long lRoom; // room effect level (at low and mid frequencies) + long lRoomHF; // relative room effect level at high frequencies + unsigned long ulFlags; // modifies the behavior of properties +}; // EAXSOURCE2DPROPERTIES + +struct EAXSPEAKERLEVELPROPERTIES +{ + long lSpeakerID; + long lLevel; +}; // EAXSPEAKERLEVELPROPERTIES + +struct EAX40ACTIVEFXSLOTS +{ + GUID guidActiveFXSlots[EAX40_MAX_ACTIVE_FXSLOTS]; +}; // EAX40ACTIVEFXSLOTS + +struct EAX50ACTIVEFXSLOTS +{ + GUID guidActiveFXSlots[EAX50_MAX_ACTIVE_FXSLOTS]; +}; // EAX50ACTIVEFXSLOTS + +bool operator==( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept; + +bool operator!=( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept; + +// Use this structure for EAXSOURCE_OBSTRUCTIONPARAMETERS property. +struct EAXOBSTRUCTIONPROPERTIES +{ + long lObstruction; + float flObstructionLFRatio; +}; // EAXOBSTRUCTIONPROPERTIES + +// Use this structure for EAXSOURCE_OCCLUSIONPARAMETERS property. +struct EAXOCCLUSIONPROPERTIES +{ + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; +}; // EAXOCCLUSIONPROPERTIES + +// Use this structure for EAXSOURCE_EXCLUSIONPARAMETERS property. +struct EAXEXCLUSIONPROPERTIES +{ + long lExclusion; + float flExclusionLFRatio; +}; // EAXEXCLUSIONPROPERTIES + +// Use this structure for EAXSOURCE_SENDPARAMETERS properties. +struct EAXSOURCESENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lSend; + long lSendHF; +}; // EAXSOURCESENDPROPERTIES + +// Use this structure for EAXSOURCE_OCCLUSIONSENDPARAMETERS +struct EAXSOURCEOCCLUSIONSENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; +}; // EAXSOURCEOCCLUSIONSENDPROPERTIES + +// Use this structure for EAXSOURCE_EXCLUSIONSENDPARAMETERS +struct EAXSOURCEEXCLUSIONSENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lExclusion; + float flExclusionLFRatio; +}; // EAXSOURCEEXCLUSIONSENDPROPERTIES + +extern const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID; + +extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID; + +extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID; + + +// EAX Reverb Effect + +extern const GUID EAX_REVERB_EFFECT; + +// Reverb effect properties +enum EAXREVERB_PROPERTY : + unsigned int +{ + EAXREVERB_NONE, + EAXREVERB_ALLPARAMETERS, + EAXREVERB_ENVIRONMENT, + EAXREVERB_ENVIRONMENTSIZE, + EAXREVERB_ENVIRONMENTDIFFUSION, + EAXREVERB_ROOM, + EAXREVERB_ROOMHF, + EAXREVERB_ROOMLF, + EAXREVERB_DECAYTIME, + EAXREVERB_DECAYHFRATIO, + EAXREVERB_DECAYLFRATIO, + EAXREVERB_REFLECTIONS, + EAXREVERB_REFLECTIONSDELAY, + EAXREVERB_REFLECTIONSPAN, + EAXREVERB_REVERB, + EAXREVERB_REVERBDELAY, + EAXREVERB_REVERBPAN, + EAXREVERB_ECHOTIME, + EAXREVERB_ECHODEPTH, + EAXREVERB_MODULATIONTIME, + EAXREVERB_MODULATIONDEPTH, + EAXREVERB_AIRABSORPTIONHF, + EAXREVERB_HFREFERENCE, + EAXREVERB_LFREFERENCE, + EAXREVERB_ROOMROLLOFFFACTOR, + EAXREVERB_FLAGS, +}; // EAXREVERB_PROPERTY + +// used by EAXREVERB_ENVIRONMENT +enum : + unsigned long +{ + EAX_ENVIRONMENT_GENERIC, + EAX_ENVIRONMENT_PADDEDCELL, + EAX_ENVIRONMENT_ROOM, + EAX_ENVIRONMENT_BATHROOM, + EAX_ENVIRONMENT_LIVINGROOM, + EAX_ENVIRONMENT_STONEROOM, + EAX_ENVIRONMENT_AUDITORIUM, + EAX_ENVIRONMENT_CONCERTHALL, + EAX_ENVIRONMENT_CAVE, + EAX_ENVIRONMENT_ARENA, + EAX_ENVIRONMENT_HANGAR, + EAX_ENVIRONMENT_CARPETEDHALLWAY, + EAX_ENVIRONMENT_HALLWAY, + EAX_ENVIRONMENT_STONECORRIDOR, + EAX_ENVIRONMENT_ALLEY, + EAX_ENVIRONMENT_FOREST, + EAX_ENVIRONMENT_CITY, + EAX_ENVIRONMENT_MOUNTAINS, + EAX_ENVIRONMENT_QUARRY, + EAX_ENVIRONMENT_PLAIN, + EAX_ENVIRONMENT_PARKINGLOT, + EAX_ENVIRONMENT_SEWERPIPE, + EAX_ENVIRONMENT_UNDERWATER, + EAX_ENVIRONMENT_DRUGGED, + EAX_ENVIRONMENT_DIZZY, + EAX_ENVIRONMENT_PSYCHOTIC, + + EAX1_ENVIRONMENT_COUNT, + + // EAX30 + EAX_ENVIRONMENT_UNDEFINED = EAX1_ENVIRONMENT_COUNT, + + EAX3_ENVIRONMENT_COUNT, +}; + + +// reverberation decay time +constexpr auto EAXREVERBFLAGS_DECAYTIMESCALE = 0x00000001UL; + +// reflection level +constexpr auto EAXREVERBFLAGS_REFLECTIONSSCALE = 0x00000002UL; + +// initial reflection delay time +constexpr auto EAXREVERBFLAGS_REFLECTIONSDELAYSCALE = 0x00000004UL; + +// reflections level +constexpr auto EAXREVERBFLAGS_REVERBSCALE = 0x00000008UL; + +// late reverberation delay time +constexpr auto EAXREVERBFLAGS_REVERBDELAYSCALE = 0x00000010UL; + +// echo time +// EAX30+ +constexpr auto EAXREVERBFLAGS_ECHOTIMESCALE = 0x00000040UL; + +// modulation time +// EAX30+ +constexpr auto EAXREVERBFLAGS_MODULATIONTIMESCALE = 0x00000080UL; + +// This flag limits high-frequency decay time according to air absorption. +constexpr auto EAXREVERBFLAGS_DECAYHFLIMIT = 0x00000020UL; + +constexpr auto EAXREVERBFLAGS_RESERVED = 0xFFFFFF00UL; // reserved future use + + +struct EAXREVERBPROPERTIES +{ + unsigned long ulEnvironment; // sets all reverb properties + float flEnvironmentSize; // environment size in meters + float flEnvironmentDiffusion; // environment diffusion + long lRoom; // room effect level (at mid frequencies) + long lRoomHF; // relative room effect level at high frequencies + long lRoomLF; // relative room effect level at low frequencies + float flDecayTime; // reverberation decay time at mid frequencies + float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio + float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio + long lReflections; // early reflections level relative to room effect + float flReflectionsDelay; // initial reflection delay time + EAXVECTOR vReflectionsPan; // early reflections panning vector + long lReverb; // late reverberation level relative to room effect + float flReverbDelay; // late reverberation delay time relative to initial reflection + EAXVECTOR vReverbPan; // late reverberation panning vector + float flEchoTime; // echo time + float flEchoDepth; // echo depth + float flModulationTime; // modulation time + float flModulationDepth; // modulation depth + float flAirAbsorptionHF; // change in level per meter at high frequencies + float flHFReference; // reference high frequency + float flLFReference; // reference low frequency + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + unsigned long ulFlags; // modifies the behavior of properties +}; // EAXREVERBPROPERTIES + +bool operator==( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept; + +bool operator!=( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept; + + +constexpr auto EAXREVERB_MINENVIRONMENT = static_cast<unsigned long>(EAX_ENVIRONMENT_GENERIC); +constexpr auto EAX1REVERB_MAXENVIRONMENT = static_cast<unsigned long>(EAX_ENVIRONMENT_PSYCHOTIC); +constexpr auto EAX30REVERB_MAXENVIRONMENT = static_cast<unsigned long>(EAX_ENVIRONMENT_UNDEFINED); +constexpr auto EAXREVERB_DEFAULTENVIRONMENT = static_cast<unsigned long>(EAX_ENVIRONMENT_GENERIC); + +constexpr auto EAXREVERB_MINENVIRONMENTSIZE = 1.0F; +constexpr auto EAXREVERB_MAXENVIRONMENTSIZE = 100.0F; +constexpr auto EAXREVERB_DEFAULTENVIRONMENTSIZE = 7.5F; + +constexpr auto EAXREVERB_MINENVIRONMENTDIFFUSION = 0.0F; +constexpr auto EAXREVERB_MAXENVIRONMENTDIFFUSION = 1.0F; +constexpr auto EAXREVERB_DEFAULTENVIRONMENTDIFFUSION = 1.0F; + +constexpr auto EAXREVERB_MINROOM = -10'000L; +constexpr auto EAXREVERB_MAXROOM = 0L; +constexpr auto EAXREVERB_DEFAULTROOM = -1'000L; + +constexpr auto EAXREVERB_MINROOMHF = -10'000L; +constexpr auto EAXREVERB_MAXROOMHF = 0L; +constexpr auto EAXREVERB_DEFAULTROOMHF = -100L; + +constexpr auto EAXREVERB_MINROOMLF = -10'000L; +constexpr auto EAXREVERB_MAXROOMLF = 0L; +constexpr auto EAXREVERB_DEFAULTROOMLF = 0L; + +constexpr auto EAXREVERB_MINDECAYTIME = 0.1F; +constexpr auto EAXREVERB_MAXDECAYTIME = 20.0F; +constexpr auto EAXREVERB_DEFAULTDECAYTIME = 1.49F; + +constexpr auto EAXREVERB_MINDECAYHFRATIO = 0.1F; +constexpr auto EAXREVERB_MAXDECAYHFRATIO = 2.0F; +constexpr auto EAXREVERB_DEFAULTDECAYHFRATIO = 0.83F; + +constexpr auto EAXREVERB_MINDECAYLFRATIO = 0.1F; +constexpr auto EAXREVERB_MAXDECAYLFRATIO = 2.0F; +constexpr auto EAXREVERB_DEFAULTDECAYLFRATIO = 1.0F; + +constexpr auto EAXREVERB_MINREFLECTIONS = -10'000L; +constexpr auto EAXREVERB_MAXREFLECTIONS = 1'000L; +constexpr auto EAXREVERB_DEFAULTREFLECTIONS = -2'602L; + +constexpr auto EAXREVERB_MINREFLECTIONSDELAY = 0.0F; +constexpr auto EAXREVERB_MAXREFLECTIONSDELAY = 0.3F; +constexpr auto EAXREVERB_DEFAULTREFLECTIONSDELAY = 0.007F; + +constexpr auto EAXREVERB_DEFAULTREFLECTIONSPAN = EAXVECTOR{0.0F, 0.0F, 0.0F}; + +constexpr auto EAXREVERB_MINREVERB = -10'000L; +constexpr auto EAXREVERB_MAXREVERB = 2'000L; +constexpr auto EAXREVERB_DEFAULTREVERB = 200L; + +constexpr auto EAXREVERB_MINREVERBDELAY = 0.0F; +constexpr auto EAXREVERB_MAXREVERBDELAY = 0.1F; +constexpr auto EAXREVERB_DEFAULTREVERBDELAY = 0.011F; + +constexpr auto EAXREVERB_DEFAULTREVERBPAN = EAXVECTOR{0.0F, 0.0F, 0.0F}; + +constexpr auto EAXREVERB_MINECHOTIME = 0.075F; +constexpr auto EAXREVERB_MAXECHOTIME = 0.25F; +constexpr auto EAXREVERB_DEFAULTECHOTIME = 0.25F; + +constexpr auto EAXREVERB_MINECHODEPTH = 0.0F; +constexpr auto EAXREVERB_MAXECHODEPTH = 1.0F; +constexpr auto EAXREVERB_DEFAULTECHODEPTH = 0.0F; + +constexpr auto EAXREVERB_MINMODULATIONTIME = 0.04F; +constexpr auto EAXREVERB_MAXMODULATIONTIME = 4.0F; +constexpr auto EAXREVERB_DEFAULTMODULATIONTIME = 0.25F; + +constexpr auto EAXREVERB_MINMODULATIONDEPTH = 0.0F; +constexpr auto EAXREVERB_MAXMODULATIONDEPTH = 1.0F; +constexpr auto EAXREVERB_DEFAULTMODULATIONDEPTH = 0.0F; + +constexpr auto EAXREVERB_MINAIRABSORPTIONHF = -100.0F; +constexpr auto EAXREVERB_MAXAIRABSORPTIONHF = 0.0F; +constexpr auto EAXREVERB_DEFAULTAIRABSORPTIONHF = -5.0F; + +constexpr auto EAXREVERB_MINHFREFERENCE = 1'000.0F; +constexpr auto EAXREVERB_MAXHFREFERENCE = 20'000.0F; +constexpr auto EAXREVERB_DEFAULTHFREFERENCE = 5'000.0F; + +constexpr auto EAXREVERB_MINLFREFERENCE = 20.0F; +constexpr auto EAXREVERB_MAXLFREFERENCE = 1'000.0F; +constexpr auto EAXREVERB_DEFAULTLFREFERENCE = 250.0F; + +constexpr auto EAXREVERB_MINROOMROLLOFFFACTOR = 0.0F; +constexpr auto EAXREVERB_MAXROOMROLLOFFFACTOR = 10.0F; +constexpr auto EAXREVERB_DEFAULTROOMROLLOFFFACTOR = 0.0F; + +constexpr auto EAX1REVERB_MINVOLUME = 0.0F; +constexpr auto EAX1REVERB_MAXVOLUME = 1.0F; + +constexpr auto EAX1REVERB_MINDAMPING = 0.0F; +constexpr auto EAX1REVERB_MAXDAMPING = 2.0F; + +constexpr auto EAXREVERB_DEFAULTFLAGS = + EAXREVERBFLAGS_DECAYTIMESCALE | + EAXREVERBFLAGS_REFLECTIONSSCALE | + EAXREVERBFLAGS_REFLECTIONSDELAYSCALE | + EAXREVERBFLAGS_REVERBSCALE | + EAXREVERBFLAGS_REVERBDELAYSCALE | + EAXREVERBFLAGS_DECAYHFLIMIT; + + +using EaxReverbPresets = std::array<EAXREVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>; +extern const EaxReverbPresets EAXREVERB_PRESETS; + + +using Eax1ReverbPresets = std::array<EAX_REVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>; +extern const Eax1ReverbPresets EAX1REVERB_PRESETS; + + +// AGC Compressor Effect + +extern const GUID EAX_AGCCOMPRESSOR_EFFECT; + +enum EAXAGCCOMPRESSOR_PROPERTY : + unsigned int +{ + EAXAGCCOMPRESSOR_NONE, + EAXAGCCOMPRESSOR_ALLPARAMETERS, + EAXAGCCOMPRESSOR_ONOFF, +}; // EAXAGCCOMPRESSOR_PROPERTY + +struct EAXAGCCOMPRESSORPROPERTIES +{ + unsigned long ulOnOff; // Switch Compressor on or off +}; // EAXAGCCOMPRESSORPROPERTIES + + +constexpr auto EAXAGCCOMPRESSOR_MINONOFF = 0UL; +constexpr auto EAXAGCCOMPRESSOR_MAXONOFF = 1UL; +constexpr auto EAXAGCCOMPRESSOR_DEFAULTONOFF = EAXAGCCOMPRESSOR_MAXONOFF; + + +// Autowah Effect + +extern const GUID EAX_AUTOWAH_EFFECT; + +enum EAXAUTOWAH_PROPERTY : + unsigned int +{ + EAXAUTOWAH_NONE, + EAXAUTOWAH_ALLPARAMETERS, + EAXAUTOWAH_ATTACKTIME, + EAXAUTOWAH_RELEASETIME, + EAXAUTOWAH_RESONANCE, + EAXAUTOWAH_PEAKLEVEL, +}; // EAXAUTOWAH_PROPERTY + +struct EAXAUTOWAHPROPERTIES +{ + float flAttackTime; // Attack time (seconds) + float flReleaseTime; // Release time (seconds) + long lResonance; // Resonance (mB) + long lPeakLevel; // Peak level (mB) +}; // EAXAUTOWAHPROPERTIES + + +constexpr auto EAXAUTOWAH_MINATTACKTIME = 0.0001F; +constexpr auto EAXAUTOWAH_MAXATTACKTIME = 1.0F; +constexpr auto EAXAUTOWAH_DEFAULTATTACKTIME = 0.06F; + +constexpr auto EAXAUTOWAH_MINRELEASETIME = 0.0001F; +constexpr auto EAXAUTOWAH_MAXRELEASETIME = 1.0F; +constexpr auto EAXAUTOWAH_DEFAULTRELEASETIME = 0.06F; + +constexpr auto EAXAUTOWAH_MINRESONANCE = 600L; +constexpr auto EAXAUTOWAH_MAXRESONANCE = 6000L; +constexpr auto EAXAUTOWAH_DEFAULTRESONANCE = 6000L; + +constexpr auto EAXAUTOWAH_MINPEAKLEVEL = -9000L; +constexpr auto EAXAUTOWAH_MAXPEAKLEVEL = 9000L; +constexpr auto EAXAUTOWAH_DEFAULTPEAKLEVEL = 2100L; + + +// Chorus Effect + +extern const GUID EAX_CHORUS_EFFECT; + + +enum EAXCHORUS_PROPERTY : + unsigned int +{ + EAXCHORUS_NONE, + EAXCHORUS_ALLPARAMETERS, + EAXCHORUS_WAVEFORM, + EAXCHORUS_PHASE, + EAXCHORUS_RATE, + EAXCHORUS_DEPTH, + EAXCHORUS_FEEDBACK, + EAXCHORUS_DELAY, +}; // EAXCHORUS_PROPERTY + +enum : + unsigned long +{ + EAX_CHORUS_SINUSOID, + EAX_CHORUS_TRIANGLE, +}; + +struct EAXCHORUSPROPERTIES +{ + unsigned long ulWaveform; // Waveform selector - see enum above + long lPhase; // Phase (Degrees) + float flRate; // Rate (Hz) + float flDepth; // Depth (0 to 1) + float flFeedback; // Feedback (-1 to 1) + float flDelay; // Delay (seconds) +}; // EAXCHORUSPROPERTIES + + +constexpr auto EAXCHORUS_MINWAVEFORM = 0UL; +constexpr auto EAXCHORUS_MAXWAVEFORM = 1UL; +constexpr auto EAXCHORUS_DEFAULTWAVEFORM = 1UL; + +constexpr auto EAXCHORUS_MINPHASE = -180L; +constexpr auto EAXCHORUS_MAXPHASE = 180L; +constexpr auto EAXCHORUS_DEFAULTPHASE = 90L; + +constexpr auto EAXCHORUS_MINRATE = 0.0F; +constexpr auto EAXCHORUS_MAXRATE = 10.0F; +constexpr auto EAXCHORUS_DEFAULTRATE = 1.1F; + +constexpr auto EAXCHORUS_MINDEPTH = 0.0F; +constexpr auto EAXCHORUS_MAXDEPTH = 1.0F; +constexpr auto EAXCHORUS_DEFAULTDEPTH = 0.1F; + +constexpr auto EAXCHORUS_MINFEEDBACK = -1.0F; +constexpr auto EAXCHORUS_MAXFEEDBACK = 1.0F; +constexpr auto EAXCHORUS_DEFAULTFEEDBACK = 0.25F; + +constexpr auto EAXCHORUS_MINDELAY = 0.0002F; +constexpr auto EAXCHORUS_MAXDELAY = 0.016F; +constexpr auto EAXCHORUS_DEFAULTDELAY = 0.016F; + + +// Distortion Effect + +extern const GUID EAX_DISTORTION_EFFECT; + +enum EAXDISTORTION_PROPERTY : + unsigned int +{ + EAXDISTORTION_NONE, + EAXDISTORTION_ALLPARAMETERS, + EAXDISTORTION_EDGE, + EAXDISTORTION_GAIN, + EAXDISTORTION_LOWPASSCUTOFF, + EAXDISTORTION_EQCENTER, + EAXDISTORTION_EQBANDWIDTH, +}; // EAXDISTORTION_PROPERTY + + +struct EAXDISTORTIONPROPERTIES +{ + float flEdge; // Controls the shape of the distortion (0 to 1) + long lGain; // Controls the post distortion gain (mB) + float flLowPassCutOff; // Controls the cut-off of the filter pre-distortion (Hz) + float flEQCenter; // Controls the center frequency of the EQ post-distortion (Hz) + float flEQBandwidth; // Controls the bandwidth of the EQ post-distortion (Hz) +}; // EAXDISTORTIONPROPERTIES + + +constexpr auto EAXDISTORTION_MINEDGE = 0.0F; +constexpr auto EAXDISTORTION_MAXEDGE = 1.0F; +constexpr auto EAXDISTORTION_DEFAULTEDGE = 0.2F; + +constexpr auto EAXDISTORTION_MINGAIN = -6000L; +constexpr auto EAXDISTORTION_MAXGAIN = 0L; +constexpr auto EAXDISTORTION_DEFAULTGAIN = -2600L; + +constexpr auto EAXDISTORTION_MINLOWPASSCUTOFF = 80.0F; +constexpr auto EAXDISTORTION_MAXLOWPASSCUTOFF = 24000.0F; +constexpr auto EAXDISTORTION_DEFAULTLOWPASSCUTOFF = 8000.0F; + +constexpr auto EAXDISTORTION_MINEQCENTER = 80.0F; +constexpr auto EAXDISTORTION_MAXEQCENTER = 24000.0F; +constexpr auto EAXDISTORTION_DEFAULTEQCENTER = 3600.0F; + +constexpr auto EAXDISTORTION_MINEQBANDWIDTH = 80.0F; +constexpr auto EAXDISTORTION_MAXEQBANDWIDTH = 24000.0F; +constexpr auto EAXDISTORTION_DEFAULTEQBANDWIDTH = 3600.0F; + + +// Echo Effect + +extern const GUID EAX_ECHO_EFFECT; + + +enum EAXECHO_PROPERTY : + unsigned int +{ + EAXECHO_NONE, + EAXECHO_ALLPARAMETERS, + EAXECHO_DELAY, + EAXECHO_LRDELAY, + EAXECHO_DAMPING, + EAXECHO_FEEDBACK, + EAXECHO_SPREAD, +}; // EAXECHO_PROPERTY + + +struct EAXECHOPROPERTIES +{ + float flDelay; // Controls the initial delay time (seconds) + float flLRDelay; // Controls the delay time between the first and second taps (seconds) + float flDamping; // Controls a low-pass filter that dampens the echoes (0 to 1) + float flFeedback; // Controls the duration of echo repetition (0 to 1) + float flSpread; // Controls the left-right spread of the echoes +}; // EAXECHOPROPERTIES + + +constexpr auto EAXECHO_MINDAMPING = 0.0F; +constexpr auto EAXECHO_MAXDAMPING = 0.99F; +constexpr auto EAXECHO_DEFAULTDAMPING = 0.5F; + +constexpr auto EAXECHO_MINDELAY = 0.002F; +constexpr auto EAXECHO_MAXDELAY = 0.207F; +constexpr auto EAXECHO_DEFAULTDELAY = 0.1F; + +constexpr auto EAXECHO_MINLRDELAY = 0.0F; +constexpr auto EAXECHO_MAXLRDELAY = 0.404F; +constexpr auto EAXECHO_DEFAULTLRDELAY = 0.1F; + +constexpr auto EAXECHO_MINFEEDBACK = 0.0F; +constexpr auto EAXECHO_MAXFEEDBACK = 1.0F; +constexpr auto EAXECHO_DEFAULTFEEDBACK = 0.5F; + +constexpr auto EAXECHO_MINSPREAD = -1.0F; +constexpr auto EAXECHO_MAXSPREAD = 1.0F; +constexpr auto EAXECHO_DEFAULTSPREAD = -1.0F; + + +// Equalizer Effect + +extern const GUID EAX_EQUALIZER_EFFECT; + + +enum EAXEQUALIZER_PROPERTY : + unsigned int +{ + EAXEQUALIZER_NONE, + EAXEQUALIZER_ALLPARAMETERS, + EAXEQUALIZER_LOWGAIN, + EAXEQUALIZER_LOWCUTOFF, + EAXEQUALIZER_MID1GAIN, + EAXEQUALIZER_MID1CENTER, + EAXEQUALIZER_MID1WIDTH, + EAXEQUALIZER_MID2GAIN, + EAXEQUALIZER_MID2CENTER, + EAXEQUALIZER_MID2WIDTH, + EAXEQUALIZER_HIGHGAIN, + EAXEQUALIZER_HIGHCUTOFF, +}; // EAXEQUALIZER_PROPERTY + + +struct EAXEQUALIZERPROPERTIES +{ + long lLowGain; // (mB) + float flLowCutOff; // (Hz) + long lMid1Gain; // (mB) + float flMid1Center; // (Hz) + float flMid1Width; // (octaves) + long lMid2Gain; // (mB) + float flMid2Center; // (Hz) + float flMid2Width; // (octaves) + long lHighGain; // (mB) + float flHighCutOff; // (Hz) +}; // EAXEQUALIZERPROPERTIES + + +constexpr auto EAXEQUALIZER_MINLOWGAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXLOWGAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTLOWGAIN = 0L; + +constexpr auto EAXEQUALIZER_MINLOWCUTOFF = 50.0F; +constexpr auto EAXEQUALIZER_MAXLOWCUTOFF = 800.0F; +constexpr auto EAXEQUALIZER_DEFAULTLOWCUTOFF = 200.0F; + +constexpr auto EAXEQUALIZER_MINMID1GAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXMID1GAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTMID1GAIN = 0L; + +constexpr auto EAXEQUALIZER_MINMID1CENTER = 200.0F; +constexpr auto EAXEQUALIZER_MAXMID1CENTER = 3000.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID1CENTER = 500.0F; + +constexpr auto EAXEQUALIZER_MINMID1WIDTH = 0.01F; +constexpr auto EAXEQUALIZER_MAXMID1WIDTH = 1.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID1WIDTH = 1.0F; + +constexpr auto EAXEQUALIZER_MINMID2GAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXMID2GAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTMID2GAIN = 0L; + +constexpr auto EAXEQUALIZER_MINMID2CENTER = 1000.0F; +constexpr auto EAXEQUALIZER_MAXMID2CENTER = 8000.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID2CENTER = 3000.0F; + +constexpr auto EAXEQUALIZER_MINMID2WIDTH = 0.01F; +constexpr auto EAXEQUALIZER_MAXMID2WIDTH = 1.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID2WIDTH = 1.0F; + +constexpr auto EAXEQUALIZER_MINHIGHGAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXHIGHGAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTHIGHGAIN = 0L; + +constexpr auto EAXEQUALIZER_MINHIGHCUTOFF = 4000.0F; +constexpr auto EAXEQUALIZER_MAXHIGHCUTOFF = 16000.0F; +constexpr auto EAXEQUALIZER_DEFAULTHIGHCUTOFF = 6000.0F; + + +// Flanger Effect + +extern const GUID EAX_FLANGER_EFFECT; + +enum EAXFLANGER_PROPERTY : + unsigned int +{ + EAXFLANGER_NONE, + EAXFLANGER_ALLPARAMETERS, + EAXFLANGER_WAVEFORM, + EAXFLANGER_PHASE, + EAXFLANGER_RATE, + EAXFLANGER_DEPTH, + EAXFLANGER_FEEDBACK, + EAXFLANGER_DELAY, +}; // EAXFLANGER_PROPERTY + +enum : + unsigned long +{ + EAX_FLANGER_SINUSOID, + EAX_FLANGER_TRIANGLE, +}; + +struct EAXFLANGERPROPERTIES +{ + unsigned long ulWaveform; // Waveform selector - see enum above + long lPhase; // Phase (Degrees) + float flRate; // Rate (Hz) + float flDepth; // Depth (0 to 1) + float flFeedback; // Feedback (0 to 1) + float flDelay; // Delay (seconds) +}; // EAXFLANGERPROPERTIES + + +constexpr auto EAXFLANGER_MINWAVEFORM = 0UL; +constexpr auto EAXFLANGER_MAXWAVEFORM = 1UL; +constexpr auto EAXFLANGER_DEFAULTWAVEFORM = 1UL; + +constexpr auto EAXFLANGER_MINPHASE = -180L; +constexpr auto EAXFLANGER_MAXPHASE = 180L; +constexpr auto EAXFLANGER_DEFAULTPHASE = 0L; + +constexpr auto EAXFLANGER_MINRATE = 0.0F; +constexpr auto EAXFLANGER_MAXRATE = 10.0F; +constexpr auto EAXFLANGER_DEFAULTRATE = 0.27F; + +constexpr auto EAXFLANGER_MINDEPTH = 0.0F; +constexpr auto EAXFLANGER_MAXDEPTH = 1.0F; +constexpr auto EAXFLANGER_DEFAULTDEPTH = 1.0F; + +constexpr auto EAXFLANGER_MINFEEDBACK = -1.0F; +constexpr auto EAXFLANGER_MAXFEEDBACK = 1.0F; +constexpr auto EAXFLANGER_DEFAULTFEEDBACK = -0.5F; + +constexpr auto EAXFLANGER_MINDELAY = 0.0002F; +constexpr auto EAXFLANGER_MAXDELAY = 0.004F; +constexpr auto EAXFLANGER_DEFAULTDELAY = 0.002F; + + +// Frequency Shifter Effect + +extern const GUID EAX_FREQUENCYSHIFTER_EFFECT; + +enum EAXFREQUENCYSHIFTER_PROPERTY : + unsigned int +{ + EAXFREQUENCYSHIFTER_NONE, + EAXFREQUENCYSHIFTER_ALLPARAMETERS, + EAXFREQUENCYSHIFTER_FREQUENCY, + EAXFREQUENCYSHIFTER_LEFTDIRECTION, + EAXFREQUENCYSHIFTER_RIGHTDIRECTION, +}; // EAXFREQUENCYSHIFTER_PROPERTY + +enum : + unsigned long +{ + EAX_FREQUENCYSHIFTER_DOWN, + EAX_FREQUENCYSHIFTER_UP, + EAX_FREQUENCYSHIFTER_OFF +}; + +struct EAXFREQUENCYSHIFTERPROPERTIES +{ + float flFrequency; // (Hz) + unsigned long ulLeftDirection; // see enum above + unsigned long ulRightDirection; // see enum above +}; // EAXFREQUENCYSHIFTERPROPERTIES + + +constexpr auto EAXFREQUENCYSHIFTER_MINFREQUENCY = 0.0F; +constexpr auto EAXFREQUENCYSHIFTER_MAXFREQUENCY = 24000.0F; +constexpr auto EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY = EAXFREQUENCYSHIFTER_MINFREQUENCY; + +constexpr auto EAXFREQUENCYSHIFTER_MINLEFTDIRECTION = 0UL; +constexpr auto EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION = 2UL; +constexpr auto EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION = EAXFREQUENCYSHIFTER_MINLEFTDIRECTION; + +constexpr auto EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION = 0UL; +constexpr auto EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION = 2UL; +constexpr auto EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION = EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION; + + +// Vocal Morpher Effect + +extern const GUID EAX_VOCALMORPHER_EFFECT; + +enum EAXVOCALMORPHER_PROPERTY : + unsigned int +{ + EAXVOCALMORPHER_NONE, + EAXVOCALMORPHER_ALLPARAMETERS, + EAXVOCALMORPHER_PHONEMEA, + EAXVOCALMORPHER_PHONEMEACOARSETUNING, + EAXVOCALMORPHER_PHONEMEB, + EAXVOCALMORPHER_PHONEMEBCOARSETUNING, + EAXVOCALMORPHER_WAVEFORM, + EAXVOCALMORPHER_RATE, +}; // EAXVOCALMORPHER_PROPERTY + +enum : + unsigned long +{ + A, + E, + I, + O, + U, + AA, + AE, + AH, + AO, + EH, + ER, + IH, + IY, + UH, + UW, + B, + D, + F, + G, + J, + K, + L, + M, + N, + P, + R, + S, + T, + V, + Z, +}; + +enum : + unsigned long +{ + EAX_VOCALMORPHER_SINUSOID, + EAX_VOCALMORPHER_TRIANGLE, + EAX_VOCALMORPHER_SAWTOOTH +}; + +// Use this structure for EAXVOCALMORPHER_ALLPARAMETERS +struct EAXVOCALMORPHERPROPERTIES +{ + unsigned long ulPhonemeA; // see enum above + long lPhonemeACoarseTuning; // (semitones) + unsigned long ulPhonemeB; // see enum above + long lPhonemeBCoarseTuning; // (semitones) + unsigned long ulWaveform; // Waveform selector - see enum above + float flRate; // (Hz) +}; // EAXVOCALMORPHERPROPERTIES + + +constexpr auto EAXVOCALMORPHER_MINPHONEMEA = 0UL; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEA = 29UL; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEA = EAXVOCALMORPHER_MINPHONEMEA; + +constexpr auto EAXVOCALMORPHER_MINPHONEMEACOARSETUNING = -24L; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING = 24L; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING = 0L; + +constexpr auto EAXVOCALMORPHER_MINPHONEMEB = 0UL; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEB = 29UL; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEB = 10UL; + +constexpr auto EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING = -24L; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING = 24L; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING = 0L; + +constexpr auto EAXVOCALMORPHER_MINWAVEFORM = 0UL; +constexpr auto EAXVOCALMORPHER_MAXWAVEFORM = 2UL; +constexpr auto EAXVOCALMORPHER_DEFAULTWAVEFORM = EAXVOCALMORPHER_MINWAVEFORM; + +constexpr auto EAXVOCALMORPHER_MINRATE = 0.0F; +constexpr auto EAXVOCALMORPHER_MAXRATE = 10.0F; +constexpr auto EAXVOCALMORPHER_DEFAULTRATE = 1.41F; + + +// Pitch Shifter Effect + +extern const GUID EAX_PITCHSHIFTER_EFFECT; + +enum EAXPITCHSHIFTER_PROPERTY : + unsigned int +{ + EAXPITCHSHIFTER_NONE, + EAXPITCHSHIFTER_ALLPARAMETERS, + EAXPITCHSHIFTER_COARSETUNE, + EAXPITCHSHIFTER_FINETUNE, +}; // EAXPITCHSHIFTER_PROPERTY + +struct EAXPITCHSHIFTERPROPERTIES +{ + long lCoarseTune; // Amount of pitch shift (semitones) + long lFineTune; // Amount of pitch shift (cents) +}; // EAXPITCHSHIFTERPROPERTIES + + +constexpr auto EAXPITCHSHIFTER_MINCOARSETUNE = -12L; +constexpr auto EAXPITCHSHIFTER_MAXCOARSETUNE = 12L; +constexpr auto EAXPITCHSHIFTER_DEFAULTCOARSETUNE = 12L; + +constexpr auto EAXPITCHSHIFTER_MINFINETUNE = -50L; +constexpr auto EAXPITCHSHIFTER_MAXFINETUNE = 50L; +constexpr auto EAXPITCHSHIFTER_DEFAULTFINETUNE = 0L; + + +// Ring Modulator Effect + +extern const GUID EAX_RINGMODULATOR_EFFECT; + +enum EAXRINGMODULATOR_PROPERTY : + unsigned int +{ + EAXRINGMODULATOR_NONE, + EAXRINGMODULATOR_ALLPARAMETERS, + EAXRINGMODULATOR_FREQUENCY, + EAXRINGMODULATOR_HIGHPASSCUTOFF, + EAXRINGMODULATOR_WAVEFORM, +}; // EAXRINGMODULATOR_PROPERTY + +enum : + unsigned long +{ + EAX_RINGMODULATOR_SINUSOID, + EAX_RINGMODULATOR_SAWTOOTH, + EAX_RINGMODULATOR_SQUARE, +}; + +// Use this structure for EAXRINGMODULATOR_ALLPARAMETERS +struct EAXRINGMODULATORPROPERTIES +{ + float flFrequency; // Frequency of modulation (Hz) + float flHighPassCutOff; // Cut-off frequency of high-pass filter (Hz) + unsigned long ulWaveform; // Waveform selector - see enum above +}; // EAXRINGMODULATORPROPERTIES + + +constexpr auto EAXRINGMODULATOR_MINFREQUENCY = 0.0F; +constexpr auto EAXRINGMODULATOR_MAXFREQUENCY = 8000.0F; +constexpr auto EAXRINGMODULATOR_DEFAULTFREQUENCY = 440.0F; + +constexpr auto EAXRINGMODULATOR_MINHIGHPASSCUTOFF = 0.0F; +constexpr auto EAXRINGMODULATOR_MAXHIGHPASSCUTOFF = 24000.0F; +constexpr auto EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF = 800.0F; + +constexpr auto EAXRINGMODULATOR_MINWAVEFORM = 0UL; +constexpr auto EAXRINGMODULATOR_MAXWAVEFORM = 2UL; +constexpr auto EAXRINGMODULATOR_DEFAULTWAVEFORM = EAXRINGMODULATOR_MINWAVEFORM; + + +using LPEAXSET = ALenum(AL_APIENTRY*)( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + +using LPEAXGET = ALenum(AL_APIENTRY*)( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + +#endif // !EAX_API_INCLUDED diff --git a/al/eax/eax_call.cpp b/al/eax/eax_call.cpp new file mode 100644 index 00000000..19565852 --- /dev/null +++ b/al/eax/eax_call.cpp @@ -0,0 +1,323 @@ +#include "config.h" + +#include "eax_call.h" +#include "exception.h" + + +namespace { + +constexpr auto deferred_flag = 0x80000000U; + +class EaxEaxCallException : + public EaxException +{ +public: + explicit EaxEaxCallException( + const char* message) + : + EaxException{"EAX_EAX_CALL", message} + { + } +}; // EaxEaxCallException + +} // namespace + + +EaxEaxCall::EaxEaxCall( + bool is_get, + const GUID& property_set_guid, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) + : is_get_{is_get}, version_{0}, property_set_id_{EaxEaxCallPropertySetId::none} + , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} + , property_buffer_{property_buffer}, property_size_{property_size} +{ + if (false) + { + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Context) + { + version_ = 4; + property_set_id_ = EaxEaxCallPropertySetId::context; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Context) + { + version_ = 5; + property_set_id_ = EaxEaxCallPropertySetId::context; + } + else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties) + { + version_ = 2; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + property_id_ = convert_eax_v2_0_listener_property_id(property_id_); + } + else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties) + { + version_ = 3; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0) + { + version_ = 4; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0) + { + version_ = 5; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1) + { + version_ = 4; + fx_slot_index_ = 1u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1) + { + version_ = 5; + fx_slot_index_ = 1u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2) + { + version_ = 4; + fx_slot_index_ = 2u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2) + { + version_ = 5; + fx_slot_index_ = 2u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3) + { + version_ = 4; + fx_slot_index_ = 3u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3) + { + version_ = 5; + fx_slot_index_ = 3u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties) + { + version_ = 2; + property_set_id_ = EaxEaxCallPropertySetId::source; + property_id_ = convert_eax_v2_0_buffer_property_id(property_id_); + } + else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties) + { + version_ = 3; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Source) + { + version_ = 4; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Source) + { + version_ = 5; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties) + { + version_ = 1; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties) + { + version_ = 1; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else + { + fail("Unsupported property set id."); + } + + if (version_ < 1 || version_ > 5) + { + fail("EAX version out of range."); + } + + if(!(property_id&deferred_flag)) + { + if(property_set_id_ != EaxEaxCallPropertySetId::fx_slot && property_id_ != 0) + { + if (!property_buffer) + { + fail("Null property buffer."); + } + + if (property_size == 0) + { + fail("Empty property."); + } + } + } + + if(property_set_id_ == EaxEaxCallPropertySetId::source && property_source_id_ == 0) + { + fail("Null AL source id."); + } + + if (property_set_id_ == EaxEaxCallPropertySetId::fx_slot) + { + if (property_id_ < EAXFXSLOT_NONE) + { + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + } + } +} + +[[noreturn]] +void EaxEaxCall::fail( + const char* message) +{ + throw EaxEaxCallException{message}; +} + +ALuint EaxEaxCall::convert_eax_v2_0_listener_property_id( + ALuint property_id) +{ + switch (property_id) + { + case DSPROPERTY_EAX20LISTENER_NONE: + return EAXREVERB_NONE; + + case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: + return EAXREVERB_ALLPARAMETERS; + + case DSPROPERTY_EAX20LISTENER_ROOM: + return EAXREVERB_ROOM; + + case DSPROPERTY_EAX20LISTENER_ROOMHF: + return EAXREVERB_ROOMHF; + + case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: + return EAXREVERB_ROOMROLLOFFFACTOR; + + case DSPROPERTY_EAX20LISTENER_DECAYTIME: + return EAXREVERB_DECAYTIME; + + case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: + return EAXREVERB_DECAYHFRATIO; + + case DSPROPERTY_EAX20LISTENER_REFLECTIONS: + return EAXREVERB_REFLECTIONS; + + case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: + return EAXREVERB_REFLECTIONSDELAY; + + case DSPROPERTY_EAX20LISTENER_REVERB: + return EAXREVERB_REVERB; + + case DSPROPERTY_EAX20LISTENER_REVERBDELAY: + return EAXREVERB_REVERBDELAY; + + case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: + return EAXREVERB_ENVIRONMENT; + + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: + return EAXREVERB_ENVIRONMENTSIZE; + + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: + return EAXREVERB_ENVIRONMENTDIFFUSION; + + case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: + return EAXREVERB_AIRABSORPTIONHF; + + case DSPROPERTY_EAX20LISTENER_FLAGS: + return EAXREVERB_FLAGS; + + default: + fail("Unsupported EAX 2.0 listener property id."); + } +} + +ALuint EaxEaxCall::convert_eax_v2_0_buffer_property_id( + ALuint property_id) +{ + switch (property_id) + { + case DSPROPERTY_EAX20BUFFER_NONE: + return EAXSOURCE_NONE; + + case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS: + return EAXSOURCE_ALLPARAMETERS; + + case DSPROPERTY_EAX20BUFFER_DIRECT: + return EAXSOURCE_DIRECT; + + case DSPROPERTY_EAX20BUFFER_DIRECTHF: + return EAXSOURCE_DIRECTHF; + + case DSPROPERTY_EAX20BUFFER_ROOM: + return EAXSOURCE_ROOM; + + case DSPROPERTY_EAX20BUFFER_ROOMHF: + return EAXSOURCE_ROOMHF; + + case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR: + return EAXSOURCE_ROOMROLLOFFFACTOR; + + case DSPROPERTY_EAX20BUFFER_OBSTRUCTION: + return EAXSOURCE_OBSTRUCTION; + + case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO: + return EAXSOURCE_OBSTRUCTIONLFRATIO; + + case DSPROPERTY_EAX20BUFFER_OCCLUSION: + return EAXSOURCE_OCCLUSION; + + case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO: + return EAXSOURCE_OCCLUSIONLFRATIO; + + case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO: + return EAXSOURCE_OCCLUSIONROOMRATIO; + + case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF: + return EAXSOURCE_OUTSIDEVOLUMEHF; + + case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR: + return EAXSOURCE_AIRABSORPTIONFACTOR; + + case DSPROPERTY_EAX20BUFFER_FLAGS: + return EAXSOURCE_FLAGS; + + default: + fail("Unsupported EAX 2.0 buffer property id."); + } +} + + +EaxEaxCall create_eax_call( + bool is_get, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) +{ + if(!property_set_id) + throw EaxEaxCallException{"Null property set ID."}; + + return EaxEaxCall{ + is_get, + *property_set_id, + property_id, + property_source_id, + property_buffer, + property_size + }; +} diff --git a/al/eax/eax_call.h b/al/eax/eax_call.h new file mode 100644 index 00000000..2c90bdc3 --- /dev/null +++ b/al/eax/eax_call.h @@ -0,0 +1,117 @@ +#ifndef EAX_EAX_CALL_INCLUDED +#define EAX_EAX_CALL_INCLUDED + + +#include "AL/al.h" + +#include "alspan.h" + +#include "api.h" +#include "fx_slot_index.h" + + +enum class EaxEaxCallPropertySetId +{ + none, + + context, + fx_slot, + source, + fx_slot_effect, +}; // EaxEaxCallPropertySetId + + +class EaxEaxCall +{ +public: + EaxEaxCall( + bool is_get, + const GUID& property_set_guid, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + bool is_get() const noexcept { return is_get_; } + int get_version() const noexcept { return version_; } + EaxEaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } + ALuint get_property_id() const noexcept { return property_id_; } + ALuint get_property_al_name() const noexcept { return property_source_id_; } + EaxFxSlotIndex get_fx_slot_index() const noexcept { return fx_slot_index_; } + + template< + typename TException, + typename TValue + > + TValue& get_value() const + { + if (property_size_ < static_cast<ALuint>(sizeof(TValue))) + { + throw TException{"Property buffer too small."}; + } + + return *static_cast<TValue*>(property_buffer_); + } + + template< + typename TException, + typename TValue + > + al::span<TValue> get_values() const + { + if (property_size_ < static_cast<ALuint>(sizeof(TValue))) + { + throw TException{"Property buffer too small."}; + } + + const auto count = property_size_ / sizeof(TValue); + + return al::span<TValue>{static_cast<TValue*>(property_buffer_), count}; + } + + template< + typename TException, + typename TValue + > + void set_value( + const TValue& value) const + { + get_value<TException, TValue>() = value; + } + + +private: + const bool is_get_; + int version_; + EaxFxSlotIndex fx_slot_index_; + EaxEaxCallPropertySetId property_set_id_; + + ALuint property_id_; + const ALuint property_source_id_; + ALvoid*const property_buffer_; + const ALuint property_size_; + + + [[noreturn]] + static void fail( + const char* message); + + + static ALuint convert_eax_v2_0_listener_property_id( + ALuint property_id); + + static ALuint convert_eax_v2_0_buffer_property_id( + ALuint property_id); +}; // EaxEaxCall + + +EaxEaxCall create_eax_call( + bool is_get, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + +#endif // !EAX_EAX_CALL_INCLUDED diff --git a/al/eax/effect.cpp b/al/eax/effect.cpp new file mode 100644 index 00000000..4e8faa73 --- /dev/null +++ b/al/eax/effect.cpp @@ -0,0 +1,3 @@ +#include "config.h" + +#include "effect.h" diff --git a/al/eax/effect.h b/al/eax/effect.h new file mode 100644 index 00000000..9c9fdef4 --- /dev/null +++ b/al/eax/effect.h @@ -0,0 +1,44 @@ +#ifndef EAX_EFFECT_INCLUDED +#define EAX_EFFECT_INCLUDED + + +#include <memory> + +#include "AL/al.h" +#include "core/effects/base.h" +#include "eax_call.h" + +class EaxEffect +{ +public: + EaxEffect(ALenum type) : al_effect_type_{type} { } + virtual ~EaxEffect() = default; + + const ALenum al_effect_type_; + EffectProps al_effect_props_{}; + + virtual void dispatch(const EaxEaxCall& eax_call) = 0; + + // Returns "true" if any immediated property was changed. + // [[nodiscard]] + virtual bool apply_deferred() = 0; +}; // EaxEffect + + +using EaxEffectUPtr = std::unique_ptr<EaxEffect>; + +EaxEffectUPtr eax_create_eax_null_effect(); +EaxEffectUPtr eax_create_eax_chorus_effect(); +EaxEffectUPtr eax_create_eax_distortion_effect(); +EaxEffectUPtr eax_create_eax_echo_effect(); +EaxEffectUPtr eax_create_eax_flanger_effect(); +EaxEffectUPtr eax_create_eax_frequency_shifter_effect(); +EaxEffectUPtr eax_create_eax_vocal_morpher_effect(); +EaxEffectUPtr eax_create_eax_pitch_shifter_effect(); +EaxEffectUPtr eax_create_eax_ring_modulator_effect(); +EaxEffectUPtr eax_create_eax_auto_wah_effect(); +EaxEffectUPtr eax_create_eax_compressor_effect(); +EaxEffectUPtr eax_create_eax_equalizer_effect(); +EaxEffectUPtr eax_create_eax_reverb_effect(); + +#endif // !EAX_EFFECT_INCLUDED diff --git a/al/eax/exception.cpp b/al/eax/exception.cpp new file mode 100644 index 00000000..3b319648 --- /dev/null +++ b/al/eax/exception.cpp @@ -0,0 +1,62 @@ +#include "config.h" + +#include "exception.h" + +#include <cassert> +#include <string> + + +EaxException::EaxException( + const char* context, + const char* message) + : + std::runtime_error{make_message(context, message)} +{ +} + +std::string EaxException::make_message( + const char* context, + const char* message) +{ + const auto context_size = (context ? std::string::traits_type::length(context) : 0); + const auto has_contex = (context_size > 0); + + const auto message_size = (message ? std::string::traits_type::length(message) : 0); + const auto has_message = (message_size > 0); + + if (!has_contex && !has_message) + { + return std::string{}; + } + + static constexpr char left_prefix[] = "["; + const auto left_prefix_size = std::string::traits_type::length(left_prefix); + + static constexpr char right_prefix[] = "] "; + const auto right_prefix_size = std::string::traits_type::length(right_prefix); + + const auto what_size = + ( + has_contex ? + left_prefix_size + context_size + right_prefix_size : + 0) + + message_size + + 1; + + auto what = std::string{}; + what.reserve(what_size); + + if (has_contex) + { + what.append(left_prefix, left_prefix_size); + what.append(context, context_size); + what.append(right_prefix, right_prefix_size); + } + + if (has_message) + { + what.append(message, message_size); + } + + return what; +} diff --git a/al/eax/exception.h b/al/eax/exception.h new file mode 100644 index 00000000..9a7acf71 --- /dev/null +++ b/al/eax/exception.h @@ -0,0 +1,25 @@ +#ifndef EAX_EXCEPTION_INCLUDED +#define EAX_EXCEPTION_INCLUDED + + +#include <stdexcept> +#include <string> + + +class EaxException : + public std::runtime_error +{ +public: + EaxException( + const char* context, + const char* message); + + +private: + static std::string make_message( + const char* context, + const char* message); +}; // EaxException + + +#endif // !EAX_EXCEPTION_INCLUDED diff --git a/al/eax/fx_slot_index.cpp b/al/eax/fx_slot_index.cpp new file mode 100644 index 00000000..28b11882 --- /dev/null +++ b/al/eax/fx_slot_index.cpp @@ -0,0 +1,71 @@ +#include "config.h" + +#include "fx_slot_index.h" + +#include "exception.h" + + +namespace +{ + + +class EaxFxSlotIndexException : + public EaxException +{ +public: + explicit EaxFxSlotIndexException( + const char* message) + : + EaxException{"EAX_FX_SLOT_INDEX", message} + { + } +}; // EaxFxSlotIndexException + + +} // namespace + + +void EaxFxSlotIndex::set(EaxFxSlotIndexValue index) +{ + if(index >= EaxFxSlotIndexValue{EAX_MAX_FXSLOTS}) + fail("Index out of range."); + + emplace(index); +} + +void EaxFxSlotIndex::set(const GUID &guid) +{ + if (false) + { + } + else if (guid == EAX_NULL_GUID) + { + reset(); + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot0 || guid == EAXPROPERTYID_EAX50_FXSlot0) + { + emplace(0u); + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot1 || guid == EAXPROPERTYID_EAX50_FXSlot1) + { + emplace(1u); + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot2 || guid == EAXPROPERTYID_EAX50_FXSlot2) + { + emplace(2u); + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot3 || guid == EAXPROPERTYID_EAX50_FXSlot3) + { + emplace(3u); + } + else + { + fail("Unsupported GUID."); + } +} + +[[noreturn]] +void EaxFxSlotIndex::fail(const char* message) +{ + throw EaxFxSlotIndexException{message}; +} diff --git a/al/eax/fx_slot_index.h b/al/eax/fx_slot_index.h new file mode 100644 index 00000000..63dba037 --- /dev/null +++ b/al/eax/fx_slot_index.h @@ -0,0 +1,41 @@ +#ifndef EAX_FX_SLOT_INDEX_INCLUDED +#define EAX_FX_SLOT_INDEX_INCLUDED + + +#include <cstddef> + +#include "aloptional.h" +#include "api.h" + + +using EaxFxSlotIndexValue = std::size_t; + +class EaxFxSlotIndex : public al::optional<EaxFxSlotIndexValue> +{ +public: + using al::optional<EaxFxSlotIndexValue>::optional; + + EaxFxSlotIndex& operator=(const EaxFxSlotIndexValue &value) { set(value); return *this; } + EaxFxSlotIndex& operator=(const GUID &guid) { set(guid); return *this; } + + void set(EaxFxSlotIndexValue index); + void set(const GUID& guid); + +private: + [[noreturn]] + static void fail(const char *message); +}; // EaxFxSlotIndex + +inline bool operator==(const EaxFxSlotIndex& lhs, const EaxFxSlotIndex& rhs) noexcept +{ + if(lhs.has_value() != rhs.has_value()) + return false; + if(lhs.has_value()) + return *lhs == *rhs; + return true; +} + +inline bool operator!=(const EaxFxSlotIndex& lhs, const EaxFxSlotIndex& rhs) noexcept +{ return !(lhs == rhs); } + +#endif // !EAX_FX_SLOT_INDEX_INCLUDED diff --git a/al/eax/fx_slots.cpp b/al/eax/fx_slots.cpp new file mode 100644 index 00000000..5897e951 --- /dev/null +++ b/al/eax/fx_slots.cpp @@ -0,0 +1,83 @@ +#include "config.h" + +#include "fx_slots.h" + +#include <array> + +#include "api.h" +#include "exception.h" + + +namespace +{ + + +class EaxFxSlotsException : + public EaxException +{ +public: + explicit EaxFxSlotsException( + const char* message) + : + EaxException{"EAX_FX_SLOTS", message} + { + } +}; // EaxFxSlotsException + + +} // namespace + + +void EaxFxSlots::initialize( + ALCcontext& al_context) +{ + initialize_fx_slots(al_context); +} + +void EaxFxSlots::uninitialize() noexcept +{ + for (auto& fx_slot : fx_slots_) + { + fx_slot = nullptr; + } +} + +const ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index) const +{ + if(!index.has_value()) + fail("Empty index."); + return *fx_slots_[index.value()]; +} + +ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index) +{ + if(!index.has_value()) + fail("Empty index."); + return *fx_slots_[index.value()]; +} + +void EaxFxSlots::unlock_legacy() noexcept +{ + fx_slots_[0]->eax_unlock_legacy(); + fx_slots_[1]->eax_unlock_legacy(); +} + +[[noreturn]] +void EaxFxSlots::fail( + const char* message) +{ + throw EaxFxSlotsException{message}; +} + +void EaxFxSlots::initialize_fx_slots( + ALCcontext& al_context) +{ + auto fx_slot_index = EaxFxSlotIndexValue{}; + + for (auto& fx_slot : fx_slots_) + { + fx_slot = eax_create_al_effect_slot(al_context); + fx_slot->eax_initialize(al_context, fx_slot_index); + fx_slot_index += 1; + } +} diff --git a/al/eax/fx_slots.h b/al/eax/fx_slots.h new file mode 100644 index 00000000..49cabd75 --- /dev/null +++ b/al/eax/fx_slots.h @@ -0,0 +1,53 @@ +#ifndef EAX_FX_SLOTS_INCLUDED +#define EAX_FX_SLOTS_INCLUDED + + +#include <array> + +#include "al/auxeffectslot.h" + +#include "api.h" +#include "fx_slot_index.h" + + +class EaxFxSlots +{ +public: + void initialize( + ALCcontext& al_context); + + void uninitialize() noexcept; + + void commit() + { + for(auto& fx_slot : fx_slots_) + fx_slot->eax_commit(); + } + + + const ALeffectslot& get( + EaxFxSlotIndex index) const; + + ALeffectslot& get( + EaxFxSlotIndex index); + + void unlock_legacy() noexcept; + + +private: + using Items = std::array<EaxAlEffectSlotUPtr, EAX_MAX_FXSLOTS>; + + + Items fx_slots_{}; + + + [[noreturn]] + static void fail( + const char* message); + + void initialize_fx_slots( + ALCcontext& al_context); +}; // EaxFxSlots + + +#endif // !EAX_FX_SLOTS_INCLUDED diff --git a/al/eax/globals.cpp b/al/eax/globals.cpp new file mode 100644 index 00000000..80e9dbfe --- /dev/null +++ b/al/eax/globals.cpp @@ -0,0 +1,21 @@ +#include "config.h" + +#include "globals.h" + + +bool eax_g_is_enabled = true; + + +const char eax1_ext_name[] = "EAX"; +const char eax2_ext_name[] = "EAX2.0"; +const char eax3_ext_name[] = "EAX3.0"; +const char eax4_ext_name[] = "EAX4.0"; +const char eax5_ext_name[] = "EAX5.0"; + +const char eax_x_ram_ext_name[] = "EAX-RAM"; + +const char eax_eax_set_func_name[] = "EAXSet"; +const char eax_eax_get_func_name[] = "EAXGet"; + +const char eax_eax_set_buffer_mode_func_name[] = "EAXSetBufferMode"; +const char eax_eax_get_buffer_mode_func_name[] = "EAXGetBufferMode"; diff --git a/al/eax/globals.h b/al/eax/globals.h new file mode 100644 index 00000000..1b4d63b8 --- /dev/null +++ b/al/eax/globals.h @@ -0,0 +1,22 @@ +#ifndef EAX_GLOBALS_INCLUDED +#define EAX_GLOBALS_INCLUDED + + +extern bool eax_g_is_enabled; + + +extern const char eax1_ext_name[]; +extern const char eax2_ext_name[]; +extern const char eax3_ext_name[]; +extern const char eax4_ext_name[]; +extern const char eax5_ext_name[]; + +extern const char eax_x_ram_ext_name[]; + +extern const char eax_eax_set_func_name[]; +extern const char eax_eax_get_func_name[]; + +extern const char eax_eax_set_buffer_mode_func_name[]; +extern const char eax_eax_get_buffer_mode_func_name[]; + +#endif // !EAX_GLOBALS_INCLUDED diff --git a/al/eax/utils.cpp b/al/eax/utils.cpp new file mode 100644 index 00000000..9fa2871d --- /dev/null +++ b/al/eax/utils.cpp @@ -0,0 +1,36 @@ +#include "config.h" + +#include "utils.h" + +#include <cassert> +#include <exception> + +#include "core/logging.h" + + +void eax_log_exception( + const char* message) noexcept +{ + const auto exception_ptr = std::current_exception(); + + assert(exception_ptr); + + if (message) + { + ERR("%s\n", message); + } + + try + { + std::rethrow_exception(exception_ptr); + } + catch (const std::exception& ex) + { + const auto ex_message = ex.what(); + ERR("%s\n", ex_message); + } + catch (...) + { + ERR("%s\n", "Generic exception."); + } +} diff --git a/al/eax/utils.h b/al/eax/utils.h new file mode 100644 index 00000000..d3d4a196 --- /dev/null +++ b/al/eax/utils.h @@ -0,0 +1,132 @@ +#ifndef EAX_UTILS_INCLUDED +#define EAX_UTILS_INCLUDED + +#include <algorithm> +#include <cstdint> +#include <string> +#include <type_traits> + + +struct EaxAlLowPassParam +{ + float gain; + float gain_hf; +}; // EaxAlLowPassParam + + +void eax_log_exception( + const char* message = nullptr) noexcept; + + +template< + typename TException, + typename TValue +> +void eax_validate_range( + const char* value_name, + const TValue& value, + const TValue& min_value, + const TValue& max_value) +{ + if (value >= min_value && value <= max_value) + { + return; + } + + const auto message = + std::string{value_name} + + " out of range (value: " + + std::to_string(value) + "; min: " + + std::to_string(min_value) + "; max: " + + std::to_string(max_value) + ")."; + + throw TException{message.c_str()}; +} + + +namespace detail +{ + + +template< + typename T +> +struct EaxIsBitFieldStruct +{ +private: + using yes = std::true_type; + using no = std::false_type; + + template< + typename U + > + static auto test(int) -> decltype(std::declval<typename U::EaxIsBitFieldStruct>(), yes{}); + + template< + typename + > + static no test(...); + + +public: + static constexpr auto value = std::is_same<decltype(test<T>(0)), yes>::value; +}; // EaxIsBitFieldStruct + + +template< + typename T, + typename TValue +> +inline bool eax_bit_fields_are_equal( + const T& lhs, + const T& rhs) noexcept +{ + static_assert(sizeof(T) == sizeof(TValue), "Invalid type size."); + + return reinterpret_cast<const TValue&>(lhs) == reinterpret_cast<const TValue&>(rhs); +} + + +} // namespace detail + + +template< + typename T, + std::enable_if_t<detail::EaxIsBitFieldStruct<T>::value, int> = 0 +> +inline bool operator==( + const T& lhs, + const T& rhs) noexcept +{ + using Value = std::conditional_t< + sizeof(T) == 1, + std::uint8_t, + std::conditional_t< + sizeof(T) == 2, + std::uint16_t, + std::conditional_t< + sizeof(T) == 4, + std::uint32_t, + void + > + > + >; + + static_assert(!std::is_same<Value, void>::value, "Unsupported type."); + + return detail::eax_bit_fields_are_equal<T, Value>(lhs, rhs); +} + +template< + typename T, + std::enable_if_t<detail::EaxIsBitFieldStruct<T>::value, int> = 0 +> +inline bool operator!=( + const T& lhs, + const T& rhs) noexcept +{ + return !(lhs == rhs); +} + + +#endif // !EAX_UTILS_INCLUDED diff --git a/al/eax/x_ram.cpp b/al/eax/x_ram.cpp new file mode 100644 index 00000000..7332c82e --- /dev/null +++ b/al/eax/x_ram.cpp @@ -0,0 +1,3 @@ +#include "config.h" + +#include "x_ram.h" diff --git a/al/eax/x_ram.h b/al/eax/x_ram.h new file mode 100644 index 00000000..438b9916 --- /dev/null +++ b/al/eax/x_ram.h @@ -0,0 +1,38 @@ +#ifndef EAX_X_RAM_INCLUDED +#define EAX_X_RAM_INCLUDED + + +#include "AL/al.h" + + +constexpr auto eax_x_ram_min_size = ALsizei{}; +constexpr auto eax_x_ram_max_size = ALsizei{64 * 1'024 * 1'024}; + + +constexpr auto AL_EAX_RAM_SIZE = ALenum{0x202201}; +constexpr auto AL_EAX_RAM_FREE = ALenum{0x202202}; + +constexpr auto AL_STORAGE_AUTOMATIC = ALenum{0x202203}; +constexpr auto AL_STORAGE_HARDWARE = ALenum{0x202204}; +constexpr auto AL_STORAGE_ACCESSIBLE = ALenum{0x202205}; + + +constexpr auto AL_EAX_RAM_SIZE_NAME = "AL_EAX_RAM_SIZE"; +constexpr auto AL_EAX_RAM_FREE_NAME = "AL_EAX_RAM_FREE"; + +constexpr auto AL_STORAGE_AUTOMATIC_NAME = "AL_STORAGE_AUTOMATIC"; +constexpr auto AL_STORAGE_HARDWARE_NAME = "AL_STORAGE_HARDWARE"; +constexpr auto AL_STORAGE_ACCESSIBLE_NAME = "AL_STORAGE_ACCESSIBLE"; + + +ALboolean AL_APIENTRY EAXSetBufferMode( + ALsizei n, + const ALuint* buffers, + ALint value); + +ALenum AL_APIENTRY EAXGetBufferMode( + ALuint buffer, + ALint* pReserved); + + +#endif // !EAX_X_RAM_INCLUDED |