Remove a couple unnecessary casts
[openal-soft.git] / al / source.h
bloba68a0eab75f82b53b7d800f0fede782d7f69a8dd
1 #ifndef AL_SOURCE_H
2 #define AL_SOURCE_H
4 #include <array>
5 #include <cstddef>
6 #include <cstdint>
7 #include <deque>
8 #include <limits>
9 #include <string_view>
10 #include <utility>
12 #include "AL/al.h"
13 #include "AL/alc.h"
14 #include "AL/alext.h"
16 #include "almalloc.h"
17 #include "alnumbers.h"
18 #include "alnumeric.h"
19 #include "alspan.h"
20 #include "core/context.h"
21 #include "core/voice.h"
23 #ifdef ALSOFT_EAX
24 #include "eax/api.h"
25 #include "eax/call.h"
26 #include "eax/exception.h"
27 #include "eax/fx_slot_index.h"
28 #include "eax/utils.h"
29 #endif // ALSOFT_EAX
31 struct ALbuffer;
32 struct ALeffectslot;
33 enum class Resampler : uint8_t;
35 enum class SourceStereo : bool {
36 Normal = AL_NORMAL_SOFT,
37 Enhanced = AL_SUPER_STEREO_SOFT
40 inline constexpr size_t DefaultSendCount{2};
42 inline constexpr ALuint InvalidVoiceIndex{std::numeric_limits<ALuint>::max()};
44 inline bool sBufferSubDataCompat{false};
46 struct ALbufferQueueItem : public VoiceBufferItem {
47 ALbuffer *mBuffer{nullptr};
51 #ifdef ALSOFT_EAX
52 class EaxSourceException : public EaxException {
53 public:
54 explicit EaxSourceException(const char* message)
55 : EaxException{"EAX_SOURCE", message}
58 #endif // ALSOFT_EAX
60 struct ALsource {
61 /** Source properties. */
62 float Pitch{1.0f};
63 float Gain{1.0f};
64 float OuterGain{0.0f};
65 float MinGain{0.0f};
66 float MaxGain{1.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};
72 #ifdef ALSOFT_EAX
73 // For EAXSOURCE_ROLLOFFFACTOR, which is distinct from and added to
74 // AL_ROLLOFF_FACTOR
75 float RolloffFactor2{0.0f};
76 #endif
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};
83 bool Looping{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};
89 bool mPanningEnabled{false};
91 bool DryGainHFAuto{true};
92 bool WetGainAuto{true};
93 bool WetGainHFAuto{true};
94 float OuterGainHF{1.0f};
96 float AirAbsorptionFactor{0.0f};
97 float RoomRolloffFactor{0.0f};
98 float DopplerFactor{1.0f};
100 /* NOTE: Stereo pan angles are specified in radians, counter-clockwise
101 * rather than clockwise.
103 std::array<float,2> StereoPan{{al::numbers::pi_v<float>/6.0f, -al::numbers::pi_v<float>/6.0f}};
105 float Radius{0.0f};
106 float EnhWidth{0.593f};
107 float mPan{0.0f};
109 /** Direct filter and auxiliary send info. */
110 struct DirectData {
111 float Gain{};
112 float GainHF{};
113 float HFReference{};
114 float GainLF{};
115 float LFReference{};
117 DirectData Direct;
119 struct SendData {
120 ALeffectslot *Slot{};
121 float Gain{};
122 float GainHF{};
123 float HFReference{};
124 float GainLF{};
125 float LFReference{};
127 std::array<SendData,MaxSendCount> Send;
130 * Last user-specified offset, and the offset type (bytes, samples, or
131 * seconds).
133 double Offset{0.0};
134 ALenum OffsetType{AL_NONE};
136 /** Source type (static, streaming, or undetermined) */
137 ALenum SourceType{AL_UNDETERMINED};
139 /** Source state (initial, playing, paused, or stopped) */
140 ALenum state{AL_INITIAL};
142 /** Source Buffer Queue head. */
143 std::deque<ALbufferQueueItem> mQueue;
145 bool mPropsDirty{true};
147 /* Index into the context's Voices array. Lazily updated, only checked and
148 * reset when looking up the voice.
150 ALuint VoiceIdx{InvalidVoiceIndex};
152 /** Self ID */
153 ALuint id{0};
156 ALsource() noexcept;
157 ~ALsource();
159 ALsource(const ALsource&) = delete;
160 ALsource& operator=(const ALsource&) = delete;
162 static void SetName(ALCcontext *context, ALuint id, std::string_view name);
164 DISABLE_ALLOC
166 #ifdef ALSOFT_EAX
167 public:
168 void eaxInitialize(ALCcontext *context) noexcept;
169 void eaxDispatch(const EaxCall& call);
170 void eaxCommit();
171 void eaxMarkAsChanged() noexcept { mEaxChanged = true; }
173 static ALsource* EaxLookupSource(ALCcontext& al_context, ALuint source_id) noexcept;
175 private:
176 using Exception = EaxSourceException;
178 static constexpr auto eax_max_speakers{9u};
180 using EaxFxSlotIds = std::array<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;
201 struct Eax1State {
202 Eax1Props i; // Immediate.
203 Eax1Props d; // Deferred.
206 using Eax2Props = EAX20BUFFERPROPERTIES;
207 struct Eax2State {
208 Eax2Props i; // Immediate.
209 Eax2Props d; // Deferred.
212 using Eax3Props = EAX30SOURCEPROPERTIES;
213 struct Eax3State {
214 Eax3Props i; // Immediate.
215 Eax3Props d; // Deferred.
218 struct Eax4Props {
219 Eax3Props source;
220 EaxSends sends;
221 EAX40ACTIVEFXSLOTS active_fx_slots;
224 struct Eax4State {
225 Eax4Props i; // Immediate.
226 Eax4Props d; // Deferred.
229 struct Eax5Props {
230 EAX50SOURCEPROPERTIES source;
231 EaxSends sends;
232 EAX50ACTIVEFXSLOTS active_fx_slots;
233 EaxSpeakerLevels speaker_levels;
236 struct Eax5State {
237 Eax5Props i; // Immediate.
238 Eax5Props d; // Deferred.
241 ALCcontext* mEaxAlContext{};
242 EaxFxSlotIndex mEaxPrimaryFxSlotId{};
243 EaxActiveFxSlots mEaxActiveFxSlots{};
244 int mEaxVersion{};
245 bool mEaxChanged{};
246 Eax1State mEax1{};
247 Eax2State mEax2{};
248 Eax3State mEax3{};
249 Eax4State mEax4{};
250 Eax5State mEax5{};
251 Eax5Props mEax{};
253 // ----------------------------------------------------------------------
254 // Source validators
256 struct Eax1SourceReverbMixValidator {
257 void operator()(float reverb_mix) const
259 if (reverb_mix == EAX_REVERBMIX_USEDISTANCE)
260 return;
262 eax_validate_range<Exception>(
263 "Reverb Mix",
264 reverb_mix,
265 EAX_BUFFER_MINREVERBMIX,
266 EAX_BUFFER_MAXREVERBMIX);
270 struct Eax2SourceDirectValidator {
271 void operator()(long lDirect) const
273 eax_validate_range<Exception>(
274 "Direct",
275 lDirect,
276 EAXSOURCE_MINDIRECT,
277 EAXSOURCE_MAXDIRECT);
281 struct Eax2SourceDirectHfValidator {
282 void operator()(long lDirectHF) const
284 eax_validate_range<Exception>(
285 "Direct HF",
286 lDirectHF,
287 EAXSOURCE_MINDIRECTHF,
288 EAXSOURCE_MAXDIRECTHF);
292 struct Eax2SourceRoomValidator {
293 void operator()(long lRoom) const
295 eax_validate_range<Exception>(
296 "Room",
297 lRoom,
298 EAXSOURCE_MINROOM,
299 EAXSOURCE_MAXROOM);
303 struct Eax2SourceRoomHfValidator {
304 void operator()(long lRoomHF) const
306 eax_validate_range<Exception>(
307 "Room HF",
308 lRoomHF,
309 EAXSOURCE_MINROOMHF,
310 EAXSOURCE_MAXROOMHF);
314 struct Eax2SourceRoomRolloffFactorValidator {
315 void operator()(float flRoomRolloffFactor) const
317 eax_validate_range<Exception>(
318 "Room Rolloff Factor",
319 flRoomRolloffFactor,
320 EAXSOURCE_MINROOMROLLOFFFACTOR,
321 EAXSOURCE_MAXROOMROLLOFFFACTOR);
325 struct Eax2SourceObstructionValidator {
326 void operator()(long lObstruction) const
328 eax_validate_range<Exception>(
329 "Obstruction",
330 lObstruction,
331 EAXSOURCE_MINOBSTRUCTION,
332 EAXSOURCE_MAXOBSTRUCTION);
336 struct Eax2SourceObstructionLfRatioValidator {
337 void operator()(float flObstructionLFRatio) const
339 eax_validate_range<Exception>(
340 "Obstruction LF Ratio",
341 flObstructionLFRatio,
342 EAXSOURCE_MINOBSTRUCTIONLFRATIO,
343 EAXSOURCE_MAXOBSTRUCTIONLFRATIO);
347 struct Eax2SourceOcclusionValidator {
348 void operator()(long lOcclusion) const
350 eax_validate_range<Exception>(
351 "Occlusion",
352 lOcclusion,
353 EAXSOURCE_MINOCCLUSION,
354 EAXSOURCE_MAXOCCLUSION);
358 struct Eax2SourceOcclusionLfRatioValidator {
359 void operator()(float flOcclusionLFRatio) const
361 eax_validate_range<Exception>(
362 "Occlusion LF Ratio",
363 flOcclusionLFRatio,
364 EAXSOURCE_MINOCCLUSIONLFRATIO,
365 EAXSOURCE_MAXOCCLUSIONLFRATIO);
369 struct Eax2SourceOcclusionRoomRatioValidator {
370 void operator()(float flOcclusionRoomRatio) const
372 eax_validate_range<Exception>(
373 "Occlusion Room Ratio",
374 flOcclusionRoomRatio,
375 EAXSOURCE_MINOCCLUSIONROOMRATIO,
376 EAXSOURCE_MAXOCCLUSIONROOMRATIO);
380 struct Eax2SourceOutsideVolumeHfValidator {
381 void operator()(long lOutsideVolumeHF) const
383 eax_validate_range<Exception>(
384 "Outside Volume HF",
385 lOutsideVolumeHF,
386 EAXSOURCE_MINOUTSIDEVOLUMEHF,
387 EAXSOURCE_MAXOUTSIDEVOLUMEHF);
391 struct Eax2SourceAirAbsorptionFactorValidator {
392 void operator()(float flAirAbsorptionFactor) const
394 eax_validate_range<Exception>(
395 "Air Absorption Factor",
396 flAirAbsorptionFactor,
397 EAXSOURCE_MINAIRABSORPTIONFACTOR,
398 EAXSOURCE_MAXAIRABSORPTIONFACTOR);
402 struct Eax2SourceFlagsValidator {
403 void operator()(unsigned long dwFlags) const
405 eax_validate_range<Exception>(
406 "Flags",
407 dwFlags,
408 0UL,
409 ~EAX20SOURCEFLAGS_RESERVED);
413 struct Eax3SourceOcclusionDirectRatioValidator {
414 void operator()(float flOcclusionDirectRatio) const
416 eax_validate_range<Exception>(
417 "Occlusion Direct Ratio",
418 flOcclusionDirectRatio,
419 EAXSOURCE_MINOCCLUSIONDIRECTRATIO,
420 EAXSOURCE_MAXOCCLUSIONDIRECTRATIO);
424 struct Eax3SourceExclusionValidator {
425 void operator()(long lExclusion) const
427 eax_validate_range<Exception>(
428 "Exclusion",
429 lExclusion,
430 EAXSOURCE_MINEXCLUSION,
431 EAXSOURCE_MAXEXCLUSION);
435 struct Eax3SourceExclusionLfRatioValidator {
436 void operator()(float flExclusionLFRatio) const
438 eax_validate_range<Exception>(
439 "Exclusion LF Ratio",
440 flExclusionLFRatio,
441 EAXSOURCE_MINEXCLUSIONLFRATIO,
442 EAXSOURCE_MAXEXCLUSIONLFRATIO);
446 struct Eax3SourceDopplerFactorValidator {
447 void operator()(float flDopplerFactor) const
449 eax_validate_range<Exception>(
450 "Doppler Factor",
451 flDopplerFactor,
452 EAXSOURCE_MINDOPPLERFACTOR,
453 EAXSOURCE_MAXDOPPLERFACTOR);
457 struct Eax3SourceRolloffFactorValidator {
458 void operator()(float flRolloffFactor) const
460 eax_validate_range<Exception>(
461 "Rolloff Factor",
462 flRolloffFactor,
463 EAXSOURCE_MINROLLOFFFACTOR,
464 EAXSOURCE_MAXROLLOFFFACTOR);
468 struct Eax5SourceMacroFXFactorValidator {
469 void operator()(float flMacroFXFactor) const
471 eax_validate_range<Exception>(
472 "Macro FX Factor",
473 flMacroFXFactor,
474 EAXSOURCE_MINMACROFXFACTOR,
475 EAXSOURCE_MAXMACROFXFACTOR);
479 struct Eax5SourceFlagsValidator {
480 void operator()(unsigned long dwFlags) const
482 eax_validate_range<Exception>(
483 "Flags",
484 dwFlags,
485 0UL,
486 ~EAX50SOURCEFLAGS_RESERVED);
490 struct Eax1SourceAllValidator {
491 void operator()(const Eax1Props& props) const
493 Eax1SourceReverbMixValidator{}(props.fMix);
497 struct Eax2SourceAllValidator {
498 void operator()(const Eax2Props& props) const
500 Eax2SourceDirectValidator{}(props.lDirect);
501 Eax2SourceDirectHfValidator{}(props.lDirectHF);
502 Eax2SourceRoomValidator{}(props.lRoom);
503 Eax2SourceRoomHfValidator{}(props.lRoomHF);
504 Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
505 Eax2SourceObstructionValidator{}(props.lObstruction);
506 Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
507 Eax2SourceOcclusionValidator{}(props.lOcclusion);
508 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
509 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
510 Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
511 Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
512 Eax2SourceFlagsValidator{}(props.dwFlags);
516 struct Eax3SourceAllValidator {
517 void operator()(const Eax3Props& props) const
519 Eax2SourceDirectValidator{}(props.lDirect);
520 Eax2SourceDirectHfValidator{}(props.lDirectHF);
521 Eax2SourceRoomValidator{}(props.lRoom);
522 Eax2SourceRoomHfValidator{}(props.lRoomHF);
523 Eax2SourceObstructionValidator{}(props.lObstruction);
524 Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
525 Eax2SourceOcclusionValidator{}(props.lOcclusion);
526 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
527 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
528 Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
529 Eax3SourceExclusionValidator{}(props.lExclusion);
530 Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
531 Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
532 Eax3SourceDopplerFactorValidator{}(props.flDopplerFactor);
533 Eax3SourceRolloffFactorValidator{}(props.flRolloffFactor);
534 Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
535 Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
536 Eax2SourceFlagsValidator{}(props.ulFlags);
540 struct Eax5SourceAllValidator {
541 void operator()(const EAX50SOURCEPROPERTIES& props) const
543 Eax2SourceDirectValidator{}(props.lDirect);
544 Eax2SourceDirectHfValidator{}(props.lDirectHF);
545 Eax2SourceRoomValidator{}(props.lRoom);
546 Eax2SourceRoomHfValidator{}(props.lRoomHF);
547 Eax2SourceObstructionValidator{}(props.lObstruction);
548 Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
549 Eax2SourceOcclusionValidator{}(props.lOcclusion);
550 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
551 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
552 Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
553 Eax3SourceExclusionValidator{}(props.lExclusion);
554 Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
555 Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
556 Eax3SourceDopplerFactorValidator{}(props.flDopplerFactor);
557 Eax3SourceRolloffFactorValidator{}(props.flRolloffFactor);
558 Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
559 Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
560 Eax5SourceFlagsValidator{}(props.ulFlags);
561 Eax5SourceMacroFXFactorValidator{}(props.flMacroFXFactor);
565 struct Eax5SourceAll2dValidator {
566 void operator()(const EAXSOURCE2DPROPERTIES& props) const
568 Eax2SourceDirectValidator{}(props.lDirect);
569 Eax2SourceDirectHfValidator{}(props.lDirectHF);
570 Eax2SourceRoomValidator{}(props.lRoom);
571 Eax2SourceRoomHfValidator{}(props.lRoomHF);
572 Eax5SourceFlagsValidator{}(props.ulFlags);
576 struct Eax4ObstructionValidator {
577 void operator()(const EAXOBSTRUCTIONPROPERTIES& props) const
579 Eax2SourceObstructionValidator{}(props.lObstruction);
580 Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
584 struct Eax4OcclusionValidator {
585 void operator()(const EAXOCCLUSIONPROPERTIES& props) const
587 Eax2SourceOcclusionValidator{}(props.lOcclusion);
588 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
589 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
590 Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
594 struct Eax4ExclusionValidator {
595 void operator()(const EAXEXCLUSIONPROPERTIES& props) const
597 Eax3SourceExclusionValidator{}(props.lExclusion);
598 Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
602 // Source validators
603 // ----------------------------------------------------------------------
604 // Send validators
606 struct Eax4SendReceivingFxSlotIdValidator {
607 void operator()(const GUID& guidReceivingFXSlotID) const
609 if (guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot0 &&
610 guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot1 &&
611 guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot2 &&
612 guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot3)
614 eax_fail_unknown_receiving_fx_slot_id();
619 struct Eax5SendReceivingFxSlotIdValidator {
620 void operator()(const GUID& guidReceivingFXSlotID) const
622 if (guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot0 &&
623 guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot1 &&
624 guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot2 &&
625 guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot3)
627 eax_fail_unknown_receiving_fx_slot_id();
632 struct Eax4SendSendValidator {
633 void operator()(long lSend) const
635 eax_validate_range<Exception>(
636 "Send",
637 lSend,
638 EAXSOURCE_MINSEND,
639 EAXSOURCE_MAXSEND);
643 struct Eax4SendSendHfValidator {
644 void operator()(long lSendHF) const
646 eax_validate_range<Exception>(
647 "Send HF",
648 lSendHF,
649 EAXSOURCE_MINSENDHF,
650 EAXSOURCE_MAXSENDHF);
654 template<typename TIdValidator>
655 struct EaxSendValidator {
656 void operator()(const EAXSOURCESENDPROPERTIES& props) const
658 TIdValidator{}(props.guidReceivingFXSlotID);
659 Eax4SendSendValidator{}(props.lSend);
660 Eax4SendSendHfValidator{}(props.lSendHF);
664 struct Eax4SendValidator : EaxSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
665 struct Eax5SendValidator : EaxSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
667 template<typename TIdValidator>
668 struct EaxOcclusionSendValidator {
669 void operator()(const EAXSOURCEOCCLUSIONSENDPROPERTIES& props) const
671 TIdValidator{}(props.guidReceivingFXSlotID);
672 Eax2SourceOcclusionValidator{}(props.lOcclusion);
673 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
674 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
675 Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
679 struct Eax4OcclusionSendValidator : EaxOcclusionSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
680 struct Eax5OcclusionSendValidator : EaxOcclusionSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
682 template<typename TIdValidator>
683 struct EaxExclusionSendValidator {
684 void operator()(const EAXSOURCEEXCLUSIONSENDPROPERTIES& props) const
686 TIdValidator{}(props.guidReceivingFXSlotID);
687 Eax3SourceExclusionValidator{}(props.lExclusion);
688 Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
692 struct Eax4ExclusionSendValidator : EaxExclusionSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
693 struct Eax5ExclusionSendValidator : EaxExclusionSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
695 template<typename TIdValidator>
696 struct EaxAllSendValidator {
697 void operator()(const EAXSOURCEALLSENDPROPERTIES& props) const
699 TIdValidator{}(props.guidReceivingFXSlotID);
700 Eax4SendSendValidator{}(props.lSend);
701 Eax4SendSendHfValidator{}(props.lSendHF);
702 Eax2SourceOcclusionValidator{}(props.lOcclusion);
703 Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
704 Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
705 Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
706 Eax3SourceExclusionValidator{}(props.lExclusion);
707 Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
711 struct Eax4AllSendValidator : EaxAllSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
712 struct Eax5AllSendValidator : EaxAllSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
714 // Send validators
715 // ----------------------------------------------------------------------
716 // Active FX slot ID validators
718 struct Eax4ActiveFxSlotIdValidator {
719 void operator()(const GUID &guid) const
721 if(guid != EAX_NULL_GUID && guid != EAX_PrimaryFXSlotID
722 && guid != EAXPROPERTYID_EAX40_FXSlot0 && guid != EAXPROPERTYID_EAX40_FXSlot1
723 && guid != EAXPROPERTYID_EAX40_FXSlot2 && guid != EAXPROPERTYID_EAX40_FXSlot3)
725 eax_fail_unknown_active_fx_slot_id();
730 struct Eax5ActiveFxSlotIdValidator {
731 void operator()(const GUID &guid) const
733 if(guid != EAX_NULL_GUID && guid != EAX_PrimaryFXSlotID
734 && guid != EAXPROPERTYID_EAX50_FXSlot0 && guid != EAXPROPERTYID_EAX50_FXSlot1
735 && guid != EAXPROPERTYID_EAX50_FXSlot2 && guid != EAXPROPERTYID_EAX50_FXSlot3)
737 eax_fail_unknown_active_fx_slot_id();
742 // Active FX slot ID validators
743 // ----------------------------------------------------------------------
744 // Speaker level validators.
746 struct Eax5SpeakerIdValidator {
747 void operator()(long lSpeakerID) const
749 switch (lSpeakerID) {
750 case EAXSPEAKER_FRONT_LEFT:
751 case EAXSPEAKER_FRONT_CENTER:
752 case EAXSPEAKER_FRONT_RIGHT:
753 case EAXSPEAKER_SIDE_RIGHT:
754 case EAXSPEAKER_REAR_RIGHT:
755 case EAXSPEAKER_REAR_CENTER:
756 case EAXSPEAKER_REAR_LEFT:
757 case EAXSPEAKER_SIDE_LEFT:
758 case EAXSPEAKER_LOW_FREQUENCY:
759 break;
761 default:
762 eax_fail("Unknown speaker ID.");
767 struct Eax5SpeakerLevelValidator {
768 void operator()(long lLevel) const
770 // TODO Use a range when the feature will be implemented.
771 if (lLevel != EAXSOURCE_DEFAULTSPEAKERLEVEL)
772 eax_fail("Speaker level out of range.");
776 struct Eax5SpeakerAllValidator {
777 void operator()(const EAXSPEAKERLEVELPROPERTIES& all) const
779 Eax5SpeakerIdValidator{}(all.lSpeakerID);
780 Eax5SpeakerLevelValidator{}(all.lLevel);
784 // Speaker level validators.
785 // ----------------------------------------------------------------------
787 struct Eax4SendIndexGetter {
788 EaxFxSlotIndexValue operator()(const GUID &guid) const
790 if(guid == EAXPROPERTYID_EAX40_FXSlot0)
791 return 0;
792 if(guid == EAXPROPERTYID_EAX40_FXSlot1)
793 return 1;
794 if(guid == EAXPROPERTYID_EAX40_FXSlot2)
795 return 2;
796 if(guid == EAXPROPERTYID_EAX40_FXSlot3)
797 return 3;
798 eax_fail_unknown_receiving_fx_slot_id();
802 struct Eax5SendIndexGetter {
803 EaxFxSlotIndexValue operator()(const GUID &guid) const
805 if(guid == EAXPROPERTYID_EAX50_FXSlot0)
806 return 0;
807 if(guid == EAXPROPERTYID_EAX50_FXSlot1)
808 return 1;
809 if(guid == EAXPROPERTYID_EAX50_FXSlot2)
810 return 2;
811 if(guid == EAXPROPERTYID_EAX50_FXSlot3)
812 return 3;
813 eax_fail_unknown_receiving_fx_slot_id();
817 [[noreturn]] static void eax_fail(const char* message);
818 [[noreturn]] static void eax_fail_unknown_property_id();
819 [[noreturn]] static void eax_fail_unknown_version();
820 [[noreturn]] static void eax_fail_unknown_active_fx_slot_id();
821 [[noreturn]] static void eax_fail_unknown_receiving_fx_slot_id();
823 static void eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept;
824 static void eax1_set_defaults(Eax1Props& props) noexcept;
825 void eax1_set_defaults() noexcept;
826 static void eax2_set_defaults(Eax2Props& props) noexcept;
827 void eax2_set_defaults() noexcept;
828 static void eax3_set_defaults(Eax3Props& props) noexcept;
829 void eax3_set_defaults() noexcept;
830 static void eax4_set_sends_defaults(EaxSends& sends) noexcept;
831 static void eax4_set_active_fx_slots_defaults(EAX40ACTIVEFXSLOTS& slots) noexcept;
832 void eax4_set_defaults() noexcept;
833 static void eax5_set_source_defaults(EAX50SOURCEPROPERTIES& props) noexcept;
834 static void eax5_set_sends_defaults(EaxSends& sends) noexcept;
835 static void eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noexcept;
836 static void eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept;
837 static void eax5_set_defaults(Eax5Props& props) noexcept;
838 void eax5_set_defaults() noexcept;
839 void eax_set_defaults() noexcept;
841 static void eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept;
842 static void eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept;
843 static void eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept;
844 static void eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept;
846 static float eax_calculate_dst_occlusion_mb(
847 long src_occlusion_mb,
848 float path_ratio,
849 float lf_ratio) noexcept;
851 [[nodiscard]] auto eax_create_direct_filter_param() const noexcept -> EaxAlLowPassParam;
853 [[nodiscard]] auto eax_create_room_filter_param(const ALeffectslot& fx_slot,
854 const EAXSOURCEALLSENDPROPERTIES& send) const noexcept -> EaxAlLowPassParam;
856 void eax_update_direct_filter();
857 void eax_update_room_filters();
858 void eax_commit_filters();
860 static void eax_copy_send_for_get(
861 const EAXSOURCEALLSENDPROPERTIES& src,
862 EAXSOURCESENDPROPERTIES& dst) noexcept
864 dst = reinterpret_cast<const EAXSOURCESENDPROPERTIES&>(src);
867 static void eax_copy_send_for_get(
868 const EAXSOURCEALLSENDPROPERTIES& src,
869 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
871 dst = src;
874 static void eax_copy_send_for_get(
875 const EAXSOURCEALLSENDPROPERTIES& src,
876 EAXSOURCEOCCLUSIONSENDPROPERTIES& dst) noexcept
878 dst.guidReceivingFXSlotID = src.guidReceivingFXSlotID;
879 dst.lOcclusion = src.lOcclusion;
880 dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
881 dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
882 dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
885 static void eax_copy_send_for_get(
886 const EAXSOURCEALLSENDPROPERTIES& src,
887 EAXSOURCEEXCLUSIONSENDPROPERTIES& dst) noexcept
889 dst.guidReceivingFXSlotID = src.guidReceivingFXSlotID;
890 dst.lExclusion = src.lExclusion;
891 dst.flExclusionLFRatio = src.flExclusionLFRatio;
894 template<typename TDstSend>
895 void eax_get_sends(const EaxCall& call, const EaxSends& src_sends)
897 const auto dst_sends = call.get_values<TDstSend>(EAX_MAX_FXSLOTS);
898 const auto count = dst_sends.size();
900 for (auto i = decltype(count){}; i < count; ++i) {
901 const auto& src_send = src_sends[i];
902 auto& dst_send = dst_sends[i];
903 eax_copy_send_for_get(src_send, dst_send);
907 static void eax_get_active_fx_slot_id(const EaxCall& call, const al::span<const GUID> src_ids);
908 static void eax1_get(const EaxCall& call, const Eax1Props& props);
909 static void eax2_get(const EaxCall& call, const Eax2Props& props);
910 static void eax3_get_obstruction(const EaxCall& call, const Eax3Props& props);
911 static void eax3_get_occlusion(const EaxCall& call, const Eax3Props& props);
912 static void eax3_get_exclusion(const EaxCall& call, const Eax3Props& props);
913 static void eax3_get(const EaxCall& call, const Eax3Props& props);
914 void eax4_get(const EaxCall& call, const Eax4Props& props);
915 static void eax5_get_all_2d(const EaxCall& call, const EAX50SOURCEPROPERTIES& props);
916 static void eax5_get_speaker_levels(const EaxCall& call, const EaxSpeakerLevels& props);
917 void eax5_get(const EaxCall& call, const Eax5Props& props);
918 void eax_get(const EaxCall& call);
920 static void eax_copy_send_for_set(
921 const EAXSOURCESENDPROPERTIES& src,
922 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
924 dst.lSend = src.lSend;
925 dst.lSendHF = src.lSendHF;
928 static void eax_copy_send_for_set(
929 const EAXSOURCEALLSENDPROPERTIES& src,
930 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
932 dst.lSend = src.lSend;
933 dst.lSendHF = src.lSendHF;
934 dst.lOcclusion = src.lOcclusion;
935 dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
936 dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
937 dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
938 dst.lExclusion = src.lExclusion;
939 dst.flExclusionLFRatio = src.flExclusionLFRatio;
942 static void eax_copy_send_for_set(
943 const EAXSOURCEOCCLUSIONSENDPROPERTIES& src,
944 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
946 dst.lOcclusion = src.lOcclusion;
947 dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
948 dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
949 dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
952 static void eax_copy_send_for_set(
953 const EAXSOURCEEXCLUSIONSENDPROPERTIES& src,
954 EAXSOURCEALLSENDPROPERTIES& dst) noexcept
956 dst.lExclusion = src.lExclusion;
957 dst.flExclusionLFRatio = src.flExclusionLFRatio;
960 template<typename TValidator, typename TIndexGetter, typename TSrcSend>
961 void eax_defer_sends(const EaxCall& call, EaxSends& dst_sends)
963 const auto src_sends = call.get_values<const TSrcSend>(EAX_MAX_FXSLOTS);
964 std::for_each(src_sends.cbegin(), src_sends.cend(), TValidator{});
965 const auto count = src_sends.size();
966 const auto index_getter = TIndexGetter{};
968 for (auto i = decltype(count){}; i < count; ++i) {
969 const auto& src_send = src_sends[i];
970 const auto dst_index = index_getter(src_send.guidReceivingFXSlotID);
971 auto& dst_send = dst_sends[dst_index];
972 eax_copy_send_for_set(src_send, dst_send);
976 template<typename TValidator, typename TSrcSend>
977 void eax4_defer_sends(const EaxCall& call, EaxSends& dst_sends)
979 eax_defer_sends<TValidator, Eax4SendIndexGetter, TSrcSend>(call, dst_sends);
982 template<typename TValidator, typename TSrcSend>
983 void eax5_defer_sends(const EaxCall& call, EaxSends& dst_sends)
985 eax_defer_sends<TValidator, Eax5SendIndexGetter, TSrcSend>(call, dst_sends);
988 template<typename TValidator, size_t TIdCount>
989 void eax_defer_active_fx_slot_id(const EaxCall& call, const al::span<GUID,TIdCount> dst_ids)
991 const auto src_ids = call.get_values<const GUID>(TIdCount);
992 std::for_each(src_ids.cbegin(), src_ids.cend(), TValidator{});
993 std::uninitialized_copy(src_ids.cbegin(), src_ids.cend(), dst_ids.begin());
996 template<size_t TIdCount>
997 void eax4_defer_active_fx_slot_id(const EaxCall& call, const al::span<GUID,TIdCount> dst_ids)
999 eax_defer_active_fx_slot_id<Eax4ActiveFxSlotIdValidator>(call, dst_ids);
1002 template<size_t TIdCount>
1003 void eax5_defer_active_fx_slot_id(const EaxCall& call, const al::span<GUID,TIdCount> dst_ids)
1005 eax_defer_active_fx_slot_id<Eax5ActiveFxSlotIdValidator>(call, dst_ids);
1008 template<typename TValidator, typename TProperty>
1009 static void eax_defer(const EaxCall& call, TProperty& property)
1011 const auto& value = call.get_value<Exception, const TProperty>();
1012 TValidator{}(value);
1013 property = value;
1016 // Defers source's sub-properties (obstruction, occlusion, exclusion).
1017 template<typename TValidator, typename TSubproperty, typename TProperty>
1018 void eax_defer_sub(const EaxCall& call, TProperty& property)
1020 const auto& src_props = call.get_value<Exception, const TSubproperty>();
1021 TValidator{}(src_props);
1022 auto& dst_props = reinterpret_cast<TSubproperty&>(property);
1023 dst_props = src_props;
1026 void eax_set_efx_outer_gain_hf();
1027 void eax_set_efx_doppler_factor();
1028 void eax_set_efx_rolloff_factor();
1029 void eax_set_efx_room_rolloff_factor();
1030 void eax_set_efx_air_absorption_factor();
1031 void eax_set_efx_dry_gain_hf_auto();
1032 void eax_set_efx_wet_gain_auto();
1033 void eax_set_efx_wet_gain_hf_auto();
1035 static void eax1_set(const EaxCall& call, Eax1Props& props);
1036 static void eax2_set(const EaxCall& call, Eax2Props& props);
1037 void eax3_set(const EaxCall& call, Eax3Props& props);
1038 void eax4_set(const EaxCall& call, Eax4Props& props);
1039 static void eax5_defer_all_2d(const EaxCall& call, EAX50SOURCEPROPERTIES& props);
1040 static void eax5_defer_speaker_levels(const EaxCall& call, EaxSpeakerLevels& props);
1041 void eax5_set(const EaxCall& call, Eax5Props& props);
1042 void eax_set(const EaxCall& call);
1044 // `alSource3i(source, AL_AUXILIARY_SEND_FILTER, ...)`
1045 void eax_set_al_source_send(ALeffectslot *slot, size_t sendidx,
1046 const EaxAlLowPassParam &filter);
1048 void eax_commit_active_fx_slots();
1049 #endif // ALSOFT_EAX
1052 void UpdateAllSourceProps(ALCcontext *context);
1054 struct SourceSubList {
1055 uint64_t FreeMask{~0_u64};
1056 gsl::owner<std::array<ALsource,64>*> Sources{nullptr};
1058 SourceSubList() noexcept = default;
1059 SourceSubList(const SourceSubList&) = delete;
1060 SourceSubList(SourceSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Sources{rhs.Sources}
1061 { rhs.FreeMask = ~0_u64; rhs.Sources = nullptr; }
1062 ~SourceSubList();
1064 SourceSubList& operator=(const SourceSubList&) = delete;
1065 SourceSubList& operator=(SourceSubList&& rhs) noexcept
1066 { std::swap(FreeMask, rhs.FreeMask); std::swap(Sources, rhs.Sources); return *this; }
1069 #endif