Mercurial > audio-send
diff OpenAL32/alSource.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/alSource.c Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,2172 @@ 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 +#include <float.h> 1.29 +#include "alMain.h" 1.30 +#include "AL/al.h" 1.31 +#include "AL/alc.h" 1.32 +#include "alError.h" 1.33 +#include "alSource.h" 1.34 +#include "alBuffer.h" 1.35 +#include "alThunk.h" 1.36 +#include "alAuxEffectSlot.h" 1.37 + 1.38 + 1.39 +enum Resampler DefaultResampler; 1.40 +const ALsizei ResamplerPadding[RESAMPLER_MAX] = { 1.41 + 0, /* Point */ 1.42 + 1, /* Linear */ 1.43 + 2, /* Cubic */ 1.44 +}; 1.45 +const ALsizei ResamplerPrePadding[RESAMPLER_MAX] = { 1.46 + 0, /* Point */ 1.47 + 0, /* Linear */ 1.48 + 1, /* Cubic */ 1.49 +}; 1.50 + 1.51 + 1.52 +static ALvoid InitSourceParams(ALsource *Source); 1.53 +static ALvoid GetSourceOffset(ALsource *Source, ALenum eName, ALdouble *Offsets, ALdouble updateLen); 1.54 +static ALint GetByteOffset(ALsource *Source); 1.55 + 1.56 +#define LookupSource(m, k) ((ALsource*)LookupUIntMapKey(&(m), (k))) 1.57 +#define LookupBuffer(m, k) ((ALbuffer*)LookupUIntMapKey(&(m), (k))) 1.58 +#define LookupFilter(m, k) ((ALfilter*)LookupUIntMapKey(&(m), (k))) 1.59 +#define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k))) 1.60 + 1.61 +AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n,ALuint *sources) 1.62 +{ 1.63 + ALCcontext *Context; 1.64 + ALCdevice *Device; 1.65 + 1.66 + Context = GetLockedContext(); 1.67 + if(!Context) return; 1.68 + 1.69 + Device = Context->Device; 1.70 + if(n < 0 || IsBadWritePtr((void*)sources, n * sizeof(ALuint))) 1.71 + alSetError(Context, AL_INVALID_VALUE); 1.72 + else if((ALuint)n > Device->MaxNoOfSources - Context->SourceMap.size) 1.73 + alSetError(Context, AL_INVALID_VALUE); 1.74 + else 1.75 + { 1.76 + ALenum err; 1.77 + ALsizei i; 1.78 + 1.79 + // Add additional sources to the list 1.80 + i = 0; 1.81 + while(i < n) 1.82 + { 1.83 + ALsource *source = calloc(1, sizeof(ALsource)); 1.84 + if(!source) 1.85 + { 1.86 + alSetError(Context, AL_OUT_OF_MEMORY); 1.87 + alDeleteSources(i, sources); 1.88 + break; 1.89 + } 1.90 + 1.91 + err = NewThunkEntry(&source->source); 1.92 + if(err == AL_NO_ERROR) 1.93 + err = InsertUIntMapEntry(&Context->SourceMap, source->source, source); 1.94 + if(err != AL_NO_ERROR) 1.95 + { 1.96 + FreeThunkEntry(source->source); 1.97 + memset(source, 0, sizeof(ALsource)); 1.98 + free(source); 1.99 + 1.100 + alSetError(Context, err); 1.101 + alDeleteSources(i, sources); 1.102 + break; 1.103 + } 1.104 + 1.105 + sources[i++] = source->source; 1.106 + InitSourceParams(source); 1.107 + } 1.108 + } 1.109 + 1.110 + UnlockContext(Context); 1.111 +} 1.112 + 1.113 + 1.114 +AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) 1.115 +{ 1.116 + ALCcontext *Context; 1.117 + ALsource *Source; 1.118 + ALsizei i, j; 1.119 + ALbufferlistitem *BufferList; 1.120 + ALboolean SourcesValid = AL_FALSE; 1.121 + 1.122 + Context = GetLockedContext(); 1.123 + if(!Context) return; 1.124 + 1.125 + if(n < 0) 1.126 + alSetError(Context, AL_INVALID_VALUE); 1.127 + else 1.128 + { 1.129 + SourcesValid = AL_TRUE; 1.130 + // Check that all Sources are valid (and can therefore be deleted) 1.131 + for(i = 0;i < n;i++) 1.132 + { 1.133 + if(LookupSource(Context->SourceMap, sources[i]) == NULL) 1.134 + { 1.135 + alSetError(Context, AL_INVALID_NAME); 1.136 + SourcesValid = AL_FALSE; 1.137 + break; 1.138 + } 1.139 + } 1.140 + } 1.141 + 1.142 + if(SourcesValid) 1.143 + { 1.144 + // All Sources are valid, and can be deleted 1.145 + for(i = 0;i < n;i++) 1.146 + { 1.147 + // Recheck that the Source is valid, because there could be duplicated Source names 1.148 + if((Source=LookupSource(Context->SourceMap, sources[i])) == NULL) 1.149 + continue; 1.150 + 1.151 + for(j = 0;j < Context->ActiveSourceCount;j++) 1.152 + { 1.153 + if(Context->ActiveSources[j] == Source) 1.154 + { 1.155 + ALsizei end = --(Context->ActiveSourceCount); 1.156 + Context->ActiveSources[j] = Context->ActiveSources[end]; 1.157 + break; 1.158 + } 1.159 + } 1.160 + 1.161 + // For each buffer in the source's queue... 1.162 + while(Source->queue != NULL) 1.163 + { 1.164 + BufferList = Source->queue; 1.165 + Source->queue = BufferList->next; 1.166 + 1.167 + if(BufferList->buffer != NULL) 1.168 + BufferList->buffer->refcount--; 1.169 + free(BufferList); 1.170 + } 1.171 + 1.172 + for(j = 0;j < MAX_SENDS;++j) 1.173 + { 1.174 + if(Source->Send[j].Slot) 1.175 + Source->Send[j].Slot->refcount--; 1.176 + Source->Send[j].Slot = NULL; 1.177 + } 1.178 + 1.179 + // Remove Source from list of Sources 1.180 + RemoveUIntMapKey(&Context->SourceMap, Source->source); 1.181 + FreeThunkEntry(Source->source); 1.182 + 1.183 + memset(Source,0,sizeof(ALsource)); 1.184 + free(Source); 1.185 + } 1.186 + } 1.187 + 1.188 + UnlockContext(Context); 1.189 +} 1.190 + 1.191 + 1.192 +AL_API ALboolean AL_APIENTRY alIsSource(ALuint source) 1.193 +{ 1.194 + ALCcontext *Context; 1.195 + ALboolean result; 1.196 + 1.197 + Context = GetLockedContext(); 1.198 + if(!Context) return AL_FALSE; 1.199 + 1.200 + result = (LookupSource(Context->SourceMap, source) ? AL_TRUE : AL_FALSE); 1.201 + 1.202 + UnlockContext(Context); 1.203 + 1.204 + return result; 1.205 +} 1.206 + 1.207 + 1.208 +AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue) 1.209 +{ 1.210 + ALCcontext *pContext; 1.211 + ALsource *Source; 1.212 + 1.213 + pContext = GetLockedContext(); 1.214 + if(!pContext) return; 1.215 + 1.216 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.217 + { 1.218 + switch(eParam) 1.219 + { 1.220 + case AL_PITCH: 1.221 + if(flValue >= 0.0f) 1.222 + { 1.223 + Source->flPitch = flValue; 1.224 + Source->NeedsUpdate = AL_TRUE; 1.225 + } 1.226 + else 1.227 + alSetError(pContext, AL_INVALID_VALUE); 1.228 + break; 1.229 + 1.230 + case AL_CONE_INNER_ANGLE: 1.231 + if(flValue >= 0.0f && flValue <= 360.0f) 1.232 + { 1.233 + Source->flInnerAngle = flValue; 1.234 + Source->NeedsUpdate = AL_TRUE; 1.235 + } 1.236 + else 1.237 + alSetError(pContext, AL_INVALID_VALUE); 1.238 + break; 1.239 + 1.240 + case AL_CONE_OUTER_ANGLE: 1.241 + if(flValue >= 0.0f && flValue <= 360.0f) 1.242 + { 1.243 + Source->flOuterAngle = flValue; 1.244 + Source->NeedsUpdate = AL_TRUE; 1.245 + } 1.246 + else 1.247 + alSetError(pContext, AL_INVALID_VALUE); 1.248 + break; 1.249 + 1.250 + case AL_GAIN: 1.251 + if(flValue >= 0.0f) 1.252 + { 1.253 + Source->flGain = flValue; 1.254 + Source->NeedsUpdate = AL_TRUE; 1.255 + } 1.256 + else 1.257 + alSetError(pContext, AL_INVALID_VALUE); 1.258 + break; 1.259 + 1.260 + case AL_MAX_DISTANCE: 1.261 + if(flValue >= 0.0f) 1.262 + { 1.263 + Source->flMaxDistance = flValue; 1.264 + Source->NeedsUpdate = AL_TRUE; 1.265 + } 1.266 + else 1.267 + alSetError(pContext, AL_INVALID_VALUE); 1.268 + break; 1.269 + 1.270 + case AL_ROLLOFF_FACTOR: 1.271 + if(flValue >= 0.0f) 1.272 + { 1.273 + Source->flRollOffFactor = flValue; 1.274 + Source->NeedsUpdate = AL_TRUE; 1.275 + } 1.276 + else 1.277 + alSetError(pContext, AL_INVALID_VALUE); 1.278 + break; 1.279 + 1.280 + case AL_REFERENCE_DISTANCE: 1.281 + if(flValue >= 0.0f) 1.282 + { 1.283 + Source->flRefDistance = flValue; 1.284 + Source->NeedsUpdate = AL_TRUE; 1.285 + } 1.286 + else 1.287 + alSetError(pContext, AL_INVALID_VALUE); 1.288 + break; 1.289 + 1.290 + case AL_MIN_GAIN: 1.291 + if(flValue >= 0.0f && flValue <= 1.0f) 1.292 + { 1.293 + Source->flMinGain = flValue; 1.294 + Source->NeedsUpdate = AL_TRUE; 1.295 + } 1.296 + else 1.297 + alSetError(pContext, AL_INVALID_VALUE); 1.298 + break; 1.299 + 1.300 + case AL_MAX_GAIN: 1.301 + if(flValue >= 0.0f && flValue <= 1.0f) 1.302 + { 1.303 + Source->flMaxGain = flValue; 1.304 + Source->NeedsUpdate = AL_TRUE; 1.305 + } 1.306 + else 1.307 + alSetError(pContext, AL_INVALID_VALUE); 1.308 + break; 1.309 + 1.310 + case AL_CONE_OUTER_GAIN: 1.311 + if(flValue >= 0.0f && flValue <= 1.0f) 1.312 + { 1.313 + Source->flOuterGain = flValue; 1.314 + Source->NeedsUpdate = AL_TRUE; 1.315 + } 1.316 + else 1.317 + alSetError(pContext, AL_INVALID_VALUE); 1.318 + break; 1.319 + 1.320 + case AL_CONE_OUTER_GAINHF: 1.321 + if(flValue >= 0.0f && flValue <= 1.0f) 1.322 + { 1.323 + Source->OuterGainHF = flValue; 1.324 + Source->NeedsUpdate = AL_TRUE; 1.325 + } 1.326 + else 1.327 + alSetError(pContext, AL_INVALID_VALUE); 1.328 + break; 1.329 + 1.330 + case AL_AIR_ABSORPTION_FACTOR: 1.331 + if(flValue >= 0.0f && flValue <= 10.0f) 1.332 + { 1.333 + Source->AirAbsorptionFactor = flValue; 1.334 + Source->NeedsUpdate = AL_TRUE; 1.335 + } 1.336 + else 1.337 + alSetError(pContext, AL_INVALID_VALUE); 1.338 + break; 1.339 + 1.340 + case AL_ROOM_ROLLOFF_FACTOR: 1.341 + if(flValue >= 0.0f && flValue <= 10.0f) 1.342 + { 1.343 + Source->RoomRolloffFactor = flValue; 1.344 + Source->NeedsUpdate = AL_TRUE; 1.345 + } 1.346 + else 1.347 + alSetError(pContext, AL_INVALID_VALUE); 1.348 + break; 1.349 + 1.350 + case AL_DOPPLER_FACTOR: 1.351 + if(flValue >= 0.0f && flValue <= 1.0f) 1.352 + { 1.353 + Source->DopplerFactor = flValue; 1.354 + Source->NeedsUpdate = AL_TRUE; 1.355 + } 1.356 + else 1.357 + alSetError(pContext, AL_INVALID_VALUE); 1.358 + break; 1.359 + 1.360 + case AL_SEC_OFFSET: 1.361 + case AL_SAMPLE_OFFSET: 1.362 + case AL_BYTE_OFFSET: 1.363 + if(flValue >= 0.0f) 1.364 + { 1.365 + Source->lOffsetType = eParam; 1.366 + 1.367 + // Store Offset (convert Seconds into Milliseconds) 1.368 + if(eParam == AL_SEC_OFFSET) 1.369 + Source->lOffset = (ALint)(flValue * 1000.0f); 1.370 + else 1.371 + Source->lOffset = (ALint)flValue; 1.372 + 1.373 + if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && 1.374 + !pContext->DeferUpdates) 1.375 + { 1.376 + if(ApplyOffset(Source) == AL_FALSE) 1.377 + alSetError(pContext, AL_INVALID_VALUE); 1.378 + } 1.379 + } 1.380 + else 1.381 + alSetError(pContext, AL_INVALID_VALUE); 1.382 + break; 1.383 + 1.384 + default: 1.385 + alSetError(pContext, AL_INVALID_ENUM); 1.386 + break; 1.387 + } 1.388 + } 1.389 + else 1.390 + { 1.391 + // Invalid Source Name 1.392 + alSetError(pContext, AL_INVALID_NAME); 1.393 + } 1.394 + 1.395 + UnlockContext(pContext); 1.396 +} 1.397 + 1.398 + 1.399 +AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum eParam, ALfloat flValue1,ALfloat flValue2,ALfloat flValue3) 1.400 +{ 1.401 + ALCcontext *pContext; 1.402 + ALsource *Source; 1.403 + 1.404 + pContext = GetLockedContext(); 1.405 + if(!pContext) return; 1.406 + 1.407 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.408 + { 1.409 + switch(eParam) 1.410 + { 1.411 + case AL_POSITION: 1.412 + if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3)) 1.413 + { 1.414 + Source->vPosition[0] = flValue1; 1.415 + Source->vPosition[1] = flValue2; 1.416 + Source->vPosition[2] = flValue3; 1.417 + Source->NeedsUpdate = AL_TRUE; 1.418 + } 1.419 + else 1.420 + alSetError(pContext, AL_INVALID_VALUE); 1.421 + break; 1.422 + 1.423 + case AL_VELOCITY: 1.424 + if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3)) 1.425 + { 1.426 + Source->vVelocity[0] = flValue1; 1.427 + Source->vVelocity[1] = flValue2; 1.428 + Source->vVelocity[2] = flValue3; 1.429 + Source->NeedsUpdate = AL_TRUE; 1.430 + } 1.431 + else 1.432 + alSetError(pContext, AL_INVALID_VALUE); 1.433 + break; 1.434 + 1.435 + case AL_DIRECTION: 1.436 + if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3)) 1.437 + { 1.438 + Source->vOrientation[0] = flValue1; 1.439 + Source->vOrientation[1] = flValue2; 1.440 + Source->vOrientation[2] = flValue3; 1.441 + Source->NeedsUpdate = AL_TRUE; 1.442 + } 1.443 + else 1.444 + alSetError(pContext, AL_INVALID_VALUE); 1.445 + break; 1.446 + 1.447 + default: 1.448 + alSetError(pContext, AL_INVALID_ENUM); 1.449 + break; 1.450 + } 1.451 + } 1.452 + else 1.453 + alSetError(pContext, AL_INVALID_NAME); 1.454 + 1.455 + UnlockContext(pContext); 1.456 +} 1.457 + 1.458 + 1.459 +AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum eParam, const ALfloat *pflValues) 1.460 +{ 1.461 + ALCcontext *pContext; 1.462 + 1.463 + if(pflValues) 1.464 + { 1.465 + switch(eParam) 1.466 + { 1.467 + case AL_PITCH: 1.468 + case AL_CONE_INNER_ANGLE: 1.469 + case AL_CONE_OUTER_ANGLE: 1.470 + case AL_GAIN: 1.471 + case AL_MAX_DISTANCE: 1.472 + case AL_ROLLOFF_FACTOR: 1.473 + case AL_REFERENCE_DISTANCE: 1.474 + case AL_MIN_GAIN: 1.475 + case AL_MAX_GAIN: 1.476 + case AL_CONE_OUTER_GAIN: 1.477 + case AL_CONE_OUTER_GAINHF: 1.478 + case AL_SEC_OFFSET: 1.479 + case AL_SAMPLE_OFFSET: 1.480 + case AL_BYTE_OFFSET: 1.481 + case AL_AIR_ABSORPTION_FACTOR: 1.482 + case AL_ROOM_ROLLOFF_FACTOR: 1.483 + alSourcef(source, eParam, pflValues[0]); 1.484 + return; 1.485 + 1.486 + case AL_POSITION: 1.487 + case AL_VELOCITY: 1.488 + case AL_DIRECTION: 1.489 + alSource3f(source, eParam, pflValues[0], pflValues[1], pflValues[2]); 1.490 + return; 1.491 + } 1.492 + } 1.493 + 1.494 + pContext = GetLockedContext(); 1.495 + if(!pContext) return; 1.496 + 1.497 + if(pflValues) 1.498 + { 1.499 + if(LookupSource(pContext->SourceMap, source) != NULL) 1.500 + { 1.501 + switch(eParam) 1.502 + { 1.503 + default: 1.504 + alSetError(pContext, AL_INVALID_ENUM); 1.505 + break; 1.506 + } 1.507 + } 1.508 + else 1.509 + alSetError(pContext, AL_INVALID_NAME); 1.510 + } 1.511 + else 1.512 + alSetError(pContext, AL_INVALID_VALUE); 1.513 + 1.514 + UnlockContext(pContext); 1.515 +} 1.516 + 1.517 + 1.518 +AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue) 1.519 +{ 1.520 + ALCcontext *pContext; 1.521 + ALsource *Source; 1.522 + ALbufferlistitem *BufferListItem; 1.523 + 1.524 + switch(eParam) 1.525 + { 1.526 + case AL_MAX_DISTANCE: 1.527 + case AL_ROLLOFF_FACTOR: 1.528 + case AL_CONE_INNER_ANGLE: 1.529 + case AL_CONE_OUTER_ANGLE: 1.530 + case AL_REFERENCE_DISTANCE: 1.531 + alSourcef(source, eParam, (ALfloat)lValue); 1.532 + return; 1.533 + } 1.534 + 1.535 + pContext = GetLockedContext(); 1.536 + if(!pContext) return; 1.537 + 1.538 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.539 + { 1.540 + ALCdevice *device = pContext->Device; 1.541 + 1.542 + switch(eParam) 1.543 + { 1.544 + case AL_SOURCE_RELATIVE: 1.545 + if(lValue == AL_FALSE || lValue == AL_TRUE) 1.546 + { 1.547 + Source->bHeadRelative = (ALboolean)lValue; 1.548 + Source->NeedsUpdate = AL_TRUE; 1.549 + } 1.550 + else 1.551 + alSetError(pContext, AL_INVALID_VALUE); 1.552 + break; 1.553 + 1.554 + case AL_LOOPING: 1.555 + if(lValue == AL_FALSE || lValue == AL_TRUE) 1.556 + Source->bLooping = (ALboolean)lValue; 1.557 + else 1.558 + alSetError(pContext, AL_INVALID_VALUE); 1.559 + break; 1.560 + 1.561 + case AL_BUFFER: 1.562 + if(Source->state == AL_STOPPED || Source->state == AL_INITIAL) 1.563 + { 1.564 + ALbuffer *buffer = NULL; 1.565 + 1.566 + if(lValue == 0 || 1.567 + (buffer=LookupBuffer(device->BufferMap, lValue)) != NULL) 1.568 + { 1.569 + // Remove all elements in the queue 1.570 + while(Source->queue != NULL) 1.571 + { 1.572 + BufferListItem = Source->queue; 1.573 + Source->queue = BufferListItem->next; 1.574 + 1.575 + if(BufferListItem->buffer) 1.576 + BufferListItem->buffer->refcount--; 1.577 + free(BufferListItem); 1.578 + } 1.579 + Source->BuffersInQueue = 0; 1.580 + 1.581 + // Add the buffer to the queue (as long as it is NOT the NULL buffer) 1.582 + if(buffer != NULL) 1.583 + { 1.584 + // Source is now in STATIC mode 1.585 + Source->lSourceType = AL_STATIC; 1.586 + 1.587 + // Add the selected buffer to the queue 1.588 + BufferListItem = malloc(sizeof(ALbufferlistitem)); 1.589 + BufferListItem->buffer = buffer; 1.590 + BufferListItem->next = NULL; 1.591 + BufferListItem->prev = NULL; 1.592 + 1.593 + Source->queue = BufferListItem; 1.594 + Source->BuffersInQueue = 1; 1.595 + 1.596 + Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels); 1.597 + Source->SampleSize = BytesFromFmt(buffer->FmtType); 1.598 + if(buffer->FmtChannels == FmtMono) 1.599 + Source->Update = CalcSourceParams; 1.600 + else 1.601 + Source->Update = CalcNonAttnSourceParams; 1.602 + 1.603 + // Increment reference counter for buffer 1.604 + buffer->refcount++; 1.605 + } 1.606 + else 1.607 + { 1.608 + // Source is now in UNDETERMINED mode 1.609 + Source->lSourceType = AL_UNDETERMINED; 1.610 + } 1.611 + Source->BuffersPlayed = 0; 1.612 + 1.613 + // Update AL_BUFFER parameter 1.614 + Source->Buffer = buffer; 1.615 + Source->NeedsUpdate = AL_TRUE; 1.616 + } 1.617 + else 1.618 + alSetError(pContext, AL_INVALID_VALUE); 1.619 + } 1.620 + else 1.621 + alSetError(pContext, AL_INVALID_OPERATION); 1.622 + break; 1.623 + 1.624 + case AL_SOURCE_STATE: 1.625 + // Query only 1.626 + alSetError(pContext, AL_INVALID_OPERATION); 1.627 + break; 1.628 + 1.629 + case AL_SEC_OFFSET: 1.630 + case AL_SAMPLE_OFFSET: 1.631 + case AL_BYTE_OFFSET: 1.632 + if(lValue >= 0) 1.633 + { 1.634 + Source->lOffsetType = eParam; 1.635 + 1.636 + // Store Offset (convert Seconds into Milliseconds) 1.637 + if(eParam == AL_SEC_OFFSET) 1.638 + Source->lOffset = lValue * 1000; 1.639 + else 1.640 + Source->lOffset = lValue; 1.641 + 1.642 + if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && 1.643 + !pContext->DeferUpdates) 1.644 + { 1.645 + if(ApplyOffset(Source) == AL_FALSE) 1.646 + alSetError(pContext, AL_INVALID_VALUE); 1.647 + } 1.648 + } 1.649 + else 1.650 + alSetError(pContext, AL_INVALID_VALUE); 1.651 + break; 1.652 + 1.653 + case AL_DIRECT_FILTER: { 1.654 + ALfilter *filter = NULL; 1.655 + 1.656 + if(lValue == 0 || 1.657 + (filter=LookupFilter(pContext->Device->FilterMap, lValue)) != NULL) 1.658 + { 1.659 + if(!filter) 1.660 + { 1.661 + Source->DirectFilter.type = AL_FILTER_NULL; 1.662 + Source->DirectFilter.filter = 0; 1.663 + } 1.664 + else 1.665 + memcpy(&Source->DirectFilter, filter, sizeof(*filter)); 1.666 + Source->NeedsUpdate = AL_TRUE; 1.667 + } 1.668 + else 1.669 + alSetError(pContext, AL_INVALID_VALUE); 1.670 + } break; 1.671 + 1.672 + case AL_DIRECT_FILTER_GAINHF_AUTO: 1.673 + if(lValue == AL_TRUE || lValue == AL_FALSE) 1.674 + { 1.675 + Source->DryGainHFAuto = lValue; 1.676 + Source->NeedsUpdate = AL_TRUE; 1.677 + } 1.678 + else 1.679 + alSetError(pContext, AL_INVALID_VALUE); 1.680 + break; 1.681 + 1.682 + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: 1.683 + if(lValue == AL_TRUE || lValue == AL_FALSE) 1.684 + { 1.685 + Source->WetGainAuto = lValue; 1.686 + Source->NeedsUpdate = AL_TRUE; 1.687 + } 1.688 + else 1.689 + alSetError(pContext, AL_INVALID_VALUE); 1.690 + break; 1.691 + 1.692 + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: 1.693 + if(lValue == AL_TRUE || lValue == AL_FALSE) 1.694 + { 1.695 + Source->WetGainHFAuto = lValue; 1.696 + Source->NeedsUpdate = AL_TRUE; 1.697 + } 1.698 + else 1.699 + alSetError(pContext, AL_INVALID_VALUE); 1.700 + break; 1.701 + 1.702 + case AL_VIRTUAL_CHANNELS_SOFT: 1.703 + if(lValue == AL_TRUE || lValue == AL_FALSE) 1.704 + { 1.705 + Source->VirtualChannels = lValue; 1.706 + Source->NeedsUpdate = AL_TRUE; 1.707 + } 1.708 + else 1.709 + alSetError(pContext, AL_INVALID_VALUE); 1.710 + break; 1.711 + 1.712 + case AL_DISTANCE_MODEL: 1.713 + if(lValue == AL_NONE || 1.714 + lValue == AL_INVERSE_DISTANCE || 1.715 + lValue == AL_INVERSE_DISTANCE_CLAMPED || 1.716 + lValue == AL_LINEAR_DISTANCE || 1.717 + lValue == AL_LINEAR_DISTANCE_CLAMPED || 1.718 + lValue == AL_EXPONENT_DISTANCE || 1.719 + lValue == AL_EXPONENT_DISTANCE_CLAMPED) 1.720 + { 1.721 + Source->DistanceModel = lValue; 1.722 + if(pContext->SourceDistanceModel) 1.723 + Source->NeedsUpdate = AL_TRUE; 1.724 + } 1.725 + else 1.726 + alSetError(pContext, AL_INVALID_VALUE); 1.727 + break; 1.728 + 1.729 + default: 1.730 + alSetError(pContext, AL_INVALID_ENUM); 1.731 + break; 1.732 + } 1.733 + } 1.734 + else 1.735 + alSetError(pContext, AL_INVALID_NAME); 1.736 + 1.737 + UnlockContext(pContext); 1.738 +} 1.739 + 1.740 + 1.741 +AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3) 1.742 +{ 1.743 + ALCcontext *pContext; 1.744 + ALsource *Source; 1.745 + 1.746 + switch(eParam) 1.747 + { 1.748 + case AL_POSITION: 1.749 + case AL_VELOCITY: 1.750 + case AL_DIRECTION: 1.751 + alSource3f(source, eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3); 1.752 + return; 1.753 + } 1.754 + 1.755 + pContext = GetLockedContext(); 1.756 + if(!pContext) return; 1.757 + 1.758 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.759 + { 1.760 + ALCdevice *device = pContext->Device; 1.761 + 1.762 + switch(eParam) 1.763 + { 1.764 + case AL_AUXILIARY_SEND_FILTER: { 1.765 + ALeffectslot *ALEffectSlot = NULL; 1.766 + ALfilter *ALFilter = NULL; 1.767 + 1.768 + if((ALuint)lValue2 < device->NumAuxSends && 1.769 + (lValue1 == 0 || 1.770 + (ALEffectSlot=LookupEffectSlot(pContext->EffectSlotMap, lValue1)) != NULL) && 1.771 + (lValue3 == 0 || 1.772 + (ALFilter=LookupFilter(device->FilterMap, lValue3)) != NULL)) 1.773 + { 1.774 + /* Release refcount on the previous slot, and add one for 1.775 + * the new slot */ 1.776 + if(Source->Send[lValue2].Slot) 1.777 + Source->Send[lValue2].Slot->refcount--; 1.778 + Source->Send[lValue2].Slot = ALEffectSlot; 1.779 + if(Source->Send[lValue2].Slot) 1.780 + Source->Send[lValue2].Slot->refcount++; 1.781 + 1.782 + if(!ALFilter) 1.783 + { 1.784 + /* Disable filter */ 1.785 + Source->Send[lValue2].WetFilter.type = 0; 1.786 + Source->Send[lValue2].WetFilter.filter = 0; 1.787 + } 1.788 + else 1.789 + memcpy(&Source->Send[lValue2].WetFilter, ALFilter, sizeof(*ALFilter)); 1.790 + Source->NeedsUpdate = AL_TRUE; 1.791 + } 1.792 + else 1.793 + alSetError(pContext, AL_INVALID_VALUE); 1.794 + } break; 1.795 + 1.796 + default: 1.797 + alSetError(pContext, AL_INVALID_ENUM); 1.798 + break; 1.799 + } 1.800 + } 1.801 + else 1.802 + alSetError(pContext, AL_INVALID_NAME); 1.803 + 1.804 + UnlockContext(pContext); 1.805 +} 1.806 + 1.807 + 1.808 +AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* plValues) 1.809 +{ 1.810 + ALCcontext *pContext; 1.811 + 1.812 + if(plValues) 1.813 + { 1.814 + switch(eParam) 1.815 + { 1.816 + case AL_SOURCE_RELATIVE: 1.817 + case AL_CONE_INNER_ANGLE: 1.818 + case AL_CONE_OUTER_ANGLE: 1.819 + case AL_LOOPING: 1.820 + case AL_BUFFER: 1.821 + case AL_SOURCE_STATE: 1.822 + case AL_SEC_OFFSET: 1.823 + case AL_SAMPLE_OFFSET: 1.824 + case AL_BYTE_OFFSET: 1.825 + case AL_MAX_DISTANCE: 1.826 + case AL_ROLLOFF_FACTOR: 1.827 + case AL_REFERENCE_DISTANCE: 1.828 + case AL_DIRECT_FILTER: 1.829 + case AL_DIRECT_FILTER_GAINHF_AUTO: 1.830 + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: 1.831 + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: 1.832 + case AL_DISTANCE_MODEL: 1.833 + case AL_VIRTUAL_CHANNELS_SOFT: 1.834 + alSourcei(source, eParam, plValues[0]); 1.835 + return; 1.836 + 1.837 + case AL_POSITION: 1.838 + case AL_VELOCITY: 1.839 + case AL_DIRECTION: 1.840 + case AL_AUXILIARY_SEND_FILTER: 1.841 + alSource3i(source, eParam, plValues[0], plValues[1], plValues[2]); 1.842 + return; 1.843 + } 1.844 + } 1.845 + 1.846 + pContext = GetLockedContext(); 1.847 + if(!pContext) return; 1.848 + 1.849 + if(plValues) 1.850 + { 1.851 + if(LookupSource(pContext->SourceMap, source) != NULL) 1.852 + { 1.853 + switch(eParam) 1.854 + { 1.855 + default: 1.856 + alSetError(pContext, AL_INVALID_ENUM); 1.857 + break; 1.858 + } 1.859 + } 1.860 + else 1.861 + alSetError(pContext, AL_INVALID_NAME); 1.862 + } 1.863 + else 1.864 + alSetError(pContext, AL_INVALID_VALUE); 1.865 + 1.866 + UnlockContext(pContext); 1.867 +} 1.868 + 1.869 + 1.870 +AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflValue) 1.871 +{ 1.872 + ALCcontext *pContext; 1.873 + ALsource *Source; 1.874 + ALdouble Offsets[2]; 1.875 + ALdouble updateLen; 1.876 + 1.877 + pContext = GetLockedContext(); 1.878 + if(!pContext) return; 1.879 + 1.880 + if(pflValue) 1.881 + { 1.882 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.883 + { 1.884 + switch(eParam) 1.885 + { 1.886 + case AL_PITCH: 1.887 + *pflValue = Source->flPitch; 1.888 + break; 1.889 + 1.890 + case AL_GAIN: 1.891 + *pflValue = Source->flGain; 1.892 + break; 1.893 + 1.894 + case AL_MIN_GAIN: 1.895 + *pflValue = Source->flMinGain; 1.896 + break; 1.897 + 1.898 + case AL_MAX_GAIN: 1.899 + *pflValue = Source->flMaxGain; 1.900 + break; 1.901 + 1.902 + case AL_MAX_DISTANCE: 1.903 + *pflValue = Source->flMaxDistance; 1.904 + break; 1.905 + 1.906 + case AL_ROLLOFF_FACTOR: 1.907 + *pflValue = Source->flRollOffFactor; 1.908 + break; 1.909 + 1.910 + case AL_CONE_OUTER_GAIN: 1.911 + *pflValue = Source->flOuterGain; 1.912 + break; 1.913 + 1.914 + case AL_CONE_OUTER_GAINHF: 1.915 + *pflValue = Source->OuterGainHF; 1.916 + break; 1.917 + 1.918 + case AL_SEC_OFFSET: 1.919 + case AL_SAMPLE_OFFSET: 1.920 + case AL_BYTE_OFFSET: 1.921 + updateLen = (ALdouble)pContext->Device->UpdateSize / 1.922 + pContext->Device->Frequency; 1.923 + GetSourceOffset(Source, eParam, Offsets, updateLen); 1.924 + *pflValue = Offsets[0]; 1.925 + break; 1.926 + 1.927 + case AL_CONE_INNER_ANGLE: 1.928 + *pflValue = Source->flInnerAngle; 1.929 + break; 1.930 + 1.931 + case AL_CONE_OUTER_ANGLE: 1.932 + *pflValue = Source->flOuterAngle; 1.933 + break; 1.934 + 1.935 + case AL_REFERENCE_DISTANCE: 1.936 + *pflValue = Source->flRefDistance; 1.937 + break; 1.938 + 1.939 + case AL_AIR_ABSORPTION_FACTOR: 1.940 + *pflValue = Source->AirAbsorptionFactor; 1.941 + break; 1.942 + 1.943 + case AL_ROOM_ROLLOFF_FACTOR: 1.944 + *pflValue = Source->RoomRolloffFactor; 1.945 + break; 1.946 + 1.947 + case AL_DOPPLER_FACTOR: 1.948 + *pflValue = Source->DopplerFactor; 1.949 + break; 1.950 + 1.951 + default: 1.952 + alSetError(pContext, AL_INVALID_ENUM); 1.953 + break; 1.954 + } 1.955 + } 1.956 + else 1.957 + alSetError(pContext, AL_INVALID_NAME); 1.958 + } 1.959 + else 1.960 + alSetError(pContext, AL_INVALID_VALUE); 1.961 + 1.962 + UnlockContext(pContext); 1.963 +} 1.964 + 1.965 + 1.966 +AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3) 1.967 +{ 1.968 + ALCcontext *pContext; 1.969 + ALsource *Source; 1.970 + 1.971 + pContext = GetLockedContext(); 1.972 + if(!pContext) return; 1.973 + 1.974 + if(pflValue1 && pflValue2 && pflValue3) 1.975 + { 1.976 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.977 + { 1.978 + switch(eParam) 1.979 + { 1.980 + case AL_POSITION: 1.981 + *pflValue1 = Source->vPosition[0]; 1.982 + *pflValue2 = Source->vPosition[1]; 1.983 + *pflValue3 = Source->vPosition[2]; 1.984 + break; 1.985 + 1.986 + case AL_VELOCITY: 1.987 + *pflValue1 = Source->vVelocity[0]; 1.988 + *pflValue2 = Source->vVelocity[1]; 1.989 + *pflValue3 = Source->vVelocity[2]; 1.990 + break; 1.991 + 1.992 + case AL_DIRECTION: 1.993 + *pflValue1 = Source->vOrientation[0]; 1.994 + *pflValue2 = Source->vOrientation[1]; 1.995 + *pflValue3 = Source->vOrientation[2]; 1.996 + break; 1.997 + 1.998 + default: 1.999 + alSetError(pContext, AL_INVALID_ENUM); 1.1000 + break; 1.1001 + } 1.1002 + } 1.1003 + else 1.1004 + alSetError(pContext, AL_INVALID_NAME); 1.1005 + } 1.1006 + else 1.1007 + alSetError(pContext, AL_INVALID_VALUE); 1.1008 + 1.1009 + UnlockContext(pContext); 1.1010 +} 1.1011 + 1.1012 + 1.1013 +AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum eParam, ALfloat *pflValues) 1.1014 +{ 1.1015 + ALCcontext *pContext; 1.1016 + ALsource *Source; 1.1017 + ALdouble Offsets[2]; 1.1018 + ALdouble updateLen; 1.1019 + 1.1020 + switch(eParam) 1.1021 + { 1.1022 + case AL_PITCH: 1.1023 + case AL_GAIN: 1.1024 + case AL_MIN_GAIN: 1.1025 + case AL_MAX_GAIN: 1.1026 + case AL_MAX_DISTANCE: 1.1027 + case AL_ROLLOFF_FACTOR: 1.1028 + case AL_DOPPLER_FACTOR: 1.1029 + case AL_CONE_OUTER_GAIN: 1.1030 + case AL_SEC_OFFSET: 1.1031 + case AL_SAMPLE_OFFSET: 1.1032 + case AL_BYTE_OFFSET: 1.1033 + case AL_CONE_INNER_ANGLE: 1.1034 + case AL_CONE_OUTER_ANGLE: 1.1035 + case AL_REFERENCE_DISTANCE: 1.1036 + case AL_CONE_OUTER_GAINHF: 1.1037 + case AL_AIR_ABSORPTION_FACTOR: 1.1038 + case AL_ROOM_ROLLOFF_FACTOR: 1.1039 + alGetSourcef(source, eParam, pflValues); 1.1040 + return; 1.1041 + 1.1042 + case AL_POSITION: 1.1043 + case AL_VELOCITY: 1.1044 + case AL_DIRECTION: 1.1045 + alGetSource3f(source, eParam, pflValues+0, pflValues+1, pflValues+2); 1.1046 + return; 1.1047 + } 1.1048 + 1.1049 + pContext = GetLockedContext(); 1.1050 + if(!pContext) return; 1.1051 + 1.1052 + if(pflValues) 1.1053 + { 1.1054 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.1055 + { 1.1056 + switch(eParam) 1.1057 + { 1.1058 + case AL_SAMPLE_RW_OFFSETS_SOFT: 1.1059 + case AL_BYTE_RW_OFFSETS_SOFT: 1.1060 + updateLen = (ALdouble)pContext->Device->UpdateSize / 1.1061 + pContext->Device->Frequency; 1.1062 + GetSourceOffset(Source, eParam, Offsets, updateLen); 1.1063 + pflValues[0] = Offsets[0]; 1.1064 + pflValues[1] = Offsets[1]; 1.1065 + break; 1.1066 + 1.1067 + default: 1.1068 + alSetError(pContext, AL_INVALID_ENUM); 1.1069 + break; 1.1070 + } 1.1071 + } 1.1072 + else 1.1073 + alSetError(pContext, AL_INVALID_NAME); 1.1074 + } 1.1075 + else 1.1076 + alSetError(pContext, AL_INVALID_VALUE); 1.1077 + 1.1078 + UnlockContext(pContext); 1.1079 +} 1.1080 + 1.1081 + 1.1082 +AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValue) 1.1083 +{ 1.1084 + ALCcontext *pContext; 1.1085 + ALsource *Source; 1.1086 + ALdouble Offsets[2]; 1.1087 + ALdouble updateLen; 1.1088 + 1.1089 + pContext = GetLockedContext(); 1.1090 + if(!pContext) return; 1.1091 + 1.1092 + if(plValue) 1.1093 + { 1.1094 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.1095 + { 1.1096 + switch(eParam) 1.1097 + { 1.1098 + case AL_MAX_DISTANCE: 1.1099 + *plValue = (ALint)Source->flMaxDistance; 1.1100 + break; 1.1101 + 1.1102 + case AL_ROLLOFF_FACTOR: 1.1103 + *plValue = (ALint)Source->flRollOffFactor; 1.1104 + break; 1.1105 + 1.1106 + case AL_REFERENCE_DISTANCE: 1.1107 + *plValue = (ALint)Source->flRefDistance; 1.1108 + break; 1.1109 + 1.1110 + case AL_SOURCE_RELATIVE: 1.1111 + *plValue = Source->bHeadRelative; 1.1112 + break; 1.1113 + 1.1114 + case AL_CONE_INNER_ANGLE: 1.1115 + *plValue = (ALint)Source->flInnerAngle; 1.1116 + break; 1.1117 + 1.1118 + case AL_CONE_OUTER_ANGLE: 1.1119 + *plValue = (ALint)Source->flOuterAngle; 1.1120 + break; 1.1121 + 1.1122 + case AL_LOOPING: 1.1123 + *plValue = Source->bLooping; 1.1124 + break; 1.1125 + 1.1126 + case AL_BUFFER: 1.1127 + *plValue = (Source->Buffer ? Source->Buffer->buffer : 0); 1.1128 + break; 1.1129 + 1.1130 + case AL_SOURCE_STATE: 1.1131 + *plValue = Source->state; 1.1132 + break; 1.1133 + 1.1134 + case AL_BUFFERS_QUEUED: 1.1135 + *plValue = Source->BuffersInQueue; 1.1136 + break; 1.1137 + 1.1138 + case AL_BUFFERS_PROCESSED: 1.1139 + if(Source->bLooping || Source->lSourceType != AL_STREAMING) 1.1140 + { 1.1141 + /* Buffers on a looping source are in a perpetual state 1.1142 + * of PENDING, so don't report any as PROCESSED */ 1.1143 + *plValue = 0; 1.1144 + } 1.1145 + else 1.1146 + *plValue = Source->BuffersPlayed; 1.1147 + break; 1.1148 + 1.1149 + case AL_SOURCE_TYPE: 1.1150 + *plValue = Source->lSourceType; 1.1151 + break; 1.1152 + 1.1153 + case AL_SEC_OFFSET: 1.1154 + case AL_SAMPLE_OFFSET: 1.1155 + case AL_BYTE_OFFSET: 1.1156 + updateLen = (ALdouble)pContext->Device->UpdateSize / 1.1157 + pContext->Device->Frequency; 1.1158 + GetSourceOffset(Source, eParam, Offsets, updateLen); 1.1159 + *plValue = (ALint)Offsets[0]; 1.1160 + break; 1.1161 + 1.1162 + case AL_DIRECT_FILTER: 1.1163 + *plValue = Source->DirectFilter.filter; 1.1164 + break; 1.1165 + 1.1166 + case AL_DIRECT_FILTER_GAINHF_AUTO: 1.1167 + *plValue = Source->DryGainHFAuto; 1.1168 + break; 1.1169 + 1.1170 + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: 1.1171 + *plValue = Source->WetGainAuto; 1.1172 + break; 1.1173 + 1.1174 + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: 1.1175 + *plValue = Source->WetGainHFAuto; 1.1176 + break; 1.1177 + 1.1178 + case AL_DOPPLER_FACTOR: 1.1179 + *plValue = (ALint)Source->DopplerFactor; 1.1180 + break; 1.1181 + 1.1182 + case AL_VIRTUAL_CHANNELS_SOFT: 1.1183 + *plValue = Source->VirtualChannels; 1.1184 + break; 1.1185 + 1.1186 + case AL_DISTANCE_MODEL: 1.1187 + *plValue = Source->DistanceModel; 1.1188 + break; 1.1189 + 1.1190 + default: 1.1191 + alSetError(pContext, AL_INVALID_ENUM); 1.1192 + break; 1.1193 + } 1.1194 + } 1.1195 + else 1.1196 + alSetError(pContext, AL_INVALID_NAME); 1.1197 + } 1.1198 + else 1.1199 + alSetError(pContext, AL_INVALID_VALUE); 1.1200 + 1.1201 + UnlockContext(pContext); 1.1202 +} 1.1203 + 1.1204 + 1.1205 +AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum eParam, ALint* plValue1, ALint* plValue2, ALint* plValue3) 1.1206 +{ 1.1207 + ALCcontext *pContext; 1.1208 + ALsource *Source; 1.1209 + 1.1210 + pContext = GetLockedContext(); 1.1211 + if(!pContext) return; 1.1212 + 1.1213 + if(plValue1 && plValue2 && plValue3) 1.1214 + { 1.1215 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.1216 + { 1.1217 + switch(eParam) 1.1218 + { 1.1219 + case AL_POSITION: 1.1220 + *plValue1 = (ALint)Source->vPosition[0]; 1.1221 + *plValue2 = (ALint)Source->vPosition[1]; 1.1222 + *plValue3 = (ALint)Source->vPosition[2]; 1.1223 + break; 1.1224 + 1.1225 + case AL_VELOCITY: 1.1226 + *plValue1 = (ALint)Source->vVelocity[0]; 1.1227 + *plValue2 = (ALint)Source->vVelocity[1]; 1.1228 + *plValue3 = (ALint)Source->vVelocity[2]; 1.1229 + break; 1.1230 + 1.1231 + case AL_DIRECTION: 1.1232 + *plValue1 = (ALint)Source->vOrientation[0]; 1.1233 + *plValue2 = (ALint)Source->vOrientation[1]; 1.1234 + *plValue3 = (ALint)Source->vOrientation[2]; 1.1235 + break; 1.1236 + 1.1237 + default: 1.1238 + alSetError(pContext, AL_INVALID_ENUM); 1.1239 + break; 1.1240 + } 1.1241 + } 1.1242 + else 1.1243 + alSetError(pContext, AL_INVALID_NAME); 1.1244 + } 1.1245 + else 1.1246 + alSetError(pContext, AL_INVALID_VALUE); 1.1247 + 1.1248 + UnlockContext(pContext); 1.1249 +} 1.1250 + 1.1251 + 1.1252 +AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValues) 1.1253 +{ 1.1254 + ALCcontext *pContext; 1.1255 + ALsource *Source; 1.1256 + ALdouble Offsets[2]; 1.1257 + ALdouble updateLen; 1.1258 + 1.1259 + switch(eParam) 1.1260 + { 1.1261 + case AL_SOURCE_RELATIVE: 1.1262 + case AL_CONE_INNER_ANGLE: 1.1263 + case AL_CONE_OUTER_ANGLE: 1.1264 + case AL_LOOPING: 1.1265 + case AL_BUFFER: 1.1266 + case AL_SOURCE_STATE: 1.1267 + case AL_BUFFERS_QUEUED: 1.1268 + case AL_BUFFERS_PROCESSED: 1.1269 + case AL_SEC_OFFSET: 1.1270 + case AL_SAMPLE_OFFSET: 1.1271 + case AL_BYTE_OFFSET: 1.1272 + case AL_MAX_DISTANCE: 1.1273 + case AL_ROLLOFF_FACTOR: 1.1274 + case AL_DOPPLER_FACTOR: 1.1275 + case AL_REFERENCE_DISTANCE: 1.1276 + case AL_SOURCE_TYPE: 1.1277 + case AL_DIRECT_FILTER: 1.1278 + case AL_DIRECT_FILTER_GAINHF_AUTO: 1.1279 + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: 1.1280 + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: 1.1281 + case AL_DISTANCE_MODEL: 1.1282 + case AL_VIRTUAL_CHANNELS_SOFT: 1.1283 + alGetSourcei(source, eParam, plValues); 1.1284 + return; 1.1285 + 1.1286 + case AL_POSITION: 1.1287 + case AL_VELOCITY: 1.1288 + case AL_DIRECTION: 1.1289 + alGetSource3i(source, eParam, plValues+0, plValues+1, plValues+2); 1.1290 + return; 1.1291 + } 1.1292 + 1.1293 + pContext = GetLockedContext(); 1.1294 + if(!pContext) return; 1.1295 + 1.1296 + if(plValues) 1.1297 + { 1.1298 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 1.1299 + { 1.1300 + switch(eParam) 1.1301 + { 1.1302 + case AL_SAMPLE_RW_OFFSETS_SOFT: 1.1303 + case AL_BYTE_RW_OFFSETS_SOFT: 1.1304 + updateLen = (ALdouble)pContext->Device->UpdateSize / 1.1305 + pContext->Device->Frequency; 1.1306 + GetSourceOffset(Source, eParam, Offsets, updateLen); 1.1307 + plValues[0] = (ALint)Offsets[0]; 1.1308 + plValues[1] = (ALint)Offsets[1]; 1.1309 + break; 1.1310 + 1.1311 + default: 1.1312 + alSetError(pContext, AL_INVALID_ENUM); 1.1313 + break; 1.1314 + } 1.1315 + } 1.1316 + else 1.1317 + alSetError(pContext, AL_INVALID_NAME); 1.1318 + } 1.1319 + else 1.1320 + alSetError(pContext, AL_INVALID_VALUE); 1.1321 + 1.1322 + UnlockContext(pContext); 1.1323 +} 1.1324 + 1.1325 + 1.1326 +AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source) 1.1327 +{ 1.1328 + alSourcePlayv(1, &source); 1.1329 +} 1.1330 + 1.1331 +AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) 1.1332 +{ 1.1333 + ALCcontext *Context; 1.1334 + ALsource *Source; 1.1335 + ALsizei i; 1.1336 + 1.1337 + Context = GetLockedContext(); 1.1338 + if(!Context) return; 1.1339 + 1.1340 + if(n < 0) 1.1341 + { 1.1342 + alSetError(Context, AL_INVALID_VALUE); 1.1343 + goto done; 1.1344 + } 1.1345 + if(n > 0 && !sources) 1.1346 + { 1.1347 + alSetError(Context, AL_INVALID_VALUE); 1.1348 + goto done; 1.1349 + } 1.1350 + 1.1351 + // Check that all the Sources are valid 1.1352 + for(i = 0;i < n;i++) 1.1353 + { 1.1354 + if(!LookupSource(Context->SourceMap, sources[i])) 1.1355 + { 1.1356 + alSetError(Context, AL_INVALID_NAME); 1.1357 + goto done; 1.1358 + } 1.1359 + } 1.1360 + 1.1361 + while(Context->MaxActiveSources-Context->ActiveSourceCount < n) 1.1362 + { 1.1363 + void *temp = NULL; 1.1364 + ALsizei newcount; 1.1365 + 1.1366 + newcount = Context->MaxActiveSources << 1; 1.1367 + if(newcount > 0) 1.1368 + temp = realloc(Context->ActiveSources, 1.1369 + sizeof(*Context->ActiveSources) * newcount); 1.1370 + if(!temp) 1.1371 + { 1.1372 + alSetError(Context, AL_OUT_OF_MEMORY); 1.1373 + goto done; 1.1374 + } 1.1375 + 1.1376 + Context->ActiveSources = temp; 1.1377 + Context->MaxActiveSources = newcount; 1.1378 + } 1.1379 + 1.1380 + for(i = 0;i < n;i++) 1.1381 + { 1.1382 + Source = LookupSource(Context->SourceMap, sources[i]); 1.1383 + if(Context->DeferUpdates) Source->new_state = AL_PLAYING; 1.1384 + else SetSourceState(Source, Context, AL_PLAYING); 1.1385 + } 1.1386 + 1.1387 +done: 1.1388 + UnlockContext(Context); 1.1389 +} 1.1390 + 1.1391 +AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source) 1.1392 +{ 1.1393 + alSourcePausev(1, &source); 1.1394 +} 1.1395 + 1.1396 +AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources) 1.1397 +{ 1.1398 + ALCcontext *Context; 1.1399 + ALsource *Source; 1.1400 + ALsizei i; 1.1401 + 1.1402 + Context = GetLockedContext(); 1.1403 + if(!Context) return; 1.1404 + 1.1405 + if(n < 0) 1.1406 + { 1.1407 + alSetError(Context, AL_INVALID_VALUE); 1.1408 + goto done; 1.1409 + } 1.1410 + if(n > 0 && !sources) 1.1411 + { 1.1412 + alSetError(Context, AL_INVALID_VALUE); 1.1413 + goto done; 1.1414 + } 1.1415 + 1.1416 + // Check all the Sources are valid 1.1417 + for(i = 0;i < n;i++) 1.1418 + { 1.1419 + if(!LookupSource(Context->SourceMap, sources[i])) 1.1420 + { 1.1421 + alSetError(Context, AL_INVALID_NAME); 1.1422 + goto done; 1.1423 + } 1.1424 + } 1.1425 + 1.1426 + for(i = 0;i < n;i++) 1.1427 + { 1.1428 + Source = LookupSource(Context->SourceMap, sources[i]); 1.1429 + if(Context->DeferUpdates) Source->new_state = AL_PAUSED; 1.1430 + else SetSourceState(Source, Context, AL_PAUSED); 1.1431 + } 1.1432 + 1.1433 +done: 1.1434 + UnlockContext(Context); 1.1435 +} 1.1436 + 1.1437 +AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source) 1.1438 +{ 1.1439 + alSourceStopv(1, &source); 1.1440 +} 1.1441 + 1.1442 +AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources) 1.1443 +{ 1.1444 + ALCcontext *Context; 1.1445 + ALsource *Source; 1.1446 + ALsizei i; 1.1447 + 1.1448 + Context = GetLockedContext(); 1.1449 + if(!Context) return; 1.1450 + 1.1451 + if(n < 0) 1.1452 + { 1.1453 + alSetError(Context, AL_INVALID_VALUE); 1.1454 + goto done; 1.1455 + } 1.1456 + if(n > 0 && !sources) 1.1457 + { 1.1458 + alSetError(Context, AL_INVALID_VALUE); 1.1459 + goto done; 1.1460 + } 1.1461 + 1.1462 + // Check all the Sources are valid 1.1463 + for(i = 0;i < n;i++) 1.1464 + { 1.1465 + if(!LookupSource(Context->SourceMap, sources[i])) 1.1466 + { 1.1467 + alSetError(Context, AL_INVALID_NAME); 1.1468 + goto done; 1.1469 + } 1.1470 + } 1.1471 + 1.1472 + for(i = 0;i < n;i++) 1.1473 + { 1.1474 + Source = LookupSource(Context->SourceMap, sources[i]); 1.1475 + if(Context->DeferUpdates) Source->new_state = AL_STOPPED; 1.1476 + else SetSourceState(Source, Context, AL_STOPPED); 1.1477 + } 1.1478 + 1.1479 +done: 1.1480 + UnlockContext(Context); 1.1481 +} 1.1482 + 1.1483 +AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source) 1.1484 +{ 1.1485 + alSourceRewindv(1, &source); 1.1486 +} 1.1487 + 1.1488 +AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources) 1.1489 +{ 1.1490 + ALCcontext *Context; 1.1491 + ALsource *Source; 1.1492 + ALsizei i; 1.1493 + 1.1494 + Context = GetLockedContext(); 1.1495 + if(!Context) return; 1.1496 + 1.1497 + if(n < 0) 1.1498 + { 1.1499 + alSetError(Context, AL_INVALID_VALUE); 1.1500 + goto done; 1.1501 + } 1.1502 + if(n > 0 && !sources) 1.1503 + { 1.1504 + alSetError(Context, AL_INVALID_VALUE); 1.1505 + goto done; 1.1506 + } 1.1507 + 1.1508 + // Check all the Sources are valid 1.1509 + for(i = 0;i < n;i++) 1.1510 + { 1.1511 + if(!LookupSource(Context->SourceMap, sources[i])) 1.1512 + { 1.1513 + alSetError(Context, AL_INVALID_NAME); 1.1514 + goto done; 1.1515 + } 1.1516 + } 1.1517 + 1.1518 + for(i = 0;i < n;i++) 1.1519 + { 1.1520 + Source = LookupSource(Context->SourceMap, sources[i]); 1.1521 + if(Context->DeferUpdates) Source->new_state = AL_INITIAL; 1.1522 + else SetSourceState(Source, Context, AL_INITIAL); 1.1523 + } 1.1524 + 1.1525 +done: 1.1526 + UnlockContext(Context); 1.1527 +} 1.1528 + 1.1529 + 1.1530 +AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const ALuint *buffers) 1.1531 +{ 1.1532 + ALCcontext *Context; 1.1533 + ALCdevice *device; 1.1534 + ALsource *Source; 1.1535 + ALbuffer *buffer; 1.1536 + ALsizei i; 1.1537 + ALbufferlistitem *BufferListStart; 1.1538 + ALbufferlistitem *BufferList; 1.1539 + ALbuffer *BufferFmt; 1.1540 + 1.1541 + if(n == 0) 1.1542 + return; 1.1543 + 1.1544 + Context = GetLockedContext(); 1.1545 + if(!Context) return; 1.1546 + 1.1547 + if(n < 0) 1.1548 + { 1.1549 + alSetError(Context, AL_INVALID_VALUE); 1.1550 + goto done; 1.1551 + } 1.1552 + 1.1553 + // Check that all buffers are valid or zero and that the source is valid 1.1554 + 1.1555 + // Check that this is a valid source 1.1556 + if((Source=LookupSource(Context->SourceMap, source)) == NULL) 1.1557 + { 1.1558 + alSetError(Context, AL_INVALID_NAME); 1.1559 + goto done; 1.1560 + } 1.1561 + 1.1562 + // Check that this is not a STATIC Source 1.1563 + if(Source->lSourceType == AL_STATIC) 1.1564 + { 1.1565 + // Invalid Source Type (can't queue on a Static Source) 1.1566 + alSetError(Context, AL_INVALID_OPERATION); 1.1567 + goto done; 1.1568 + } 1.1569 + 1.1570 + device = Context->Device; 1.1571 + 1.1572 + BufferFmt = NULL; 1.1573 + 1.1574 + // Check existing Queue (if any) for a valid Buffers and get its frequency and format 1.1575 + BufferList = Source->queue; 1.1576 + while(BufferList) 1.1577 + { 1.1578 + if(BufferList->buffer) 1.1579 + { 1.1580 + BufferFmt = BufferList->buffer; 1.1581 + break; 1.1582 + } 1.1583 + BufferList = BufferList->next; 1.1584 + } 1.1585 + 1.1586 + for(i = 0;i < n;i++) 1.1587 + { 1.1588 + if(!buffers[i]) 1.1589 + continue; 1.1590 + 1.1591 + if((buffer=LookupBuffer(device->BufferMap, buffers[i])) == NULL) 1.1592 + { 1.1593 + alSetError(Context, AL_INVALID_NAME); 1.1594 + goto done; 1.1595 + } 1.1596 + 1.1597 + if(BufferFmt == NULL) 1.1598 + { 1.1599 + BufferFmt = buffer; 1.1600 + 1.1601 + Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels); 1.1602 + Source->SampleSize = BytesFromFmt(buffer->FmtType); 1.1603 + if(buffer->FmtChannels == FmtMono) 1.1604 + Source->Update = CalcSourceParams; 1.1605 + else 1.1606 + Source->Update = CalcNonAttnSourceParams; 1.1607 + 1.1608 + Source->NeedsUpdate = AL_TRUE; 1.1609 + } 1.1610 + else if(BufferFmt->Frequency != buffer->Frequency || 1.1611 + BufferFmt->OriginalChannels != buffer->OriginalChannels || 1.1612 + BufferFmt->OriginalType != buffer->OriginalType) 1.1613 + { 1.1614 + alSetError(Context, AL_INVALID_OPERATION); 1.1615 + goto done; 1.1616 + } 1.1617 + } 1.1618 + 1.1619 + // Change Source Type 1.1620 + Source->lSourceType = AL_STREAMING; 1.1621 + 1.1622 + buffer = LookupBuffer(device->BufferMap, buffers[0]); 1.1623 + 1.1624 + // All buffers are valid - so add them to the list 1.1625 + BufferListStart = malloc(sizeof(ALbufferlistitem)); 1.1626 + BufferListStart->buffer = buffer; 1.1627 + BufferListStart->next = NULL; 1.1628 + BufferListStart->prev = NULL; 1.1629 + 1.1630 + // Increment reference counter for buffer 1.1631 + if(buffer) buffer->refcount++; 1.1632 + 1.1633 + BufferList = BufferListStart; 1.1634 + 1.1635 + for(i = 1;i < n;i++) 1.1636 + { 1.1637 + buffer = LookupBuffer(device->BufferMap, buffers[i]); 1.1638 + 1.1639 + BufferList->next = malloc(sizeof(ALbufferlistitem)); 1.1640 + BufferList->next->buffer = buffer; 1.1641 + BufferList->next->next = NULL; 1.1642 + BufferList->next->prev = BufferList; 1.1643 + 1.1644 + // Increment reference counter for buffer 1.1645 + if(buffer) buffer->refcount++; 1.1646 + 1.1647 + BufferList = BufferList->next; 1.1648 + } 1.1649 + 1.1650 + if(Source->queue == NULL) 1.1651 + { 1.1652 + Source->queue = BufferListStart; 1.1653 + // Update Current Buffer 1.1654 + Source->Buffer = BufferListStart->buffer; 1.1655 + } 1.1656 + else 1.1657 + { 1.1658 + // Find end of queue 1.1659 + BufferList = Source->queue; 1.1660 + while(BufferList->next != NULL) 1.1661 + BufferList = BufferList->next; 1.1662 + 1.1663 + BufferList->next = BufferListStart; 1.1664 + BufferList->next->prev = BufferList; 1.1665 + } 1.1666 + 1.1667 + // Update number of buffers in queue 1.1668 + Source->BuffersInQueue += n; 1.1669 + 1.1670 +done: 1.1671 + UnlockContext(Context); 1.1672 +} 1.1673 + 1.1674 + 1.1675 +// Implementation assumes that n is the number of buffers to be removed from the queue and buffers is 1.1676 +// an array of buffer IDs that are to be filled with the names of the buffers removed 1.1677 +AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers ) 1.1678 +{ 1.1679 + ALCcontext *Context; 1.1680 + ALsource *Source; 1.1681 + ALsizei i; 1.1682 + ALbufferlistitem *BufferList; 1.1683 + 1.1684 + if(n == 0) 1.1685 + return; 1.1686 + 1.1687 + Context = GetLockedContext(); 1.1688 + if(!Context) return; 1.1689 + 1.1690 + if(n < 0) 1.1691 + { 1.1692 + alSetError(Context, AL_INVALID_VALUE); 1.1693 + goto done; 1.1694 + } 1.1695 + 1.1696 + if((Source=LookupSource(Context->SourceMap, source)) == NULL) 1.1697 + { 1.1698 + alSetError(Context, AL_INVALID_NAME); 1.1699 + goto done; 1.1700 + } 1.1701 + 1.1702 + if(Source->bLooping || Source->lSourceType != AL_STREAMING || 1.1703 + (ALuint)n > Source->BuffersPlayed) 1.1704 + { 1.1705 + // Some buffers can't be unqueue because they have not been processed 1.1706 + alSetError(Context, AL_INVALID_VALUE); 1.1707 + goto done; 1.1708 + } 1.1709 + 1.1710 + for(i = 0;i < n;i++) 1.1711 + { 1.1712 + BufferList = Source->queue; 1.1713 + Source->queue = BufferList->next; 1.1714 + 1.1715 + if(BufferList->buffer) 1.1716 + { 1.1717 + // Record name of buffer 1.1718 + buffers[i] = BufferList->buffer->buffer; 1.1719 + // Decrement buffer reference counter 1.1720 + BufferList->buffer->refcount--; 1.1721 + } 1.1722 + else 1.1723 + buffers[i] = 0; 1.1724 + 1.1725 + // Release memory for buffer list item 1.1726 + free(BufferList); 1.1727 + Source->BuffersInQueue--; 1.1728 + } 1.1729 + if(Source->queue) 1.1730 + Source->queue->prev = NULL; 1.1731 + 1.1732 + if(Source->state != AL_PLAYING) 1.1733 + { 1.1734 + if(Source->queue) 1.1735 + Source->Buffer = Source->queue->buffer; 1.1736 + else 1.1737 + Source->Buffer = NULL; 1.1738 + } 1.1739 + Source->BuffersPlayed -= n; 1.1740 + 1.1741 +done: 1.1742 + UnlockContext(Context); 1.1743 +} 1.1744 + 1.1745 + 1.1746 +static ALvoid InitSourceParams(ALsource *Source) 1.1747 +{ 1.1748 + Source->flInnerAngle = 360.0f; 1.1749 + Source->flOuterAngle = 360.0f; 1.1750 + Source->flPitch = 1.0f; 1.1751 + Source->vPosition[0] = 0.0f; 1.1752 + Source->vPosition[1] = 0.0f; 1.1753 + Source->vPosition[2] = 0.0f; 1.1754 + Source->vOrientation[0] = 0.0f; 1.1755 + Source->vOrientation[1] = 0.0f; 1.1756 + Source->vOrientation[2] = 0.0f; 1.1757 + Source->vVelocity[0] = 0.0f; 1.1758 + Source->vVelocity[1] = 0.0f; 1.1759 + Source->vVelocity[2] = 0.0f; 1.1760 + Source->flRefDistance = 1.0f; 1.1761 + Source->flMaxDistance = FLT_MAX; 1.1762 + Source->flRollOffFactor = 1.0f; 1.1763 + Source->bLooping = AL_FALSE; 1.1764 + Source->flGain = 1.0f; 1.1765 + Source->flMinGain = 0.0f; 1.1766 + Source->flMaxGain = 1.0f; 1.1767 + Source->flOuterGain = 0.0f; 1.1768 + Source->OuterGainHF = 1.0f; 1.1769 + 1.1770 + Source->DryGainHFAuto = AL_TRUE; 1.1771 + Source->WetGainAuto = AL_TRUE; 1.1772 + Source->WetGainHFAuto = AL_TRUE; 1.1773 + Source->AirAbsorptionFactor = 0.0f; 1.1774 + Source->RoomRolloffFactor = 0.0f; 1.1775 + Source->DopplerFactor = 1.0f; 1.1776 + Source->VirtualChannels = AL_TRUE; 1.1777 + 1.1778 + Source->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED; 1.1779 + 1.1780 + Source->Resampler = DefaultResampler; 1.1781 + 1.1782 + Source->state = AL_INITIAL; 1.1783 + Source->new_state = AL_NONE; 1.1784 + Source->lSourceType = AL_UNDETERMINED; 1.1785 + Source->lOffset = -1; 1.1786 + 1.1787 + Source->NeedsUpdate = AL_TRUE; 1.1788 + 1.1789 + Source->Buffer = NULL; 1.1790 + 1.1791 + Source->HrtfMoving = AL_FALSE; 1.1792 + Source->HrtfCounter = 0; 1.1793 +} 1.1794 + 1.1795 + 1.1796 +/* 1.1797 + * SetSourceState 1.1798 + * 1.1799 + * Sets the source's new play state given its current state 1.1800 + */ 1.1801 +ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) 1.1802 +{ 1.1803 + if(state == AL_PLAYING) 1.1804 + { 1.1805 + ALbufferlistitem *BufferList; 1.1806 + ALsizei j, k; 1.1807 + 1.1808 + /* Check that there is a queue containing at least one non-null, non zero length AL Buffer */ 1.1809 + BufferList = Source->queue; 1.1810 + while(BufferList) 1.1811 + { 1.1812 + if(BufferList->buffer != NULL && BufferList->buffer->size) 1.1813 + break; 1.1814 + BufferList = BufferList->next; 1.1815 + } 1.1816 + 1.1817 + /* If there's nothing to play, or device is disconnected, go right to 1.1818 + * stopped */ 1.1819 + if(!BufferList || !Context->Device->Connected) 1.1820 + { 1.1821 + SetSourceState(Source, Context, AL_STOPPED); 1.1822 + return; 1.1823 + } 1.1824 + 1.1825 + if(Source->state != AL_PLAYING) 1.1826 + { 1.1827 + for(j = 0;j < MAXCHANNELS;j++) 1.1828 + { 1.1829 + for(k = 0;k < SRC_HISTORY_LENGTH;k++) 1.1830 + Source->HrtfHistory[j][k] = 0.0f; 1.1831 + for(k = 0;k < HRIR_LENGTH;k++) 1.1832 + { 1.1833 + Source->HrtfValues[j][k][0] = 0.0f; 1.1834 + Source->HrtfValues[j][k][1] = 0.0f; 1.1835 + } 1.1836 + } 1.1837 + } 1.1838 + 1.1839 + if(Source->state != AL_PAUSED) 1.1840 + { 1.1841 + Source->state = AL_PLAYING; 1.1842 + Source->position = 0; 1.1843 + Source->position_fraction = 0; 1.1844 + Source->BuffersPlayed = 0; 1.1845 + 1.1846 + Source->Buffer = Source->queue->buffer; 1.1847 + } 1.1848 + else 1.1849 + Source->state = AL_PLAYING; 1.1850 + 1.1851 + // Check if an Offset has been set 1.1852 + if(Source->lOffset != -1) 1.1853 + ApplyOffset(Source); 1.1854 + 1.1855 + for(j = 0;j < Context->ActiveSourceCount;j++) 1.1856 + { 1.1857 + if(Context->ActiveSources[j] == Source) 1.1858 + break; 1.1859 + } 1.1860 + if(j == Context->ActiveSourceCount) 1.1861 + Context->ActiveSources[Context->ActiveSourceCount++] = Source; 1.1862 + } 1.1863 + else if(state == AL_PAUSED) 1.1864 + { 1.1865 + if(Source->state == AL_PLAYING) 1.1866 + { 1.1867 + Source->state = AL_PAUSED; 1.1868 + Source->HrtfMoving = AL_FALSE; 1.1869 + Source->HrtfCounter = 0; 1.1870 + } 1.1871 + } 1.1872 + else if(state == AL_STOPPED) 1.1873 + { 1.1874 + if(Source->state != AL_INITIAL) 1.1875 + { 1.1876 + Source->state = AL_STOPPED; 1.1877 + Source->BuffersPlayed = Source->BuffersInQueue; 1.1878 + Source->HrtfMoving = AL_FALSE; 1.1879 + Source->HrtfCounter = 0; 1.1880 + } 1.1881 + Source->lOffset = -1; 1.1882 + } 1.1883 + else if(state == AL_INITIAL) 1.1884 + { 1.1885 + if(Source->state != AL_INITIAL) 1.1886 + { 1.1887 + Source->state = AL_INITIAL; 1.1888 + Source->position = 0; 1.1889 + Source->position_fraction = 0; 1.1890 + Source->BuffersPlayed = 0; 1.1891 + if(Source->queue) 1.1892 + Source->Buffer = Source->queue->buffer; 1.1893 + Source->HrtfMoving = AL_FALSE; 1.1894 + Source->HrtfCounter = 0; 1.1895 + } 1.1896 + Source->lOffset = -1; 1.1897 + } 1.1898 +} 1.1899 + 1.1900 +/* 1.1901 + GetSourceOffset 1.1902 + 1.1903 + Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds) 1.1904 + The offset is relative to the start of the queue (not the start of the current buffer) 1.1905 +*/ 1.1906 +static ALvoid GetSourceOffset(ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen) 1.1907 +{ 1.1908 + const ALbufferlistitem *BufferList; 1.1909 + const ALbuffer *Buffer = NULL; 1.1910 + enum UserFmtType OriginalType; 1.1911 + ALsizei BufferFreq; 1.1912 + ALint Channels, Bytes; 1.1913 + ALuint readPos, writePos; 1.1914 + ALuint TotalBufferDataSize; 1.1915 + ALuint i; 1.1916 + 1.1917 + // Find the first non-NULL Buffer in the Queue 1.1918 + BufferList = Source->queue; 1.1919 + while(BufferList) 1.1920 + { 1.1921 + if(BufferList->buffer) 1.1922 + { 1.1923 + Buffer = BufferList->buffer; 1.1924 + break; 1.1925 + } 1.1926 + BufferList = BufferList->next; 1.1927 + } 1.1928 + 1.1929 + if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer) 1.1930 + { 1.1931 + offset[0] = 0.0; 1.1932 + offset[1] = 0.0; 1.1933 + return; 1.1934 + } 1.1935 + 1.1936 + // Get Current Buffer Size and frequency (in milliseconds) 1.1937 + BufferFreq = Buffer->Frequency; 1.1938 + OriginalType = Buffer->OriginalType; 1.1939 + Channels = ChannelsFromFmt(Buffer->FmtChannels); 1.1940 + Bytes = BytesFromFmt(Buffer->FmtType); 1.1941 + 1.1942 + // Get Current BytesPlayed (NOTE : This is the byte offset into the *current* buffer) 1.1943 + readPos = Source->position * Channels * Bytes; 1.1944 + // Add byte length of any processed buffers in the queue 1.1945 + TotalBufferDataSize = 0; 1.1946 + BufferList = Source->queue; 1.1947 + for(i = 0;BufferList;i++) 1.1948 + { 1.1949 + if(BufferList->buffer) 1.1950 + { 1.1951 + if(i < Source->BuffersPlayed) 1.1952 + readPos += BufferList->buffer->size; 1.1953 + TotalBufferDataSize += BufferList->buffer->size; 1.1954 + } 1.1955 + BufferList = BufferList->next; 1.1956 + } 1.1957 + if(Source->state == AL_PLAYING) 1.1958 + writePos = readPos + ((ALuint)(updateLen*BufferFreq) * Channels * Bytes); 1.1959 + else 1.1960 + writePos = readPos; 1.1961 + 1.1962 + if(Source->bLooping) 1.1963 + { 1.1964 + readPos %= TotalBufferDataSize; 1.1965 + writePos %= TotalBufferDataSize; 1.1966 + } 1.1967 + else 1.1968 + { 1.1969 + // Wrap positions back to 0 1.1970 + if(readPos >= TotalBufferDataSize) 1.1971 + readPos = 0; 1.1972 + if(writePos >= TotalBufferDataSize) 1.1973 + writePos = 0; 1.1974 + } 1.1975 + 1.1976 + switch(name) 1.1977 + { 1.1978 + case AL_SEC_OFFSET: 1.1979 + offset[0] = (ALdouble)readPos / (Channels * Bytes * BufferFreq); 1.1980 + offset[1] = (ALdouble)writePos / (Channels * Bytes * BufferFreq); 1.1981 + break; 1.1982 + case AL_SAMPLE_OFFSET: 1.1983 + case AL_SAMPLE_RW_OFFSETS_SOFT: 1.1984 + offset[0] = (ALdouble)(readPos / (Channels * Bytes)); 1.1985 + offset[1] = (ALdouble)(writePos / (Channels * Bytes)); 1.1986 + break; 1.1987 + case AL_BYTE_OFFSET: 1.1988 + case AL_BYTE_RW_OFFSETS_SOFT: 1.1989 + // Take into account the original format of the Buffer 1.1990 + if(OriginalType == UserFmtIMA4) 1.1991 + { 1.1992 + ALuint FrameBlockSize = 65 * Bytes * Channels; 1.1993 + ALuint BlockSize = 36 * Channels; 1.1994 + 1.1995 + // Round down to nearest ADPCM block 1.1996 + offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize); 1.1997 + if(Source->state != AL_PLAYING) 1.1998 + offset[1] = offset[0]; 1.1999 + else 1.2000 + { 1.2001 + // Round up to nearest ADPCM block 1.2002 + offset[1] = (ALdouble)((writePos+FrameBlockSize-1) / 1.2003 + FrameBlockSize * BlockSize); 1.2004 + } 1.2005 + } 1.2006 + else 1.2007 + { 1.2008 + ALuint OrigBytes = BytesFromUserFmt(OriginalType); 1.2009 + offset[0] = (ALdouble)(readPos / Bytes * OrigBytes); 1.2010 + offset[1] = (ALdouble)(writePos / Bytes * OrigBytes); 1.2011 + } 1.2012 + break; 1.2013 + } 1.2014 +} 1.2015 + 1.2016 + 1.2017 +/* 1.2018 + ApplyOffset 1.2019 + 1.2020 + Apply a playback offset to the Source. This function will update the queue (to correctly 1.2021 + mark buffers as 'pending' or 'processed' depending upon the new offset. 1.2022 +*/ 1.2023 +ALboolean ApplyOffset(ALsource *Source) 1.2024 +{ 1.2025 + const ALbufferlistitem *BufferList; 1.2026 + const ALbuffer *Buffer; 1.2027 + ALint lBufferSize, lTotalBufferSize; 1.2028 + ALint BuffersPlayed; 1.2029 + ALint lByteOffset; 1.2030 + 1.2031 + // Get true byte offset 1.2032 + lByteOffset = GetByteOffset(Source); 1.2033 + 1.2034 + // If the offset is invalid, don't apply it 1.2035 + if(lByteOffset == -1) 1.2036 + return AL_FALSE; 1.2037 + 1.2038 + // Sort out the queue (pending and processed states) 1.2039 + BufferList = Source->queue; 1.2040 + lTotalBufferSize = 0; 1.2041 + BuffersPlayed = 0; 1.2042 + 1.2043 + while(BufferList) 1.2044 + { 1.2045 + Buffer = BufferList->buffer; 1.2046 + lBufferSize = Buffer ? Buffer->size : 0; 1.2047 + 1.2048 + if(lBufferSize <= lByteOffset-lTotalBufferSize) 1.2049 + { 1.2050 + // Offset is past this buffer so increment BuffersPlayed 1.2051 + BuffersPlayed++; 1.2052 + } 1.2053 + else if(lTotalBufferSize <= lByteOffset) 1.2054 + { 1.2055 + // Offset is within this buffer 1.2056 + // Set Current Buffer 1.2057 + Source->Buffer = BufferList->buffer; 1.2058 + Source->BuffersPlayed = BuffersPlayed; 1.2059 + 1.2060 + // SW Mixer Positions are in Samples 1.2061 + Source->position = (lByteOffset - lTotalBufferSize) / 1.2062 + FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType); 1.2063 + return AL_TRUE; 1.2064 + } 1.2065 + 1.2066 + // Increment the TotalBufferSize 1.2067 + lTotalBufferSize += lBufferSize; 1.2068 + 1.2069 + // Move on to next buffer in the Queue 1.2070 + BufferList = BufferList->next; 1.2071 + } 1.2072 + // Offset is out of range of the buffer queue 1.2073 + return AL_FALSE; 1.2074 +} 1.2075 + 1.2076 + 1.2077 +/* 1.2078 + GetByteOffset 1.2079 + 1.2080 + Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond 1.2081 + offset supplied by the application). This takes into account the fact that the buffer format 1.2082 + may have been modifed by AL (e.g 8bit samples are converted to float) 1.2083 +*/ 1.2084 +static ALint GetByteOffset(ALsource *Source) 1.2085 +{ 1.2086 + const ALbuffer *Buffer = NULL; 1.2087 + const ALbufferlistitem *BufferList; 1.2088 + ALint ByteOffset = -1; 1.2089 + 1.2090 + // Find the first non-NULL Buffer in the Queue 1.2091 + BufferList = Source->queue; 1.2092 + while(BufferList) 1.2093 + { 1.2094 + if(BufferList->buffer) 1.2095 + { 1.2096 + Buffer = BufferList->buffer; 1.2097 + break; 1.2098 + } 1.2099 + BufferList = BufferList->next; 1.2100 + } 1.2101 + 1.2102 + if(!Buffer) 1.2103 + { 1.2104 + Source->lOffset = -1; 1.2105 + return -1; 1.2106 + } 1.2107 + 1.2108 + // Determine the ByteOffset (and ensure it is block aligned) 1.2109 + switch(Source->lOffsetType) 1.2110 + { 1.2111 + case AL_BYTE_OFFSET: 1.2112 + // Take into consideration the original format 1.2113 + ByteOffset = Source->lOffset; 1.2114 + if(Buffer->OriginalType == UserFmtIMA4) 1.2115 + { 1.2116 + // Round down to nearest ADPCM block 1.2117 + ByteOffset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels); 1.2118 + // Multiply by compression rate (65 sample frames per block) 1.2119 + ByteOffset *= 65; 1.2120 + } 1.2121 + else 1.2122 + ByteOffset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType); 1.2123 + ByteOffset *= FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType); 1.2124 + break; 1.2125 + 1.2126 + case AL_SAMPLE_OFFSET: 1.2127 + ByteOffset = Source->lOffset * FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType); 1.2128 + break; 1.2129 + 1.2130 + case AL_SEC_OFFSET: 1.2131 + // Note - lOffset is internally stored as Milliseconds 1.2132 + ByteOffset = (ALint)(Source->lOffset / 1000.0 * Buffer->Frequency); 1.2133 + ByteOffset *= FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType); 1.2134 + break; 1.2135 + } 1.2136 + // Clear Offset 1.2137 + Source->lOffset = -1; 1.2138 + 1.2139 + return ByteOffset; 1.2140 +} 1.2141 + 1.2142 + 1.2143 +ALvoid ReleaseALSources(ALCcontext *Context) 1.2144 +{ 1.2145 + ALsizei pos; 1.2146 + ALuint j; 1.2147 + for(pos = 0;pos < Context->SourceMap.size;pos++) 1.2148 + { 1.2149 + ALsource *temp = Context->SourceMap.array[pos].value; 1.2150 + Context->SourceMap.array[pos].value = NULL; 1.2151 + 1.2152 + // For each buffer in the source's queue, decrement its reference counter and remove it 1.2153 + while(temp->queue != NULL) 1.2154 + { 1.2155 + ALbufferlistitem *BufferList = temp->queue; 1.2156 + temp->queue = BufferList->next; 1.2157 + 1.2158 + if(BufferList->buffer != NULL) 1.2159 + BufferList->buffer->refcount--; 1.2160 + free(BufferList); 1.2161 + } 1.2162 + 1.2163 + for(j = 0;j < MAX_SENDS;++j) 1.2164 + { 1.2165 + if(temp->Send[j].Slot) 1.2166 + temp->Send[j].Slot->refcount--; 1.2167 + temp->Send[j].Slot = NULL; 1.2168 + } 1.2169 + 1.2170 + // Release source structure 1.2171 + FreeThunkEntry(temp->source); 1.2172 + memset(temp, 0, sizeof(ALsource)); 1.2173 + free(temp); 1.2174 + } 1.2175 +}