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
);
36 static void InitFilterParams(ALfilter
*filter
, ALenum type
);
39 AL_API ALvoid AL_APIENTRY
alGenFilters(ALsizei n
, ALuint
*filters
)
46 context
= GetContextRef();
50 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
52 device
= context
->Device
;
53 for(cur
= 0;cur
< n
;cur
++)
55 ALfilter
*filter
= calloc(1, sizeof(ALfilter
));
58 alDeleteFilters(cur
, filters
);
59 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
61 InitFilterParams(filter
, AL_FILTER_NULL
);
63 err
= NewThunkEntry(&filter
->id
);
64 if(err
== AL_NO_ERROR
)
65 err
= InsertUIntMapEntry(&device
->FilterMap
, filter
->id
, filter
);
66 if(err
!= AL_NO_ERROR
)
68 FreeThunkEntry(filter
->id
);
69 memset(filter
, 0, sizeof(ALfilter
));
72 alDeleteFilters(cur
, filters
);
73 SET_ERROR_AND_GOTO(context
, err
, done
);
76 filters
[cur
] = filter
->id
;
80 ALCcontext_DecRef(context
);
83 AL_API ALvoid AL_APIENTRY
alDeleteFilters(ALsizei n
, const ALuint
*filters
)
90 context
= GetContextRef();
94 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
96 device
= context
->Device
;
99 if(filters
[i
] && LookupFilter(device
, filters
[i
]) == NULL
)
100 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
104 if((filter
=RemoveFilter(device
, filters
[i
])) == NULL
)
106 FreeThunkEntry(filter
->id
);
108 memset(filter
, 0, sizeof(*filter
));
113 ALCcontext_DecRef(context
);
116 AL_API ALboolean AL_APIENTRY
alIsFilter(ALuint filter
)
121 Context
= GetContextRef();
122 if(!Context
) return AL_FALSE
;
124 result
= ((!filter
|| LookupFilter(Context
->Device
, filter
)) ?
127 ALCcontext_DecRef(Context
);
132 AL_API ALvoid AL_APIENTRY
alFilteri(ALuint filter
, ALenum param
, ALint value
)
138 Context
= GetContextRef();
141 Device
= Context
->Device
;
142 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
143 alSetError(Context
, AL_INVALID_NAME
);
146 if(param
== AL_FILTER_TYPE
)
148 if(value
== AL_FILTER_NULL
|| value
== AL_FILTER_LOWPASS
)
149 InitFilterParams(ALFilter
, value
);
151 alSetError(Context
, AL_INVALID_VALUE
);
155 /* Call the appropriate handler */
156 ALfilter_SetParami(ALFilter
, Context
, param
, value
);
160 ALCcontext_DecRef(Context
);
163 AL_API ALvoid AL_APIENTRY
alFilteriv(ALuint filter
, ALenum param
, const ALint
*values
)
172 alFilteri(filter
, param
, values
[0]);
176 Context
= GetContextRef();
179 Device
= Context
->Device
;
180 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
181 alSetError(Context
, AL_INVALID_NAME
);
184 /* Call the appropriate handler */
185 ALfilter_SetParamiv(ALFilter
, Context
, param
, values
);
188 ALCcontext_DecRef(Context
);
191 AL_API ALvoid AL_APIENTRY
alFilterf(ALuint filter
, ALenum param
, ALfloat value
)
197 Context
= GetContextRef();
200 Device
= Context
->Device
;
201 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
202 alSetError(Context
, AL_INVALID_NAME
);
205 /* Call the appropriate handler */
206 ALfilter_SetParamf(ALFilter
, Context
, param
, value
);
209 ALCcontext_DecRef(Context
);
212 AL_API ALvoid AL_APIENTRY
alFilterfv(ALuint filter
, ALenum param
, const ALfloat
*values
)
218 Context
= GetContextRef();
221 Device
= Context
->Device
;
222 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
223 alSetError(Context
, AL_INVALID_NAME
);
226 /* Call the appropriate handler */
227 ALfilter_SetParamfv(ALFilter
, Context
, param
, values
);
230 ALCcontext_DecRef(Context
);
233 AL_API ALvoid AL_APIENTRY
alGetFilteri(ALuint filter
, ALenum param
, ALint
*value
)
239 Context
= GetContextRef();
242 Device
= Context
->Device
;
243 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
244 alSetError(Context
, AL_INVALID_NAME
);
247 if(param
== AL_FILTER_TYPE
)
248 *value
= ALFilter
->type
;
251 /* Call the appropriate handler */
252 ALfilter_GetParami(ALFilter
, Context
, param
, value
);
256 ALCcontext_DecRef(Context
);
259 AL_API ALvoid AL_APIENTRY
alGetFilteriv(ALuint filter
, ALenum param
, ALint
*values
)
268 alGetFilteri(filter
, param
, values
);
272 Context
= GetContextRef();
275 Device
= Context
->Device
;
276 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
277 alSetError(Context
, AL_INVALID_NAME
);
280 /* Call the appropriate handler */
281 ALfilter_GetParamiv(ALFilter
, Context
, param
, values
);
284 ALCcontext_DecRef(Context
);
287 AL_API ALvoid AL_APIENTRY
alGetFilterf(ALuint filter
, ALenum param
, ALfloat
*value
)
293 Context
= GetContextRef();
296 Device
= Context
->Device
;
297 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
298 alSetError(Context
, AL_INVALID_NAME
);
301 /* Call the appropriate handler */
302 ALfilter_GetParamf(ALFilter
, Context
, param
, value
);
305 ALCcontext_DecRef(Context
);
308 AL_API ALvoid AL_APIENTRY
alGetFilterfv(ALuint filter
, ALenum param
, ALfloat
*values
)
314 Context
= GetContextRef();
317 Device
= Context
->Device
;
318 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
319 alSetError(Context
, AL_INVALID_NAME
);
322 /* Call the appropriate handler */
323 ALfilter_GetParamfv(ALFilter
, Context
, param
, values
);
326 ALCcontext_DecRef(Context
);
330 void ALfilterState_clear(ALfilterState
*filter
)
338 void ALfilterState_setParams(ALfilterState
*filter
, ALfilterType type
, ALfloat gain
, ALfloat freq_scale
, ALfloat bandwidth
)
343 // Limit gain to -100dB
344 gain
= maxf(gain
, 0.00001f
);
346 w0
= F_2PI
* freq_scale
;
348 /* Calculate filter coefficients depending on filter type */
351 case ALfilterType_HighShelf
:
352 alpha
= sinf(w0
) / 2.0f
* sqrtf((gain
+ 1.0f
/gain
) *
353 (1.0f
/0.75f
- 1.0f
) + 2.0f
);
354 filter
->b
[0] = gain
* ((gain
+ 1.0f
) +
355 (gain
- 1.0f
) * cosf(w0
) +
356 2.0f
* sqrtf(gain
) * alpha
);
357 filter
->b
[1] = -2.0f
* gain
* ((gain
- 1.0f
) +
358 (gain
+ 1.0f
) * cosf(w0
));
359 filter
->b
[2] = gain
* ((gain
+ 1.0f
) +
360 (gain
- 1.0f
) * cosf(w0
) -
361 2.0f
* sqrtf(gain
) * alpha
);
362 filter
->a
[0] = (gain
+ 1.0f
) -
363 (gain
- 1.0f
) * cosf(w0
) +
364 2.0f
* sqrtf(gain
) * alpha
;
365 filter
->a
[1] = 2.0f
* ((gain
- 1.0f
) -
366 (gain
+ 1.0f
) * cosf(w0
));
367 filter
->a
[2] = (gain
+ 1.0f
) -
368 (gain
- 1.0f
) * cosf(w0
) -
369 2.0f
* sqrtf(gain
) * alpha
;
371 case ALfilterType_LowShelf
:
372 alpha
= sinf(w0
) / 2.0f
* sqrtf((gain
+ 1.0f
/ gain
) *
373 (1.0f
/ 0.75f
- 1.0f
) + 2.0f
);
374 filter
->b
[0] = gain
* ((gain
+ 1.0f
) -
375 (gain
- 1.0f
) * cosf(w0
) +
376 2.0f
* sqrtf(gain
) * alpha
);
377 filter
->b
[1] = 2.0f
* gain
* ((gain
- 1.0f
) -
378 (gain
+ 1.0f
) * cosf(w0
));
379 filter
->b
[2] = gain
* ((gain
+ 1.0f
) -
380 (gain
- 1.0f
) * cosf(w0
) -
381 2.0f
* sqrtf(gain
) * alpha
);
382 filter
->a
[0] = (gain
+ 1.0f
) +
383 (gain
- 1.0f
) * cosf(w0
) +
384 2.0f
* sqrtf(gain
) * alpha
;
385 filter
->a
[1] = -2.0f
* ((gain
- 1.0f
) +
386 (gain
+ 1.0f
) * cosf(w0
));
387 filter
->a
[2] = (gain
+ 1.0f
) +
388 (gain
- 1.0f
) * cosf(w0
) -
389 2.0f
* sqrtf(gain
) * alpha
;
391 case ALfilterType_Peaking
:
392 alpha
= sinf(w0
) * sinhf(logf(2.0f
) / 2.0f
* bandwidth
* w0
/ sinf(w0
));
393 filter
->b
[0] = 1.0f
+ alpha
* gain
;
394 filter
->b
[1] = -2.0f
* cosf(w0
);
395 filter
->b
[2] = 1.0f
- alpha
* gain
;
396 filter
->a
[0] = 1.0f
+ alpha
/ gain
;
397 filter
->a
[1] = -2.0f
* cosf(w0
);
398 filter
->a
[2] = 1.0f
- alpha
/ gain
;
401 case ALfilterType_LowPass
:
402 alpha
= sinf(w0
) * sinhf(logf(2.0f
) / 2.0f
* bandwidth
* w0
/ sinf(w0
));
403 filter
->b
[0] = (1.0f
- cosf(w0
)) / 2.0f
;
404 filter
->b
[1] = 1.0f
- cosf(w0
);
405 filter
->b
[2] = (1.0f
- cosf(w0
)) / 2.0f
;
406 filter
->a
[0] = 1.0f
+ alpha
;
407 filter
->a
[1] = -2.0f
* cosf(w0
);
408 filter
->a
[2] = 1.0f
- alpha
;
410 case ALfilterType_HighPass
:
411 alpha
= sinf(w0
) * sinhf(logf(2.0f
) / 2.0f
* bandwidth
* w0
/ sinf(w0
));
412 filter
->b
[0] = (1.0f
+ cosf(w0
)) / 2.0f
;
413 filter
->b
[1] = 1.0f
+ cosf(w0
);
414 filter
->b
[2] = (1.0f
+ cosf(w0
)) / 2.0f
;
415 filter
->a
[0] = 1.0f
+ alpha
;
416 filter
->a
[1] = -2.0f
* cosf(w0
);
417 filter
->a
[2] = 1.0f
- alpha
;
419 case ALfilterType_BandPass
:
420 alpha
= sinf(w0
) * sinhf(logf(2.0f
) / 2.0f
* bandwidth
* w0
/ sinf(w0
));
421 filter
->b
[0] = alpha
;
423 filter
->b
[2] = -alpha
;
424 filter
->a
[0] = 1.0f
+ alpha
;
425 filter
->a
[1] = -2.0f
* cosf(w0
);
426 filter
->a
[2] = 1.0f
- alpha
;
430 filter
->b
[2] /= filter
->a
[0];
431 filter
->b
[1] /= filter
->a
[0];
432 filter
->b
[0] /= filter
->a
[0];
433 filter
->a
[2] /= filter
->a
[0];
434 filter
->a
[1] /= filter
->a
[0];
435 filter
->a
[0] /= filter
->a
[0];
439 static void lp_SetParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), ALint
UNUSED(val
))
440 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
441 static void lp_SetParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), const ALint
*UNUSED(vals
))
442 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
443 static void lp_SetParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat val
)
447 case AL_LOWPASS_GAIN
:
448 if(!(val
>= AL_LOWPASS_MIN_GAIN
&& val
<= AL_LOWPASS_MAX_GAIN
))
449 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
453 case AL_LOWPASS_GAINHF
:
454 if(!(val
>= AL_LOWPASS_MIN_GAINHF
&& val
<= AL_LOWPASS_MAX_GAINHF
))
455 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
456 filter
->GainHF
= val
;
460 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
463 static void lp_SetParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
465 lp_SetParamf(filter
, context
, param
, vals
[0]);
468 static void lp_GetParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), ALint
*UNUSED(val
))
469 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
470 static void lp_GetParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), ALint
*UNUSED(vals
))
471 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
472 static void lp_GetParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
476 case AL_LOWPASS_GAIN
:
480 case AL_LOWPASS_GAINHF
:
481 *val
= filter
->GainHF
;
485 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
488 static void lp_GetParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
490 lp_GetParamf(filter
, context
, param
, vals
);
494 static void null_SetParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), ALint
UNUSED(val
))
495 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
496 static void null_SetParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), const ALint
*UNUSED(vals
))
497 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
498 static void null_SetParamf(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), ALfloat
UNUSED(val
))
499 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
500 static void null_SetParamfv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), const ALfloat
*UNUSED(vals
))
501 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
503 static void null_GetParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), ALint
*UNUSED(val
))
504 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
505 static void null_GetParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), ALint
*UNUSED(vals
))
506 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
507 static void null_GetParamf(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), ALfloat
*UNUSED(val
))
508 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
509 static void null_GetParamfv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum
UNUSED(param
), ALfloat
*UNUSED(vals
))
510 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
513 ALvoid
ReleaseALFilters(ALCdevice
*device
)
516 for(i
= 0;i
< device
->FilterMap
.size
;i
++)
518 ALfilter
*temp
= device
->FilterMap
.array
[i
].value
;
519 device
->FilterMap
.array
[i
].value
= NULL
;
521 // Release filter structure
522 FreeThunkEntry(temp
->id
);
523 memset(temp
, 0, sizeof(ALfilter
));
529 static void InitFilterParams(ALfilter
*filter
, ALenum type
)
531 if(type
== AL_FILTER_LOWPASS
)
533 filter
->Gain
= AL_LOWPASS_DEFAULT_GAIN
;
534 filter
->GainHF
= AL_LOWPASS_DEFAULT_GAINHF
;
535 filter
->HFReference
= LOWPASSFREQREF
;
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
;