15 #include "alc/context.h"
16 #include "alc/inprogext.h"
19 #include "alnumeric.h"
21 #include "core/voice.h"
26 #include "eax/exception.h"
27 #include "eax/fx_slot_index.h"
28 #include "eax/utils.h"
35 enum class SourceStereo : bool {
36 Normal = AL_NORMAL_SOFT,
37 Enhanced = AL_SUPER_STEREO_SOFT
40 #define DEFAULT_SENDS 2
42 #define INVALID_VOICE_IDX static_cast<ALuint>(-1)
44 extern bool sBufferSubDataCompat;
46 struct ALbufferQueueItem : public VoiceBufferItem {
47 ALbuffer *mBuffer{nullptr};
54 class EaxSourceException : public EaxException {
56 explicit EaxSourceException(const char* message)
57 : EaxException{"EAX_SOURCE", message}
63 /** Source properties. */
66 float OuterGain{0.0f};
69 float InnerAngle{360.0f};
70 float OuterAngle{360.0f};
71 float RefDistance{1.0f};
72 float MaxDistance{std::numeric_limits<float>::max()};
73 float RolloffFactor{1.0f};
75 // For EAXSOURCE_ROLLOFFFACTOR, which is distinct from and added to
77 float RolloffFactor2{0.0f};
79 std::array<float,3> Position{{0.0f, 0.0f, 0.0f}};
80 std::array<float,3> Velocity{{0.0f, 0.0f, 0.0f}};
81 std::array<float,3> Direction{{0.0f, 0.0f, 0.0f}};
82 std::array<float,3> OrientAt{{0.0f, 0.0f, -1.0f}};
83 std::array<float,3> OrientUp{{0.0f, 1.0f, 0.0f}};
84 bool HeadRelative{false};
86 DistanceModel mDistanceModel{DistanceModel::Default};
87 Resampler mResampler{ResamplerDefault};
88 DirectMode DirectChannels{DirectMode::Off};
89 SpatializeMode mSpatialize{SpatializeMode::Auto};
90 SourceStereo mStereoMode{SourceStereo::Normal};
92 bool DryGainHFAuto{true};
93 bool WetGainAuto{true};
94 bool WetGainHFAuto{true};
95 float OuterGainHF{1.0f};
97 float AirAbsorptionFactor{0.0f};
98 float RoomRolloffFactor{0.0f};
99 float DopplerFactor{1.0f};
101 /* NOTE: Stereo pan angles are specified in radians, counter-clockwise
102 * rather than clockwise.
104 std::array<float,2> StereoPan{{al::numbers::pi_v<float>/6.0f, -al::numbers::pi_v<float>/6.0f}};
107 float EnhWidth{0.593f};
109 /** Direct filter and auxiliary send info. */
125 std::array<SendData,MAX_SENDS> Send;
128 * Last user-specified offset, and the offset type (bytes, samples, or
132 ALenum OffsetType{AL_NONE};
134 /** Source type (static, streaming, or undetermined) */
135 ALenum SourceType{AL_UNDETERMINED};
137 /** Source state (initial, playing, paused, or stopped) */
138 ALenum state{AL_INITIAL};
140 /** Source Buffer Queue head. */
141 al::deque<ALbufferQueueItem> mQueue;
143 bool mPropsDirty{true};
145 /* Index into the context's Voices array. Lazily updated, only checked and
146 * reset when looking up the voice.
148 ALuint VoiceIdx{INVALID_VOICE_IDX};
157 ALsource(const ALsource&) = delete;
158 ALsource& operator=(const ALsource&) = delete;
164 void eaxInitialize(ALCcontext *context) noexcept;
165 void eaxDispatch(const EaxCall& call);
167 void eaxMarkAsChanged() noexcept { mEaxChanged = true; }
169 static ALsource* EaxLookupSource(ALCcontext& al_context, ALuint source_id) noexcept;
172 using Exception = EaxSourceException;
174 static constexpr auto eax_max_speakers = 9;
176 using EaxFxSlotIds = const GUID* [EAX_MAX_FXSLOTS];
178 static constexpr const EaxFxSlotIds eax4_fx_slot_ids = {
179 &EAXPROPERTYID_EAX40_FXSlot0,
180 &EAXPROPERTYID_EAX40_FXSlot1,
181 &EAXPROPERTYID_EAX40_FXSlot2,
182 &EAXPROPERTYID_EAX40_FXSlot3,
185 static constexpr const EaxFxSlotIds eax5_fx_slot_ids = {
186 &EAXPROPERTYID_EAX50_FXSlot0,
187 &EAXPROPERTYID_EAX50_FXSlot1,
188 &EAXPROPERTYID_EAX50_FXSlot2,
189 &EAXPROPERTYID_EAX50_FXSlot3,
192 using EaxActiveFxSlots = std::array<bool, EAX_MAX_FXSLOTS>;
193 using EaxSpeakerLevels = std::array<EAXSPEAKERLEVELPROPERTIES, eax_max_speakers>;
194 using EaxSends = std::array<EAXSOURCEALLSENDPROPERTIES, EAX_MAX_FXSLOTS>;
196 using Eax1Props = EAXBUFFER_REVERBPROPERTIES;
198 Eax1Props i; // Immediate.
199 Eax1Props d; // Deferred.
202 using Eax2Props = EAX20BUFFERPROPERTIES;
204 Eax2Props i; // Immediate.
205 Eax2Props d; // Deferred.
208 using Eax3Props = EAX30SOURCEPROPERTIES;
210 Eax3Props i; // Immediate.
211 Eax3Props d; // Deferred.
217 EAX40ACTIVEFXSLOTS active_fx_slots;
219 bool operator==(const Eax4Props& rhs) noexcept
221 return std::memcmp(this, &rhs, sizeof(Eax4Props)) == 0;
226 Eax4Props i; // Immediate.
227 Eax4Props d; // Deferred.
231 EAX50SOURCEPROPERTIES source;
233 EAX50ACTIVEFXSLOTS active_fx_slots;
234 EaxSpeakerLevels speaker_levels;
236 bool operator==(const Eax5Props& rhs) noexcept
238 return std::memcmp(this, &rhs, sizeof(Eax5Props)) == 0;
243 Eax5Props i; // Immediate.
244 Eax5Props d; // Deferred.
247 ALCcontext* mEaxAlContext{};
248 EaxFxSlotIndex mEaxPrimaryFxSlotId{};
249 EaxActiveFxSlots mEaxActiveFxSlots{};
259 // ----------------------------------------------------------------------
262 struct Eax1SourceReverbMixValidator {
263 void operator()(float reverb_mix) const
265 if (reverb_mix == EAX_REVERBMIX_USEDISTANCE)
268 eax_validate_range<Exception>(
271 EAX_BUFFER_MINREVERBMIX,
272 EAX_BUFFER_MAXREVERBMIX);
276 struct Eax2SourceDirectValidator {
277 void operator()(long lDirect) const
279 eax_validate_range<Exception>(
283 EAXSOURCE_MAXDIRECT);
287 struct Eax2SourceDirectHfValidator {
288 void operator()(long lDirectHF) const
290 eax_validate_range<Exception>(
293 EAXSOURCE_MINDIRECTHF,
294 EAXSOURCE_MAXDIRECTHF);
298 struct Eax2SourceRoomValidator {
299 void operator()(long lRoom) const
301 eax_validate_range<Exception>(
309 struct Eax2SourceRoomHfValidator {
310 void operator()(long lRoomHF) const
312 eax_validate_range<Exception>(
316 EAXSOURCE_MAXROOMHF);
320 struct Eax2SourceRoomRolloffFactorValidator {
321 void operator()(float flRoomRolloffFactor) const
323 eax_validate_range<Exception>(
324 "Room Rolloff Factor",
326 EAXSOURCE_MINROOMROLLOFFFACTOR,
327 EAXSOURCE_MAXROOMROLLOFFFACTOR);
331 struct Eax2SourceObstructionValidator {
332 void operator()(long lObstruction) const
334 eax_validate_range<Exception>(
337 EAXSOURCE_MINOBSTRUCTION,
338 EAXSOURCE_MAXOBSTRUCTION);
342 struct Eax2SourceObstructionLfRatioValidator {
343 void operator()(float flObstructionLFRatio) const
345 eax_validate_range<Exception>(
346 "Obstruction LF Ratio",
347 flObstructionLFRatio,
348 EAXSOURCE_MINOBSTRUCTIONLFRATIO,
349 EAXSOURCE_MAXOBSTRUCTIONLFRATIO);
353 struct Eax2SourceOcclusionValidator {
354 void operator()(long lOcclusion) const
356 eax_validate_range<Exception>(
359 EAXSOURCE_MINOCCLUSION,
360 EAXSOURCE_MAXOCCLUSION);
364 struct Eax2SourceOcclusionLfRatioValidator {
365 void operator()(float flOcclusionLFRatio) const
367 eax_validate_range<Exception>(
368 "Occlusion LF Ratio",
370 EAXSOURCE_MINOCCLUSIONLFRATIO,
371 EAXSOURCE_MAXOCCLUSIONLFRATIO);
375 struct Eax2SourceOcclusionRoomRatioValidator {
376 void operator()(float flOcclusionRoomRatio) const
378 eax_validate_range<Exception>(
379 "Occlusion Room Ratio",
380 flOcclusionRoomRatio,
381 EAXSOURCE_MINOCCLUSIONROOMRATIO,
382 EAXSOURCE_MAXOCCLUSIONROOMRATIO);
386 struct Eax2SourceOutsideVolumeHfValidator {
387 void operator()(long lOutsideVolumeHF) const
389 eax_validate_range<Exception>(
392 EAXSOURCE_MINOUTSIDEVOLUMEHF,
393 EAXSOURCE_MAXOUTSIDEVOLUMEHF);
397 struct Eax2SourceAirAbsorptionFactorValidator {
398 void operator()(float flAirAbsorptionFactor) const
400 eax_validate_range<Exception>(
401 "Air Absorption Factor",
402 flAirAbsorptionFactor,
403 EAXSOURCE_MINAIRABSORPTIONFACTOR,
404 EAXSOURCE_MAXAIRABSORPTIONFACTOR);
408 struct Eax2SourceFlagsValidator {
409 void operator()(unsigned long dwFlags) const
411 eax_validate_range<Exception>(
415 ~EAX20SOURCEFLAGS_RESERVED);
419 struct Eax3SourceOcclusionDirectRatioValidator {
420 void operator()(float flOcclusionDirectRatio) const
422 eax_validate_range<Exception>(
423 "Occlusion Direct Ratio",
424 flOcclusionDirectRatio,
425 EAXSOURCE_MINOCCLUSIONDIRECTRATIO,
426 EAXSOURCE_MAXOCCLUSIONDIRECTRATIO);
430 struct Eax3SourceExclusionValidator {
431 void operator()(long lExclusion) const
433 eax_validate_range<Exception>(
436 EAXSOURCE_MINEXCLUSION,
437 EAXSOURCE_MAXEXCLUSION);
441 struct Eax3SourceExclusionLfRatioValidator {
442 void operator()(float flExclusionLFRatio) const
444 eax_validate_range<Exception>(
445 "Exclusion LF Ratio",
447 EAXSOURCE_MINEXCLUSIONLFRATIO,
448 EAXSOURCE_MAXEXCLUSIONLFRATIO);
452 struct Eax3SourceDopplerFactorValidator {
453 void operator()(float flDopplerFactor) const
455 eax_validate_range<Exception>(
458 EAXSOURCE_MINDOPPLERFACTOR,
459 EAXSOURCE_MAXDOPPLERFACTOR);
463 struct Eax3SourceRolloffFactorValidator {
464 void operator()(float flRolloffFactor) const
466 eax_validate_range<Exception>(
469 EAXSOURCE_MINROLLOFFFACTOR,
470 EAXSOURCE_MAXROLLOFFFACTOR);
474 struct Eax5SourceMacroFXFactorValidator {
475 void operator()(float flMacroFXFactor) const
477 eax_validate_range<Exception>(
480 EAXSOURCE_MINMACROFXFACTOR,
481 EAXSOURCE_MAXMACROFXFACTOR);
485 struct Eax5SourceFlagsValidator {
486 void operator()(unsigned long dwFlags) const
488 eax_validate_range<Exception>(
492 ~EAX50SOURCEFLAGS_RESERVED);
496 struct Eax1SourceAllValidator {
497 void operator()(const Eax1Props& props) const
499 Eax1SourceReverbMixValidator{}(props.fMix);
503 struct Eax2SourceAllValidator {
504 void operator()(const Eax2Props& props) const
506 Eax2SourceDirectValidator{}(props.lDirect);
507 Eax2SourceDirectHfValidator{}(props.lDirectHF);
508 Eax2SourceRoomValidator{}(props.lRoom);
509 Eax2SourceRoomHfValidator{}(props.lRoomHF);
510 Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
511 Eax2SourceObstructionValidator{}(props.lObstruction);
512 Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
513 Eax2SourceOcclusionValidator{}(props.lOcclusion);
514 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
515 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
516 Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
517 Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
518 Eax2SourceFlagsValidator{}(props.dwFlags);
522 struct Eax3SourceAllValidator {
523 void operator()(const Eax3Props& props) const
525 Eax2SourceDirectValidator{}(props.lDirect);
526 Eax2SourceDirectHfValidator{}(props.lDirectHF);
527 Eax2SourceRoomValidator{}(props.lRoom);
528 Eax2SourceRoomHfValidator{}(props.lRoomHF);
529 Eax2SourceObstructionValidator{}(props.lObstruction);
530 Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
531 Eax2SourceOcclusionValidator{}(props.lOcclusion);
532 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
533 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
534 Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
535 Eax3SourceExclusionValidator{}(props.lExclusion);
536 Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
537 Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
538 Eax3SourceDopplerFactorValidator{}(props.flDopplerFactor);
539 Eax3SourceRolloffFactorValidator{}(props.flRolloffFactor);
540 Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
541 Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
542 Eax2SourceFlagsValidator{}(props.ulFlags);
546 struct Eax5SourceAllValidator {
547 void operator()(const EAX50SOURCEPROPERTIES& props) const
549 Eax3SourceAllValidator{}(static_cast<const Eax3Props&>(props));
550 Eax5SourceMacroFXFactorValidator{}(props.flMacroFXFactor);
554 struct Eax5SourceAll2dValidator {
555 void operator()(const EAXSOURCE2DPROPERTIES& props) const
557 Eax2SourceDirectValidator{}(props.lDirect);
558 Eax2SourceDirectHfValidator{}(props.lDirectHF);
559 Eax2SourceRoomValidator{}(props.lRoom);
560 Eax2SourceRoomHfValidator{}(props.lRoomHF);
561 Eax5SourceFlagsValidator{}(props.ulFlags);
565 struct Eax4ObstructionValidator {
566 void operator()(const EAXOBSTRUCTIONPROPERTIES& props) const
568 Eax2SourceObstructionValidator{}(props.lObstruction);
569 Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
573 struct Eax4OcclusionValidator {
574 void operator()(const EAXOCCLUSIONPROPERTIES& props) const
576 Eax2SourceOcclusionValidator{}(props.lOcclusion);
577 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
578 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
579 Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
583 struct Eax4ExclusionValidator {
584 void operator()(const EAXEXCLUSIONPROPERTIES& props) const
586 Eax3SourceExclusionValidator{}(props.lExclusion);
587 Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
592 // ----------------------------------------------------------------------
595 struct Eax4SendReceivingFxSlotIdValidator {
596 void operator()(const GUID& guidReceivingFXSlotID) const
598 if (guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot0 &&
599 guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot1 &&
600 guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot2 &&
601 guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot3)
603 eax_fail_unknown_receiving_fx_slot_id();
608 struct Eax5SendReceivingFxSlotIdValidator {
609 void operator()(const GUID& guidReceivingFXSlotID) const
611 if (guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot0 &&
612 guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot1 &&
613 guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot2 &&
614 guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot3)
616 eax_fail_unknown_receiving_fx_slot_id();
621 struct Eax4SendSendValidator {
622 void operator()(long lSend) const
624 eax_validate_range<Exception>(
632 struct Eax4SendSendHfValidator {
633 void operator()(long lSendHF) const
635 eax_validate_range<Exception>(
639 EAXSOURCE_MAXSENDHF);
643 template<typename TIdValidator>
644 struct EaxSendValidator {
645 void operator()(const EAXSOURCESENDPROPERTIES& props) const
647 TIdValidator{}(props.guidReceivingFXSlotID);
648 Eax4SendSendValidator{}(props.lSend);
649 Eax4SendSendHfValidator{}(props.lSendHF);
653 struct Eax4SendValidator : EaxSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
654 struct Eax5SendValidator : EaxSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
656 template<typename TIdValidator>
657 struct EaxOcclusionSendValidator {
658 void operator()(const EAXSOURCEOCCLUSIONSENDPROPERTIES& props) const
660 TIdValidator{}(props.guidReceivingFXSlotID);
661 Eax2SourceOcclusionValidator{}(props.lOcclusion);
662 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
663 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
664 Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
668 struct Eax4OcclusionSendValidator : EaxOcclusionSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
669 struct Eax5OcclusionSendValidator : EaxOcclusionSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
671 template<typename TIdValidator>
672 struct EaxExclusionSendValidator {
673 void operator()(const EAXSOURCEEXCLUSIONSENDPROPERTIES& props) const
675 TIdValidator{}(props.guidReceivingFXSlotID);
676 Eax3SourceExclusionValidator{}(props.lExclusion);
677 Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
681 struct Eax4ExclusionSendValidator : EaxExclusionSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
682 struct Eax5ExclusionSendValidator : EaxExclusionSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
684 template<typename TIdValidator>
685 struct EaxAllSendValidator {
686 void operator()(const EAXSOURCEALLSENDPROPERTIES& props) const
688 TIdValidator{}(props.guidReceivingFXSlotID);
689 Eax4SendSendValidator{}(props.lSend);
690 Eax4SendSendHfValidator{}(props.lSendHF);
691 Eax2SourceOcclusionValidator{}(props.lOcclusion);
692 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
693 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
694 Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
695 Eax3SourceExclusionValidator{}(props.lExclusion);
696 Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
700 struct Eax4AllSendValidator : EaxAllSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
701 struct Eax5AllSendValidator : EaxAllSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
704 // ----------------------------------------------------------------------
705 // Active FX slot ID validators
707 struct Eax4ActiveFxSlotIdValidator {
708 void operator()(const GUID &guid) const
710 if(guid != EAX_NULL_GUID && guid != EAX_PrimaryFXSlotID
711 && guid != EAXPROPERTYID_EAX40_FXSlot0 && guid != EAXPROPERTYID_EAX40_FXSlot1
712 && guid != EAXPROPERTYID_EAX40_FXSlot2 && guid != EAXPROPERTYID_EAX40_FXSlot3)
714 eax_fail_unknown_active_fx_slot_id();
719 struct Eax5ActiveFxSlotIdValidator {
720 void operator()(const GUID &guid) const
722 if(guid != EAX_NULL_GUID && guid != EAX_PrimaryFXSlotID
723 && guid != EAXPROPERTYID_EAX50_FXSlot0 && guid != EAXPROPERTYID_EAX50_FXSlot1
724 && guid != EAXPROPERTYID_EAX50_FXSlot2 && guid != EAXPROPERTYID_EAX50_FXSlot3)
726 eax_fail_unknown_active_fx_slot_id();
731 // Active FX slot ID validators
732 // ----------------------------------------------------------------------
733 // Speaker level validators.
735 struct Eax5SpeakerIdValidator {
736 void operator()(long lSpeakerID) const
738 switch (lSpeakerID) {
739 case EAXSPEAKER_FRONT_LEFT:
740 case EAXSPEAKER_FRONT_CENTER:
741 case EAXSPEAKER_FRONT_RIGHT:
742 case EAXSPEAKER_SIDE_RIGHT:
743 case EAXSPEAKER_REAR_RIGHT:
744 case EAXSPEAKER_REAR_CENTER:
745 case EAXSPEAKER_REAR_LEFT:
746 case EAXSPEAKER_SIDE_LEFT:
747 case EAXSPEAKER_LOW_FREQUENCY:
751 eax_fail("Unknown speaker ID.");
756 struct Eax5SpeakerLevelValidator {
757 void operator()(long lLevel) const
759 // TODO Use a range when the feature will be implemented.
760 if (lLevel != EAXSOURCE_DEFAULTSPEAKERLEVEL)
761 eax_fail("Speaker level out of range.");
765 struct Eax5SpeakerAllValidator {
766 void operator()(const EAXSPEAKERLEVELPROPERTIES& all) const
768 Eax5SpeakerIdValidator{}(all.lSpeakerID);
769 Eax5SpeakerLevelValidator{}(all.lLevel);
773 // Speaker level validators.
774 // ----------------------------------------------------------------------
776 struct Eax4SendIndexGetter {
777 EaxFxSlotIndexValue operator()(const GUID &guid) const
779 if(guid == EAXPROPERTYID_EAX40_FXSlot0)
781 if(guid == EAXPROPERTYID_EAX40_FXSlot1)
783 if(guid == EAXPROPERTYID_EAX40_FXSlot2)
785 if(guid == EAXPROPERTYID_EAX40_FXSlot3)
787 eax_fail_unknown_receiving_fx_slot_id();
791 struct Eax5SendIndexGetter {
792 EaxFxSlotIndexValue operator()(const GUID &guid) const
794 if(guid == EAXPROPERTYID_EAX50_FXSlot0)
796 if(guid == EAXPROPERTYID_EAX50_FXSlot1)
798 if(guid == EAXPROPERTYID_EAX50_FXSlot2)
800 if(guid == EAXPROPERTYID_EAX50_FXSlot3)
802 eax_fail_unknown_receiving_fx_slot_id();
806 [[noreturn]] static void eax_fail(const char* message);
807 [[noreturn]] static void eax_fail_unknown_property_id();
808 [[noreturn]] static void eax_fail_unknown_version();
809 [[noreturn]] static void eax_fail_unknown_active_fx_slot_id();
810 [[noreturn]] static void eax_fail_unknown_receiving_fx_slot_id();
812 void eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept;
813 void eax1_set_defaults(Eax1Props& props) noexcept;
814 void eax1_set_defaults() noexcept;
815 void eax2_set_defaults(Eax2Props& props) noexcept;
816 void eax2_set_defaults() noexcept;
817 void eax3_set_defaults(Eax3Props& props) noexcept;
818 void eax3_set_defaults() noexcept;
819 void eax4_set_sends_defaults(EaxSends& sends) noexcept;
820 void eax4_set_active_fx_slots_defaults(EAX40ACTIVEFXSLOTS& slots) noexcept;
821 void eax4_set_defaults() noexcept;
822 void eax5_set_source_defaults(EAX50SOURCEPROPERTIES& props) noexcept;
823 void eax5_set_sends_defaults(EaxSends& sends) noexcept;
824 void eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noexcept;
825 void eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept;
826 void eax5_set_defaults(Eax5Props& props) noexcept;
827 void eax5_set_defaults() noexcept;
828 void eax_set_defaults() noexcept;
830 void eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept;
831 void eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept;
832 void eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept;
833 void eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept;
835 static float eax_calculate_dst_occlusion_mb(
836 long src_occlusion_mb,
838 float lf_ratio) noexcept;
840 EaxAlLowPassParam eax_create_direct_filter_param() const noexcept;
842 EaxAlLowPassParam eax_create_room_filter_param(
843 const ALeffectslot& fx_slot,
844 const EAXSOURCEALLSENDPROPERTIES& send) const noexcept;
846 void eax_update_direct_filter();
847 void eax_update_room_filters();
848 void eax_commit_filters();
850 static void eax_copy_send_for_get(
851 const EAXSOURCEALLSENDPROPERTIES& src,
852 EAXSOURCESENDPROPERTIES& dst) noexcept
854 dst = reinterpret_cast<const EAXSOURCESENDPROPERTIES&>(src);
857 static void eax_copy_send_for_get(
858 const EAXSOURCEALLSENDPROPERTIES& src,
859 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
864 static void eax_copy_send_for_get(
865 const EAXSOURCEALLSENDPROPERTIES& src,
866 EAXSOURCEOCCLUSIONSENDPROPERTIES& dst) noexcept
868 dst.guidReceivingFXSlotID = src.guidReceivingFXSlotID;
869 dst.lOcclusion = src.lOcclusion;
870 dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
871 dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
872 dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
875 static void eax_copy_send_for_get(
876 const EAXSOURCEALLSENDPROPERTIES& src,
877 EAXSOURCEEXCLUSIONSENDPROPERTIES& dst) noexcept
879 dst.guidReceivingFXSlotID = src.guidReceivingFXSlotID;
880 dst.lExclusion = src.lExclusion;
881 dst.flExclusionLFRatio = src.flExclusionLFRatio;
884 template<typename TDstSend>
885 void eax_get_sends(const EaxCall& call, const EaxSends& src_sends)
887 const auto dst_sends = call.get_values<TDstSend>(EAX_MAX_FXSLOTS);
888 const auto count = dst_sends.size();
890 for (auto i = decltype(count){}; i < count; ++i) {
891 const auto& src_send = src_sends[i];
892 auto& dst_send = dst_sends[i];
893 eax_copy_send_for_get(src_send, dst_send);
897 void eax_get_active_fx_slot_id(const EaxCall& call, const GUID* ids, size_t max_count);
898 void eax1_get(const EaxCall& call, const Eax1Props& props);
899 void eax2_get(const EaxCall& call, const Eax2Props& props);
900 void eax3_get_obstruction(const EaxCall& call, const Eax3Props& props);
901 void eax3_get_occlusion(const EaxCall& call, const Eax3Props& props);
902 void eax3_get_exclusion(const EaxCall& call, const Eax3Props& props);
903 void eax3_get(const EaxCall& call, const Eax3Props& props);
904 void eax4_get(const EaxCall& call, const Eax4Props& props);
905 void eax5_get_all_2d(const EaxCall& call, const EAX50SOURCEPROPERTIES& props);
906 void eax5_get_speaker_levels(const EaxCall& call, const EaxSpeakerLevels& props);
907 void eax5_get(const EaxCall& call, const Eax5Props& props);
908 void eax_get(const EaxCall& call);
910 static void eax_copy_send_for_set(
911 const EAXSOURCESENDPROPERTIES& src,
912 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
914 dst.lSend = src.lSend;
915 dst.lSendHF = src.lSendHF;
918 static void eax_copy_send_for_set(
919 const EAXSOURCEALLSENDPROPERTIES& src,
920 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
922 dst.lSend = src.lSend;
923 dst.lSendHF = src.lSendHF;
924 dst.lOcclusion = src.lOcclusion;
925 dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
926 dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
927 dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
928 dst.lExclusion = src.lExclusion;
929 dst.flExclusionLFRatio = src.flExclusionLFRatio;
932 static void eax_copy_send_for_set(
933 const EAXSOURCEOCCLUSIONSENDPROPERTIES& src,
934 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
936 dst.lOcclusion = src.lOcclusion;
937 dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
938 dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
939 dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
942 static void eax_copy_send_for_set(
943 const EAXSOURCEEXCLUSIONSENDPROPERTIES& src,
944 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
946 dst.lExclusion = src.lExclusion;
947 dst.flExclusionLFRatio = src.flExclusionLFRatio;
950 template<typename TValidator, typename TIndexGetter, typename TSrcSend>
951 void eax_defer_sends(const EaxCall& call, EaxSends& dst_sends)
953 const auto src_sends = call.get_values<const TSrcSend>(EAX_MAX_FXSLOTS);
954 std::for_each(src_sends.cbegin(), src_sends.cend(), TValidator{});
955 const auto count = src_sends.size();
956 const auto index_getter = TIndexGetter{};
958 for (auto i = decltype(count){}; i < count; ++i) {
959 const auto& src_send = src_sends[i];
960 const auto dst_index = index_getter(src_send.guidReceivingFXSlotID);
961 auto& dst_send = dst_sends[dst_index];
962 eax_copy_send_for_set(src_send, dst_send);
966 template<typename TValidator, typename TSrcSend>
967 void eax4_defer_sends(const EaxCall& call, EaxSends& dst_sends)
969 eax_defer_sends<TValidator, Eax4SendIndexGetter, TSrcSend>(call, dst_sends);
972 template<typename TValidator, typename TSrcSend>
973 void eax5_defer_sends(const EaxCall& call, EaxSends& dst_sends)
975 eax_defer_sends<TValidator, Eax5SendIndexGetter, TSrcSend>(call, dst_sends);
978 template<typename TValidator, size_t TIdCount>
979 void eax_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount])
981 const auto src_ids = call.get_values<const GUID>(TIdCount);
982 std::for_each(src_ids.cbegin(), src_ids.cend(), TValidator{});
983 std::uninitialized_copy(src_ids.cbegin(), src_ids.cend(), dst_ids);
986 template<size_t TIdCount>
987 void eax4_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount])
989 eax_defer_active_fx_slot_id<Eax4ActiveFxSlotIdValidator>(call, dst_ids);
992 template<size_t TIdCount>
993 void eax5_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount])
995 eax_defer_active_fx_slot_id<Eax5ActiveFxSlotIdValidator>(call, dst_ids);
998 template<typename TValidator, typename TProperty>
999 static void eax_defer(const EaxCall& call, TProperty& property)
1001 const auto& value = call.get_value<Exception, const TProperty>();
1002 TValidator{}(value);
1006 // Defers source's sub-properties (obstruction, occlusion, exclusion).
1007 template<typename TValidator, typename TSubproperty, typename TProperty>
1008 void eax_defer_sub(const EaxCall& call, TProperty& property)
1010 const auto& src_props = call.get_value<Exception, const TSubproperty>();
1011 TValidator{}(src_props);
1012 auto& dst_props = reinterpret_cast<TSubproperty&>(property);
1013 dst_props = src_props;
1016 void eax_set_efx_outer_gain_hf();
1017 void eax_set_efx_doppler_factor();
1018 void eax_set_efx_rolloff_factor();
1019 void eax_set_efx_room_rolloff_factor();
1020 void eax_set_efx_air_absorption_factor();
1021 void eax_set_efx_dry_gain_hf_auto();
1022 void eax_set_efx_wet_gain_auto();
1023 void eax_set_efx_wet_gain_hf_auto();
1025 void eax1_set(const EaxCall& call, Eax1Props& props);
1026 void eax2_set(const EaxCall& call, Eax2Props& props);
1027 void eax3_set(const EaxCall& call, Eax3Props& props);
1028 void eax4_set(const EaxCall& call, Eax4Props& props);
1029 void eax5_defer_all_2d(const EaxCall& call, EAX50SOURCEPROPERTIES& props);
1030 void eax5_defer_speaker_levels(const EaxCall& call, EaxSpeakerLevels& props);
1031 void eax5_set(const EaxCall& call, Eax5Props& props);
1032 void eax_set(const EaxCall& call);
1034 // `alSource3i(source, AL_AUXILIARY_SEND_FILTER, ...)`
1035 void eax_set_al_source_send(ALeffectslot *slot, size_t sendidx,
1036 const EaxAlLowPassParam &filter);
1038 void eax_commit_active_fx_slots();
1039 #endif // ALSOFT_EAX
1042 void UpdateAllSourceProps(ALCcontext *context);