Seperate data converters into reusable functions
[openal-soft.git] / OpenAL32 / alEffect.c
blob8f52bcaf10a5f3392182f8d32871a733c34a4dba
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 "alEffect.h"
29 #include "alThunk.h"
30 #include "alError.h"
32 static ALeffect *g_EffectList;
33 static ALuint g_EffectCount;
35 static void InitEffectParams(ALeffect *effect, ALenum type);
38 ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
40 ALCcontext *Context;
41 ALsizei i;
43 Context = alcGetCurrentContext();
44 SuspendContext(Context);
46 if (n > 0)
48 // Check that enough memory has been allocted in the 'effects' array for n Effects
49 if (!IsBadWritePtr((void*)effects, n * sizeof(ALuint)))
51 ALeffect **list = &g_EffectList;
52 while(*list)
53 list = &(*list)->next;
55 i = 0;
56 while(i < n)
58 *list = calloc(1, sizeof(ALeffect));
59 if(!(*list))
61 // We must have run out or memory
62 alDeleteEffects(i, effects);
63 alSetError(AL_OUT_OF_MEMORY);
64 break;
67 effects[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
68 (*list)->effect = effects[i];
70 InitEffectParams(*list, AL_EFFECT_NULL);
71 g_EffectCount++;
72 i++;
74 list = &(*list)->next;
79 ProcessContext(Context);
82 ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects)
84 ALCcontext *Context;
85 ALeffect *ALEffect;
86 ALsizei i;
88 Context = alcGetCurrentContext();
89 SuspendContext(Context);
91 if (n >= 0)
93 // Check that all effects are valid
94 for (i = 0; i < n; i++)
96 if (!alIsEffect(effects[i]))
98 alSetError(AL_INVALID_NAME);
99 break;
103 if (i == n)
105 // All effects are valid
106 for (i = 0; i < n; i++)
108 // Recheck that the effect is valid, because there could be duplicated names
109 if (effects[i] && alIsEffect(effects[i]))
111 ALeffect **list;
113 ALEffect = ((ALeffect*)ALTHUNK_LOOKUPENTRY(effects[i]));
115 // Remove Source from list of Sources
116 list = &g_EffectList;
117 while(*list && *list != ALEffect)
118 list = &(*list)->next;
120 if(*list)
121 *list = (*list)->next;
122 ALTHUNK_REMOVEENTRY(ALEffect->effect);
124 memset(ALEffect, 0, sizeof(ALeffect));
125 free(ALEffect);
127 g_EffectCount--;
132 else
133 alSetError(AL_INVALID_VALUE);
135 ProcessContext(Context);
138 ALboolean AL_APIENTRY alIsEffect(ALuint effect)
140 ALCcontext *Context;
141 ALeffect **list;
143 Context = alcGetCurrentContext();
144 SuspendContext(Context);
146 list = &g_EffectList;
147 while(*list && (*list)->effect != effect)
148 list = &(*list)->next;
150 ProcessContext(Context);
152 return ((*list || !effect) ? AL_TRUE : AL_FALSE);
155 ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
157 ALCcontext *Context;
159 Context = alcGetCurrentContext();
160 SuspendContext(Context);
162 if (effect && alIsEffect(effect))
164 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
166 if(param == AL_EFFECT_TYPE)
168 if(iValue == AL_EFFECT_NULL ||
169 iValue == AL_EFFECT_REVERB)
170 InitEffectParams(ALEffect, iValue);
171 else
172 alSetError(AL_INVALID_VALUE);
174 else if(ALEffect->type == AL_EFFECT_REVERB)
176 switch(param)
178 case AL_REVERB_DECAY_HFLIMIT:
179 if(iValue == AL_TRUE || iValue == AL_FALSE)
180 ALEffect->Reverb.DecayHFLimit = iValue;
181 else
182 alSetError(AL_INVALID_VALUE);
183 break;
185 default:
186 alSetError(AL_INVALID_ENUM);
187 break;
190 else
191 alSetError(AL_INVALID_ENUM);
193 else
194 alSetError(AL_INVALID_NAME);
196 ProcessContext(Context);
199 ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues)
201 ALCcontext *Context;
203 Context = alcGetCurrentContext();
204 SuspendContext(Context);
206 if (effect && alIsEffect(effect))
208 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
210 if(param == AL_EFFECT_TYPE)
212 alEffecti(effect, param, piValues[0]);
214 else if(ALEffect->type == AL_EFFECT_REVERB)
216 switch(param)
218 case AL_REVERB_DECAY_HFLIMIT:
219 alEffecti(effect, param, piValues[0]);
220 break;
222 default:
223 alSetError(AL_INVALID_ENUM);
224 break;
227 else
228 alSetError(AL_INVALID_ENUM);
230 else
231 alSetError(AL_INVALID_NAME);
233 ProcessContext(Context);
236 ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
238 ALCcontext *Context;
240 Context = alcGetCurrentContext();
241 SuspendContext(Context);
243 if (effect && alIsEffect(effect))
245 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
247 if(ALEffect->type == AL_EFFECT_REVERB)
249 switch(param)
251 case AL_REVERB_DENSITY:
252 if(flValue >= 0.0f && flValue <= 1.0f)
253 ALEffect->Reverb.Density = flValue;
254 else
255 alSetError(AL_INVALID_VALUE);
256 break;
258 case AL_REVERB_DIFFUSION:
259 if(flValue >= 0.0f && flValue <= 1.0f)
260 ALEffect->Reverb.Diffusion = flValue;
261 else
262 alSetError(AL_INVALID_VALUE);
263 break;
265 case AL_REVERB_GAIN:
266 if(flValue >= 0.0f && flValue <= 1.0f)
267 ALEffect->Reverb.Gain = flValue;
268 else
269 alSetError(AL_INVALID_VALUE);
270 break;
272 case AL_REVERB_GAINHF:
273 if(flValue >= 0.0f && flValue <= 1.0f)
274 ALEffect->Reverb.GainHF = flValue;
275 else
276 alSetError(AL_INVALID_VALUE);
277 break;
279 case AL_REVERB_DECAY_TIME:
280 if(flValue >= 0.1f && flValue <= 20.0f)
281 ALEffect->Reverb.DecayTime = flValue;
282 else
283 alSetError(AL_INVALID_VALUE);
284 break;
286 case AL_REVERB_DECAY_HFRATIO:
287 if(flValue >= 0.1f && flValue <= 2.0f)
288 ALEffect->Reverb.DecayHFRatio = flValue;
289 else
290 alSetError(AL_INVALID_VALUE);
291 break;
293 case AL_REVERB_REFLECTIONS_GAIN:
294 if(flValue >= 0.0f && flValue <= 3.16f)
295 ALEffect->Reverb.ReflectionsGain = flValue;
296 else
297 alSetError(AL_INVALID_VALUE);
298 break;
300 case AL_REVERB_REFLECTIONS_DELAY:
301 if(flValue >= 0.0f && flValue <= 0.3f)
302 ALEffect->Reverb.ReflectionsDelay = flValue;
303 else
304 alSetError(AL_INVALID_VALUE);
305 break;
307 case AL_REVERB_LATE_REVERB_GAIN:
308 if(flValue >= 0.0f && flValue <= 10.0f)
309 ALEffect->Reverb.LateReverbGain = flValue;
310 else
311 alSetError(AL_INVALID_VALUE);
312 break;
314 case AL_REVERB_LATE_REVERB_DELAY:
315 if(flValue >= 0.0f && flValue <= 0.1f)
316 ALEffect->Reverb.LateReverbDelay = flValue;
317 else
318 alSetError(AL_INVALID_VALUE);
319 break;
321 case AL_REVERB_AIR_ABSORPTION_GAINHF:
322 if(flValue >= 0.892f && flValue <= 1.0f)
323 ALEffect->Reverb.AirAbsorptionGainHF = flValue;
324 else
325 alSetError(AL_INVALID_VALUE);
326 break;
328 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
329 if(flValue >= 0.0f && flValue <= 10.0f)
330 ALEffect->Reverb.RoomRolloffFactor = flValue;
331 else
332 alSetError(AL_INVALID_VALUE);
333 break;
335 default:
336 alSetError(AL_INVALID_ENUM);
337 break;
340 else
341 alSetError(AL_INVALID_ENUM);
343 else
344 alSetError(AL_INVALID_NAME);
346 ProcessContext(Context);
349 ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
351 ALCcontext *Context;
353 Context = alcGetCurrentContext();
354 SuspendContext(Context);
356 if (effect && alIsEffect(effect))
358 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
360 if(ALEffect->type == AL_EFFECT_REVERB)
362 switch(param)
364 case AL_REVERB_DENSITY:
365 case AL_REVERB_DIFFUSION:
366 case AL_REVERB_GAIN:
367 case AL_REVERB_GAINHF:
368 case AL_REVERB_DECAY_TIME:
369 case AL_REVERB_DECAY_HFRATIO:
370 case AL_REVERB_REFLECTIONS_GAIN:
371 case AL_REVERB_REFLECTIONS_DELAY:
372 case AL_REVERB_LATE_REVERB_GAIN:
373 case AL_REVERB_LATE_REVERB_DELAY:
374 case AL_REVERB_AIR_ABSORPTION_GAINHF:
375 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
376 alEffectf(effect, param, pflValues[0]);
377 break;
379 default:
380 alSetError(AL_INVALID_ENUM);
381 break;
384 else
385 alSetError(AL_INVALID_ENUM);
387 else
388 alSetError(AL_INVALID_NAME);
390 ProcessContext(Context);
393 ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
395 ALCcontext *Context;
397 Context = alcGetCurrentContext();
398 SuspendContext(Context);
400 if (effect && alIsEffect(effect))
402 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
404 if(param == AL_EFFECT_TYPE)
406 *piValue = ALEffect->type;
408 else if(ALEffect->type == AL_EFFECT_REVERB)
410 switch(param)
412 case AL_REVERB_DECAY_HFLIMIT:
413 *piValue = ALEffect->Reverb.DecayHFLimit;
414 break;
416 default:
417 alSetError(AL_INVALID_ENUM);
418 break;
421 else
422 alSetError(AL_INVALID_ENUM);
424 else
425 alSetError(AL_INVALID_NAME);
427 ProcessContext(Context);
430 ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
432 ALCcontext *Context;
434 Context = alcGetCurrentContext();
435 SuspendContext(Context);
437 if (effect && alIsEffect(effect))
439 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
441 if(param == AL_EFFECT_TYPE)
443 alGetEffecti(effect, param, piValues);
445 else if(ALEffect->type == AL_EFFECT_REVERB)
447 switch(param)
449 case AL_REVERB_DECAY_HFLIMIT:
450 alGetEffecti(effect, param, piValues);
451 break;
453 default:
454 alSetError(AL_INVALID_ENUM);
455 break;
458 else
459 alSetError(AL_INVALID_ENUM);
461 else
462 alSetError(AL_INVALID_NAME);
464 ProcessContext(Context);
467 ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
469 ALCcontext *Context;
471 Context = alcGetCurrentContext();
472 SuspendContext(Context);
474 if (effect && alIsEffect(effect))
476 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
478 if(ALEffect->type == AL_EFFECT_REVERB)
480 switch(param)
482 case AL_REVERB_DENSITY:
483 *pflValue = ALEffect->Reverb.Density;
484 break;
486 case AL_REVERB_DIFFUSION:
487 *pflValue = ALEffect->Reverb.Diffusion;
488 break;
490 case AL_REVERB_GAIN:
491 *pflValue = ALEffect->Reverb.Gain;
492 break;
494 case AL_REVERB_GAINHF:
495 *pflValue = ALEffect->Reverb.GainHF;
496 break;
498 case AL_REVERB_DECAY_TIME:
499 *pflValue = ALEffect->Reverb.DecayTime;
500 break;
502 case AL_REVERB_DECAY_HFRATIO:
503 *pflValue = ALEffect->Reverb.DecayHFRatio;
504 break;
506 case AL_REVERB_REFLECTIONS_GAIN:
507 *pflValue = ALEffect->Reverb.ReflectionsGain;
508 break;
510 case AL_REVERB_REFLECTIONS_DELAY:
511 *pflValue = ALEffect->Reverb.ReflectionsDelay;
512 break;
514 case AL_REVERB_LATE_REVERB_GAIN:
515 *pflValue = ALEffect->Reverb.LateReverbGain;
516 break;
518 case AL_REVERB_LATE_REVERB_DELAY:
519 *pflValue = ALEffect->Reverb.LateReverbDelay;
520 break;
522 case AL_REVERB_AIR_ABSORPTION_GAINHF:
523 *pflValue = ALEffect->Reverb.AirAbsorptionGainHF;
524 break;
526 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
527 *pflValue = ALEffect->Reverb.RoomRolloffFactor;
528 break;
530 default:
531 alSetError(AL_INVALID_ENUM);
532 break;
535 else
536 alSetError(AL_INVALID_ENUM);
538 else
539 alSetError(AL_INVALID_NAME);
541 ProcessContext(Context);
544 ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
546 ALCcontext *Context;
548 Context = alcGetCurrentContext();
549 SuspendContext(Context);
551 if (effect && alIsEffect(effect))
553 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
555 if(ALEffect->type == AL_EFFECT_REVERB)
557 switch(param)
559 case AL_REVERB_DENSITY:
560 case AL_REVERB_DIFFUSION:
561 case AL_REVERB_GAIN:
562 case AL_REVERB_GAINHF:
563 case AL_REVERB_DECAY_TIME:
564 case AL_REVERB_DECAY_HFRATIO:
565 case AL_REVERB_REFLECTIONS_GAIN:
566 case AL_REVERB_REFLECTIONS_DELAY:
567 case AL_REVERB_LATE_REVERB_GAIN:
568 case AL_REVERB_LATE_REVERB_DELAY:
569 case AL_REVERB_AIR_ABSORPTION_GAINHF:
570 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
571 alGetEffectf(effect, param, pflValues);
572 break;
574 default:
575 alSetError(AL_INVALID_ENUM);
576 break;
579 else
580 alSetError(AL_INVALID_ENUM);
582 else
583 alSetError(AL_INVALID_NAME);
585 ProcessContext(Context);
589 ALvoid ReleaseALEffects(ALvoid)
591 #ifdef _DEBUG
592 if(g_EffectCount > 0)
593 AL_PRINT("exit(): deleting %d Effect(s)\n", g_EffectCount);
594 #endif
596 while(g_EffectList)
598 ALeffect *temp = g_EffectList;
599 g_EffectList = g_EffectList->next;
601 // Release effect structure
602 memset(temp, 0, sizeof(ALeffect));
603 free(temp);
605 g_EffectCount = 0;
609 static void InitEffectParams(ALeffect *effect, ALenum type)
611 effect->type = type;
612 switch(type)
614 case AL_EFFECT_REVERB:
615 effect->Reverb.Density = 1.0f;
616 effect->Reverb.Diffusion = 1.0f;
617 effect->Reverb.Gain = 0.32f;
618 effect->Reverb.GainHF = 0.89f;
619 effect->Reverb.DecayTime = 1.49f;
620 effect->Reverb.DecayHFRatio = 0.83f;
621 effect->Reverb.ReflectionsGain = 0.05f;
622 effect->Reverb.ReflectionsDelay = 0.007f;
623 effect->Reverb.LateReverbGain = 1.26f;
624 effect->Reverb.LateReverbDelay = 0.011f;
625 effect->Reverb.AirAbsorptionGainHF = 0.994f;
626 effect->Reverb.RoomRolloffFactor = 0.0f;
627 effect->Reverb.DecayHFLimit = AL_TRUE;
628 break;