2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
28 #include "alcontext.h"
36 #define FILTER_MIN_GAIN 0.0f
37 #define FILTER_MAX_GAIN 4.0f /* +12dB */
39 void ALlowpass_setParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
UNUSED(val
))
40 { alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass integer property 0x%04x", param
); }
41 void ALlowpass_setParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALint
*UNUSED(vals
))
42 { alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass integer-vector property 0x%04x", param
); }
43 void ALlowpass_setParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat val
)
48 if(!(val
>= FILTER_MIN_GAIN
&& val
<= FILTER_MAX_GAIN
))
49 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Low-pass gain %f out of range", val
);
53 case AL_LOWPASS_GAINHF
:
54 if(!(val
>= AL_LOWPASS_MIN_GAINHF
&& val
<= AL_LOWPASS_MAX_GAINHF
))
55 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Low-pass gainhf %f out of range", val
);
60 alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass float property 0x%04x", param
);
63 void ALlowpass_setParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
64 { ALlowpass_setParamf(filter
, context
, param
, vals
[0]); }
66 void ALlowpass_getParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(val
))
67 { alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass integer property 0x%04x", param
); }
68 void ALlowpass_getParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(vals
))
69 { alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass integer-vector property 0x%04x", param
); }
70 void ALlowpass_getParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
78 case AL_LOWPASS_GAINHF
:
79 *val
= filter
->GainHF
;
83 alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass float property 0x%04x", param
);
86 void ALlowpass_getParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
87 { ALlowpass_getParamf(filter
, context
, param
, vals
); }
89 DEFINE_ALFILTER_VTABLE(ALlowpass
);
92 void ALhighpass_setParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
UNUSED(val
))
93 { alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass integer property 0x%04x", param
); }
94 void ALhighpass_setParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALint
*UNUSED(vals
))
95 { alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass integer-vector property 0x%04x", param
); }
96 void ALhighpass_setParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat val
)
100 case AL_HIGHPASS_GAIN
:
101 if(!(val
>= FILTER_MIN_GAIN
&& val
<= FILTER_MAX_GAIN
))
102 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "High-pass gain out of range");
106 case AL_HIGHPASS_GAINLF
:
107 if(!(val
>= AL_HIGHPASS_MIN_GAINLF
&& val
<= AL_HIGHPASS_MAX_GAINLF
))
108 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "High-pass gainlf out of range");
109 filter
->GainLF
= val
;
113 alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass float property 0x%04x", param
);
116 void ALhighpass_setParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
117 { ALhighpass_setParamf(filter
, context
, param
, vals
[0]); }
119 void ALhighpass_getParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(val
))
120 { alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass integer property 0x%04x", param
); }
121 void ALhighpass_getParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(vals
))
122 { alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass integer-vector property 0x%04x", param
); }
123 void ALhighpass_getParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
127 case AL_HIGHPASS_GAIN
:
131 case AL_HIGHPASS_GAINLF
:
132 *val
= filter
->GainLF
;
136 alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass float property 0x%04x", param
);
139 void ALhighpass_getParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
140 { ALhighpass_getParamf(filter
, context
, param
, vals
); }
142 DEFINE_ALFILTER_VTABLE(ALhighpass
);
145 void ALbandpass_setParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
UNUSED(val
))
146 { alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass integer property 0x%04x", param
); }
147 void ALbandpass_setParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALint
*UNUSED(vals
))
148 { alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass integer-vector property 0x%04x", param
); }
149 void ALbandpass_setParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat val
)
153 case AL_BANDPASS_GAIN
:
154 if(!(val
>= FILTER_MIN_GAIN
&& val
<= FILTER_MAX_GAIN
))
155 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Band-pass gain out of range");
159 case AL_BANDPASS_GAINHF
:
160 if(!(val
>= AL_BANDPASS_MIN_GAINHF
&& val
<= AL_BANDPASS_MAX_GAINHF
))
161 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Band-pass gainhf out of range");
162 filter
->GainHF
= val
;
165 case AL_BANDPASS_GAINLF
:
166 if(!(val
>= AL_BANDPASS_MIN_GAINLF
&& val
<= AL_BANDPASS_MAX_GAINLF
))
167 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Band-pass gainlf out of range");
168 filter
->GainLF
= val
;
172 alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass float property 0x%04x", param
);
175 void ALbandpass_setParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
176 { ALbandpass_setParamf(filter
, context
, param
, vals
[0]); }
178 void ALbandpass_getParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(val
))
179 { alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass integer property 0x%04x", param
); }
180 void ALbandpass_getParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(vals
))
181 { alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass integer-vector property 0x%04x", param
); }
182 void ALbandpass_getParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
186 case AL_BANDPASS_GAIN
:
190 case AL_BANDPASS_GAINHF
:
191 *val
= filter
->GainHF
;
194 case AL_BANDPASS_GAINLF
:
195 *val
= filter
->GainLF
;
199 alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass float property 0x%04x", param
);
202 void ALbandpass_getParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
203 { ALbandpass_getParamf(filter
, context
, param
, vals
); }
205 DEFINE_ALFILTER_VTABLE(ALbandpass
);
208 void ALnullfilter_setParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
UNUSED(val
))
209 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
210 void ALnullfilter_setParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALint
*UNUSED(vals
))
211 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
212 void ALnullfilter_setParamf(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALfloat
UNUSED(val
))
213 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
214 void ALnullfilter_setParamfv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALfloat
*UNUSED(vals
))
215 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
217 void ALnullfilter_getParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(val
))
218 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
219 void ALnullfilter_getParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(vals
))
220 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
221 void ALnullfilter_getParamf(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALfloat
*UNUSED(val
))
222 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
223 void ALnullfilter_getParamfv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALfloat
*UNUSED(vals
))
224 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
226 DEFINE_ALFILTER_VTABLE(ALnullfilter
);
229 void InitFilterParams(ALfilter
*filter
, ALenum type
)
231 if(type
== AL_FILTER_LOWPASS
)
233 filter
->Gain
= AL_LOWPASS_DEFAULT_GAIN
;
234 filter
->GainHF
= AL_LOWPASS_DEFAULT_GAINHF
;
235 filter
->HFReference
= LOWPASSFREQREF
;
236 filter
->GainLF
= 1.0f
;
237 filter
->LFReference
= HIGHPASSFREQREF
;
238 filter
->vtab
= &ALlowpass_vtable
;
240 else if(type
== AL_FILTER_HIGHPASS
)
242 filter
->Gain
= AL_HIGHPASS_DEFAULT_GAIN
;
243 filter
->GainHF
= 1.0f
;
244 filter
->HFReference
= LOWPASSFREQREF
;
245 filter
->GainLF
= AL_HIGHPASS_DEFAULT_GAINLF
;
246 filter
->LFReference
= HIGHPASSFREQREF
;
247 filter
->vtab
= &ALhighpass_vtable
;
249 else if(type
== AL_FILTER_BANDPASS
)
251 filter
->Gain
= AL_BANDPASS_DEFAULT_GAIN
;
252 filter
->GainHF
= AL_BANDPASS_DEFAULT_GAINHF
;
253 filter
->HFReference
= LOWPASSFREQREF
;
254 filter
->GainLF
= AL_BANDPASS_DEFAULT_GAINLF
;
255 filter
->LFReference
= HIGHPASSFREQREF
;
256 filter
->vtab
= &ALbandpass_vtable
;
261 filter
->GainHF
= 1.0f
;
262 filter
->HFReference
= LOWPASSFREQREF
;
263 filter
->GainLF
= 1.0f
;
264 filter
->LFReference
= HIGHPASSFREQREF
;
265 filter
->vtab
= &ALnullfilter_vtable
;
270 ALfilter
*AllocFilter(ALCcontext
*context
)
272 ALCdevice
*device
= context
->Device
;
273 almtx_lock(&device
->FilterLock
);
275 auto sublist
= std::find_if(device
->FilterList
.begin(), device
->FilterList
.end(),
276 [](const FilterSubList
&entry
) noexcept
-> bool
277 { return entry
.FreeMask
!= 0; }
280 auto lidx
= std::distance(device
->FilterList
.begin(), sublist
);
281 ALfilter
*filter
{nullptr};
283 if(LIKELY(sublist
!= device
->FilterList
.end()))
285 slidx
= CTZ64(sublist
->FreeMask
);
286 filter
= sublist
->Filters
+ slidx
;
290 /* Don't allocate so many list entries that the 32-bit ID could
293 if(UNLIKELY(device
->FilterList
.size() >= 1<<25))
295 almtx_unlock(&device
->FilterLock
);
296 alSetError(context
, AL_OUT_OF_MEMORY
, "Too many filters allocated");
299 device
->FilterList
.emplace_back();
300 sublist
= device
->FilterList
.end() - 1;
301 sublist
->FreeMask
= ~U64(0);
302 sublist
->Filters
= static_cast<ALfilter
*>(al_calloc(16, sizeof(ALfilter
)*64));
303 if(UNLIKELY(!sublist
->Filters
))
305 device
->FilterList
.pop_back();
306 almtx_unlock(&device
->FilterLock
);
307 alSetError(context
, AL_OUT_OF_MEMORY
, "Failed to allocate filter batch");
312 filter
= sublist
->Filters
+ slidx
;
315 filter
= new (filter
) ALfilter
{};
316 InitFilterParams(filter
, AL_FILTER_NULL
);
318 /* Add 1 to avoid filter ID 0. */
319 filter
->id
= ((lidx
<<6) | slidx
) + 1;
321 sublist
->FreeMask
&= ~(U64(1)<<slidx
);
322 almtx_unlock(&device
->FilterLock
);
327 void FreeFilter(ALCdevice
*device
, ALfilter
*filter
)
329 ALuint id
= filter
->id
- 1;
330 ALsizei lidx
= id
>> 6;
331 ALsizei slidx
= id
& 0x3f;
335 device
->FilterList
[lidx
].FreeMask
|= U64(1) << slidx
;
339 inline ALfilter
*LookupFilter(ALCdevice
*device
, ALuint id
)
341 ALuint lidx
= (id
-1) >> 6;
342 ALsizei slidx
= (id
-1) & 0x3f;
344 if(UNLIKELY(lidx
>= device
->FilterList
.size()))
346 FilterSubList
&sublist
= device
->FilterList
[lidx
];
347 if(UNLIKELY(sublist
.FreeMask
& (U64(1)<<slidx
)))
349 return sublist
.Filters
+ slidx
;
354 AL_API ALvoid AL_APIENTRY
alGenFilters(ALsizei n
, ALuint
*filters
)
356 ContextRef context
{GetContextRef()};
357 if(UNLIKELY(!context
)) return;
361 alSetError(context
.get(), AL_INVALID_VALUE
, "Generating %d filters", n
);
367 /* Special handling for the easy and normal case. */
368 ALfilter
*filter
= AllocFilter(context
.get());
369 if(filter
) filters
[0] = filter
->id
;
373 /* Store the allocated buffer IDs in a separate local list, to avoid
374 * modifying the user storage in case of failure.
376 al::vector
<ALuint
> ids
;
379 ALfilter
*filter
= AllocFilter(context
.get());
382 alDeleteFilters(ids
.size(), ids
.data());
386 ids
.emplace_back(filter
->id
);
388 std::copy(ids
.begin(), ids
.end(), filters
);
392 AL_API ALvoid AL_APIENTRY
alDeleteFilters(ALsizei n
, const ALuint
*filters
)
394 ContextRef context
{GetContextRef()};
395 if(UNLIKELY(!context
)) return;
399 alSetError(context
.get(), AL_INVALID_VALUE
, "Deleting %d filters", n
);
405 ALCdevice
*device
{context
->Device
};
406 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
408 /* First try to find any filters that are invalid. */
409 const ALuint
*filters_end
= filters
+ n
;
410 auto invflt
= std::find_if(filters
, filters_end
,
411 [device
, &context
](ALuint fid
) -> bool
413 if(!fid
) return false;
414 ALfilter
*filter
{LookupFilter(device
, fid
)};
415 if(UNLIKELY(!filter
))
417 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", fid
);
423 if(LIKELY(invflt
== filters_end
))
425 /* All good. Delete non-0 filter IDs. */
426 std::for_each(filters
, filters_end
,
427 [device
](ALuint fid
) -> void
429 ALfilter
*filter
{fid
? LookupFilter(device
, fid
) : nullptr};
430 if(filter
) FreeFilter(device
, filter
);
436 AL_API ALboolean AL_APIENTRY
alIsFilter(ALuint filter
)
438 ContextRef context
{GetContextRef()};
441 ALCdevice
*device
{context
->Device
};
442 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
443 if(!filter
|| LookupFilter(device
, filter
))
450 AL_API ALvoid AL_APIENTRY
alFilteri(ALuint filter
, ALenum param
, ALint value
)
452 ContextRef context
{GetContextRef()};
453 if(UNLIKELY(!context
)) return;
455 ALCdevice
*device
{context
->Device
};
456 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
458 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
459 if(UNLIKELY(!alfilt
))
460 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
463 if(param
== AL_FILTER_TYPE
)
465 if(value
== AL_FILTER_NULL
|| value
== AL_FILTER_LOWPASS
||
466 value
== AL_FILTER_HIGHPASS
|| value
== AL_FILTER_BANDPASS
)
467 InitFilterParams(alfilt
, value
);
469 alSetError(context
.get(), AL_INVALID_VALUE
, "Invalid filter type 0x%04x", value
);
473 /* Call the appropriate handler */
474 ALfilter_setParami(alfilt
, context
.get(), param
, value
);
479 AL_API ALvoid AL_APIENTRY
alFilteriv(ALuint filter
, ALenum param
, const ALint
*values
)
484 alFilteri(filter
, param
, values
[0]);
488 ContextRef context
{GetContextRef()};
489 if(UNLIKELY(!context
)) return;
491 ALCdevice
*device
{context
->Device
};
492 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
494 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
495 if(UNLIKELY(!alfilt
))
496 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
499 /* Call the appropriate handler */
500 ALfilter_setParamiv(alfilt
, context
.get(), param
, values
);
504 AL_API ALvoid AL_APIENTRY
alFilterf(ALuint filter
, ALenum param
, ALfloat value
)
506 ContextRef context
{GetContextRef()};
507 if(UNLIKELY(!context
)) return;
509 ALCdevice
*device
{context
->Device
};
510 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
512 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
513 if(UNLIKELY(!alfilt
))
514 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
517 /* Call the appropriate handler */
518 ALfilter_setParamf(alfilt
, context
.get(), param
, value
);
522 AL_API ALvoid AL_APIENTRY
alFilterfv(ALuint filter
, ALenum param
, const ALfloat
*values
)
524 ContextRef context
{GetContextRef()};
525 if(UNLIKELY(!context
)) return;
527 ALCdevice
*device
{context
->Device
};
528 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
530 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
531 if(UNLIKELY(!alfilt
))
532 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
535 /* Call the appropriate handler */
536 ALfilter_setParamfv(alfilt
, context
.get(), param
, values
);
540 AL_API ALvoid AL_APIENTRY
alGetFilteri(ALuint filter
, ALenum param
, ALint
*value
)
542 ContextRef context
{GetContextRef()};
543 if(UNLIKELY(!context
)) return;
545 ALCdevice
*device
{context
->Device
};
546 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
548 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
549 if(UNLIKELY(!alfilt
))
550 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
553 if(param
== AL_FILTER_TYPE
)
554 *value
= alfilt
->type
;
557 /* Call the appropriate handler */
558 ALfilter_getParami(alfilt
, context
.get(), param
, value
);
563 AL_API ALvoid AL_APIENTRY
alGetFilteriv(ALuint filter
, ALenum param
, ALint
*values
)
568 alGetFilteri(filter
, param
, values
);
572 ContextRef context
{GetContextRef()};
573 if(UNLIKELY(!context
)) return;
575 ALCdevice
*device
{context
->Device
};
576 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
578 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
579 if(UNLIKELY(!alfilt
))
580 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
583 /* Call the appropriate handler */
584 ALfilter_getParamiv(alfilt
, context
.get(), param
, values
);
588 AL_API ALvoid AL_APIENTRY
alGetFilterf(ALuint filter
, ALenum param
, ALfloat
*value
)
590 ContextRef context
{GetContextRef()};
591 if(UNLIKELY(!context
)) return;
593 ALCdevice
*device
{context
->Device
};
594 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
596 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
597 if(UNLIKELY(!alfilt
))
598 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
601 /* Call the appropriate handler */
602 ALfilter_getParamf(alfilt
, context
.get(), param
, value
);
606 AL_API ALvoid AL_APIENTRY
alGetFilterfv(ALuint filter
, ALenum param
, ALfloat
*values
)
608 ContextRef context
{GetContextRef()};
609 if(UNLIKELY(!context
)) return;
611 ALCdevice
*device
{context
->Device
};
612 std::lock_guard
<almtx_t
> _
{device
->FilterLock
};
614 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
615 if(UNLIKELY(!alfilt
))
616 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
619 /* Call the appropriate handler */
620 ALfilter_getParamfv(alfilt
, context
.get(), param
, values
);
625 void ReleaseALFilters(ALCdevice
*device
)
628 for(auto &sublist
: device
->FilterList
)
630 ALuint64 usemask
= ~sublist
.FreeMask
;
633 ALsizei idx
= CTZ64(usemask
);
634 ALfilter
*filter
= sublist
.Filters
+ idx
;
639 usemask
&= ~(U64(1) << idx
);
641 sublist
.FreeMask
= ~usemask
;
644 WARN("(%p) Deleted " SZFMT
" Filter%s\n", device
, leftover
, (leftover
==1)?"":"s");