Clean up some code formatting in the pitch shifter source
[openal-soft.git] / OpenAL32 / alFilter.c
blob08f66d26d484a2e252522bfc585fb3b59ea4aa6c
1 /**
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
21 #include "config.h"
23 #include <stdlib.h>
25 #include "alMain.h"
26 #include "alu.h"
27 #include "alFilter.h"
28 #include "alError.h"
31 extern inline void LockFilterList(ALCdevice *device);
32 extern inline void UnlockFilterList(ALCdevice *device);
33 extern inline void ALfilterState_clear(ALfilterState *filter);
34 extern inline void ALfilterState_copyParams(ALfilterState *restrict dst, const ALfilterState *restrict src);
35 extern inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *restrict src, ALsizei numsamples);
36 extern inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope);
37 extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat f0norm, ALfloat bandwidth);
39 static ALfilter *AllocFilter(ALCcontext *context);
40 static void FreeFilter(ALCdevice *device, ALfilter *filter);
41 static void InitFilterParams(ALfilter *filter, ALenum type);
43 static inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
45 FilterSubList *sublist;
46 ALuint lidx = (id-1) >> 6;
47 ALsizei slidx = (id-1) & 0x3f;
49 if(UNLIKELY(lidx >= VECTOR_SIZE(device->FilterList)))
50 return NULL;
51 sublist = &VECTOR_ELEM(device->FilterList, lidx);
52 if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
53 return NULL;
54 return sublist->Filters + slidx;
58 AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
60 ALCcontext *context;
61 ALsizei cur = 0;
63 context = GetContextRef();
64 if(!context) return;
66 if(!(n >= 0))
67 alSetError(context, AL_INVALID_VALUE, "Generating %d filters", n);
68 else for(cur = 0;cur < n;cur++)
70 ALfilter *filter = AllocFilter(context);
71 if(!filter)
73 alDeleteFilters(cur, filters);
74 break;
77 filters[cur] = filter->id;
80 ALCcontext_DecRef(context);
83 AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
85 ALCdevice *device;
86 ALCcontext *context;
87 ALfilter *filter;
88 ALsizei i;
90 context = GetContextRef();
91 if(!context) return;
93 device = context->Device;
94 LockFilterList(device);
95 if(!(n >= 0))
96 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d filters", n);
97 for(i = 0;i < n;i++)
99 if(filters[i] && LookupFilter(device, filters[i]) == NULL)
100 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid filter ID %u", filters[i]);
102 for(i = 0;i < n;i++)
104 if((filter=LookupFilter(device, filters[i])) != NULL)
105 FreeFilter(device, filter);
108 done:
109 UnlockFilterList(device);
110 ALCcontext_DecRef(context);
113 AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
115 ALCcontext *Context;
116 ALboolean result;
118 Context = GetContextRef();
119 if(!Context) return AL_FALSE;
121 LockFilterList(Context->Device);
122 result = ((!filter || LookupFilter(Context->Device, filter)) ?
123 AL_TRUE : AL_FALSE);
124 UnlockFilterList(Context->Device);
126 ALCcontext_DecRef(Context);
128 return result;
131 AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
133 ALCcontext *Context;
134 ALCdevice *Device;
135 ALfilter *ALFilter;
137 Context = GetContextRef();
138 if(!Context) return;
140 Device = Context->Device;
141 LockFilterList(Device);
142 if((ALFilter=LookupFilter(Device, filter)) == NULL)
143 alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
144 else
146 if(param == AL_FILTER_TYPE)
148 if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS ||
149 value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS)
150 InitFilterParams(ALFilter, value);
151 else
152 alSetError(Context, AL_INVALID_VALUE, "Invalid filter type 0x%04x", value);
154 else
156 /* Call the appropriate handler */
157 ALfilter_setParami(ALFilter, Context, param, value);
160 UnlockFilterList(Device);
162 ALCcontext_DecRef(Context);
165 AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values)
167 ALCcontext *Context;
168 ALCdevice *Device;
169 ALfilter *ALFilter;
171 switch(param)
173 case AL_FILTER_TYPE:
174 alFilteri(filter, param, values[0]);
175 return;
178 Context = GetContextRef();
179 if(!Context) return;
181 Device = Context->Device;
182 LockFilterList(Device);
183 if((ALFilter=LookupFilter(Device, filter)) == NULL)
184 alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
185 else
187 /* Call the appropriate handler */
188 ALfilter_setParamiv(ALFilter, Context, param, values);
190 UnlockFilterList(Device);
192 ALCcontext_DecRef(Context);
195 AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
197 ALCcontext *Context;
198 ALCdevice *Device;
199 ALfilter *ALFilter;
201 Context = GetContextRef();
202 if(!Context) return;
204 Device = Context->Device;
205 LockFilterList(Device);
206 if((ALFilter=LookupFilter(Device, filter)) == NULL)
207 alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
208 else
210 /* Call the appropriate handler */
211 ALfilter_setParamf(ALFilter, Context, param, value);
213 UnlockFilterList(Device);
215 ALCcontext_DecRef(Context);
218 AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values)
220 ALCcontext *Context;
221 ALCdevice *Device;
222 ALfilter *ALFilter;
224 Context = GetContextRef();
225 if(!Context) return;
227 Device = Context->Device;
228 LockFilterList(Device);
229 if((ALFilter=LookupFilter(Device, filter)) == NULL)
230 alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
231 else
233 /* Call the appropriate handler */
234 ALfilter_setParamfv(ALFilter, Context, param, values);
236 UnlockFilterList(Device);
238 ALCcontext_DecRef(Context);
241 AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
243 ALCcontext *Context;
244 ALCdevice *Device;
245 ALfilter *ALFilter;
247 Context = GetContextRef();
248 if(!Context) return;
250 Device = Context->Device;
251 LockFilterList(Device);
252 if((ALFilter=LookupFilter(Device, filter)) == NULL)
253 alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
254 else
256 if(param == AL_FILTER_TYPE)
257 *value = ALFilter->type;
258 else
260 /* Call the appropriate handler */
261 ALfilter_getParami(ALFilter, Context, param, value);
264 UnlockFilterList(Device);
266 ALCcontext_DecRef(Context);
269 AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values)
271 ALCcontext *Context;
272 ALCdevice *Device;
273 ALfilter *ALFilter;
275 switch(param)
277 case AL_FILTER_TYPE:
278 alGetFilteri(filter, param, values);
279 return;
282 Context = GetContextRef();
283 if(!Context) return;
285 Device = Context->Device;
286 LockFilterList(Device);
287 if((ALFilter=LookupFilter(Device, filter)) == NULL)
288 alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
289 else
291 /* Call the appropriate handler */
292 ALfilter_getParamiv(ALFilter, Context, param, values);
294 UnlockFilterList(Device);
296 ALCcontext_DecRef(Context);
299 AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value)
301 ALCcontext *Context;
302 ALCdevice *Device;
303 ALfilter *ALFilter;
305 Context = GetContextRef();
306 if(!Context) return;
308 Device = Context->Device;
309 LockFilterList(Device);
310 if((ALFilter=LookupFilter(Device, filter)) == NULL)
311 alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
312 else
314 /* Call the appropriate handler */
315 ALfilter_getParamf(ALFilter, Context, param, value);
317 UnlockFilterList(Device);
319 ALCcontext_DecRef(Context);
322 AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values)
324 ALCcontext *Context;
325 ALCdevice *Device;
326 ALfilter *ALFilter;
328 Context = GetContextRef();
329 if(!Context) return;
331 Device = Context->Device;
332 LockFilterList(Device);
333 if((ALFilter=LookupFilter(Device, filter)) == NULL)
334 alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
335 else
337 /* Call the appropriate handler */
338 ALfilter_getParamfv(ALFilter, Context, param, values);
340 UnlockFilterList(Device);
342 ALCcontext_DecRef(Context);
346 void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat f0norm, ALfloat rcpQ)
348 ALfloat alpha, sqrtgain_alpha_2;
349 ALfloat w0, sin_w0, cos_w0;
350 ALfloat a[3] = { 1.0f, 0.0f, 0.0f };
351 ALfloat b[3] = { 1.0f, 0.0f, 0.0f };
353 // Limit gain to -100dB
354 assert(gain > 0.00001f);
356 w0 = F_TAU * f0norm;
357 sin_w0 = sinf(w0);
358 cos_w0 = cosf(w0);
359 alpha = sin_w0/2.0f * rcpQ;
361 /* Calculate filter coefficients depending on filter type */
362 switch(type)
364 case ALfilterType_HighShelf:
365 sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
366 b[0] = gain*((gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
367 b[1] = -2.0f*gain*((gain-1.0f) + (gain+1.0f)*cos_w0 );
368 b[2] = gain*((gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
369 a[0] = (gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2;
370 a[1] = 2.0f* ((gain-1.0f) - (gain+1.0f)*cos_w0 );
371 a[2] = (gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
372 break;
373 case ALfilterType_LowShelf:
374 sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
375 b[0] = gain*((gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
376 b[1] = 2.0f*gain*((gain-1.0f) - (gain+1.0f)*cos_w0 );
377 b[2] = gain*((gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
378 a[0] = (gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2;
379 a[1] = -2.0f* ((gain-1.0f) + (gain+1.0f)*cos_w0 );
380 a[2] = (gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
381 break;
382 case ALfilterType_Peaking:
383 gain = sqrtf(gain);
384 b[0] = 1.0f + alpha * gain;
385 b[1] = -2.0f * cos_w0;
386 b[2] = 1.0f - alpha * gain;
387 a[0] = 1.0f + alpha / gain;
388 a[1] = -2.0f * cos_w0;
389 a[2] = 1.0f - alpha / gain;
390 break;
392 case ALfilterType_LowPass:
393 b[0] = (1.0f - cos_w0) / 2.0f;
394 b[1] = 1.0f - cos_w0;
395 b[2] = (1.0f - cos_w0) / 2.0f;
396 a[0] = 1.0f + alpha;
397 a[1] = -2.0f * cos_w0;
398 a[2] = 1.0f - alpha;
399 break;
400 case ALfilterType_HighPass:
401 b[0] = (1.0f + cos_w0) / 2.0f;
402 b[1] = -(1.0f + cos_w0);
403 b[2] = (1.0f + cos_w0) / 2.0f;
404 a[0] = 1.0f + alpha;
405 a[1] = -2.0f * cos_w0;
406 a[2] = 1.0f - alpha;
407 break;
408 case ALfilterType_BandPass:
409 b[0] = alpha;
410 b[1] = 0;
411 b[2] = -alpha;
412 a[0] = 1.0f + alpha;
413 a[1] = -2.0f * cos_w0;
414 a[2] = 1.0f - alpha;
415 break;
418 filter->a1 = a[1] / a[0];
419 filter->a2 = a[2] / a[0];
420 filter->b0 = b[0] / a[0];
421 filter->b1 = b[1] / a[0];
422 filter->b2 = b[2] / a[0];
426 static void ALlowpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
427 { alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param); }
428 static void ALlowpass_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
429 { alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer-vector property 0x%04x", param); }
430 static void ALlowpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
432 switch(param)
434 case AL_LOWPASS_GAIN:
435 if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN))
436 SETERR_RETURN(context, AL_INVALID_VALUE,, "Low-pass gain %f out of range", val);
437 filter->Gain = val;
438 break;
440 case AL_LOWPASS_GAINHF:
441 if(!(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF))
442 SETERR_RETURN(context, AL_INVALID_VALUE,, "Low-pass gainhf %f out of range", val);
443 filter->GainHF = val;
444 break;
446 default:
447 alSetError(context, AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param);
450 static void ALlowpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
451 { ALlowpass_setParamf(filter, context, param, vals[0]); }
453 static void ALlowpass_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val))
454 { alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param); }
455 static void ALlowpass_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
456 { alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer-vector property 0x%04x", param); }
457 static void ALlowpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
459 switch(param)
461 case AL_LOWPASS_GAIN:
462 *val = filter->Gain;
463 break;
465 case AL_LOWPASS_GAINHF:
466 *val = filter->GainHF;
467 break;
469 default:
470 alSetError(context, AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param);
473 static void ALlowpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
474 { ALlowpass_getParamf(filter, context, param, vals); }
476 DEFINE_ALFILTER_VTABLE(ALlowpass);
479 static void ALhighpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
480 { alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param); }
481 static void ALhighpass_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
482 { alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer-vector property 0x%04x", param); }
483 static void ALhighpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
485 switch(param)
487 case AL_HIGHPASS_GAIN:
488 if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN))
489 SETERR_RETURN(context, AL_INVALID_VALUE,, "High-pass gain out of range");
490 filter->Gain = val;
491 break;
493 case AL_HIGHPASS_GAINLF:
494 if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF))
495 SETERR_RETURN(context, AL_INVALID_VALUE,, "High-pass gainlf out of range");
496 filter->GainLF = val;
497 break;
499 default:
500 alSetError(context, AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param);
503 static void ALhighpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
504 { ALhighpass_setParamf(filter, context, param, vals[0]); }
506 static void ALhighpass_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val))
507 { alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param); }
508 static void ALhighpass_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
509 { alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer-vector property 0x%04x", param); }
510 static void ALhighpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
512 switch(param)
514 case AL_HIGHPASS_GAIN:
515 *val = filter->Gain;
516 break;
518 case AL_HIGHPASS_GAINLF:
519 *val = filter->GainLF;
520 break;
522 default:
523 alSetError(context, AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param);
526 static void ALhighpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
527 { ALhighpass_getParamf(filter, context, param, vals); }
529 DEFINE_ALFILTER_VTABLE(ALhighpass);
532 static void ALbandpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
533 { alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param); }
534 static void ALbandpass_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
535 { alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer-vector property 0x%04x", param); }
536 static void ALbandpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
538 switch(param)
540 case AL_BANDPASS_GAIN:
541 if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN))
542 SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gain out of range");
543 filter->Gain = val;
544 break;
546 case AL_BANDPASS_GAINHF:
547 if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF))
548 SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gainhf out of range");
549 filter->GainHF = val;
550 break;
552 case AL_BANDPASS_GAINLF:
553 if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF))
554 SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gainlf out of range");
555 filter->GainLF = val;
556 break;
558 default:
559 alSetError(context, AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param);
562 static void ALbandpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
563 { ALbandpass_setParamf(filter, context, param, vals[0]); }
565 static void ALbandpass_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val))
566 { alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param); }
567 static void ALbandpass_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
568 { alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer-vector property 0x%04x", param); }
569 static void ALbandpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
571 switch(param)
573 case AL_BANDPASS_GAIN:
574 *val = filter->Gain;
575 break;
577 case AL_BANDPASS_GAINHF:
578 *val = filter->GainHF;
579 break;
581 case AL_BANDPASS_GAINLF:
582 *val = filter->GainLF;
583 break;
585 default:
586 alSetError(context, AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param);
589 static void ALbandpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
590 { ALbandpass_getParamf(filter, context, param, vals); }
592 DEFINE_ALFILTER_VTABLE(ALbandpass);
595 static void ALnullfilter_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
596 { alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
597 static void ALnullfilter_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
598 { alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
599 static void ALnullfilter_setParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALfloat UNUSED(val))
600 { alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
601 static void ALnullfilter_setParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALfloat *UNUSED(vals))
602 { alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
604 static void ALnullfilter_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val))
605 { alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
606 static void ALnullfilter_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
607 { alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
608 static void ALnullfilter_getParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALfloat *UNUSED(val))
609 { alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
610 static void ALnullfilter_getParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALfloat *UNUSED(vals))
611 { alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
613 DEFINE_ALFILTER_VTABLE(ALnullfilter);
616 static ALfilter *AllocFilter(ALCcontext *context)
618 ALCdevice *device = context->Device;
619 FilterSubList *sublist, *subend;
620 ALfilter *filter = NULL;
621 ALsizei lidx = 0;
622 ALsizei slidx;
624 almtx_lock(&device->FilterLock);
625 sublist = VECTOR_BEGIN(device->FilterList);
626 subend = VECTOR_END(device->FilterList);
627 for(;sublist != subend;++sublist)
629 if(sublist->FreeMask)
631 slidx = CTZ64(sublist->FreeMask);
632 filter = sublist->Filters + slidx;
633 break;
635 ++lidx;
637 if(UNLIKELY(!filter))
639 const FilterSubList empty_sublist = { 0, NULL };
640 /* Don't allocate so many list entries that the 32-bit ID could
641 * overflow...
643 if(UNLIKELY(VECTOR_SIZE(device->FilterList) >= 1<<25))
645 almtx_unlock(&device->FilterLock);
646 alSetError(context, AL_OUT_OF_MEMORY, "Too many filters allocated");
647 return NULL;
649 lidx = (ALsizei)VECTOR_SIZE(device->FilterList);
650 VECTOR_PUSH_BACK(device->FilterList, empty_sublist);
651 sublist = &VECTOR_BACK(device->FilterList);
652 sublist->FreeMask = ~U64(0);
653 sublist->Filters = al_calloc(16, sizeof(ALfilter)*64);
654 if(UNLIKELY(!sublist->Filters))
656 VECTOR_POP_BACK(device->FilterList);
657 almtx_unlock(&device->FilterLock);
658 alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate filter batch");
659 return NULL;
662 slidx = 0;
663 filter = sublist->Filters + slidx;
666 memset(filter, 0, sizeof(*filter));
667 InitFilterParams(filter, AL_FILTER_NULL);
669 /* Add 1 to avoid filter ID 0. */
670 filter->id = ((lidx<<6) | slidx) + 1;
672 sublist->FreeMask &= ~(U64(1)<<slidx);
673 almtx_unlock(&device->FilterLock);
675 return filter;
678 static void FreeFilter(ALCdevice *device, ALfilter *filter)
680 ALuint id = filter->id - 1;
681 ALsizei lidx = id >> 6;
682 ALsizei slidx = id & 0x3f;
684 memset(filter, 0, sizeof(*filter));
686 VECTOR_ELEM(device->FilterList, lidx).FreeMask |= U64(1) << slidx;
689 void ReleaseALFilters(ALCdevice *device)
691 FilterSubList *sublist = VECTOR_BEGIN(device->FilterList);
692 FilterSubList *subend = VECTOR_END(device->FilterList);
693 size_t leftover = 0;
694 for(;sublist != subend;++sublist)
696 ALuint64 usemask = ~sublist->FreeMask;
697 while(usemask)
699 ALsizei idx = CTZ64(usemask);
700 ALfilter *filter = sublist->Filters + idx;
702 memset(filter, 0, sizeof(*filter));
703 ++leftover;
705 usemask &= ~(U64(1) << idx);
707 sublist->FreeMask = ~usemask;
709 if(leftover > 0)
710 WARN("(%p) Deleted "SZFMT" Filter%s\n", device, leftover, (leftover==1)?"":"s");
714 static void InitFilterParams(ALfilter *filter, ALenum type)
716 if(type == AL_FILTER_LOWPASS)
718 filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
719 filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
720 filter->HFReference = LOWPASSFREQREF;
721 filter->GainLF = 1.0f;
722 filter->LFReference = HIGHPASSFREQREF;
723 filter->vtab = &ALlowpass_vtable;
725 else if(type == AL_FILTER_HIGHPASS)
727 filter->Gain = AL_HIGHPASS_DEFAULT_GAIN;
728 filter->GainHF = 1.0f;
729 filter->HFReference = LOWPASSFREQREF;
730 filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF;
731 filter->LFReference = HIGHPASSFREQREF;
732 filter->vtab = &ALhighpass_vtable;
734 else if(type == AL_FILTER_BANDPASS)
736 filter->Gain = AL_BANDPASS_DEFAULT_GAIN;
737 filter->GainHF = AL_BANDPASS_DEFAULT_GAINHF;
738 filter->HFReference = LOWPASSFREQREF;
739 filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF;
740 filter->LFReference = HIGHPASSFREQREF;
741 filter->vtab = &ALbandpass_vtable;
743 else
745 filter->Gain = 1.0f;
746 filter->GainHF = 1.0f;
747 filter->HFReference = LOWPASSFREQREF;
748 filter->GainLF = 1.0f;
749 filter->LFReference = HIGHPASSFREQREF;
750 filter->vtab = &ALnullfilter_vtable;
752 filter->type = type;