Mercurial > audio-send
diff OpenAL32/alAuxEffectSlot.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/OpenAL32/alAuxEffectSlot.c Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,540 @@ 1.4 +/** 1.5 + * OpenAL cross platform audio library 1.6 + * Copyright (C) 1999-2007 by authors. 1.7 + * This library is free software; you can redistribute it and/or 1.8 + * modify it under the terms of the GNU Library General Public 1.9 + * License as published by the Free Software Foundation; either 1.10 + * version 2 of the License, or (at your option) any later version. 1.11 + * 1.12 + * This library is distributed in the hope that it will be useful, 1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.15 + * Library General Public License for more details. 1.16 + * 1.17 + * You should have received a copy of the GNU Library General Public 1.18 + * License along with this library; if not, write to the 1.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 1.20 + * Boston, MA 02111-1307, USA. 1.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 1.22 + */ 1.23 + 1.24 +#include "config.h" 1.25 + 1.26 +#include <stdlib.h> 1.27 +#include <math.h> 1.28 + 1.29 +#include "AL/al.h" 1.30 +#include "AL/alc.h" 1.31 +#include "alMain.h" 1.32 +#include "alAuxEffectSlot.h" 1.33 +#include "alThunk.h" 1.34 +#include "alError.h" 1.35 +#include "alSource.h" 1.36 + 1.37 + 1.38 +static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect); 1.39 + 1.40 +#define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k))) 1.41 +#define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k))) 1.42 + 1.43 +AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) 1.44 +{ 1.45 + ALCcontext *Context; 1.46 + ALCdevice *Device; 1.47 + 1.48 + Context = GetLockedContext(); 1.49 + if(!Context) return; 1.50 + 1.51 + Device = Context->Device; 1.52 + if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint))) 1.53 + alSetError(Context, AL_INVALID_VALUE); 1.54 + else if((ALuint)n > Device->AuxiliaryEffectSlotMax - Context->EffectSlotMap.size) 1.55 + alSetError(Context, AL_INVALID_VALUE); 1.56 + else 1.57 + { 1.58 + ALenum err; 1.59 + ALsizei i, j; 1.60 + 1.61 + i = 0; 1.62 + while(i < n) 1.63 + { 1.64 + ALeffectslot *slot = calloc(1, sizeof(ALeffectslot)); 1.65 + if(!slot || !(slot->EffectState=NoneCreate())) 1.66 + { 1.67 + free(slot); 1.68 + // We must have run out or memory 1.69 + alSetError(Context, AL_OUT_OF_MEMORY); 1.70 + alDeleteAuxiliaryEffectSlots(i, effectslots); 1.71 + break; 1.72 + } 1.73 + 1.74 + err = NewThunkEntry(&slot->effectslot); 1.75 + if(err == AL_NO_ERROR) 1.76 + err = InsertUIntMapEntry(&Context->EffectSlotMap, slot->effectslot, slot); 1.77 + if(err != AL_NO_ERROR) 1.78 + { 1.79 + FreeThunkEntry(slot->effectslot); 1.80 + ALEffect_Destroy(slot->EffectState); 1.81 + free(slot); 1.82 + 1.83 + alSetError(Context, err); 1.84 + alDeleteAuxiliaryEffectSlots(i, effectslots); 1.85 + break; 1.86 + } 1.87 + 1.88 + effectslots[i++] = slot->effectslot; 1.89 + 1.90 + slot->Gain = 1.0; 1.91 + slot->AuxSendAuto = AL_TRUE; 1.92 + slot->NeedsUpdate = AL_FALSE; 1.93 + for(j = 0;j < BUFFERSIZE;j++) 1.94 + slot->WetBuffer[j] = 0.0f; 1.95 + for(j = 0;j < 1;j++) 1.96 + { 1.97 + slot->ClickRemoval[j] = 0.0f; 1.98 + slot->PendingClicks[j] = 0.0f; 1.99 + } 1.100 + slot->refcount = 0; 1.101 + } 1.102 + } 1.103 + 1.104 + UnlockContext(Context); 1.105 +} 1.106 + 1.107 +AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) 1.108 +{ 1.109 + ALCcontext *Context; 1.110 + ALeffectslot *EffectSlot; 1.111 + ALboolean SlotsValid = AL_FALSE; 1.112 + ALsizei i; 1.113 + 1.114 + Context = GetLockedContext(); 1.115 + if(!Context) return; 1.116 + 1.117 + if(n < 0) 1.118 + alSetError(Context, AL_INVALID_VALUE); 1.119 + else 1.120 + { 1.121 + SlotsValid = AL_TRUE; 1.122 + // Check that all effectslots are valid 1.123 + for(i = 0;i < n;i++) 1.124 + { 1.125 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL) 1.126 + { 1.127 + alSetError(Context, AL_INVALID_NAME); 1.128 + SlotsValid = AL_FALSE; 1.129 + break; 1.130 + } 1.131 + else if(EffectSlot->refcount > 0) 1.132 + { 1.133 + alSetError(Context, AL_INVALID_NAME); 1.134 + SlotsValid = AL_FALSE; 1.135 + break; 1.136 + } 1.137 + } 1.138 + } 1.139 + 1.140 + if(SlotsValid) 1.141 + { 1.142 + // All effectslots are valid 1.143 + for(i = 0;i < n;i++) 1.144 + { 1.145 + // Recheck that the effectslot is valid, because there could be duplicated names 1.146 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL) 1.147 + continue; 1.148 + 1.149 + ALEffect_Destroy(EffectSlot->EffectState); 1.150 + 1.151 + RemoveUIntMapKey(&Context->EffectSlotMap, EffectSlot->effectslot); 1.152 + FreeThunkEntry(EffectSlot->effectslot); 1.153 + 1.154 + memset(EffectSlot, 0, sizeof(ALeffectslot)); 1.155 + free(EffectSlot); 1.156 + } 1.157 + } 1.158 + 1.159 + UnlockContext(Context); 1.160 +} 1.161 + 1.162 +AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot) 1.163 +{ 1.164 + ALCcontext *Context; 1.165 + ALboolean result; 1.166 + 1.167 + Context = GetLockedContext(); 1.168 + if(!Context) return AL_FALSE; 1.169 + 1.170 + result = (LookupEffectSlot(Context->EffectSlotMap, effectslot) ? 1.171 + AL_TRUE : AL_FALSE); 1.172 + 1.173 + UnlockContext(Context); 1.174 + 1.175 + return result; 1.176 +} 1.177 + 1.178 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue) 1.179 +{ 1.180 + ALCdevice *Device; 1.181 + ALCcontext *Context; 1.182 + ALeffectslot *EffectSlot; 1.183 + 1.184 + Context = GetLockedContext(); 1.185 + if(!Context) return; 1.186 + 1.187 + Device = Context->Device; 1.188 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL) 1.189 + { 1.190 + switch(param) 1.191 + { 1.192 + case AL_EFFECTSLOT_EFFECT: { 1.193 + ALeffect *effect = NULL; 1.194 + 1.195 + if(iValue == 0 || 1.196 + (effect=LookupEffect(Device->EffectMap, iValue)) != NULL) 1.197 + { 1.198 + InitializeEffect(Context, EffectSlot, effect); 1.199 + Context->UpdateSources = AL_TRUE; 1.200 + } 1.201 + else 1.202 + alSetError(Context, AL_INVALID_VALUE); 1.203 + } break; 1.204 + 1.205 + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: 1.206 + if(iValue == AL_TRUE || iValue == AL_FALSE) 1.207 + { 1.208 + EffectSlot->AuxSendAuto = iValue; 1.209 + Context->UpdateSources = AL_TRUE; 1.210 + } 1.211 + else 1.212 + alSetError(Context, AL_INVALID_VALUE); 1.213 + break; 1.214 + 1.215 + default: 1.216 + alSetError(Context, AL_INVALID_ENUM); 1.217 + break; 1.218 + } 1.219 + } 1.220 + else 1.221 + alSetError(Context, AL_INVALID_NAME); 1.222 + 1.223 + UnlockContext(Context); 1.224 +} 1.225 + 1.226 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) 1.227 +{ 1.228 + ALCcontext *Context; 1.229 + 1.230 + switch(param) 1.231 + { 1.232 + case AL_EFFECTSLOT_EFFECT: 1.233 + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: 1.234 + alAuxiliaryEffectSloti(effectslot, param, piValues[0]); 1.235 + return; 1.236 + } 1.237 + 1.238 + Context = GetLockedContext(); 1.239 + if(!Context) return; 1.240 + 1.241 + if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL) 1.242 + { 1.243 + switch(param) 1.244 + { 1.245 + default: 1.246 + alSetError(Context, AL_INVALID_ENUM); 1.247 + break; 1.248 + } 1.249 + } 1.250 + else 1.251 + alSetError(Context, AL_INVALID_NAME); 1.252 + 1.253 + UnlockContext(Context); 1.254 +} 1.255 + 1.256 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue) 1.257 +{ 1.258 + ALCcontext *Context; 1.259 + ALeffectslot *EffectSlot; 1.260 + 1.261 + Context = GetLockedContext(); 1.262 + if(!Context) return; 1.263 + 1.264 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL) 1.265 + { 1.266 + switch(param) 1.267 + { 1.268 + case AL_EFFECTSLOT_GAIN: 1.269 + if(flValue >= 0.0f && flValue <= 1.0f) 1.270 + { 1.271 + EffectSlot->Gain = flValue; 1.272 + EffectSlot->NeedsUpdate = AL_TRUE; 1.273 + } 1.274 + else 1.275 + alSetError(Context, AL_INVALID_VALUE); 1.276 + break; 1.277 + 1.278 + default: 1.279 + alSetError(Context, AL_INVALID_ENUM); 1.280 + break; 1.281 + } 1.282 + } 1.283 + else 1.284 + alSetError(Context, AL_INVALID_NAME); 1.285 + 1.286 + UnlockContext(Context); 1.287 +} 1.288 + 1.289 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) 1.290 +{ 1.291 + ALCcontext *Context; 1.292 + 1.293 + switch(param) 1.294 + { 1.295 + case AL_EFFECTSLOT_GAIN: 1.296 + alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]); 1.297 + return; 1.298 + } 1.299 + 1.300 + Context = GetLockedContext(); 1.301 + if(!Context) return; 1.302 + 1.303 + if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL) 1.304 + { 1.305 + switch(param) 1.306 + { 1.307 + default: 1.308 + alSetError(Context, AL_INVALID_ENUM); 1.309 + break; 1.310 + } 1.311 + } 1.312 + else 1.313 + alSetError(Context, AL_INVALID_NAME); 1.314 + 1.315 + UnlockContext(Context); 1.316 +} 1.317 + 1.318 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue) 1.319 +{ 1.320 + ALCcontext *Context; 1.321 + ALeffectslot *EffectSlot; 1.322 + 1.323 + Context = GetLockedContext(); 1.324 + if(!Context) return; 1.325 + 1.326 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL) 1.327 + { 1.328 + switch(param) 1.329 + { 1.330 + case AL_EFFECTSLOT_EFFECT: 1.331 + *piValue = EffectSlot->effect.effect; 1.332 + break; 1.333 + 1.334 + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: 1.335 + *piValue = EffectSlot->AuxSendAuto; 1.336 + break; 1.337 + 1.338 + default: 1.339 + alSetError(Context, AL_INVALID_ENUM); 1.340 + break; 1.341 + } 1.342 + } 1.343 + else 1.344 + alSetError(Context, AL_INVALID_NAME); 1.345 + 1.346 + UnlockContext(Context); 1.347 +} 1.348 + 1.349 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) 1.350 +{ 1.351 + ALCcontext *Context; 1.352 + 1.353 + switch(param) 1.354 + { 1.355 + case AL_EFFECTSLOT_EFFECT: 1.356 + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: 1.357 + alGetAuxiliaryEffectSloti(effectslot, param, piValues); 1.358 + return; 1.359 + } 1.360 + 1.361 + Context = GetLockedContext(); 1.362 + if(!Context) return; 1.363 + 1.364 + if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL) 1.365 + { 1.366 + switch(param) 1.367 + { 1.368 + default: 1.369 + alSetError(Context, AL_INVALID_ENUM); 1.370 + break; 1.371 + } 1.372 + } 1.373 + else 1.374 + alSetError(Context, AL_INVALID_NAME); 1.375 + 1.376 + UnlockContext(Context); 1.377 +} 1.378 + 1.379 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue) 1.380 +{ 1.381 + ALCcontext *Context; 1.382 + ALeffectslot *EffectSlot; 1.383 + 1.384 + Context = GetLockedContext(); 1.385 + if(!Context) return; 1.386 + 1.387 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL) 1.388 + { 1.389 + switch(param) 1.390 + { 1.391 + case AL_EFFECTSLOT_GAIN: 1.392 + *pflValue = EffectSlot->Gain; 1.393 + break; 1.394 + 1.395 + default: 1.396 + alSetError(Context, AL_INVALID_ENUM); 1.397 + break; 1.398 + } 1.399 + } 1.400 + else 1.401 + alSetError(Context, AL_INVALID_NAME); 1.402 + 1.403 + UnlockContext(Context); 1.404 +} 1.405 + 1.406 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) 1.407 +{ 1.408 + ALCcontext *Context; 1.409 + 1.410 + switch(param) 1.411 + { 1.412 + case AL_EFFECTSLOT_GAIN: 1.413 + alGetAuxiliaryEffectSlotf(effectslot, param, pflValues); 1.414 + return; 1.415 + } 1.416 + 1.417 + Context = GetLockedContext(); 1.418 + if(!Context) return; 1.419 + 1.420 + if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL) 1.421 + { 1.422 + switch(param) 1.423 + { 1.424 + default: 1.425 + alSetError(Context, AL_INVALID_ENUM); 1.426 + break; 1.427 + } 1.428 + } 1.429 + else 1.430 + alSetError(Context, AL_INVALID_NAME); 1.431 + 1.432 + UnlockContext(Context); 1.433 +} 1.434 + 1.435 + 1.436 +static ALvoid NoneDestroy(ALeffectState *State) 1.437 +{ free(State); } 1.438 +static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device) 1.439 +{ 1.440 + return AL_TRUE; 1.441 + (void)State; 1.442 + (void)Device; 1.443 +} 1.444 +static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffectslot *Slot) 1.445 +{ 1.446 + (void)State; 1.447 + (void)Context; 1.448 + (void)Slot; 1.449 +} 1.450 +static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) 1.451 +{ 1.452 + (void)State; 1.453 + (void)Slot; 1.454 + (void)SamplesToDo; 1.455 + (void)SamplesIn; 1.456 + (void)SamplesOut; 1.457 +} 1.458 +ALeffectState *NoneCreate(void) 1.459 +{ 1.460 + ALeffectState *state; 1.461 + 1.462 + state = calloc(1, sizeof(*state)); 1.463 + if(!state) 1.464 + return NULL; 1.465 + 1.466 + state->Destroy = NoneDestroy; 1.467 + state->DeviceUpdate = NoneDeviceUpdate; 1.468 + state->Update = NoneUpdate; 1.469 + state->Process = NoneProcess; 1.470 + 1.471 + return state; 1.472 +} 1.473 + 1.474 +static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect) 1.475 +{ 1.476 + if(EffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL)) 1.477 + { 1.478 + ALeffectState *NewState = NULL; 1.479 + if(!effect || effect->type == AL_EFFECT_NULL) 1.480 + NewState = NoneCreate(); 1.481 + else if(effect->type == AL_EFFECT_EAXREVERB) 1.482 + NewState = EAXVerbCreate(); 1.483 + else if(effect->type == AL_EFFECT_REVERB) 1.484 + NewState = VerbCreate(); 1.485 + else if(effect->type == AL_EFFECT_ECHO) 1.486 + NewState = EchoCreate(); 1.487 + else if(effect->type == AL_EFFECT_RING_MODULATOR) 1.488 + NewState = ModulatorCreate(); 1.489 + else if(effect->type == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT) 1.490 + NewState = DedicatedLFECreate(); 1.491 + else if(effect->type == AL_EFFECT_DEDICATED_DIALOGUE) 1.492 + NewState = DedicatedDLGCreate(); 1.493 + /* No new state? An error occured.. */ 1.494 + if(NewState == NULL || 1.495 + ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE) 1.496 + { 1.497 + if(NewState) 1.498 + ALEffect_Destroy(NewState); 1.499 + alSetError(Context, AL_OUT_OF_MEMORY); 1.500 + return; 1.501 + } 1.502 + if(EffectSlot->EffectState) 1.503 + ALEffect_Destroy(EffectSlot->EffectState); 1.504 + EffectSlot->EffectState = NewState; 1.505 + 1.506 + if(!effect) 1.507 + memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect)); 1.508 + else 1.509 + memcpy(&EffectSlot->effect, effect, sizeof(*effect)); 1.510 + /* FIXME: This should be done asychronously, but since the EfefctState 1.511 + * object was changed, it needs an update before its Process method can 1.512 + * be called (coming changes may not guarantee an update when the 1.513 + * NeedsUpdate flag is set). */ 1.514 + EffectSlot->NeedsUpdate = AL_FALSE; 1.515 + ALEffect_Update(EffectSlot->EffectState, Context, EffectSlot); 1.516 + } 1.517 + else 1.518 + { 1.519 + if(!effect) 1.520 + memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect)); 1.521 + else 1.522 + memcpy(&EffectSlot->effect, effect, sizeof(*effect)); 1.523 + EffectSlot->NeedsUpdate = AL_TRUE; 1.524 + } 1.525 +} 1.526 + 1.527 + 1.528 +ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context) 1.529 +{ 1.530 + ALsizei pos; 1.531 + for(pos = 0;pos < Context->EffectSlotMap.size;pos++) 1.532 + { 1.533 + ALeffectslot *temp = Context->EffectSlotMap.array[pos].value; 1.534 + Context->EffectSlotMap.array[pos].value = NULL; 1.535 + 1.536 + // Release effectslot structure 1.537 + ALEffect_Destroy(temp->EffectState); 1.538 + 1.539 + FreeThunkEntry(temp->effectslot); 1.540 + memset(temp, 0, sizeof(ALeffectslot)); 1.541 + free(temp); 1.542 + } 1.543 +}