Allow PulseAudio to spawn a server by default
[openal-soft/openal-hmr.git] / OpenAL32 / alFilter.c
blobd943d9f1ec8a98ad83172acb4c076972adba312a
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 cur = 0;
41 Context = GetContextRef();
42 if(!Context) return;
44 al_try
46 ALCdevice *device = Context->Device;
47 ALenum err;
49 CHECK_VALUE(Context, n >= 0);
50 for(cur = 0;cur < n;cur++)
52 ALfilter *filter = calloc(1, sizeof(ALfilter));
53 if(!filter)
54 al_throwerr(Context, AL_OUT_OF_MEMORY);
55 InitFilterParams(filter, AL_FILTER_NULL);
57 err = NewThunkEntry(&filter->id);
58 if(err == AL_NO_ERROR)
59 err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter);
60 if(err != AL_NO_ERROR)
62 FreeThunkEntry(filter->id);
63 memset(filter, 0, sizeof(ALfilter));
64 free(filter);
66 al_throwerr(Context, err);
69 filters[cur] = filter->id;
72 al_catchany()
74 if(cur > 0)
75 alDeleteFilters(cur, filters);
77 al_endtry;
79 ALCcontext_DecRef(Context);
82 AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
84 ALCcontext *Context;
85 ALfilter *Filter;
86 ALsizei i;
88 Context = GetContextRef();
89 if(!Context) return;
91 al_try
93 ALCdevice *device = Context->Device;
94 CHECK_VALUE(Context, n >= 0);
95 for(i = 0;i < n;i++)
97 if(filters[i] && LookupFilter(device, filters[i]) == NULL)
98 al_throwerr(Context, AL_INVALID_NAME);
101 for(i = 0;i < n;i++)
103 if((Filter=RemoveFilter(device, filters[i])) == NULL)
104 continue;
105 FreeThunkEntry(Filter->id);
107 memset(Filter, 0, sizeof(*Filter));
108 free(Filter);
111 al_endtry;
113 ALCcontext_DecRef(Context);
116 AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
118 ALCcontext *Context;
119 ALboolean result;
121 Context = GetContextRef();
122 if(!Context) return AL_FALSE;
124 result = ((!filter || LookupFilter(Context->Device, filter)) ?
125 AL_TRUE : AL_FALSE);
127 ALCcontext_DecRef(Context);
129 return result;
132 AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
134 ALCcontext *Context;
135 ALCdevice *Device;
136 ALfilter *ALFilter;
138 Context = GetContextRef();
139 if(!Context) return;
141 Device = Context->Device;
142 if((ALFilter=LookupFilter(Device, filter)) == NULL)
143 alSetError(Context, AL_INVALID_NAME);
144 else
146 if(param == AL_FILTER_TYPE)
148 if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS)
149 InitFilterParams(ALFilter, value);
150 else
151 alSetError(Context, AL_INVALID_VALUE);
153 else
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)
165 ALCcontext *Context;
166 ALCdevice *Device;
167 ALfilter *ALFilter;
169 switch(param)
171 case AL_FILTER_TYPE:
172 alFilteri(filter, param, values[0]);
173 return;
176 Context = GetContextRef();
177 if(!Context) return;
179 Device = Context->Device;
180 if((ALFilter=LookupFilter(Device, filter)) == NULL)
181 alSetError(Context, AL_INVALID_NAME);
182 else
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)
193 ALCcontext *Context;
194 ALCdevice *Device;
195 ALfilter *ALFilter;
197 Context = GetContextRef();
198 if(!Context) return;
200 Device = Context->Device;
201 if((ALFilter=LookupFilter(Device, filter)) == NULL)
202 alSetError(Context, AL_INVALID_NAME);
203 else
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)
214 ALCcontext *Context;
215 ALCdevice *Device;
216 ALfilter *ALFilter;
218 Context = GetContextRef();
219 if(!Context) return;
221 Device = Context->Device;
222 if((ALFilter=LookupFilter(Device, filter)) == NULL)
223 alSetError(Context, AL_INVALID_NAME);
224 else
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)
235 ALCcontext *Context;
236 ALCdevice *Device;
237 ALfilter *ALFilter;
239 Context = GetContextRef();
240 if(!Context) return;
242 Device = Context->Device;
243 if((ALFilter=LookupFilter(Device, filter)) == NULL)
244 alSetError(Context, AL_INVALID_NAME);
245 else
247 if(param == AL_FILTER_TYPE)
248 *value = ALFilter->type;
249 else
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)
261 ALCcontext *Context;
262 ALCdevice *Device;
263 ALfilter *ALFilter;
265 switch(param)
267 case AL_FILTER_TYPE:
268 alGetFilteri(filter, param, values);
269 return;
272 Context = GetContextRef();
273 if(!Context) return;
275 Device = Context->Device;
276 if((ALFilter=LookupFilter(Device, filter)) == NULL)
277 alSetError(Context, AL_INVALID_NAME);
278 else
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)
289 ALCcontext *Context;
290 ALCdevice *Device;
291 ALfilter *ALFilter;
293 Context = GetContextRef();
294 if(!Context) return;
296 Device = Context->Device;
297 if((ALFilter=LookupFilter(Device, filter)) == NULL)
298 alSetError(Context, AL_INVALID_NAME);
299 else
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)
310 ALCcontext *Context;
311 ALCdevice *Device;
312 ALfilter *ALFilter;
314 Context = GetContextRef();
315 if(!Context) return;
317 Device = Context->Device;
318 if((ALFilter=LookupFilter(Device, filter)) == NULL)
319 alSetError(Context, AL_INVALID_NAME);
320 else
322 /* Call the appropriate handler */
323 ALfilter_GetParamfv(ALFilter, Context, param, values);
326 ALCcontext_DecRef(Context);
330 ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
332 ALfloat a = 0.0f;
334 if(g < 0.9999f) /* 1-epsilon */
336 /* Be careful with gains < 0.001, as that causes the coefficient head
337 * towards 1, which will flatten the signal */
338 g = maxf(g, 0.001f);
339 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
340 (1 - g);
343 return a;
347 static void lp_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
348 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
349 static void lp_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
350 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
351 static void lp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
353 switch(param)
355 case AL_LOWPASS_GAIN:
356 if(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN)
357 filter->Gain = val;
358 else
359 alSetError(context, AL_INVALID_VALUE);
360 break;
362 case AL_LOWPASS_GAINHF:
363 if(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF)
364 filter->GainHF = val;
365 else
366 alSetError(context, AL_INVALID_VALUE);
367 break;
369 default:
370 alSetError(context, AL_INVALID_ENUM);
371 break;
374 static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
376 lp_SetParamf(filter, context, param, vals[0]);
379 static void lp_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
380 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
381 static void lp_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
382 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
383 static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
385 switch(param)
387 case AL_LOWPASS_GAIN:
388 *val = filter->Gain;
389 break;
391 case AL_LOWPASS_GAINHF:
392 *val = filter->GainHF;
393 break;
395 default:
396 alSetError(context, AL_INVALID_ENUM);
397 break;
400 static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
402 lp_GetParamf(filter, context, param, vals);
406 static void null_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
407 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
408 static void null_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
409 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
410 static void null_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
411 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
412 static void null_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
413 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
415 static void null_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
416 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
417 static void null_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
418 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
419 static void null_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
420 { (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
421 static void null_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
422 { (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
425 ALvoid ReleaseALFilters(ALCdevice *device)
427 ALsizei i;
428 for(i = 0;i < device->FilterMap.size;i++)
430 ALfilter *temp = device->FilterMap.array[i].value;
431 device->FilterMap.array[i].value = NULL;
433 // Release filter structure
434 FreeThunkEntry(temp->id);
435 memset(temp, 0, sizeof(ALfilter));
436 free(temp);
441 static void InitFilterParams(ALfilter *filter, ALenum type)
443 if(type == AL_FILTER_LOWPASS)
445 filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
446 filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
448 filter->SetParami = lp_SetParami;
449 filter->SetParamiv = lp_SetParamiv;
450 filter->SetParamf = lp_SetParamf;
451 filter->SetParamfv = lp_SetParamfv;
452 filter->GetParami = lp_GetParami;
453 filter->GetParamiv = lp_GetParamiv;
454 filter->GetParamf = lp_GetParamf;
455 filter->GetParamfv = lp_GetParamfv;
457 else
459 filter->SetParami = null_SetParami;
460 filter->SetParamiv = null_SetParamiv;
461 filter->SetParamf = null_SetParamf;
462 filter->SetParamfv = null_SetParamfv;
463 filter->GetParami = null_GetParami;
464 filter->GetParamiv = null_GetParamiv;
465 filter->GetParamf = null_GetParamf;
466 filter->GetParamfv = null_GetParamfv;
468 filter->type = type;