Release 1.15.1
[openal-soft.git] / OpenAL32 / alFilter.c
bloba03ee2d8332b8d57d23fe1e65a8c65ab8ccbbcc8
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 static void InitFilterParams(ALfilter *filter, ALenum type);
35 AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
37 ALCcontext *Context;
38 ALsizei cur = 0;
40 Context = GetContextRef();
41 if(!Context) return;
43 al_try
45 ALCdevice *device = Context->Device;
46 ALenum err;
48 CHECK_VALUE(Context, n >= 0);
49 for(cur = 0;cur < n;cur++)
51 ALfilter *filter = calloc(1, sizeof(ALfilter));
52 if(!filter)
53 al_throwerr(Context, AL_OUT_OF_MEMORY);
54 InitFilterParams(filter, AL_FILTER_NULL);
56 err = NewThunkEntry(&filter->id);
57 if(err == AL_NO_ERROR)
58 err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter);
59 if(err != AL_NO_ERROR)
61 FreeThunkEntry(filter->id);
62 memset(filter, 0, sizeof(ALfilter));
63 free(filter);
65 al_throwerr(Context, err);
68 filters[cur] = filter->id;
71 al_catchany()
73 if(cur > 0)
74 alDeleteFilters(cur, filters);
76 al_endtry;
78 ALCcontext_DecRef(Context);
81 AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
83 ALCcontext *Context;
84 ALfilter *Filter;
85 ALsizei i;
87 Context = GetContextRef();
88 if(!Context) return;
90 al_try
92 ALCdevice *device = Context->Device;
93 CHECK_VALUE(Context, n >= 0);
94 for(i = 0;i < n;i++)
96 if(filters[i] && LookupFilter(device, filters[i]) == NULL)
97 al_throwerr(Context, AL_INVALID_NAME);
100 for(i = 0;i < n;i++)
102 if((Filter=RemoveFilter(device, filters[i])) == NULL)
103 continue;
104 FreeThunkEntry(Filter->id);
106 memset(Filter, 0, sizeof(*Filter));
107 free(Filter);
110 al_endtry;
112 ALCcontext_DecRef(Context);
115 AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
117 ALCcontext *Context;
118 ALboolean result;
120 Context = GetContextRef();
121 if(!Context) return AL_FALSE;
123 result = ((!filter || LookupFilter(Context->Device, filter)) ?
124 AL_TRUE : AL_FALSE);
126 ALCcontext_DecRef(Context);
128 return result;
131 AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
133 ALCcontext *Context;
134 ALCdevice *Device;
135 ALfilter *ALFilter;
137 Context = GetContextRef();
138 if(!Context) return;
140 Device = Context->Device;
141 if((ALFilter=LookupFilter(Device, filter)) == NULL)
142 alSetError(Context, AL_INVALID_NAME);
143 else
145 if(param == AL_FILTER_TYPE)
147 if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS)
148 InitFilterParams(ALFilter, value);
149 else
150 alSetError(Context, AL_INVALID_VALUE);
152 else
154 /* Call the appropriate handler */
155 ALfilter_SetParami(ALFilter, Context, param, value);
159 ALCcontext_DecRef(Context);
162 AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values)
164 ALCcontext *Context;
165 ALCdevice *Device;
166 ALfilter *ALFilter;
168 switch(param)
170 case AL_FILTER_TYPE:
171 alFilteri(filter, param, values[0]);
172 return;
175 Context = GetContextRef();
176 if(!Context) return;
178 Device = Context->Device;
179 if((ALFilter=LookupFilter(Device, filter)) == NULL)
180 alSetError(Context, AL_INVALID_NAME);
181 else
183 /* Call the appropriate handler */
184 ALfilter_SetParamiv(ALFilter, Context, param, values);
187 ALCcontext_DecRef(Context);
190 AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
192 ALCcontext *Context;
193 ALCdevice *Device;
194 ALfilter *ALFilter;
196 Context = GetContextRef();
197 if(!Context) return;
199 Device = Context->Device;
200 if((ALFilter=LookupFilter(Device, filter)) == NULL)
201 alSetError(Context, AL_INVALID_NAME);
202 else
204 /* Call the appropriate handler */
205 ALfilter_SetParamf(ALFilter, Context, param, value);
208 ALCcontext_DecRef(Context);
211 AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values)
213 ALCcontext *Context;
214 ALCdevice *Device;
215 ALfilter *ALFilter;
217 Context = GetContextRef();
218 if(!Context) return;
220 Device = Context->Device;
221 if((ALFilter=LookupFilter(Device, filter)) == NULL)
222 alSetError(Context, AL_INVALID_NAME);
223 else
225 /* Call the appropriate handler */
226 ALfilter_SetParamfv(ALFilter, Context, param, values);
229 ALCcontext_DecRef(Context);
232 AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
234 ALCcontext *Context;
235 ALCdevice *Device;
236 ALfilter *ALFilter;
238 Context = GetContextRef();
239 if(!Context) return;
241 Device = Context->Device;
242 if((ALFilter=LookupFilter(Device, filter)) == NULL)
243 alSetError(Context, AL_INVALID_NAME);
244 else
246 if(param == AL_FILTER_TYPE)
247 *value = ALFilter->type;
248 else
250 /* Call the appropriate handler */
251 ALfilter_GetParami(ALFilter, Context, param, value);
255 ALCcontext_DecRef(Context);
258 AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values)
260 ALCcontext *Context;
261 ALCdevice *Device;
262 ALfilter *ALFilter;
264 switch(param)
266 case AL_FILTER_TYPE:
267 alGetFilteri(filter, param, values);
268 return;
271 Context = GetContextRef();
272 if(!Context) return;
274 Device = Context->Device;
275 if((ALFilter=LookupFilter(Device, filter)) == NULL)
276 alSetError(Context, AL_INVALID_NAME);
277 else
279 /* Call the appropriate handler */
280 ALfilter_GetParamiv(ALFilter, Context, param, values);
283 ALCcontext_DecRef(Context);
286 AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value)
288 ALCcontext *Context;
289 ALCdevice *Device;
290 ALfilter *ALFilter;
292 Context = GetContextRef();
293 if(!Context) return;
295 Device = Context->Device;
296 if((ALFilter=LookupFilter(Device, filter)) == NULL)
297 alSetError(Context, AL_INVALID_NAME);
298 else
300 /* Call the appropriate handler */
301 ALfilter_GetParamf(ALFilter, Context, param, value);
304 ALCcontext_DecRef(Context);
307 AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values)
309 ALCcontext *Context;
310 ALCdevice *Device;
311 ALfilter *ALFilter;
313 Context = GetContextRef();
314 if(!Context) return;
316 Device = Context->Device;
317 if((ALFilter=LookupFilter(Device, filter)) == NULL)
318 alSetError(Context, AL_INVALID_NAME);
319 else
321 /* Call the appropriate handler */
322 ALfilter_GetParamfv(ALFilter, Context, param, values);
325 ALCcontext_DecRef(Context);
329 ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
331 ALfloat a = 0.0f;
333 if(g < 0.9999f) /* 1-epsilon */
335 /* Be careful with gains < 0.001, as that causes the coefficient head
336 * towards 1, which will flatten the signal */
337 g = maxf(g, 0.001f);
338 a = (1 - g*cw - sqrtf(2*g*(1-cw) - g*g*(1 - cw*cw))) /
339 (1 - g);
342 return a;
346 static void lp_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
347 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
348 static void lp_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
349 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
350 static void lp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
352 switch(param)
354 case AL_LOWPASS_GAIN:
355 if(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN)
356 filter->Gain = val;
357 else
358 alSetError(context, AL_INVALID_VALUE);
359 break;
361 case AL_LOWPASS_GAINHF:
362 if(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF)
363 filter->GainHF = val;
364 else
365 alSetError(context, AL_INVALID_VALUE);
366 break;
368 default:
369 alSetError(context, AL_INVALID_ENUM);
370 break;
373 static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
375 lp_SetParamf(filter, context, param, vals[0]);
378 static void lp_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
379 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
380 static void lp_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
381 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
382 static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
384 switch(param)
386 case AL_LOWPASS_GAIN:
387 *val = filter->Gain;
388 break;
390 case AL_LOWPASS_GAINHF:
391 *val = filter->GainHF;
392 break;
394 default:
395 alSetError(context, AL_INVALID_ENUM);
396 break;
399 static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
401 lp_GetParamf(filter, context, param, vals);
405 static void null_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
406 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
407 static void null_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
408 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
409 static void null_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
410 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
411 static void null_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
412 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
414 static void null_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
415 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
416 static void null_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
417 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
418 static void null_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
419 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
420 static void null_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
421 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
424 ALvoid ReleaseALFilters(ALCdevice *device)
426 ALsizei i;
427 for(i = 0;i < device->FilterMap.size;i++)
429 ALfilter *temp = device->FilterMap.array[i].value;
430 device->FilterMap.array[i].value = NULL;
432 // Release filter structure
433 FreeThunkEntry(temp->id);
434 memset(temp, 0, sizeof(ALfilter));
435 free(temp);
440 static void InitFilterParams(ALfilter *filter, ALenum type)
442 if(type == AL_FILTER_LOWPASS)
444 filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
445 filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
447 filter->SetParami = lp_SetParami;
448 filter->SetParamiv = lp_SetParamiv;
449 filter->SetParamf = lp_SetParamf;
450 filter->SetParamfv = lp_SetParamfv;
451 filter->GetParami = lp_GetParami;
452 filter->GetParamiv = lp_GetParamiv;
453 filter->GetParamf = lp_GetParamf;
454 filter->GetParamfv = lp_GetParamfv;
456 else
458 filter->SetParami = null_SetParami;
459 filter->SetParamiv = null_SetParamiv;
460 filter->SetParamf = null_SetParamf;
461 filter->SetParamfv = null_SetParamfv;
462 filter->GetParami = null_GetParami;
463 filter->GetParamiv = null_GetParamiv;
464 filter->GetParamf = null_GetParamf;
465 filter->GetParamfv = null_GetParamfv;
467 filter->type = type;