2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
32 #include "alListener.h"
33 #include "alAuxEffectSlot.h"
38 #if defined (HAVE_FLOAT_H)
42 #if defined(HAVE_STDINT_H)
44 typedef int64_t ALint64
;
45 #elif defined(HAVE___INT64)
46 typedef __int64 ALint64
;
47 #elif (SIZEOF_LONG == 8)
49 #elif (SIZEOF_LONG_LONG == 8)
50 typedef long long ALint64
;
54 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
56 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
60 #define aluAcos(x) ((ALfloat)acosf((float)(x)))
62 #define aluAcos(x) ((ALfloat)acos((double)(x)))
66 #if defined(max) && !defined(__max)
69 #if defined(min) && !defined(__min)
73 #define BUFFERSIZE 24000
74 #define FRACTIONBITS 14
75 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
76 #define MAX_PITCH 65536
78 /* Minimum ramp length in milliseconds. The value below was chosen to
79 * adequately reduce clicks and pops from harsh gain changes. */
80 #define MIN_RAMP_LENGTH 16
82 ALboolean DuplicateStereo
= AL_FALSE
;
84 /* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
85 * converted to AL_FORMAT_QUAD* when loaded */
86 __inline ALuint
aluBytesFromFormat(ALenum format
)
91 case AL_FORMAT_STEREO8
:
92 case AL_FORMAT_QUAD8_LOKI
:
94 case AL_FORMAT_51CHN8
:
95 case AL_FORMAT_61CHN8
:
96 case AL_FORMAT_71CHN8
:
99 case AL_FORMAT_MONO16
:
100 case AL_FORMAT_STEREO16
:
101 case AL_FORMAT_QUAD16_LOKI
:
102 case AL_FORMAT_QUAD16
:
103 case AL_FORMAT_51CHN16
:
104 case AL_FORMAT_61CHN16
:
105 case AL_FORMAT_71CHN16
:
108 case AL_FORMAT_MONO_FLOAT32
:
109 case AL_FORMAT_STEREO_FLOAT32
:
110 case AL_FORMAT_QUAD32
:
111 case AL_FORMAT_51CHN32
:
112 case AL_FORMAT_61CHN32
:
113 case AL_FORMAT_71CHN32
:
121 __inline ALuint
aluChannelsFromFormat(ALenum format
)
125 case AL_FORMAT_MONO8
:
126 case AL_FORMAT_MONO16
:
127 case AL_FORMAT_MONO_FLOAT32
:
130 case AL_FORMAT_STEREO8
:
131 case AL_FORMAT_STEREO16
:
132 case AL_FORMAT_STEREO_FLOAT32
:
135 case AL_FORMAT_QUAD8_LOKI
:
136 case AL_FORMAT_QUAD16_LOKI
:
137 case AL_FORMAT_QUAD8
:
138 case AL_FORMAT_QUAD16
:
139 case AL_FORMAT_QUAD32
:
142 case AL_FORMAT_51CHN8
:
143 case AL_FORMAT_51CHN16
:
144 case AL_FORMAT_51CHN32
:
147 case AL_FORMAT_61CHN8
:
148 case AL_FORMAT_61CHN16
:
149 case AL_FORMAT_61CHN32
:
152 case AL_FORMAT_71CHN8
:
153 case AL_FORMAT_71CHN16
:
154 case AL_FORMAT_71CHN32
:
163 static __inline ALfloat
lpFilter(FILTER
*iir
, ALfloat input
)
165 ALfloat
*history
= iir
->history
;
166 ALfloat a
= iir
->coeff
;
167 ALfloat output
= input
;
169 output
= output
+ (history
[0]-output
)*a
;
171 output
= output
+ (history
[1]-output
)*a
;
173 output
= output
+ (history
[2]-output
)*a
;
175 output
= output
+ (history
[3]-output
)*a
;
181 static __inline ALfloat
lpFilterMC(FILTER
*iir
, ALuint chan
, ALfloat input
)
183 ALfloat
*history
= &iir
->history
[chan
*2];
184 ALfloat a
= iir
->coeff
;
185 ALfloat output
= input
;
187 output
= output
+ (history
[0]-output
)*a
;
189 output
= output
+ (history
[1]-output
)*a
;
196 static __inline ALshort
aluF2S(ALfloat Value
)
201 i
= __min( 32767, i
);
202 i
= __max(-32768, i
);
206 static __inline ALvoid
aluCrossproduct(ALfloat
*inVector1
,ALfloat
*inVector2
,ALfloat
*outVector
)
208 outVector
[0] = inVector1
[1]*inVector2
[2] - inVector1
[2]*inVector2
[1];
209 outVector
[1] = inVector1
[2]*inVector2
[0] - inVector1
[0]*inVector2
[2];
210 outVector
[2] = inVector1
[0]*inVector2
[1] - inVector1
[1]*inVector2
[0];
213 static __inline ALfloat
aluDotproduct(ALfloat
*inVector1
,ALfloat
*inVector2
)
215 return inVector1
[0]*inVector2
[0] + inVector1
[1]*inVector2
[1] +
216 inVector1
[2]*inVector2
[2];
219 static __inline ALvoid
aluNormalize(ALfloat
*inVector
)
221 ALfloat length
, inverse_length
;
223 length
= aluSqrt(aluDotproduct(inVector
, inVector
));
226 inverse_length
= 1.0f
/length
;
227 inVector
[0] *= inverse_length
;
228 inVector
[1] *= inverse_length
;
229 inVector
[2] *= inverse_length
;
233 static __inline ALvoid
aluMatrixVector(ALfloat
*vector
,ALfloat matrix
[3][3])
237 result
[0] = vector
[0]*matrix
[0][0] + vector
[1]*matrix
[1][0] + vector
[2]*matrix
[2][0];
238 result
[1] = vector
[0]*matrix
[0][1] + vector
[1]*matrix
[1][1] + vector
[2]*matrix
[2][1];
239 result
[2] = vector
[0]*matrix
[0][2] + vector
[1]*matrix
[1][2] + vector
[2]*matrix
[2][2];
240 memcpy(vector
, result
, sizeof(result
));
244 static ALvoid
CalcSourceParams(ALCcontext
*ALContext
, ALsource
*ALSource
,
245 ALenum isMono
, ALenum OutputFormat
,
246 ALfloat
*drysend
, ALfloat
*wetsend
,
247 ALfloat
*pitch
, ALfloat
*drygainhf
,
250 ALfloat InnerAngle
,OuterAngle
,Angle
,Distance
,DryMix
,WetMix
=0.0f
;
251 ALfloat Direction
[3],Position
[3],SourceToListener
[3];
252 ALfloat MinVolume
,MaxVolume
,MinDist
,MaxDist
,Rolloff
,OuterGainHF
;
253 ALfloat ConeVolume
,SourceVolume
,PanningFB
,PanningLR
,ListenerGain
;
254 ALfloat U
[3],V
[3],N
[3];
255 ALfloat DopplerFactor
, DopplerVelocity
, flSpeedOfSound
, flMaxVelocity
;
256 ALfloat Matrix
[3][3];
257 ALfloat flAttenuation
;
258 ALfloat RoomAttenuation
;
259 ALfloat MetersPerUnit
;
261 ALfloat DryGainHF
= 1.0f
;
262 ALfloat WetGainHF
= 1.0f
;
265 //Get context properties
266 DopplerFactor
= ALContext
->DopplerFactor
* ALSource
->DopplerFactor
;
267 DopplerVelocity
= ALContext
->DopplerVelocity
;
268 flSpeedOfSound
= ALContext
->flSpeedOfSound
;
270 //Get listener properties
271 ListenerGain
= ALContext
->Listener
.Gain
;
272 MetersPerUnit
= ALContext
->Listener
.MetersPerUnit
;
274 //Get source properties
275 SourceVolume
= ALSource
->flGain
;
276 memcpy(Position
, ALSource
->vPosition
, sizeof(ALSource
->vPosition
));
277 memcpy(Direction
, ALSource
->vOrientation
, sizeof(ALSource
->vOrientation
));
278 MinVolume
= ALSource
->flMinGain
;
279 MaxVolume
= ALSource
->flMaxGain
;
280 MinDist
= ALSource
->flRefDistance
;
281 MaxDist
= ALSource
->flMaxDistance
;
282 Rolloff
= ALSource
->flRollOffFactor
;
283 InnerAngle
= ALSource
->flInnerAngle
;
284 OuterAngle
= ALSource
->flOuterAngle
;
285 OuterGainHF
= ALSource
->OuterGainHF
;
286 RoomRolloff
= ALSource
->RoomRolloffFactor
;
288 //Only apply 3D calculations for mono buffers
289 if(isMono
!= AL_FALSE
)
291 //1. Translate Listener to origin (convert to head relative)
292 // Note that Direction and SourceToListener are *not* transformed.
293 // SourceToListener is used with the source and listener velocities,
294 // which are untransformed, and Direction is used with SourceToListener
295 // for the sound cone
296 if(ALSource
->bHeadRelative
==AL_FALSE
)
298 // Build transform matrix
299 aluCrossproduct(ALContext
->Listener
.Forward
, ALContext
->Listener
.Up
, U
); // Right-vector
300 aluNormalize(U
); // Normalized Right-vector
301 memcpy(V
, ALContext
->Listener
.Up
, sizeof(V
)); // Up-vector
302 aluNormalize(V
); // Normalized Up-vector
303 memcpy(N
, ALContext
->Listener
.Forward
, sizeof(N
)); // At-vector
304 aluNormalize(N
); // Normalized At-vector
305 Matrix
[0][0] = U
[0]; Matrix
[0][1] = V
[0]; Matrix
[0][2] = -N
[0];
306 Matrix
[1][0] = U
[1]; Matrix
[1][1] = V
[1]; Matrix
[1][2] = -N
[1];
307 Matrix
[2][0] = U
[2]; Matrix
[2][1] = V
[2]; Matrix
[2][2] = -N
[2];
309 // Translate source position into listener space
310 Position
[0] -= ALContext
->Listener
.Position
[0];
311 Position
[1] -= ALContext
->Listener
.Position
[1];
312 Position
[2] -= ALContext
->Listener
.Position
[2];
314 SourceToListener
[0] = -Position
[0];
315 SourceToListener
[1] = -Position
[1];
316 SourceToListener
[2] = -Position
[2];
318 // Transform source position and direction into listener space
319 aluMatrixVector(Position
, Matrix
);
323 SourceToListener
[0] = -Position
[0];
324 SourceToListener
[1] = -Position
[1];
325 SourceToListener
[2] = -Position
[2];
327 aluNormalize(SourceToListener
);
328 aluNormalize(Direction
);
330 //2. Calculate distance attenuation
331 Distance
= aluSqrt(aluDotproduct(Position
, Position
));
333 if(ALSource
->Send
[0].Slot
)
335 if(ALSource
->Send
[0].Slot
->effect
.type
== AL_EFFECT_REVERB
)
336 RoomRolloff
+= ALSource
->Send
[0].Slot
->effect
.Reverb
.RoomRolloffFactor
;
339 flAttenuation
= 1.0f
;
340 RoomAttenuation
= 1.0f
;
341 switch (ALSource
->DistanceModel
)
343 case AL_INVERSE_DISTANCE_CLAMPED
:
344 Distance
=__max(Distance
,MinDist
);
345 Distance
=__min(Distance
,MaxDist
);
346 if (MaxDist
< MinDist
)
349 case AL_INVERSE_DISTANCE
:
352 if ((MinDist
+ (Rolloff
* (Distance
- MinDist
))) > 0.0f
)
353 flAttenuation
= MinDist
/ (MinDist
+ (Rolloff
* (Distance
- MinDist
)));
354 if ((MinDist
+ (RoomRolloff
* (Distance
- MinDist
))) > 0.0f
)
355 RoomAttenuation
= MinDist
/ (MinDist
+ (RoomRolloff
* (Distance
- MinDist
)));
359 case AL_LINEAR_DISTANCE_CLAMPED
:
360 Distance
=__max(Distance
,MinDist
);
361 Distance
=__min(Distance
,MaxDist
);
362 if (MaxDist
< MinDist
)
365 case AL_LINEAR_DISTANCE
:
366 Distance
=__min(Distance
,MaxDist
);
367 if (MaxDist
!= MinDist
)
369 flAttenuation
= 1.0f
- (Rolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
370 RoomAttenuation
= 1.0f
- (RoomRolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
374 case AL_EXPONENT_DISTANCE_CLAMPED
:
375 Distance
=__max(Distance
,MinDist
);
376 Distance
=__min(Distance
,MaxDist
);
377 if (MaxDist
< MinDist
)
380 case AL_EXPONENT_DISTANCE
:
381 if ((Distance
> 0.0f
) && (MinDist
> 0.0f
))
383 flAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -Rolloff
);
384 RoomAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -RoomRolloff
);
389 flAttenuation
= 1.0f
;
390 RoomAttenuation
= 1.0f
;
394 // Distance-based air absorption
395 if(ALSource
->AirAbsorptionFactor
> 0.0f
&& ALContext
->DistanceModel
!= AL_NONE
)
397 ALfloat dist
= Distance
-MinDist
;
400 if(dist
< 0.0f
) dist
= 0.0f
;
401 // Absorption calculation is done in dB
402 absorb
= (ALSource
->AirAbsorptionFactor
*AIRABSORBGAINDBHF
) *
403 (Distance
*MetersPerUnit
);
404 // Convert dB to linear gain before applying
405 absorb
= pow(10.0, absorb
/20.0);
410 // Source Gain + Attenuation and clamp to Min/Max Gain
411 DryMix
= SourceVolume
* flAttenuation
;
412 DryMix
= __min(DryMix
,MaxVolume
);
413 DryMix
= __max(DryMix
,MinVolume
);
415 WetMix
= SourceVolume
* RoomAttenuation
;
416 WetMix
= __min(WetMix
,MaxVolume
);
417 WetMix
= __max(WetMix
,MinVolume
);
419 //3. Apply directional soundcones
420 Angle
= aluAcos(aluDotproduct(Direction
,SourceToListener
)) * 180.0f
/
422 if(Angle
>= InnerAngle
&& Angle
<= OuterAngle
)
424 ALfloat scale
= (Angle
-InnerAngle
) / (OuterAngle
-InnerAngle
);
425 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
)*scale
);
426 DryMix
*= ConeVolume
;
427 if(ALSource
->WetGainAuto
)
428 WetMix
*= ConeVolume
;
429 if(ALSource
->DryGainHFAuto
)
430 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
431 if(ALSource
->WetGainHFAuto
)
432 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
434 else if(Angle
> OuterAngle
)
436 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
));
437 DryMix
*= ConeVolume
;
438 if(ALSource
->WetGainAuto
)
439 WetMix
*= ConeVolume
;
440 if(ALSource
->DryGainHFAuto
)
441 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
442 if(ALSource
->WetGainHFAuto
)
443 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
446 //4. Calculate Velocity
447 if(DopplerFactor
!= 0.0f
)
449 ALfloat flVSS
, flVLS
= 0.0f
;
451 if(ALSource
->bHeadRelative
==AL_FALSE
)
452 flVLS
= aluDotproduct(ALContext
->Listener
.Velocity
, SourceToListener
);
453 flVSS
= aluDotproduct(ALSource
->vVelocity
, SourceToListener
);
455 flMaxVelocity
= (DopplerVelocity
* flSpeedOfSound
) / DopplerFactor
;
457 if (flVSS
>= flMaxVelocity
)
458 flVSS
= (flMaxVelocity
- 1.0f
);
459 else if (flVSS
<= -flMaxVelocity
)
460 flVSS
= -flMaxVelocity
+ 1.0f
;
462 if (flVLS
>= flMaxVelocity
)
463 flVLS
= (flMaxVelocity
- 1.0f
);
464 else if (flVLS
<= -flMaxVelocity
)
465 flVLS
= -flMaxVelocity
+ 1.0f
;
467 pitch
[0] = ALSource
->flPitch
*
468 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVLS
)) /
469 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVSS
));
472 pitch
[0] = ALSource
->flPitch
;
474 if(ALSource
->Send
[0].Slot
&&
475 ALSource
->Send
[0].Slot
->effect
.type
!= AL_EFFECT_NULL
)
477 if(ALSource
->Send
[0].Slot
->AuxSendAuto
)
479 // Apply minimal attenuation in place of missing statistical
481 WetMix
*= pow(DryMix
, 1.0f
/ 2.0f
);
485 // If the slot's auxilliary send auto is off, the data sent to the
486 // effect slot is the same as the dry path, sans filter effects
488 WetGainHF
= DryGainHF
;
491 // Note that this is really applied by the effect slot. However,
492 // it's easier (more optimal) to handle it here.
493 if(ALSource
->Send
[0].Slot
->effect
.type
== AL_EFFECT_REVERB
)
494 WetGainHF
*= ALSource
->Send
[0].Slot
->effect
.Reverb
.GainHF
;
502 //5. Apply filter gains and filters
503 switch(ALSource
->DirectFilter
.type
)
505 case AL_FILTER_LOWPASS
:
506 DryMix
*= ALSource
->DirectFilter
.Gain
;
507 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
511 switch(ALSource
->Send
[0].WetFilter
.type
)
513 case AL_FILTER_LOWPASS
:
514 WetMix
*= ALSource
->Send
[0].WetFilter
.Gain
;
515 WetGainHF
*= ALSource
->Send
[0].WetFilter
.GainHF
;
519 DryMix
*= ListenerGain
;
520 WetMix
*= ListenerGain
;
522 //6. Convert normalized position into pannings, then into channel volumes
523 aluNormalize(Position
);
524 switch(aluChannelsFromFormat(OutputFormat
))
528 PanningLR
= 0.5f
+ 0.5f
*Position
[0];
529 drysend
[FRONT_LEFT
] = DryMix
* aluSqrt(1.0f
-PanningLR
); //L Direct
530 drysend
[FRONT_RIGHT
] = DryMix
* aluSqrt( PanningLR
); //R Direct
531 drysend
[BACK_LEFT
] = 0.0f
;
532 drysend
[BACK_RIGHT
] = 0.0f
;
533 drysend
[SIDE_LEFT
] = 0.0f
;
534 drysend
[SIDE_RIGHT
] = 0.0f
;
537 /* TODO: Add center/lfe channel in spatial calculations? */
539 // Apply a scalar so each individual speaker has more weight
540 PanningLR
= 0.5f
+ (0.5f
*Position
[0]*1.41421356f
);
541 PanningLR
= __min(1.0f
, PanningLR
);
542 PanningLR
= __max(0.0f
, PanningLR
);
543 PanningFB
= 0.5f
+ (0.5f
*Position
[2]*1.41421356f
);
544 PanningFB
= __min(1.0f
, PanningFB
);
545 PanningFB
= __max(0.0f
, PanningFB
);
546 drysend
[FRONT_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
547 drysend
[FRONT_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
548 drysend
[BACK_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
549 drysend
[BACK_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
550 drysend
[SIDE_LEFT
] = 0.0f
;
551 drysend
[SIDE_RIGHT
] = 0.0f
;
555 PanningFB
= 1.0f
- fabs(Position
[2]*1.15470054f
);
556 PanningFB
= __min(1.0f
, PanningFB
);
557 PanningFB
= __max(0.0f
, PanningFB
);
558 PanningLR
= 0.5f
+ (0.5*Position
[0]*((1.0f
-PanningFB
)*2.0f
));
559 PanningLR
= __min(1.0f
, PanningLR
);
560 PanningLR
= __max(0.0f
, PanningLR
);
561 if(Position
[2] > 0.0f
)
563 drysend
[BACK_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
564 drysend
[BACK_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
565 drysend
[SIDE_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
566 drysend
[SIDE_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
567 drysend
[FRONT_LEFT
] = 0.0f
;
568 drysend
[FRONT_RIGHT
] = 0.0f
;
572 drysend
[FRONT_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
573 drysend
[FRONT_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
574 drysend
[SIDE_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
575 drysend
[SIDE_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
576 drysend
[BACK_LEFT
] = 0.0f
;
577 drysend
[BACK_RIGHT
] = 0.0f
;
584 // Update filter coefficients. Calculations based on the I3DL2 spec.
585 cw
= cos(2.0f
*3.141592654f
* LOWPASSFREQCUTOFF
/ ALContext
->Frequency
);
586 // We use four chained one-pole filters, so we need to take the fourth
587 // root of the squared gain, which is the same as the square root of
589 // Be careful with gains < 0.0001, as that causes the coefficient to
590 // head towards 1, which will flatten the signal
591 g
= aluSqrt(__max(DryGainHF
, 0.0001f
));
593 if(g
< 0.9999f
) // 1-epsilon
594 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
595 ALSource
->iirFilter
.coeff
= a
;
597 g
= aluSqrt(__max(WetGainHF
, 0.0001f
));
599 if(g
< 0.9999f
) // 1-epsilon
600 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
601 ALSource
->Send
[0].iirFilter
.coeff
= a
;
603 *drygainhf
= DryGainHF
;
604 *wetgainhf
= WetGainHF
;
608 //1. Multi-channel buffers always play "normal"
609 pitch
[0] = ALSource
->flPitch
;
611 DryMix
= SourceVolume
;
613 switch(ALSource
->DirectFilter
.type
)
615 case AL_FILTER_LOWPASS
:
616 DryMix
*= ALSource
->DirectFilter
.Gain
;
617 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
621 drysend
[FRONT_LEFT
] = DryMix
* ListenerGain
;
622 drysend
[FRONT_RIGHT
] = DryMix
* ListenerGain
;
623 drysend
[SIDE_LEFT
] = DryMix
* ListenerGain
;
624 drysend
[SIDE_RIGHT
] = DryMix
* ListenerGain
;
625 drysend
[BACK_LEFT
] = DryMix
* ListenerGain
;
626 drysend
[BACK_RIGHT
] = DryMix
* ListenerGain
;
627 drysend
[CENTER
] = DryMix
* ListenerGain
;
628 drysend
[LFE
] = DryMix
* ListenerGain
;
631 cw
= cos(2.0f
*3.141592654f
* LOWPASSFREQCUTOFF
/ ALContext
->Frequency
);
632 g
= __max(DryGainHF
, 0.01f
);
634 if(g
< 0.9999f
) // 1-epsilon
635 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
636 ALSource
->iirFilter
.coeff
= a
;
637 ALSource
->Send
[0].iirFilter
.coeff
= 0.0f
;
639 *drygainhf
= DryGainHF
;
640 *wetgainhf
= WetGainHF
;
644 static __inline ALshort
lerp(ALshort val1
, ALshort val2
, ALint frac
)
646 return val1
+ (((val2
-val1
)*frac
)>>FRACTIONBITS
);
649 ALvoid
aluMixData(ALCcontext
*ALContext
,ALvoid
*buffer
,ALsizei size
,ALenum format
)
651 static float DryBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
652 static float WetBuffer
[BUFFERSIZE
];
653 ALfloat newDrySend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
654 ALfloat newWetSend
= 0.0f
;
655 ALfloat DryGainHF
= 0.0f
;
656 ALfloat WetGainHF
= 0.0f
;
660 ALfloat dryGainStep
[OUTPUTCHANNELS
];
662 ALuint BlockAlign
,BufferSize
;
663 ALuint DataSize
=0,DataPosInt
=0,DataPosFrac
=0;
664 ALuint Channels
,Frequency
,ulExtraSamples
;
672 ALeffectslot
*ALEffectSlot
;
676 ALbufferlistitem
*BufferListItem
;
678 ALint64 DataSize64
,DataPos64
;
679 FILTER
*DryFilter
, *WetFilter
;
682 SuspendContext(ALContext
);
684 #if defined(HAVE_FESETROUND)
685 fpuState
= fegetround();
686 fesetround(FE_TOWARDZERO
);
687 #elif defined(HAVE__CONTROLFP)
688 fpuState
= _controlfp(0, 0);
689 _controlfp(_RC_CHOP
, _MCW_RC
);
694 //Figure output format variables
695 BlockAlign
= aluChannelsFromFormat(format
);
696 BlockAlign
*= aluBytesFromFormat(format
);
702 SamplesToDo
= min(size
, BUFFERSIZE
);
705 ALEffectSlot
= ALContext
->AuxiliaryEffectSlot
;
706 ALSource
= ALContext
->Source
;
707 rampLength
= ALContext
->Frequency
* MIN_RAMP_LENGTH
/ 1000;
715 rampLength
= max(rampLength
, SamplesToDo
);
717 //Clear mixing buffer
718 memset(WetBuffer
, 0, SamplesToDo
*sizeof(ALfloat
));
719 memset(DryBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
725 State
= ALSource
->state
;
727 while(State
== AL_PLAYING
&& j
< SamplesToDo
)
734 if((Buffer
= ALSource
->ulBufferID
))
736 ALBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(Buffer
);
738 Data
= ALBuffer
->data
;
739 Channels
= aluChannelsFromFormat(ALBuffer
->format
);
740 DataSize
= ALBuffer
->size
;
741 DataSize
/= Channels
* aluBytesFromFormat(ALBuffer
->format
);
742 Frequency
= ALBuffer
->frequency
;
743 DataPosInt
= ALSource
->position
;
744 DataPosFrac
= ALSource
->position_fraction
;
746 if(DataPosInt
>= DataSize
)
749 CalcSourceParams(ALContext
, ALSource
,
750 (Channels
==1) ? AL_TRUE
: AL_FALSE
,
751 format
, newDrySend
, &newWetSend
, &Pitch
,
752 &DryGainHF
, &WetGainHF
);
754 Pitch
= (Pitch
*Frequency
) / ALContext
->Frequency
;
757 DryFilter
= &ALSource
->iirFilter
;
758 WetFilter
= &ALSource
->Send
[0].iirFilter
;
759 DrySend
= ALSource
->DryGains
;
760 WetSend
= &ALSource
->WetGain
;
762 //Compute the gain steps for each output channel
763 if(ALSource
->FirstStart
&& DataPosInt
== 0 && DataPosFrac
== 0)
765 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
767 DrySend
[i
] = newDrySend
[i
];
770 *WetSend
= newWetSend
;
775 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
776 dryGainStep
[i
] = (newDrySend
[i
]-DrySend
[i
]) / rampLength
;
777 wetGainStep
= (newWetSend
-(*WetSend
)) / rampLength
;
779 ALSource
->FirstStart
= AL_FALSE
;
781 //Compute 18.14 fixed point step
782 if(Pitch
> (float)MAX_PITCH
)
783 Pitch
= (float)MAX_PITCH
;
784 increment
= (ALint
)(Pitch
*(ALfloat
)(1L<<FRACTIONBITS
));
786 increment
= (1<<FRACTIONBITS
);
788 //Figure out how many samples we can mix.
789 DataSize64
= DataSize
;
790 DataSize64
<<= FRACTIONBITS
;
791 DataPos64
= DataPosInt
;
792 DataPos64
<<= FRACTIONBITS
;
793 DataPos64
+= DataPosFrac
;
794 BufferSize
= (ALuint
)((DataSize64
-DataPos64
+(increment
-1)) / increment
);
796 BufferListItem
= ALSource
->queue
;
797 for(loop
= 0; loop
< ALSource
->BuffersPlayed
; loop
++)
800 BufferListItem
= BufferListItem
->next
;
804 if (BufferListItem
->next
)
806 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
);
807 if(NextBuf
&& NextBuf
->data
)
809 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
810 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
813 else if (ALSource
->bLooping
)
815 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
);
816 if (NextBuf
&& NextBuf
->data
)
818 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
819 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
823 memset(&Data
[DataSize
*Channels
], 0, (ALBuffer
->padding
*Channels
*2));
825 BufferSize
= min(BufferSize
, (SamplesToDo
-j
));
827 //Actual sample mixing loop
829 Data
+= DataPosInt
*Channels
;
832 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
833 DrySend
[i
] += dryGainStep
[i
];
834 *WetSend
+= wetGainStep
;
838 ALfloat sample
, outsamp
;
839 //First order interpolator
840 sample
= lerp(Data
[k
], Data
[k
+1], DataPosFrac
);
842 //Direct path final mix buffer and panning
843 outsamp
= lpFilter(DryFilter
, sample
);
844 DryBuffer
[j
][FRONT_LEFT
] += outsamp
*DrySend
[FRONT_LEFT
];
845 DryBuffer
[j
][FRONT_RIGHT
] += outsamp
*DrySend
[FRONT_RIGHT
];
846 DryBuffer
[j
][SIDE_LEFT
] += outsamp
*DrySend
[SIDE_LEFT
];
847 DryBuffer
[j
][SIDE_RIGHT
] += outsamp
*DrySend
[SIDE_RIGHT
];
848 DryBuffer
[j
][BACK_LEFT
] += outsamp
*DrySend
[BACK_LEFT
];
849 DryBuffer
[j
][BACK_RIGHT
] += outsamp
*DrySend
[BACK_RIGHT
];
850 //Room path final mix buffer and panning
851 outsamp
= lpFilter(WetFilter
, sample
);
852 WetBuffer
[j
] += outsamp
*(*WetSend
);
856 ALfloat samp1
, samp2
;
857 //First order interpolator (front left)
858 samp1
= lerp(Data
[k
*Channels
], Data
[(k
+1)*Channels
], DataPosFrac
);
859 samp1
= lpFilterMC(DryFilter
, FRONT_LEFT
, samp1
);
860 DryBuffer
[j
][FRONT_LEFT
] += samp1
*DrySend
[FRONT_LEFT
];
861 //First order interpolator (front right)
862 samp2
= lerp(Data
[k
*Channels
+1], Data
[(k
+1)*Channels
+1], DataPosFrac
);
863 samp2
= lpFilterMC(DryFilter
, FRONT_RIGHT
, samp2
);
864 DryBuffer
[j
][FRONT_RIGHT
] += samp2
*DrySend
[FRONT_RIGHT
];
872 //First order interpolator (center)
873 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
874 DryBuffer
[j
][CENTER
] += lpFilterMC(DryFilter
, CENTER
, value
)*DrySend
[CENTER
];
877 //First order interpolator (lfe)
878 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
879 DryBuffer
[j
][LFE
] += lpFilterMC(DryFilter
, LFE
, value
)*DrySend
[LFE
];
882 //First order interpolator (back left)
883 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
884 DryBuffer
[j
][BACK_LEFT
] += lpFilterMC(DryFilter
, BACK_LEFT
, value
)*DrySend
[BACK_LEFT
];
886 //First order interpolator (back right)
887 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
888 DryBuffer
[j
][BACK_RIGHT
] += lpFilterMC(DryFilter
, BACK_RIGHT
, value
)*DrySend
[BACK_RIGHT
];
892 //First order interpolator (side left)
893 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
894 DryBuffer
[j
][SIDE_LEFT
] += lpFilterMC(DryFilter
, SIDE_LEFT
, value
)*DrySend
[SIDE_LEFT
];
896 //First order interpolator (side right)
897 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
898 DryBuffer
[j
][SIDE_RIGHT
] += lpFilterMC(DryFilter
, SIDE_RIGHT
, value
)*DrySend
[SIDE_RIGHT
];
902 else if(DuplicateStereo
)
904 //Duplicate stereo channels on the back speakers
905 DryBuffer
[j
][BACK_LEFT
] += samp1
*DrySend
[BACK_LEFT
];
906 DryBuffer
[j
][BACK_RIGHT
] += samp2
*DrySend
[BACK_RIGHT
];
909 DataPosFrac
+= increment
;
910 k
+= DataPosFrac
>>FRACTIONBITS
;
911 DataPosFrac
&= FRACTIONMASK
;
917 ALSource
->position
= DataPosInt
;
918 ALSource
->position_fraction
= DataPosFrac
;
923 //Handle looping sources
924 if(!Buffer
|| DataPosInt
>= DataSize
)
929 Looping
= ALSource
->bLooping
;
930 if(ALSource
->BuffersPlayed
< (ALSource
->BuffersInQueue
-1))
932 BufferListItem
= ALSource
->queue
;
933 for(loop
= 0; loop
<= ALSource
->BuffersPlayed
; loop
++)
938 BufferListItem
->bufferstate
= PROCESSED
;
939 BufferListItem
= BufferListItem
->next
;
943 ALSource
->ulBufferID
= BufferListItem
->buffer
;
944 ALSource
->position
= DataPosInt
-DataSize
;
945 ALSource
->position_fraction
= DataPosFrac
;
946 ALSource
->BuffersPlayed
++;
953 ALSource
->state
= AL_STOPPED
;
954 ALSource
->inuse
= AL_FALSE
;
955 ALSource
->BuffersPlayed
= ALSource
->BuffersInQueue
;
956 BufferListItem
= ALSource
->queue
;
957 while(BufferListItem
!= NULL
)
959 BufferListItem
->bufferstate
= PROCESSED
;
960 BufferListItem
= BufferListItem
->next
;
962 ALSource
->position
= DataSize
;
963 ALSource
->position_fraction
= 0;
969 ALSource
->state
= AL_PLAYING
;
970 ALSource
->inuse
= AL_TRUE
;
971 ALSource
->play
= AL_TRUE
;
972 ALSource
->BuffersPlayed
= 0;
973 BufferListItem
= ALSource
->queue
;
974 while(BufferListItem
!= NULL
)
976 BufferListItem
->bufferstate
= PENDING
;
977 BufferListItem
= BufferListItem
->next
;
979 ALSource
->ulBufferID
= ALSource
->queue
->buffer
;
981 if(ALSource
->BuffersInQueue
== 1)
982 ALSource
->position
= DataPosInt
%DataSize
;
984 ALSource
->position
= DataPosInt
-DataSize
;
985 ALSource
->position_fraction
= DataPosFrac
;
992 State
= ALSource
->state
;
995 ALSource
= ALSource
->next
;
998 // effect slot processing
1001 if(ALEffectSlot
->effect
.type
== AL_EFFECT_REVERB
)
1002 VerbProcess(ALEffectSlot
->ReverbState
, SamplesToDo
, WetBuffer
, DryBuffer
);
1004 ALEffectSlot
= ALEffectSlot
->next
;
1007 //Post processing loop
1010 case AL_FORMAT_MONO8
:
1011 for(i
= 0;i
< SamplesToDo
;i
++)
1013 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1014 buffer
= ((ALubyte
*)buffer
) + 1;
1017 case AL_FORMAT_STEREO8
:
1018 if(ALContext
&& ALContext
->bs2b
)
1020 for(i
= 0;i
< SamplesToDo
;i
++)
1023 samples
[0] = DryBuffer
[i
][FRONT_LEFT
];
1024 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
];
1025 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1026 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(samples
[0])>>8)+128);
1027 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(samples
[1])>>8)+128);
1028 buffer
= ((ALubyte
*)buffer
) + 2;
1033 for(i
= 0;i
< SamplesToDo
;i
++)
1035 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1036 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1037 buffer
= ((ALubyte
*)buffer
) + 2;
1041 case AL_FORMAT_QUAD8
:
1042 for(i
= 0;i
< SamplesToDo
;i
++)
1044 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1045 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1046 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1047 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1048 buffer
= ((ALubyte
*)buffer
) + 4;
1051 case AL_FORMAT_51CHN8
:
1052 for(i
= 0;i
< SamplesToDo
;i
++)
1054 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1055 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1056 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1057 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
])>>8)+128);
1058 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1059 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1060 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1062 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1063 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1064 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
])>>8)+128);
1065 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1067 buffer
= ((ALubyte
*)buffer
) + 6;
1070 case AL_FORMAT_61CHN8
:
1071 for(i
= 0;i
< SamplesToDo
;i
++)
1073 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1074 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1076 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1077 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1078 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1080 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1081 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1082 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1084 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
])>>8)+128);
1085 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1086 buffer
= ((ALubyte
*)buffer
) + 7;
1089 case AL_FORMAT_71CHN8
:
1090 for(i
= 0;i
< SamplesToDo
;i
++)
1092 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1093 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1095 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
])>>8)+128);
1096 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1097 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1098 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1100 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1101 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1102 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
])>>8)+128);
1103 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1105 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
])>>8)+128);
1106 ((ALubyte
*)buffer
)[7] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1107 buffer
= ((ALubyte
*)buffer
) + 8;
1111 case AL_FORMAT_MONO16
:
1112 for(i
= 0;i
< SamplesToDo
;i
++)
1114 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]);
1115 buffer
= ((ALshort
*)buffer
) + 1;
1118 case AL_FORMAT_STEREO16
:
1119 if(ALContext
&& ALContext
->bs2b
)
1121 for(i
= 0;i
< SamplesToDo
;i
++)
1124 samples
[0] = DryBuffer
[i
][FRONT_LEFT
];
1125 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
];
1126 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1127 ((ALshort
*)buffer
)[0] = aluF2S(samples
[0]);
1128 ((ALshort
*)buffer
)[1] = aluF2S(samples
[1]);
1129 buffer
= ((ALshort
*)buffer
) + 2;
1134 for(i
= 0;i
< SamplesToDo
;i
++)
1136 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1137 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1138 buffer
= ((ALshort
*)buffer
) + 2;
1142 case AL_FORMAT_QUAD16
:
1143 for(i
= 0;i
< SamplesToDo
;i
++)
1145 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1146 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1147 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1148 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1149 buffer
= ((ALshort
*)buffer
) + 4;
1152 case AL_FORMAT_51CHN16
:
1153 for(i
= 0;i
< SamplesToDo
;i
++)
1155 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1156 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1158 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][CENTER
]);
1159 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
]);
1160 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1161 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1163 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1164 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1165 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
]);
1166 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
]);
1168 buffer
= ((ALshort
*)buffer
) + 6;
1171 case AL_FORMAT_61CHN16
:
1172 for(i
= 0;i
< SamplesToDo
;i
++)
1174 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1175 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1177 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][LFE
]);
1178 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1179 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1181 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1182 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1183 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][LFE
]);
1185 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][SIDE_LEFT
]);
1186 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
]);
1187 buffer
= ((ALshort
*)buffer
) + 7;
1190 case AL_FORMAT_71CHN16
:
1191 for(i
= 0;i
< SamplesToDo
;i
++)
1193 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1194 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1196 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][CENTER
]);
1197 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
]);
1198 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1199 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1201 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1202 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1203 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
]);
1204 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
]);
1206 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_LEFT
]);
1207 ((ALshort
*)buffer
)[7] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
]);
1208 buffer
= ((ALshort
*)buffer
) + 8;
1216 size
-= SamplesToDo
;
1219 #if defined(HAVE_FESETROUND)
1220 fesetround(fpuState
);
1221 #elif defined(HAVE__CONTROLFP)
1222 _controlfp(fpuState
, 0xfffff);
1225 ProcessContext(ALContext
);