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"
37 #if defined(HAVE_STDINT_H)
39 typedef int64_t ALint64
;
40 #elif defined(HAVE___INT64)
41 typedef __int64 ALint64
;
42 #elif (SIZEOF_LONG == 8)
44 #elif (SIZEOF_LONG_LONG == 8)
45 typedef long long ALint64
;
49 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
51 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
55 #define aluAcos(x) ((ALfloat)acosf((float)(x)))
57 #define aluAcos(x) ((ALfloat)acos((double)(x)))
61 #if defined(max) && !defined(__max)
64 #if defined(min) && !defined(__min)
68 #define BUFFERSIZE 24000
69 #define FRACTIONBITS 14
70 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
73 /* Minimum ramp length in milliseconds. The value below was chosen to
74 * adequately reduce clicks and pops from harsh gain changes. */
75 #define MIN_RAMP_LENGTH 16
77 ALboolean DuplicateStereo
= AL_FALSE
;
79 /* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
80 * converted to AL_FORMAT_QUAD* when loaded */
81 __inline ALuint
aluBytesFromFormat(ALenum format
)
86 case AL_FORMAT_STEREO8
:
87 case AL_FORMAT_QUAD8_LOKI
:
89 case AL_FORMAT_51CHN8
:
90 case AL_FORMAT_61CHN8
:
91 case AL_FORMAT_71CHN8
:
94 case AL_FORMAT_MONO16
:
95 case AL_FORMAT_STEREO16
:
96 case AL_FORMAT_QUAD16_LOKI
:
97 case AL_FORMAT_QUAD16
:
98 case AL_FORMAT_51CHN16
:
99 case AL_FORMAT_61CHN16
:
100 case AL_FORMAT_71CHN16
:
103 case AL_FORMAT_MONO_FLOAT32
:
104 case AL_FORMAT_STEREO_FLOAT32
:
105 case AL_FORMAT_QUAD32
:
106 case AL_FORMAT_51CHN32
:
107 case AL_FORMAT_61CHN32
:
108 case AL_FORMAT_71CHN32
:
116 __inline ALuint
aluChannelsFromFormat(ALenum format
)
120 case AL_FORMAT_MONO8
:
121 case AL_FORMAT_MONO16
:
122 case AL_FORMAT_MONO_FLOAT32
:
125 case AL_FORMAT_STEREO8
:
126 case AL_FORMAT_STEREO16
:
127 case AL_FORMAT_STEREO_FLOAT32
:
130 case AL_FORMAT_QUAD8_LOKI
:
131 case AL_FORMAT_QUAD16_LOKI
:
132 case AL_FORMAT_QUAD8
:
133 case AL_FORMAT_QUAD16
:
134 case AL_FORMAT_QUAD32
:
137 case AL_FORMAT_51CHN8
:
138 case AL_FORMAT_51CHN16
:
139 case AL_FORMAT_51CHN32
:
142 case AL_FORMAT_61CHN8
:
143 case AL_FORMAT_61CHN16
:
144 case AL_FORMAT_61CHN32
:
147 case AL_FORMAT_71CHN8
:
148 case AL_FORMAT_71CHN16
:
149 case AL_FORMAT_71CHN32
:
158 static __inline ALfloat
lpFilter(FILTER
*iir
, ALfloat input
)
160 ALfloat
*history
= iir
->history
;
161 ALfloat a
= iir
->coeff
;
162 ALfloat output
= input
;
164 output
= output
+ (history
[0]-output
)*a
;
166 output
= output
+ (history
[1]-output
)*a
;
168 output
= output
+ (history
[2]-output
)*a
;
170 output
= output
+ (history
[3]-output
)*a
;
177 static __inline ALshort
aluF2S(ALfloat Value
)
182 i
= __min( 32767, i
);
183 i
= __max(-32768, i
);
187 static __inline ALvoid
aluCrossproduct(ALfloat
*inVector1
,ALfloat
*inVector2
,ALfloat
*outVector
)
189 outVector
[0] = inVector1
[1]*inVector2
[2] - inVector1
[2]*inVector2
[1];
190 outVector
[1] = inVector1
[2]*inVector2
[0] - inVector1
[0]*inVector2
[2];
191 outVector
[2] = inVector1
[0]*inVector2
[1] - inVector1
[1]*inVector2
[0];
194 static __inline ALfloat
aluDotproduct(ALfloat
*inVector1
,ALfloat
*inVector2
)
196 return inVector1
[0]*inVector2
[0] + inVector1
[1]*inVector2
[1] +
197 inVector1
[2]*inVector2
[2];
200 static __inline ALvoid
aluNormalize(ALfloat
*inVector
)
202 ALfloat length
, inverse_length
;
204 length
= aluSqrt(aluDotproduct(inVector
, inVector
));
207 inverse_length
= 1.0f
/length
;
208 inVector
[0] *= inverse_length
;
209 inVector
[1] *= inverse_length
;
210 inVector
[2] *= inverse_length
;
214 static __inline ALvoid
aluMatrixVector(ALfloat
*vector
,ALfloat matrix
[3][3])
218 result
[0] = vector
[0]*matrix
[0][0] + vector
[1]*matrix
[1][0] + vector
[2]*matrix
[2][0];
219 result
[1] = vector
[0]*matrix
[0][1] + vector
[1]*matrix
[1][1] + vector
[2]*matrix
[2][1];
220 result
[2] = vector
[0]*matrix
[0][2] + vector
[1]*matrix
[1][2] + vector
[2]*matrix
[2][2];
221 memcpy(vector
, result
, sizeof(result
));
225 static ALvoid
CalcSourceParams(ALCcontext
*ALContext
, ALsource
*ALSource
,
226 ALenum isMono
, ALenum OutputFormat
,
227 ALfloat
*drysend
, ALfloat
*wetsend
,
228 ALfloat
*pitch
, ALfloat
*drygainhf
,
231 ALfloat InnerAngle
,OuterAngle
,Angle
,Distance
,DryMix
,WetMix
=0.0f
;
232 ALfloat Direction
[3],Position
[3],SourceToListener
[3];
233 ALfloat MinVolume
,MaxVolume
,MinDist
,MaxDist
,Rolloff
,OuterGainHF
;
234 ALfloat ConeVolume
,SourceVolume
,PanningFB
,PanningLR
,ListenerGain
;
235 ALfloat U
[3],V
[3],N
[3];
236 ALfloat DopplerFactor
, DopplerVelocity
, flSpeedOfSound
, flMaxVelocity
;
237 ALfloat Matrix
[3][3];
238 ALfloat flAttenuation
;
239 ALfloat RoomAttenuation
;
240 ALfloat MetersPerUnit
;
242 ALfloat DryGainHF
= 1.0f
;
243 ALfloat WetGainHF
= 1.0f
;
246 //Get context properties
247 DopplerFactor
= ALContext
->DopplerFactor
* ALSource
->DopplerFactor
;
248 DopplerVelocity
= ALContext
->DopplerVelocity
;
249 flSpeedOfSound
= ALContext
->flSpeedOfSound
;
251 //Get listener properties
252 ListenerGain
= ALContext
->Listener
.Gain
;
253 MetersPerUnit
= ALContext
->Listener
.MetersPerUnit
;
255 //Get source properties
256 SourceVolume
= ALSource
->flGain
;
257 memcpy(Position
, ALSource
->vPosition
, sizeof(ALSource
->vPosition
));
258 memcpy(Direction
, ALSource
->vOrientation
, sizeof(ALSource
->vOrientation
));
259 MinVolume
= ALSource
->flMinGain
;
260 MaxVolume
= ALSource
->flMaxGain
;
261 MinDist
= ALSource
->flRefDistance
;
262 MaxDist
= ALSource
->flMaxDistance
;
263 Rolloff
= ALSource
->flRollOffFactor
;
264 InnerAngle
= ALSource
->flInnerAngle
;
265 OuterAngle
= ALSource
->flOuterAngle
;
266 OuterGainHF
= ALSource
->OuterGainHF
;
267 RoomRolloff
= ALSource
->RoomRolloffFactor
;
269 //Only apply 3D calculations for mono buffers
270 if(isMono
!= AL_FALSE
)
272 //1. Translate Listener to origin (convert to head relative)
273 // Note that Direction and SourceToListener are *not* transformed.
274 // SourceToListener is used with the source and listener velocities,
275 // which are untransformed, and Direction is used with SourceToListener
276 // for the sound cone
277 if(ALSource
->bHeadRelative
==AL_FALSE
)
279 // Build transform matrix
280 aluCrossproduct(ALContext
->Listener
.Forward
, ALContext
->Listener
.Up
, U
); // Right-vector
281 aluNormalize(U
); // Normalized Right-vector
282 memcpy(V
, ALContext
->Listener
.Up
, sizeof(V
)); // Up-vector
283 aluNormalize(V
); // Normalized Up-vector
284 memcpy(N
, ALContext
->Listener
.Forward
, sizeof(N
)); // At-vector
285 aluNormalize(N
); // Normalized At-vector
286 Matrix
[0][0] = U
[0]; Matrix
[0][1] = V
[0]; Matrix
[0][2] = -N
[0];
287 Matrix
[1][0] = U
[1]; Matrix
[1][1] = V
[1]; Matrix
[1][2] = -N
[1];
288 Matrix
[2][0] = U
[2]; Matrix
[2][1] = V
[2]; Matrix
[2][2] = -N
[2];
290 // Translate source position into listener space
291 Position
[0] -= ALContext
->Listener
.Position
[0];
292 Position
[1] -= ALContext
->Listener
.Position
[1];
293 Position
[2] -= ALContext
->Listener
.Position
[2];
295 SourceToListener
[0] = -Position
[0];
296 SourceToListener
[1] = -Position
[1];
297 SourceToListener
[2] = -Position
[2];
299 // Transform source position and direction into listener space
300 aluMatrixVector(Position
, Matrix
);
304 SourceToListener
[0] = -Position
[0];
305 SourceToListener
[1] = -Position
[1];
306 SourceToListener
[2] = -Position
[2];
308 aluNormalize(SourceToListener
);
309 aluNormalize(Direction
);
311 //2. Calculate distance attenuation
312 Distance
= aluSqrt(aluDotproduct(Position
, Position
));
314 if(ALSource
->Send
[0].Slot
)
316 if(ALSource
->Send
[0].Slot
->effect
.type
== AL_EFFECT_REVERB
)
317 RoomRolloff
+= ALSource
->Send
[0].Slot
->effect
.Reverb
.RoomRolloffFactor
;
320 flAttenuation
= 1.0f
;
321 RoomAttenuation
= 1.0f
;
322 switch (ALContext
->DistanceModel
)
324 case AL_INVERSE_DISTANCE_CLAMPED
:
325 Distance
=__max(Distance
,MinDist
);
326 Distance
=__min(Distance
,MaxDist
);
327 if (MaxDist
< MinDist
)
330 case AL_INVERSE_DISTANCE
:
333 if ((MinDist
+ (Rolloff
* (Distance
- MinDist
))) > 0.0f
)
334 flAttenuation
= MinDist
/ (MinDist
+ (Rolloff
* (Distance
- MinDist
)));
335 if ((MinDist
+ (RoomRolloff
* (Distance
- MinDist
))) > 0.0f
)
336 RoomAttenuation
= MinDist
/ (MinDist
+ (RoomRolloff
* (Distance
- MinDist
)));
340 case AL_LINEAR_DISTANCE_CLAMPED
:
341 Distance
=__max(Distance
,MinDist
);
342 Distance
=__min(Distance
,MaxDist
);
343 if (MaxDist
< MinDist
)
346 case AL_LINEAR_DISTANCE
:
347 Distance
=__min(Distance
,MaxDist
);
348 if (MaxDist
!= MinDist
)
350 flAttenuation
= 1.0f
- (Rolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
351 RoomAttenuation
= 1.0f
- (RoomRolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
355 case AL_EXPONENT_DISTANCE_CLAMPED
:
356 Distance
=__max(Distance
,MinDist
);
357 Distance
=__min(Distance
,MaxDist
);
358 if (MaxDist
< MinDist
)
361 case AL_EXPONENT_DISTANCE
:
362 if ((Distance
> 0.0f
) && (MinDist
> 0.0f
))
364 flAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -Rolloff
);
365 RoomAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -RoomRolloff
);
370 flAttenuation
= 1.0f
;
371 RoomAttenuation
= 1.0f
;
375 // Distance-based air absorption
376 if(ALSource
->AirAbsorptionFactor
> 0.0f
&& ALContext
->DistanceModel
!= AL_NONE
)
378 ALfloat dist
= Distance
-MinDist
;
381 if(dist
< 0.0f
) dist
= 0.0f
;
382 // Absorption calculation is done in dB
383 absorb
= (ALSource
->AirAbsorptionFactor
*AIRABSORBGAINDBHF
) *
384 (Distance
*MetersPerUnit
);
385 // Convert dB to linear gain before applying
386 absorb
= pow(0.5, absorb
/-6.0);
391 // Source Gain + Attenuation and clamp to Min/Max Gain
392 DryMix
= SourceVolume
* flAttenuation
;
393 DryMix
= __min(DryMix
,MaxVolume
);
394 DryMix
= __max(DryMix
,MinVolume
);
396 WetMix
= SourceVolume
* RoomAttenuation
;
397 WetMix
= __min(WetMix
,MaxVolume
);
398 WetMix
= __max(WetMix
,MinVolume
);
400 //3. Apply directional soundcones
401 Angle
= aluAcos(aluDotproduct(Direction
,SourceToListener
)) * 180.0f
/
403 if(Angle
>= InnerAngle
&& Angle
<= OuterAngle
)
405 ALfloat scale
= (Angle
-InnerAngle
) / (OuterAngle
-InnerAngle
);
406 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
)*scale
);
407 DryMix
*= ConeVolume
;
408 if(ALSource
->WetGainAuto
)
409 WetMix
*= ConeVolume
;
410 if(ALSource
->DryGainHFAuto
)
411 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
412 if(ALSource
->WetGainHFAuto
)
413 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
415 else if(Angle
> OuterAngle
)
417 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
));
418 DryMix
*= ConeVolume
;
419 if(ALSource
->WetGainAuto
)
420 WetMix
*= ConeVolume
;
421 if(ALSource
->DryGainHFAuto
)
422 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
423 if(ALSource
->WetGainHFAuto
)
424 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
427 //4. Calculate Velocity
428 if(DopplerFactor
!= 0.0f
)
430 ALfloat flVSS
, flVLS
= 0.0f
;
432 if(ALSource
->bHeadRelative
==AL_FALSE
)
433 flVLS
= aluDotproduct(ALContext
->Listener
.Velocity
, SourceToListener
);
434 flVSS
= aluDotproduct(ALSource
->vVelocity
, SourceToListener
);
436 flMaxVelocity
= (DopplerVelocity
* flSpeedOfSound
) / DopplerFactor
;
438 if (flVSS
>= flMaxVelocity
)
439 flVSS
= (flMaxVelocity
- 1.0f
);
440 else if (flVSS
<= -flMaxVelocity
)
441 flVSS
= -flMaxVelocity
+ 1.0f
;
443 if (flVLS
>= flMaxVelocity
)
444 flVLS
= (flMaxVelocity
- 1.0f
);
445 else if (flVLS
<= -flMaxVelocity
)
446 flVLS
= -flMaxVelocity
+ 1.0f
;
448 pitch
[0] = ALSource
->flPitch
*
449 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVLS
)) /
450 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVSS
));
453 pitch
[0] = ALSource
->flPitch
;
455 if(ALSource
->Send
[0].Slot
)
457 // If the slot's auxilliary send auto is off, the data sent to the
458 // effect slot is the same as the dry path, sans filter effects
459 if(!ALSource
->Send
[0].Slot
->AuxSendAuto
)
462 WetGainHF
= DryGainHF
;
465 // Note that these are really applied by the effect slot. However,
466 // it's easier to handle them here (particularly the lowpass
467 // filter). Applying the gain to the individual sources going to
468 // the effect slot should have the same effect as applying the gain
469 // to the accumulated sources in the effect slot.
470 // vol1*g + vol2*g + ... voln*g = (vol1+vol2+...voln)*g
471 WetMix
*= ALSource
->Send
[0].Slot
->Gain
;
472 if(ALSource
->Send
[0].Slot
->effect
.type
== AL_EFFECT_REVERB
)
474 WetMix
*= ALSource
->Send
[0].Slot
->effect
.Reverb
.Gain
;
475 WetGainHF
*= ALSource
->Send
[0].Slot
->effect
.Reverb
.GainHF
;
476 WetGainHF
*= pow(ALSource
->Send
[0].Slot
->effect
.Reverb
.AirAbsorptionGainHF
,
477 Distance
* MetersPerUnit
);
486 //5. Apply filter gains and filters
487 switch(ALSource
->DirectFilter
.type
)
489 case AL_FILTER_LOWPASS
:
490 DryMix
*= ALSource
->DirectFilter
.Gain
;
491 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
495 switch(ALSource
->Send
[0].WetFilter
.type
)
497 case AL_FILTER_LOWPASS
:
498 WetMix
*= ALSource
->Send
[0].WetFilter
.Gain
;
499 WetGainHF
*= ALSource
->Send
[0].WetFilter
.GainHF
;
503 DryMix
*= ListenerGain
;
504 WetMix
*= ListenerGain
;
506 //6. Convert normalized position into pannings, then into channel volumes
507 aluNormalize(Position
);
508 switch(aluChannelsFromFormat(OutputFormat
))
512 PanningLR
= 0.5f
+ 0.5f
*Position
[0];
513 drysend
[FRONT_LEFT
] = DryMix
* aluSqrt(1.0f
-PanningLR
); //L Direct
514 drysend
[FRONT_RIGHT
] = DryMix
* aluSqrt( PanningLR
); //R Direct
515 drysend
[BACK_LEFT
] = drysend
[FRONT_LEFT
];
516 drysend
[BACK_RIGHT
] = drysend
[FRONT_RIGHT
];
517 drysend
[SIDE_LEFT
] = drysend
[FRONT_LEFT
];
518 drysend
[SIDE_RIGHT
] = drysend
[FRONT_RIGHT
];
519 wetsend
[FRONT_LEFT
] = WetMix
* aluSqrt(1.0f
-PanningLR
); //L Room
520 wetsend
[FRONT_RIGHT
] = WetMix
* aluSqrt( PanningLR
); //R Room
521 wetsend
[BACK_LEFT
] = wetsend
[FRONT_LEFT
];
522 wetsend
[BACK_RIGHT
] = wetsend
[FRONT_RIGHT
];
523 wetsend
[SIDE_LEFT
] = wetsend
[FRONT_LEFT
];
524 wetsend
[SIDE_RIGHT
] = wetsend
[FRONT_RIGHT
];
527 /* TODO: Add center/lfe channel in spatial calculations? */
529 // Apply a scalar so each individual speaker has more weight
530 PanningLR
= 0.5f
+ (0.5f
*Position
[0]*1.41421356f
);
531 PanningLR
= __min(1.0f
, PanningLR
);
532 PanningLR
= __max(0.0f
, PanningLR
);
533 PanningFB
= 0.5f
+ (0.5f
*Position
[2]*1.41421356f
);
534 PanningFB
= __min(1.0f
, PanningFB
);
535 PanningFB
= __max(0.0f
, PanningFB
);
536 drysend
[FRONT_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
537 drysend
[FRONT_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
538 drysend
[BACK_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
539 drysend
[BACK_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
540 drysend
[SIDE_LEFT
] = (drysend
[FRONT_LEFT
] +drysend
[BACK_LEFT
]) * 0.5f
;
541 drysend
[SIDE_RIGHT
] = (drysend
[FRONT_RIGHT
]+drysend
[BACK_RIGHT
]) * 0.5f
;
542 wetsend
[FRONT_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
543 wetsend
[FRONT_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
544 wetsend
[BACK_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
545 wetsend
[BACK_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
546 wetsend
[SIDE_LEFT
] = (wetsend
[FRONT_LEFT
] +wetsend
[BACK_LEFT
]) * 0.5f
;
547 wetsend
[SIDE_RIGHT
] = (wetsend
[FRONT_RIGHT
]+wetsend
[BACK_RIGHT
]) * 0.5f
;
551 PanningFB
= 1.0f
- fabs(Position
[2]*1.15470054f
);
552 PanningFB
= __min(1.0f
, PanningFB
);
553 PanningFB
= __max(0.0f
, PanningFB
);
554 PanningLR
= 0.5f
+ (0.5*Position
[0]*((1.0f
-PanningFB
)*2.0f
));
555 PanningLR
= __min(1.0f
, PanningLR
);
556 PanningLR
= __max(0.0f
, PanningLR
);
557 if(Position
[2] > 0.0f
)
559 drysend
[BACK_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
560 drysend
[BACK_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
561 drysend
[SIDE_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
562 drysend
[SIDE_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
563 drysend
[FRONT_LEFT
] = 0.0f
;
564 drysend
[FRONT_RIGHT
] = 0.0f
;
565 wetsend
[BACK_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
566 wetsend
[BACK_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
567 wetsend
[SIDE_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
568 wetsend
[SIDE_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
569 wetsend
[FRONT_LEFT
] = 0.0f
;
570 wetsend
[FRONT_RIGHT
] = 0.0f
;
574 drysend
[FRONT_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
575 drysend
[FRONT_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
576 drysend
[SIDE_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
577 drysend
[SIDE_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
578 drysend
[BACK_LEFT
] = 0.0f
;
579 drysend
[BACK_RIGHT
] = 0.0f
;
580 wetsend
[FRONT_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
581 wetsend
[FRONT_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
582 wetsend
[SIDE_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
583 wetsend
[SIDE_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
584 wetsend
[BACK_LEFT
] = 0.0f
;
585 wetsend
[BACK_RIGHT
] = 0.0f
;
591 // Update filter coefficients. Calculations based on the I3DL2 spec.
592 cw
= cos(2.0f
*3.141592654f
* LOWPASSFREQCUTOFF
/ ALContext
->Frequency
);
593 // We use four chained one-pole filters, so we need to take the fourth
594 // root of the squared gain, which is the same as the square root of
596 // Be careful with gains < 0.0001, as that causes the coefficient to
597 // head towards 1, which will flatten the signal
598 g
= aluSqrt(__max(DryGainHF
, 0.0001f
));
600 if(g
< 0.9999f
) // 1-epsilon
601 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
602 ALSource
->iirFilter
.coeff
= a
;
604 g
= aluSqrt(__max(WetGainHF
, 0.0001f
));
606 if(g
< 0.9999f
) // 1-epsilon
607 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
608 ALSource
->Send
[0].iirFilter
.coeff
= a
;
610 *drygainhf
= DryGainHF
;
611 *wetgainhf
= WetGainHF
;
615 //1. Multi-channel buffers always play "normal"
616 pitch
[0] = ALSource
->flPitch
;
618 drysend
[FRONT_LEFT
] = SourceVolume
* ListenerGain
;
619 drysend
[FRONT_RIGHT
] = SourceVolume
* ListenerGain
;
620 drysend
[SIDE_LEFT
] = SourceVolume
* ListenerGain
;
621 drysend
[SIDE_RIGHT
] = SourceVolume
* ListenerGain
;
622 drysend
[BACK_LEFT
] = SourceVolume
* ListenerGain
;
623 drysend
[BACK_RIGHT
] = SourceVolume
* ListenerGain
;
624 drysend
[CENTER
] = SourceVolume
* ListenerGain
;
625 drysend
[LFE
] = SourceVolume
* ListenerGain
;
626 wetsend
[FRONT_LEFT
] = 0.0f
;
627 wetsend
[FRONT_RIGHT
] = 0.0f
;
628 wetsend
[SIDE_LEFT
] = 0.0f
;
629 wetsend
[SIDE_RIGHT
] = 0.0f
;
630 wetsend
[BACK_LEFT
] = 0.0f
;
631 wetsend
[BACK_RIGHT
] = 0.0f
;
632 wetsend
[CENTER
] = 0.0f
;
636 *drygainhf
= DryGainHF
;
637 *wetgainhf
= WetGainHF
;
641 ALvoid
aluMixData(ALCcontext
*ALContext
,ALvoid
*buffer
,ALsizei size
,ALenum format
)
643 static float DryBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
644 static float WetBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
645 ALfloat newDrySend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
646 ALfloat newWetSend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
647 ALfloat DryGainHF
= 0.0f
;
648 ALfloat WetGainHF
= 0.0f
;
652 ALfloat dryGainStep
[OUTPUTCHANNELS
];
653 ALfloat wetGainStep
[OUTPUTCHANNELS
];
654 ALuint BlockAlign
,BufferSize
;
655 ALuint DataSize
=0,DataPosInt
=0,DataPosFrac
=0;
656 ALuint Channels
,Frequency
,ulExtraSamples
;
659 ALint fraction
,increment
;
664 ALeffectslot
*ALEffectSlot
;
668 ALbufferlistitem
*BufferListItem
;
670 ALint64 DataSize64
,DataPos64
;
671 FILTER
*DryFilter
, *WetFilter
;
674 SuspendContext(ALContext
);
676 #if defined(HAVE_FESETROUND)
677 fpuState
= fegetround();
678 fesetround(FE_TOWARDZERO
);
679 #elif defined(HAVE__CONTROLFP)
680 fpuState
= _controlfp(0, 0);
681 _controlfp(_RC_CHOP
, _MCW_RC
);
686 //Figure output format variables
687 BlockAlign
= aluChannelsFromFormat(format
);
688 BlockAlign
*= aluBytesFromFormat(format
);
694 SamplesToDo
= min(size
, BUFFERSIZE
);
697 ALEffectSlot
= ALContext
->AuxiliaryEffectSlot
;
698 ALSource
= ALContext
->Source
;
699 rampLength
= ALContext
->Frequency
* MIN_RAMP_LENGTH
/ 1000;
707 rampLength
= max(rampLength
, SamplesToDo
);
709 //Clear mixing buffer
710 memset(DryBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
711 memset(WetBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
717 State
= ALSource
->state
;
719 while(State
== AL_PLAYING
&& j
< SamplesToDo
)
726 if((Buffer
= ALSource
->ulBufferID
))
728 ALBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(Buffer
);
730 Data
= ALBuffer
->data
;
731 Channels
= aluChannelsFromFormat(ALBuffer
->format
);
732 DataSize
= ALBuffer
->size
;
733 Frequency
= ALBuffer
->frequency
;
735 CalcSourceParams(ALContext
, ALSource
,
736 (Channels
==1) ? AL_TRUE
: AL_FALSE
,
737 format
, newDrySend
, newWetSend
, &Pitch
,
738 &DryGainHF
, &WetGainHF
);
740 Pitch
= (Pitch
*Frequency
) / ALContext
->Frequency
;
741 DataSize
/= Channels
* aluBytesFromFormat(ALBuffer
->format
);
744 DataPosInt
= ALSource
->position
;
745 DataPosFrac
= ALSource
->position_fraction
;
746 DryFilter
= &ALSource
->iirFilter
;
747 WetFilter
= &ALSource
->Send
[0].iirFilter
;
748 DrySend
= ALSource
->DryGains
;
749 WetSend
= ALSource
->WetGains
;
751 //Compute the gain steps for each output channel
752 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
754 dryGainStep
[i
] = (newDrySend
[i
]-DrySend
[i
]) / rampLength
;
755 wetGainStep
[i
] = (newWetSend
[i
]-WetSend
[i
]) / rampLength
;
758 //Compute 18.14 fixed point step
759 increment
= (ALint
)(Pitch
*(ALfloat
)(1L<<FRACTIONBITS
));
760 if(increment
> (MAX_PITCH
<<FRACTIONBITS
))
761 increment
= (MAX_PITCH
<<FRACTIONBITS
);
762 else if(increment
<= 0)
763 increment
= (1<<FRACTIONBITS
);
765 //Figure out how many samples we can mix.
766 DataSize64
= DataSize
;
767 DataSize64
<<= FRACTIONBITS
;
768 DataPos64
= DataPosInt
;
769 DataPos64
<<= FRACTIONBITS
;
770 DataPos64
+= DataPosFrac
;
771 BufferSize
= (ALuint
)((DataSize64
-DataPos64
+(increment
-1)) / increment
);
773 BufferListItem
= ALSource
->queue
;
774 for(loop
= 0; loop
< ALSource
->BuffersPlayed
; loop
++)
777 BufferListItem
= BufferListItem
->next
;
781 if (BufferListItem
->next
)
783 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
);
784 if(NextBuf
&& NextBuf
->data
)
786 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
787 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
790 else if (ALSource
->bLooping
)
792 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
);
793 if (NextBuf
&& NextBuf
->data
)
795 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
796 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
800 memset(&Data
[DataSize
*Channels
], 0, (ALBuffer
->padding
*Channels
*2));
802 BufferSize
= min(BufferSize
, (SamplesToDo
-j
));
804 //Actual sample mixing loop
805 Data
+= DataPosInt
*Channels
;
808 k
= DataPosFrac
>>FRACTIONBITS
;
809 fraction
= DataPosFrac
&FRACTIONMASK
;
811 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
813 DrySend
[i
] += dryGainStep
[i
];
814 WetSend
[i
] += wetGainStep
[i
];
819 ALfloat sample
, outsamp
;
820 //First order interpolator
821 sample
= (Data
[k
]*((1<<FRACTIONBITS
)-fraction
) +
822 Data
[k
+1]*fraction
) >> FRACTIONBITS
;
824 //Direct path final mix buffer and panning
825 outsamp
= lpFilter(DryFilter
, sample
);
826 DryBuffer
[j
][FRONT_LEFT
] += outsamp
*DrySend
[FRONT_LEFT
];
827 DryBuffer
[j
][FRONT_RIGHT
] += outsamp
*DrySend
[FRONT_RIGHT
];
828 DryBuffer
[j
][SIDE_LEFT
] += outsamp
*DrySend
[SIDE_LEFT
];
829 DryBuffer
[j
][SIDE_RIGHT
] += outsamp
*DrySend
[SIDE_RIGHT
];
830 DryBuffer
[j
][BACK_LEFT
] += outsamp
*DrySend
[BACK_LEFT
];
831 DryBuffer
[j
][BACK_RIGHT
] += outsamp
*DrySend
[BACK_RIGHT
];
832 //Room path final mix buffer and panning
833 outsamp
= lpFilter(WetFilter
, sample
);
834 WetBuffer
[j
][FRONT_LEFT
] += outsamp
*WetSend
[FRONT_LEFT
];
835 WetBuffer
[j
][FRONT_RIGHT
] += outsamp
*WetSend
[FRONT_RIGHT
];
836 WetBuffer
[j
][SIDE_LEFT
] += outsamp
*WetSend
[SIDE_LEFT
];
837 WetBuffer
[j
][SIDE_RIGHT
] += outsamp
*WetSend
[SIDE_RIGHT
];
838 WetBuffer
[j
][BACK_LEFT
] += outsamp
*WetSend
[BACK_LEFT
];
839 WetBuffer
[j
][BACK_RIGHT
] += outsamp
*WetSend
[BACK_RIGHT
];
843 ALfloat samp1
, samp2
;
844 //First order interpolator (front left)
845 samp1
= (Data
[k
*Channels
]*((1<<FRACTIONBITS
)-fraction
) +
846 Data
[(k
+1)*Channels
]*fraction
) >> FRACTIONBITS
;
847 DryBuffer
[j
][FRONT_LEFT
] += samp1
*DrySend
[FRONT_LEFT
];
848 WetBuffer
[j
][FRONT_LEFT
] += samp1
*WetSend
[FRONT_LEFT
];
849 //First order interpolator (front right)
850 samp2
= (Data
[k
*Channels
+1]*((1<<FRACTIONBITS
)-fraction
) +
851 Data
[(k
+1)*Channels
+1]*fraction
) >> FRACTIONBITS
;
852 DryBuffer
[j
][FRONT_RIGHT
] += samp2
*DrySend
[FRONT_RIGHT
];
853 WetBuffer
[j
][FRONT_RIGHT
] += samp2
*WetSend
[FRONT_RIGHT
];
861 //First order interpolator (center)
862 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
863 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
864 DryBuffer
[j
][CENTER
] += value
*DrySend
[CENTER
];
865 WetBuffer
[j
][CENTER
] += value
*WetSend
[CENTER
];
868 //First order interpolator (lfe)
869 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
870 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
871 DryBuffer
[j
][LFE
] += value
*DrySend
[LFE
];
872 WetBuffer
[j
][LFE
] += value
*WetSend
[LFE
];
875 //First order interpolator (back left)
876 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
877 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
878 DryBuffer
[j
][BACK_LEFT
] += value
*DrySend
[BACK_LEFT
];
879 WetBuffer
[j
][BACK_LEFT
] += value
*WetSend
[BACK_LEFT
];
881 //First order interpolator (back right)
882 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
883 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
884 DryBuffer
[j
][BACK_RIGHT
] += value
*DrySend
[BACK_RIGHT
];
885 WetBuffer
[j
][BACK_RIGHT
] += value
*WetSend
[BACK_RIGHT
];
889 //First order interpolator (side left)
890 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
891 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
892 DryBuffer
[j
][SIDE_LEFT
] += value
*DrySend
[SIDE_LEFT
];
893 WetBuffer
[j
][SIDE_LEFT
] += value
*WetSend
[SIDE_LEFT
];
895 //First order interpolator (side right)
896 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
897 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
898 DryBuffer
[j
][SIDE_RIGHT
] += value
*DrySend
[SIDE_RIGHT
];
899 WetBuffer
[j
][SIDE_RIGHT
] += value
*WetSend
[SIDE_RIGHT
];
903 else if(DuplicateStereo
)
905 //Duplicate stereo channels on the back speakers
906 DryBuffer
[j
][BACK_LEFT
] += samp1
*DrySend
[BACK_LEFT
];
907 WetBuffer
[j
][BACK_LEFT
] += samp1
*WetSend
[BACK_LEFT
];
908 DryBuffer
[j
][BACK_RIGHT
] += samp2
*DrySend
[BACK_RIGHT
];
909 WetBuffer
[j
][BACK_RIGHT
] += samp2
*WetSend
[BACK_RIGHT
];
912 DataPosFrac
+= increment
;
915 DataPosInt
+= (DataPosFrac
>>FRACTIONBITS
);
916 DataPosFrac
= (DataPosFrac
&FRACTIONMASK
);
919 ALSource
->position
= DataPosInt
;
920 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
;
967 ALSource
->state
= AL_PLAYING
;
968 ALSource
->inuse
= AL_TRUE
;
969 ALSource
->play
= AL_TRUE
;
970 ALSource
->BuffersPlayed
= 0;
971 ALSource
->BufferPosition
= 0;
972 ALSource
->lBytesPlayed
= 0;
973 BufferListItem
= ALSource
->queue
;
974 while(BufferListItem
!= NULL
)
976 BufferListItem
->bufferstate
= PENDING
;
977 BufferListItem
= BufferListItem
->next
;
979 ALSource
->ulBufferID
= ALSource
->queue
->buffer
;
981 ALSource
->position
= DataPosInt
-DataSize
;
982 ALSource
->position_fraction
= DataPosFrac
;
989 State
= ALSource
->state
;
992 ALSource
= ALSource
->next
;
995 // effect slot processing
998 if(ALEffectSlot
->effect
.type
== AL_EFFECT_REVERB
)
1000 ALfloat
*DelayBuffer
= ALEffectSlot
->ReverbBuffer
;
1001 ALuint Pos
= ALEffectSlot
->ReverbPos
;
1002 ALuint LatePos
= ALEffectSlot
->ReverbLatePos
;
1003 ALuint ReflectPos
= ALEffectSlot
->ReverbReflectPos
;
1004 ALuint Length
= ALEffectSlot
->ReverbLength
;
1005 ALfloat DecayGain
= ALEffectSlot
->ReverbDecayGain
;
1006 ALfloat DecayHFRatio
= ALEffectSlot
->effect
.Reverb
.DecayHFRatio
;
1007 ALfloat ReflectGain
= ALEffectSlot
->effect
.Reverb
.ReflectionsGain
;
1008 ALfloat LateReverbGain
= ALEffectSlot
->effect
.Reverb
.LateReverbGain
;
1009 ALfloat sample
, lowsample
;
1011 WetFilter
= &ALEffectSlot
->iirFilter
;
1012 for(i
= 0;i
< SamplesToDo
;i
++)
1014 sample
= WetBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][BACK_LEFT
];
1015 sample
+= WetBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][SIDE_RIGHT
]+WetBuffer
[i
][BACK_RIGHT
];
1016 DelayBuffer
[Pos
] = sample
/ 6.0f
;
1018 sample
= DelayBuffer
[ReflectPos
] * ReflectGain
;
1020 DelayBuffer
[LatePos
] *= LateReverbGain
;
1022 Pos
= (Pos
+1) % Length
;
1023 lowsample
= lpFilter(WetFilter
, DelayBuffer
[Pos
]);
1024 lowsample
+= (DelayBuffer
[Pos
]-lowsample
) * DecayHFRatio
;
1026 DelayBuffer
[LatePos
] += lowsample
* DecayGain
;
1028 sample
+= DelayBuffer
[LatePos
];
1030 WetBuffer
[i
][FRONT_LEFT
] = sample
;
1031 WetBuffer
[i
][FRONT_RIGHT
] = sample
;
1032 WetBuffer
[i
][SIDE_LEFT
] = sample
;
1033 WetBuffer
[i
][SIDE_RIGHT
] = sample
;
1034 WetBuffer
[i
][BACK_LEFT
] = sample
;
1035 WetBuffer
[i
][BACK_RIGHT
] = sample
;
1037 LatePos
= (LatePos
+1) % Length
;
1038 ReflectPos
= (ReflectPos
+1) % Length
;
1041 ALEffectSlot
->ReverbPos
= Pos
;
1042 ALEffectSlot
->ReverbLatePos
= LatePos
;
1043 ALEffectSlot
->ReverbReflectPos
= ReflectPos
;
1046 ALEffectSlot
= ALEffectSlot
->next
;
1049 //Post processing loop
1052 case AL_FORMAT_MONO8
:
1053 for(i
= 0;i
< SamplesToDo
;i
++)
1055 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
1056 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1057 buffer
= ((ALubyte
*)buffer
) + 1;
1060 case AL_FORMAT_STEREO8
:
1061 if(ALContext
&& ALContext
->bs2b
)
1063 for(i
= 0;i
< SamplesToDo
;i
++)
1066 samples
[0] = DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
];
1067 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
];
1068 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1069 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(samples
[0])>>8)+128);
1070 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(samples
[1])>>8)+128);
1071 buffer
= ((ALubyte
*)buffer
) + 2;
1076 for(i
= 0;i
< SamplesToDo
;i
++)
1078 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1079 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1080 buffer
= ((ALubyte
*)buffer
) + 2;
1084 case AL_FORMAT_QUAD8
:
1085 for(i
= 0;i
< SamplesToDo
;i
++)
1087 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1088 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1089 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1090 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1091 buffer
= ((ALubyte
*)buffer
) + 4;
1094 case AL_FORMAT_51CHN8
:
1095 for(i
= 0;i
< SamplesToDo
;i
++)
1097 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1098 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1099 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1100 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1101 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1102 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1103 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1105 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1106 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1107 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1108 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1110 buffer
= ((ALubyte
*)buffer
) + 6;
1113 case AL_FORMAT_61CHN8
:
1114 for(i
= 0;i
< SamplesToDo
;i
++)
1116 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1117 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1119 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1120 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1121 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1123 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1124 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1125 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1127 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
])>>8)+128);
1128 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1129 buffer
= ((ALubyte
*)buffer
) + 7;
1132 case AL_FORMAT_71CHN8
:
1133 for(i
= 0;i
< SamplesToDo
;i
++)
1135 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1136 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1138 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1139 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1140 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1141 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1143 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1144 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1145 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1146 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1148 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
])>>8)+128);
1149 ((ALubyte
*)buffer
)[7] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1150 buffer
= ((ALubyte
*)buffer
) + 8;
1154 case AL_FORMAT_MONO16
:
1155 for(i
= 0;i
< SamplesToDo
;i
++)
1157 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
1158 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1159 buffer
= ((ALshort
*)buffer
) + 1;
1162 case AL_FORMAT_STEREO16
:
1163 if(ALContext
&& ALContext
->bs2b
)
1165 for(i
= 0;i
< SamplesToDo
;i
++)
1168 samples
[0] = DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
];
1169 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
];
1170 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1171 ((ALshort
*)buffer
)[0] = aluF2S(samples
[0]);
1172 ((ALshort
*)buffer
)[1] = aluF2S(samples
[1]);
1173 buffer
= ((ALshort
*)buffer
) + 2;
1178 for(i
= 0;i
< SamplesToDo
;i
++)
1180 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1181 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1182 buffer
= ((ALshort
*)buffer
) + 2;
1186 case AL_FORMAT_QUAD16
:
1187 for(i
= 0;i
< SamplesToDo
;i
++)
1189 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1190 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1191 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1192 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1193 buffer
= ((ALshort
*)buffer
) + 4;
1196 case AL_FORMAT_51CHN16
:
1197 for(i
= 0;i
< SamplesToDo
;i
++)
1199 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1200 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1202 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1203 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1204 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1205 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1207 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1208 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1209 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1210 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1212 buffer
= ((ALshort
*)buffer
) + 6;
1215 case AL_FORMAT_61CHN16
:
1216 for(i
= 0;i
< SamplesToDo
;i
++)
1218 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1219 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1221 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1222 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1223 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1225 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1226 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1227 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1229 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
]);
1230 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
]);
1231 buffer
= ((ALshort
*)buffer
) + 7;
1234 case AL_FORMAT_71CHN16
:
1235 for(i
= 0;i
< SamplesToDo
;i
++)
1237 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1238 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1240 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1241 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1242 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1243 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1245 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1246 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1247 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1248 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1250 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
]);
1251 ((ALshort
*)buffer
)[7] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
]);
1252 buffer
= ((ALshort
*)buffer
) + 8;
1260 size
-= SamplesToDo
;
1263 #if defined(HAVE_FESETROUND)
1264 fesetround(fpuState
);
1265 #elif defined(HAVE__CONTROLFP)
1266 _controlfp(fpuState
, 0xfffff);
1269 ProcessContext(ALContext
);