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 struct ALbufferQueueItem
: public VoiceBufferItem
{
45 ALbuffer
*mBuffer
{nullptr};
52 class EaxSourceException
: public EaxException
{
54 explicit EaxSourceException(const char* message
)
55 : EaxException
{"EAX_SOURCE", message
}
61 /** Source properties. */
64 float OuterGain
{0.0f
};
67 float InnerAngle
{360.0f
};
68 float OuterAngle
{360.0f
};
69 float RefDistance
{1.0f
};
70 float MaxDistance
{std::numeric_limits
<float>::max()};
71 float RolloffFactor
{1.0f
};
73 // For EAXSOURCE_ROLLOFFFACTOR, which is distinct from and added to
75 float RolloffFactor2
{0.0f
};
77 std::array
<float,3> Position
{{0.0f
, 0.0f
, 0.0f
}};
78 std::array
<float,3> Velocity
{{0.0f
, 0.0f
, 0.0f
}};
79 std::array
<float,3> Direction
{{0.0f
, 0.0f
, 0.0f
}};
80 std::array
<float,3> OrientAt
{{0.0f
, 0.0f
, -1.0f
}};
81 std::array
<float,3> OrientUp
{{0.0f
, 1.0f
, 0.0f
}};
82 bool HeadRelative
{false};
84 DistanceModel mDistanceModel
{DistanceModel::Default
};
85 Resampler mResampler
{ResamplerDefault
};
86 DirectMode DirectChannels
{DirectMode::Off
};
87 SpatializeMode mSpatialize
{SpatializeMode::Auto
};
88 SourceStereo mStereoMode
{SourceStereo::Normal
};
90 bool DryGainHFAuto
{true};
91 bool WetGainAuto
{true};
92 bool WetGainHFAuto
{true};
93 float OuterGainHF
{1.0f
};
95 float AirAbsorptionFactor
{0.0f
};
96 float RoomRolloffFactor
{0.0f
};
97 float DopplerFactor
{1.0f
};
99 /* NOTE: Stereo pan angles are specified in radians, counter-clockwise
100 * rather than clockwise.
102 std::array
<float,2> StereoPan
{{al::numbers::pi_v
<float>/6.0f
, -al::numbers::pi_v
<float>/6.0f
}};
105 float EnhWidth
{0.593f
};
107 /** Direct filter and auxiliary send info. */
123 std::array
<SendData
,MAX_SENDS
> Send
;
126 * Last user-specified offset, and the offset type (bytes, samples, or
130 ALenum OffsetType
{AL_NONE
};
132 /** Source type (static, streaming, or undetermined) */
133 ALenum SourceType
{AL_UNDETERMINED
};
135 /** Source state (initial, playing, paused, or stopped) */
136 ALenum state
{AL_INITIAL
};
138 /** Source Buffer Queue head. */
139 al::deque
<ALbufferQueueItem
> mQueue
;
141 bool mPropsDirty
{true};
143 /* Index into the context's Voices array. Lazily updated, only checked and
144 * reset when looking up the voice.
146 ALuint VoiceIdx
{INVALID_VOICE_IDX
};
155 ALsource(const ALsource
&) = delete;
156 ALsource
& operator=(const ALsource
&) = delete;
162 void eax_initialize(ALCcontext
*context
) noexcept
;
163 void eax_dispatch(const EaxCall
& call
);
164 void eax_commit() { eax_commit(EaxCommitType::normal
); }
165 void eax_commit_and_update();
166 bool eax_is_initialized() const noexcept
{ return eax_al_context_
!= nullptr; }
168 static ALsource
* eax_lookup_source(ALCcontext
& al_context
, ALuint source_id
) noexcept
;
171 using Exception
= EaxSourceException
;
173 enum class EaxCommitType
{
178 static constexpr auto eax_max_speakers
= 9;
180 using EaxFxSlotIds
= const GUID
* [EAX_MAX_FXSLOTS
];
182 static constexpr const EaxFxSlotIds eax4_fx_slot_ids
= {
183 &EAXPROPERTYID_EAX40_FXSlot0
,
184 &EAXPROPERTYID_EAX40_FXSlot1
,
185 &EAXPROPERTYID_EAX40_FXSlot2
,
186 &EAXPROPERTYID_EAX40_FXSlot3
,
189 static constexpr const EaxFxSlotIds eax5_fx_slot_ids
= {
190 &EAXPROPERTYID_EAX50_FXSlot0
,
191 &EAXPROPERTYID_EAX50_FXSlot1
,
192 &EAXPROPERTYID_EAX50_FXSlot2
,
193 &EAXPROPERTYID_EAX50_FXSlot3
,
196 using EaxActiveFxSlots
= std::array
<bool, EAX_MAX_FXSLOTS
>;
197 using EaxSpeakerLevels
= std::array
<EAXSPEAKERLEVELPROPERTIES
, eax_max_speakers
>;
198 using EaxSends
= std::array
<EAXSOURCEALLSENDPROPERTIES
, EAX_MAX_FXSLOTS
>;
200 using Eax1Props
= EAXBUFFER_REVERBPROPERTIES
;
203 Eax1Props i
; // Immediate.
204 Eax1Props d
; // Deferred.
207 using Eax2Props
= EAX20BUFFERPROPERTIES
;
210 Eax2Props i
; // Immediate.
211 Eax2Props d
; // Deferred.
214 using Eax3Props
= EAX30SOURCEPROPERTIES
;
217 Eax3Props i
; // Immediate.
218 Eax3Props d
; // Deferred.
224 EAX40ACTIVEFXSLOTS active_fx_slots
;
226 bool operator==(const Eax4Props
& rhs
) noexcept
228 return std::memcmp(this, &rhs
, sizeof(Eax4Props
)) == 0;
233 Eax4Props i
; // Immediate.
234 Eax4Props d
; // Deferred.
238 EAX50SOURCEPROPERTIES source
;
240 EAX50ACTIVEFXSLOTS active_fx_slots
;
241 EaxSpeakerLevels speaker_levels
;
243 bool operator==(const Eax5Props
& rhs
) noexcept
245 return std::memcmp(this, &rhs
, sizeof(Eax5Props
)) == 0;
250 Eax5Props i
; // Immediate.
251 Eax5Props d
; // Deferred.
254 ALCcontext
* eax_al_context_
{};
255 EaxFxSlotIndex eax_primary_fx_slot_id_
{};
256 EaxActiveFxSlots eax_active_fx_slots_
{};
266 // ----------------------------------------------------------------------
269 struct Eax1SourceReverbMixValidator
{
270 void operator()(float reverb_mix
) const
272 if (reverb_mix
== EAX_REVERBMIX_USEDISTANCE
)
275 eax_validate_range
<Exception
>(
278 EAX_BUFFER_MINREVERBMIX
,
279 EAX_BUFFER_MAXREVERBMIX
);
283 struct Eax2SourceDirectValidator
{
284 void operator()(long lDirect
) const
286 eax_validate_range
<Exception
>(
290 EAXSOURCE_MAXDIRECT
);
294 struct Eax2SourceDirectHfValidator
{
295 void operator()(long lDirectHF
) const
297 eax_validate_range
<Exception
>(
300 EAXSOURCE_MINDIRECTHF
,
301 EAXSOURCE_MAXDIRECTHF
);
305 struct Eax2SourceRoomValidator
{
306 void operator()(long lRoom
) const
308 eax_validate_range
<Exception
>(
316 struct Eax2SourceRoomHfValidator
{
317 void operator()(long lRoomHF
) const
319 eax_validate_range
<Exception
>(
323 EAXSOURCE_MAXROOMHF
);
327 struct Eax2SourceRoomRolloffFactorValidator
{
328 void operator()(float flRoomRolloffFactor
) const
330 eax_validate_range
<Exception
>(
331 "Room Rolloff Factor",
333 EAXSOURCE_MINROOMROLLOFFFACTOR
,
334 EAXSOURCE_MAXROOMROLLOFFFACTOR
);
338 struct Eax2SourceObstructionValidator
{
339 void operator()(long lObstruction
) const
341 eax_validate_range
<Exception
>(
344 EAXSOURCE_MINOBSTRUCTION
,
345 EAXSOURCE_MAXOBSTRUCTION
);
349 struct Eax2SourceObstructionLfRatioValidator
{
350 void operator()(float flObstructionLFRatio
) const
352 eax_validate_range
<Exception
>(
353 "Obstruction LF Ratio",
354 flObstructionLFRatio
,
355 EAXSOURCE_MINOBSTRUCTIONLFRATIO
,
356 EAXSOURCE_MAXOBSTRUCTIONLFRATIO
);
360 struct Eax2SourceOcclusionValidator
{
361 void operator()(long lOcclusion
) const
363 eax_validate_range
<Exception
>(
366 EAXSOURCE_MINOCCLUSION
,
367 EAXSOURCE_MAXOCCLUSION
);
371 struct Eax2SourceOcclusionLfRatioValidator
{
372 void operator()(float flOcclusionLFRatio
) const
374 eax_validate_range
<Exception
>(
375 "Occlusion LF Ratio",
377 EAXSOURCE_MINOCCLUSIONLFRATIO
,
378 EAXSOURCE_MAXOCCLUSIONLFRATIO
);
382 struct Eax2SourceOcclusionRoomRatioValidator
{
383 void operator()(float flOcclusionRoomRatio
) const
385 eax_validate_range
<Exception
>(
386 "Occlusion Room Ratio",
387 flOcclusionRoomRatio
,
388 EAXSOURCE_MINOCCLUSIONROOMRATIO
,
389 EAXSOURCE_MAXOCCLUSIONROOMRATIO
);
393 struct Eax2SourceOutsideVolumeHfValidator
{
394 void operator()(long lOutsideVolumeHF
) const
396 eax_validate_range
<Exception
>(
399 EAXSOURCE_MINOUTSIDEVOLUMEHF
,
400 EAXSOURCE_MAXOUTSIDEVOLUMEHF
);
404 struct Eax2SourceAirAbsorptionFactorValidator
{
405 void operator()(float flAirAbsorptionFactor
) const
407 eax_validate_range
<Exception
>(
408 "Air Absorption Factor",
409 flAirAbsorptionFactor
,
410 EAXSOURCE_MINAIRABSORPTIONFACTOR
,
411 EAXSOURCE_MAXAIRABSORPTIONFACTOR
);
415 struct Eax2SourceFlagsValidator
{
416 void operator()(unsigned long dwFlags
) const
418 eax_validate_range
<Exception
>(
422 ~EAX20SOURCEFLAGS_RESERVED
);
426 struct Eax3SourceOcclusionDirectRatioValidator
{
427 void operator()(float flOcclusionDirectRatio
) const
429 eax_validate_range
<Exception
>(
430 "Occlusion Direct Ratio",
431 flOcclusionDirectRatio
,
432 EAXSOURCE_MINOCCLUSIONDIRECTRATIO
,
433 EAXSOURCE_MAXOCCLUSIONDIRECTRATIO
);
437 struct Eax3SourceExclusionValidator
{
438 void operator()(long lExclusion
) const
440 eax_validate_range
<Exception
>(
443 EAXSOURCE_MINEXCLUSION
,
444 EAXSOURCE_MAXEXCLUSION
);
448 struct Eax3SourceExclusionLfRatioValidator
{
449 void operator()(float flExclusionLFRatio
) const
451 eax_validate_range
<Exception
>(
452 "Exclusion LF Ratio",
454 EAXSOURCE_MINEXCLUSIONLFRATIO
,
455 EAXSOURCE_MAXEXCLUSIONLFRATIO
);
459 struct Eax3SourceDopplerFactorValidator
{
460 void operator()(float flDopplerFactor
) const
462 eax_validate_range
<Exception
>(
465 EAXSOURCE_MINDOPPLERFACTOR
,
466 EAXSOURCE_MAXDOPPLERFACTOR
);
470 struct Eax3SourceRolloffFactorValidator
{
471 void operator()(float flRolloffFactor
) const
473 eax_validate_range
<Exception
>(
476 EAXSOURCE_MINROLLOFFFACTOR
,
477 EAXSOURCE_MAXROLLOFFFACTOR
);
481 struct Eax5SourceMacroFXFactorValidator
{
482 void operator()(float flMacroFXFactor
) const
484 eax_validate_range
<Exception
>(
487 EAXSOURCE_MINMACROFXFACTOR
,
488 EAXSOURCE_MAXMACROFXFACTOR
);
492 struct Eax5SourceFlagsValidator
{
493 void operator()(unsigned long dwFlags
) const
495 eax_validate_range
<Exception
>(
499 ~EAX50SOURCEFLAGS_RESERVED
);
503 struct Eax1SourceAllValidator
{
504 void operator()(const Eax1Props
& props
) const
506 Eax1SourceReverbMixValidator
{}(props
.fMix
);
510 struct Eax2SourceAllValidator
{
511 void operator()(const Eax2Props
& props
) const
513 Eax2SourceDirectValidator
{}(props
.lDirect
);
514 Eax2SourceDirectHfValidator
{}(props
.lDirectHF
);
515 Eax2SourceRoomValidator
{}(props
.lRoom
);
516 Eax2SourceRoomHfValidator
{}(props
.lRoomHF
);
517 Eax2SourceRoomRolloffFactorValidator
{}(props
.flRoomRolloffFactor
);
518 Eax2SourceObstructionValidator
{}(props
.lObstruction
);
519 Eax2SourceObstructionLfRatioValidator
{}(props
.flObstructionLFRatio
);
520 Eax2SourceOcclusionValidator
{}(props
.lOcclusion
);
521 Eax2SourceOcclusionLfRatioValidator
{}(props
.flOcclusionLFRatio
);
522 Eax2SourceOcclusionRoomRatioValidator
{}(props
.flOcclusionRoomRatio
);
523 Eax2SourceOutsideVolumeHfValidator
{}(props
.lOutsideVolumeHF
);
524 Eax2SourceAirAbsorptionFactorValidator
{}(props
.flAirAbsorptionFactor
);
525 Eax2SourceFlagsValidator
{}(props
.dwFlags
);
529 struct Eax3SourceAllValidator
{
530 void operator()(const Eax3Props
& props
) const
532 Eax2SourceDirectValidator
{}(props
.lDirect
);
533 Eax2SourceDirectHfValidator
{}(props
.lDirectHF
);
534 Eax2SourceRoomValidator
{}(props
.lRoom
);
535 Eax2SourceRoomHfValidator
{}(props
.lRoomHF
);
536 Eax2SourceObstructionValidator
{}(props
.lObstruction
);
537 Eax2SourceObstructionLfRatioValidator
{}(props
.flObstructionLFRatio
);
538 Eax2SourceOcclusionValidator
{}(props
.lOcclusion
);
539 Eax2SourceOcclusionLfRatioValidator
{}(props
.flOcclusionLFRatio
);
540 Eax2SourceOcclusionRoomRatioValidator
{}(props
.flOcclusionRoomRatio
);
541 Eax3SourceOcclusionDirectRatioValidator
{}(props
.flOcclusionDirectRatio
);
542 Eax3SourceExclusionValidator
{}(props
.lExclusion
);
543 Eax3SourceExclusionLfRatioValidator
{}(props
.flExclusionLFRatio
);
544 Eax2SourceOutsideVolumeHfValidator
{}(props
.lOutsideVolumeHF
);
545 Eax3SourceDopplerFactorValidator
{}(props
.flDopplerFactor
);
546 Eax3SourceRolloffFactorValidator
{}(props
.flRolloffFactor
);
547 Eax2SourceRoomRolloffFactorValidator
{}(props
.flRoomRolloffFactor
);
548 Eax2SourceAirAbsorptionFactorValidator
{}(props
.flAirAbsorptionFactor
);
549 Eax2SourceFlagsValidator
{}(props
.ulFlags
);
553 struct Eax5SourceAllValidator
{
554 void operator()(const EAX50SOURCEPROPERTIES
& props
) const
556 Eax3SourceAllValidator
{}(static_cast<const Eax3Props
&>(props
));
557 Eax5SourceMacroFXFactorValidator
{}(props
.flMacroFXFactor
);
561 struct Eax5SourceAll2dValidator
{
562 void operator()(const EAXSOURCE2DPROPERTIES
& props
) const
564 Eax2SourceDirectValidator
{}(props
.lDirect
);
565 Eax2SourceDirectHfValidator
{}(props
.lDirectHF
);
566 Eax2SourceRoomValidator
{}(props
.lRoom
);
567 Eax2SourceRoomHfValidator
{}(props
.lRoomHF
);
568 Eax5SourceFlagsValidator
{}(props
.ulFlags
);
572 struct Eax4ObstructionValidator
{
573 void operator()(const EAXOBSTRUCTIONPROPERTIES
& props
) const
575 Eax2SourceObstructionValidator
{}(props
.lObstruction
);
576 Eax2SourceObstructionLfRatioValidator
{}(props
.flObstructionLFRatio
);
580 struct Eax4OcclusionValidator
{
581 void operator()(const EAXOCCLUSIONPROPERTIES
& props
) const
583 Eax2SourceOcclusionValidator
{}(props
.lOcclusion
);
584 Eax2SourceOcclusionLfRatioValidator
{}(props
.flOcclusionLFRatio
);
585 Eax2SourceOcclusionRoomRatioValidator
{}(props
.flOcclusionRoomRatio
);
586 Eax3SourceOcclusionDirectRatioValidator
{}(props
.flOcclusionDirectRatio
);
590 struct Eax4ExclusionValidator
{
591 void operator()(const EAXEXCLUSIONPROPERTIES
& props
) const
593 Eax3SourceExclusionValidator
{}(props
.lExclusion
);
594 Eax3SourceExclusionLfRatioValidator
{}(props
.flExclusionLFRatio
);
599 // ----------------------------------------------------------------------
602 struct Eax4SendReceivingFxSlotIdValidator
{
603 void operator()(const GUID
& guidReceivingFXSlotID
) const
605 if (guidReceivingFXSlotID
!= EAXPROPERTYID_EAX40_FXSlot0
&&
606 guidReceivingFXSlotID
!= EAXPROPERTYID_EAX40_FXSlot1
&&
607 guidReceivingFXSlotID
!= EAXPROPERTYID_EAX40_FXSlot2
&&
608 guidReceivingFXSlotID
!= EAXPROPERTYID_EAX40_FXSlot3
)
610 eax_fail_unknown_receiving_fx_slot_id();
615 struct Eax5SendReceivingFxSlotIdValidator
{
616 void operator()(const GUID
& guidReceivingFXSlotID
) const
618 if (guidReceivingFXSlotID
!= EAXPROPERTYID_EAX50_FXSlot0
&&
619 guidReceivingFXSlotID
!= EAXPROPERTYID_EAX50_FXSlot1
&&
620 guidReceivingFXSlotID
!= EAXPROPERTYID_EAX50_FXSlot2
&&
621 guidReceivingFXSlotID
!= EAXPROPERTYID_EAX50_FXSlot3
)
623 eax_fail_unknown_receiving_fx_slot_id();
628 struct Eax4SendSendValidator
{
629 void operator()(long lSend
) const
631 eax_validate_range
<Exception
>(
639 struct Eax4SendSendHfValidator
{
640 void operator()(long lSendHF
) const
642 eax_validate_range
<Exception
>(
646 EAXSOURCE_MAXSENDHF
);
650 template<typename TIdValidator
>
651 struct EaxSendValidator
{
652 void operator()(const EAXSOURCESENDPROPERTIES
& props
) const
654 TIdValidator
{}(props
.guidReceivingFXSlotID
);
655 Eax4SendSendValidator
{}(props
.lSend
);
656 Eax4SendSendHfValidator
{}(props
.lSendHF
);
660 struct Eax4SendValidator
: EaxSendValidator
<Eax4SendReceivingFxSlotIdValidator
> {};
661 struct Eax5SendValidator
: EaxSendValidator
<Eax5SendReceivingFxSlotIdValidator
> {};
663 template<typename TIdValidator
>
664 struct EaxOcclusionSendValidator
{
665 void operator()(const EAXSOURCEOCCLUSIONSENDPROPERTIES
& props
) const
667 TIdValidator
{}(props
.guidReceivingFXSlotID
);
668 Eax2SourceOcclusionValidator
{}(props
.lOcclusion
);
669 Eax2SourceOcclusionLfRatioValidator
{}(props
.flOcclusionLFRatio
);
670 Eax2SourceOcclusionRoomRatioValidator
{}(props
.flOcclusionRoomRatio
);
671 Eax3SourceOcclusionDirectRatioValidator
{}(props
.flOcclusionDirectRatio
);
675 struct Eax4OcclusionSendValidator
: EaxOcclusionSendValidator
<Eax4SendReceivingFxSlotIdValidator
> {};
676 struct Eax5OcclusionSendValidator
: EaxOcclusionSendValidator
<Eax5SendReceivingFxSlotIdValidator
> {};
678 template<typename TIdValidator
>
679 struct EaxExclusionSendValidator
{
680 void operator()(const EAXSOURCEEXCLUSIONSENDPROPERTIES
& props
) const
682 TIdValidator
{}(props
.guidReceivingFXSlotID
);
683 Eax3SourceExclusionValidator
{}(props
.lExclusion
);
684 Eax3SourceExclusionLfRatioValidator
{}(props
.flExclusionLFRatio
);
688 struct Eax4ExclusionSendValidator
: EaxExclusionSendValidator
<Eax4SendReceivingFxSlotIdValidator
> {};
689 struct Eax5ExclusionSendValidator
: EaxExclusionSendValidator
<Eax5SendReceivingFxSlotIdValidator
> {};
691 template<typename TIdValidator
>
692 struct EaxAllSendValidator
{
693 void operator()(const EAXSOURCEALLSENDPROPERTIES
& props
) const
695 TIdValidator
{}(props
.guidReceivingFXSlotID
);
696 Eax4SendSendValidator
{}(props
.lSend
);
697 Eax4SendSendHfValidator
{}(props
.lSendHF
);
698 Eax2SourceOcclusionValidator
{}(props
.lOcclusion
);
699 Eax2SourceOcclusionLfRatioValidator
{}(props
.flOcclusionLFRatio
);
700 Eax2SourceOcclusionRoomRatioValidator
{}(props
.flOcclusionRoomRatio
);
701 Eax3SourceOcclusionDirectRatioValidator
{}(props
.flOcclusionDirectRatio
);
702 Eax3SourceExclusionValidator
{}(props
.lExclusion
);
703 Eax3SourceExclusionLfRatioValidator
{}(props
.flExclusionLFRatio
);
707 struct Eax4AllSendValidator
: EaxAllSendValidator
<Eax4SendReceivingFxSlotIdValidator
> {};
708 struct Eax5AllSendValidator
: EaxAllSendValidator
<Eax5SendReceivingFxSlotIdValidator
> {};
711 // ----------------------------------------------------------------------
712 // Active FX slot ID validators
714 struct Eax4ActiveFxSlotIdValidator
{
715 void operator()(const GUID
&guid
) const
717 if(guid
!= EAX_NULL_GUID
&& guid
!= EAX_PrimaryFXSlotID
718 && guid
!= EAXPROPERTYID_EAX40_FXSlot0
&& guid
!= EAXPROPERTYID_EAX40_FXSlot1
719 && guid
!= EAXPROPERTYID_EAX40_FXSlot2
&& guid
!= EAXPROPERTYID_EAX40_FXSlot3
)
721 eax_fail_unknown_active_fx_slot_id();
726 struct Eax5ActiveFxSlotIdValidator
{
727 void operator()(const GUID
&guid
) const
729 if(guid
!= EAX_NULL_GUID
&& guid
!= EAX_PrimaryFXSlotID
730 && guid
!= EAXPROPERTYID_EAX50_FXSlot0
&& guid
!= EAXPROPERTYID_EAX50_FXSlot1
731 && guid
!= EAXPROPERTYID_EAX50_FXSlot2
&& guid
!= EAXPROPERTYID_EAX50_FXSlot3
)
733 eax_fail_unknown_active_fx_slot_id();
738 // Active FX slot ID validators
739 // ----------------------------------------------------------------------
740 // Speaker level validators.
742 struct Eax5SpeakerIdValidator
{
743 void operator()(long lSpeakerID
) const
745 switch (lSpeakerID
) {
746 case EAXSPEAKER_FRONT_LEFT
:
747 case EAXSPEAKER_FRONT_CENTER
:
748 case EAXSPEAKER_FRONT_RIGHT
:
749 case EAXSPEAKER_SIDE_RIGHT
:
750 case EAXSPEAKER_REAR_RIGHT
:
751 case EAXSPEAKER_REAR_CENTER
:
752 case EAXSPEAKER_REAR_LEFT
:
753 case EAXSPEAKER_SIDE_LEFT
:
754 case EAXSPEAKER_LOW_FREQUENCY
:
758 eax_fail("Unknown speaker ID.");
763 struct Eax5SpeakerLevelValidator
{
764 void operator()(long lLevel
) const
766 // TODO Use a range when the feature will be implemented.
767 if (lLevel
!= EAXSOURCE_DEFAULTSPEAKERLEVEL
)
768 eax_fail("Speaker level out of range.");
772 struct Eax5SpeakerAllValidator
{
773 void operator()(const EAXSPEAKERLEVELPROPERTIES
& all
) const
775 Eax5SpeakerIdValidator
{}(all
.lSpeakerID
);
776 Eax5SpeakerLevelValidator
{}(all
.lLevel
);
780 // Speaker level validators.
781 // ----------------------------------------------------------------------
783 struct Eax4SendIndexGetter
{
784 EaxFxSlotIndexValue
operator()(const GUID
&guid
) const
786 if(guid
== EAXPROPERTYID_EAX40_FXSlot0
)
788 if(guid
== EAXPROPERTYID_EAX40_FXSlot1
)
790 if(guid
== EAXPROPERTYID_EAX40_FXSlot2
)
792 if(guid
== EAXPROPERTYID_EAX40_FXSlot3
)
794 eax_fail_unknown_receiving_fx_slot_id();
798 struct Eax5SendIndexGetter
{
799 EaxFxSlotIndexValue
operator()(const GUID
&guid
) const
801 if(guid
== EAXPROPERTYID_EAX50_FXSlot0
)
803 if(guid
== EAXPROPERTYID_EAX50_FXSlot1
)
805 if(guid
== EAXPROPERTYID_EAX50_FXSlot2
)
807 if(guid
== EAXPROPERTYID_EAX50_FXSlot3
)
809 eax_fail_unknown_receiving_fx_slot_id();
813 [[noreturn
]] static void eax_fail(const char* message
);
814 [[noreturn
]] static void eax_fail_unknown_property_id();
815 [[noreturn
]] static void eax_fail_unknown_version();
816 [[noreturn
]] static void eax_fail_unknown_active_fx_slot_id();
817 [[noreturn
]] static void eax_fail_unknown_receiving_fx_slot_id();
819 void eax_set_sends_defaults(EaxSends
& sends
, const EaxFxSlotIds
& ids
) noexcept
;
820 void eax1_set_defaults(Eax1Props
& props
) noexcept
;
821 void eax1_set_defaults() noexcept
;
822 void eax2_set_defaults(Eax2Props
& props
) noexcept
;
823 void eax2_set_defaults() noexcept
;
824 void eax3_set_defaults(Eax3Props
& props
) noexcept
;
825 void eax3_set_defaults() noexcept
;
826 void eax4_set_sends_defaults(EaxSends
& sends
) noexcept
;
827 void eax4_set_active_fx_slots_defaults(EAX40ACTIVEFXSLOTS
& slots
) noexcept
;
828 void eax4_set_defaults() noexcept
;
829 void eax5_set_source_defaults(EAX50SOURCEPROPERTIES
& props
) noexcept
;
830 void eax5_set_sends_defaults(EaxSends
& sends
) noexcept
;
831 void eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS
& slots
) noexcept
;
832 void eax5_set_speaker_levels_defaults(EaxSpeakerLevels
& speaker_levels
) noexcept
;
833 void eax5_set_defaults(Eax5Props
& props
) noexcept
;
834 void eax5_set_defaults() noexcept
;
835 void eax_set_defaults() noexcept
;
837 void eax1_translate(const Eax1Props
& src
, Eax5Props
& dst
) noexcept
;
838 void eax2_translate(const Eax2Props
& src
, Eax5Props
& dst
) noexcept
;
839 void eax3_translate(const Eax3Props
& src
, Eax5Props
& dst
) noexcept
;
840 void eax4_translate(const Eax4Props
& src
, Eax5Props
& dst
) noexcept
;
842 static float eax_calculate_dst_occlusion_mb(
843 long src_occlusion_mb
,
845 float lf_ratio
) noexcept
;
847 EaxAlLowPassParam
eax_create_direct_filter_param() const noexcept
;
849 EaxAlLowPassParam
eax_create_room_filter_param(
850 const ALeffectslot
& fx_slot
,
851 const EAXSOURCEALLSENDPROPERTIES
& send
) const noexcept
;
853 void eax_update_direct_filter();
854 void eax_update_room_filters();
855 void eax_commit_filters();
857 static void eax_copy_send_for_get(
858 const EAXSOURCEALLSENDPROPERTIES
& src
,
859 EAXSOURCESENDPROPERTIES
& dst
) noexcept
861 dst
= reinterpret_cast<const EAXSOURCESENDPROPERTIES
&>(src
);
864 static void eax_copy_send_for_get(
865 const EAXSOURCEALLSENDPROPERTIES
& src
,
866 EAXSOURCEALLSENDPROPERTIES
& dst
) noexcept
871 static void eax_copy_send_for_get(
872 const EAXSOURCEALLSENDPROPERTIES
& src
,
873 EAXSOURCEOCCLUSIONSENDPROPERTIES
& dst
) noexcept
875 dst
.guidReceivingFXSlotID
= src
.guidReceivingFXSlotID
;
876 dst
.lOcclusion
= src
.lOcclusion
;
877 dst
.flOcclusionLFRatio
= src
.flOcclusionLFRatio
;
878 dst
.flOcclusionRoomRatio
= src
.flOcclusionRoomRatio
;
879 dst
.flOcclusionDirectRatio
= src
.flOcclusionDirectRatio
;
882 static void eax_copy_send_for_get(
883 const EAXSOURCEALLSENDPROPERTIES
& src
,
884 EAXSOURCEEXCLUSIONSENDPROPERTIES
& dst
) noexcept
886 dst
.guidReceivingFXSlotID
= src
.guidReceivingFXSlotID
;
887 dst
.lExclusion
= src
.lExclusion
;
888 dst
.flExclusionLFRatio
= src
.flExclusionLFRatio
;
891 template<typename TDstSend
>
892 void eax_get_sends(const EaxCall
& call
, const EaxSends
& src_sends
)
894 const auto dst_sends
= call
.get_values
<TDstSend
>(EAX_MAX_FXSLOTS
);
895 const auto count
= dst_sends
.size();
897 for (auto i
= decltype(count
){}; i
< count
; ++i
) {
898 const auto& src_send
= src_sends
[i
];
899 auto& dst_send
= dst_sends
[i
];
900 eax_copy_send_for_get(src_send
, dst_send
);
904 void eax1_get(const EaxCall
& call
, const Eax1Props
& props
);
905 void eax2_get(const EaxCall
& call
, const Eax2Props
& props
);
906 void eax3_get_obstruction(const EaxCall
& call
, const Eax3Props
& props
);
907 void eax3_get_occlusion(const EaxCall
& call
, const Eax3Props
& props
);
908 void eax3_get_exclusion(const EaxCall
& call
, const Eax3Props
& props
);
909 void eax3_get(const EaxCall
& call
, const Eax3Props
& props
);
910 void eax4_get(const EaxCall
& call
, const Eax4Props
& props
);
911 void eax5_get_all_2d(const EaxCall
& call
, const EAX50SOURCEPROPERTIES
& props
);
912 void eax5_get_speaker_levels(const EaxCall
& call
, const EaxSpeakerLevels
& props
);
913 void eax5_get(const EaxCall
& call
, const Eax5Props
& props
);
914 void eax_get(const EaxCall
& call
);
916 static void eax_copy_send_for_set(
917 const EAXSOURCESENDPROPERTIES
& src
,
918 EAXSOURCEALLSENDPROPERTIES
& dst
) noexcept
920 dst
.lSend
= src
.lSend
;
921 dst
.lSendHF
= src
.lSendHF
;
924 static void eax_copy_send_for_set(
925 const EAXSOURCEALLSENDPROPERTIES
& src
,
926 EAXSOURCEALLSENDPROPERTIES
& dst
) noexcept
928 dst
.lSend
= src
.lSend
;
929 dst
.lSendHF
= src
.lSendHF
;
930 dst
.lOcclusion
= src
.lOcclusion
;
931 dst
.flOcclusionLFRatio
= src
.flOcclusionLFRatio
;
932 dst
.flOcclusionRoomRatio
= src
.flOcclusionRoomRatio
;
933 dst
.flOcclusionDirectRatio
= src
.flOcclusionDirectRatio
;
934 dst
.lExclusion
= src
.lExclusion
;
935 dst
.flExclusionLFRatio
= src
.flExclusionLFRatio
;
938 static void eax_copy_send_for_set(
939 const EAXSOURCEOCCLUSIONSENDPROPERTIES
& src
,
940 EAXSOURCEALLSENDPROPERTIES
& dst
) noexcept
942 dst
.lOcclusion
= src
.lOcclusion
;
943 dst
.flOcclusionLFRatio
= src
.flOcclusionLFRatio
;
944 dst
.flOcclusionRoomRatio
= src
.flOcclusionRoomRatio
;
945 dst
.flOcclusionDirectRatio
= src
.flOcclusionDirectRatio
;
948 static void eax_copy_send_for_set(
949 const EAXSOURCEEXCLUSIONSENDPROPERTIES
& src
,
950 EAXSOURCEALLSENDPROPERTIES
& dst
) noexcept
952 dst
.lExclusion
= src
.lExclusion
;
953 dst
.flExclusionLFRatio
= src
.flExclusionLFRatio
;
956 template<typename TValidator
, typename TIndexGetter
, typename TSrcSend
>
957 void eax_defer_sends(const EaxCall
& call
, EaxSends
& dst_sends
)
959 const auto src_sends
= call
.get_values
<const TSrcSend
>(EAX_MAX_FXSLOTS
);
960 std::for_each(src_sends
.cbegin(), src_sends
.cend(), TValidator
{});
961 const auto count
= src_sends
.size();
962 const auto index_getter
= TIndexGetter
{};
964 for (auto i
= decltype(count
){}; i
< count
; ++i
) {
965 const auto& src_send
= src_sends
[i
];
966 const auto dst_index
= index_getter(src_send
.guidReceivingFXSlotID
);
967 auto& dst_send
= dst_sends
[dst_index
];
968 eax_copy_send_for_set(src_send
, dst_send
);
972 template<typename TValidator
, typename TSrcSend
>
973 void eax4_defer_sends(const EaxCall
& call
, EaxSends
& dst_sends
)
975 eax_defer_sends
<TValidator
, Eax4SendIndexGetter
, TSrcSend
>(call
, dst_sends
);
978 template<typename TValidator
, typename TSrcSend
>
979 void eax5_defer_sends(const EaxCall
& call
, EaxSends
& dst_sends
)
981 eax_defer_sends
<TValidator
, Eax5SendIndexGetter
, TSrcSend
>(call
, dst_sends
);
984 template<typename TValidator
, size_t TIdCount
>
985 void eax_defer_active_fx_slot_id(const EaxCall
& call
, GUID (&dst_ids
)[TIdCount
])
987 const auto src_ids
= call
.get_values
<const GUID
>(TIdCount
);
988 std::for_each(src_ids
.cbegin(), src_ids
.cend(), TValidator
{});
989 std::uninitialized_copy(src_ids
.cbegin(), src_ids
.cend(), dst_ids
);
992 template<size_t TIdCount
>
993 void eax4_defer_active_fx_slot_id(const EaxCall
& call
, GUID (&dst_ids
)[TIdCount
])
995 eax_defer_active_fx_slot_id
<Eax4ActiveFxSlotIdValidator
>(call
, dst_ids
);
998 template<size_t TIdCount
>
999 void eax5_defer_active_fx_slot_id(const EaxCall
& call
, GUID (&dst_ids
)[TIdCount
])
1001 eax_defer_active_fx_slot_id
<Eax5ActiveFxSlotIdValidator
>(call
, dst_ids
);
1004 template<typename TValidator
, typename TProperty
>
1005 static void eax_defer(const EaxCall
& call
, TProperty
& property
)
1007 const auto& value
= call
.get_value
<Exception
, const TProperty
>();
1008 TValidator
{}(value
);
1012 // Defers source's sub-properties (obstruction, occlusion, exclusion).
1013 template<typename TValidator
, typename TSubproperty
, typename TProperty
>
1014 void eax_defer_sub(const EaxCall
& call
, TProperty
& property
)
1016 const auto& src_props
= call
.get_value
<Exception
, const TSubproperty
>();
1017 TValidator
{}(src_props
);
1018 auto& dst_props
= reinterpret_cast<TSubproperty
&>(property
);
1019 dst_props
= src_props
;
1022 void eax_set_efx_outer_gain_hf();
1023 void eax_set_efx_doppler_factor();
1024 void eax_set_efx_rolloff_factor();
1025 void eax_set_efx_room_rolloff_factor();
1026 void eax_set_efx_air_absorption_factor();
1027 void eax_set_efx_dry_gain_hf_auto();
1028 void eax_set_efx_wet_gain_auto();
1029 void eax_set_efx_wet_gain_hf_auto();
1031 void eax1_set(const EaxCall
& call
, Eax1Props
& props
);
1032 void eax2_set(const EaxCall
& call
, Eax2Props
& props
);
1033 void eax3_set(const EaxCall
& call
, Eax3Props
& props
);
1034 void eax4_set(const EaxCall
& call
, Eax4Props
& props
);
1035 void eax5_defer_all_2d(const EaxCall
& call
, EAX50SOURCEPROPERTIES
& props
);
1036 void eax5_defer_speaker_levels(const EaxCall
& call
, EaxSpeakerLevels
& props
);
1037 void eax5_set(const EaxCall
& call
, Eax5Props
& props
);
1038 void eax_set(const EaxCall
& call
);
1040 // `alSource3i(source, AL_AUXILIARY_SEND_FILTER, ...)`
1041 void eax_set_al_source_send(ALeffectslot
*slot
, size_t sendidx
,
1042 const EaxAlLowPassParam
&filter
);
1044 void eax_commit_active_fx_slots();
1045 void eax_commit(EaxCommitType commit_type
);
1046 #endif // ALSOFT_EAX
1049 void UpdateAllSourceProps(ALCcontext
*context
);