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
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
)
42 Context
= GetLockedContext();
45 if(n
< 0 || IsBadWritePtr((void*)filters
, n
* sizeof(ALuint
)))
46 alSetError(Context
, AL_INVALID_VALUE
);
49 ALCdevice
*device
= Context
->Device
;
54 ALfilter
*filter
= calloc(1, sizeof(ALfilter
));
57 alSetError(Context
, AL_OUT_OF_MEMORY
);
58 alDeleteFilters(i
, filters
);
62 err
= ALTHUNK_ADDENTRY(filter
, &filter
->filter
);
63 if(err
== AL_NO_ERROR
)
64 err
= InsertUIntMapEntry(&device
->FilterMap
, filter
->filter
, filter
);
65 if(err
!= AL_NO_ERROR
)
67 ALTHUNK_REMOVEENTRY(filter
->filter
);
68 memset(filter
, 0, sizeof(ALfilter
));
71 alSetError(Context
, err
);
72 alDeleteFilters(i
, filters
);
76 filters
[i
++] = filter
->filter
;
77 InitFilterParams(filter
, AL_FILTER_NULL
);
81 UnlockContext(Context
);
84 AL_API ALvoid AL_APIENTRY
alDeleteFilters(ALsizei n
, ALuint
*filters
)
92 Context
= GetLockedContext();
96 device
= Context
->Device
;
98 alSetError(Context
, AL_INVALID_VALUE
);
102 // Check that all filters are valid
108 if(LookupFilter(device
->FilterMap
, filters
[i
]) == NULL
)
110 alSetError(Context
, AL_INVALID_NAME
);
119 // All filters are valid
122 // Recheck that the filter is valid, because there could be duplicated names
123 if((ALFilter
=LookupFilter(device
->FilterMap
, filters
[i
])) == NULL
)
126 RemoveUIntMapKey(&device
->FilterMap
, ALFilter
->filter
);
127 ALTHUNK_REMOVEENTRY(ALFilter
->filter
);
129 memset(ALFilter
, 0, sizeof(ALfilter
));
134 UnlockContext(Context
);
137 AL_API ALboolean AL_APIENTRY
alIsFilter(ALuint filter
)
142 Context
= GetLockedContext();
143 if(!Context
) return AL_FALSE
;
145 result
= ((!filter
|| LookupFilter(Context
->Device
->FilterMap
, filter
)) ?
148 UnlockContext(Context
);
153 AL_API ALvoid AL_APIENTRY
alFilteri(ALuint filter
, ALenum param
, ALint iValue
)
159 Context
= GetLockedContext();
162 Device
= Context
->Device
;
163 if((ALFilter
=LookupFilter(Device
->FilterMap
, filter
)) != NULL
)
168 if(iValue
== AL_FILTER_NULL
||
169 iValue
== AL_FILTER_LOWPASS
)
170 InitFilterParams(ALFilter
, iValue
);
172 alSetError(Context
, AL_INVALID_VALUE
);
176 alSetError(Context
, AL_INVALID_ENUM
);
181 alSetError(Context
, AL_INVALID_NAME
);
183 UnlockContext(Context
);
186 AL_API ALvoid AL_APIENTRY
alFilteriv(ALuint filter
, ALenum param
, ALint
*piValues
)
194 alFilteri(filter
, param
, piValues
[0]);
198 Context
= GetLockedContext();
201 Device
= Context
->Device
;
202 if(LookupFilter(Device
->FilterMap
, filter
) != NULL
)
207 alSetError(Context
, AL_INVALID_ENUM
);
212 alSetError(Context
, AL_INVALID_NAME
);
214 UnlockContext(Context
);
217 AL_API ALvoid AL_APIENTRY
alFilterf(ALuint filter
, ALenum param
, ALfloat flValue
)
223 Context
= GetLockedContext();
226 Device
= Context
->Device
;
227 if((ALFilter
=LookupFilter(Device
->FilterMap
, filter
)) != NULL
)
229 switch(ALFilter
->type
)
231 case AL_FILTER_LOWPASS
:
234 case AL_LOWPASS_GAIN
:
235 if(flValue
>= AL_LOWPASS_MIN_GAIN
&&
236 flValue
<= AL_LOWPASS_MAX_GAIN
)
237 ALFilter
->Gain
= flValue
;
239 alSetError(Context
, AL_INVALID_VALUE
);
242 case AL_LOWPASS_GAINHF
:
243 if(flValue
>= AL_LOWPASS_MIN_GAINHF
&&
244 flValue
<= AL_LOWPASS_MAX_GAINHF
)
245 ALFilter
->GainHF
= flValue
;
247 alSetError(Context
, AL_INVALID_VALUE
);
251 alSetError(Context
, AL_INVALID_ENUM
);
257 alSetError(Context
, AL_INVALID_ENUM
);
262 alSetError(Context
, AL_INVALID_NAME
);
264 UnlockContext(Context
);
267 AL_API ALvoid AL_APIENTRY
alFilterfv(ALuint filter
, ALenum param
, ALfloat
*pflValues
)
269 /* There are currently no multi-value filter parameters */
270 alFilterf(filter
, param
, pflValues
[0]);
273 AL_API ALvoid AL_APIENTRY
alGetFilteri(ALuint filter
, ALenum param
, ALint
*piValue
)
279 Context
= GetLockedContext();
282 Device
= Context
->Device
;
283 if((ALFilter
=LookupFilter(Device
->FilterMap
, filter
)) != NULL
)
288 *piValue
= ALFilter
->type
;
292 alSetError(Context
, AL_INVALID_ENUM
);
297 alSetError(Context
, AL_INVALID_NAME
);
299 UnlockContext(Context
);
302 AL_API ALvoid AL_APIENTRY
alGetFilteriv(ALuint filter
, ALenum param
, ALint
*piValues
)
310 alGetFilteri(filter
, param
, piValues
);
314 Context
= GetLockedContext();
317 Device
= Context
->Device
;
318 if(LookupFilter(Device
->FilterMap
, filter
) != NULL
)
323 alSetError(Context
, AL_INVALID_ENUM
);
328 alSetError(Context
, AL_INVALID_NAME
);
330 UnlockContext(Context
);
333 AL_API ALvoid AL_APIENTRY
alGetFilterf(ALuint filter
, ALenum param
, ALfloat
*pflValue
)
339 Context
= GetLockedContext();
342 Device
= Context
->Device
;
343 if((ALFilter
=LookupFilter(Device
->FilterMap
, filter
)) != NULL
)
345 switch(ALFilter
->type
)
347 case AL_FILTER_LOWPASS
:
350 case AL_LOWPASS_GAIN
:
351 *pflValue
= ALFilter
->Gain
;
354 case AL_LOWPASS_GAINHF
:
355 *pflValue
= ALFilter
->GainHF
;
359 alSetError(Context
, AL_INVALID_ENUM
);
365 alSetError(Context
, AL_INVALID_ENUM
);
370 alSetError(Context
, AL_INVALID_NAME
);
372 UnlockContext(Context
);
375 AL_API ALvoid AL_APIENTRY
alGetFilterfv(ALuint filter
, ALenum param
, ALfloat
*pflValues
)
377 /* There are currently no multi-value filter parameters */
378 alGetFilterf(filter
, param
, pflValues
);
382 ALfloat
lpCoeffCalc(ALfloat g
, ALfloat cw
)
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 */
391 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) /
398 ALvoid
ReleaseALFilters(ALCdevice
*device
)
401 for(i
= 0;i
< device
->FilterMap
.size
;i
++)
403 ALfilter
*temp
= device
->FilterMap
.array
[i
].value
;
404 device
->FilterMap
.array
[i
].value
= NULL
;
406 // Release filter structure
407 ALTHUNK_REMOVEENTRY(temp
->filter
);
408 memset(temp
, 0, sizeof(ALfilter
));
414 static void InitFilterParams(ALfilter
*filter
, ALenum type
)
418 filter
->Gain
= AL_LOWPASS_DEFAULT_GAIN
;
419 filter
->GainHF
= AL_LOWPASS_DEFAULT_GAINHF
;