23 #include "inprogext.h"
25 #include "polymorphism.h"
26 #include "static_assert.h"
44 #define HAS_BUILTIN __has_builtin
46 #define HAS_BUILTIN(x) (0)
50 /* LIKELY optimizes the case where the condition is true. The condition is not
51 * required to be true, but it can result in more optimal code for the true
52 * path at the expense of a less optimal false path.
54 #define LIKELY(x) __builtin_expect(!!(x), !0)
55 /* The opposite of LIKELY, optimizing the case where the condition is false. */
56 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
57 /* Unlike LIKELY, ASSUME requires the condition to be true or else it invokes
58 * undefined behavior. It's essentially an assert without actually checking the
59 * condition at run-time, allowing for stronger optimizations than LIKELY.
61 #if HAS_BUILTIN(__builtin_assume)
62 #define ASSUME __builtin_assume
64 #define ASSUME(x) do { if(!(x)) __builtin_unreachable(); } while(0)
69 #define LIKELY(x) (!!(x))
70 #define UNLIKELY(x) (!!(x))
72 #define ASSUME __assume
74 #define ASSUME(x) ((void)0)
79 #define UINT64_MAX U64(18446744073709551615)
83 #if defined(__cplusplus)
85 #elif defined(__GNUC__)
86 #define UNUSED(x) UNUSED_##x __attribute__((unused))
87 #elif defined(__LCLINT__)
88 #define UNUSED(x) /*@unused@*/ x
94 /* Calculates the size of a struct with N elements of a flexible array member.
95 * GCC and Clang allow offsetof(Type, fam[N]) for this, but MSVC seems to have
96 * trouble, so a bit more verbose workaround is needed.
98 #define FAM_SIZE(T, M, N) (offsetof(T, M) + sizeof(((T*)NULL)->M[0])*(N))
105 typedef ALint64SOFT ALint64
;
106 typedef ALuint64SOFT ALuint64
;
109 #if defined(_MSC_VER)
110 #define U64(x) ((ALuint64)(x##ui64))
111 #elif SIZEOF_LONG == 8
112 #define U64(x) ((ALuint64)(x##ul))
113 #elif SIZEOF_LONG_LONG == 8
114 #define U64(x) ((ALuint64)(x##ull))
119 #if defined(_MSC_VER)
120 #define I64(x) ((ALint64)(x##i64))
121 #elif SIZEOF_LONG == 8
122 #define I64(x) ((ALint64)(x##l))
123 #elif SIZEOF_LONG_LONG == 8
124 #define I64(x) ((ALint64)(x##ll))
128 /* Define a CTZ64 macro (count trailing zeros, for 64-bit integers). The result
129 * is *UNDEFINED* if the value is 0.
134 #define CTZ64 __builtin_ctzl
136 #define CTZ64 __builtin_ctzll
139 #elif defined(HAVE_BITSCANFORWARD64_INTRINSIC)
141 inline int msvc64_ctz64(ALuint64 v
)
143 unsigned long idx
= 64;
144 _BitScanForward64(&idx
, v
);
147 #define CTZ64 msvc64_ctz64
149 #elif defined(HAVE_BITSCANFORWARD_INTRINSIC)
151 inline int msvc_ctz64(ALuint64 v
)
153 unsigned long idx
= 64;
154 if(!_BitScanForward(&idx
, v
&0xffffffff))
156 if(_BitScanForward(&idx
, v
>>32))
161 #define CTZ64 msvc_ctz64
165 /* There be black magics here. The popcnt64 method is derived from
166 * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
167 * while the ctz-utilizing-popcnt algorithm is shown here
168 * http://www.hackersdelight.org/hdcodetxt/ntz.c.txt
169 * as the ntz2 variant. These likely aren't the most efficient methods, but
170 * they're good enough if the GCC or MSVC intrinsics aren't available.
172 inline int fallback_popcnt64(ALuint64 v
)
174 v
= v
- ((v
>> 1) & U64(0x5555555555555555));
175 v
= (v
& U64(0x3333333333333333)) + ((v
>> 2) & U64(0x3333333333333333));
176 v
= (v
+ (v
>> 4)) & U64(0x0f0f0f0f0f0f0f0f);
177 return (int)((v
* U64(0x0101010101010101)) >> 56);
180 inline int fallback_ctz64(ALuint64 value
)
182 return fallback_popcnt64(~value
& (value
- 1));
184 #define CTZ64 fallback_ctz64
187 #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
188 #define IS_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
192 ALubyte b
[sizeof(ALuint
)];
193 } EndianTest
= { 1 };
194 #define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
197 #define COUNTOF(x) (sizeof(x) / sizeof(0[x]))
200 struct ll_ringbuffer
;
203 struct DirectHrtfState
;
204 struct FrontStablizer
;
211 struct ALcontextProps
;
212 struct ALlistenerProps
;
214 struct ALeffectslotProps
;
217 #define DEFAULT_OUTPUT_RATE (44100)
218 #define MIN_OUTPUT_RATE (8000)
221 /* Find the next power-of-2 for non-power-of-2 numbers. */
222 inline ALuint
NextPowerOf2(ALuint value
)
236 /** Round up a value to the next multiple. */
237 inline size_t RoundUp(size_t value
, size_t r
)
240 return value
- (value
%r
);
243 /* Fast float-to-int conversion. No particular rounding mode is assumed; the
244 * IEEE-754 default is round-to-nearest with ties-to-even, though an app could
245 * change it on its own threads. On some systems, a truncating conversion may
246 * always be the fastest method.
248 inline ALint
fastf2i(ALfloat f
)
250 #if defined(HAVE_INTRIN_H) && ((defined(_M_IX86_FP) && (_M_IX86_FP > 0)) || defined(_M_X64))
251 return _mm_cvt_ss2si(_mm_set1_ps(f
));
253 #elif defined(_MSC_VER) && defined(_M_IX86_FP)
260 #elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
264 __asm__("cvtss2si %1, %0" : "=r"(i
) : "x"(f
));
266 __asm__
__volatile__("fistpl %0" : "=m"(i
) : "t"(f
) : "st");
270 /* On GCC when compiling with -fno-math-errno, lrintf can be inlined to
271 * some simple instructions. Clang does not inline it, always generating a
272 * libc call, while MSVC's implementation is horribly slow, so always fall
273 * back to a normal integer conversion for them.
275 #elif defined(HAVE_LRINTF) && !defined(_MSC_VER) && !defined(__clang__)
285 /* Converts float-to-int using standard behavior (truncation). */
286 inline int float2int(float f
)
288 #if ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
289 !defined(__SSE_MATH__)) || (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0)
290 ALint sign
, shift
, mant
;
297 sign
= (conv
.i
>>31) | 1;
298 shift
= ((conv
.i
>>23)&0xff) - (127+23);
301 if(UNLIKELY(shift
>= 31 || shift
< -23))
304 mant
= (conv
.i
&0x7fffff) | 0x800000;
305 if(LIKELY(shift
< 0))
306 return (mant
>> -shift
) * sign
;
307 return (mant
<< shift
) * sign
;
315 /* Rounds a float to the nearest integral value, according to the current
316 * rounding mode. This is essentially an inlined version of rintf, although
317 * makes fewer promises (e.g. -0 or -0.25 rounded to 0 may result in +0).
319 inline float fast_roundf(float f
)
321 #if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
322 !defined(__SSE_MATH__)
325 __asm__
__volatile__("frndint" : "=t"(out
) : "0"(f
));
330 /* Integral limit, where sub-integral precision is not available for
333 static const float ilim
[2] = {
334 8388608.0f
/* 0x1.0p+23 */,
335 -8388608.0f
/* -0x1.0p+23 */
344 sign
= (conv
.i
>>31)&0x01;
345 expo
= (conv
.i
>>23)&0xff;
347 if(UNLIKELY(expo
>= 150/*+23*/))
349 /* An exponent (base-2) of 23 or higher is incapable of sub-integral
350 * precision, so it's already an integral value. We don't need to worry
351 * about infinity or NaN here.
355 /* Adding the integral limit to the value (with a matching sign) forces a
356 * result that has no sub-integral precision, and is consequently forced to
357 * round to an integral value. Removing the integral limit then restores
358 * the initial value rounded to the integral. The compiler should not
359 * optimize this out because of non-associative rules on floating-point
360 * math (as long as you don't use -fassociative-math,
361 * -funsafe-math-optimizations, -ffast-math, or -Ofast, in which case this
365 return f
- ilim
[sign
];
377 InverseDistanceClamped
= AL_INVERSE_DISTANCE_CLAMPED
,
378 LinearDistanceClamped
= AL_LINEAR_DISTANCE_CLAMPED
,
379 ExponentDistanceClamped
= AL_EXPONENT_DISTANCE_CLAMPED
,
380 InverseDistance
= AL_INVERSE_DISTANCE
,
381 LinearDistance
= AL_LINEAR_DISTANCE
,
382 ExponentDistance
= AL_EXPONENT_DISTANCE
,
383 DisableDistance
= AL_NONE
,
385 DefaultDistanceModel
= InverseDistanceClamped
431 DevFmtByte
= ALC_BYTE_SOFT
,
432 DevFmtUByte
= ALC_UNSIGNED_BYTE_SOFT
,
433 DevFmtShort
= ALC_SHORT_SOFT
,
434 DevFmtUShort
= ALC_UNSIGNED_SHORT_SOFT
,
435 DevFmtInt
= ALC_INT_SOFT
,
436 DevFmtUInt
= ALC_UNSIGNED_INT_SOFT
,
437 DevFmtFloat
= ALC_FLOAT_SOFT
,
439 DevFmtTypeDefault
= DevFmtFloat
441 enum DevFmtChannels
{
442 DevFmtMono
= ALC_MONO_SOFT
,
443 DevFmtStereo
= ALC_STEREO_SOFT
,
444 DevFmtQuad
= ALC_QUAD_SOFT
,
445 DevFmtX51
= ALC_5POINT1_SOFT
,
446 DevFmtX61
= ALC_6POINT1_SOFT
,
447 DevFmtX71
= ALC_7POINT1_SOFT
,
448 DevFmtAmbi3D
= ALC_BFORMAT3D_SOFT
,
450 /* Similar to 5.1, except using rear channels instead of sides */
451 DevFmtX51Rear
= 0x80000000,
453 DevFmtChannelsDefault
= DevFmtStereo
455 #define MAX_OUTPUT_CHANNELS (16)
457 ALsizei
BytesFromDevFmt(enum DevFmtType type
);
458 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
);
459 inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
)
461 return ChannelsFromDevFmt(chans
, ambiorder
) * BytesFromDevFmt(type
);
465 AmbiLayout_FuMa
= ALC_FUMA_SOFT
, /* FuMa channel order */
466 AmbiLayout_ACN
= ALC_ACN_SOFT
, /* ACN channel order */
468 AmbiLayout_Default
= AmbiLayout_ACN
472 AmbiNorm_FuMa
= ALC_FUMA_SOFT
, /* FuMa normalization */
473 AmbiNorm_SN3D
= ALC_SN3D_SOFT
, /* SN3D normalization */
474 AmbiNorm_N3D
= ALC_N3D_SOFT
, /* N3D normalization */
476 AmbiNorm_Default
= AmbiNorm_SN3D
494 /* The maximum number of Ambisonics coefficients. For a given order (o), the
495 * size needed will be (o+1)**2, thus zero-order has 1, first-order has 4,
496 * second-order has 9, third-order has 16, and fourth-order has 25.
498 #define MAX_AMBI_ORDER 3
499 #define MAX_AMBI_COEFFS ((MAX_AMBI_ORDER+1) * (MAX_AMBI_ORDER+1))
501 /* A bitmask of ambisonic channels with height information. If none of these
502 * channels are used/needed, there's no height (e.g. with most surround sound
503 * speaker setups). This only specifies up to 4th order, which is the highest
504 * order a 32-bit mask value can specify (a 64-bit mask could handle up to 7th
505 * order). This is ACN ordering, with bit 0 being ACN 0, etc.
507 #define AMBI_PERIPHONIC_MASK (0xfe7ce4)
509 /* The maximum number of Ambisonic coefficients for 2D (non-periphonic)
510 * representation. This is 2 per each order above zero-order, plus 1 for zero-
511 * order. Or simply, o*2 + 1.
513 #define MAX_AMBI2D_COEFFS (MAX_AMBI_ORDER*2 + 1)
516 typedef ALfloat ChannelConfig
[MAX_AMBI_COEFFS
];
517 typedef struct BFChannelConfig
{
522 typedef union AmbiConfig
{
523 /* Ambisonic coefficients for mixing to the dry buffer. */
524 ChannelConfig Coeffs
[MAX_OUTPUT_CHANNELS
];
525 /* Coefficient channel mapping for mixing to the dry buffer. */
526 BFChannelConfig Map
[MAX_OUTPUT_CHANNELS
];
530 typedef struct BufferSubList
{
532 struct ALbuffer
*Buffers
; /* 64 */
534 TYPEDEF_VECTOR(BufferSubList
, vector_BufferSubList
)
536 typedef struct EffectSubList
{
538 struct ALeffect
*Effects
; /* 64 */
540 TYPEDEF_VECTOR(EffectSubList
, vector_EffectSubList
)
542 typedef struct FilterSubList
{
544 struct ALfilter
*Filters
; /* 64 */
546 TYPEDEF_VECTOR(FilterSubList
, vector_FilterSubList
)
548 typedef struct SourceSubList
{
550 struct ALsource
*Sources
; /* 64 */
552 TYPEDEF_VECTOR(SourceSubList
, vector_SourceSubList
)
554 /* Effect slots are rather large, and apps aren't likely to have more than one
555 * or two (let alone 64), so hold them individually.
557 typedef struct ALeffectslot
*ALeffectslotPtr
;
558 TYPEDEF_VECTOR(ALeffectslotPtr
, vector_ALeffectslotPtr
)
561 typedef struct EnumeratedHrtf
{
564 struct HrtfEntry
*hrtf
;
566 TYPEDEF_VECTOR(EnumeratedHrtf
, vector_EnumeratedHrtf
)
569 /* Maximum delay in samples for speaker distance compensation. */
570 #define MAX_DELAY_LENGTH 1024
572 typedef struct DistanceComp
{
574 ALsizei Length
; /* Valid range is [0...MAX_DELAY_LENGTH). */
578 /* Size for temporary storage of buffer data, in ALfloats. Larger values need
579 * more memory, while smaller values may need more iterations. The value needs
580 * to be a sensible size, however, as it constrains the max stepping value used
581 * for mixing, as well as the maximum number of samples per mixing iteration.
583 #define BUFFERSIZE 2048
585 typedef struct DryMixParams
{
587 /* Number of coefficients in each Ambi.Coeffs to mix together (4 for first-
588 * order, 9 for second-order, etc). If the count is 0, Ambi.Map is used
589 * instead to map each output to a coefficient index.
593 ALfloat (*Buffer
)[BUFFERSIZE
];
595 ALsizei NumChannelsPerOrder
[MAX_AMBI_ORDER
+1];
598 typedef struct BFMixParams
{
600 /* Will only be 4 or 0. */
603 ALfloat (*Buffer
)[BUFFERSIZE
];
607 typedef struct RealMixParams
{
608 enum Channel ChannelName
[MAX_OUTPUT_CHANNELS
];
610 ALfloat (*Buffer
)[BUFFERSIZE
];
614 typedef void (*POSTPROCESS
)(ALCdevice
*device
, ALsizei SamplesToDo
);
616 struct ALCdevice_struct
{
619 ATOMIC(ALenum
) Connected
;
620 enum DeviceType Type
;
625 enum DevFmtChannels FmtChans
;
626 enum DevFmtType FmtType
;
627 ALboolean IsHeadphones
;
629 /* For DevFmtAmbi* output only, specifies the channel order and
632 enum AmbiLayout AmbiLayout
;
633 enum AmbiNorm AmbiScale
;
635 al_string DeviceName
;
637 ATOMIC(ALCenum
) LastError
;
639 // Maximum number of sources that can be created
641 // Maximum number of slots that can be created
642 ALuint AuxiliaryEffectSlotMax
;
644 ALCuint NumMonoSources
;
645 ALCuint NumStereoSources
;
648 // Map of Buffers for this device
649 vector_BufferSubList BufferList
;
652 // Map of Effects for this device
653 vector_EffectSubList EffectList
;
656 // Map of Filters for this device
657 vector_FilterSubList FilterList
;
660 POSTPROCESS PostProcess
;
662 /* HRTF state and info */
663 struct DirectHrtfState
*Hrtf
;
665 struct Hrtf
*HrtfHandle
;
666 vector_EnumeratedHrtf HrtfList
;
669 /* UHJ encoder state */
670 struct Uhj2Encoder
*Uhj_Encoder
;
672 /* High quality Ambisonic decoder */
673 struct BFormatDec
*AmbiDecoder
;
675 /* Stereo-to-binaural filter */
678 /* First-order ambisonic upsampler for higher-order output */
679 struct AmbiUpsampler
*AmbiUp
;
681 /* Rendering mode. */
682 enum RenderMode Render_Mode
;
690 /* Temp storage used for mixer processing. */
691 alignas(16) ALfloat TempBuffer
[4][BUFFERSIZE
];
693 /* The "dry" path corresponds to the main output. */
696 /* First-order ambisonics output, to be upsampled to the dry buffer if different. */
699 /* "Real" output, which will be written to the device buffer. May alias the
702 RealMixParams RealOut
;
704 struct FrontStablizer
*Stablizer
;
706 struct Compressor
*Limiter
;
708 /* The average speaker distance as determined by the ambdec configuration
709 * (or alternatively, by the NFC-HOA reference delay). Only used for NFC.
711 ALfloat AvgSpeakerDist
;
713 /* Delay buffers used to compensate for speaker distances. */
714 DistanceComp ChannelDelay
[MAX_OUTPUT_CHANNELS
];
716 /* Dithering control. */
720 /* Running count of the mixer invocations, in 31.1 fixed point. This
721 * actually increments *twice* when mixing, first at the start and then at
722 * the end, so the bottom bit indicates if the device is currently mixing
723 * and the upper bits indicates how many mixes have been done.
727 // Contexts created on this device
728 ATOMIC(ALCcontext
*) ContextList
;
731 struct ALCbackend
*Backend
;
733 ATOMIC(ALCdevice
*) next
;
736 // Frequency was requested by the app or config file
737 #define DEVICE_FREQUENCY_REQUEST (1u<<1)
738 // Channel configuration was requested by the config file
739 #define DEVICE_CHANNELS_REQUEST (1u<<2)
740 // Sample type was requested by the config file
741 #define DEVICE_SAMPLE_TYPE_REQUEST (1u<<3)
743 // Specifies if the DSP is paused at user request
744 #define DEVICE_PAUSED (1u<<30)
746 // Specifies if the device is currently running
747 #define DEVICE_RUNNING (1u<<31)
750 /* Nanosecond resolution for the device clock time. */
751 #define DEVICE_CLOCK_RES U64(1000000000)
754 /* Must be less than 15 characters (16 including terminating null) for
755 * compatibility with pthread_setname_np limitations. */
756 #define MIXER_THREAD_NAME "alsoft-mixer"
758 #define RECORD_THREAD_NAME "alsoft-record"
762 EventType_SourceStateChange
= 1<<0,
763 EventType_BufferCompleted
= 1<<1,
764 EventType_Error
= 1<<2,
765 EventType_Performance
= 1<<3,
766 EventType_Deprecated
= 1<<4,
767 EventType_Disconnected
= 1<<5,
770 typedef struct AsyncEvent
{
771 unsigned int EnumType
;
775 ALchar Message
[1008];
778 struct ALCcontext_struct
{
781 struct ALlistener
*Listener
;
783 vector_SourceSubList SourceList
;
787 vector_ALeffectslotPtr EffectSlotList
;
788 almtx_t EffectSlotLock
;
790 ATOMIC(ALenum
) LastError
;
792 enum DistanceModel DistanceModel
;
793 ALboolean SourceDistanceModel
;
795 ALfloat DopplerFactor
;
796 ALfloat DopplerVelocity
;
797 ALfloat SpeedOfSound
;
798 ALfloat MetersPerUnit
;
800 ATOMIC_FLAG PropsClean
;
801 ATOMIC(ALenum
) DeferUpdates
;
805 /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
806 * indicates if updates are currently happening).
808 RefCount UpdateCount
;
809 ATOMIC(ALenum
) HoldUpdates
;
813 ATOMIC(struct ALcontextProps
*) Update
;
815 /* Linked lists of unused property containers, free to use for future
818 ATOMIC(struct ALcontextProps
*) FreeContextProps
;
819 ATOMIC(struct ALlistenerProps
*) FreeListenerProps
;
820 ATOMIC(struct ALvoiceProps
*) FreeVoiceProps
;
821 ATOMIC(struct ALeffectslotProps
*) FreeEffectslotProps
;
823 struct ALvoice
**Voices
;
827 ATOMIC(struct ALeffectslotArray
*) ActiveAuxSlots
;
829 almtx_t EventThrdLock
;
830 althrd_t EventThread
;
832 struct ll_ringbuffer
*AsyncEvents
;
833 ATOMIC(ALbitfieldSOFT
) EnabledEvts
;
835 ALEVENTPROCSOFT EventCb
;
838 /* Default effect slot */
839 struct ALeffectslot
*DefaultSlot
;
842 const ALCchar
*ExtensionList
;
844 ATOMIC(ALCcontext
*) next
;
846 /* Memory space used by the listener (and possibly default effect slot) */
847 alignas(16) ALCbyte _listener_mem
[];
850 ALCcontext
*GetContextRef(void);
852 void ALCcontext_DecRef(ALCcontext
*context
);
854 void ALCcontext_DeferUpdates(ALCcontext
*context
);
855 void ALCcontext_ProcessUpdates(ALCcontext
*context
);
857 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
);
859 void AppendAllDevicesList(const ALCchar
*name
);
860 void AppendCaptureDeviceList(const ALCchar
*name
);
863 extern ALint RTPrioLevel
;
864 void SetRTPriority(void);
866 void SetDefaultChannelOrder(ALCdevice
*device
);
867 void SetDefaultWFXChannelOrder(ALCdevice
*device
);
869 const ALCchar
*DevFmtTypeString(enum DevFmtType type
);
870 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
);
872 inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
)
875 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
883 * GetChannelIdxByName
885 * Returns the index for the given channel name (e.g. FrontCenter), or -1 if it
888 inline ALint
GetChannelIdxByName(const RealMixParams
*real
, enum Channel chan
)
889 { return GetChannelIndex(real
->ChannelName
, chan
); }
892 inline void LockBufferList(ALCdevice
*device
) { almtx_lock(&device
->BufferLock
); }
893 inline void UnlockBufferList(ALCdevice
*device
) { almtx_unlock(&device
->BufferLock
); }
895 inline void LockEffectList(ALCdevice
*device
) { almtx_lock(&device
->EffectLock
); }
896 inline void UnlockEffectList(ALCdevice
*device
) { almtx_unlock(&device
->EffectLock
); }
898 inline void LockFilterList(ALCdevice
*device
) { almtx_lock(&device
->FilterLock
); }
899 inline void UnlockFilterList(ALCdevice
*device
) { almtx_unlock(&device
->FilterLock
); }
901 inline void LockEffectSlotList(ALCcontext
*context
)
902 { almtx_lock(&context
->EffectSlotLock
); }
903 inline void UnlockEffectSlotList(ALCcontext
*context
)
904 { almtx_unlock(&context
->EffectSlotLock
); }
907 vector_al_string
SearchDataFiles(const char *match
, const char *subdir
);