Mercurial > audio-send
view OpenAL32/alAuxEffectSlot.c @ 19:22ac5a0367cd
finally, a first pass at ear.org
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Thu, 03 Nov 2011 14:54:45 -0700 |
parents | f9476ff7637e |
children |
line wrap: on
line source
1 /**2 * OpenAL cross platform audio library3 * Copyright (C) 1999-2007 by authors.4 * This library is free software; you can redistribute it and/or5 * modify it under the terms of the GNU Library General Public6 * License as published by the Free Software Foundation; either7 * 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 of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12 * Library General Public License for more details.13 *14 * You should have received a copy of the GNU Library General Public15 * License along with this library; if not, write to the16 * 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.html19 */21 #include "config.h"23 #include <stdlib.h>24 #include <math.h>26 #include "AL/al.h"27 #include "AL/alc.h"28 #include "alMain.h"29 #include "alAuxEffectSlot.h"30 #include "alThunk.h"31 #include "alError.h"32 #include "alSource.h"35 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect);37 #define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k)))38 #define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k)))40 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)41 {42 ALCcontext *Context;43 ALCdevice *Device;45 Context = GetLockedContext();46 if(!Context) return;48 Device = Context->Device;49 if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))50 alSetError(Context, AL_INVALID_VALUE);51 else if((ALuint)n > Device->AuxiliaryEffectSlotMax - Context->EffectSlotMap.size)52 alSetError(Context, AL_INVALID_VALUE);53 else54 {55 ALenum err;56 ALsizei i, j;58 i = 0;59 while(i < n)60 {61 ALeffectslot *slot = calloc(1, sizeof(ALeffectslot));62 if(!slot || !(slot->EffectState=NoneCreate()))63 {64 free(slot);65 // We must have run out or memory66 alSetError(Context, AL_OUT_OF_MEMORY);67 alDeleteAuxiliaryEffectSlots(i, effectslots);68 break;69 }71 err = NewThunkEntry(&slot->effectslot);72 if(err == AL_NO_ERROR)73 err = InsertUIntMapEntry(&Context->EffectSlotMap, slot->effectslot, slot);74 if(err != AL_NO_ERROR)75 {76 FreeThunkEntry(slot->effectslot);77 ALEffect_Destroy(slot->EffectState);78 free(slot);80 alSetError(Context, err);81 alDeleteAuxiliaryEffectSlots(i, effectslots);82 break;83 }85 effectslots[i++] = slot->effectslot;87 slot->Gain = 1.0;88 slot->AuxSendAuto = AL_TRUE;89 slot->NeedsUpdate = AL_FALSE;90 for(j = 0;j < BUFFERSIZE;j++)91 slot->WetBuffer[j] = 0.0f;92 for(j = 0;j < 1;j++)93 {94 slot->ClickRemoval[j] = 0.0f;95 slot->PendingClicks[j] = 0.0f;96 }97 slot->refcount = 0;98 }99 }101 UnlockContext(Context);102 }104 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)105 {106 ALCcontext *Context;107 ALeffectslot *EffectSlot;108 ALboolean SlotsValid = AL_FALSE;109 ALsizei i;111 Context = GetLockedContext();112 if(!Context) return;114 if(n < 0)115 alSetError(Context, AL_INVALID_VALUE);116 else117 {118 SlotsValid = AL_TRUE;119 // Check that all effectslots are valid120 for(i = 0;i < n;i++)121 {122 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL)123 {124 alSetError(Context, AL_INVALID_NAME);125 SlotsValid = AL_FALSE;126 break;127 }128 else if(EffectSlot->refcount > 0)129 {130 alSetError(Context, AL_INVALID_NAME);131 SlotsValid = AL_FALSE;132 break;133 }134 }135 }137 if(SlotsValid)138 {139 // All effectslots are valid140 for(i = 0;i < n;i++)141 {142 // Recheck that the effectslot is valid, because there could be duplicated names143 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL)144 continue;146 ALEffect_Destroy(EffectSlot->EffectState);148 RemoveUIntMapKey(&Context->EffectSlotMap, EffectSlot->effectslot);149 FreeThunkEntry(EffectSlot->effectslot);151 memset(EffectSlot, 0, sizeof(ALeffectslot));152 free(EffectSlot);153 }154 }156 UnlockContext(Context);157 }159 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)160 {161 ALCcontext *Context;162 ALboolean result;164 Context = GetLockedContext();165 if(!Context) return AL_FALSE;167 result = (LookupEffectSlot(Context->EffectSlotMap, effectslot) ?168 AL_TRUE : AL_FALSE);170 UnlockContext(Context);172 return result;173 }175 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)176 {177 ALCdevice *Device;178 ALCcontext *Context;179 ALeffectslot *EffectSlot;181 Context = GetLockedContext();182 if(!Context) return;184 Device = Context->Device;185 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)186 {187 switch(param)188 {189 case AL_EFFECTSLOT_EFFECT: {190 ALeffect *effect = NULL;192 if(iValue == 0 ||193 (effect=LookupEffect(Device->EffectMap, iValue)) != NULL)194 {195 InitializeEffect(Context, EffectSlot, effect);196 Context->UpdateSources = AL_TRUE;197 }198 else199 alSetError(Context, AL_INVALID_VALUE);200 } break;202 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:203 if(iValue == AL_TRUE || iValue == AL_FALSE)204 {205 EffectSlot->AuxSendAuto = iValue;206 Context->UpdateSources = AL_TRUE;207 }208 else209 alSetError(Context, AL_INVALID_VALUE);210 break;212 default:213 alSetError(Context, AL_INVALID_ENUM);214 break;215 }216 }217 else218 alSetError(Context, AL_INVALID_NAME);220 UnlockContext(Context);221 }223 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)224 {225 ALCcontext *Context;227 switch(param)228 {229 case AL_EFFECTSLOT_EFFECT:230 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:231 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);232 return;233 }235 Context = GetLockedContext();236 if(!Context) return;238 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)239 {240 switch(param)241 {242 default:243 alSetError(Context, AL_INVALID_ENUM);244 break;245 }246 }247 else248 alSetError(Context, AL_INVALID_NAME);250 UnlockContext(Context);251 }253 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)254 {255 ALCcontext *Context;256 ALeffectslot *EffectSlot;258 Context = GetLockedContext();259 if(!Context) return;261 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)262 {263 switch(param)264 {265 case AL_EFFECTSLOT_GAIN:266 if(flValue >= 0.0f && flValue <= 1.0f)267 {268 EffectSlot->Gain = flValue;269 EffectSlot->NeedsUpdate = AL_TRUE;270 }271 else272 alSetError(Context, AL_INVALID_VALUE);273 break;275 default:276 alSetError(Context, AL_INVALID_ENUM);277 break;278 }279 }280 else281 alSetError(Context, AL_INVALID_NAME);283 UnlockContext(Context);284 }286 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)287 {288 ALCcontext *Context;290 switch(param)291 {292 case AL_EFFECTSLOT_GAIN:293 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);294 return;295 }297 Context = GetLockedContext();298 if(!Context) return;300 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)301 {302 switch(param)303 {304 default:305 alSetError(Context, AL_INVALID_ENUM);306 break;307 }308 }309 else310 alSetError(Context, AL_INVALID_NAME);312 UnlockContext(Context);313 }315 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)316 {317 ALCcontext *Context;318 ALeffectslot *EffectSlot;320 Context = GetLockedContext();321 if(!Context) return;323 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)324 {325 switch(param)326 {327 case AL_EFFECTSLOT_EFFECT:328 *piValue = EffectSlot->effect.effect;329 break;331 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:332 *piValue = EffectSlot->AuxSendAuto;333 break;335 default:336 alSetError(Context, AL_INVALID_ENUM);337 break;338 }339 }340 else341 alSetError(Context, AL_INVALID_NAME);343 UnlockContext(Context);344 }346 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)347 {348 ALCcontext *Context;350 switch(param)351 {352 case AL_EFFECTSLOT_EFFECT:353 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:354 alGetAuxiliaryEffectSloti(effectslot, param, piValues);355 return;356 }358 Context = GetLockedContext();359 if(!Context) return;361 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)362 {363 switch(param)364 {365 default:366 alSetError(Context, AL_INVALID_ENUM);367 break;368 }369 }370 else371 alSetError(Context, AL_INVALID_NAME);373 UnlockContext(Context);374 }376 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)377 {378 ALCcontext *Context;379 ALeffectslot *EffectSlot;381 Context = GetLockedContext();382 if(!Context) return;384 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)385 {386 switch(param)387 {388 case AL_EFFECTSLOT_GAIN:389 *pflValue = EffectSlot->Gain;390 break;392 default:393 alSetError(Context, AL_INVALID_ENUM);394 break;395 }396 }397 else398 alSetError(Context, AL_INVALID_NAME);400 UnlockContext(Context);401 }403 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)404 {405 ALCcontext *Context;407 switch(param)408 {409 case AL_EFFECTSLOT_GAIN:410 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);411 return;412 }414 Context = GetLockedContext();415 if(!Context) return;417 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)418 {419 switch(param)420 {421 default:422 alSetError(Context, AL_INVALID_ENUM);423 break;424 }425 }426 else427 alSetError(Context, AL_INVALID_NAME);429 UnlockContext(Context);430 }433 static ALvoid NoneDestroy(ALeffectState *State)434 { free(State); }435 static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)436 {437 return AL_TRUE;438 (void)State;439 (void)Device;440 }441 static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffectslot *Slot)442 {443 (void)State;444 (void)Context;445 (void)Slot;446 }447 static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])448 {449 (void)State;450 (void)Slot;451 (void)SamplesToDo;452 (void)SamplesIn;453 (void)SamplesOut;454 }455 ALeffectState *NoneCreate(void)456 {457 ALeffectState *state;459 state = calloc(1, sizeof(*state));460 if(!state)461 return NULL;463 state->Destroy = NoneDestroy;464 state->DeviceUpdate = NoneDeviceUpdate;465 state->Update = NoneUpdate;466 state->Process = NoneProcess;468 return state;469 }471 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)472 {473 if(EffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL))474 {475 ALeffectState *NewState = NULL;476 if(!effect || effect->type == AL_EFFECT_NULL)477 NewState = NoneCreate();478 else if(effect->type == AL_EFFECT_EAXREVERB)479 NewState = EAXVerbCreate();480 else if(effect->type == AL_EFFECT_REVERB)481 NewState = VerbCreate();482 else if(effect->type == AL_EFFECT_ECHO)483 NewState = EchoCreate();484 else if(effect->type == AL_EFFECT_RING_MODULATOR)485 NewState = ModulatorCreate();486 else if(effect->type == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)487 NewState = DedicatedLFECreate();488 else if(effect->type == AL_EFFECT_DEDICATED_DIALOGUE)489 NewState = DedicatedDLGCreate();490 /* No new state? An error occured.. */491 if(NewState == NULL ||492 ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)493 {494 if(NewState)495 ALEffect_Destroy(NewState);496 alSetError(Context, AL_OUT_OF_MEMORY);497 return;498 }499 if(EffectSlot->EffectState)500 ALEffect_Destroy(EffectSlot->EffectState);501 EffectSlot->EffectState = NewState;503 if(!effect)504 memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));505 else506 memcpy(&EffectSlot->effect, effect, sizeof(*effect));507 /* FIXME: This should be done asychronously, but since the EfefctState508 * object was changed, it needs an update before its Process method can509 * be called (coming changes may not guarantee an update when the510 * NeedsUpdate flag is set). */511 EffectSlot->NeedsUpdate = AL_FALSE;512 ALEffect_Update(EffectSlot->EffectState, Context, EffectSlot);513 }514 else515 {516 if(!effect)517 memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));518 else519 memcpy(&EffectSlot->effect, effect, sizeof(*effect));520 EffectSlot->NeedsUpdate = AL_TRUE;521 }522 }525 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)526 {527 ALsizei pos;528 for(pos = 0;pos < Context->EffectSlotMap.size;pos++)529 {530 ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;531 Context->EffectSlotMap.array[pos].value = NULL;533 // Release effectslot structure534 ALEffect_Destroy(temp->EffectState);536 FreeThunkEntry(temp->effectslot);537 memset(temp, 0, sizeof(ALeffectslot));538 free(temp);539 }540 }