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
33 #include <unordered_map>
41 #include "alc/context.h"
42 #include "alc/device.h"
44 #include "alnumeric.h"
46 #include "direct_defs.h"
48 #include "intrusive_ptr.h"
49 #include "opthelpers.h"
54 using SubListAllocator
= al::allocator
<std::array
<ALfilter
,64>>;
57 void InitFilterParams(ALfilter
*filter
, ALenum type
)
59 if(type
== AL_FILTER_LOWPASS
)
61 filter
->Gain
= AL_LOWPASS_DEFAULT_GAIN
;
62 filter
->GainHF
= AL_LOWPASS_DEFAULT_GAINHF
;
63 filter
->HFReference
= LowPassFreqRef
;
64 filter
->GainLF
= 1.0f
;
65 filter
->LFReference
= HighPassFreqRef
;
66 filter
->mTypeVariant
.emplace
<LowpassFilterTable
>();
68 else if(type
== AL_FILTER_HIGHPASS
)
70 filter
->Gain
= AL_HIGHPASS_DEFAULT_GAIN
;
71 filter
->GainHF
= 1.0f
;
72 filter
->HFReference
= LowPassFreqRef
;
73 filter
->GainLF
= AL_HIGHPASS_DEFAULT_GAINLF
;
74 filter
->LFReference
= HighPassFreqRef
;
75 filter
->mTypeVariant
.emplace
<HighpassFilterTable
>();
77 else if(type
== AL_FILTER_BANDPASS
)
79 filter
->Gain
= AL_BANDPASS_DEFAULT_GAIN
;
80 filter
->GainHF
= AL_BANDPASS_DEFAULT_GAINHF
;
81 filter
->HFReference
= LowPassFreqRef
;
82 filter
->GainLF
= AL_BANDPASS_DEFAULT_GAINLF
;
83 filter
->LFReference
= HighPassFreqRef
;
84 filter
->mTypeVariant
.emplace
<BandpassFilterTable
>();
89 filter
->GainHF
= 1.0f
;
90 filter
->HFReference
= LowPassFreqRef
;
91 filter
->GainLF
= 1.0f
;
92 filter
->LFReference
= HighPassFreqRef
;
93 filter
->mTypeVariant
.emplace
<NullFilterTable
>();
98 auto EnsureFilters(al::Device
*device
, size_t needed
) noexcept
-> bool
100 size_t count
{std::accumulate(device
->FilterList
.cbegin(), device
->FilterList
.cend(), 0_uz
,
101 [](size_t cur
, const FilterSubList
&sublist
) noexcept
-> size_t
102 { return cur
+ static_cast<ALuint
>(al::popcount(sublist
.FreeMask
)); })};
104 while(needed
> count
)
106 if(device
->FilterList
.size() >= 1<<25) UNLIKELY
109 FilterSubList sublist
{};
110 sublist
.FreeMask
= ~0_u64
;
111 sublist
.Filters
= SubListAllocator
{}.allocate(1);
112 device
->FilterList
.emplace_back(std::move(sublist
));
113 count
+= std::tuple_size_v
<SubListAllocator::value_type
>;
122 auto AllocFilter(al::Device
*device
) noexcept
-> ALfilter
*
124 auto sublist
= std::find_if(device
->FilterList
.begin(), device
->FilterList
.end(),
125 [](const FilterSubList
&entry
) noexcept
-> bool
126 { return entry
.FreeMask
!= 0; });
127 auto lidx
= static_cast<ALuint
>(std::distance(device
->FilterList
.begin(), sublist
));
128 auto slidx
= static_cast<ALuint
>(al::countr_zero(sublist
->FreeMask
));
131 ALfilter
*filter
{al::construct_at(al::to_address(sublist
->Filters
->begin() + slidx
))};
132 InitFilterParams(filter
, AL_FILTER_NULL
);
134 /* Add 1 to avoid filter ID 0. */
135 filter
->id
= ((lidx
<<6) | slidx
) + 1;
137 sublist
->FreeMask
&= ~(1_u64
<< slidx
);
142 void FreeFilter(al::Device
*device
, ALfilter
*filter
)
144 device
->mFilterNames
.erase(filter
->id
);
146 const ALuint id
{filter
->id
- 1};
147 const size_t lidx
{id
>> 6};
148 const ALuint slidx
{id
& 0x3f};
150 std::destroy_at(filter
);
152 device
->FilterList
[lidx
].FreeMask
|= 1_u64
<< slidx
;
156 auto LookupFilter(al::Device
*device
, ALuint id
) noexcept
-> ALfilter
*
158 const size_t lidx
{(id
-1) >> 6};
159 const ALuint slidx
{(id
-1) & 0x3f};
161 if(lidx
>= device
->FilterList
.size()) UNLIKELY
163 FilterSubList
&sublist
= device
->FilterList
[lidx
];
164 if(sublist
.FreeMask
& (1_u64
<< slidx
)) UNLIKELY
166 return al::to_address(sublist
.Filters
->begin() + slidx
);
171 /* Null filter parameter handlers */
173 void FilterTable
<NullFilterTable
>::setParami(ALfilter
*, ALenum param
, int)
174 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
}; }
176 void FilterTable
<NullFilterTable
>::setParamiv(ALfilter
*, ALenum param
, const int*)
177 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
}; }
179 void FilterTable
<NullFilterTable
>::setParamf(ALfilter
*, ALenum param
, float)
180 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
}; }
182 void FilterTable
<NullFilterTable
>::setParamfv(ALfilter
*, ALenum param
, const float*)
183 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
}; }
185 void FilterTable
<NullFilterTable
>::getParami(const ALfilter
*, ALenum param
, int*)
186 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
}; }
188 void FilterTable
<NullFilterTable
>::getParamiv(const ALfilter
*, ALenum param
, int*)
189 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
}; }
191 void FilterTable
<NullFilterTable
>::getParamf(const ALfilter
*, ALenum param
, float*)
192 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
}; }
194 void FilterTable
<NullFilterTable
>::getParamfv(const ALfilter
*, ALenum param
, float*)
195 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
}; }
197 /* Lowpass parameter handlers */
199 void FilterTable
<LowpassFilterTable
>::setParami(ALfilter
*, ALenum param
, int)
200 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid low-pass integer property 0x%04x", param
}; }
202 void FilterTable
<LowpassFilterTable
>::setParamiv(ALfilter
*filter
, ALenum param
, const int *values
)
203 { setParami(filter
, param
, *values
); }
205 void FilterTable
<LowpassFilterTable
>::setParamf(ALfilter
*filter
, ALenum param
, float val
)
209 case AL_LOWPASS_GAIN
:
210 if(!(val
>= AL_LOWPASS_MIN_GAIN
&& val
<= AL_LOWPASS_MAX_GAIN
))
211 throw al::context_error
{AL_INVALID_VALUE
, "Low-pass gain %f out of range", val
};
215 case AL_LOWPASS_GAINHF
:
216 if(!(val
>= AL_LOWPASS_MIN_GAINHF
&& val
<= AL_LOWPASS_MAX_GAINHF
))
217 throw al::context_error
{AL_INVALID_VALUE
, "Low-pass gainhf %f out of range", val
};
218 filter
->GainHF
= val
;
221 throw al::context_error
{AL_INVALID_ENUM
, "Invalid low-pass float property 0x%04x", param
};
224 void FilterTable
<LowpassFilterTable
>::setParamfv(ALfilter
*filter
, ALenum param
, const float *vals
)
225 { setParamf(filter
, param
, *vals
); }
227 void FilterTable
<LowpassFilterTable
>::getParami(const ALfilter
*, ALenum param
, int*)
228 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid low-pass integer property 0x%04x", param
}; }
230 void FilterTable
<LowpassFilterTable
>::getParamiv(const ALfilter
*filter
, ALenum param
, int *values
)
231 { getParami(filter
, param
, values
); }
233 void FilterTable
<LowpassFilterTable
>::getParamf(const ALfilter
*filter
, ALenum param
, float *val
)
237 case AL_LOWPASS_GAIN
: *val
= filter
->Gain
; return;
238 case AL_LOWPASS_GAINHF
: *val
= filter
->GainHF
; return;
240 throw al::context_error
{AL_INVALID_ENUM
, "Invalid low-pass float property 0x%04x", param
};
243 void FilterTable
<LowpassFilterTable
>::getParamfv(const ALfilter
*filter
, ALenum param
, float *vals
)
244 { getParamf(filter
, param
, vals
); }
246 /* Highpass parameter handlers */
248 void FilterTable
<HighpassFilterTable
>::setParami(ALfilter
*, ALenum param
, int)
249 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid high-pass integer property 0x%04x", param
}; }
251 void FilterTable
<HighpassFilterTable
>::setParamiv(ALfilter
*filter
, ALenum param
, const int *values
)
252 { setParami(filter
, param
, *values
); }
254 void FilterTable
<HighpassFilterTable
>::setParamf(ALfilter
*filter
, ALenum param
, float val
)
258 case AL_HIGHPASS_GAIN
:
259 if(!(val
>= AL_HIGHPASS_MIN_GAIN
&& val
<= AL_HIGHPASS_MAX_GAIN
))
260 throw al::context_error
{AL_INVALID_VALUE
, "High-pass gain %f out of range", val
};
264 case AL_HIGHPASS_GAINLF
:
265 if(!(val
>= AL_HIGHPASS_MIN_GAINLF
&& val
<= AL_HIGHPASS_MAX_GAINLF
))
266 throw al::context_error
{AL_INVALID_VALUE
, "High-pass gainlf %f out of range", val
};
267 filter
->GainLF
= val
;
270 throw al::context_error
{AL_INVALID_ENUM
, "Invalid high-pass float property 0x%04x", param
};
273 void FilterTable
<HighpassFilterTable
>::setParamfv(ALfilter
*filter
, ALenum param
, const float *vals
)
274 { setParamf(filter
, param
, *vals
); }
276 void FilterTable
<HighpassFilterTable
>::getParami(const ALfilter
*, ALenum param
, int*)
277 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid high-pass integer property 0x%04x", param
}; }
279 void FilterTable
<HighpassFilterTable
>::getParamiv(const ALfilter
*filter
, ALenum param
, int *values
)
280 { getParami(filter
, param
, values
); }
282 void FilterTable
<HighpassFilterTable
>::getParamf(const ALfilter
*filter
, ALenum param
, float *val
)
286 case AL_HIGHPASS_GAIN
: *val
= filter
->Gain
; return;
287 case AL_HIGHPASS_GAINLF
: *val
= filter
->GainLF
; return;
289 throw al::context_error
{AL_INVALID_ENUM
, "Invalid high-pass float property 0x%04x", param
};
292 void FilterTable
<HighpassFilterTable
>::getParamfv(const ALfilter
*filter
, ALenum param
, float *vals
)
293 { getParamf(filter
, param
, vals
); }
295 /* Bandpass parameter handlers */
297 void FilterTable
<BandpassFilterTable
>::setParami(ALfilter
*, ALenum param
, int)
298 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid band-pass integer property 0x%04x", param
}; }
300 void FilterTable
<BandpassFilterTable
>::setParamiv(ALfilter
*filter
, ALenum param
, const int *values
)
301 { setParami(filter
, param
, *values
); }
303 void FilterTable
<BandpassFilterTable
>::setParamf(ALfilter
*filter
, ALenum param
, float val
)
307 case AL_BANDPASS_GAIN
:
308 if(!(val
>= AL_BANDPASS_MIN_GAIN
&& val
<= AL_BANDPASS_MAX_GAIN
))
309 throw al::context_error
{AL_INVALID_VALUE
, "Band-pass gain %f out of range", val
};
313 case AL_BANDPASS_GAINHF
:
314 if(!(val
>= AL_BANDPASS_MIN_GAINHF
&& val
<= AL_BANDPASS_MAX_GAINHF
))
315 throw al::context_error
{AL_INVALID_VALUE
, "Band-pass gainhf %f out of range", val
};
316 filter
->GainHF
= val
;
319 case AL_BANDPASS_GAINLF
:
320 if(!(val
>= AL_BANDPASS_MIN_GAINLF
&& val
<= AL_BANDPASS_MAX_GAINLF
))
321 throw al::context_error
{AL_INVALID_VALUE
, "Band-pass gainlf %f out of range", val
};
322 filter
->GainLF
= val
;
325 throw al::context_error
{AL_INVALID_ENUM
, "Invalid band-pass float property 0x%04x", param
};
328 void FilterTable
<BandpassFilterTable
>::setParamfv(ALfilter
*filter
, ALenum param
, const float *vals
)
329 { setParamf(filter
, param
, *vals
); }
331 void FilterTable
<BandpassFilterTable
>::getParami(const ALfilter
*, ALenum param
, int*)
332 { throw al::context_error
{AL_INVALID_ENUM
, "Invalid band-pass integer property 0x%04x", param
}; }
334 void FilterTable
<BandpassFilterTable
>::getParamiv(const ALfilter
*filter
, ALenum param
, int *values
)
335 { getParami(filter
, param
, values
); }
337 void FilterTable
<BandpassFilterTable
>::getParamf(const ALfilter
*filter
, ALenum param
, float *val
)
341 case AL_BANDPASS_GAIN
: *val
= filter
->Gain
; return;
342 case AL_BANDPASS_GAINHF
: *val
= filter
->GainHF
; return;
343 case AL_BANDPASS_GAINLF
: *val
= filter
->GainLF
; return;
345 throw al::context_error
{AL_INVALID_ENUM
, "Invalid band-pass float property 0x%04x", param
};
348 void FilterTable
<BandpassFilterTable
>::getParamfv(const ALfilter
*filter
, ALenum param
, float *vals
)
349 { getParamf(filter
, param
, vals
); }
352 AL_API
DECL_FUNC2(void, alGenFilters
, ALsizei
,n
, ALuint
*,filters
)
353 FORCE_ALIGN
void AL_APIENTRY
alGenFiltersDirect(ALCcontext
*context
, ALsizei n
, ALuint
*filters
) noexcept
356 throw al::context_error
{AL_INVALID_VALUE
, "Generating %d filters", n
};
357 if(n
<= 0) UNLIKELY
return;
359 auto *device
= context
->mALDevice
.get();
360 auto filterlock
= std::lock_guard
{device
->FilterLock
};
362 const al::span fids
{filters
, static_cast<ALuint
>(n
)};
363 if(!EnsureFilters(device
, fids
.size()))
364 throw al::context_error
{AL_OUT_OF_MEMORY
, "Failed to allocate %d filter%s", n
,
365 (n
== 1) ? "" : "s"};
367 std::generate(fids
.begin(), fids
.end(), [device
]{ return AllocFilter(device
)->id
; });
369 catch(al::context_error
& e
) {
370 context
->setError(e
.errorCode(), "%s", e
.what());
373 AL_API
DECL_FUNC2(void, alDeleteFilters
, ALsizei
,n
, const ALuint
*,filters
)
374 FORCE_ALIGN
void AL_APIENTRY
alDeleteFiltersDirect(ALCcontext
*context
, ALsizei n
,
375 const ALuint
*filters
) noexcept
378 throw al::context_error
{AL_INVALID_VALUE
, "Deleting %d filters", n
};
379 if(n
<= 0) UNLIKELY
return;
381 auto *device
= context
->mALDevice
.get();
382 auto filterlock
= std::lock_guard
{device
->FilterLock
};
384 /* First try to find any filters that are invalid. */
385 auto validate_filter
= [device
](const ALuint fid
) -> bool
386 { return !fid
|| LookupFilter(device
, fid
) != nullptr; };
388 const al::span fids
{filters
, static_cast<ALuint
>(n
)};
389 auto invflt
= std::find_if_not(fids
.begin(), fids
.end(), validate_filter
);
390 if(invflt
!= fids
.end())
391 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", *invflt
};
393 /* All good. Delete non-0 filter IDs. */
394 auto delete_filter
= [device
](const ALuint fid
) -> void
396 if(ALfilter
*filter
{fid
? LookupFilter(device
, fid
) : nullptr})
397 FreeFilter(device
, filter
);
399 std::for_each(fids
.begin(), fids
.end(), delete_filter
);
401 catch(al::context_error
& e
) {
402 context
->setError(e
.errorCode(), "%s", e
.what());
405 AL_API
DECL_FUNC1(ALboolean
, alIsFilter
, ALuint
,filter
)
406 FORCE_ALIGN ALboolean AL_APIENTRY
alIsFilterDirect(ALCcontext
*context
, ALuint filter
) noexcept
408 auto *device
= context
->mALDevice
.get();
409 auto filterlock
= std::lock_guard
{device
->FilterLock
};
410 if(!filter
|| LookupFilter(device
, filter
))
416 AL_API
DECL_FUNC3(void, alFilteri
, ALuint
,filter
, ALenum
,param
, ALint
,value
)
417 FORCE_ALIGN
void AL_APIENTRY
alFilteriDirect(ALCcontext
*context
, ALuint filter
, ALenum param
,
418 ALint value
) noexcept
420 auto *device
= context
->mALDevice
.get();
421 auto filterlock
= std::lock_guard
{device
->FilterLock
};
423 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
425 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", filter
};
430 if(!(value
== AL_FILTER_NULL
|| value
== AL_FILTER_LOWPASS
431 || value
== AL_FILTER_HIGHPASS
|| value
== AL_FILTER_BANDPASS
))
432 throw al::context_error
{AL_INVALID_VALUE
, "Invalid filter type 0x%04x", value
};
433 InitFilterParams(alfilt
, value
);
437 /* Call the appropriate handler */
438 std::visit([alfilt
,param
,value
](auto&& thunk
){thunk
.setParami(alfilt
, param
, value
);},
439 alfilt
->mTypeVariant
);
441 catch(al::context_error
& e
) {
442 context
->setError(e
.errorCode(), "%s", e
.what());
445 AL_API
DECL_FUNC3(void, alFilteriv
, ALuint
,filter
, ALenum
,param
, const ALint
*,values
)
446 FORCE_ALIGN
void AL_APIENTRY
alFilterivDirect(ALCcontext
*context
, ALuint filter
, ALenum param
,
447 const ALint
*values
) noexcept
452 alFilteriDirect(context
, filter
, param
, *values
);
456 auto *device
= context
->mALDevice
.get();
457 auto filterlock
= std::lock_guard
{device
->FilterLock
};
459 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
461 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", filter
};
463 /* Call the appropriate handler */
464 std::visit([alfilt
,param
,values
](auto&& thunk
){thunk
.setParamiv(alfilt
, param
, values
);},
465 alfilt
->mTypeVariant
);
467 catch(al::context_error
& e
) {
468 context
->setError(e
.errorCode(), "%s", e
.what());
471 AL_API
DECL_FUNC3(void, alFilterf
, ALuint
,filter
, ALenum
,param
, ALfloat
,value
)
472 FORCE_ALIGN
void AL_APIENTRY
alFilterfDirect(ALCcontext
*context
, ALuint filter
, ALenum param
,
473 ALfloat value
) noexcept
475 auto *device
= context
->mALDevice
.get();
476 auto filterlock
= std::lock_guard
{device
->FilterLock
};
478 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
480 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", filter
};
482 /* Call the appropriate handler */
483 std::visit([alfilt
,param
,value
](auto&& thunk
){thunk
.setParamf(alfilt
, param
, value
);},
484 alfilt
->mTypeVariant
);
486 catch(al::context_error
& e
) {
487 context
->setError(e
.errorCode(), "%s", e
.what());
490 AL_API
DECL_FUNC3(void, alFilterfv
, ALuint
,filter
, ALenum
,param
, const ALfloat
*,values
)
491 FORCE_ALIGN
void AL_APIENTRY
alFilterfvDirect(ALCcontext
*context
, ALuint filter
, ALenum param
,
492 const ALfloat
*values
) noexcept
494 auto *device
= context
->mALDevice
.get();
495 auto filterlock
= std::lock_guard
{device
->FilterLock
};
497 ALfilter
*alfilt
{LookupFilter(device
, filter
)};
499 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", filter
};
501 /* Call the appropriate handler */
502 std::visit([alfilt
,param
,values
](auto&& thunk
){thunk
.setParamfv(alfilt
, param
, values
);},
503 alfilt
->mTypeVariant
);
505 catch(al::context_error
& e
) {
506 context
->setError(e
.errorCode(), "%s", e
.what());
509 AL_API
DECL_FUNC3(void, alGetFilteri
, ALuint
,filter
, ALenum
,param
, ALint
*,value
)
510 FORCE_ALIGN
void AL_APIENTRY
alGetFilteriDirect(ALCcontext
*context
, ALuint filter
, ALenum param
,
511 ALint
*value
) noexcept
513 auto *device
= context
->mALDevice
.get();
514 auto filterlock
= std::lock_guard
{device
->FilterLock
};
516 const ALfilter
*alfilt
{LookupFilter(device
, filter
)};
518 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", filter
};
523 *value
= alfilt
->type
;
527 /* Call the appropriate handler */
528 std::visit([alfilt
,param
,value
](auto&& thunk
){thunk
.getParami(alfilt
, param
, value
);},
529 alfilt
->mTypeVariant
);
531 catch(al::context_error
& e
) {
532 context
->setError(e
.errorCode(), "%s", e
.what());
535 AL_API
DECL_FUNC3(void, alGetFilteriv
, ALuint
,filter
, ALenum
,param
, ALint
*,values
)
536 FORCE_ALIGN
void AL_APIENTRY
alGetFilterivDirect(ALCcontext
*context
, ALuint filter
, ALenum param
,
537 ALint
*values
) noexcept
542 alGetFilteriDirect(context
, filter
, param
, values
);
546 auto *device
= context
->mALDevice
.get();
547 auto filterlock
= std::lock_guard
{device
->FilterLock
};
549 const ALfilter
*alfilt
{LookupFilter(device
, filter
)};
551 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", filter
};
553 /* Call the appropriate handler */
554 std::visit([alfilt
,param
,values
](auto&& thunk
){thunk
.getParamiv(alfilt
, param
, values
);},
555 alfilt
->mTypeVariant
);
557 catch(al::context_error
& e
) {
558 context
->setError(e
.errorCode(), "%s", e
.what());
561 AL_API
DECL_FUNC3(void, alGetFilterf
, ALuint
,filter
, ALenum
,param
, ALfloat
*,value
)
562 FORCE_ALIGN
void AL_APIENTRY
alGetFilterfDirect(ALCcontext
*context
, ALuint filter
, ALenum param
,
563 ALfloat
*value
) noexcept
565 auto *device
= context
->mALDevice
.get();
566 auto filterlock
= std::lock_guard
{device
->FilterLock
};
568 const ALfilter
*alfilt
{LookupFilter(device
, filter
)};
570 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", filter
};
572 /* Call the appropriate handler */
573 std::visit([alfilt
,param
,value
](auto&& thunk
){thunk
.getParamf(alfilt
, param
, value
);},
574 alfilt
->mTypeVariant
);
576 catch(al::context_error
& e
) {
577 context
->setError(e
.errorCode(), "%s", e
.what());
580 AL_API
DECL_FUNC3(void, alGetFilterfv
, ALuint
,filter
, ALenum
,param
, ALfloat
*,values
)
581 FORCE_ALIGN
void AL_APIENTRY
alGetFilterfvDirect(ALCcontext
*context
, ALuint filter
, ALenum param
,
582 ALfloat
*values
) noexcept
584 auto *device
= context
->mALDevice
.get();
585 auto filterlock
= std::lock_guard
{device
->FilterLock
};
587 const ALfilter
*alfilt
{LookupFilter(device
, filter
)};
589 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", filter
};
591 /* Call the appropriate handler */
592 std::visit([alfilt
,param
,values
](auto&& thunk
){thunk
.getParamfv(alfilt
, param
, values
);},
593 alfilt
->mTypeVariant
);
595 catch(al::context_error
& e
) {
596 context
->setError(e
.errorCode(), "%s", e
.what());
600 void ALfilter::SetName(ALCcontext
*context
, ALuint id
, std::string_view name
)
602 auto *device
= context
->mALDevice
.get();
603 auto filterlock
= std::lock_guard
{device
->FilterLock
};
605 auto filter
= LookupFilter(device
, id
);
607 throw al::context_error
{AL_INVALID_NAME
, "Invalid filter ID %u", id
};
609 device
->mFilterNames
.insert_or_assign(id
, name
);
613 FilterSubList::~FilterSubList()
618 uint64_t usemask
{~FreeMask
};
621 const int idx
{al::countr_zero(usemask
)};
622 std::destroy_at(al::to_address(Filters
->begin() + idx
));
623 usemask
&= ~(1_u64
<< idx
);
626 SubListAllocator
{}.deallocate(Filters
, 1);