Move a comment
[openal-soft.git] / OpenAL32 / alFilter.c
blobb51864705b7d51e0d062bcb89fd2dc4e5b4041f6
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->id);
63 if(err == AL_NO_ERROR)
64 err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter);
65 if(err != AL_NO_ERROR)
67 FreeThunkEntry(filter->id);
68 memset(filter, 0, sizeof(ALfilter));
69 free(filter);
71 alSetError(Context, err);
72 alDeleteFilters(i, filters);
73 break;
76 filters[i] = filter->id;
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->id);
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 value)
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)
154 alSetError(Context, AL_INVALID_NAME);
155 else
157 if(param == AL_FILTER_TYPE)
159 if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS)
160 InitFilterParams(ALFilter, value);
161 else
162 alSetError(Context, AL_INVALID_VALUE);
164 else
166 /* Call the appropriate handler */
167 ALfilter_SetParami(ALFilter, Context, param, value);
171 ALCcontext_DecRef(Context);
174 AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values)
176 ALCcontext *Context;
177 ALCdevice *Device;
178 ALfilter *ALFilter;
180 switch(param)
182 case AL_FILTER_TYPE:
183 alFilteri(filter, param, values[0]);
184 return;
187 Context = GetContextRef();
188 if(!Context) return;
190 Device = Context->Device;
191 if((ALFilter=LookupFilter(Device, filter)) == NULL)
192 alSetError(Context, AL_INVALID_NAME);
193 else
195 /* Call the appropriate handler */
196 ALfilter_SetParamiv(ALFilter, Context, param, values);
199 ALCcontext_DecRef(Context);
202 AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
204 ALCcontext *Context;
205 ALCdevice *Device;
206 ALfilter *ALFilter;
208 Context = GetContextRef();
209 if(!Context) return;
211 Device = Context->Device;
212 if((ALFilter=LookupFilter(Device, filter)) == NULL)
213 alSetError(Context, AL_INVALID_NAME);
214 else
216 /* Call the appropriate handler */
217 ALfilter_SetParamf(ALFilter, Context, param, value);
220 ALCcontext_DecRef(Context);
223 AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values)
225 ALCcontext *Context;
226 ALCdevice *Device;
227 ALfilter *ALFilter;
229 Context = GetContextRef();
230 if(!Context) return;
232 Device = Context->Device;
233 if((ALFilter=LookupFilter(Device, filter)) == NULL)
234 alSetError(Context, AL_INVALID_NAME);
235 else
237 /* Call the appropriate handler */
238 ALfilter_SetParamfv(ALFilter, Context, param, values);
241 ALCcontext_DecRef(Context);
244 AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
246 ALCcontext *Context;
247 ALCdevice *Device;
248 ALfilter *ALFilter;
250 Context = GetContextRef();
251 if(!Context) return;
253 Device = Context->Device;
254 if((ALFilter=LookupFilter(Device, filter)) == NULL)
255 alSetError(Context, AL_INVALID_NAME);
256 else
258 if(param == AL_FILTER_TYPE)
259 *value = ALFilter->type;
260 else
262 /* Call the appropriate handler */
263 ALfilter_GetParami(ALFilter, Context, param, value);
267 ALCcontext_DecRef(Context);
270 AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values)
272 ALCcontext *Context;
273 ALCdevice *Device;
274 ALfilter *ALFilter;
276 switch(param)
278 case AL_FILTER_TYPE:
279 alGetFilteri(filter, param, values);
280 return;
283 Context = GetContextRef();
284 if(!Context) return;
286 Device = Context->Device;
287 if((ALFilter=LookupFilter(Device, filter)) == NULL)
288 alSetError(Context, AL_INVALID_NAME);
289 else
291 /* Call the appropriate handler */
292 ALfilter_GetParamiv(ALFilter, Context, param, values);
295 ALCcontext_DecRef(Context);
298 AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value)
300 ALCcontext *Context;
301 ALCdevice *Device;
302 ALfilter *ALFilter;
304 Context = GetContextRef();
305 if(!Context) return;
307 Device = Context->Device;
308 if((ALFilter=LookupFilter(Device, filter)) == NULL)
309 alSetError(Context, AL_INVALID_NAME);
310 else
312 /* Call the appropriate handler */
313 ALfilter_GetParamf(ALFilter, Context, param, value);
316 ALCcontext_DecRef(Context);
319 AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values)
321 ALCcontext *Context;
322 ALCdevice *Device;
323 ALfilter *ALFilter;
325 Context = GetContextRef();
326 if(!Context) return;
328 Device = Context->Device;
329 if((ALFilter=LookupFilter(Device, filter)) == NULL)
330 alSetError(Context, AL_INVALID_NAME);
331 else
333 /* Call the appropriate handler */
334 ALfilter_GetParamfv(ALFilter, Context, param, values);
337 ALCcontext_DecRef(Context);
341 ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
343 ALfloat a = 0.0f;
345 if(g < 0.9999f) /* 1-epsilon */
347 /* Be careful with gains < 0.001, as that causes the coefficient head
348 * towards 1, which will flatten the signal */
349 g = maxf(g, 0.001f);
350 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
351 (1 - g);
354 return a;
358 static void lp_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
359 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
360 static void lp_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
361 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
362 static void lp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
364 switch(param)
366 case AL_LOWPASS_GAIN:
367 if(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN)
368 filter->Gain = val;
369 else
370 alSetError(context, AL_INVALID_VALUE);
371 break;
373 case AL_LOWPASS_GAINHF:
374 if(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF)
375 filter->GainHF = val;
376 else
377 alSetError(context, AL_INVALID_VALUE);
378 break;
380 default:
381 alSetError(context, AL_INVALID_ENUM);
382 break;
385 static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
387 lp_SetParamf(filter, context, param, vals[0]);
390 static void lp_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
391 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
392 static void lp_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
393 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
394 static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
396 switch(param)
398 case AL_LOWPASS_GAIN:
399 *val = filter->Gain;
400 break;
402 case AL_LOWPASS_GAINHF:
403 *val = filter->GainHF;
404 break;
406 default:
407 alSetError(context, AL_INVALID_ENUM);
408 break;
411 static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
413 lp_GetParamf(filter, context, param, vals);
417 static void null_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
418 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
419 static void null_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
420 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
421 static void null_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
422 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
423 static void null_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
424 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
426 static void null_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
427 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
428 static void null_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
429 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
430 static void null_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
431 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
432 static void null_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
433 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
436 ALvoid ReleaseALFilters(ALCdevice *device)
438 ALsizei i;
439 for(i = 0;i < device->FilterMap.size;i++)
441 ALfilter *temp = device->FilterMap.array[i].value;
442 device->FilterMap.array[i].value = NULL;
444 // Release filter structure
445 FreeThunkEntry(temp->id);
446 memset(temp, 0, sizeof(ALfilter));
447 free(temp);
452 static void InitFilterParams(ALfilter *filter, ALenum type)
454 if(type == AL_FILTER_LOWPASS)
456 filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
457 filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
459 filter->SetParami = lp_SetParami;
460 filter->SetParamiv = lp_SetParamiv;
461 filter->SetParamf = lp_SetParamf;
462 filter->SetParamfv = lp_SetParamfv;
463 filter->GetParami = lp_GetParami;
464 filter->GetParamiv = lp_GetParamiv;
465 filter->GetParamf = lp_GetParamf;
466 filter->GetParamfv = lp_GetParamfv;
468 else
470 filter->SetParami = null_SetParami;
471 filter->SetParamiv = null_SetParamiv;
472 filter->SetParamf = null_SetParamf;
473 filter->SetParamfv = null_SetParamfv;
474 filter->GetParami = null_GetParami;
475 filter->GetParamiv = null_GetParamiv;
476 filter->GetParamf = null_GetParamf;
477 filter->GetParamfv = null_GetParamfv;
479 filter->type = type;