Mercurial > fife-parpg
diff ext/openal-soft/OpenAL32/alAuxEffectSlot.c @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/openal-soft/OpenAL32/alAuxEffectSlot.c Sun Jun 29 18:44:17 2008 +0000 @@ -0,0 +1,541 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2007 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include <stdlib.h> +#include <math.h> + +#include "AL/al.h" +#include "AL/alc.h" +#include "alMain.h" +#include "alAuxEffectSlot.h" +#include "alThunk.h" +#include "alError.h" + + +static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect); + + +AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) +{ + ALCcontext *Context; + ALsizei i; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (n > 0) + { + /* NOTE: We only support one slot currently */ + if(n == 1 && Context->AuxiliaryEffectSlotCount == 0) + { + // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots + if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint))) + { + ALeffectslot **list = &Context->AuxiliaryEffectSlot; + while(*list) + list = &(*list)->next; + + i = 0; + while(i < n) + { + *list = calloc(1, sizeof(ALeffectslot)); + if(!(*list)) + { + // We must have run out or memory + alDeleteAuxiliaryEffectSlots(i, effectslots); + alSetError(AL_OUT_OF_MEMORY); + break; + } + + (*list)->Gain = 1.0; + (*list)->AuxSendAuto = AL_TRUE; + (*list)->refcount = 0; + + effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list); + (*list)->effectslot = effectslots[i]; + + Context->AuxiliaryEffectSlotCount++; + i++; + + list = &(*list)->next; + } + } + } + else + alSetError(AL_INVALID_OPERATION); + } + + ProcessContext(Context); +} + +AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) +{ + ALCcontext *Context; + ALeffectslot *ALAuxiliaryEffectSlot; + ALsizei i; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (n >= 0) + { + // Check that all effectslots are valid + for (i = 0; i < n; i++) + { + if (!alIsAuxiliaryEffectSlot(effectslots[i])) + { + alSetError(AL_INVALID_NAME); + break; + } + else + { + ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]); + if(ALAuxiliaryEffectSlot->refcount > 0) + { + alSetError(AL_INVALID_NAME); + break; + } + } + } + + if (i == n) + { + // All effectslots are valid + for (i = 0; i < n; i++) + { + // Recheck that the effectslot is valid, because there could be duplicated names + if (alIsAuxiliaryEffectSlot(effectslots[i])) + { + ALeffectslot **list; + + ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i])); + + // Remove Source from list of Sources + list = &Context->AuxiliaryEffectSlot; + while(*list && *list != ALAuxiliaryEffectSlot) + list = &(*list)->next; + + if(*list) + *list = (*list)->next; + ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot); + + free(ALAuxiliaryEffectSlot->ReverbBuffer); + + memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot)); + free(ALAuxiliaryEffectSlot); + + Context->AuxiliaryEffectSlotCount--; + } + } + } + } + else + alSetError(AL_INVALID_VALUE); + + ProcessContext(Context); +} + +AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot) +{ + ALCcontext *Context; + ALeffectslot **list; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return AL_FALSE; + } + SuspendContext(Context); + + list = &Context->AuxiliaryEffectSlot; + while(*list && (*list)->effectslot != effectslot) + list = &(*list)->next; + + ProcessContext(Context); + + return (*list ? AL_TRUE : AL_FALSE); +} + +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue) +{ + ALCcontext *Context; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (alIsAuxiliaryEffectSlot(effectslot)) + { + ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot); + + switch(param) + { + case AL_EFFECTSLOT_EFFECT: + if(alIsEffect(iValue)) + { + ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue); + InitializeEffect(Context, ALEffectSlot, effect); + } + else + alSetError(AL_INVALID_VALUE); + break; + + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: + if(iValue == AL_TRUE || iValue == AL_FALSE) + ALEffectSlot->AuxSendAuto = iValue; + else + alSetError(AL_INVALID_VALUE); + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(Context); +} + +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) +{ + ALCcontext *Context; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (alIsAuxiliaryEffectSlot(effectslot)) + { + switch(param) + { + case AL_EFFECTSLOT_EFFECT: + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: + alAuxiliaryEffectSloti(effectslot, param, piValues[0]); + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(Context); +} + +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue) +{ + ALCcontext *Context; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (alIsAuxiliaryEffectSlot(effectslot)) + { + ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot); + + switch(param) + { + case AL_EFFECTSLOT_GAIN: + if(flValue >= 0.0f && flValue <= 1.0f) + ALEffectSlot->Gain = flValue; + else + alSetError(AL_INVALID_VALUE); + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(Context); +} + +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) +{ + ALCcontext *Context; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (alIsAuxiliaryEffectSlot(effectslot)) + { + switch(param) + { + case AL_EFFECTSLOT_GAIN: + alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]); + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(Context); +} + +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue) +{ + ALCcontext *Context; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (alIsAuxiliaryEffectSlot(effectslot)) + { + ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot); + + switch(param) + { + case AL_EFFECTSLOT_EFFECT: + *piValue = ALEffectSlot->effect.effect; + break; + + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: + *piValue = ALEffectSlot->AuxSendAuto; + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(Context); +} + +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) +{ + ALCcontext *Context; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (alIsAuxiliaryEffectSlot(effectslot)) + { + switch(param) + { + case AL_EFFECTSLOT_EFFECT: + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: + alGetAuxiliaryEffectSloti(effectslot, param, piValues); + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(Context); +} + +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue) +{ + ALCcontext *Context; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (alIsAuxiliaryEffectSlot(effectslot)) + { + ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot); + + switch(param) + { + case AL_EFFECTSLOT_GAIN: + *pflValue = ALEffectSlot->Gain; + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(Context); +} + +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) +{ + ALCcontext *Context; + + Context = alcGetCurrentContext(); + if(!Context) + { + alSetError(AL_INVALID_OPERATION); + return; + } + SuspendContext(Context); + + if (alIsAuxiliaryEffectSlot(effectslot)) + { + switch(param) + { + case AL_EFFECTSLOT_GAIN: + alGetAuxiliaryEffectSlotf(effectslot, param, pflValues); + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(Context); +} + + +static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect) +{ + ALfloat *ptr = NULL; + + if(!effect) + { + memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect)); + goto done; + } + + if(effect->type == AL_EFFECT_REVERB) + { + ALuint size; + ALfloat reverbwait; + + reverbwait = (1.0f-effect->Reverb.Density)*(0.1f-0.075f) + 0.075f; + + size = (ALuint)((ALfloat)Context->Frequency * + (effect->Reverb.ReflectionsDelay + + effect->Reverb.LateReverbDelay + + reverbwait)) + 1; + + ptr = calloc(size, sizeof(ALfloat)); + if(!ptr) + { + alSetError(AL_OUT_OF_MEMORY); + return; + } + if(ALEffectSlot->ReverbBuffer) + memcpy(ptr, ALEffectSlot->ReverbBuffer, min(size, ALEffectSlot->ReverbLength)*sizeof(ALfloat)); + ALEffectSlot->ReverbLength = size; + ALEffectSlot->ReverbPos %= size; + ALEffectSlot->ReverbReflectPos = (ALuint)(ALEffectSlot->ReverbLength - + ((ALfloat)Context->Frequency * + effect->Reverb.ReflectionsDelay) + + ALEffectSlot->ReverbPos) % + ALEffectSlot->ReverbLength; + ALEffectSlot->ReverbLatePos = (ALuint)(ALEffectSlot->ReverbLength - + ((ALfloat)Context->Frequency * + (effect->Reverb.LateReverbDelay + + effect->Reverb.ReflectionsDelay)) + + ALEffectSlot->ReverbPos) % + ALEffectSlot->ReverbLength; + ALEffectSlot->ReverbDecayGain = pow(1.0/32768.0, 1.0/(effect->Reverb.DecayTime/reverbwait)); + } + + memcpy(&ALEffectSlot->effect, effect, sizeof(*effect)); +done: + free(ALEffectSlot->ReverbBuffer); + ALEffectSlot->ReverbBuffer = ptr; +} + + +ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context) +{ +#ifdef _DEBUG + if(Context->AuxiliaryEffectSlotCount > 0) + AL_PRINT("alcDestroyContext(): %d AuxiliaryEffectSlot(s) NOT deleted\n", Context->AuxiliaryEffectSlotCount); +#endif + + while(Context->AuxiliaryEffectSlot) + { + ALeffectslot *temp = Context->AuxiliaryEffectSlot; + Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next; + + // Release effectslot structure + free(temp->ReverbBuffer); + ALTHUNK_REMOVEENTRY(temp->effectslot); + + memset(temp, 0, sizeof(ALeffectslot)); + free(temp); + } + Context->AuxiliaryEffectSlotCount = 0; +}