zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ALu.c
Go to the documentation of this file.
1 
21 #include "config.h"
22 
23 #include <math.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
28 
29 #include "alMain.h"
30 #include "alSource.h"
31 #include "alBuffer.h"
32 #include "alListener.h"
33 #include "alAuxEffectSlot.h"
34 #include "alu.h"
35 #include "bs2b.h"
36 
37 #include "mixer_defs.h"
38 
39 
40 struct ChanMap {
41  enum Channel channel;
42  ALfloat angle;
43 };
44 
45 /* Cone scalar */
47 
48 /* Localized Z scalar for mono sources */
49 ALfloat ZScale = 1.0f;
50 
51 
53 {
54  if(increment == FRACTIONONE)
55  return Resample_copy32_C;
56  switch(Resampler)
57  {
58  case PointResampler:
59  return Resample_point32_C;
60  case LinearResampler:
61  return Resample_lerp32_C;
62  case CubicResampler:
63  return Resample_cubic32_C;
64  case ResamplerMax:
65  /* Shouldn't happen */
66  break;
67  }
68 
69  return Resample_point32_C;
70 }
71 
72 
74 {
75 #ifdef HAVE_SSE
77  return MixDirect_Hrtf_SSE;
78 #endif
79 #ifdef HAVE_NEON
81  return MixDirect_Hrtf_Neon;
82 #endif
83 
84  return MixDirect_Hrtf_C;
85 }
86 
88 {
89 #ifdef HAVE_SSE
91  return MixDirect_SSE;
92 #endif
93 
94  return MixDirect_C;
95 }
96 
98 {
99 #ifdef HAVE_SSE
101  return MixSend_SSE;
102 #endif
103 
104  return MixSend_C;
105 }
106 
107 
108 static __inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
109 {
110  outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
111  outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
112  outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
113 }
114 
115 static __inline ALfloat aluDotproduct(const ALfloat *inVector1, const ALfloat *inVector2)
116 {
117  return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
118  inVector1[2]*inVector2[2];
119 }
120 
121 static __inline void aluNormalize(ALfloat *inVector)
122 {
123  ALfloat lengthsqr = aluDotproduct(inVector, inVector);
124  if(lengthsqr > 0.0f)
125  {
126  ALfloat inv_length = 1.0f/sqrtf(lengthsqr);
127  inVector[0] *= inv_length;
128  inVector[1] *= inv_length;
129  inVector[2] *= inv_length;
130  }
131 }
132 
133 static __inline ALvoid aluMatrixVector(ALfloat *vector, ALfloat w, ALfloat (*RESTRICT matrix)[4])
134 {
135  ALfloat temp[4] = {
136  vector[0], vector[1], vector[2], w
137  };
138 
139  vector[0] = temp[0]*matrix[0][0] + temp[1]*matrix[1][0] + temp[2]*matrix[2][0] + temp[3]*matrix[3][0];
140  vector[1] = temp[0]*matrix[0][1] + temp[1]*matrix[1][1] + temp[2]*matrix[2][1] + temp[3]*matrix[3][1];
141  vector[2] = temp[0]*matrix[0][2] + temp[1]*matrix[1][2] + temp[2]*matrix[2][2] + temp[3]*matrix[3][2];
142 }
143 
144 
146 {
147  ALfloat N[3], V[3], U[3], P[3];
148 
149  /* AT then UP */
150  N[0] = Listener->Forward[0];
151  N[1] = Listener->Forward[1];
152  N[2] = Listener->Forward[2];
153  aluNormalize(N);
154  V[0] = Listener->Up[0];
155  V[1] = Listener->Up[1];
156  V[2] = Listener->Up[2];
157  aluNormalize(V);
158  /* Build and normalize right-vector */
159  aluCrossproduct(N, V, U);
160  aluNormalize(U);
161 
162  Listener->Params.Matrix[0][0] = U[0];
163  Listener->Params.Matrix[0][1] = V[0];
164  Listener->Params.Matrix[0][2] = -N[0];
165  Listener->Params.Matrix[0][3] = 0.0f;
166  Listener->Params.Matrix[1][0] = U[1];
167  Listener->Params.Matrix[1][1] = V[1];
168  Listener->Params.Matrix[1][2] = -N[1];
169  Listener->Params.Matrix[1][3] = 0.0f;
170  Listener->Params.Matrix[2][0] = U[2];
171  Listener->Params.Matrix[2][1] = V[2];
172  Listener->Params.Matrix[2][2] = -N[2];
173  Listener->Params.Matrix[2][3] = 0.0f;
174  Listener->Params.Matrix[3][0] = 0.0f;
175  Listener->Params.Matrix[3][1] = 0.0f;
176  Listener->Params.Matrix[3][2] = 0.0f;
177  Listener->Params.Matrix[3][3] = 1.0f;
178 
179  P[0] = Listener->Position[0];
180  P[1] = Listener->Position[1];
181  P[2] = Listener->Position[2];
182  aluMatrixVector(P, 1.0f, Listener->Params.Matrix);
183  Listener->Params.Matrix[3][0] = -P[0];
184  Listener->Params.Matrix[3][1] = -P[1];
185  Listener->Params.Matrix[3][2] = -P[2];
186 
187  Listener->Params.Velocity[0] = Listener->Velocity[0];
188  Listener->Params.Velocity[1] = Listener->Velocity[1];
189  Listener->Params.Velocity[2] = Listener->Velocity[2];
190  aluMatrixVector(Listener->Params.Velocity, 0.0f, Listener->Params.Matrix);
191 }
192 
193 ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
194 {
195  static const struct ChanMap MonoMap[1] = { { FrontCenter, 0.0f } };
196  static const struct ChanMap StereoMap[2] = {
197  { FrontLeft, -30.0f * F_PI/180.0f },
198  { FrontRight, 30.0f * F_PI/180.0f }
199  };
200  static const struct ChanMap StereoWideMap[2] = {
201  { FrontLeft, -90.0f * F_PI/180.0f },
202  { FrontRight, 90.0f * F_PI/180.0f }
203  };
204  static const struct ChanMap RearMap[2] = {
205  { BackLeft, -150.0f * F_PI/180.0f },
206  { BackRight, 150.0f * F_PI/180.0f }
207  };
208  static const struct ChanMap QuadMap[4] = {
209  { FrontLeft, -45.0f * F_PI/180.0f },
210  { FrontRight, 45.0f * F_PI/180.0f },
211  { BackLeft, -135.0f * F_PI/180.0f },
212  { BackRight, 135.0f * F_PI/180.0f }
213  };
214  static const struct ChanMap X51Map[6] = {
215  { FrontLeft, -30.0f * F_PI/180.0f },
216  { FrontRight, 30.0f * F_PI/180.0f },
217  { FrontCenter, 0.0f * F_PI/180.0f },
218  { LFE, 0.0f },
219  { BackLeft, -110.0f * F_PI/180.0f },
220  { BackRight, 110.0f * F_PI/180.0f }
221  };
222  static const struct ChanMap X61Map[7] = {
223  { FrontLeft, -30.0f * F_PI/180.0f },
224  { FrontRight, 30.0f * F_PI/180.0f },
225  { FrontCenter, 0.0f * F_PI/180.0f },
226  { LFE, 0.0f },
227  { BackCenter, 180.0f * F_PI/180.0f },
228  { SideLeft, -90.0f * F_PI/180.0f },
229  { SideRight, 90.0f * F_PI/180.0f }
230  };
231  static const struct ChanMap X71Map[8] = {
232  { FrontLeft, -30.0f * F_PI/180.0f },
233  { FrontRight, 30.0f * F_PI/180.0f },
234  { FrontCenter, 0.0f * F_PI/180.0f },
235  { LFE, 0.0f },
236  { BackLeft, -150.0f * F_PI/180.0f },
237  { BackRight, 150.0f * F_PI/180.0f },
238  { SideLeft, -90.0f * F_PI/180.0f },
239  { SideRight, 90.0f * F_PI/180.0f }
240  };
241 
242  ALCdevice *Device = ALContext->Device;
243  ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume;
244  ALbufferlistitem *BufferListItem;
245  enum FmtChannels Channels;
246  ALfloat (*SrcMatrix)[MaxChannels];
247  ALfloat DryGain, DryGainHF;
248  ALfloat WetGain[MAX_SENDS];
249  ALfloat WetGainHF[MAX_SENDS];
250  ALint NumSends, Frequency;
251  const struct ChanMap *chans = NULL;
252  enum Resampler Resampler;
253  ALint num_channels = 0;
254  ALboolean DirectChannels;
255  ALfloat hwidth = 0.0f;
256  ALfloat Pitch;
257  ALfloat cw;
258  ALint i, c;
259 
260  /* Get device properties */
261  NumSends = Device->NumAuxSends;
262  Frequency = Device->Frequency;
263 
264  /* Get listener properties */
265  ListenerGain = ALContext->Listener->Gain;
266 
267  /* Get source properties */
268  SourceVolume = ALSource->Gain;
269  MinVolume = ALSource->MinGain;
270  MaxVolume = ALSource->MaxGain;
271  Pitch = ALSource->Pitch;
272  Resampler = ALSource->Resampler;
273  DirectChannels = ALSource->DirectChannels;
274 
275  /* Calculate the stepping value */
276  Channels = FmtMono;
277  BufferListItem = ALSource->queue;
278  while(BufferListItem != NULL)
279  {
280  ALbuffer *ALBuffer;
281  if((ALBuffer=BufferListItem->buffer) != NULL)
282  {
283  ALsizei maxstep = BUFFERSIZE;
284  maxstep -= ResamplerPadding[Resampler] +
286  maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS);
287 
288  Pitch = Pitch * ALBuffer->Frequency / Frequency;
289  if(Pitch > (ALfloat)maxstep)
290  ALSource->Params.Step = maxstep<<FRACTIONBITS;
291  else
292  {
293  ALSource->Params.Step = fastf2i(Pitch*FRACTIONONE);
294  if(ALSource->Params.Step == 0)
295  ALSource->Params.Step = 1;
296  }
297  ALSource->Params.Resample = SelectResampler(Resampler, ALSource->Params.Step);
298 
299  Channels = ALBuffer->FmtChannels;
300  break;
301  }
302  BufferListItem = BufferListItem->next;
303  }
304  if(!DirectChannels && Device->Hrtf)
305  ALSource->Params.DryMix = SelectHrtfMixer();
306  else
307  ALSource->Params.DryMix = SelectDirectMixer();
308  ALSource->Params.WetMix = SelectSendMixer();
309 
310  /* Calculate gains */
311  DryGain = clampf(SourceVolume, MinVolume, MaxVolume);
312  DryGain *= ALSource->DirectGain * ListenerGain;
313  DryGainHF = ALSource->DirectGainHF;
314  for(i = 0;i < NumSends;i++)
315  {
316  WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume);
317  WetGain[i] *= ALSource->Send[i].Gain * ListenerGain;
318  WetGainHF[i] = ALSource->Send[i].GainHF;
319  }
320 
321  SrcMatrix = ALSource->Params.Direct.Gains;
322  for(i = 0;i < MaxChannels;i++)
323  {
324  for(c = 0;c < MaxChannels;c++)
325  SrcMatrix[i][c] = 0.0f;
326  }
327  switch(Channels)
328  {
329  case FmtMono:
330  chans = MonoMap;
331  num_channels = 1;
332  break;
333 
334  case FmtStereo:
335  if(!(Device->Flags&DEVICE_WIDE_STEREO))
336  {
337  /* HACK: Place the stereo channels at +/-90 degrees when using non-
338  * HRTF stereo output. This helps reduce the "monoization" caused
339  * by them panning towards the center. */
340  if(Device->FmtChans == DevFmtStereo && !Device->Hrtf)
341  chans = StereoWideMap;
342  else
343  chans = StereoMap;
344  }
345  else
346  {
347  chans = StereoWideMap;
348  hwidth = 60.0f * F_PI/180.0f;
349  }
350  num_channels = 2;
351  break;
352 
353  case FmtRear:
354  chans = RearMap;
355  num_channels = 2;
356  break;
357 
358  case FmtQuad:
359  chans = QuadMap;
360  num_channels = 4;
361  break;
362 
363  case FmtX51:
364  chans = X51Map;
365  num_channels = 6;
366  break;
367 
368  case FmtX61:
369  chans = X61Map;
370  num_channels = 7;
371  break;
372 
373  case FmtX71:
374  chans = X71Map;
375  num_channels = 8;
376  break;
377  }
378 
379  if(DirectChannels != AL_FALSE)
380  {
381  for(c = 0;c < num_channels;c++)
382  {
383  for(i = 0;i < (ALint)Device->NumChan;i++)
384  {
385  enum Channel chan = Device->Speaker2Chan[i];
386  if(chan == chans[c].channel)
387  {
388  SrcMatrix[c][chan] = DryGain;
389  break;
390  }
391  }
392  }
393  }
394  else if(Device->Hrtf)
395  {
396  for(c = 0;c < num_channels;c++)
397  {
398  if(chans[c].channel == LFE)
399  {
400  /* Skip LFE */
401  ALSource->Params.Direct.Hrtf.Params.Delay[c][0] = 0;
402  ALSource->Params.Direct.Hrtf.Params.Delay[c][1] = 0;
403  for(i = 0;i < HRIR_LENGTH;i++)
404  {
405  ALSource->Params.Direct.Hrtf.Params.Coeffs[c][i][0] = 0.0f;
406  ALSource->Params.Direct.Hrtf.Params.Coeffs[c][i][1] = 0.0f;
407  }
408  }
409  else
410  {
411  /* Get the static HRIR coefficients and delays for this
412  * channel. */
413  GetLerpedHrtfCoeffs(Device->Hrtf,
414  0.0f, chans[c].angle, DryGain,
415  ALSource->Params.Direct.Hrtf.Params.Coeffs[c],
416  ALSource->Params.Direct.Hrtf.Params.Delay[c]);
417  }
418  }
419  ALSource->Hrtf.Counter = 0;
420  ALSource->Params.Direct.Hrtf.Params.IrSize = GetHrtfIrSize(Device->Hrtf);
421 
422  ALSource->Params.Direct.Hrtf.State = &ALSource->Hrtf;
423  }
424  else
425  {
426  DryGain *= lerp(1.0f, 1.0f/sqrtf((float)Device->NumChan), hwidth/F_PI);
427  for(c = 0;c < num_channels;c++)
428  {
429  /* Special-case LFE */
430  if(chans[c].channel == LFE)
431  {
432  SrcMatrix[c][chans[c].channel] = DryGain;
433  continue;
434  }
435  ComputeAngleGains(Device, chans[c].angle, hwidth, DryGain,
436  SrcMatrix[c]);
437  }
438  }
439 
440  ALSource->Params.Direct.OutBuffer = Device->DryBuffer;
441  ALSource->Params.Direct.ClickRemoval = Device->ClickRemoval;
442  ALSource->Params.Direct.PendingClicks = Device->PendingClicks;
443  for(i = 0;i < NumSends;i++)
444  {
445  ALeffectslot *Slot = ALSource->Send[i].Slot;
446 
447  if(!Slot && i == 0)
448  Slot = Device->DefaultSlot;
449  if(Slot && Slot->effect.type == AL_EFFECT_NULL)
450  Slot = NULL;
451  ALSource->Params.Send[i].Slot = Slot;
452  ALSource->Params.Send[i].Gain = WetGain[i];
453  }
454 
455  /* Update filter coefficients. Calculations based on the I3DL2
456  * spec. */
457  cw = cosf(F_PI*2.0f * LOWPASSFREQREF / Frequency);
458 
459  /* We use two chained one-pole filters, so we need to take the
460  * square root of the squared gain, which is the same as the base
461  * gain. */
462  ALSource->Params.Direct.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw);
463  for(i = 0;i < NumSends;i++)
464  {
465  ALfloat a = lpCoeffCalc(WetGainHF[i], cw);
466  ALSource->Params.Send[i].iirFilter.coeff = a;
467  }
468 }
469 
470 ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
471 {
472  ALCdevice *Device = ALContext->Device;
473  ALfloat Velocity[3],Direction[3],Position[3],SourceToListener[3];
474  ALfloat InnerAngle,OuterAngle,Angle,Distance,ClampedDist;
475  ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
476  ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain;
477  ALfloat DopplerFactor, SpeedOfSound;
478  ALfloat AirAbsorptionFactor;
479  ALfloat RoomAirAbsorption[MAX_SENDS];
480  ALbufferlistitem *BufferListItem;
481  ALfloat Attenuation;
482  ALfloat RoomAttenuation[MAX_SENDS];
483  ALfloat MetersPerUnit;
484  ALfloat RoomRolloffBase;
485  ALfloat RoomRolloff[MAX_SENDS];
486  ALfloat DecayDistance[MAX_SENDS];
487  ALfloat DryGain;
488  ALfloat DryGainHF;
489  ALboolean DryGainHFAuto;
490  ALfloat WetGain[MAX_SENDS];
491  ALfloat WetGainHF[MAX_SENDS];
492  ALboolean WetGainAuto;
493  ALboolean WetGainHFAuto;
494  enum Resampler Resampler;
495  ALfloat Pitch;
496  ALuint Frequency;
497  ALint NumSends;
498  ALfloat cw;
499  ALint i, j;
500 
501  DryGainHF = 1.0f;
502  for(i = 0;i < MAX_SENDS;i++)
503  WetGainHF[i] = 1.0f;
504 
505  /* Get context/device properties */
506  DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
507  SpeedOfSound = ALContext->SpeedOfSound * ALContext->DopplerVelocity;
508  NumSends = Device->NumAuxSends;
509  Frequency = Device->Frequency;
510 
511  /* Get listener properties */
512  ListenerGain = ALContext->Listener->Gain;
513  MetersPerUnit = ALContext->Listener->MetersPerUnit;
514 
515  /* Get source properties */
516  SourceVolume = ALSource->Gain;
517  MinVolume = ALSource->MinGain;
518  MaxVolume = ALSource->MaxGain;
519  Pitch = ALSource->Pitch;
520  Resampler = ALSource->Resampler;
521  Position[0] = ALSource->Position[0];
522  Position[1] = ALSource->Position[1];
523  Position[2] = ALSource->Position[2];
524  Direction[0] = ALSource->Orientation[0];
525  Direction[1] = ALSource->Orientation[1];
526  Direction[2] = ALSource->Orientation[2];
527  Velocity[0] = ALSource->Velocity[0];
528  Velocity[1] = ALSource->Velocity[1];
529  Velocity[2] = ALSource->Velocity[2];
530  MinDist = ALSource->RefDistance;
531  MaxDist = ALSource->MaxDistance;
532  Rolloff = ALSource->RollOffFactor;
533  InnerAngle = ALSource->InnerAngle;
534  OuterAngle = ALSource->OuterAngle;
535  AirAbsorptionFactor = ALSource->AirAbsorptionFactor;
536  DryGainHFAuto = ALSource->DryGainHFAuto;
537  WetGainAuto = ALSource->WetGainAuto;
538  WetGainHFAuto = ALSource->WetGainHFAuto;
539  RoomRolloffBase = ALSource->RoomRolloffFactor;
540 
541  ALSource->Params.Direct.OutBuffer = Device->DryBuffer;
542  ALSource->Params.Direct.ClickRemoval = Device->ClickRemoval;
543  ALSource->Params.Direct.PendingClicks = Device->PendingClicks;
544  for(i = 0;i < NumSends;i++)
545  {
546  ALeffectslot *Slot = ALSource->Send[i].Slot;
547 
548  if(!Slot && i == 0)
549  Slot = Device->DefaultSlot;
550  if(!Slot || Slot->effect.type == AL_EFFECT_NULL)
551  {
552  Slot = NULL;
553  RoomRolloff[i] = 0.0f;
554  DecayDistance[i] = 0.0f;
555  RoomAirAbsorption[i] = 1.0f;
556  }
557  else if(Slot->AuxSendAuto)
558  {
559  RoomRolloff[i] = RoomRolloffBase;
560  if(IsReverbEffect(Slot->effect.type))
561  {
562  RoomRolloff[i] += Slot->effect.Reverb.RoomRolloffFactor;
563  DecayDistance[i] = Slot->effect.Reverb.DecayTime *
565  RoomAirAbsorption[i] = Slot->effect.Reverb.AirAbsorptionGainHF;
566  }
567  else
568  {
569  DecayDistance[i] = 0.0f;
570  RoomAirAbsorption[i] = 1.0f;
571  }
572  }
573  else
574  {
575  /* If the slot's auxiliary send auto is off, the data sent to the
576  * effect slot is the same as the dry path, sans filter effects */
577  RoomRolloff[i] = Rolloff;
578  DecayDistance[i] = 0.0f;
579  RoomAirAbsorption[i] = AIRABSORBGAINHF;
580  }
581 
582  ALSource->Params.Send[i].Slot = Slot;
583  }
584 
585  /* Transform source to listener space (convert to head relative) */
586  if(ALSource->HeadRelative == AL_FALSE)
587  {
588  ALfloat (*RESTRICT Matrix)[4] = ALContext->Listener->Params.Matrix;
589  /* Transform source vectors */
590  aluMatrixVector(Position, 1.0f, Matrix);
591  aluMatrixVector(Direction, 0.0f, Matrix);
592  aluMatrixVector(Velocity, 0.0f, Matrix);
593  }
594  else
595  {
596  const ALfloat *ListenerVel = ALContext->Listener->Params.Velocity;
597  /* Offset the source velocity to be relative of the listener velocity */
598  Velocity[0] += ListenerVel[0];
599  Velocity[1] += ListenerVel[1];
600  Velocity[2] += ListenerVel[2];
601  }
602 
603  SourceToListener[0] = -Position[0];
604  SourceToListener[1] = -Position[1];
605  SourceToListener[2] = -Position[2];
606  aluNormalize(SourceToListener);
607  aluNormalize(Direction);
608 
609  /* Calculate distance attenuation */
610  Distance = sqrtf(aluDotproduct(Position, Position));
611  ClampedDist = Distance;
612 
613  Attenuation = 1.0f;
614  for(i = 0;i < NumSends;i++)
615  RoomAttenuation[i] = 1.0f;
616  switch(ALContext->SourceDistanceModel ? ALSource->DistanceModel :
617  ALContext->DistanceModel)
618  {
620  ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
621  if(MaxDist < MinDist)
622  break;
623  /*fall-through*/
624  case InverseDistance:
625  if(MinDist > 0.0f)
626  {
627  if((MinDist + (Rolloff * (ClampedDist - MinDist))) > 0.0f)
628  Attenuation = MinDist / (MinDist + (Rolloff * (ClampedDist - MinDist)));
629  for(i = 0;i < NumSends;i++)
630  {
631  if((MinDist + (RoomRolloff[i] * (ClampedDist - MinDist))) > 0.0f)
632  RoomAttenuation[i] = MinDist / (MinDist + (RoomRolloff[i] * (ClampedDist - MinDist)));
633  }
634  }
635  break;
636 
638  ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
639  if(MaxDist < MinDist)
640  break;
641  /*fall-through*/
642  case LinearDistance:
643  if(MaxDist != MinDist)
644  {
645  Attenuation = 1.0f - (Rolloff*(ClampedDist-MinDist)/(MaxDist - MinDist));
646  Attenuation = maxf(Attenuation, 0.0f);
647  for(i = 0;i < NumSends;i++)
648  {
649  RoomAttenuation[i] = 1.0f - (RoomRolloff[i]*(ClampedDist-MinDist)/(MaxDist - MinDist));
650  RoomAttenuation[i] = maxf(RoomAttenuation[i], 0.0f);
651  }
652  }
653  break;
654 
656  ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
657  if(MaxDist < MinDist)
658  break;
659  /*fall-through*/
660  case ExponentDistance:
661  if(ClampedDist > 0.0f && MinDist > 0.0f)
662  {
663  Attenuation = powf(ClampedDist/MinDist, -Rolloff);
664  for(i = 0;i < NumSends;i++)
665  RoomAttenuation[i] = powf(ClampedDist/MinDist, -RoomRolloff[i]);
666  }
667  break;
668 
669  case DisableDistance:
670  ClampedDist = MinDist;
671  break;
672  }
673 
674  /* Source Gain + Attenuation */
675  DryGain = SourceVolume * Attenuation;
676  for(i = 0;i < NumSends;i++)
677  WetGain[i] = SourceVolume * RoomAttenuation[i];
678 
679  /* Distance-based air absorption */
680  if(AirAbsorptionFactor > 0.0f && ClampedDist > MinDist)
681  {
682  ALfloat meters = maxf(ClampedDist-MinDist, 0.0f) * MetersPerUnit;
683  DryGainHF *= powf(AIRABSORBGAINHF, AirAbsorptionFactor*meters);
684  for(i = 0;i < NumSends;i++)
685  WetGainHF[i] *= powf(RoomAirAbsorption[i], AirAbsorptionFactor*meters);
686  }
687 
688  if(WetGainAuto)
689  {
690  ALfloat ApparentDist = 1.0f/maxf(Attenuation, 0.00001f) - 1.0f;
691 
692  /* Apply a decay-time transformation to the wet path, based on the
693  * attenuation of the dry path.
694  *
695  * Using the apparent distance, based on the distance attenuation, the
696  * initial decay of the reverb effect is calculated and applied to the
697  * wet path.
698  */
699  for(i = 0;i < NumSends;i++)
700  {
701  if(DecayDistance[i] > 0.0f)
702  WetGain[i] *= powf(0.001f/*-60dB*/, ApparentDist/DecayDistance[i]);
703  }
704  }
705 
706  /* Calculate directional soundcones */
707  Angle = acosf(aluDotproduct(Direction,SourceToListener)) * ConeScale * (360.0f/F_PI);
708  if(Angle > InnerAngle && Angle <= OuterAngle)
709  {
710  ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
711  ConeVolume = lerp(1.0f, ALSource->OuterGain, scale);
712  ConeHF = lerp(1.0f, ALSource->OuterGainHF, scale);
713  }
714  else if(Angle > OuterAngle)
715  {
716  ConeVolume = ALSource->OuterGain;
717  ConeHF = ALSource->OuterGainHF;
718  }
719  else
720  {
721  ConeVolume = 1.0f;
722  ConeHF = 1.0f;
723  }
724 
725  DryGain *= ConeVolume;
726  if(WetGainAuto)
727  {
728  for(i = 0;i < NumSends;i++)
729  WetGain[i] *= ConeVolume;
730  }
731  if(DryGainHFAuto)
732  DryGainHF *= ConeHF;
733  if(WetGainHFAuto)
734  {
735  for(i = 0;i < NumSends;i++)
736  WetGainHF[i] *= ConeHF;
737  }
738 
739  /* Clamp to Min/Max Gain */
740  DryGain = clampf(DryGain, MinVolume, MaxVolume);
741  for(i = 0;i < NumSends;i++)
742  WetGain[i] = clampf(WetGain[i], MinVolume, MaxVolume);
743 
744  /* Apply gain and frequency filters */
745  DryGain *= ALSource->DirectGain * ListenerGain;
746  DryGainHF *= ALSource->DirectGainHF;
747  for(i = 0;i < NumSends;i++)
748  {
749  WetGain[i] *= ALSource->Send[i].Gain * ListenerGain;
750  WetGainHF[i] *= ALSource->Send[i].GainHF;
751  }
752 
753  /* Calculate velocity-based doppler effect */
754  if(DopplerFactor > 0.0f)
755  {
756  const ALfloat *ListenerVel = ALContext->Listener->Params.Velocity;
757  ALfloat VSS, VLS;
758 
759  if(SpeedOfSound < 1.0f)
760  {
761  DopplerFactor *= 1.0f/SpeedOfSound;
762  SpeedOfSound = 1.0f;
763  }
764 
765  VSS = aluDotproduct(Velocity, SourceToListener) * DopplerFactor;
766  VLS = aluDotproduct(ListenerVel, SourceToListener) * DopplerFactor;
767 
768  Pitch *= clampf(SpeedOfSound-VLS, 1.0f, SpeedOfSound*2.0f - 1.0f) /
769  clampf(SpeedOfSound-VSS, 1.0f, SpeedOfSound*2.0f - 1.0f);
770  }
771 
772  BufferListItem = ALSource->queue;
773  while(BufferListItem != NULL)
774  {
775  ALbuffer *ALBuffer;
776  if((ALBuffer=BufferListItem->buffer) != NULL)
777  {
778  /* Calculate fixed-point stepping value, based on the pitch, buffer
779  * frequency, and output frequency. */
780  ALsizei maxstep = BUFFERSIZE;
781  maxstep -= ResamplerPadding[Resampler] +
783  maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS);
784 
785  Pitch = Pitch * ALBuffer->Frequency / Frequency;
786  if(Pitch > (ALfloat)maxstep)
787  ALSource->Params.Step = maxstep<<FRACTIONBITS;
788  else
789  {
790  ALSource->Params.Step = fastf2i(Pitch*FRACTIONONE);
791  if(ALSource->Params.Step == 0)
792  ALSource->Params.Step = 1;
793  }
794  ALSource->Params.Resample = SelectResampler(Resampler, ALSource->Params.Step);
795 
796  break;
797  }
798  BufferListItem = BufferListItem->next;
799  }
800  if(Device->Hrtf)
801  ALSource->Params.DryMix = SelectHrtfMixer();
802  else
803  ALSource->Params.DryMix = SelectDirectMixer();
804  ALSource->Params.WetMix = SelectSendMixer();
805 
806  if(Device->Hrtf)
807  {
808  /* Use a binaural HRTF algorithm for stereo headphone playback */
809  ALfloat delta, ev = 0.0f, az = 0.0f;
810 
811  if(Distance > FLT_EPSILON)
812  {
813  ALfloat invlen = 1.0f/Distance;
814  Position[0] *= invlen;
815  Position[1] *= invlen;
816  Position[2] *= invlen;
817 
818  /* Calculate elevation and azimuth only when the source is not at
819  * the listener. This prevents +0 and -0 Z from producing
820  * inconsistent panning. Also, clamp Y in case FP precision errors
821  * cause it to land outside of -1..+1. */
822  ev = asinf(clampf(Position[1], -1.0f, 1.0f));
823  az = atan2f(Position[0], -Position[2]*ZScale);
824  }
825 
826  /* Check to see if the HRIR is already moving. */
827  if(ALSource->Hrtf.Moving)
828  {
829  /* Calculate the normalized HRTF transition factor (delta). */
830  delta = CalcHrtfDelta(ALSource->Params.Direct.Hrtf.Params.Gain, DryGain,
831  ALSource->Params.Direct.Hrtf.Params.Dir, Position);
832  /* If the delta is large enough, get the moving HRIR target
833  * coefficients, target delays, steppping values, and counter. */
834  if(delta > 0.001f)
835  {
836  ALSource->Hrtf.Counter = GetMovingHrtfCoeffs(Device->Hrtf,
837  ev, az, DryGain, delta,
838  ALSource->Hrtf.Counter,
839  ALSource->Params.Direct.Hrtf.Params.Coeffs[0],
840  ALSource->Params.Direct.Hrtf.Params.Delay[0],
841  ALSource->Params.Direct.Hrtf.Params.CoeffStep,
842  ALSource->Params.Direct.Hrtf.Params.DelayStep);
843  ALSource->Params.Direct.Hrtf.Params.Gain = DryGain;
844  ALSource->Params.Direct.Hrtf.Params.Dir[0] = Position[0];
845  ALSource->Params.Direct.Hrtf.Params.Dir[1] = Position[1];
846  ALSource->Params.Direct.Hrtf.Params.Dir[2] = Position[2];
847  }
848  }
849  else
850  {
851  /* Get the initial (static) HRIR coefficients and delays. */
852  GetLerpedHrtfCoeffs(Device->Hrtf, ev, az, DryGain,
853  ALSource->Params.Direct.Hrtf.Params.Coeffs[0],
854  ALSource->Params.Direct.Hrtf.Params.Delay[0]);
855  ALSource->Hrtf.Counter = 0;
856  ALSource->Hrtf.Moving = AL_TRUE;
857  ALSource->Params.Direct.Hrtf.Params.Gain = DryGain;
858  ALSource->Params.Direct.Hrtf.Params.Dir[0] = Position[0];
859  ALSource->Params.Direct.Hrtf.Params.Dir[1] = Position[1];
860  ALSource->Params.Direct.Hrtf.Params.Dir[2] = Position[2];
861  }
862  ALSource->Params.Direct.Hrtf.Params.IrSize = GetHrtfIrSize(Device->Hrtf);
863 
864  ALSource->Params.Direct.Hrtf.State = &ALSource->Hrtf;
865  }
866  else
867  {
868  ALfloat (*Matrix)[MaxChannels] = ALSource->Params.Direct.Gains;
869  ALfloat DirGain = 0.0f;
870  ALfloat AmbientGain;
871 
872  for(i = 0;i < MaxChannels;i++)
873  {
874  for(j = 0;j < MaxChannels;j++)
875  Matrix[i][j] = 0.0f;
876  }
877 
878  /* Normalize the length, and compute panned gains. */
879  if(Distance > FLT_EPSILON)
880  {
881  ALfloat invlen = 1.0f/Distance;
882  Position[0] *= invlen;
883  Position[1] *= invlen;
884  Position[2] *= invlen;
885 
886  DirGain = sqrtf(Position[0]*Position[0] + Position[2]*Position[2]);
887  ComputeAngleGains(Device, atan2f(Position[0], -Position[2]*ZScale), 0.0f,
888  DryGain*DirGain, Matrix[0]);
889  }
890 
891  /* Adjustment for vertical offsets. Not the greatest, but simple
892  * enough. */
893  AmbientGain = DryGain * sqrtf(1.0f/Device->NumChan) * (1.0f-DirGain);
894  for(i = 0;i < (ALint)Device->NumChan;i++)
895  {
896  enum Channel chan = Device->Speaker2Chan[i];
897  Matrix[0][chan] = maxf(Matrix[0][chan], AmbientGain);
898  }
899  }
900  for(i = 0;i < NumSends;i++)
901  ALSource->Params.Send[i].Gain = WetGain[i];
902 
903  /* Update filter coefficients. */
904  cw = cosf(F_PI*2.0f * LOWPASSFREQREF / Frequency);
905 
906  ALSource->Params.Direct.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw);
907  for(i = 0;i < NumSends;i++)
908  {
909  ALfloat a = lpCoeffCalc(WetGainHF[i], cw);
910  ALSource->Params.Send[i].iirFilter.coeff = a;
911  }
912 }
913 
914 
915 static __inline ALfloat aluF2F(ALfloat val)
916 { return val; }
917 static __inline ALint aluF2I(ALfloat val)
918 {
919  /* Clamp the value between -1 and +1. This handles that without branching. */
920  val = val+1.0f - fabsf(val-1.0f);
921  val = (val-2.0f + fabsf(val+2.0f)) * 0.25f;
922  /* Convert to a signed integer, between -2147483647 and +2147483647. */
923  return fastf2i((ALfloat)(val*2147483647.0));
924 }
925 static __inline ALuint aluF2UI(ALfloat val)
926 { return aluF2I(val)+2147483648u; }
927 static __inline ALshort aluF2S(ALfloat val)
928 { return aluF2I(val)>>16; }
929 static __inline ALushort aluF2US(ALfloat val)
930 { return aluF2S(val)+32768; }
931 static __inline ALbyte aluF2B(ALfloat val)
932 { return aluF2I(val)>>24; }
933 static __inline ALubyte aluF2UB(ALfloat val)
934 { return aluF2B(val)+128; }
935 
936 #define DECL_TEMPLATE(T, func) \
937 static int Write_##T(ALCdevice *device, T *RESTRICT buffer, \
938  ALuint SamplesToDo) \
939 { \
940  ALfloat (*RESTRICT DryBuffer)[BUFFERSIZE] = device->DryBuffer; \
941  ALuint numchans = ChannelsFromDevFmt(device->FmtChans); \
942  const ALuint *offsets = device->ChannelOffsets; \
943  ALuint i, j; \
944  \
945  for(j = 0;j < MaxChannels;j++) \
946  { \
947  T *RESTRICT out; \
948  \
949  if(offsets[j] == INVALID_OFFSET) \
950  continue; \
951  \
952  out = buffer + offsets[j]; \
953  for(i = 0;i < SamplesToDo;i++) \
954  out[i*numchans] = func(DryBuffer[j][i]); \
955  } \
956  return SamplesToDo*numchans*sizeof(T); \
957 }
958 
966 
967 #undef DECL_TEMPLATE
968 
969 
971 {
972  ALuint SamplesToDo;
973  ALeffectslot **slot, **slot_end;
974  ALsource **src, **src_end;
975  ALCcontext *ctx;
976  FPUCtl oldMode;
977  ALuint i, c;
978 
979  SetMixerFPUMode(&oldMode);
980 
981  while(size > 0)
982  {
983  SamplesToDo = minu(size, BUFFERSIZE);
984  for(c = 0;c < MaxChannels;c++)
985  memset(device->DryBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
986 
987  ALCdevice_Lock(device);
988  ctx = device->ContextList;
989  while(ctx)
990  {
991  ALenum DeferUpdates = ctx->DeferUpdates;
992  ALenum UpdateSources = AL_FALSE;
993 
994  if(!DeferUpdates)
995  UpdateSources = ExchangeInt(&ctx->UpdateSources, AL_FALSE);
996 
997  if(UpdateSources)
999 
1000  /* source processing */
1001  src = ctx->ActiveSources;
1002  src_end = src + ctx->ActiveSourceCount;
1003  while(src != src_end)
1004  {
1005  if((*src)->state != AL_PLAYING)
1006  {
1007  --(ctx->ActiveSourceCount);
1008  *src = *(--src_end);
1009  continue;
1010  }
1011 
1012  if(!DeferUpdates && (ExchangeInt(&(*src)->NeedsUpdate, AL_FALSE) ||
1013  UpdateSources))
1014  ALsource_Update(*src, ctx);
1015 
1016  MixSource(*src, device, SamplesToDo);
1017  src++;
1018  }
1019 
1020  /* effect slot processing */
1021  slot = ctx->ActiveEffectSlots;
1022  slot_end = slot + ctx->ActiveEffectSlotCount;
1023  while(slot != slot_end)
1024  {
1025  ALfloat offset = (*slot)->ClickRemoval[0];
1026  if(offset < (1.0f/32768.0f))
1027  offset = 0.0f;
1028  else for(i = 0;i < SamplesToDo;i++)
1029  {
1030  (*slot)->WetBuffer[0][i] += offset;
1031  offset -= offset * (1.0f/256.0f);
1032  }
1033  (*slot)->ClickRemoval[0] = offset + (*slot)->PendingClicks[0];
1034  (*slot)->PendingClicks[0] = 0.0f;
1035 
1036  if(!DeferUpdates && ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
1037  ALeffectState_Update((*slot)->EffectState, device, *slot);
1038 
1039  ALeffectState_Process((*slot)->EffectState, SamplesToDo,
1040  (*slot)->WetBuffer[0], device->DryBuffer);
1041 
1042  for(i = 0;i < SamplesToDo;i++)
1043  (*slot)->WetBuffer[0][i] = 0.0f;
1044 
1045  slot++;
1046  }
1047 
1048  ctx = ctx->next;
1049  }
1050 
1051  slot = &device->DefaultSlot;
1052  if(*slot != NULL)
1053  {
1054  ALfloat offset = (*slot)->ClickRemoval[0];
1055  if(offset < (1.0f/32768.0f))
1056  offset = 0.0f;
1057  else for(i = 0;i < SamplesToDo;i++)
1058  {
1059  (*slot)->WetBuffer[0][i] += offset;
1060  offset -= offset * (1.0f/256.0f);
1061  }
1062  (*slot)->ClickRemoval[0] = offset + (*slot)->PendingClicks[0];
1063  (*slot)->PendingClicks[0] = 0.0f;
1064 
1065  if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
1066  ALeffectState_Update((*slot)->EffectState, device, *slot);
1067 
1068  ALeffectState_Process((*slot)->EffectState, SamplesToDo,
1069  (*slot)->WetBuffer[0], device->DryBuffer);
1070 
1071  for(i = 0;i < SamplesToDo;i++)
1072  (*slot)->WetBuffer[0][i] = 0.0f;
1073  }
1074  ALCdevice_Unlock(device);
1075 
1076  /* Click-removal. Could do better; this only really handles immediate
1077  * changes between updates where a predictive sample could be
1078  * generated. Delays caused by effects and HRTF aren't caught. */
1079  if(device->FmtChans == DevFmtMono)
1080  {
1081  ALfloat offset = device->ClickRemoval[FrontCenter];
1082  if(offset < (1.0f/32768.0f))
1083  offset = 0.0f;
1084  else for(i = 0;i < SamplesToDo;i++)
1085  {
1086  device->DryBuffer[FrontCenter][i] += offset;
1087  offset -= offset * (1.0f/256.0f);
1088  }
1089  device->ClickRemoval[FrontCenter] = offset + device->PendingClicks[FrontCenter];
1090  device->PendingClicks[FrontCenter] = 0.0f;
1091  }
1092  else if(device->FmtChans == DevFmtStereo)
1093  {
1094  /* Assumes the first two channels are FrontLeft and FrontRight */
1095  for(c = 0;c < 2;c++)
1096  {
1097  ALfloat offset = device->ClickRemoval[c];
1098  if(offset < (1.0f/32768.0f))
1099  offset = 0.0f;
1100  else for(i = 0;i < SamplesToDo;i++)
1101  {
1102  device->DryBuffer[c][i] += offset;
1103  offset -= offset * (1.0f/256.0f);
1104  }
1105  device->ClickRemoval[c] = offset + device->PendingClicks[c];
1106  device->PendingClicks[c] = 0.0f;
1107  }
1108  if(device->Bs2b)
1109  {
1110  float samples[2];
1111  for(i = 0;i < SamplesToDo;i++)
1112  {
1113  samples[0] = device->DryBuffer[FrontLeft][i];
1114  samples[1] = device->DryBuffer[FrontRight][i];
1115  bs2b_cross_feed(device->Bs2b, samples);
1116  device->DryBuffer[FrontLeft][i] = samples[0];
1117  device->DryBuffer[FrontRight][i] = samples[1];
1118  }
1119  }
1120  }
1121  else
1122  {
1123  for(c = 0;c < MaxChannels;c++)
1124  {
1125  ALfloat offset = device->ClickRemoval[c];
1126  if(offset < (1.0f/32768.0f))
1127  offset = 0.0f;
1128  else for(i = 0;i < SamplesToDo;i++)
1129  {
1130  device->DryBuffer[c][i] += offset;
1131  offset -= offset * (1.0f/256.0f);
1132  }
1133  device->ClickRemoval[c] = offset + device->PendingClicks[c];
1134  device->PendingClicks[c] = 0.0f;
1135  }
1136  }
1137 
1138  if(buffer)
1139  {
1140  int bytes = 0;
1141  switch(device->FmtType)
1142  {
1143  case DevFmtByte:
1144  bytes = Write_ALbyte(device, buffer, SamplesToDo);
1145  break;
1146  case DevFmtUByte:
1147  bytes = Write_ALubyte(device, buffer, SamplesToDo);
1148  break;
1149  case DevFmtShort:
1150  bytes = Write_ALshort(device, buffer, SamplesToDo);
1151  break;
1152  case DevFmtUShort:
1153  bytes = Write_ALushort(device, buffer, SamplesToDo);
1154  break;
1155  case DevFmtInt:
1156  bytes = Write_ALint(device, buffer, SamplesToDo);
1157  break;
1158  case DevFmtUInt:
1159  bytes = Write_ALuint(device, buffer, SamplesToDo);
1160  break;
1161  case DevFmtFloat:
1162  bytes = Write_ALfloat(device, buffer, SamplesToDo);
1163  break;
1164  }
1165 
1166  buffer = (ALubyte*)buffer + bytes;
1167  }
1168 
1169  size -= SamplesToDo;
1170  }
1171 
1172  RestoreFPUMode(&oldMode);
1173 }
1174 
1175 
1177 {
1178  ALCcontext *Context;
1179 
1180  device->Connected = ALC_FALSE;
1181 
1182  Context = device->ContextList;
1183  while(Context)
1184  {
1185  ALsource **src, **src_end;
1186 
1187  src = Context->ActiveSources;
1188  src_end = src + Context->ActiveSourceCount;
1189  while(src != src_end)
1190  {
1191  if((*src)->state == AL_PLAYING)
1192  {
1193  (*src)->state = AL_STOPPED;
1194  (*src)->BuffersPlayed = (*src)->BuffersInQueue;
1195  (*src)->position = 0;
1196  (*src)->position_fraction = 0;
1197  }
1198  src++;
1199  }
1200  Context->ActiveSourceCount = 0;
1201 
1202  Context = Context->next;
1203  }
1204 }
static WetMixerFunc SelectSendMixer(void)
Definition: ALu.c:97
ALfloat(* OutBuffer)[BUFFERSIZE]
Definition: alSource.h:50
enum DistanceModel DistanceModel
Definition: alMain.h:688
struct ALeffectslot * Slot
Definition: alSource.h:150
volatile ALenum UpdateSources
Definition: alMain.h:686
ALvoid(* WetMixerFunc)(const struct SendParams *params, const ALfloat *RESTRICT data, ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
Definition: alu.h:40
unsigned char ALubyte
Definition: al.h:47
volatile ALfloat DopplerFactor
Definition: alMain.h:691
volatile ALboolean WetGainHFAuto
Definition: alSource.h:105
struct ALlistener * Listener
Definition: alMain.h:679
void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat(*coeffs)[2], ALuint *delays)
Definition: hrtf.c:140
ALfloat coeff
Definition: alFilter.h:13
ALCboolean Connected
Definition: alMain.h:564
GLuint const GLfloat * val
Definition: glew.h:2715
#define F_PI
Definition: alu.h:16
void ALvoid
Definition: al.h:74
ALuint IrSize
Definition: alSource.h:46
static __inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
Definition: ALu.c:108
struct ALeffect::@52 Reverb
#define AL_STOPPED
Definition: al.h:241
#define ALeffectState_Process(a, b, c, d)
void MixDirect_SSE(const struct DirectParams *, const ALfloat *RESTRICT, ALuint, ALuint, ALuint, ALuint)
#define ALeffectState_Update(a, b, c)
Definition: alMain.h:484
struct Hrtf * Hrtf
Definition: alMain.h:598
ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat(*coeffs)[2], ALuint *delays, ALfloat(*coeffStep)[2], ALint *delayStep)
Definition: hrtf.c:232
#define AL_TRUE
Definition: al.h:86
enum FmtChannels FmtChannels
Definition: alBuffer.h:77
struct ALeffectslot * DefaultSlot
Definition: alMain.h:624
volatile ALfloat DopplerFactor
Definition: alSource.h:110
#define SPEEDOFSOUNDMETRESPERSEC
Definition: alu.h:46
#define NULL
Definition: ftobjs.h:61
ALsizei ActiveEffectSlotCount
Definition: alMain.h:701
static __inline ALboolean IsReverbEffect(ALenum type)
Definition: alEffect.h:102
struct ALsource ** ActiveSources
Definition: alMain.h:696
GLclampf f
Definition: glew.h:3390
volatile ALfloat MetersPerUnit
Definition: alListener.h:16
#define ALsource_Update(s, a)
Definition: alSource.h:179
static __inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
Definition: alu.h:90
GLdouble angle
Definition: glew.h:8396
ALfloat ConeScale
Definition: ALu.c:46
volatile ALfloat Pitch
Definition: alSource.h:85
ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
Definition: alFilter.c:329
volatile ALfloat SpeedOfSound
Definition: alMain.h:693
const ALsizei ResamplerPadding[ResamplerMax]
Definition: alSource.c:38
ALuint NumAuxSends
Definition: alMain.h:586
static __inline ALfloat aluDotproduct(const ALfloat *inVector1, const ALfloat *inVector2)
Definition: ALu.c:115
static __inline ALubyte aluF2UB(ALfloat val)
Definition: ALu.c:933
int ALsizei
Definition: al.h:62
ALuint Frequency
Definition: alMain.h:569
#define FLT_EPSILON
Definition: alu.h:20
ALvoid(* DryMixerFunc)(const struct DirectParams *params, const ALfloat *RESTRICT data, ALuint srcchan, ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
Definition: alu.h:36
int ALint
Definition: al.h:56
int32_t j
Definition: e_log.c:102
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
Definition: ALu.c:970
#define memset
Definition: SDL_malloc.c:633
#define AL_FALSE
Definition: al.h:83
ALuint GetHrtfIrSize(const struct Hrtf *Hrtf)
Definition: hrtf.c:801
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
#define FRACTIONONE
Definition: alu.h:50
ALsizei Frequency
Definition: alBuffer.h:73
static DryMixerFunc SelectHrtfMixer(void)
Definition: ALu.c:73
short ALshort
Definition: al.h:50
void MixDirect_Hrtf_Neon(const struct DirectParams *, const ALfloat *RESTRICT, ALuint, ALuint, ALuint, ALuint)
volatile ALfloat Position[3]
Definition: alSource.h:95
ALint DelayStep[2]
Definition: alSource.h:45
void MixSend_SSE(const struct SendParams *, const ALfloat *RESTRICT, ALuint, ALuint, ALuint)
volatile ALfloat OuterGainHF
Definition: alSource.h:106
ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3])
Definition: hrtf.c:106
ALuint Flags
Definition: alMain.h:605
void RestoreFPUMode(const FPUCtl *ctl)
Definition: helpers.c:235
struct bs2b * Bs2b
Definition: alMain.h:601
static __inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
Definition: alu.h:58
ALuint Delay[MaxChannels][2]
Definition: alSource.h:44
void SetMixerFPUMode(FPUCtl *ctl)
Definition: helpers.c:193
ALsizei ActiveSourceCount
Definition: alMain.h:697
static __inline ALfloat maxf(ALfloat a, ALfloat b)
Definition: alu.h:56
#define HRIR_LENGTH
Definition: alMain.h:776
float ALfloat
Definition: al.h:68
static __inline ALushort aluF2US(ALfloat val)
Definition: ALu.c:929
ALvoid aluHandleDisconnect(ALCdevice *device)
Definition: ALu.c:1176
DryMixerFunc DryMix
Definition: alSource.h:161
signed char ALbyte
Definition: al.h:44
volatile ALfloat Position[3]
Definition: alListener.h:11
volatile ALfloat MinGain
Definition: alSource.h:88
FILTER iirFilter
Definition: alSource.h:65
static __inline ALvoid aluMatrixVector(ALfloat *vector, ALfloat w, ALfloat(*RESTRICT matrix)[4])
Definition: ALu.c:133
ALint Step
Definition: alSource.h:164
#define ALCdevice_Unlock(a)
Definition: alMain.h:647
ALfloat AirAbsorptionGainHF
Definition: alEffect.h:41
volatile ALfloat RoomRolloffFactor
Definition: alSource.h:109
static __inline ALshort aluF2S(ALfloat val)
Definition: ALu.c:927
void Resample_point32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *RESTRICT dst, ALuint dstlen)
EGLContext EGLenum EGLClientBuffer buffer
Definition: eglext.h:87
static __inline ALfloat aluF2F(ALfloat val)
Definition: ALu.c:915
volatile ALfloat AirAbsorptionFactor
Definition: alSource.h:108
#define ALC_FALSE
Definition: alc.h:81
volatile ALfloat Velocity[3]
Definition: alSource.h:96
ALuint NumChan
Definition: alMain.h:611
enum Resampler Resampler
Definition: alSource.h:112
ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
Definition: ALu.c:470
ALuint u
Definition: alMain.h:58
ALfloat DirectGainHF
Definition: alSource.h:147
enum Channel Speaker2Chan[MaxChannels]
Definition: alMain.h:609
volatile ALfloat RefDistance
Definition: alSource.h:92
ALeffect effect
ALfloat DirectGain
Definition: alSource.h:146
#define AL_PLAYING
Definition: al.h:239
struct ALlistener::@56 Params
ALfloat GainHF
Definition: alSource.h:152
volatile ALboolean HeadRelative
Definition: alSource.h:98
volatile ALfloat OuterAngle
Definition: alSource.h:91
volatile ALfloat MaxDistance
Definition: alSource.h:93
unsigned short ALushort
Definition: al.h:53
static __inline ALuint aluF2UI(ALfloat val)
Definition: ALu.c:925
ALfloat RoomRolloffFactor
Definition: alEffect.h:42
ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
Definition: mixer.c:97
WetMixerFunc WetMix
Definition: alSource.h:162
#define MAX_SENDS
Definition: alSource.h:4
const ALsizei ResamplerPrePadding[ResamplerMax]
Definition: alSource.c:43
GLsizei samples
Definition: gl2ext.h:970
const GLfloat * c
Definition: glew.h:14913
volatile ALboolean DryGainHFAuto
Definition: alSource.h:103
static ALvoid CalcListenerParams(ALlistener *Listener)
Definition: ALu.c:145
void MixDirect_Hrtf_SSE(const struct DirectParams *, const ALfloat *RESTRICT, ALuint, ALuint, ALuint, ALuint)
HrtfParams Params
Definition: alSource.h:55
volatile ALboolean SourceDistanceModel
Definition: alMain.h:689
ALvoid ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat *gains)
Definition: panning.c:149
ResamplerFunc Resample
Definition: alSource.h:160
int ALenum
Definition: al.h:65
volatile ALenum DeferUpdates
Definition: alMain.h:694
#define AL_EFFECT_NULL
Definition: efx.h:154
void Resample_cubic32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *RESTRICT dst, ALuint dstlen)
volatile ALfloat Up[3]
Definition: alListener.h:14
void MixSend_C(const SendParams *params, const ALfloat *RESTRICT data, ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
Definition: mixer_c.c:112
ALfloat Gains[MaxChannels][MaxChannels]
Definition: alSource.h:62
static __inline ALbyte aluF2B(ALfloat val)
Definition: ALu.c:931
unsigned int ALuint
Definition: al.h:59
volatile ALfloat OuterGain
Definition: alSource.h:87
ALfloat Dir[3]
Definition: alSource.h:41
void MixDirect_C(const DirectParams *params, const ALfloat *RESTRICT data, ALuint srcchan, ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
Definition: mixer_c.c:86
GLuint GLenum matrix
Definition: glew.h:13408
enum DevFmtChannels FmtChans
Definition: alMain.h:572
volatile ALfloat DopplerVelocity
Definition: alMain.h:692
DirectParams Direct
Definition: alSource.h:166
static __inline ALuint minu(ALuint a, ALuint b)
Definition: alu.h:61
GLenum GLenum GLenum GLenum GLenum scale
Definition: glew.h:12632
void Resample_lerp32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *RESTRICT dst, ALuint dstlen)
ALfloat ZScale
Definition: ALu.c:49
volatile ALfloat MaxGain
Definition: alSource.h:89
volatile ALboolean WetGainAuto
Definition: alSource.h:104
struct ALbuffer * buffer
Definition: alSource.h:26
#define DECL_TEMPLATE(T, func)
Definition: ALu.c:936
ALboolean Moving
Definition: alSource.h:32
volatile ALfloat Velocity[3]
Definition: alListener.h:12
Definition: alMain.h:738
GLintptr offset
Definition: glew.h:1668
volatile ALboolean DirectChannels
Definition: alSource.h:101
#define FRACTIONBITS
Definition: alu.h:49
FmtChannels
Definition: alBuffer.h:51
volatile ALfloat Forward[3]
Definition: alListener.h:13
ALfloat ClickRemoval[1]
static ResamplerFunc SelectResampler(enum Resampler Resampler, ALuint increment)
Definition: ALu.c:52
volatile ALfloat Gain
Definition: alListener.h:15
ALfloat * PendingClicks
Definition: alSource.h:52
ALCcontext *volatile ContextList
Definition: alMain.h:627
Resampler
Definition: alMain.h:472
static __inline void aluNormalize(ALfloat *inVector)
Definition: ALu.c:121
#define LOWPASSFREQREF
Definition: alFilter.h:10
struct ALbufferlistitem * next
Definition: alSource.h:27
struct DirectParams::@60 Hrtf
struct ALsource::@62 Params
volatile ALfloat Gain
Definition: alSource.h:86
ALuint Counter
Definition: alSource.h:33
enum DevFmtType FmtType
Definition: alMain.h:573
HrtfState * State
Definition: alSource.h:56
ALfloat Matrix[4][4]
Definition: alListener.h:19
ALfloat Gain
Definition: alSource.h:40
static DryMixerFunc SelectDirectMixer(void)
Definition: ALu.c:87
char ALboolean
Definition: al.h:38
volatile ALboolean AuxSendAuto
ALCcontext *volatile next
Definition: alMain.h:707
ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
Definition: ALu.c:193
GLint GLint GLint GLint GLint w
Definition: gl2ext.h:1215
volatile ALfloat RollOffFactor
Definition: alSource.h:94
static __inline ALint mini(ALint a, ALint b)
Definition: alu.h:68
ALCdevice * Device
Definition: alMain.h:704
GLenum src
Definition: glew.h:2396
void bs2b_cross_feed(struct bs2b *bs2b, float *sample)
Definition: bs2b.c:154
ALfloat DecayTime
Definition: alEffect.h:35
int i
Definition: pngrutil.c:1377
static __inline ALint fastf2i(ALfloat f)
Definition: alMain.h:363
ALuint CPUCapFlags
Definition: helpers.c:70
void(* ResamplerFunc)(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *RESTRICT dst, ALuint dstlen)
Definition: alu.h:33
struct ALsource::@61 Send[MAX_SENDS]
#define BUFFERSIZE
Definition: alMain.h:556
struct ALeffectslot ** ActiveEffectSlots
Definition: alMain.h:700
enum DistanceModel DistanceModel
Definition: alSource.h:100
volatile ALfloat InnerAngle
Definition: alSource.h:90
#define AIRABSORBGAINHF
Definition: alu.h:47
Channel
Definition: alMain.h:480
ALenum type
Definition: alEffect.h:27
ALfloat * ClickRemoval
Definition: alSource.h:51
volatile ALfloat Orientation[3]
Definition: alSource.h:97
static __inline ALint aluF2I(ALfloat val)
Definition: ALu.c:917
ALbufferlistitem * queue
Definition: alSource.h:137
#define ALCdevice_Lock(a)
Definition: alMain.h:646
void Resample_copy32_C(const ALfloat *data, ALuint frac, ALuint increment, ALfloat *RESTRICT OutBuffer, ALuint BufferSize)
Definition: mixer_c.c:18
HrtfState Hrtf
Definition: alSource.h:156
void MixDirect_Hrtf_C(const struct DirectParams *, const ALfloat *RESTRICT, ALuint, ALuint, ALuint, ALuint)
GLsizei size
Definition: gl2ext.h:1467
#define DEVICE_WIDE_STEREO
Definition: alMain.h:658
EGLContext ctx
Definition: eglext.h:87