Clamp the low-pass reference gain to -60 dB instead of -40 dB
[openal-soft/android.git] / OpenAL32 / alFilter.c
blob5697b8686308833d3a7dd377e3951ae382b35140
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 "AL/al.h"
26 #include "AL/alc.h"
27 #include "alMain.h"
28 #include "alFilter.h"
29 #include "alThunk.h"
30 #include "alError.h"
33 static void InitFilterParams(ALfilter *filter, ALenum type);
36 AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
38 ALCcontext *Context;
39 ALsizei i;
41 Context = GetContextRef();
42 if(!Context) return;
44 if(n < 0 || IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
45 alSetError(Context, AL_INVALID_VALUE);
46 else
48 ALCdevice *device = Context->Device;
49 ALenum err;
51 for(i = 0;i < n;i++)
53 ALfilter *filter = calloc(1, sizeof(ALfilter));
54 if(!filter)
56 alSetError(Context, AL_OUT_OF_MEMORY);
57 alDeleteFilters(i, filters);
58 break;
60 InitFilterParams(filter, AL_FILTER_NULL);
62 err = NewThunkEntry(&filter->filter);
63 if(err == AL_NO_ERROR)
64 err = InsertUIntMapEntry(&device->FilterMap, filter->filter, filter);
65 if(err != AL_NO_ERROR)
67 FreeThunkEntry(filter->filter);
68 memset(filter, 0, sizeof(ALfilter));
69 free(filter);
71 alSetError(Context, err);
72 alDeleteFilters(i, filters);
73 break;
76 filters[i] = filter->filter;
80 ALCcontext_DecRef(Context);
83 AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
85 ALCcontext *Context;
86 ALCdevice *device;
87 ALfilter *ALFilter;
88 ALsizei i;
90 Context = GetContextRef();
91 if(!Context) return;
93 device = Context->Device;
94 if(n < 0)
95 alSetError(Context, AL_INVALID_VALUE);
96 else
98 // Check that all filters are valid
99 for(i = 0;i < n;i++)
101 if(!filters[i])
102 continue;
104 if(LookupFilter(device, filters[i]) == NULL)
106 alSetError(Context, AL_INVALID_NAME);
107 n = 0;
108 break;
112 for(i = 0;i < n;i++)
114 // Recheck that the filter is valid, because there could be duplicated names
115 if((ALFilter=RemoveFilter(device, filters[i])) == NULL)
116 continue;
117 FreeThunkEntry(ALFilter->filter);
119 memset(ALFilter, 0, sizeof(ALfilter));
120 free(ALFilter);
124 ALCcontext_DecRef(Context);
127 AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
129 ALCcontext *Context;
130 ALboolean result;
132 Context = GetContextRef();
133 if(!Context) return AL_FALSE;
135 result = ((!filter || LookupFilter(Context->Device, filter)) ?
136 AL_TRUE : AL_FALSE);
138 ALCcontext_DecRef(Context);
140 return result;
143 AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
145 ALCcontext *Context;
146 ALCdevice *Device;
147 ALfilter *ALFilter;
149 Context = GetContextRef();
150 if(!Context) return;
152 Device = Context->Device;
153 if((ALFilter=LookupFilter(Device, filter)) != NULL)
155 switch(param)
157 case AL_FILTER_TYPE:
158 if(iValue == AL_FILTER_NULL || iValue == AL_FILTER_LOWPASS)
159 InitFilterParams(ALFilter, iValue);
160 else
161 alSetError(Context, AL_INVALID_VALUE);
162 break;
164 default:
165 /* Call the appropriate handler */
166 ALfilter_SetParami(ALFilter, Context, param, iValue);
167 break;
170 else
171 alSetError(Context, AL_INVALID_NAME);
173 ALCcontext_DecRef(Context);
176 AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues)
178 ALCcontext *Context;
179 ALCdevice *Device;
180 ALfilter *ALFilter;
182 switch(param)
184 case AL_FILTER_TYPE:
185 alFilteri(filter, param, piValues[0]);
186 return;
189 Context = GetContextRef();
190 if(!Context) return;
192 Device = Context->Device;
193 if((ALFilter=LookupFilter(Device, filter)) != NULL)
195 /* Call the appropriate handler */
196 ALfilter_SetParamiv(ALFilter, Context, param, piValues);
198 else
199 alSetError(Context, AL_INVALID_NAME);
201 ALCcontext_DecRef(Context);
204 AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue)
206 ALCcontext *Context;
207 ALCdevice *Device;
208 ALfilter *ALFilter;
210 Context = GetContextRef();
211 if(!Context) return;
213 Device = Context->Device;
214 if((ALFilter=LookupFilter(Device, filter)) != NULL)
216 /* Call the appropriate handler */
217 ALfilter_SetParamf(ALFilter, Context, param, flValue);
219 else
220 alSetError(Context, AL_INVALID_NAME);
222 ALCcontext_DecRef(Context);
225 AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues)
227 ALCcontext *Context;
228 ALCdevice *Device;
229 ALfilter *ALFilter;
231 Context = GetContextRef();
232 if(!Context) return;
234 Device = Context->Device;
235 if((ALFilter=LookupFilter(Device, filter)) != NULL)
237 /* Call the appropriate handler */
238 ALfilter_SetParamfv(ALFilter, Context, param, pflValues);
240 else
241 alSetError(Context, AL_INVALID_NAME);
243 ALCcontext_DecRef(Context);
246 AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue)
248 ALCcontext *Context;
249 ALCdevice *Device;
250 ALfilter *ALFilter;
252 Context = GetContextRef();
253 if(!Context) return;
255 Device = Context->Device;
256 if((ALFilter=LookupFilter(Device, filter)) != NULL)
258 switch(param)
260 case AL_FILTER_TYPE:
261 *piValue = ALFilter->type;
262 break;
264 default:
265 /* Call the appropriate handler */
266 ALfilter_GetParami(ALFilter, Context, param, piValue);
267 break;
270 else
271 alSetError(Context, AL_INVALID_NAME);
273 ALCcontext_DecRef(Context);
276 AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues)
278 ALCcontext *Context;
279 ALCdevice *Device;
280 ALfilter *ALFilter;
282 switch(param)
284 case AL_FILTER_TYPE:
285 alGetFilteri(filter, param, piValues);
286 return;
289 Context = GetContextRef();
290 if(!Context) return;
292 Device = Context->Device;
293 if((ALFilter=LookupFilter(Device, filter)) != NULL)
295 /* Call the appropriate handler */
296 ALfilter_GetParamiv(ALFilter, Context, param, piValues);
298 else
299 alSetError(Context, AL_INVALID_NAME);
301 ALCcontext_DecRef(Context);
304 AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue)
306 ALCcontext *Context;
307 ALCdevice *Device;
308 ALfilter *ALFilter;
310 Context = GetContextRef();
311 if(!Context) return;
313 Device = Context->Device;
314 if((ALFilter=LookupFilter(Device, filter)) != NULL)
316 /* Call the appropriate handler */
317 ALfilter_GetParamf(ALFilter, Context, param, pflValue);
319 else
320 alSetError(Context, AL_INVALID_NAME);
322 ALCcontext_DecRef(Context);
325 AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
327 ALCcontext *Context;
328 ALCdevice *Device;
329 ALfilter *ALFilter;
331 Context = GetContextRef();
332 if(!Context) return;
334 Device = Context->Device;
335 if((ALFilter=LookupFilter(Device, filter)) != NULL)
337 /* Call the appropriate handler */
338 ALfilter_GetParamfv(ALFilter, Context, param, pflValues);
340 else
341 alSetError(Context, AL_INVALID_NAME);
343 ALCcontext_DecRef(Context);
347 ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
349 ALfloat a = 0.0f;
351 /* Be careful with gains < 0.001, as that causes the coefficient head
352 * towards 1, which will flatten the signal */
353 if(g < 0.9999f) /* 1-epsilon */
355 g = maxf(g, 0.001f);
356 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
357 (1 - g);
360 return a;
364 static void lp_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
365 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
366 static void lp_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
367 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
368 static void lp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
370 switch(param)
372 case AL_LOWPASS_GAIN:
373 if(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN)
374 filter->Gain = val;
375 else
376 alSetError(context, AL_INVALID_VALUE);
377 break;
379 case AL_LOWPASS_GAINHF:
380 if(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF)
381 filter->GainHF = val;
382 else
383 alSetError(context, AL_INVALID_VALUE);
384 break;
386 default:
387 alSetError(context, AL_INVALID_ENUM);
388 break;
391 static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
393 lp_SetParamf(filter, context, param, vals[0]);
396 static void lp_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
397 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
398 static void lp_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
399 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
400 static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
402 switch(param)
404 case AL_LOWPASS_GAIN:
405 *val = filter->Gain;
406 break;
408 case AL_LOWPASS_GAINHF:
409 *val = filter->GainHF;
410 break;
412 default:
413 alSetError(context, AL_INVALID_ENUM);
414 break;
417 static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
419 lp_GetParamf(filter, context, param, vals);
423 static void null_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
424 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
425 static void null_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
426 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
427 static void null_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
428 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
429 static void null_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
430 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
432 static void null_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
433 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
434 static void null_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
435 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
436 static void null_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
437 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
438 static void null_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
439 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
442 ALvoid ReleaseALFilters(ALCdevice *device)
444 ALsizei i;
445 for(i = 0;i < device->FilterMap.size;i++)
447 ALfilter *temp = device->FilterMap.array[i].value;
448 device->FilterMap.array[i].value = NULL;
450 // Release filter structure
451 FreeThunkEntry(temp->filter);
452 memset(temp, 0, sizeof(ALfilter));
453 free(temp);
458 static void InitFilterParams(ALfilter *filter, ALenum type)
460 if(type == AL_FILTER_LOWPASS)
462 filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
463 filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
465 filter->SetParami = lp_SetParami;
466 filter->SetParamiv = lp_SetParamiv;
467 filter->SetParamf = lp_SetParamf;
468 filter->SetParamfv = lp_SetParamfv;
469 filter->GetParami = lp_GetParami;
470 filter->GetParamiv = lp_GetParamiv;
471 filter->GetParamf = lp_GetParamf;
472 filter->GetParamfv = lp_GetParamfv;
474 else
476 filter->SetParami = null_SetParami;
477 filter->SetParamiv = null_SetParamiv;
478 filter->SetParamf = null_SetParamf;
479 filter->SetParamfv = null_SetParamfv;
480 filter->GetParami = null_GetParami;
481 filter->GetParamiv = null_GetParamiv;
482 filter->GetParamf = null_GetParamf;
483 filter->GetParamfv = null_GetParamfv;
485 filter->type = type;