view OpenAL32/alFilter.c @ 32:b8bc24918d63

moved ear.org into cortex
author Robert McIntyre <rlm@mit.edu>
date Sat, 04 Feb 2012 01:43:33 -0700
parents f9476ff7637e
children
line wrap: on
line source
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.
8 *
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.
13 *
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
19 */
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);
35 #define LookupFilter(m, k) ((ALfilter*)LookupUIntMapKey(&(m), (k)))
37 AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
38 {
39 ALCcontext *Context;
40 ALsizei i=0;
42 Context = GetLockedContext();
43 if(!Context) return;
45 if(n < 0 || IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
46 alSetError(Context, AL_INVALID_VALUE);
47 else
48 {
49 ALCdevice *device = Context->Device;
50 ALenum err;
52 while(i < n)
53 {
54 ALfilter *filter = calloc(1, sizeof(ALfilter));
55 if(!filter)
56 {
57 alSetError(Context, AL_OUT_OF_MEMORY);
58 alDeleteFilters(i, filters);
59 break;
60 }
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)
66 {
67 FreeThunkEntry(filter->filter);
68 memset(filter, 0, sizeof(ALfilter));
69 free(filter);
71 alSetError(Context, err);
72 alDeleteFilters(i, filters);
73 break;
74 }
76 filters[i++] = filter->filter;
77 InitFilterParams(filter, AL_FILTER_NULL);
78 }
79 }
81 UnlockContext(Context);
82 }
84 AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
85 {
86 ALCcontext *Context;
87 ALCdevice *device;
88 ALfilter *ALFilter;
89 ALboolean Failed;
90 ALsizei i;
92 Context = GetLockedContext();
93 if(!Context) return;
95 Failed = AL_TRUE;
96 device = Context->Device;
97 if(n < 0)
98 alSetError(Context, AL_INVALID_VALUE);
99 else
100 {
101 Failed = AL_FALSE;
102 // Check that all filters are valid
103 for(i = 0;i < n;i++)
104 {
105 if(!filters[i])
106 continue;
108 if(LookupFilter(device->FilterMap, filters[i]) == NULL)
109 {
110 alSetError(Context, AL_INVALID_NAME);
111 Failed = AL_TRUE;
112 break;
113 }
114 }
115 }
117 if(!Failed)
118 {
119 // All filters are valid
120 for(i = 0;i < n;i++)
121 {
122 // Recheck that the filter is valid, because there could be duplicated names
123 if((ALFilter=LookupFilter(device->FilterMap, filters[i])) == NULL)
124 continue;
126 RemoveUIntMapKey(&device->FilterMap, ALFilter->filter);
127 FreeThunkEntry(ALFilter->filter);
129 memset(ALFilter, 0, sizeof(ALfilter));
130 free(ALFilter);
131 }
132 }
134 UnlockContext(Context);
135 }
137 AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
138 {
139 ALCcontext *Context;
140 ALboolean result;
142 Context = GetLockedContext();
143 if(!Context) return AL_FALSE;
145 result = ((!filter || LookupFilter(Context->Device->FilterMap, filter)) ?
146 AL_TRUE : AL_FALSE);
148 UnlockContext(Context);
150 return result;
151 }
153 AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
154 {
155 ALCcontext *Context;
156 ALCdevice *Device;
157 ALfilter *ALFilter;
159 Context = GetLockedContext();
160 if(!Context) return;
162 Device = Context->Device;
163 if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)
164 {
165 switch(param)
166 {
167 case AL_FILTER_TYPE:
168 if(iValue == AL_FILTER_NULL ||
169 iValue == AL_FILTER_LOWPASS)
170 InitFilterParams(ALFilter, iValue);
171 else
172 alSetError(Context, AL_INVALID_VALUE);
173 break;
175 default:
176 alSetError(Context, AL_INVALID_ENUM);
177 break;
178 }
179 }
180 else
181 alSetError(Context, AL_INVALID_NAME);
183 UnlockContext(Context);
184 }
186 AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues)
187 {
188 ALCcontext *Context;
189 ALCdevice *Device;
191 switch(param)
192 {
193 case AL_FILTER_TYPE:
194 alFilteri(filter, param, piValues[0]);
195 return;
196 }
198 Context = GetLockedContext();
199 if(!Context) return;
201 Device = Context->Device;
202 if(LookupFilter(Device->FilterMap, filter) != NULL)
203 {
204 switch(param)
205 {
206 default:
207 alSetError(Context, AL_INVALID_ENUM);
208 break;
209 }
210 }
211 else
212 alSetError(Context, AL_INVALID_NAME);
214 UnlockContext(Context);
215 }
217 AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue)
218 {
219 ALCcontext *Context;
220 ALCdevice *Device;
221 ALfilter *ALFilter;
223 Context = GetLockedContext();
224 if(!Context) return;
226 Device = Context->Device;
227 if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)
228 {
229 switch(ALFilter->type)
230 {
231 case AL_FILTER_LOWPASS:
232 switch(param)
233 {
234 case AL_LOWPASS_GAIN:
235 if(flValue >= AL_LOWPASS_MIN_GAIN &&
236 flValue <= AL_LOWPASS_MAX_GAIN)
237 ALFilter->Gain = flValue;
238 else
239 alSetError(Context, AL_INVALID_VALUE);
240 break;
242 case AL_LOWPASS_GAINHF:
243 if(flValue >= AL_LOWPASS_MIN_GAINHF &&
244 flValue <= AL_LOWPASS_MAX_GAINHF)
245 ALFilter->GainHF = flValue;
246 else
247 alSetError(Context, AL_INVALID_VALUE);
248 break;
250 default:
251 alSetError(Context, AL_INVALID_ENUM);
252 break;
253 }
254 break;
256 default:
257 alSetError(Context, AL_INVALID_ENUM);
258 break;
259 }
260 }
261 else
262 alSetError(Context, AL_INVALID_NAME);
264 UnlockContext(Context);
265 }
267 AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
268 {
269 /* There are currently no multi-value filter parameters */
270 alFilterf(filter, param, pflValues[0]);
271 }
273 AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue)
274 {
275 ALCcontext *Context;
276 ALCdevice *Device;
277 ALfilter *ALFilter;
279 Context = GetLockedContext();
280 if(!Context) return;
282 Device = Context->Device;
283 if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)
284 {
285 switch(param)
286 {
287 case AL_FILTER_TYPE:
288 *piValue = ALFilter->type;
289 break;
291 default:
292 alSetError(Context, AL_INVALID_ENUM);
293 break;
294 }
295 }
296 else
297 alSetError(Context, AL_INVALID_NAME);
299 UnlockContext(Context);
300 }
302 AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues)
303 {
304 ALCcontext *Context;
305 ALCdevice *Device;
307 switch(param)
308 {
309 case AL_FILTER_TYPE:
310 alGetFilteri(filter, param, piValues);
311 return;
312 }
314 Context = GetLockedContext();
315 if(!Context) return;
317 Device = Context->Device;
318 if(LookupFilter(Device->FilterMap, filter) != NULL)
319 {
320 switch(param)
321 {
322 default:
323 alSetError(Context, AL_INVALID_ENUM);
324 break;
325 }
326 }
327 else
328 alSetError(Context, AL_INVALID_NAME);
330 UnlockContext(Context);
331 }
333 AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue)
334 {
335 ALCcontext *Context;
336 ALCdevice *Device;
337 ALfilter *ALFilter;
339 Context = GetLockedContext();
340 if(!Context) return;
342 Device = Context->Device;
343 if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)
344 {
345 switch(ALFilter->type)
346 {
347 case AL_FILTER_LOWPASS:
348 switch(param)
349 {
350 case AL_LOWPASS_GAIN:
351 *pflValue = ALFilter->Gain;
352 break;
354 case AL_LOWPASS_GAINHF:
355 *pflValue = ALFilter->GainHF;
356 break;
358 default:
359 alSetError(Context, AL_INVALID_ENUM);
360 break;
361 }
362 break;
364 default:
365 alSetError(Context, AL_INVALID_ENUM);
366 break;
367 }
368 }
369 else
370 alSetError(Context, AL_INVALID_NAME);
372 UnlockContext(Context);
373 }
375 AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
376 {
377 /* There are currently no multi-value filter parameters */
378 alGetFilterf(filter, param, pflValues);
379 }
382 ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
383 {
384 ALfloat a = 0.0f;
386 /* Be careful with gains < 0.01, as that causes the coefficient
387 * head towards 1, which will flatten the signal */
388 if(g < 0.9999f) /* 1-epsilon */
389 {
390 g = maxf(g, 0.01f);
391 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
392 (1 - g);
393 }
395 return a;
396 }
398 ALvoid ReleaseALFilters(ALCdevice *device)
399 {
400 ALsizei i;
401 for(i = 0;i < device->FilterMap.size;i++)
402 {
403 ALfilter *temp = device->FilterMap.array[i].value;
404 device->FilterMap.array[i].value = NULL;
406 // Release filter structure
407 FreeThunkEntry(temp->filter);
408 memset(temp, 0, sizeof(ALfilter));
409 free(temp);
410 }
411 }
414 static void InitFilterParams(ALfilter *filter, ALenum type)
415 {
416 filter->type = type;
418 filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
419 filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
420 }