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 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
274 auto sublist
= std::find_if(device
->FilterList
.begin(), device
->FilterList
.end(),
275 [](const FilterSubList
&entry
) noexcept
-> bool
276 { return entry
.FreeMask
!= 0; }
279 auto lidx
= std::distance(device
->FilterList
.begin(), sublist
);
280 ALfilter
*filter
{nullptr};
282 if(LIKELY(sublist
!= device
->FilterList
.end()))
284 slidx
= CTZ64(sublist
->FreeMask
);
285 filter
= sublist
->Filters
+ slidx
;
289 /* Don't allocate so many list entries that the 32-bit ID could
292 if(UNLIKELY(device
->FilterList
.size() >= 1<<25))
294 alSetError(context
, AL_OUT_OF_MEMORY
, "Too many filters allocated");
297 device
->FilterList
.emplace_back();
298 sublist
= device
->FilterList
.end() - 1;
299 sublist
->FreeMask
= ~U64(0);
300 sublist
->Filters
= static_cast<ALfilter
*>(al_calloc(16, sizeof(ALfilter
)*64));
301 if(UNLIKELY(!sublist
->Filters
))
303 device
->FilterList
.pop_back();
304 alSetError(context
, AL_OUT_OF_MEMORY
, "Failed to allocate filter batch");
309 filter
= sublist
->Filters
+ slidx
;
312 filter
= new (filter
) ALfilter
{};
313 InitFilterParams(filter
, AL_FILTER_NULL
);
315 /* Add 1 to avoid filter ID 0. */
316 filter
->id
= ((lidx
<<6) | slidx
) + 1;
318 sublist
->FreeMask
&= ~(U64(1)<<slidx
);
323 void FreeFilter(ALCdevice
*device
, ALfilter
*filter
)
325 ALuint id
= filter
->id
- 1;
326 ALsizei lidx
= id
>> 6;
327 ALsizei slidx
= id
& 0x3f;
331 device
->FilterList
[lidx
].FreeMask
|= U64(1) << slidx
;
335 inline ALfilter
*LookupFilter(ALCdevice
*device
, ALuint id
)
337 ALuint lidx
= (id
-1) >> 6;
338 ALsizei slidx
= (id
-1) & 0x3f;
340 if(UNLIKELY(lidx
>= device
->FilterList
.size()))
342 FilterSubList
&sublist
= device
->FilterList
[lidx
];
343 if(UNLIKELY(sublist
.FreeMask
& (U64(1)<<slidx
)))
345 return sublist
.Filters
+ slidx
;
350 AL_API ALvoid AL_APIENTRY
alGenFilters(ALsizei n
, ALuint
*filters
)
352 ContextRef context
{GetContextRef()};
353 if(UNLIKELY(!context
)) return;
357 alSetError(context
.get(), AL_INVALID_VALUE
, "Generating %d filters", n
);
363 /* Special handling for the easy and normal case. */
364 ALfilter
*filter
= AllocFilter(context
.get());
365 if(filter
) filters
[0] = filter
->id
;
369 /* Store the allocated buffer IDs in a separate local list, to avoid
370 * modifying the user storage in case of failure.
372 al::vector
<ALuint
> ids
;
375 ALfilter
*filter
= AllocFilter(context
.get());
378 alDeleteFilters(ids
.size(), ids
.data());
382 ids
.emplace_back(filter
->id
);
384 std::copy(ids
.begin(), ids
.end(), filters
);
388 AL_API ALvoid AL_APIENTRY
alDeleteFilters(ALsizei n
, const ALuint
*filters
)
390 ContextRef context
{GetContextRef()};
391 if(UNLIKELY(!context
)) return;
395 alSetError(context
.get(), AL_INVALID_VALUE
, "Deleting %d filters", n
);
401 ALCdevice
*device
{context
->Device
};
402 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
404 /* First try to find any filters that are invalid. */
405 const ALuint
*filters_end
= filters
+ n
;
406 auto invflt
= std::find_if(filters
, filters_end
,
407 [device
, &context
](ALuint fid
) -> bool
409 if(!fid
) return false;
410 ALfilter
*filter
{LookupFilter(device
, fid
)};
411 if(UNLIKELY(!filter
))
413 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", fid
);
419 if(LIKELY(invflt
== filters_end
))
421 /* All good. Delete non-0 filter IDs. */
422 std::for_each(filters
, filters_end
,
423 [device
](ALuint fid
) -> void
425 ALfilter
*filter
{fid
? LookupFilter(device
, fid
) : nullptr};
426 if(filter
) FreeFilter(device
, filter
);
432 AL_API ALboolean AL_APIENTRY
alIsFilter(ALuint filter
)
434 ContextRef context
{GetContextRef()};
437 ALCdevice
*device
{context
->Device
};
438 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
439 if(!filter
|| LookupFilter(device
, filter
))
446 AL_API ALvoid AL_APIENTRY
alFilteri(ALuint filter
, ALenum param
, ALint value
)
448 ContextRef context
{GetContextRef()};
449 if(UNLIKELY(!context
)) return;
451 ALCdevice
*device
{context
->Device
};
452 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
454 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
455 if(UNLIKELY(!alfilt
))
456 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
459 if(param
== AL_FILTER_TYPE
)
461 if(value
== AL_FILTER_NULL
|| value
== AL_FILTER_LOWPASS
||
462 value
== AL_FILTER_HIGHPASS
|| value
== AL_FILTER_BANDPASS
)
463 InitFilterParams(alfilt
, value
);
465 alSetError(context
.get(), AL_INVALID_VALUE
, "Invalid filter type 0x%04x", value
);
469 /* Call the appropriate handler */
470 ALfilter_setParami(alfilt
, context
.get(), param
, value
);
475 AL_API ALvoid AL_APIENTRY
alFilteriv(ALuint filter
, ALenum param
, const ALint
*values
)
480 alFilteri(filter
, param
, values
[0]);
484 ContextRef context
{GetContextRef()};
485 if(UNLIKELY(!context
)) return;
487 ALCdevice
*device
{context
->Device
};
488 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
490 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
491 if(UNLIKELY(!alfilt
))
492 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
495 /* Call the appropriate handler */
496 ALfilter_setParamiv(alfilt
, context
.get(), param
, values
);
500 AL_API ALvoid AL_APIENTRY
alFilterf(ALuint filter
, ALenum param
, ALfloat value
)
502 ContextRef context
{GetContextRef()};
503 if(UNLIKELY(!context
)) return;
505 ALCdevice
*device
{context
->Device
};
506 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
508 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
509 if(UNLIKELY(!alfilt
))
510 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
513 /* Call the appropriate handler */
514 ALfilter_setParamf(alfilt
, context
.get(), param
, value
);
518 AL_API ALvoid AL_APIENTRY
alFilterfv(ALuint filter
, ALenum param
, const ALfloat
*values
)
520 ContextRef context
{GetContextRef()};
521 if(UNLIKELY(!context
)) return;
523 ALCdevice
*device
{context
->Device
};
524 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
526 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
527 if(UNLIKELY(!alfilt
))
528 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
531 /* Call the appropriate handler */
532 ALfilter_setParamfv(alfilt
, context
.get(), param
, values
);
536 AL_API ALvoid AL_APIENTRY
alGetFilteri(ALuint filter
, ALenum param
, ALint
*value
)
538 ContextRef context
{GetContextRef()};
539 if(UNLIKELY(!context
)) return;
541 ALCdevice
*device
{context
->Device
};
542 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
544 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
545 if(UNLIKELY(!alfilt
))
546 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
549 if(param
== AL_FILTER_TYPE
)
550 *value
= alfilt
->type
;
553 /* Call the appropriate handler */
554 ALfilter_getParami(alfilt
, context
.get(), param
, value
);
559 AL_API ALvoid AL_APIENTRY
alGetFilteriv(ALuint filter
, ALenum param
, ALint
*values
)
564 alGetFilteri(filter
, param
, values
);
568 ContextRef context
{GetContextRef()};
569 if(UNLIKELY(!context
)) return;
571 ALCdevice
*device
{context
->Device
};
572 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
574 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
575 if(UNLIKELY(!alfilt
))
576 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
579 /* Call the appropriate handler */
580 ALfilter_getParamiv(alfilt
, context
.get(), param
, values
);
584 AL_API ALvoid AL_APIENTRY
alGetFilterf(ALuint filter
, ALenum param
, ALfloat
*value
)
586 ContextRef context
{GetContextRef()};
587 if(UNLIKELY(!context
)) return;
589 ALCdevice
*device
{context
->Device
};
590 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
592 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
593 if(UNLIKELY(!alfilt
))
594 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
597 /* Call the appropriate handler */
598 ALfilter_getParamf(alfilt
, context
.get(), param
, value
);
602 AL_API ALvoid AL_APIENTRY
alGetFilterfv(ALuint filter
, ALenum param
, ALfloat
*values
)
604 ContextRef context
{GetContextRef()};
605 if(UNLIKELY(!context
)) return;
607 ALCdevice
*device
{context
->Device
};
608 std::lock_guard
<std::mutex
> _
{device
->FilterLock
};
610 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
611 if(UNLIKELY(!alfilt
))
612 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
615 /* Call the appropriate handler */
616 ALfilter_getParamfv(alfilt
, context
.get(), param
, values
);
621 FilterSubList::~FilterSubList()
623 ALuint64 usemask
= ~FreeMask
;
626 ALsizei idx
= CTZ64(usemask
);
627 Filters
[idx
].~ALfilter();
628 usemask
&= ~(U64(1) << idx
);