|
|
- #ifndef AL_SOURCE_H
- #define AL_SOURCE_H
-
- #include <array>
- #include <atomic>
- #include <cstddef>
- #include <iterator>
- #include <limits>
- #include <deque>
-
- #include "AL/al.h"
- #include "AL/alc.h"
-
- #include "alc/alu.h"
- #include "alc/context.h"
- #include "alc/inprogext.h"
- #include "aldeque.h"
- #include "almalloc.h"
- #include "alnumeric.h"
- #include "atomic.h"
- #include "core/voice.h"
- #include "vector.h"
-
- #ifdef ALSOFT_EAX
- #include "eax/call.h"
- #include "eax/exception.h"
- #include "eax/fx_slot_index.h"
- #include "eax/utils.h"
- #endif // ALSOFT_EAX
-
- struct ALbuffer;
- struct ALeffectslot;
-
-
- enum class SourceStereo : bool {
- Normal = AL_NORMAL_SOFT,
- Enhanced = AL_SUPER_STEREO_SOFT
- };
-
- #define DEFAULT_SENDS 2
-
- #define INVALID_VOICE_IDX static_cast<ALuint>(-1)
-
- struct ALbufferQueueItem : public VoiceBufferItem {
- ALbuffer *mBuffer{nullptr};
-
- DISABLE_ALLOC()
- };
-
-
- #ifdef ALSOFT_EAX
- class EaxSourceException : public EaxException {
- public:
- explicit EaxSourceException(const char* message)
- : EaxException{"EAX_SOURCE", message}
- {}
- };
- #endif // ALSOFT_EAX
-
- struct ALsource {
- /** Source properties. */
- float Pitch{1.0f};
- float Gain{1.0f};
- float OuterGain{0.0f};
- float MinGain{0.0f};
- float MaxGain{1.0f};
- float InnerAngle{360.0f};
- float OuterAngle{360.0f};
- float RefDistance{1.0f};
- float MaxDistance{std::numeric_limits<float>::max()};
- float RolloffFactor{1.0f};
- #ifdef ALSOFT_EAX
- // For EAXSOURCE_ROLLOFFFACTOR, which is distinct from and added to
- // AL_ROLLOFF_FACTOR
- float RolloffFactor2{0.0f};
- #endif
- std::array<float,3> Position{{0.0f, 0.0f, 0.0f}};
- std::array<float,3> Velocity{{0.0f, 0.0f, 0.0f}};
- std::array<float,3> Direction{{0.0f, 0.0f, 0.0f}};
- std::array<float,3> OrientAt{{0.0f, 0.0f, -1.0f}};
- std::array<float,3> OrientUp{{0.0f, 1.0f, 0.0f}};
- bool HeadRelative{false};
- bool Looping{false};
- DistanceModel mDistanceModel{DistanceModel::Default};
- Resampler mResampler{ResamplerDefault};
- DirectMode DirectChannels{DirectMode::Off};
- SpatializeMode mSpatialize{SpatializeMode::Auto};
- SourceStereo mStereoMode{SourceStereo::Normal};
-
- bool DryGainHFAuto{true};
- bool WetGainAuto{true};
- bool WetGainHFAuto{true};
- float OuterGainHF{1.0f};
-
- float AirAbsorptionFactor{0.0f};
- float RoomRolloffFactor{0.0f};
- float DopplerFactor{1.0f};
-
- /* NOTE: Stereo pan angles are specified in radians, counter-clockwise
- * rather than clockwise.
- */
- std::array<float,2> StereoPan{{al::numbers::pi_v<float>/6.0f, -al::numbers::pi_v<float>/6.0f}};
-
- float Radius{0.0f};
- float EnhWidth{0.593f};
-
- /** Direct filter and auxiliary send info. */
- struct {
- float Gain;
- float GainHF;
- float HFReference;
- float GainLF;
- float LFReference;
- } Direct;
- struct SendData {
- ALeffectslot *Slot;
- float Gain;
- float GainHF;
- float HFReference;
- float GainLF;
- float LFReference;
- };
- std::array<SendData,MAX_SENDS> Send;
-
- /**
- * Last user-specified offset, and the offset type (bytes, samples, or
- * seconds).
- */
- double Offset{0.0};
- ALenum OffsetType{AL_NONE};
-
- /** Source type (static, streaming, or undetermined) */
- ALenum SourceType{AL_UNDETERMINED};
-
- /** Source state (initial, playing, paused, or stopped) */
- ALenum state{AL_INITIAL};
-
- /** Source Buffer Queue head. */
- al::deque<ALbufferQueueItem> mQueue;
-
- bool mPropsDirty{true};
-
- /* Index into the context's Voices array. Lazily updated, only checked and
- * reset when looking up the voice.
- */
- ALuint VoiceIdx{INVALID_VOICE_IDX};
-
- /** Self ID */
- ALuint id{0};
-
-
- ALsource();
- ~ALsource();
-
- ALsource(const ALsource&) = delete;
- ALsource& operator=(const ALsource&) = delete;
-
- DISABLE_ALLOC()
-
- #ifdef ALSOFT_EAX
- public:
- void eax_initialize(ALCcontext *context) noexcept;
- void eax_dispatch(const EaxCall& call);
- void eax_commit() { eax_commit(EaxCommitType::normal); }
- void eax_commit_and_update();
- bool eax_is_initialized() const noexcept { return eax_al_context_ != nullptr; }
-
- static ALsource* eax_lookup_source(ALCcontext& al_context, ALuint source_id) noexcept;
-
- private:
- using Exception = EaxSourceException;
-
- enum class EaxCommitType {
- normal,
- forced,
- };
-
- static constexpr auto eax_max_speakers = 9;
-
- using EaxFxSlotIds = const GUID* [EAX_MAX_FXSLOTS];
-
- static constexpr const EaxFxSlotIds eax4_fx_slot_ids = {
- &EAXPROPERTYID_EAX40_FXSlot0,
- &EAXPROPERTYID_EAX40_FXSlot1,
- &EAXPROPERTYID_EAX40_FXSlot2,
- &EAXPROPERTYID_EAX40_FXSlot3,
- };
-
- static constexpr const EaxFxSlotIds eax5_fx_slot_ids = {
- &EAXPROPERTYID_EAX50_FXSlot0,
- &EAXPROPERTYID_EAX50_FXSlot1,
- &EAXPROPERTYID_EAX50_FXSlot2,
- &EAXPROPERTYID_EAX50_FXSlot3,
- };
-
- using EaxActiveFxSlots = std::array<bool, EAX_MAX_FXSLOTS>;
- using EaxSpeakerLevels = std::array<EAXSPEAKERLEVELPROPERTIES, eax_max_speakers>;
- using EaxSends = std::array<EAXSOURCEALLSENDPROPERTIES, EAX_MAX_FXSLOTS>;
-
- using Eax1Props = EAXBUFFER_REVERBPROPERTIES;
-
- struct Eax1State {
- Eax1Props i; // Immediate.
- Eax1Props d; // Deferred.
- };
-
- using Eax2Props = EAX20BUFFERPROPERTIES;
-
- struct Eax2State {
- Eax2Props i; // Immediate.
- Eax2Props d; // Deferred.
- };
-
- using Eax3Props = EAX30SOURCEPROPERTIES;
-
- struct Eax3State {
- Eax3Props i; // Immediate.
- Eax3Props d; // Deferred.
- };
-
- struct Eax4Props {
- Eax3Props source;
- EaxSends sends;
- EAX40ACTIVEFXSLOTS active_fx_slots;
-
- bool operator==(const Eax4Props& rhs) noexcept
- {
- return std::memcmp(this, &rhs, sizeof(Eax4Props)) == 0;
- }
- };
-
- struct Eax4State {
- Eax4Props i; // Immediate.
- Eax4Props d; // Deferred.
- };
-
- struct Eax5Props {
- EAX50SOURCEPROPERTIES source;
- EaxSends sends;
- EAX50ACTIVEFXSLOTS active_fx_slots;
- EaxSpeakerLevels speaker_levels;
-
- bool operator==(const Eax5Props& rhs) noexcept
- {
- return std::memcmp(this, &rhs, sizeof(Eax5Props)) == 0;
- }
- };
-
- struct Eax5State {
- Eax5Props i; // Immediate.
- Eax5Props d; // Deferred.
- };
-
- ALCcontext* eax_al_context_{};
- EaxFxSlotIndex eax_primary_fx_slot_id_{};
- EaxActiveFxSlots eax_active_fx_slots_{};
- int eax_version_{};
- bool eax_changed_{};
- Eax1State eax1_{};
- Eax2State eax2_{};
- Eax3State eax3_{};
- Eax4State eax4_{};
- Eax5State eax5_{};
- Eax5Props eax_{};
-
- // ----------------------------------------------------------------------
- // Source validators
-
- struct Eax1SourceReverbMixValidator {
- void operator()(float reverb_mix) const
- {
- if (reverb_mix == EAX_REVERBMIX_USEDISTANCE)
- return;
-
- eax_validate_range<Exception>(
- "Reverb Mix",
- reverb_mix,
- EAX_BUFFER_MINREVERBMIX,
- EAX_BUFFER_MAXREVERBMIX);
- }
- };
-
- struct Eax2SourceDirectValidator {
- void operator()(long lDirect) const
- {
- eax_validate_range<Exception>(
- "Direct",
- lDirect,
- EAXSOURCE_MINDIRECT,
- EAXSOURCE_MAXDIRECT);
- }
- };
-
- struct Eax2SourceDirectHfValidator {
- void operator()(long lDirectHF) const
- {
- eax_validate_range<Exception>(
- "Direct HF",
- lDirectHF,
- EAXSOURCE_MINDIRECTHF,
- EAXSOURCE_MAXDIRECTHF);
- }
- };
-
- struct Eax2SourceRoomValidator {
- void operator()(long lRoom) const
- {
- eax_validate_range<Exception>(
- "Room",
- lRoom,
- EAXSOURCE_MINROOM,
- EAXSOURCE_MAXROOM);
- }
- };
-
- struct Eax2SourceRoomHfValidator {
- void operator()(long lRoomHF) const
- {
- eax_validate_range<Exception>(
- "Room HF",
- lRoomHF,
- EAXSOURCE_MINROOMHF,
- EAXSOURCE_MAXROOMHF);
- }
- };
-
- struct Eax2SourceRoomRolloffFactorValidator {
- void operator()(float flRoomRolloffFactor) const
- {
- eax_validate_range<Exception>(
- "Room Rolloff Factor",
- flRoomRolloffFactor,
- EAXSOURCE_MINROOMROLLOFFFACTOR,
- EAXSOURCE_MAXROOMROLLOFFFACTOR);
- }
- };
-
- struct Eax2SourceObstructionValidator {
- void operator()(long lObstruction) const
- {
- eax_validate_range<Exception>(
- "Obstruction",
- lObstruction,
- EAXSOURCE_MINOBSTRUCTION,
- EAXSOURCE_MAXOBSTRUCTION);
- }
- };
-
- struct Eax2SourceObstructionLfRatioValidator {
- void operator()(float flObstructionLFRatio) const
- {
- eax_validate_range<Exception>(
- "Obstruction LF Ratio",
- flObstructionLFRatio,
- EAXSOURCE_MINOBSTRUCTIONLFRATIO,
- EAXSOURCE_MAXOBSTRUCTIONLFRATIO);
- }
- };
-
- struct Eax2SourceOcclusionValidator {
- void operator()(long lOcclusion) const
- {
- eax_validate_range<Exception>(
- "Occlusion",
- lOcclusion,
- EAXSOURCE_MINOCCLUSION,
- EAXSOURCE_MAXOCCLUSION);
- }
- };
-
- struct Eax2SourceOcclusionLfRatioValidator {
- void operator()(float flOcclusionLFRatio) const
- {
- eax_validate_range<Exception>(
- "Occlusion LF Ratio",
- flOcclusionLFRatio,
- EAXSOURCE_MINOCCLUSIONLFRATIO,
- EAXSOURCE_MAXOCCLUSIONLFRATIO);
- }
- };
-
- struct Eax2SourceOcclusionRoomRatioValidator {
- void operator()(float flOcclusionRoomRatio) const
- {
- eax_validate_range<Exception>(
- "Occlusion Room Ratio",
- flOcclusionRoomRatio,
- EAXSOURCE_MINOCCLUSIONROOMRATIO,
- EAXSOURCE_MAXOCCLUSIONROOMRATIO);
- }
- };
-
- struct Eax2SourceOutsideVolumeHfValidator {
- void operator()(long lOutsideVolumeHF) const
- {
- eax_validate_range<Exception>(
- "Outside Volume HF",
- lOutsideVolumeHF,
- EAXSOURCE_MINOUTSIDEVOLUMEHF,
- EAXSOURCE_MAXOUTSIDEVOLUMEHF);
- }
- };
-
- struct Eax2SourceAirAbsorptionFactorValidator {
- void operator()(float flAirAbsorptionFactor) const
- {
- eax_validate_range<Exception>(
- "Air Absorption Factor",
- flAirAbsorptionFactor,
- EAXSOURCE_MINAIRABSORPTIONFACTOR,
- EAXSOURCE_MAXAIRABSORPTIONFACTOR);
- }
- };
-
- struct Eax2SourceFlagsValidator {
- void operator()(unsigned long dwFlags) const
- {
- eax_validate_range<Exception>(
- "Flags",
- dwFlags,
- 0UL,
- ~EAX20SOURCEFLAGS_RESERVED);
- }
- };
-
- struct Eax3SourceOcclusionDirectRatioValidator {
- void operator()(float flOcclusionDirectRatio) const
- {
- eax_validate_range<Exception>(
- "Occlusion Direct Ratio",
- flOcclusionDirectRatio,
- EAXSOURCE_MINOCCLUSIONDIRECTRATIO,
- EAXSOURCE_MAXOCCLUSIONDIRECTRATIO);
- }
- };
-
- struct Eax3SourceExclusionValidator {
- void operator()(long lExclusion) const
- {
- eax_validate_range<Exception>(
- "Exclusion",
- lExclusion,
- EAXSOURCE_MINEXCLUSION,
- EAXSOURCE_MAXEXCLUSION);
- }
- };
-
- struct Eax3SourceExclusionLfRatioValidator {
- void operator()(float flExclusionLFRatio) const
- {
- eax_validate_range<Exception>(
- "Exclusion LF Ratio",
- flExclusionLFRatio,
- EAXSOURCE_MINEXCLUSIONLFRATIO,
- EAXSOURCE_MAXEXCLUSIONLFRATIO);
- }
- };
-
- struct Eax3SourceDopplerFactorValidator {
- void operator()(float flDopplerFactor) const
- {
- eax_validate_range<Exception>(
- "Doppler Factor",
- flDopplerFactor,
- EAXSOURCE_MINDOPPLERFACTOR,
- EAXSOURCE_MAXDOPPLERFACTOR);
- }
- };
-
- struct Eax3SourceRolloffFactorValidator {
- void operator()(float flRolloffFactor) const
- {
- eax_validate_range<Exception>(
- "Rolloff Factor",
- flRolloffFactor,
- EAXSOURCE_MINROLLOFFFACTOR,
- EAXSOURCE_MAXROLLOFFFACTOR);
- }
- };
-
- struct Eax5SourceMacroFXFactorValidator {
- void operator()(float flMacroFXFactor) const
- {
- eax_validate_range<Exception>(
- "Macro FX Factor",
- flMacroFXFactor,
- EAXSOURCE_MINMACROFXFACTOR,
- EAXSOURCE_MAXMACROFXFACTOR);
- }
- };
-
- struct Eax5SourceFlagsValidator {
- void operator()(unsigned long dwFlags) const
- {
- eax_validate_range<Exception>(
- "Flags",
- dwFlags,
- 0UL,
- ~EAX50SOURCEFLAGS_RESERVED);
- }
- };
-
- struct Eax1SourceAllValidator {
- void operator()(const Eax1Props& props) const
- {
- Eax1SourceReverbMixValidator{}(props.fMix);
- }
- };
-
- struct Eax2SourceAllValidator {
- void operator()(const Eax2Props& props) const
- {
- Eax2SourceDirectValidator{}(props.lDirect);
- Eax2SourceDirectHfValidator{}(props.lDirectHF);
- Eax2SourceRoomValidator{}(props.lRoom);
- Eax2SourceRoomHfValidator{}(props.lRoomHF);
- Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
- Eax2SourceObstructionValidator{}(props.lObstruction);
- Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
- Eax2SourceOcclusionValidator{}(props.lOcclusion);
- Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
- Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
- Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
- Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
- Eax2SourceFlagsValidator{}(props.dwFlags);
- }
- };
-
- struct Eax3SourceAllValidator {
- void operator()(const Eax3Props& props) const
- {
- Eax2SourceDirectValidator{}(props.lDirect);
- Eax2SourceDirectHfValidator{}(props.lDirectHF);
- Eax2SourceRoomValidator{}(props.lRoom);
- Eax2SourceRoomHfValidator{}(props.lRoomHF);
- Eax2SourceObstructionValidator{}(props.lObstruction);
- Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
- Eax2SourceOcclusionValidator{}(props.lOcclusion);
- Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
- Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
- Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
- Eax3SourceExclusionValidator{}(props.lExclusion);
- Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
- Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
- Eax3SourceDopplerFactorValidator{}(props.flDopplerFactor);
- Eax3SourceRolloffFactorValidator{}(props.flRolloffFactor);
- Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
- Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
- Eax2SourceFlagsValidator{}(props.ulFlags);
- }
- };
-
- struct Eax5SourceAllValidator {
- void operator()(const EAX50SOURCEPROPERTIES& props) const
- {
- Eax3SourceAllValidator{}(static_cast<const Eax3Props&>(props));
- Eax5SourceMacroFXFactorValidator{}(props.flMacroFXFactor);
- }
- };
-
- struct Eax5SourceAll2dValidator {
- void operator()(const EAXSOURCE2DPROPERTIES& props) const
- {
- Eax2SourceDirectValidator{}(props.lDirect);
- Eax2SourceDirectHfValidator{}(props.lDirectHF);
- Eax2SourceRoomValidator{}(props.lRoom);
- Eax2SourceRoomHfValidator{}(props.lRoomHF);
- Eax5SourceFlagsValidator{}(props.ulFlags);
- }
- };
-
- struct Eax4ObstructionValidator {
- void operator()(const EAXOBSTRUCTIONPROPERTIES& props) const
- {
- Eax2SourceObstructionValidator{}(props.lObstruction);
- Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
- }
- };
-
- struct Eax4OcclusionValidator {
- void operator()(const EAXOCCLUSIONPROPERTIES& props) const
- {
- Eax2SourceOcclusionValidator{}(props.lOcclusion);
- Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
- Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
- Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
- }
- };
-
- struct Eax4ExclusionValidator {
- void operator()(const EAXEXCLUSIONPROPERTIES& props) const
- {
- Eax3SourceExclusionValidator{}(props.lExclusion);
- Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
- }
- };
-
- // Source validators
- // ----------------------------------------------------------------------
- // Send validators
-
- struct Eax4SendReceivingFxSlotIdValidator {
- void operator()(const GUID& guidReceivingFXSlotID) const
- {
- if (guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot0 &&
- guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot1 &&
- guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot2 &&
- guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot3)
- {
- eax_fail_unknown_receiving_fx_slot_id();
- }
- }
- };
-
- struct Eax5SendReceivingFxSlotIdValidator {
- void operator()(const GUID& guidReceivingFXSlotID) const
- {
- if (guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot0 &&
- guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot1 &&
- guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot2 &&
- guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot3)
- {
- eax_fail_unknown_receiving_fx_slot_id();
- }
- }
- };
-
- struct Eax4SendSendValidator {
- void operator()(long lSend) const
- {
- eax_validate_range<Exception>(
- "Send",
- lSend,
- EAXSOURCE_MINSEND,
- EAXSOURCE_MAXSEND);
- }
- };
-
- struct Eax4SendSendHfValidator {
- void operator()(long lSendHF) const
- {
- eax_validate_range<Exception>(
- "Send HF",
- lSendHF,
- EAXSOURCE_MINSENDHF,
- EAXSOURCE_MAXSENDHF);
- }
- };
-
- template<typename TIdValidator>
- struct EaxSendValidator {
- void operator()(const EAXSOURCESENDPROPERTIES& props) const
- {
- TIdValidator{}(props.guidReceivingFXSlotID);
- Eax4SendSendValidator{}(props.lSend);
- Eax4SendSendHfValidator{}(props.lSendHF);
- }
- };
-
- struct Eax4SendValidator : EaxSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
- struct Eax5SendValidator : EaxSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
-
- template<typename TIdValidator>
- struct EaxOcclusionSendValidator {
- void operator()(const EAXSOURCEOCCLUSIONSENDPROPERTIES& props) const
- {
- TIdValidator{}(props.guidReceivingFXSlotID);
- Eax2SourceOcclusionValidator{}(props.lOcclusion);
- Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
- Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
- Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
- }
- };
-
- struct Eax4OcclusionSendValidator : EaxOcclusionSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
- struct Eax5OcclusionSendValidator : EaxOcclusionSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
-
- template<typename TIdValidator>
- struct EaxExclusionSendValidator {
- void operator()(const EAXSOURCEEXCLUSIONSENDPROPERTIES& props) const
- {
- TIdValidator{}(props.guidReceivingFXSlotID);
- Eax3SourceExclusionValidator{}(props.lExclusion);
- Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
- }
- };
-
- struct Eax4ExclusionSendValidator : EaxExclusionSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
- struct Eax5ExclusionSendValidator : EaxExclusionSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
-
- template<typename TIdValidator>
- struct EaxAllSendValidator {
- void operator()(const EAXSOURCEALLSENDPROPERTIES& props) const
- {
- TIdValidator{}(props.guidReceivingFXSlotID);
- Eax4SendSendValidator{}(props.lSend);
- Eax4SendSendHfValidator{}(props.lSendHF);
- Eax2SourceOcclusionValidator{}(props.lOcclusion);
- Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
- Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
- Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
- Eax3SourceExclusionValidator{}(props.lExclusion);
- Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
- }
- };
-
- struct Eax4AllSendValidator : EaxAllSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
- struct Eax5AllSendValidator : EaxAllSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
-
- // Send validators
- // ----------------------------------------------------------------------
- // Active FX slot ID validators
-
- struct Eax4ActiveFxSlotIdValidator {
- void operator()(const GUID &guid) const
- {
- if(guid != EAX_NULL_GUID && guid != EAX_PrimaryFXSlotID
- && guid != EAXPROPERTYID_EAX40_FXSlot0 && guid != EAXPROPERTYID_EAX40_FXSlot1
- && guid != EAXPROPERTYID_EAX40_FXSlot2 && guid != EAXPROPERTYID_EAX40_FXSlot3)
- {
- eax_fail_unknown_active_fx_slot_id();
- }
- }
- };
-
- struct Eax5ActiveFxSlotIdValidator {
- void operator()(const GUID &guid) const
- {
- if(guid != EAX_NULL_GUID && guid != EAX_PrimaryFXSlotID
- && guid != EAXPROPERTYID_EAX50_FXSlot0 && guid != EAXPROPERTYID_EAX50_FXSlot1
- && guid != EAXPROPERTYID_EAX50_FXSlot2 && guid != EAXPROPERTYID_EAX50_FXSlot3)
- {
- eax_fail_unknown_active_fx_slot_id();
- }
- }
- };
-
- // Active FX slot ID validators
- // ----------------------------------------------------------------------
- // Speaker level validators.
-
- struct Eax5SpeakerIdValidator {
- void operator()(long lSpeakerID) const
- {
- switch (lSpeakerID) {
- case EAXSPEAKER_FRONT_LEFT:
- case EAXSPEAKER_FRONT_CENTER:
- case EAXSPEAKER_FRONT_RIGHT:
- case EAXSPEAKER_SIDE_RIGHT:
- case EAXSPEAKER_REAR_RIGHT:
- case EAXSPEAKER_REAR_CENTER:
- case EAXSPEAKER_REAR_LEFT:
- case EAXSPEAKER_SIDE_LEFT:
- case EAXSPEAKER_LOW_FREQUENCY:
- break;
-
- default:
- eax_fail("Unknown speaker ID.");
- }
- }
- };
-
- struct Eax5SpeakerLevelValidator {
- void operator()(long lLevel) const
- {
- // TODO Use a range when the feature will be implemented.
- if (lLevel != EAXSOURCE_DEFAULTSPEAKERLEVEL)
- eax_fail("Speaker level out of range.");
- }
- };
-
- struct Eax5SpeakerAllValidator {
- void operator()(const EAXSPEAKERLEVELPROPERTIES& all) const
- {
- Eax5SpeakerIdValidator{}(all.lSpeakerID);
- Eax5SpeakerLevelValidator{}(all.lLevel);
- }
- };
-
- // Speaker level validators.
- // ----------------------------------------------------------------------
-
- struct Eax4SendIndexGetter {
- EaxFxSlotIndexValue operator()(const GUID &guid) const
- {
- if(guid == EAXPROPERTYID_EAX40_FXSlot0)
- return 0;
- if(guid == EAXPROPERTYID_EAX40_FXSlot1)
- return 1;
- if(guid == EAXPROPERTYID_EAX40_FXSlot2)
- return 2;
- if(guid == EAXPROPERTYID_EAX40_FXSlot3)
- return 3;
- eax_fail_unknown_receiving_fx_slot_id();
- }
- };
-
- struct Eax5SendIndexGetter {
- EaxFxSlotIndexValue operator()(const GUID &guid) const
- {
- if(guid == EAXPROPERTYID_EAX50_FXSlot0)
- return 0;
- if(guid == EAXPROPERTYID_EAX50_FXSlot1)
- return 1;
- if(guid == EAXPROPERTYID_EAX50_FXSlot2)
- return 2;
- if(guid == EAXPROPERTYID_EAX50_FXSlot3)
- return 3;
- eax_fail_unknown_receiving_fx_slot_id();
- }
- };
-
- [[noreturn]] static void eax_fail(const char* message);
- [[noreturn]] static void eax_fail_unknown_property_id();
- [[noreturn]] static void eax_fail_unknown_version();
- [[noreturn]] static void eax_fail_unknown_active_fx_slot_id();
- [[noreturn]] static void eax_fail_unknown_receiving_fx_slot_id();
-
- void eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept;
- void eax1_set_defaults(Eax1Props& props) noexcept;
- void eax1_set_defaults() noexcept;
- void eax2_set_defaults(Eax2Props& props) noexcept;
- void eax2_set_defaults() noexcept;
- void eax3_set_defaults(Eax3Props& props) noexcept;
- void eax3_set_defaults() noexcept;
- void eax4_set_sends_defaults(EaxSends& sends) noexcept;
- void eax4_set_active_fx_slots_defaults(EAX40ACTIVEFXSLOTS& slots) noexcept;
- void eax4_set_defaults() noexcept;
- void eax5_set_source_defaults(EAX50SOURCEPROPERTIES& props) noexcept;
- void eax5_set_sends_defaults(EaxSends& sends) noexcept;
- void eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noexcept;
- void eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept;
- void eax5_set_defaults(Eax5Props& props) noexcept;
- void eax5_set_defaults() noexcept;
- void eax_set_defaults() noexcept;
-
- void eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept;
- void eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept;
- void eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept;
- void eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept;
-
- static float eax_calculate_dst_occlusion_mb(
- long src_occlusion_mb,
- float path_ratio,
- float lf_ratio) noexcept;
-
- EaxAlLowPassParam eax_create_direct_filter_param() const noexcept;
-
- EaxAlLowPassParam eax_create_room_filter_param(
- const ALeffectslot& fx_slot,
- const EAXSOURCEALLSENDPROPERTIES& send) const noexcept;
-
- void eax_update_direct_filter();
- void eax_update_room_filters();
- void eax_commit_filters();
-
- static void eax_copy_send_for_get(
- const EAXSOURCEALLSENDPROPERTIES& src,
- EAXSOURCESENDPROPERTIES& dst) noexcept
- {
- dst = reinterpret_cast<const EAXSOURCESENDPROPERTIES&>(src);
- }
-
- static void eax_copy_send_for_get(
- const EAXSOURCEALLSENDPROPERTIES& src,
- EAXSOURCEALLSENDPROPERTIES& dst) noexcept
- {
- dst = src;
- }
-
- static void eax_copy_send_for_get(
- const EAXSOURCEALLSENDPROPERTIES& src,
- EAXSOURCEOCCLUSIONSENDPROPERTIES& dst) noexcept
- {
- dst.guidReceivingFXSlotID = src.guidReceivingFXSlotID;
- dst.lOcclusion = src.lOcclusion;
- dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
- dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
- dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
- }
-
- static void eax_copy_send_for_get(
- const EAXSOURCEALLSENDPROPERTIES& src,
- EAXSOURCEEXCLUSIONSENDPROPERTIES& dst) noexcept
- {
- dst.guidReceivingFXSlotID = src.guidReceivingFXSlotID;
- dst.lExclusion = src.lExclusion;
- dst.flExclusionLFRatio = src.flExclusionLFRatio;
- }
-
- template<typename TDstSend>
- void eax_get_sends(const EaxCall& call, const EaxSends& src_sends)
- {
- const auto dst_sends = call.get_values<TDstSend>(EAX_MAX_FXSLOTS);
- const auto count = dst_sends.size();
-
- for (auto i = decltype(count){}; i < count; ++i) {
- const auto& src_send = src_sends[i];
- auto& dst_send = dst_sends[i];
- eax_copy_send_for_get(src_send, dst_send);
- }
- }
-
- void eax1_get(const EaxCall& call, const Eax1Props& props);
- void eax2_get(const EaxCall& call, const Eax2Props& props);
- void eax3_get_obstruction(const EaxCall& call, const Eax3Props& props);
- void eax3_get_occlusion(const EaxCall& call, const Eax3Props& props);
- void eax3_get_exclusion(const EaxCall& call, const Eax3Props& props);
- void eax3_get(const EaxCall& call, const Eax3Props& props);
- void eax4_get(const EaxCall& call, const Eax4Props& props);
- void eax5_get_all_2d(const EaxCall& call, const EAX50SOURCEPROPERTIES& props);
- void eax5_get_speaker_levels(const EaxCall& call, const EaxSpeakerLevels& props);
- void eax5_get(const EaxCall& call, const Eax5Props& props);
- void eax_get(const EaxCall& call);
-
- static void eax_copy_send_for_set(
- const EAXSOURCESENDPROPERTIES& src,
- EAXSOURCEALLSENDPROPERTIES& dst) noexcept
- {
- dst.lSend = src.lSend;
- dst.lSendHF = src.lSendHF;
- }
-
- static void eax_copy_send_for_set(
- const EAXSOURCEALLSENDPROPERTIES& src,
- EAXSOURCEALLSENDPROPERTIES& dst) noexcept
- {
- dst.lSend = src.lSend;
- dst.lSendHF = src.lSendHF;
- dst.lOcclusion = src.lOcclusion;
- dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
- dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
- dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
- dst.lExclusion = src.lExclusion;
- dst.flExclusionLFRatio = src.flExclusionLFRatio;
- }
-
- static void eax_copy_send_for_set(
- const EAXSOURCEOCCLUSIONSENDPROPERTIES& src,
- EAXSOURCEALLSENDPROPERTIES& dst) noexcept
- {
- dst.lOcclusion = src.lOcclusion;
- dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
- dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
- dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
- }
-
- static void eax_copy_send_for_set(
- const EAXSOURCEEXCLUSIONSENDPROPERTIES& src,
- EAXSOURCEALLSENDPROPERTIES& dst) noexcept
- {
- dst.lExclusion = src.lExclusion;
- dst.flExclusionLFRatio = src.flExclusionLFRatio;
- }
-
- template<typename TValidator, typename TIndexGetter, typename TSrcSend>
- void eax_defer_sends(const EaxCall& call, EaxSends& dst_sends)
- {
- const auto src_sends = call.get_values<const TSrcSend>(EAX_MAX_FXSLOTS);
- std::for_each(src_sends.cbegin(), src_sends.cend(), TValidator{});
- const auto count = src_sends.size();
- const auto index_getter = TIndexGetter{};
-
- for (auto i = decltype(count){}; i < count; ++i) {
- const auto& src_send = src_sends[i];
- const auto dst_index = index_getter(src_send.guidReceivingFXSlotID);
- auto& dst_send = dst_sends[dst_index];
- eax_copy_send_for_set(src_send, dst_send);
- }
- }
-
- template<typename TValidator, typename TSrcSend>
- void eax4_defer_sends(const EaxCall& call, EaxSends& dst_sends)
- {
- eax_defer_sends<TValidator, Eax4SendIndexGetter, TSrcSend>(call, dst_sends);
- }
-
- template<typename TValidator, typename TSrcSend>
- void eax5_defer_sends(const EaxCall& call, EaxSends& dst_sends)
- {
- eax_defer_sends<TValidator, Eax5SendIndexGetter, TSrcSend>(call, dst_sends);
- }
-
- template<typename TValidator, size_t TIdCount>
- void eax_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount])
- {
- const auto src_ids = call.get_values<const GUID>(TIdCount);
- std::for_each(src_ids.cbegin(), src_ids.cend(), TValidator{});
- std::uninitialized_copy(src_ids.cbegin(), src_ids.cend(), dst_ids);
- }
-
- template<size_t TIdCount>
- void eax4_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount])
- {
- eax_defer_active_fx_slot_id<Eax4ActiveFxSlotIdValidator>(call, dst_ids);
- }
-
- template<size_t TIdCount>
- void eax5_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount])
- {
- eax_defer_active_fx_slot_id<Eax5ActiveFxSlotIdValidator>(call, dst_ids);
- }
-
- template<typename TValidator, typename TProperty>
- static void eax_defer(const EaxCall& call, TProperty& property)
- {
- const auto& value = call.get_value<Exception, const TProperty>();
- TValidator{}(value);
- property = value;
- }
-
- // Defers source's sub-properties (obstruction, occlusion, exclusion).
- template<typename TValidator, typename TSubproperty, typename TProperty>
- void eax_defer_sub(const EaxCall& call, TProperty& property)
- {
- const auto& src_props = call.get_value<Exception, const TSubproperty>();
- TValidator{}(src_props);
- auto& dst_props = reinterpret_cast<TSubproperty&>(property);
- dst_props = src_props;
- }
-
- void eax_set_efx_outer_gain_hf();
- void eax_set_efx_doppler_factor();
- void eax_set_efx_rolloff_factor();
- void eax_set_efx_room_rolloff_factor();
- void eax_set_efx_air_absorption_factor();
- void eax_set_efx_dry_gain_hf_auto();
- void eax_set_efx_wet_gain_auto();
- void eax_set_efx_wet_gain_hf_auto();
-
- void eax1_set(const EaxCall& call, Eax1Props& props);
- void eax2_set(const EaxCall& call, Eax2Props& props);
- void eax3_set(const EaxCall& call, Eax3Props& props);
- void eax4_set(const EaxCall& call, Eax4Props& props);
- void eax5_defer_all_2d(const EaxCall& call, EAX50SOURCEPROPERTIES& props);
- void eax5_defer_speaker_levels(const EaxCall& call, EaxSpeakerLevels& props);
- void eax5_set(const EaxCall& call, Eax5Props& props);
- void eax_set(const EaxCall& call);
-
- // `alSource3i(source, AL_AUXILIARY_SEND_FILTER, ...)`
- void eax_set_al_source_send(ALeffectslot *slot, size_t sendidx,
- const EaxAlLowPassParam &filter);
-
- void eax_commit_active_fx_slots();
- void eax_commit(EaxCommitType commit_type);
- #endif // ALSOFT_EAX
- };
-
- void UpdateAllSourceProps(ALCcontext *context);
-
- #endif
|