Mercurial > audio-send
diff Alc/ALu.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/Alc/ALu.c Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,1168 @@ 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 <math.h> 1.27 +#include <stdlib.h> 1.28 +#include <string.h> 1.29 +#include <ctype.h> 1.30 +#include <assert.h> 1.31 + 1.32 +#include "alMain.h" 1.33 +#include "AL/al.h" 1.34 +#include "AL/alc.h" 1.35 +#include "alSource.h" 1.36 +#include "alBuffer.h" 1.37 +#include "alListener.h" 1.38 +#include "alAuxEffectSlot.h" 1.39 +#include "alu.h" 1.40 +#include "bs2b.h" 1.41 + 1.42 + 1.43 +static __inline ALvoid aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector) 1.44 +{ 1.45 + outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1]; 1.46 + outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2]; 1.47 + outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0]; 1.48 +} 1.49 + 1.50 +static __inline ALfloat aluDotproduct(const ALfloat *inVector1, const ALfloat *inVector2) 1.51 +{ 1.52 + return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] + 1.53 + inVector1[2]*inVector2[2]; 1.54 +} 1.55 + 1.56 +static __inline ALvoid aluNormalize(ALfloat *inVector) 1.57 +{ 1.58 + ALfloat length, inverse_length; 1.59 + 1.60 + length = aluSqrt(aluDotproduct(inVector, inVector)); 1.61 + if(length != 0.0f) 1.62 + { 1.63 + inverse_length = 1.0f/length; 1.64 + inVector[0] *= inverse_length; 1.65 + inVector[1] *= inverse_length; 1.66 + inVector[2] *= inverse_length; 1.67 + } 1.68 +} 1.69 + 1.70 +static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat w,ALfloat matrix[4][4]) 1.71 +{ 1.72 + ALfloat temp[4] = { 1.73 + vector[0], vector[1], vector[2], w 1.74 + }; 1.75 + 1.76 + vector[0] = temp[0]*matrix[0][0] + temp[1]*matrix[1][0] + temp[2]*matrix[2][0] + temp[3]*matrix[3][0]; 1.77 + vector[1] = temp[0]*matrix[0][1] + temp[1]*matrix[1][1] + temp[2]*matrix[2][1] + temp[3]*matrix[3][1]; 1.78 + vector[2] = temp[0]*matrix[0][2] + temp[1]*matrix[1][2] + temp[2]*matrix[2][2] + temp[3]*matrix[3][2]; 1.79 +} 1.80 + 1.81 + 1.82 +ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) 1.83 +{ 1.84 + static const ALfloat angles_Mono[1] = { 0.0f }; 1.85 + static const ALfloat angles_Stereo[2] = { -30.0f, 30.0f }; 1.86 + static const ALfloat angles_Rear[2] = { -150.0f, 150.0f }; 1.87 + static const ALfloat angles_Quad[4] = { -45.0f, 45.0f, -135.0f, 135.0f }; 1.88 + static const ALfloat angles_X51[6] = { -30.0f, 30.0f, 0.0f, 0.0f, 1.89 + -110.0f, 110.0f }; 1.90 + static const ALfloat angles_X61[7] = { -30.0f, 30.0f, 0.0f, 0.0f, 1.91 + 180.0f, -90.0f, 90.0f }; 1.92 + static const ALfloat angles_X71[8] = { -30.0f, 30.0f, 0.0f, 0.0f, 1.93 + -110.0f, 110.0f, -90.0f, 90.0f }; 1.94 + 1.95 + static const enum Channel chans_Mono[1] = { FRONT_CENTER }; 1.96 + static const enum Channel chans_Stereo[2] = { FRONT_LEFT, FRONT_RIGHT }; 1.97 + static const enum Channel chans_Rear[2] = { BACK_LEFT, BACK_RIGHT }; 1.98 + static const enum Channel chans_Quad[4] = { FRONT_LEFT, FRONT_RIGHT, 1.99 + BACK_LEFT, BACK_RIGHT }; 1.100 + static const enum Channel chans_X51[6] = { FRONT_LEFT, FRONT_RIGHT, 1.101 + FRONT_CENTER, LFE, 1.102 + BACK_LEFT, BACK_RIGHT }; 1.103 + static const enum Channel chans_X61[7] = { FRONT_LEFT, FRONT_RIGHT, 1.104 + FRONT_CENTER, LFE, BACK_CENTER, 1.105 + SIDE_LEFT, SIDE_RIGHT }; 1.106 + static const enum Channel chans_X71[8] = { FRONT_LEFT, FRONT_RIGHT, 1.107 + FRONT_CENTER, LFE, 1.108 + BACK_LEFT, BACK_RIGHT, 1.109 + SIDE_LEFT, SIDE_RIGHT }; 1.110 + 1.111 + ALCdevice *Device = ALContext->Device; 1.112 + ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume; 1.113 + ALbufferlistitem *BufferListItem; 1.114 + enum DevFmtChannels DevChans; 1.115 + enum FmtChannels Channels; 1.116 + ALfloat (*SrcMatrix)[MAXCHANNELS]; 1.117 + ALfloat DryGain, DryGainHF; 1.118 + ALfloat WetGain[MAX_SENDS]; 1.119 + ALfloat WetGainHF[MAX_SENDS]; 1.120 + ALint NumSends, Frequency; 1.121 + const ALfloat *SpeakerGain; 1.122 + const ALfloat *angles = NULL; 1.123 + const enum Channel *chans = NULL; 1.124 + enum Resampler Resampler; 1.125 + ALint num_channels = 0; 1.126 + ALboolean VirtualChannels; 1.127 + ALfloat Pitch; 1.128 + ALfloat cw; 1.129 + ALuint pos; 1.130 + ALint i, c; 1.131 + 1.132 + /* Get device properties */ 1.133 + DevChans = ALContext->Device->FmtChans; 1.134 + NumSends = ALContext->Device->NumAuxSends; 1.135 + Frequency = ALContext->Device->Frequency; 1.136 + 1.137 + /* Get listener properties */ 1.138 + ListenerGain = ALContext->Listener.Gain; 1.139 + 1.140 + /* Get source properties */ 1.141 + SourceVolume = ALSource->flGain; 1.142 + MinVolume = ALSource->flMinGain; 1.143 + MaxVolume = ALSource->flMaxGain; 1.144 + Pitch = ALSource->flPitch; 1.145 + Resampler = ALSource->Resampler; 1.146 + VirtualChannels = ALSource->VirtualChannels; 1.147 + 1.148 + /* Calculate the stepping value */ 1.149 + Channels = FmtMono; 1.150 + BufferListItem = ALSource->queue; 1.151 + while(BufferListItem != NULL) 1.152 + { 1.153 + ALbuffer *ALBuffer; 1.154 + if((ALBuffer=BufferListItem->buffer) != NULL) 1.155 + { 1.156 + ALint maxstep = STACK_DATA_SIZE / ALSource->NumChannels / 1.157 + ALSource->SampleSize; 1.158 + maxstep -= ResamplerPadding[Resampler] + 1.159 + ResamplerPrePadding[Resampler] + 1; 1.160 + maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS); 1.161 + 1.162 + Pitch = Pitch * ALBuffer->Frequency / Frequency; 1.163 + if(Pitch > (ALfloat)maxstep) 1.164 + ALSource->Params.Step = maxstep<<FRACTIONBITS; 1.165 + else 1.166 + { 1.167 + ALSource->Params.Step = Pitch*FRACTIONONE; 1.168 + if(ALSource->Params.Step == 0) 1.169 + ALSource->Params.Step = 1; 1.170 + } 1.171 + 1.172 + Channels = ALBuffer->FmtChannels; 1.173 + 1.174 + if(ALSource->VirtualChannels && (Device->Flags&DEVICE_USE_HRTF)) 1.175 + ALSource->Params.DoMix = SelectHrtfMixer(ALBuffer, 1.176 + (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER : 1.177 + Resampler); 1.178 + else 1.179 + ALSource->Params.DoMix = SelectMixer(ALBuffer, 1.180 + (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER : 1.181 + Resampler); 1.182 + break; 1.183 + } 1.184 + BufferListItem = BufferListItem->next; 1.185 + } 1.186 + 1.187 + /* Calculate gains */ 1.188 + DryGain = clampf(SourceVolume, MinVolume, MaxVolume); 1.189 + DryGainHF = 1.0f; 1.190 + switch(ALSource->DirectFilter.type) 1.191 + { 1.192 + case AL_FILTER_LOWPASS: 1.193 + DryGain *= ALSource->DirectFilter.Gain; 1.194 + DryGainHF *= ALSource->DirectFilter.GainHF; 1.195 + break; 1.196 + } 1.197 + for(i = 0;i < NumSends;i++) 1.198 + { 1.199 + WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume); 1.200 + WetGainHF[i] = 1.0f; 1.201 + switch(ALSource->Send[i].WetFilter.type) 1.202 + { 1.203 + case AL_FILTER_LOWPASS: 1.204 + WetGain[i] *= ALSource->Send[i].WetFilter.Gain; 1.205 + WetGainHF[i] *= ALSource->Send[i].WetFilter.GainHF; 1.206 + break; 1.207 + } 1.208 + } 1.209 + 1.210 + SrcMatrix = ALSource->Params.DryGains; 1.211 + for(i = 0;i < MAXCHANNELS;i++) 1.212 + { 1.213 + for(c = 0;c < MAXCHANNELS;c++) 1.214 + SrcMatrix[i][c] = 0.0f; 1.215 + } 1.216 + switch(Channels) 1.217 + { 1.218 + case FmtMono: 1.219 + angles = angles_Mono; 1.220 + chans = chans_Mono; 1.221 + num_channels = 1; 1.222 + break; 1.223 + case FmtStereo: 1.224 + if(VirtualChannels && (ALContext->Device->Flags&DEVICE_DUPLICATE_STEREO)) 1.225 + { 1.226 + DryGain *= aluSqrt(2.0f/4.0f); 1.227 + for(c = 0;c < 2;c++) 1.228 + { 1.229 + pos = aluCart2LUTpos(cos(angles_Rear[c] * (M_PI/180.0)), 1.230 + sin(angles_Rear[c] * (M_PI/180.0))); 1.231 + SpeakerGain = Device->PanningLUT[pos]; 1.232 + 1.233 + for(i = 0;i < (ALint)Device->NumChan;i++) 1.234 + { 1.235 + enum Channel chan = Device->Speaker2Chan[i]; 1.236 + SrcMatrix[c][chan] += DryGain * ListenerGain * 1.237 + SpeakerGain[chan]; 1.238 + } 1.239 + } 1.240 + } 1.241 + angles = angles_Stereo; 1.242 + chans = chans_Stereo; 1.243 + num_channels = 2; 1.244 + break; 1.245 + 1.246 + case FmtRear: 1.247 + angles = angles_Rear; 1.248 + chans = chans_Rear; 1.249 + num_channels = 2; 1.250 + break; 1.251 + 1.252 + case FmtQuad: 1.253 + angles = angles_Quad; 1.254 + chans = chans_Quad; 1.255 + num_channels = 4; 1.256 + break; 1.257 + 1.258 + case FmtX51: 1.259 + angles = angles_X51; 1.260 + chans = chans_X51; 1.261 + num_channels = 6; 1.262 + break; 1.263 + 1.264 + case FmtX61: 1.265 + angles = angles_X61; 1.266 + chans = chans_X61; 1.267 + num_channels = 7; 1.268 + break; 1.269 + 1.270 + case FmtX71: 1.271 + angles = angles_X71; 1.272 + chans = chans_X71; 1.273 + num_channels = 8; 1.274 + break; 1.275 + } 1.276 + 1.277 + if(VirtualChannels == AL_FALSE) 1.278 + { 1.279 + for(c = 0;c < num_channels;c++) 1.280 + SrcMatrix[c][chans[c]] += DryGain * ListenerGain; 1.281 + } 1.282 + else if((Device->Flags&DEVICE_USE_HRTF)) 1.283 + { 1.284 + for(c = 0;c < num_channels;c++) 1.285 + { 1.286 + if(chans[c] == LFE) 1.287 + { 1.288 + /* Skip LFE */ 1.289 + ALSource->Params.HrtfDelay[c][0] = 0; 1.290 + ALSource->Params.HrtfDelay[c][1] = 0; 1.291 + for(i = 0;i < HRIR_LENGTH;i++) 1.292 + { 1.293 + ALSource->Params.HrtfCoeffs[c][i][0] = 0.0f; 1.294 + ALSource->Params.HrtfCoeffs[c][i][1] = 0.0f; 1.295 + } 1.296 + } 1.297 + else 1.298 + { 1.299 + /* Get the static HRIR coefficients and delays for this 1.300 + * channel. */ 1.301 + GetLerpedHrtfCoeffs(0.0, angles[c] * (M_PI/180.0), 1.302 + DryGain*ListenerGain, 1.303 + ALSource->Params.HrtfCoeffs[c], 1.304 + ALSource->Params.HrtfDelay[c]); 1.305 + } 1.306 + ALSource->HrtfCounter = 0; 1.307 + } 1.308 + } 1.309 + else 1.310 + { 1.311 + for(c = 0;c < num_channels;c++) 1.312 + { 1.313 + if(chans[c] == LFE) /* Special-case LFE */ 1.314 + { 1.315 + SrcMatrix[c][LFE] += DryGain * ListenerGain; 1.316 + continue; 1.317 + } 1.318 + pos = aluCart2LUTpos(cos(angles[c] * (M_PI/180.0)), 1.319 + sin(angles[c] * (M_PI/180.0))); 1.320 + SpeakerGain = Device->PanningLUT[pos]; 1.321 + 1.322 + for(i = 0;i < (ALint)Device->NumChan;i++) 1.323 + { 1.324 + enum Channel chan = Device->Speaker2Chan[i]; 1.325 + SrcMatrix[c][chan] += DryGain * ListenerGain * 1.326 + SpeakerGain[chan]; 1.327 + } 1.328 + } 1.329 + } 1.330 + for(i = 0;i < NumSends;i++) 1.331 + { 1.332 + ALSource->Params.Send[i].Slot = ALSource->Send[i].Slot; 1.333 + ALSource->Params.Send[i].WetGain = WetGain[i] * ListenerGain; 1.334 + } 1.335 + 1.336 + /* Update filter coefficients. Calculations based on the I3DL2 1.337 + * spec. */ 1.338 + cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / Frequency); 1.339 + 1.340 + /* We use two chained one-pole filters, so we need to take the 1.341 + * square root of the squared gain, which is the same as the base 1.342 + * gain. */ 1.343 + ALSource->Params.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw); 1.344 + for(i = 0;i < NumSends;i++) 1.345 + { 1.346 + /* We use a one-pole filter, so we need to take the squared gain */ 1.347 + ALfloat a = lpCoeffCalc(WetGainHF[i]*WetGainHF[i], cw); 1.348 + ALSource->Params.Send[i].iirFilter.coeff = a; 1.349 + } 1.350 +} 1.351 + 1.352 +ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) 1.353 +{ 1.354 + const ALCdevice *Device = ALContext->Device; 1.355 + ALfloat InnerAngle,OuterAngle,Angle,Distance,ClampedDist; 1.356 + ALfloat Direction[3],Position[3],SourceToListener[3]; 1.357 + ALfloat Velocity[3],ListenerVel[3]; 1.358 + ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff; 1.359 + ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain; 1.360 + ALfloat DopplerFactor, DopplerVelocity, SpeedOfSound; 1.361 + ALfloat AirAbsorptionFactor; 1.362 + ALfloat RoomAirAbsorption[MAX_SENDS]; 1.363 + ALbufferlistitem *BufferListItem; 1.364 + ALfloat Attenuation, EffectiveDist; 1.365 + ALfloat RoomAttenuation[MAX_SENDS]; 1.366 + ALfloat MetersPerUnit; 1.367 + ALfloat RoomRolloffBase; 1.368 + ALfloat RoomRolloff[MAX_SENDS]; 1.369 + ALfloat DecayDistance[MAX_SENDS]; 1.370 + ALfloat DryGain; 1.371 + ALfloat DryGainHF; 1.372 + ALboolean DryGainHFAuto; 1.373 + ALfloat WetGain[MAX_SENDS]; 1.374 + ALfloat WetGainHF[MAX_SENDS]; 1.375 + ALboolean WetGainAuto; 1.376 + ALboolean WetGainHFAuto; 1.377 + enum Resampler Resampler; 1.378 + ALfloat Pitch; 1.379 + ALuint Frequency; 1.380 + ALint NumSends; 1.381 + ALfloat cw; 1.382 + ALint i; 1.383 + 1.384 + DryGainHF = 1.0f; 1.385 + for(i = 0;i < MAX_SENDS;i++) 1.386 + WetGainHF[i] = 1.0f; 1.387 + 1.388 + //Get context properties 1.389 + DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor; 1.390 + DopplerVelocity = ALContext->DopplerVelocity; 1.391 + SpeedOfSound = ALContext->flSpeedOfSound; 1.392 + NumSends = Device->NumAuxSends; 1.393 + Frequency = Device->Frequency; 1.394 + 1.395 + //Get listener properties 1.396 + ListenerGain = ALContext->Listener.Gain; 1.397 + MetersPerUnit = ALContext->Listener.MetersPerUnit; 1.398 + memcpy(ListenerVel, ALContext->Listener.Velocity, sizeof(ALContext->Listener.Velocity)); 1.399 + 1.400 + //Get source properties 1.401 + SourceVolume = ALSource->flGain; 1.402 + MinVolume = ALSource->flMinGain; 1.403 + MaxVolume = ALSource->flMaxGain; 1.404 + Pitch = ALSource->flPitch; 1.405 + Resampler = ALSource->Resampler; 1.406 + memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition)); 1.407 + memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation)); 1.408 + memcpy(Velocity, ALSource->vVelocity, sizeof(ALSource->vVelocity)); 1.409 + MinDist = ALSource->flRefDistance; 1.410 + MaxDist = ALSource->flMaxDistance; 1.411 + Rolloff = ALSource->flRollOffFactor; 1.412 + InnerAngle = ALSource->flInnerAngle * ConeScale; 1.413 + OuterAngle = ALSource->flOuterAngle * ConeScale; 1.414 + AirAbsorptionFactor = ALSource->AirAbsorptionFactor; 1.415 + DryGainHFAuto = ALSource->DryGainHFAuto; 1.416 + WetGainAuto = ALSource->WetGainAuto; 1.417 + WetGainHFAuto = ALSource->WetGainHFAuto; 1.418 + RoomRolloffBase = ALSource->RoomRolloffFactor; 1.419 + for(i = 0;i < NumSends;i++) 1.420 + { 1.421 + ALeffectslot *Slot = ALSource->Send[i].Slot; 1.422 + 1.423 + if(!Slot || Slot->effect.type == AL_EFFECT_NULL) 1.424 + { 1.425 + RoomRolloff[i] = 0.0f; 1.426 + DecayDistance[i] = 0.0f; 1.427 + RoomAirAbsorption[i] = 1.0f; 1.428 + } 1.429 + else if(Slot->AuxSendAuto) 1.430 + { 1.431 + RoomRolloff[i] = RoomRolloffBase; 1.432 + if(IsReverbEffect(Slot->effect.type)) 1.433 + { 1.434 + RoomRolloff[i] += Slot->effect.Params.Reverb.RoomRolloffFactor; 1.435 + DecayDistance[i] = Slot->effect.Params.Reverb.DecayTime * 1.436 + SPEEDOFSOUNDMETRESPERSEC; 1.437 + RoomAirAbsorption[i] = Slot->effect.Params.Reverb.AirAbsorptionGainHF; 1.438 + } 1.439 + else 1.440 + { 1.441 + DecayDistance[i] = 0.0f; 1.442 + RoomAirAbsorption[i] = 1.0f; 1.443 + } 1.444 + } 1.445 + else 1.446 + { 1.447 + /* If the slot's auxiliary send auto is off, the data sent to the 1.448 + * effect slot is the same as the dry path, sans filter effects */ 1.449 + RoomRolloff[i] = Rolloff; 1.450 + DecayDistance[i] = 0.0f; 1.451 + RoomAirAbsorption[i] = AIRABSORBGAINHF; 1.452 + } 1.453 + 1.454 + ALSource->Params.Send[i].Slot = Slot; 1.455 + } 1.456 + 1.457 + //1. Translate Listener to origin (convert to head relative) 1.458 + if(ALSource->bHeadRelative == AL_FALSE) 1.459 + { 1.460 + ALfloat U[3],V[3],N[3]; 1.461 + ALfloat Matrix[4][4]; 1.462 + 1.463 + // Build transform matrix 1.464 + memcpy(N, ALContext->Listener.Forward, sizeof(N)); // At-vector 1.465 + aluNormalize(N); // Normalized At-vector 1.466 + memcpy(V, ALContext->Listener.Up, sizeof(V)); // Up-vector 1.467 + aluNormalize(V); // Normalized Up-vector 1.468 + aluCrossproduct(N, V, U); // Right-vector 1.469 + aluNormalize(U); // Normalized Right-vector 1.470 + Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0]; Matrix[0][3] = 0.0f; 1.471 + Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1]; Matrix[1][3] = 0.0f; 1.472 + Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2]; Matrix[2][3] = 0.0f; 1.473 + Matrix[3][0] = 0.0f; Matrix[3][1] = 0.0f; Matrix[3][2] = 0.0f; Matrix[3][3] = 1.0f; 1.474 + 1.475 + // Translate position 1.476 + Position[0] -= ALContext->Listener.Position[0]; 1.477 + Position[1] -= ALContext->Listener.Position[1]; 1.478 + Position[2] -= ALContext->Listener.Position[2]; 1.479 + 1.480 + // Transform source position and direction into listener space 1.481 + aluMatrixVector(Position, 1.0f, Matrix); 1.482 + aluMatrixVector(Direction, 0.0f, Matrix); 1.483 + // Transform source and listener velocity into listener space 1.484 + aluMatrixVector(Velocity, 0.0f, Matrix); 1.485 + aluMatrixVector(ListenerVel, 0.0f, Matrix); 1.486 + } 1.487 + else 1.488 + ListenerVel[0] = ListenerVel[1] = ListenerVel[2] = 0.0f; 1.489 + 1.490 + SourceToListener[0] = -Position[0]; 1.491 + SourceToListener[1] = -Position[1]; 1.492 + SourceToListener[2] = -Position[2]; 1.493 + aluNormalize(SourceToListener); 1.494 + aluNormalize(Direction); 1.495 + 1.496 + //2. Calculate distance attenuation 1.497 + Distance = aluSqrt(aluDotproduct(Position, Position)); 1.498 + ClampedDist = Distance; 1.499 + 1.500 + Attenuation = 1.0f; 1.501 + for(i = 0;i < NumSends;i++) 1.502 + RoomAttenuation[i] = 1.0f; 1.503 + switch(ALContext->SourceDistanceModel ? ALSource->DistanceModel : 1.504 + ALContext->DistanceModel) 1.505 + { 1.506 + case InverseDistanceClamped: 1.507 + ClampedDist = clampf(ClampedDist, MinDist, MaxDist); 1.508 + if(MaxDist < MinDist) 1.509 + break; 1.510 + //fall-through 1.511 + case InverseDistance: 1.512 + if(MinDist > 0.0f) 1.513 + { 1.514 + if((MinDist + (Rolloff * (ClampedDist - MinDist))) > 0.0f) 1.515 + Attenuation = MinDist / (MinDist + (Rolloff * (ClampedDist - MinDist))); 1.516 + for(i = 0;i < NumSends;i++) 1.517 + { 1.518 + if((MinDist + (RoomRolloff[i] * (ClampedDist - MinDist))) > 0.0f) 1.519 + RoomAttenuation[i] = MinDist / (MinDist + (RoomRolloff[i] * (ClampedDist - MinDist))); 1.520 + } 1.521 + } 1.522 + break; 1.523 + 1.524 + case LinearDistanceClamped: 1.525 + ClampedDist = clampf(ClampedDist, MinDist, MaxDist); 1.526 + if(MaxDist < MinDist) 1.527 + break; 1.528 + //fall-through 1.529 + case LinearDistance: 1.530 + if(MaxDist != MinDist) 1.531 + { 1.532 + Attenuation = 1.0f - (Rolloff*(ClampedDist-MinDist)/(MaxDist - MinDist)); 1.533 + Attenuation = maxf(Attenuation, 0.0f); 1.534 + for(i = 0;i < NumSends;i++) 1.535 + { 1.536 + RoomAttenuation[i] = 1.0f - (RoomRolloff[i]*(ClampedDist-MinDist)/(MaxDist - MinDist)); 1.537 + RoomAttenuation[i] = maxf(RoomAttenuation[i], 0.0f); 1.538 + } 1.539 + } 1.540 + break; 1.541 + 1.542 + case ExponentDistanceClamped: 1.543 + ClampedDist = clampf(ClampedDist, MinDist, MaxDist); 1.544 + if(MaxDist < MinDist) 1.545 + break; 1.546 + //fall-through 1.547 + case ExponentDistance: 1.548 + if(ClampedDist > 0.0f && MinDist > 0.0f) 1.549 + { 1.550 + Attenuation = aluPow(ClampedDist/MinDist, -Rolloff); 1.551 + for(i = 0;i < NumSends;i++) 1.552 + RoomAttenuation[i] = aluPow(ClampedDist/MinDist, -RoomRolloff[i]); 1.553 + } 1.554 + break; 1.555 + 1.556 + case DisableDistance: 1.557 + break; 1.558 + } 1.559 + 1.560 + // Source Gain + Attenuation 1.561 + DryGain = SourceVolume * Attenuation; 1.562 + for(i = 0;i < NumSends;i++) 1.563 + WetGain[i] = SourceVolume * RoomAttenuation[i]; 1.564 + 1.565 + // Distance-based air absorption 1.566 + EffectiveDist = 0.0f; 1.567 + if(MinDist > 0.0f && Attenuation < 1.0f) 1.568 + EffectiveDist = (MinDist/Attenuation - MinDist)*MetersPerUnit; 1.569 + if(AirAbsorptionFactor > 0.0f && EffectiveDist > 0.0f) 1.570 + { 1.571 + DryGainHF *= aluPow(AIRABSORBGAINHF, AirAbsorptionFactor*EffectiveDist); 1.572 + for(i = 0;i < NumSends;i++) 1.573 + WetGainHF[i] *= aluPow(RoomAirAbsorption[i], 1.574 + AirAbsorptionFactor*EffectiveDist); 1.575 + } 1.576 + 1.577 + //3. Apply directional soundcones 1.578 + Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * (180.0/M_PI); 1.579 + if(Angle >= InnerAngle && Angle <= OuterAngle) 1.580 + { 1.581 + ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle); 1.582 + ConeVolume = lerp(1.0, ALSource->flOuterGain, scale); 1.583 + ConeHF = lerp(1.0, ALSource->OuterGainHF, scale); 1.584 + } 1.585 + else if(Angle > OuterAngle) 1.586 + { 1.587 + ConeVolume = ALSource->flOuterGain; 1.588 + ConeHF = ALSource->OuterGainHF; 1.589 + } 1.590 + else 1.591 + { 1.592 + ConeVolume = 1.0f; 1.593 + ConeHF = 1.0f; 1.594 + } 1.595 + 1.596 + DryGain *= ConeVolume; 1.597 + if(WetGainAuto) 1.598 + { 1.599 + for(i = 0;i < NumSends;i++) 1.600 + WetGain[i] *= ConeVolume; 1.601 + } 1.602 + if(DryGainHFAuto) 1.603 + DryGainHF *= ConeHF; 1.604 + if(WetGainHFAuto) 1.605 + { 1.606 + for(i = 0;i < NumSends;i++) 1.607 + WetGainHF[i] *= ConeHF; 1.608 + } 1.609 + 1.610 + // Clamp to Min/Max Gain 1.611 + DryGain = clampf(DryGain, MinVolume, MaxVolume); 1.612 + for(i = 0;i < NumSends;i++) 1.613 + WetGain[i] = clampf(WetGain[i], MinVolume, MaxVolume); 1.614 + 1.615 + // Apply filter gains and filters 1.616 + switch(ALSource->DirectFilter.type) 1.617 + { 1.618 + case AL_FILTER_LOWPASS: 1.619 + DryGain *= ALSource->DirectFilter.Gain; 1.620 + DryGainHF *= ALSource->DirectFilter.GainHF; 1.621 + break; 1.622 + } 1.623 + DryGain *= ListenerGain; 1.624 + for(i = 0;i < NumSends;i++) 1.625 + { 1.626 + switch(ALSource->Send[i].WetFilter.type) 1.627 + { 1.628 + case AL_FILTER_LOWPASS: 1.629 + WetGain[i] *= ALSource->Send[i].WetFilter.Gain; 1.630 + WetGainHF[i] *= ALSource->Send[i].WetFilter.GainHF; 1.631 + break; 1.632 + } 1.633 + WetGain[i] *= ListenerGain; 1.634 + } 1.635 + 1.636 + if(WetGainAuto) 1.637 + { 1.638 + /* Apply a decay-time transformation to the wet path, based on the 1.639 + * attenuation of the dry path. 1.640 + * 1.641 + * Using the approximate (effective) source to listener distance, the 1.642 + * initial decay of the reverb effect is calculated and applied to the 1.643 + * wet path. 1.644 + */ 1.645 + for(i = 0;i < NumSends;i++) 1.646 + { 1.647 + if(DecayDistance[i] > 0.0f) 1.648 + WetGain[i] *= aluPow(0.001f /* -60dB */, 1.649 + EffectiveDist / DecayDistance[i]); 1.650 + } 1.651 + } 1.652 + 1.653 + // Calculate Velocity 1.654 + if(DopplerFactor != 0.0f) 1.655 + { 1.656 + ALfloat VSS, VLS; 1.657 + ALfloat MaxVelocity = (SpeedOfSound*DopplerVelocity) / 1.658 + DopplerFactor; 1.659 + 1.660 + VSS = aluDotproduct(Velocity, SourceToListener); 1.661 + if(VSS >= MaxVelocity) 1.662 + VSS = (MaxVelocity - 1.0f); 1.663 + else if(VSS <= -MaxVelocity) 1.664 + VSS = -MaxVelocity + 1.0f; 1.665 + 1.666 + VLS = aluDotproduct(ListenerVel, SourceToListener); 1.667 + if(VLS >= MaxVelocity) 1.668 + VLS = (MaxVelocity - 1.0f); 1.669 + else if(VLS <= -MaxVelocity) 1.670 + VLS = -MaxVelocity + 1.0f; 1.671 + 1.672 + Pitch *= ((SpeedOfSound*DopplerVelocity) - (DopplerFactor*VLS)) / 1.673 + ((SpeedOfSound*DopplerVelocity) - (DopplerFactor*VSS)); 1.674 + } 1.675 + 1.676 + BufferListItem = ALSource->queue; 1.677 + while(BufferListItem != NULL) 1.678 + { 1.679 + ALbuffer *ALBuffer; 1.680 + if((ALBuffer=BufferListItem->buffer) != NULL) 1.681 + { 1.682 + ALint maxstep = STACK_DATA_SIZE / ALSource->NumChannels / 1.683 + ALSource->SampleSize; 1.684 + maxstep -= ResamplerPadding[Resampler] + 1.685 + ResamplerPrePadding[Resampler] + 1; 1.686 + maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS); 1.687 + 1.688 + Pitch = Pitch * ALBuffer->Frequency / Frequency; 1.689 + if(Pitch > (ALfloat)maxstep) 1.690 + ALSource->Params.Step = maxstep<<FRACTIONBITS; 1.691 + else 1.692 + { 1.693 + ALSource->Params.Step = Pitch*FRACTIONONE; 1.694 + if(ALSource->Params.Step == 0) 1.695 + ALSource->Params.Step = 1; 1.696 + } 1.697 + 1.698 + if((Device->Flags&DEVICE_USE_HRTF)) 1.699 + ALSource->Params.DoMix = SelectHrtfMixer(ALBuffer, 1.700 + (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER : 1.701 + Resampler); 1.702 + else 1.703 + ALSource->Params.DoMix = SelectMixer(ALBuffer, 1.704 + (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER : 1.705 + Resampler); 1.706 + break; 1.707 + } 1.708 + BufferListItem = BufferListItem->next; 1.709 + } 1.710 + 1.711 + if((Device->Flags&DEVICE_USE_HRTF)) 1.712 + { 1.713 + // Use a binaural HRTF algorithm for stereo headphone playback 1.714 + ALfloat delta, ev = 0.0f, az = 0.0f; 1.715 + 1.716 + if(Distance > 0.0f) 1.717 + { 1.718 + ALfloat invlen = 1.0f/Distance; 1.719 + Position[0] *= invlen; 1.720 + Position[1] *= invlen; 1.721 + Position[2] *= invlen; 1.722 + 1.723 + // Calculate elevation and azimuth only when the source is not at 1.724 + // the listener. This prevents +0 and -0 Z from producing 1.725 + // inconsistent panning. 1.726 + ev = asin(Position[1]); 1.727 + az = atan2(Position[0], -Position[2]*ZScale); 1.728 + } 1.729 + 1.730 + // Check to see if the HRIR is already moving. 1.731 + if(ALSource->HrtfMoving) 1.732 + { 1.733 + // Calculate the normalized HRTF transition factor (delta). 1.734 + delta = CalcHrtfDelta(ALSource->Params.HrtfGain, DryGain, 1.735 + ALSource->Params.HrtfDir, Position); 1.736 + // If the delta is large enough, get the moving HRIR target 1.737 + // coefficients, target delays, steppping values, and counter. 1.738 + if(delta > 0.001f) 1.739 + { 1.740 + ALSource->HrtfCounter = GetMovingHrtfCoeffs(ev, az, DryGain, 1.741 + delta, ALSource->HrtfCounter, 1.742 + ALSource->Params.HrtfCoeffs[0], 1.743 + ALSource->Params.HrtfDelay[0], 1.744 + ALSource->Params.HrtfCoeffStep, 1.745 + ALSource->Params.HrtfDelayStep); 1.746 + ALSource->Params.HrtfGain = DryGain; 1.747 + ALSource->Params.HrtfDir[0] = Position[0]; 1.748 + ALSource->Params.HrtfDir[1] = Position[1]; 1.749 + ALSource->Params.HrtfDir[2] = Position[2]; 1.750 + } 1.751 + } 1.752 + else 1.753 + { 1.754 + // Get the initial (static) HRIR coefficients and delays. 1.755 + GetLerpedHrtfCoeffs(ev, az, DryGain, 1.756 + ALSource->Params.HrtfCoeffs[0], 1.757 + ALSource->Params.HrtfDelay[0]); 1.758 + ALSource->HrtfCounter = 0; 1.759 + ALSource->Params.HrtfGain = DryGain; 1.760 + ALSource->Params.HrtfDir[0] = Position[0]; 1.761 + ALSource->Params.HrtfDir[1] = Position[1]; 1.762 + ALSource->Params.HrtfDir[2] = Position[2]; 1.763 + } 1.764 + } 1.765 + else 1.766 + { 1.767 + // Use energy-preserving panning algorithm for multi-speaker playback 1.768 + ALfloat DirGain, AmbientGain; 1.769 + const ALfloat *SpeakerGain; 1.770 + ALfloat length; 1.771 + ALint pos; 1.772 + 1.773 + length = maxf(Distance, MinDist); 1.774 + if(length > 0.0f) 1.775 + { 1.776 + ALfloat invlen = 1.0f/length; 1.777 + Position[0] *= invlen; 1.778 + Position[1] *= invlen; 1.779 + Position[2] *= invlen; 1.780 + } 1.781 + 1.782 + pos = aluCart2LUTpos(-Position[2]*ZScale, Position[0]); 1.783 + SpeakerGain = Device->PanningLUT[pos]; 1.784 + 1.785 + DirGain = aluSqrt(Position[0]*Position[0] + Position[2]*Position[2]); 1.786 + // elevation adjustment for directional gain. this sucks, but 1.787 + // has low complexity 1.788 + AmbientGain = aluSqrt(1.0/Device->NumChan); 1.789 + for(i = 0;i < MAXCHANNELS;i++) 1.790 + { 1.791 + ALuint i2; 1.792 + for(i2 = 0;i2 < MAXCHANNELS;i2++) 1.793 + ALSource->Params.DryGains[i][i2] = 0.0f; 1.794 + } 1.795 + for(i = 0;i < (ALint)Device->NumChan;i++) 1.796 + { 1.797 + enum Channel chan = Device->Speaker2Chan[i]; 1.798 + ALfloat gain = lerp(AmbientGain, SpeakerGain[chan], DirGain); 1.799 + ALSource->Params.DryGains[0][chan] = DryGain * gain; 1.800 + } 1.801 + } 1.802 + for(i = 0;i < NumSends;i++) 1.803 + ALSource->Params.Send[i].WetGain = WetGain[i]; 1.804 + 1.805 + /* Update filter coefficients. */ 1.806 + cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / Frequency); 1.807 + 1.808 + ALSource->Params.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw); 1.809 + for(i = 0;i < NumSends;i++) 1.810 + { 1.811 + ALfloat a = lpCoeffCalc(WetGainHF[i]*WetGainHF[i], cw); 1.812 + ALSource->Params.Send[i].iirFilter.coeff = a; 1.813 + } 1.814 +} 1.815 + 1.816 + 1.817 +static __inline ALfloat aluF2F(ALfloat val) 1.818 +{ return val; } 1.819 +static __inline ALshort aluF2S(ALfloat val) 1.820 +{ 1.821 + if(val > 1.0f) return 32767; 1.822 + if(val < -1.0f) return -32768; 1.823 + return (ALint)(val*32767.0f); 1.824 +} 1.825 +static __inline ALushort aluF2US(ALfloat val) 1.826 +{ return aluF2S(val)+32768; } 1.827 +static __inline ALbyte aluF2B(ALfloat val) 1.828 +{ return aluF2S(val)>>8; } 1.829 +static __inline ALubyte aluF2UB(ALfloat val) 1.830 +{ return aluF2US(val)>>8; } 1.831 + 1.832 +#define DECL_TEMPLATE(T, N, func) \ 1.833 +static void Write_##T##_##N(ALCdevice *device, T *RESTRICT buffer, \ 1.834 + ALuint SamplesToDo) \ 1.835 +{ \ 1.836 + ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS] = device->DryBuffer; \ 1.837 + const enum Channel *ChanMap = device->DevChannels; \ 1.838 + ALuint i, j; \ 1.839 + \ 1.840 + for(i = 0;i < SamplesToDo;i++) \ 1.841 + { \ 1.842 + for(j = 0;j < N;j++) \ 1.843 + *(buffer++) = func(DryBuffer[i][ChanMap[j]]); \ 1.844 + } \ 1.845 +} 1.846 + 1.847 +DECL_TEMPLATE(ALfloat, 1, aluF2F) 1.848 +DECL_TEMPLATE(ALfloat, 4, aluF2F) 1.849 +DECL_TEMPLATE(ALfloat, 6, aluF2F) 1.850 +DECL_TEMPLATE(ALfloat, 7, aluF2F) 1.851 +DECL_TEMPLATE(ALfloat, 8, aluF2F) 1.852 + 1.853 +DECL_TEMPLATE(ALushort, 1, aluF2US) 1.854 +DECL_TEMPLATE(ALushort, 4, aluF2US) 1.855 +DECL_TEMPLATE(ALushort, 6, aluF2US) 1.856 +DECL_TEMPLATE(ALushort, 7, aluF2US) 1.857 +DECL_TEMPLATE(ALushort, 8, aluF2US) 1.858 + 1.859 +DECL_TEMPLATE(ALshort, 1, aluF2S) 1.860 +DECL_TEMPLATE(ALshort, 4, aluF2S) 1.861 +DECL_TEMPLATE(ALshort, 6, aluF2S) 1.862 +DECL_TEMPLATE(ALshort, 7, aluF2S) 1.863 +DECL_TEMPLATE(ALshort, 8, aluF2S) 1.864 + 1.865 +DECL_TEMPLATE(ALubyte, 1, aluF2UB) 1.866 +DECL_TEMPLATE(ALubyte, 4, aluF2UB) 1.867 +DECL_TEMPLATE(ALubyte, 6, aluF2UB) 1.868 +DECL_TEMPLATE(ALubyte, 7, aluF2UB) 1.869 +DECL_TEMPLATE(ALubyte, 8, aluF2UB) 1.870 + 1.871 +DECL_TEMPLATE(ALbyte, 1, aluF2B) 1.872 +DECL_TEMPLATE(ALbyte, 4, aluF2B) 1.873 +DECL_TEMPLATE(ALbyte, 6, aluF2B) 1.874 +DECL_TEMPLATE(ALbyte, 7, aluF2B) 1.875 +DECL_TEMPLATE(ALbyte, 8, aluF2B) 1.876 + 1.877 +#undef DECL_TEMPLATE 1.878 + 1.879 +#define DECL_TEMPLATE(T, N, func) \ 1.880 +static void Write_##T##_##N(ALCdevice *device, T *RESTRICT buffer, \ 1.881 + ALuint SamplesToDo) \ 1.882 +{ \ 1.883 + ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS] = device->DryBuffer; \ 1.884 + const enum Channel *ChanMap = device->DevChannels; \ 1.885 + ALuint i, j; \ 1.886 + \ 1.887 + if(device->Bs2b) \ 1.888 + { \ 1.889 + for(i = 0;i < SamplesToDo;i++) \ 1.890 + { \ 1.891 + float samples[2]; \ 1.892 + samples[0] = DryBuffer[i][ChanMap[0]]; \ 1.893 + samples[1] = DryBuffer[i][ChanMap[1]]; \ 1.894 + bs2b_cross_feed(device->Bs2b, samples); \ 1.895 + *(buffer++) = func(samples[0]); \ 1.896 + *(buffer++) = func(samples[1]); \ 1.897 + } \ 1.898 + } \ 1.899 + else \ 1.900 + { \ 1.901 + for(i = 0;i < SamplesToDo;i++) \ 1.902 + { \ 1.903 + for(j = 0;j < N;j++) \ 1.904 + *(buffer++) = func(DryBuffer[i][ChanMap[j]]); \ 1.905 + } \ 1.906 + } \ 1.907 +} 1.908 + 1.909 +DECL_TEMPLATE(ALfloat, 2, aluF2F) 1.910 +DECL_TEMPLATE(ALushort, 2, aluF2US) 1.911 +DECL_TEMPLATE(ALshort, 2, aluF2S) 1.912 +DECL_TEMPLATE(ALubyte, 2, aluF2UB) 1.913 +DECL_TEMPLATE(ALbyte, 2, aluF2B) 1.914 + 1.915 +#undef DECL_TEMPLATE 1.916 + 1.917 +#define DECL_TEMPLATE(T) \ 1.918 +static void Write_##T(ALCdevice *device, T *buffer, ALuint SamplesToDo) \ 1.919 +{ \ 1.920 + switch(device->FmtChans) \ 1.921 + { \ 1.922 + case DevFmtMono: \ 1.923 + Write_##T##_1(device, buffer, SamplesToDo); \ 1.924 + break; \ 1.925 + case DevFmtStereo: \ 1.926 + Write_##T##_2(device, buffer, SamplesToDo); \ 1.927 + break; \ 1.928 + case DevFmtQuad: \ 1.929 + Write_##T##_4(device, buffer, SamplesToDo); \ 1.930 + break; \ 1.931 + case DevFmtX51: \ 1.932 + case DevFmtX51Side: \ 1.933 + Write_##T##_6(device, buffer, SamplesToDo); \ 1.934 + break; \ 1.935 + case DevFmtX61: \ 1.936 + Write_##T##_7(device, buffer, SamplesToDo); \ 1.937 + break; \ 1.938 + case DevFmtX71: \ 1.939 + Write_##T##_8(device, buffer, SamplesToDo); \ 1.940 + break; \ 1.941 + } \ 1.942 +} 1.943 + 1.944 +DECL_TEMPLATE(ALfloat) 1.945 +DECL_TEMPLATE(ALushort) 1.946 +DECL_TEMPLATE(ALshort) 1.947 +DECL_TEMPLATE(ALubyte) 1.948 +DECL_TEMPLATE(ALbyte) 1.949 + 1.950 +#undef DECL_TEMPLATE 1.951 + 1.952 +ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) 1.953 +{ 1.954 + ALuint SamplesToDo; 1.955 + ALeffectslot *ALEffectSlot; 1.956 + ALCcontext **ctx, **ctx_end; 1.957 + ALsource **src, **src_end; 1.958 + int fpuState; 1.959 + ALuint i, c; 1.960 + ALsizei e; 1.961 + 1.962 +#if defined(HAVE_FESETROUND) 1.963 + fpuState = fegetround(); 1.964 + fesetround(FE_TOWARDZERO); 1.965 +#elif defined(HAVE__CONTROLFP) 1.966 + fpuState = _controlfp(0, 0); 1.967 + (void)_controlfp(_RC_CHOP, _MCW_RC); 1.968 +#else 1.969 + (void)fpuState; 1.970 +#endif 1.971 + 1.972 + while(size > 0) 1.973 + { 1.974 + /* Setup variables */ 1.975 + SamplesToDo = minu(size, BUFFERSIZE); 1.976 + 1.977 + /* Clear mixing buffer */ 1.978 + memset(device->DryBuffer, 0, SamplesToDo*MAXCHANNELS*sizeof(ALfloat)); 1.979 + 1.980 + LockDevice(device); 1.981 + ctx = device->Contexts; 1.982 + ctx_end = ctx + device->NumContexts; 1.983 + //printf("Contexts: %d\n", device->NumContexts); 1.984 + int context_number = 0; 1.985 + while(ctx != ctx_end) 1.986 + { 1.987 + //printf("Context %d:\n", context_number++); 1.988 + ALboolean DeferUpdates = (*ctx)->DeferUpdates; 1.989 + ALboolean UpdateSources = AL_FALSE; 1.990 + 1.991 + if(!DeferUpdates) 1.992 + { 1.993 + //printf("NOT deferring updates, whatever that means\n"); 1.994 + UpdateSources = (*ctx)->UpdateSources; 1.995 + //printf("update sources is set to %d\n", UpdateSources); 1.996 + (*ctx)->UpdateSources = AL_FALSE; 1.997 + } 1.998 + 1.999 + src = (*ctx)->ActiveSources; 1.1000 + src_end = src + (*ctx)->ActiveSourceCount; 1.1001 + //printf("number of active sources are %d\n", (*ctx)->ActiveSourceCount); 1.1002 + while(src != src_end) 1.1003 + { 1.1004 + 1.1005 + if((*src)->state != AL_PLAYING) 1.1006 + { 1.1007 + --((*ctx)->ActiveSourceCount); 1.1008 + *src = *(--src_end); 1.1009 + continue; 1.1010 + } 1.1011 + 1.1012 + if(!DeferUpdates && ((*src)->NeedsUpdate || UpdateSources)) 1.1013 + { 1.1014 + (*src)->NeedsUpdate = AL_FALSE; 1.1015 + ALsource_Update(*src, *ctx); 1.1016 + } 1.1017 + //printf("calling MixSource!\n"); 1.1018 + MixSource(*src, device, SamplesToDo); 1.1019 + src++; 1.1020 + } 1.1021 + 1.1022 + /* effect slot processing */ 1.1023 + for(e = 0;e < (*ctx)->EffectSlotMap.size;e++) 1.1024 + { 1.1025 + ALEffectSlot = (*ctx)->EffectSlotMap.array[e].value; 1.1026 + 1.1027 + for(i = 0;i < SamplesToDo;i++) 1.1028 + { 1.1029 + // RLM: remove click-removal 1.1030 + ALEffectSlot->WetBuffer[i] += ALEffectSlot->ClickRemoval[0]; 1.1031 + ALEffectSlot->ClickRemoval[0] -= ALEffectSlot->ClickRemoval[0] / 256.0f; 1.1032 + } 1.1033 + for(i = 0;i < 1;i++) 1.1034 + { 1.1035 + // RLM: remove click-removal 1.1036 + ALEffectSlot->ClickRemoval[i] += ALEffectSlot->PendingClicks[i]; 1.1037 + ALEffectSlot->PendingClicks[i] = 0.0f; 1.1038 + } 1.1039 + 1.1040 + if(!DeferUpdates && ALEffectSlot->NeedsUpdate) 1.1041 + { 1.1042 + ALEffectSlot->NeedsUpdate = AL_FALSE; 1.1043 + ALEffect_Update(ALEffectSlot->EffectState, *ctx, ALEffectSlot); 1.1044 + } 1.1045 + 1.1046 + ALEffect_Process(ALEffectSlot->EffectState, ALEffectSlot, 1.1047 + SamplesToDo, ALEffectSlot->WetBuffer, 1.1048 + device->DryBuffer); 1.1049 + 1.1050 + for(i = 0;i < SamplesToDo;i++) 1.1051 + ALEffectSlot->WetBuffer[i] = 0.0f; 1.1052 + } 1.1053 + 1.1054 + ctx++; 1.1055 + } 1.1056 + UnlockDevice(device); 1.1057 + 1.1058 + //Post processing loop 1.1059 + if(device->FmtChans == DevFmtMono) 1.1060 + { 1.1061 + for(i = 0;i < SamplesToDo;i++) 1.1062 + { 1.1063 + // RLM: remove click-removal 1.1064 + device->DryBuffer[i][FRONT_CENTER] += device->ClickRemoval[FRONT_CENTER]; 1.1065 + device->ClickRemoval[FRONT_CENTER] -= device->ClickRemoval[FRONT_CENTER] / 256.0f; 1.1066 + } 1.1067 + // RLM: remove click-removal 1.1068 + device->ClickRemoval[FRONT_CENTER] += device->PendingClicks[FRONT_CENTER]; 1.1069 + device->PendingClicks[FRONT_CENTER] = 0.0f; 1.1070 + } 1.1071 + else if(device->FmtChans == DevFmtStereo) 1.1072 + { 1.1073 + /* Assumes the first two channels are FRONT_LEFT and FRONT_RIGHT */ 1.1074 + for(i = 0;i < SamplesToDo;i++) 1.1075 + { 1.1076 + for(c = 0;c < 2;c++) 1.1077 + { 1.1078 + // RLM: remove click-removal 1.1079 + device->DryBuffer[i][c] += device->ClickRemoval[c]; 1.1080 + device->ClickRemoval[c] -= device->ClickRemoval[c] / 256.0f; 1.1081 + } 1.1082 + } 1.1083 + for(c = 0;c < 2;c++) 1.1084 + { 1.1085 + // RLM: remove click-removal 1.1086 + device->ClickRemoval[c] += device->PendingClicks[c]; 1.1087 + device->PendingClicks[c] = 0.0f; 1.1088 + } 1.1089 + } 1.1090 + else 1.1091 + { 1.1092 + for(i = 0;i < SamplesToDo;i++) 1.1093 + { 1.1094 + for(c = 0;c < MAXCHANNELS;c++) 1.1095 + { 1.1096 + // RLM: remove click-removal 1.1097 + device->DryBuffer[i][c] += device->ClickRemoval[c]; 1.1098 + device->ClickRemoval[c] -= device->ClickRemoval[c] / 256.0f; 1.1099 + } 1.1100 + } 1.1101 + for(c = 0;c < MAXCHANNELS;c++) 1.1102 + { 1.1103 + // RLM: remove click-removal 1.1104 + device->ClickRemoval[c] += device->PendingClicks[c]; 1.1105 + device->PendingClicks[c] = 0.0f; 1.1106 + } 1.1107 + } 1.1108 + 1.1109 + if(buffer) 1.1110 + { 1.1111 + switch(device->FmtType) 1.1112 + { 1.1113 + case DevFmtByte: 1.1114 + Write_ALbyte(device, buffer, SamplesToDo); 1.1115 + break; 1.1116 + case DevFmtUByte: 1.1117 + Write_ALubyte(device, buffer, SamplesToDo); 1.1118 + break; 1.1119 + case DevFmtShort: 1.1120 + Write_ALshort(device, buffer, SamplesToDo); 1.1121 + break; 1.1122 + case DevFmtUShort: 1.1123 + Write_ALushort(device, buffer, SamplesToDo); 1.1124 + break; 1.1125 + case DevFmtFloat: 1.1126 + Write_ALfloat(device, buffer, SamplesToDo); 1.1127 + break; 1.1128 + } 1.1129 + } 1.1130 + 1.1131 + size -= SamplesToDo; 1.1132 + } 1.1133 + 1.1134 +#if defined(HAVE_FESETROUND) 1.1135 + fesetround(fpuState); 1.1136 +#elif defined(HAVE__CONTROLFP) 1.1137 + _controlfp(fpuState, _MCW_RC); 1.1138 +#endif 1.1139 +} 1.1140 + 1.1141 + 1.1142 + 1.1143 + 1.1144 + 1.1145 +ALvoid aluHandleDisconnect(ALCdevice *device) 1.1146 +{ 1.1147 + ALuint i; 1.1148 + 1.1149 + LockDevice(device); 1.1150 + for(i = 0;i < device->NumContexts;i++) 1.1151 + { 1.1152 + ALCcontext *Context = device->Contexts[i]; 1.1153 + ALsource *source; 1.1154 + ALsizei pos; 1.1155 + 1.1156 + for(pos = 0;pos < Context->SourceMap.size;pos++) 1.1157 + { 1.1158 + source = Context->SourceMap.array[pos].value; 1.1159 + if(source->state == AL_PLAYING) 1.1160 + { 1.1161 + source->state = AL_STOPPED; 1.1162 + source->BuffersPlayed = source->BuffersInQueue; 1.1163 + source->position = 0; 1.1164 + source->position_fraction = 0; 1.1165 + } 1.1166 + } 1.1167 + } 1.1168 + 1.1169 + device->Connected = ALC_FALSE; 1.1170 + UnlockDevice(device); 1.1171 +}