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
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
)
47 context
= GetContextRef();
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
));
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
));
73 alDeleteFilters(cur
, filters
);
74 SET_ERROR_AND_GOTO(context
, err
, done
);
77 filters
[cur
] = filter
->id
;
81 ALCcontext_DecRef(context
);
84 AL_API ALvoid AL_APIENTRY
alDeleteFilters(ALsizei n
, const ALuint
*filters
)
91 context
= GetContextRef();
95 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
97 device
= context
->Device
;
100 if(filters
[i
] && LookupFilter(device
, filters
[i
]) == NULL
)
101 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
105 if((filter
=RemoveFilter(device
, filters
[i
])) == NULL
)
107 FreeThunkEntry(filter
->id
);
109 memset(filter
, 0, sizeof(*filter
));
114 ALCcontext_DecRef(context
);
117 AL_API ALboolean AL_APIENTRY
alIsFilter(ALuint filter
)
122 Context
= GetContextRef();
123 if(!Context
) return AL_FALSE
;
125 result
= ((!filter
|| LookupFilter(Context
->Device
, filter
)) ?
128 ALCcontext_DecRef(Context
);
133 AL_API ALvoid AL_APIENTRY
alFilteri(ALuint filter
, ALenum param
, ALint value
)
139 Context
= GetContextRef();
142 Device
= Context
->Device
;
143 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
144 alSetError(Context
, AL_INVALID_NAME
);
147 if(param
== AL_FILTER_TYPE
)
149 if(value
== AL_FILTER_NULL
|| value
== AL_FILTER_LOWPASS
)
150 InitFilterParams(ALFilter
, value
);
152 alSetError(Context
, AL_INVALID_VALUE
);
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
)
173 alFilteri(filter
, param
, values
[0]);
177 Context
= GetContextRef();
180 Device
= Context
->Device
;
181 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
182 alSetError(Context
, AL_INVALID_NAME
);
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
)
198 Context
= GetContextRef();
201 Device
= Context
->Device
;
202 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
203 alSetError(Context
, AL_INVALID_NAME
);
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
)
219 Context
= GetContextRef();
222 Device
= Context
->Device
;
223 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
224 alSetError(Context
, AL_INVALID_NAME
);
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
)
240 Context
= GetContextRef();
243 Device
= Context
->Device
;
244 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
245 alSetError(Context
, AL_INVALID_NAME
);
248 if(param
== AL_FILTER_TYPE
)
249 *value
= ALFilter
->type
;
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
)
269 alGetFilteri(filter
, param
, values
);
273 Context
= GetContextRef();
276 Device
= Context
->Device
;
277 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
278 alSetError(Context
, AL_INVALID_NAME
);
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
)
294 Context
= GetContextRef();
297 Device
= Context
->Device
;
298 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
299 alSetError(Context
, AL_INVALID_NAME
);
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
)
315 Context
= GetContextRef();
318 Device
= Context
->Device
;
319 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
320 alSetError(Context
, AL_INVALID_NAME
);
323 /* Call the appropriate handler */
324 ALfilter_GetParamfv(ALFilter
, Context
, param
, values
);
327 ALCcontext_DecRef(Context
);
331 void ALfilterState_clear(ALfilterState
*filter
)
339 void ALfilterState_setParams(ALfilterState
*filter
, ALfilterType type
, ALfloat gain
, ALfloat freq_scale
, ALfloat bandwidth
)
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 */
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
;
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
;
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
;
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
;
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
;
420 case ALfilterType_BandPass
:
421 alpha
= sinf(w0
) * sinhf(logf(2.0f
) / 2.0f
* bandwidth
* w0
/ sinf(w0
));
422 filter
->b
[0] = alpha
;
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
;
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
)
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
);
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
;
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
)
477 case AL_LOWPASS_GAIN
:
481 case AL_LOWPASS_GAINHF
:
482 *val
= filter
->GainHF
;
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
)
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
));
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
;
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
;