Remove an unnecessary conditional
[openal-soft.git] / OpenAL32 / alFilter.c
blob692109f58a6bb9f50334a9e99e2dbb53a749abb2
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, 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 "alThunk.h"
29 #include "alError.h"
32 extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id);
33 extern inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id);
34 extern inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample);
35 extern inline ALfloat ALfilterState_processSingleC(const ALfilterState *filter, ALfloat sample);
37 static void InitFilterParams(ALfilter *filter, ALenum type);
40 AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
42 ALCdevice *device;
43 ALCcontext *context;
44 ALsizei cur = 0;
45 ALenum err;
47 context = GetContextRef();
48 if(!context) return;
50 if(!(n >= 0))
51 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
53 device = context->Device;
54 for(cur = 0;cur < n;cur++)
56 ALfilter *filter = calloc(1, sizeof(ALfilter));
57 if(!filter)
59 alDeleteFilters(cur, filters);
60 SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
62 InitFilterParams(filter, AL_FILTER_NULL);
64 err = NewThunkEntry(&filter->id);
65 if(err == AL_NO_ERROR)
66 err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter);
67 if(err != AL_NO_ERROR)
69 FreeThunkEntry(filter->id);
70 memset(filter, 0, sizeof(ALfilter));
71 free(filter);
73 alDeleteFilters(cur, filters);
74 SET_ERROR_AND_GOTO(context, err, done);
77 filters[cur] = filter->id;
80 done:
81 ALCcontext_DecRef(context);
84 AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
86 ALCdevice *device;
87 ALCcontext *context;
88 ALfilter *filter;
89 ALsizei i;
91 context = GetContextRef();
92 if(!context) return;
94 if(!(n >= 0))
95 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
97 device = context->Device;
98 for(i = 0;i < n;i++)
100 if(filters[i] && LookupFilter(device, filters[i]) == NULL)
101 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
103 for(i = 0;i < n;i++)
105 if((filter=RemoveFilter(device, filters[i])) == NULL)
106 continue;
107 FreeThunkEntry(filter->id);
109 memset(filter, 0, sizeof(*filter));
110 free(filter);
113 done:
114 ALCcontext_DecRef(context);
117 AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
119 ALCcontext *Context;
120 ALboolean result;
122 Context = GetContextRef();
123 if(!Context) return AL_FALSE;
125 result = ((!filter || LookupFilter(Context->Device, filter)) ?
126 AL_TRUE : AL_FALSE);
128 ALCcontext_DecRef(Context);
130 return result;
133 AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
135 ALCcontext *Context;
136 ALCdevice *Device;
137 ALfilter *ALFilter;
139 Context = GetContextRef();
140 if(!Context) return;
142 Device = Context->Device;
143 if((ALFilter=LookupFilter(Device, filter)) == NULL)
144 alSetError(Context, AL_INVALID_NAME);
145 else
147 if(param == AL_FILTER_TYPE)
149 if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS)
150 InitFilterParams(ALFilter, value);
151 else
152 alSetError(Context, AL_INVALID_VALUE);
154 else
156 /* Call the appropriate handler */
157 ALfilter_SetParami(ALFilter, Context, param, value);
161 ALCcontext_DecRef(Context);
164 AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values)
166 ALCcontext *Context;
167 ALCdevice *Device;
168 ALfilter *ALFilter;
170 switch(param)
172 case AL_FILTER_TYPE:
173 alFilteri(filter, param, values[0]);
174 return;
177 Context = GetContextRef();
178 if(!Context) return;
180 Device = Context->Device;
181 if((ALFilter=LookupFilter(Device, filter)) == NULL)
182 alSetError(Context, AL_INVALID_NAME);
183 else
185 /* Call the appropriate handler */
186 ALfilter_SetParamiv(ALFilter, Context, param, values);
189 ALCcontext_DecRef(Context);
192 AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
194 ALCcontext *Context;
195 ALCdevice *Device;
196 ALfilter *ALFilter;
198 Context = GetContextRef();
199 if(!Context) return;
201 Device = Context->Device;
202 if((ALFilter=LookupFilter(Device, filter)) == NULL)
203 alSetError(Context, AL_INVALID_NAME);
204 else
206 /* Call the appropriate handler */
207 ALfilter_SetParamf(ALFilter, Context, param, value);
210 ALCcontext_DecRef(Context);
213 AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values)
215 ALCcontext *Context;
216 ALCdevice *Device;
217 ALfilter *ALFilter;
219 Context = GetContextRef();
220 if(!Context) return;
222 Device = Context->Device;
223 if((ALFilter=LookupFilter(Device, filter)) == NULL)
224 alSetError(Context, AL_INVALID_NAME);
225 else
227 /* Call the appropriate handler */
228 ALfilter_SetParamfv(ALFilter, Context, param, values);
231 ALCcontext_DecRef(Context);
234 AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
236 ALCcontext *Context;
237 ALCdevice *Device;
238 ALfilter *ALFilter;
240 Context = GetContextRef();
241 if(!Context) return;
243 Device = Context->Device;
244 if((ALFilter=LookupFilter(Device, filter)) == NULL)
245 alSetError(Context, AL_INVALID_NAME);
246 else
248 if(param == AL_FILTER_TYPE)
249 *value = ALFilter->type;
250 else
252 /* Call the appropriate handler */
253 ALfilter_GetParami(ALFilter, Context, param, value);
257 ALCcontext_DecRef(Context);
260 AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values)
262 ALCcontext *Context;
263 ALCdevice *Device;
264 ALfilter *ALFilter;
266 switch(param)
268 case AL_FILTER_TYPE:
269 alGetFilteri(filter, param, values);
270 return;
273 Context = GetContextRef();
274 if(!Context) return;
276 Device = Context->Device;
277 if((ALFilter=LookupFilter(Device, filter)) == NULL)
278 alSetError(Context, AL_INVALID_NAME);
279 else
281 /* Call the appropriate handler */
282 ALfilter_GetParamiv(ALFilter, Context, param, values);
285 ALCcontext_DecRef(Context);
288 AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value)
290 ALCcontext *Context;
291 ALCdevice *Device;
292 ALfilter *ALFilter;
294 Context = GetContextRef();
295 if(!Context) return;
297 Device = Context->Device;
298 if((ALFilter=LookupFilter(Device, filter)) == NULL)
299 alSetError(Context, AL_INVALID_NAME);
300 else
302 /* Call the appropriate handler */
303 ALfilter_GetParamf(ALFilter, Context, param, value);
306 ALCcontext_DecRef(Context);
309 AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values)
311 ALCcontext *Context;
312 ALCdevice *Device;
313 ALfilter *ALFilter;
315 Context = GetContextRef();
316 if(!Context) return;
318 Device = Context->Device;
319 if((ALFilter=LookupFilter(Device, filter)) == NULL)
320 alSetError(Context, AL_INVALID_NAME);
321 else
323 /* Call the appropriate handler */
324 ALfilter_GetParamfv(ALFilter, Context, param, values);
327 ALCcontext_DecRef(Context);
331 void ALfilterState_clear(ALfilterState *filter)
333 filter->x[0] = 0.0f;
334 filter->x[1] = 0.0f;
335 filter->y[0] = 0.0f;
336 filter->y[1] = 0.0f;
339 void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_scale, ALfloat bandwidth)
341 ALfloat alpha;
342 ALfloat w0;
344 // Limit gain to -100dB
345 gain = maxf(gain, 0.00001f);
347 w0 = F_2PI * freq_scale;
349 /* Calculate filter coefficients depending on filter type */
350 switch(type)
352 case ALfilterType_HighShelf:
353 alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f/gain) *
354 (1.0f/0.75f - 1.0f) + 2.0f);
355 filter->b[0] = gain * ((gain + 1.0f) +
356 (gain - 1.0f) * cosf(w0) +
357 2.0f * sqrtf(gain) * alpha);
358 filter->b[1] = -2.0f * gain * ((gain - 1.0f) +
359 (gain + 1.0f) * cosf(w0));
360 filter->b[2] = gain * ((gain + 1.0f) +
361 (gain - 1.0f) * cosf(w0) -
362 2.0f * sqrtf(gain) * alpha);
363 filter->a[0] = (gain + 1.0f) -
364 (gain - 1.0f) * cosf(w0) +
365 2.0f * sqrtf(gain) * alpha;
366 filter->a[1] = 2.0f * ((gain - 1.0f) -
367 (gain + 1.0f) * cosf(w0));
368 filter->a[2] = (gain + 1.0f) -
369 (gain - 1.0f) * cosf(w0) -
370 2.0f * sqrtf(gain) * alpha;
371 break;
372 case ALfilterType_LowShelf:
373 alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f / gain) *
374 (1.0f / 0.75f - 1.0f) + 2.0f);
375 filter->b[0] = gain * ((gain + 1.0f) -
376 (gain - 1.0f) * cosf(w0) +
377 2.0f * sqrtf(gain) * alpha);
378 filter->b[1] = 2.0f * gain * ((gain - 1.0f) -
379 (gain + 1.0f) * cosf(w0));
380 filter->b[2] = gain * ((gain + 1.0f) -
381 (gain - 1.0f) * cosf(w0) -
382 2.0f * sqrtf(gain) * alpha);
383 filter->a[0] = (gain + 1.0f) +
384 (gain - 1.0f) * cosf(w0) +
385 2.0f * sqrtf(gain) * alpha;
386 filter->a[1] = -2.0f * ((gain - 1.0f) +
387 (gain + 1.0f) * cosf(w0));
388 filter->a[2] = (gain + 1.0f) +
389 (gain - 1.0f) * cosf(w0) -
390 2.0f * sqrtf(gain) * alpha;
391 break;
392 case ALfilterType_Peaking:
393 alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
394 filter->b[0] = 1.0f + alpha * gain;
395 filter->b[1] = -2.0f * cosf(w0);
396 filter->b[2] = 1.0f - alpha * gain;
397 filter->a[0] = 1.0f + alpha / gain;
398 filter->a[1] = -2.0f * cosf(w0);
399 filter->a[2] = 1.0f - alpha / gain;
400 break;
402 case ALfilterType_LowPass:
403 alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
404 filter->b[0] = (1.0f - cosf(w0)) / 2.0f;
405 filter->b[1] = 1.0f - cosf(w0);
406 filter->b[2] = (1.0f - cosf(w0)) / 2.0f;
407 filter->a[0] = 1.0f + alpha;
408 filter->a[1] = -2.0f * cosf(w0);
409 filter->a[2] = 1.0f - alpha;
410 break;
411 case ALfilterType_HighPass:
412 alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
413 filter->b[0] = (1.0f + cosf(w0)) / 2.0f;
414 filter->b[1] = 1.0f + cosf(w0);
415 filter->b[2] = (1.0f + cosf(w0)) / 2.0f;
416 filter->a[0] = 1.0f + alpha;
417 filter->a[1] = -2.0f * cosf(w0);
418 filter->a[2] = 1.0f - alpha;
419 break;
420 case ALfilterType_BandPass:
421 alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
422 filter->b[0] = alpha;
423 filter->b[1] = 0;
424 filter->b[2] = -alpha;
425 filter->a[0] = 1.0f + alpha;
426 filter->a[1] = -2.0f * cosf(w0);
427 filter->a[2] = 1.0f - alpha;
428 break;
431 filter->b[2] /= filter->a[0];
432 filter->b[1] /= filter->a[0];
433 filter->b[0] /= filter->a[0];
434 filter->a[2] /= filter->a[0];
435 filter->a[1] /= filter->a[0];
436 filter->a[0] /= filter->a[0];
440 static void lp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
441 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
442 static void lp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
443 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
444 static void lp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
446 switch(param)
448 case AL_LOWPASS_GAIN:
449 if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN))
450 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
451 filter->Gain = val;
452 break;
454 case AL_LOWPASS_GAINHF:
455 if(!(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF))
456 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
457 filter->GainHF = val;
458 break;
460 default:
461 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
464 static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
466 lp_SetParamf(filter, context, param, vals[0]);
469 static void lp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
470 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
471 static void lp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
472 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
473 static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
475 switch(param)
477 case AL_LOWPASS_GAIN:
478 *val = filter->Gain;
479 break;
481 case AL_LOWPASS_GAINHF:
482 *val = filter->GainHF;
483 break;
485 default:
486 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
489 static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
491 lp_GetParamf(filter, context, param, vals);
495 static void null_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
496 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
497 static void null_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
498 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
499 static void null_SetParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat UNUSED(val))
500 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
501 static void null_SetParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALfloat *UNUSED(vals))
502 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
504 static void null_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
505 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
506 static void null_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
507 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
508 static void null_GetParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(val))
509 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
510 static void null_GetParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(vals))
511 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
514 ALvoid ReleaseALFilters(ALCdevice *device)
516 ALsizei i;
517 for(i = 0;i < device->FilterMap.size;i++)
519 ALfilter *temp = device->FilterMap.array[i].value;
520 device->FilterMap.array[i].value = NULL;
522 // Release filter structure
523 FreeThunkEntry(temp->id);
524 memset(temp, 0, sizeof(ALfilter));
525 free(temp);
530 static void InitFilterParams(ALfilter *filter, ALenum type)
532 if(type == AL_FILTER_LOWPASS)
534 filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
535 filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
537 filter->SetParami = lp_SetParami;
538 filter->SetParamiv = lp_SetParamiv;
539 filter->SetParamf = lp_SetParamf;
540 filter->SetParamfv = lp_SetParamfv;
541 filter->GetParami = lp_GetParami;
542 filter->GetParamiv = lp_GetParamiv;
543 filter->GetParamf = lp_GetParamf;
544 filter->GetParamfv = lp_GetParamfv;
546 else
548 filter->SetParami = null_SetParami;
549 filter->SetParamiv = null_SetParamiv;
550 filter->SetParamf = null_SetParamf;
551 filter->SetParamfv = null_SetParamfv;
552 filter->GetParami = null_GetParami;
553 filter->GetParamiv = null_GetParamiv;
554 filter->GetParamf = null_GetParamf;
555 filter->GetParamfv = null_GetParamfv;
557 filter->type = type;