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 float *hist1_ptr
,*hist2_ptr
,*coef_ptr
;
161 ALfloat output
,new_hist
,history1
,history2
;
163 coef_ptr
= iir
->coef
; /* coefficient pointer */
165 hist1_ptr
= iir
->history
; /* first history */
166 hist2_ptr
= hist1_ptr
+ 1; /* next history */
168 /* 1st number of coefficients array is overall input scale factor,
170 output
= input
* (*coef_ptr
++);
172 history1
= *hist1_ptr
; /* history values */
173 history2
= *hist2_ptr
;
175 output
= output
- history1
* (*coef_ptr
++);
176 new_hist
= output
- history2
* (*coef_ptr
++); /* poles */
178 output
= new_hist
+ history1
* (*coef_ptr
++);
179 output
= output
+ history2
* (*coef_ptr
++); /* zeros */
181 *hist2_ptr
++ = *hist1_ptr
;
182 *hist1_ptr
++ = new_hist
;
190 static __inline ALshort
aluF2S(ALfloat Value
)
195 i
= __min( 32767, i
);
196 i
= __max(-32768, i
);
200 static __inline ALvoid
aluCrossproduct(ALfloat
*inVector1
,ALfloat
*inVector2
,ALfloat
*outVector
)
202 outVector
[0] = inVector1
[1]*inVector2
[2] - inVector1
[2]*inVector2
[1];
203 outVector
[1] = inVector1
[2]*inVector2
[0] - inVector1
[0]*inVector2
[2];
204 outVector
[2] = inVector1
[0]*inVector2
[1] - inVector1
[1]*inVector2
[0];
207 static __inline ALfloat
aluDotproduct(ALfloat
*inVector1
,ALfloat
*inVector2
)
209 return inVector1
[0]*inVector2
[0] + inVector1
[1]*inVector2
[1] +
210 inVector1
[2]*inVector2
[2];
213 static __inline ALvoid
aluNormalize(ALfloat
*inVector
)
215 ALfloat length
, inverse_length
;
217 length
= aluSqrt(aluDotproduct(inVector
, inVector
));
220 inverse_length
= 1.0f
/length
;
221 inVector
[0] *= inverse_length
;
222 inVector
[1] *= inverse_length
;
223 inVector
[2] *= inverse_length
;
227 static __inline ALvoid
aluMatrixVector(ALfloat
*vector
,ALfloat matrix
[3][3])
231 result
[0] = vector
[0]*matrix
[0][0] + vector
[1]*matrix
[1][0] + vector
[2]*matrix
[2][0];
232 result
[1] = vector
[0]*matrix
[0][1] + vector
[1]*matrix
[1][1] + vector
[2]*matrix
[2][1];
233 result
[2] = vector
[0]*matrix
[0][2] + vector
[1]*matrix
[1][2] + vector
[2]*matrix
[2][2];
234 memcpy(vector
, result
, sizeof(result
));
237 static __inline ALfloat
aluComputeSample(ALfloat GainHF
, ALfloat sample
, ALfloat LowSample
)
239 return LowSample
+ ((sample
- LowSample
) * GainHF
);
242 static ALvoid
CalcSourceParams(ALCcontext
*ALContext
, ALsource
*ALSource
,
243 ALenum isMono
, ALenum OutputFormat
,
244 ALfloat
*drysend
, ALfloat
*wetsend
,
245 ALfloat
*pitch
, ALfloat
*drygainhf
,
248 ALfloat InnerAngle
,OuterAngle
,Angle
,Distance
,DryMix
,WetMix
=0.0f
;
249 ALfloat Direction
[3],Position
[3],SourceToListener
[3];
250 ALfloat MinVolume
,MaxVolume
,MinDist
,MaxDist
,Rolloff
,OuterGainHF
;
251 ALfloat ConeVolume
,SourceVolume
,PanningFB
,PanningLR
,ListenerGain
;
252 ALfloat U
[3],V
[3],N
[3];
253 ALfloat DopplerFactor
, DopplerVelocity
, flSpeedOfSound
, flMaxVelocity
;
254 ALfloat Matrix
[3][3];
255 ALfloat flAttenuation
;
256 ALfloat RoomAttenuation
;
257 ALfloat MetersPerUnit
;
259 ALfloat DryGainHF
= 1.0f
;
260 ALfloat WetGainHF
= 1.0f
;
262 //Get context properties
263 DopplerFactor
= ALContext
->DopplerFactor
* ALSource
->DopplerFactor
;
264 DopplerVelocity
= ALContext
->DopplerVelocity
;
265 flSpeedOfSound
= ALContext
->flSpeedOfSound
;
267 //Get listener properties
268 ListenerGain
= ALContext
->Listener
.Gain
;
269 MetersPerUnit
= ALContext
->Listener
.MetersPerUnit
;
271 //Get source properties
272 SourceVolume
= ALSource
->flGain
;
273 memcpy(Position
, ALSource
->vPosition
, sizeof(ALSource
->vPosition
));
274 memcpy(Direction
, ALSource
->vOrientation
, sizeof(ALSource
->vOrientation
));
275 MinVolume
= ALSource
->flMinGain
;
276 MaxVolume
= ALSource
->flMaxGain
;
277 MinDist
= ALSource
->flRefDistance
;
278 MaxDist
= ALSource
->flMaxDistance
;
279 Rolloff
= ALSource
->flRollOffFactor
;
280 InnerAngle
= ALSource
->flInnerAngle
;
281 OuterAngle
= ALSource
->flOuterAngle
;
282 OuterGainHF
= ALSource
->OuterGainHF
;
283 RoomRolloff
= ALSource
->RoomRolloffFactor
;
285 //Only apply 3D calculations for mono buffers
286 if(isMono
!= AL_FALSE
)
288 //1. Translate Listener to origin (convert to head relative)
289 // Note that Direction and SourceToListener are *not* transformed.
290 // SourceToListener is used with the source and listener velocities,
291 // which are untransformed, and Direction is used with SourceToListener
292 // for the sound cone
293 if(ALSource
->bHeadRelative
==AL_FALSE
)
295 // Build transform matrix
296 aluCrossproduct(ALContext
->Listener
.Forward
, ALContext
->Listener
.Up
, U
); // Right-vector
297 aluNormalize(U
); // Normalized Right-vector
298 memcpy(V
, ALContext
->Listener
.Up
, sizeof(V
)); // Up-vector
299 aluNormalize(V
); // Normalized Up-vector
300 memcpy(N
, ALContext
->Listener
.Forward
, sizeof(N
)); // At-vector
301 aluNormalize(N
); // Normalized At-vector
302 Matrix
[0][0] = U
[0]; Matrix
[0][1] = V
[0]; Matrix
[0][2] = -N
[0];
303 Matrix
[1][0] = U
[1]; Matrix
[1][1] = V
[1]; Matrix
[1][2] = -N
[1];
304 Matrix
[2][0] = U
[2]; Matrix
[2][1] = V
[2]; Matrix
[2][2] = -N
[2];
306 // Translate source position into listener space
307 Position
[0] -= ALContext
->Listener
.Position
[0];
308 Position
[1] -= ALContext
->Listener
.Position
[1];
309 Position
[2] -= ALContext
->Listener
.Position
[2];
311 SourceToListener
[0] = -Position
[0];
312 SourceToListener
[1] = -Position
[1];
313 SourceToListener
[2] = -Position
[2];
315 // Transform source position and direction into listener space
316 aluMatrixVector(Position
, Matrix
);
320 SourceToListener
[0] = -Position
[0];
321 SourceToListener
[1] = -Position
[1];
322 SourceToListener
[2] = -Position
[2];
324 aluNormalize(SourceToListener
);
325 aluNormalize(Direction
);
327 //2. Calculate distance attenuation
328 Distance
= aluSqrt(aluDotproduct(Position
, Position
));
330 if(ALSource
->Send
[0].Slot
&& !ALSource
->Send
[0].Slot
->AuxSendAuto
)
332 if(ALSource
->Send
[0].Slot
->effect
.type
== AL_EFFECT_REVERB
)
333 RoomRolloff
+= ALSource
->Send
[0].Slot
->effect
.Reverb
.RoomRolloffFactor
;
336 flAttenuation
= 1.0f
;
337 RoomAttenuation
= 1.0f
;
338 switch (ALContext
->DistanceModel
)
340 case AL_INVERSE_DISTANCE_CLAMPED
:
341 Distance
=__max(Distance
,MinDist
);
342 Distance
=__min(Distance
,MaxDist
);
343 if (MaxDist
< MinDist
)
346 case AL_INVERSE_DISTANCE
:
349 if ((MinDist
+ (Rolloff
* (Distance
- MinDist
))) > 0.0f
)
350 flAttenuation
= MinDist
/ (MinDist
+ (Rolloff
* (Distance
- MinDist
)));
351 if ((MinDist
+ (RoomRolloff
* (Distance
- MinDist
))) > 0.0f
)
352 RoomAttenuation
= MinDist
/ (MinDist
+ (RoomRolloff
* (Distance
- MinDist
)));
356 case AL_LINEAR_DISTANCE_CLAMPED
:
357 Distance
=__max(Distance
,MinDist
);
358 Distance
=__min(Distance
,MaxDist
);
359 if (MaxDist
< MinDist
)
362 case AL_LINEAR_DISTANCE
:
363 Distance
=__min(Distance
,MaxDist
);
364 if (MaxDist
!= MinDist
)
366 flAttenuation
= 1.0f
- (Rolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
367 RoomAttenuation
= 1.0f
- (RoomRolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
371 case AL_EXPONENT_DISTANCE_CLAMPED
:
372 Distance
=__max(Distance
,MinDist
);
373 Distance
=__min(Distance
,MaxDist
);
374 if (MaxDist
< MinDist
)
377 case AL_EXPONENT_DISTANCE
:
378 if ((Distance
> 0.0f
) && (MinDist
> 0.0f
))
380 flAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -Rolloff
);
381 RoomAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -RoomRolloff
);
387 flAttenuation
= 1.0f
;
388 RoomAttenuation
= 1.0f
;
392 // Source Gain + Attenuation and clamp to Min/Max Gain
393 DryMix
= SourceVolume
* flAttenuation
;
394 DryMix
= __min(DryMix
,MaxVolume
);
395 DryMix
= __max(DryMix
,MinVolume
);
397 WetMix
= SourceVolume
* (ALSource
->WetGainAuto
?
398 RoomAttenuation
: 1.0f
);
399 WetMix
= __min(WetMix
,MaxVolume
);
400 WetMix
= __max(WetMix
,MinVolume
);
402 //3. Apply directional soundcones
403 Angle
= aluAcos(aluDotproduct(Direction
,SourceToListener
)) * 180.0f
/
405 if(Angle
>= InnerAngle
&& Angle
<= OuterAngle
)
407 ALfloat scale
= (Angle
-InnerAngle
) / (OuterAngle
-InnerAngle
);
408 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
)*scale
);
409 if(ALSource
->WetGainAuto
)
410 WetMix
*= ConeVolume
;
411 if(ALSource
->DryGainHFAuto
)
412 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
413 if(ALSource
->WetGainHFAuto
)
414 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
416 else if(Angle
> OuterAngle
)
418 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
));
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
));
429 //4. Calculate Velocity
430 if(DopplerFactor
!= 0.0f
)
432 ALfloat flVSS
, flVLS
= 0.0f
;
434 if(ALSource
->bHeadRelative
==AL_FALSE
)
435 flVLS
= aluDotproduct(ALContext
->Listener
.Velocity
, SourceToListener
);
436 flVSS
= aluDotproduct(ALSource
->vVelocity
, SourceToListener
);
438 flMaxVelocity
= (DopplerVelocity
* flSpeedOfSound
) / DopplerFactor
;
440 if (flVSS
>= flMaxVelocity
)
441 flVSS
= (flMaxVelocity
- 1.0f
);
442 else if (flVSS
<= -flMaxVelocity
)
443 flVSS
= -flMaxVelocity
+ 1.0f
;
445 if (flVLS
>= flMaxVelocity
)
446 flVLS
= (flMaxVelocity
- 1.0f
);
447 else if (flVLS
<= -flMaxVelocity
)
448 flVLS
= -flMaxVelocity
+ 1.0f
;
450 pitch
[0] = ALSource
->flPitch
*
451 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVLS
)) /
452 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVSS
));
455 pitch
[0] = ALSource
->flPitch
;
457 //5. Apply filter gains and filters
458 switch(ALSource
->DirectFilter
.type
)
460 case AL_FILTER_LOWPASS
:
461 DryMix
*= ALSource
->DirectFilter
.Gain
;
462 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
466 switch(ALSource
->Send
[0].WetFilter
.type
)
468 case AL_FILTER_LOWPASS
:
469 WetMix
*= ALSource
->Send
[0].WetFilter
.Gain
;
470 WetGainHF
*= ALSource
->Send
[0].WetFilter
.GainHF
;
474 if(ALSource
->AirAbsorptionFactor
> 0.0f
)
475 DryGainHF
*= pow(ALSource
->AirAbsorptionFactor
* AIRABSORBGAINHF
,
476 Distance
* MetersPerUnit
);
478 if(ALSource
->Send
[0].Slot
)
480 WetMix
*= ALSource
->Send
[0].Slot
->Gain
;
482 if(ALSource
->Send
[0].Slot
->effect
.type
== AL_EFFECT_REVERB
)
484 WetMix
*= ALSource
->Send
[0].Slot
->effect
.Reverb
.Gain
;
485 WetGainHF
*= ALSource
->Send
[0].Slot
->effect
.Reverb
.GainHF
;
486 WetGainHF
*= pow(ALSource
->Send
[0].Slot
->effect
.Reverb
.AirAbsorptionGainHF
,
487 Distance
* MetersPerUnit
);
496 DryMix
*= ListenerGain
* ConeVolume
;
497 WetMix
*= ListenerGain
;
499 //6. Convert normalized position into pannings, then into channel volumes
500 aluNormalize(Position
);
501 switch(aluChannelsFromFormat(OutputFormat
))
505 PanningLR
= 0.5f
+ 0.5f
*Position
[0];
506 drysend
[FRONT_LEFT
] = DryMix
* aluSqrt(1.0f
-PanningLR
); //L Direct
507 drysend
[FRONT_RIGHT
] = DryMix
* aluSqrt( PanningLR
); //R Direct
508 drysend
[BACK_LEFT
] = drysend
[FRONT_LEFT
];
509 drysend
[BACK_RIGHT
] = drysend
[FRONT_RIGHT
];
510 drysend
[SIDE_LEFT
] = drysend
[FRONT_LEFT
];
511 drysend
[SIDE_RIGHT
] = drysend
[FRONT_RIGHT
];
512 wetsend
[FRONT_LEFT
] = WetMix
* aluSqrt(1.0f
-PanningLR
); //L Room
513 wetsend
[FRONT_RIGHT
] = WetMix
* aluSqrt( PanningLR
); //R Room
514 wetsend
[BACK_LEFT
] = wetsend
[FRONT_LEFT
];
515 wetsend
[BACK_RIGHT
] = wetsend
[FRONT_RIGHT
];
516 wetsend
[SIDE_LEFT
] = wetsend
[FRONT_LEFT
];
517 wetsend
[SIDE_RIGHT
] = wetsend
[FRONT_RIGHT
];
520 /* TODO: Add center/lfe channel in spatial calculations? */
522 // Apply a scalar so each individual speaker has more weight
523 PanningLR
= 0.5f
+ (0.5f
*Position
[0]*1.41421356f
);
524 PanningLR
= __min(1.0f
, PanningLR
);
525 PanningLR
= __max(0.0f
, PanningLR
);
526 PanningFB
= 0.5f
+ (0.5f
*Position
[2]*1.41421356f
);
527 PanningFB
= __min(1.0f
, PanningFB
);
528 PanningFB
= __max(0.0f
, PanningFB
);
529 drysend
[FRONT_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
530 drysend
[FRONT_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
531 drysend
[BACK_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
532 drysend
[BACK_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
533 drysend
[SIDE_LEFT
] = (drysend
[FRONT_LEFT
] +drysend
[BACK_LEFT
]) * 0.5f
;
534 drysend
[SIDE_RIGHT
] = (drysend
[FRONT_RIGHT
]+drysend
[BACK_RIGHT
]) * 0.5f
;
535 wetsend
[FRONT_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
536 wetsend
[FRONT_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
537 wetsend
[BACK_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
538 wetsend
[BACK_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
539 wetsend
[SIDE_LEFT
] = (wetsend
[FRONT_LEFT
] +wetsend
[BACK_LEFT
]) * 0.5f
;
540 wetsend
[SIDE_RIGHT
] = (wetsend
[FRONT_RIGHT
]+wetsend
[BACK_RIGHT
]) * 0.5f
;
544 PanningFB
= 1.0f
- fabs(Position
[2]*1.15470054f
);
545 PanningFB
= __min(1.0f
, PanningFB
);
546 PanningFB
= __max(0.0f
, PanningFB
);
547 PanningLR
= 0.5f
+ (0.5*Position
[0]*((1.0f
-PanningFB
)*2.0f
));
548 PanningLR
= __min(1.0f
, PanningLR
);
549 PanningLR
= __max(0.0f
, PanningLR
);
550 if(Position
[2] > 0.0f
)
552 drysend
[BACK_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
553 drysend
[BACK_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
554 drysend
[SIDE_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
555 drysend
[SIDE_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
556 drysend
[FRONT_LEFT
] = 0.0f
;
557 drysend
[FRONT_RIGHT
] = 0.0f
;
558 wetsend
[BACK_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
559 wetsend
[BACK_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
560 wetsend
[SIDE_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
561 wetsend
[SIDE_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
562 wetsend
[FRONT_LEFT
] = 0.0f
;
563 wetsend
[FRONT_RIGHT
] = 0.0f
;
567 drysend
[FRONT_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
568 drysend
[FRONT_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
569 drysend
[SIDE_LEFT
] = DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
570 drysend
[SIDE_RIGHT
] = DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
571 drysend
[BACK_LEFT
] = 0.0f
;
572 drysend
[BACK_RIGHT
] = 0.0f
;
573 wetsend
[FRONT_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
574 wetsend
[FRONT_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
575 wetsend
[SIDE_LEFT
] = WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
576 wetsend
[SIDE_RIGHT
] = WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
577 wetsend
[BACK_LEFT
] = 0.0f
;
578 wetsend
[BACK_RIGHT
] = 0.0f
;
584 *drygainhf
= DryGainHF
;
585 *wetgainhf
= WetGainHF
;
589 //1. Multi-channel buffers always play "normal"
590 pitch
[0] = ALSource
->flPitch
;
592 drysend
[FRONT_LEFT
] = SourceVolume
* ListenerGain
;
593 drysend
[FRONT_RIGHT
] = SourceVolume
* ListenerGain
;
594 drysend
[SIDE_LEFT
] = SourceVolume
* ListenerGain
;
595 drysend
[SIDE_RIGHT
] = SourceVolume
* ListenerGain
;
596 drysend
[BACK_LEFT
] = SourceVolume
* ListenerGain
;
597 drysend
[BACK_RIGHT
] = SourceVolume
* ListenerGain
;
598 drysend
[CENTER
] = SourceVolume
* ListenerGain
;
599 drysend
[LFE
] = SourceVolume
* ListenerGain
;
600 wetsend
[FRONT_LEFT
] = 0.0f
;
601 wetsend
[FRONT_RIGHT
] = 0.0f
;
602 wetsend
[SIDE_LEFT
] = 0.0f
;
603 wetsend
[SIDE_RIGHT
] = 0.0f
;
604 wetsend
[BACK_LEFT
] = 0.0f
;
605 wetsend
[BACK_RIGHT
] = 0.0f
;
606 wetsend
[CENTER
] = 0.0f
;
610 *drygainhf
= DryGainHF
;
611 *wetgainhf
= WetGainHF
;
615 ALvoid
aluMixData(ALCcontext
*ALContext
,ALvoid
*buffer
,ALsizei size
,ALenum format
)
617 static float DryBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
618 static float WetBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
619 ALfloat newDrySend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
620 ALfloat newWetSend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
621 ALfloat DryGainHF
= 0.0f
;
622 ALfloat WetGainHF
= 0.0f
;
626 ALfloat dryGainStep
[OUTPUTCHANNELS
];
627 ALfloat wetGainStep
[OUTPUTCHANNELS
];
628 ALfloat dryGainHFStep
;
629 ALfloat wetGainHFStep
;
630 ALuint BlockAlign
,BufferSize
;
631 ALuint DataSize
=0,DataPosInt
=0,DataPosFrac
=0;
632 ALuint Channels
,Frequency
,ulExtraSamples
;
635 ALint fraction
,increment
;
640 ALeffectslot
*ALEffectSlot
;
644 ALbufferlistitem
*BufferListItem
;
646 ALint64 DataSize64
,DataPos64
;
650 SuspendContext(ALContext
);
652 #if defined(HAVE_FESETROUND)
653 fpuState
= fegetround();
654 fesetround(FE_TOWARDZERO
);
655 #elif defined(HAVE__CONTROLFP)
656 fpuState
= _controlfp(0, 0);
657 _controlfp(_RC_CHOP
, _MCW_RC
);
662 //Figure output format variables
663 BlockAlign
= aluChannelsFromFormat(format
);
664 BlockAlign
*= aluBytesFromFormat(format
);
670 SamplesToDo
= min(size
, BUFFERSIZE
);
673 ALEffectSlot
= ALContext
->AuxiliaryEffectSlot
;
674 ALSource
= ALContext
->Source
;
675 rampLength
= ALContext
->Frequency
* MIN_RAMP_LENGTH
/ 1000;
683 rampLength
= max(rampLength
, SamplesToDo
);
685 //Clear mixing buffer
686 memset(DryBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
687 memset(WetBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
693 State
= ALSource
->state
;
695 while(State
== AL_PLAYING
&& j
< SamplesToDo
)
702 if((Buffer
= ALSource
->ulBufferID
))
704 ALBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(Buffer
);
706 Data
= ALBuffer
->data
;
707 Channels
= aluChannelsFromFormat(ALBuffer
->format
);
708 DataSize
= ALBuffer
->size
;
709 Frequency
= ALBuffer
->frequency
;
711 CalcSourceParams(ALContext
, ALSource
,
712 (Channels
==1) ? AL_TRUE
: AL_FALSE
,
713 format
, newDrySend
, newWetSend
, &Pitch
,
714 &DryGainHF
, &WetGainHF
);
716 Pitch
= (Pitch
*Frequency
) / ALContext
->Frequency
;
717 DataSize
/= Channels
* aluBytesFromFormat(ALBuffer
->format
);
720 DataPosInt
= ALSource
->position
;
721 DataPosFrac
= ALSource
->position_fraction
;
722 Filter
= &ALSource
->iirFilter
;
723 DrySend
= ALSource
->DryGains
;
724 WetSend
= ALSource
->WetGains
;
726 //Compute the gain steps for each output channel
727 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
729 dryGainStep
[i
] = (newDrySend
[i
]-DrySend
[i
]) / rampLength
;
730 wetGainStep
[i
] = (newWetSend
[i
]-WetSend
[i
]) / rampLength
;
732 dryGainHFStep
= (DryGainHF
-ALSource
->DryGainHF
) / rampLength
;
733 wetGainHFStep
= (WetGainHF
-ALSource
->WetGainHF
) / rampLength
;
734 DryGainHF
= ALSource
->DryGainHF
;
735 WetGainHF
= ALSource
->WetGainHF
;
737 //Compute 18.14 fixed point step
738 increment
= (ALint
)(Pitch
*(ALfloat
)(1L<<FRACTIONBITS
));
739 if(increment
> (MAX_PITCH
<<FRACTIONBITS
))
740 increment
= (MAX_PITCH
<<FRACTIONBITS
);
741 else if(increment
<= 0)
742 increment
= (1<<FRACTIONBITS
);
744 //Figure out how many samples we can mix.
745 DataSize64
= DataSize
;
746 DataSize64
<<= FRACTIONBITS
;
747 DataPos64
= DataPosInt
;
748 DataPos64
<<= FRACTIONBITS
;
749 DataPos64
+= DataPosFrac
;
750 BufferSize
= (ALuint
)((DataSize64
-DataPos64
+(increment
-1)) / increment
);
752 BufferListItem
= ALSource
->queue
;
753 for(loop
= 0; loop
< ALSource
->BuffersPlayed
; loop
++)
756 BufferListItem
= BufferListItem
->next
;
760 if (BufferListItem
->next
)
762 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
);
763 if(NextBuf
&& NextBuf
->data
)
765 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
766 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
769 else if (ALSource
->bLooping
)
771 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
);
772 if (NextBuf
&& NextBuf
->data
)
774 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
775 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
779 memset(&Data
[DataSize
*Channels
], 0, (ALBuffer
->padding
*Channels
*2));
781 BufferSize
= min(BufferSize
, (SamplesToDo
-j
));
783 //Actual sample mixing loop
784 Data
+= DataPosInt
*Channels
;
787 k
= DataPosFrac
>>FRACTIONBITS
;
788 fraction
= DataPosFrac
&FRACTIONMASK
;
790 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
792 DrySend
[i
] += dryGainStep
[i
];
793 WetSend
[i
] += wetGainStep
[i
];
795 DryGainHF
+= dryGainHFStep
;
796 WetGainHF
+= wetGainHFStep
;
800 ALfloat sample
, lowsamp
, outsamp
;
801 //First order interpolator
802 sample
= (Data
[k
]*((1<<FRACTIONBITS
)-fraction
) +
803 Data
[k
+1]*fraction
) >> FRACTIONBITS
;
804 lowsamp
= lpFilter(Filter
, sample
);
806 //Direct path final mix buffer and panning
807 outsamp
= aluComputeSample(DryGainHF
, sample
, lowsamp
);
808 DryBuffer
[j
][FRONT_LEFT
] += outsamp
*DrySend
[FRONT_LEFT
];
809 DryBuffer
[j
][FRONT_RIGHT
] += outsamp
*DrySend
[FRONT_RIGHT
];
810 DryBuffer
[j
][SIDE_LEFT
] += outsamp
*DrySend
[SIDE_LEFT
];
811 DryBuffer
[j
][SIDE_RIGHT
] += outsamp
*DrySend
[SIDE_RIGHT
];
812 DryBuffer
[j
][BACK_LEFT
] += outsamp
*DrySend
[BACK_LEFT
];
813 DryBuffer
[j
][BACK_RIGHT
] += outsamp
*DrySend
[BACK_RIGHT
];
814 //Room path final mix buffer and panning
815 outsamp
= aluComputeSample(WetGainHF
, sample
, lowsamp
);
816 WetBuffer
[j
][FRONT_LEFT
] += outsamp
*WetSend
[FRONT_LEFT
];
817 WetBuffer
[j
][FRONT_RIGHT
] += outsamp
*WetSend
[FRONT_RIGHT
];
818 WetBuffer
[j
][SIDE_LEFT
] += outsamp
*WetSend
[SIDE_LEFT
];
819 WetBuffer
[j
][SIDE_RIGHT
] += outsamp
*WetSend
[SIDE_RIGHT
];
820 WetBuffer
[j
][BACK_LEFT
] += outsamp
*WetSend
[BACK_LEFT
];
821 WetBuffer
[j
][BACK_RIGHT
] += outsamp
*WetSend
[BACK_RIGHT
];
825 ALfloat samp1
, samp2
;
826 //First order interpolator (front left)
827 samp1
= (Data
[k
*Channels
]*((1<<FRACTIONBITS
)-fraction
) +
828 Data
[(k
+1)*Channels
]*fraction
) >> FRACTIONBITS
;
829 DryBuffer
[j
][FRONT_LEFT
] += samp1
*DrySend
[FRONT_LEFT
];
830 WetBuffer
[j
][FRONT_LEFT
] += samp1
*WetSend
[FRONT_LEFT
];
831 //First order interpolator (front right)
832 samp2
= (Data
[k
*Channels
+1]*((1<<FRACTIONBITS
)-fraction
) +
833 Data
[(k
+1)*Channels
+1]*fraction
) >> FRACTIONBITS
;
834 DryBuffer
[j
][FRONT_RIGHT
] += samp2
*DrySend
[FRONT_RIGHT
];
835 WetBuffer
[j
][FRONT_RIGHT
] += samp2
*WetSend
[FRONT_RIGHT
];
843 //First order interpolator (center)
844 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
845 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
846 DryBuffer
[j
][CENTER
] += value
*DrySend
[CENTER
];
847 WetBuffer
[j
][CENTER
] += value
*WetSend
[CENTER
];
850 //First order interpolator (lfe)
851 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
852 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
853 DryBuffer
[j
][LFE
] += value
*DrySend
[LFE
];
854 WetBuffer
[j
][LFE
] += value
*WetSend
[LFE
];
857 //First order interpolator (back left)
858 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
859 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
860 DryBuffer
[j
][BACK_LEFT
] += value
*DrySend
[BACK_LEFT
];
861 WetBuffer
[j
][BACK_LEFT
] += value
*WetSend
[BACK_LEFT
];
863 //First order interpolator (back right)
864 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
865 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
866 DryBuffer
[j
][BACK_RIGHT
] += value
*DrySend
[BACK_RIGHT
];
867 WetBuffer
[j
][BACK_RIGHT
] += value
*WetSend
[BACK_RIGHT
];
871 //First order interpolator (side left)
872 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
873 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
874 DryBuffer
[j
][SIDE_LEFT
] += value
*DrySend
[SIDE_LEFT
];
875 WetBuffer
[j
][SIDE_LEFT
] += value
*WetSend
[SIDE_LEFT
];
877 //First order interpolator (side right)
878 value
= (Data
[k
*Channels
+i
]*((1<<FRACTIONBITS
)-fraction
) +
879 Data
[(k
+1)*Channels
+i
]*fraction
) >> FRACTIONBITS
;
880 DryBuffer
[j
][SIDE_RIGHT
] += value
*DrySend
[SIDE_RIGHT
];
881 WetBuffer
[j
][SIDE_RIGHT
] += value
*WetSend
[SIDE_RIGHT
];
885 else if(DuplicateStereo
)
887 //Duplicate stereo channels on the back speakers
888 DryBuffer
[j
][BACK_LEFT
] += samp1
*DrySend
[BACK_LEFT
];
889 WetBuffer
[j
][BACK_LEFT
] += samp1
*WetSend
[BACK_LEFT
];
890 DryBuffer
[j
][BACK_RIGHT
] += samp2
*DrySend
[BACK_RIGHT
];
891 WetBuffer
[j
][BACK_RIGHT
] += samp2
*WetSend
[BACK_RIGHT
];
894 DataPosFrac
+= increment
;
897 DataPosInt
+= (DataPosFrac
>>FRACTIONBITS
);
898 DataPosFrac
= (DataPosFrac
&FRACTIONMASK
);
901 ALSource
->position
= DataPosInt
;
902 ALSource
->position_fraction
= DataPosFrac
;
903 ALSource
->DryGainHF
= DryGainHF
;
904 ALSource
->WetGainHF
= WetGainHF
;
907 //Handle looping sources
908 if(!Buffer
|| DataPosInt
>= DataSize
)
913 Looping
= ALSource
->bLooping
;
914 if(ALSource
->BuffersPlayed
< (ALSource
->BuffersInQueue
-1))
916 BufferListItem
= ALSource
->queue
;
917 for(loop
= 0; loop
<= ALSource
->BuffersPlayed
; loop
++)
922 BufferListItem
->bufferstate
= PROCESSED
;
923 BufferListItem
= BufferListItem
->next
;
927 ALSource
->ulBufferID
= BufferListItem
->buffer
;
928 ALSource
->position
= DataPosInt
-DataSize
;
929 ALSource
->position_fraction
= DataPosFrac
;
930 ALSource
->BuffersPlayed
++;
937 ALSource
->state
= AL_STOPPED
;
938 ALSource
->inuse
= AL_FALSE
;
939 ALSource
->BuffersPlayed
= ALSource
->BuffersInQueue
;
940 BufferListItem
= ALSource
->queue
;
941 while(BufferListItem
!= NULL
)
943 BufferListItem
->bufferstate
= PROCESSED
;
944 BufferListItem
= BufferListItem
->next
;
951 ALSource
->state
= AL_PLAYING
;
952 ALSource
->inuse
= AL_TRUE
;
953 ALSource
->play
= AL_TRUE
;
954 ALSource
->BuffersPlayed
= 0;
955 ALSource
->BufferPosition
= 0;
956 ALSource
->lBytesPlayed
= 0;
957 BufferListItem
= ALSource
->queue
;
958 while(BufferListItem
!= NULL
)
960 BufferListItem
->bufferstate
= PENDING
;
961 BufferListItem
= BufferListItem
->next
;
963 ALSource
->ulBufferID
= ALSource
->queue
->buffer
;
965 ALSource
->position
= DataPosInt
-DataSize
;
966 ALSource
->position_fraction
= DataPosFrac
;
973 State
= ALSource
->state
;
976 ALSource
= ALSource
->next
;
979 // effect slot processing
982 if(ALEffectSlot
->effect
.type
== AL_EFFECT_REVERB
)
984 ALfloat
*DelayBuffer
= ALEffectSlot
->ReverbBuffer
;
985 ALuint Pos
= ALEffectSlot
->ReverbPos
;
986 ALuint LatePos
= ALEffectSlot
->ReverbLatePos
;
987 ALuint ReflectPos
= ALEffectSlot
->ReverbReflectPos
;
988 ALuint Length
= ALEffectSlot
->ReverbLength
;
989 ALfloat DecayGain
= ALEffectSlot
->ReverbDecayGain
;
990 ALfloat DecayHFRatio
= ALEffectSlot
->effect
.Reverb
.DecayHFRatio
;
991 ALfloat ReflectGain
= ALEffectSlot
->effect
.Reverb
.ReflectionsGain
;
992 ALfloat LateReverbGain
= ALEffectSlot
->effect
.Reverb
.LateReverbGain
;
993 ALfloat sample
, lowsample
;
995 Filter
= &ALEffectSlot
->iirFilter
;
996 for(i
= 0;i
< SamplesToDo
;i
++)
998 sample
= WetBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][BACK_LEFT
];
999 sample
+= WetBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][SIDE_RIGHT
]+WetBuffer
[i
][BACK_RIGHT
];
1000 DelayBuffer
[Pos
] = sample
/ 6.0f
;
1002 sample
= DelayBuffer
[ReflectPos
] * ReflectGain
;
1004 DelayBuffer
[LatePos
] *= LateReverbGain
;
1006 Pos
= (Pos
+1) % Length
;
1007 lowsample
= lpFilter(Filter
, DelayBuffer
[Pos
]);
1008 lowsample
+= (DelayBuffer
[Pos
]-lowsample
) * DecayHFRatio
;
1010 DelayBuffer
[LatePos
] += lowsample
* DecayGain
;
1012 sample
+= DelayBuffer
[LatePos
];
1014 WetBuffer
[i
][FRONT_LEFT
] = sample
;
1015 WetBuffer
[i
][FRONT_RIGHT
] = sample
;
1016 WetBuffer
[i
][SIDE_LEFT
] = sample
;
1017 WetBuffer
[i
][SIDE_RIGHT
] = sample
;
1018 WetBuffer
[i
][BACK_LEFT
] = sample
;
1019 WetBuffer
[i
][BACK_RIGHT
] = sample
;
1021 LatePos
= (LatePos
+1) % Length
;
1022 ReflectPos
= (ReflectPos
+1) % Length
;
1025 ALEffectSlot
->ReverbPos
= Pos
;
1026 ALEffectSlot
->ReverbLatePos
= LatePos
;
1027 ALEffectSlot
->ReverbReflectPos
= ReflectPos
;
1030 ALEffectSlot
= ALEffectSlot
->next
;
1033 //Post processing loop
1036 case AL_FORMAT_MONO8
:
1037 for(i
= 0;i
< SamplesToDo
;i
++)
1039 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
1040 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1041 buffer
= ((ALubyte
*)buffer
) + 1;
1044 case AL_FORMAT_STEREO8
:
1045 if(ALContext
&& ALContext
->bs2b
)
1047 for(i
= 0;i
< SamplesToDo
;i
++)
1050 samples
[0] = DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
];
1051 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
];
1052 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1053 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(samples
[0])>>8)+128);
1054 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(samples
[1])>>8)+128);
1055 buffer
= ((ALubyte
*)buffer
) + 2;
1060 for(i
= 0;i
< SamplesToDo
;i
++)
1062 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1063 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1064 buffer
= ((ALubyte
*)buffer
) + 2;
1068 case AL_FORMAT_QUAD8
:
1069 for(i
= 0;i
< SamplesToDo
;i
++)
1071 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1072 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1073 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1074 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1075 buffer
= ((ALubyte
*)buffer
) + 4;
1078 case AL_FORMAT_51CHN8
:
1079 for(i
= 0;i
< SamplesToDo
;i
++)
1081 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1082 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1083 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1084 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1085 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1086 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1087 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_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 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1092 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1094 buffer
= ((ALubyte
*)buffer
) + 6;
1097 case AL_FORMAT_61CHN8
:
1098 for(i
= 0;i
< SamplesToDo
;i
++)
1100 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1101 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1103 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1104 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1105 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1107 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1108 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1109 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1111 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
])>>8)+128);
1112 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1113 buffer
= ((ALubyte
*)buffer
) + 7;
1116 case AL_FORMAT_71CHN8
:
1117 for(i
= 0;i
< SamplesToDo
;i
++)
1119 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1120 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1122 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1123 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1124 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1125 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1127 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1128 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1129 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1130 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1132 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
])>>8)+128);
1133 ((ALubyte
*)buffer
)[7] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1134 buffer
= ((ALubyte
*)buffer
) + 8;
1138 case AL_FORMAT_MONO16
:
1139 for(i
= 0;i
< SamplesToDo
;i
++)
1141 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
1142 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1143 buffer
= ((ALshort
*)buffer
) + 1;
1146 case AL_FORMAT_STEREO16
:
1147 if(ALContext
&& ALContext
->bs2b
)
1149 for(i
= 0;i
< SamplesToDo
;i
++)
1152 samples
[0] = DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
];
1153 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
];
1154 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1155 ((ALshort
*)buffer
)[0] = aluF2S(samples
[0]);
1156 ((ALshort
*)buffer
)[1] = aluF2S(samples
[1]);
1157 buffer
= ((ALshort
*)buffer
) + 2;
1162 for(i
= 0;i
< SamplesToDo
;i
++)
1164 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1165 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1166 buffer
= ((ALshort
*)buffer
) + 2;
1170 case AL_FORMAT_QUAD16
:
1171 for(i
= 0;i
< SamplesToDo
;i
++)
1173 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1174 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1175 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1176 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1177 buffer
= ((ALshort
*)buffer
) + 4;
1180 case AL_FORMAT_51CHN16
:
1181 for(i
= 0;i
< SamplesToDo
;i
++)
1183 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1184 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1186 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1187 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1188 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1189 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_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 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1194 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1196 buffer
= ((ALshort
*)buffer
) + 6;
1199 case AL_FORMAT_61CHN16
:
1200 for(i
= 0;i
< SamplesToDo
;i
++)
1202 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1203 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1205 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1206 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1207 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1209 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1210 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1211 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1213 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
]);
1214 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
]);
1215 buffer
= ((ALshort
*)buffer
) + 7;
1218 case AL_FORMAT_71CHN16
:
1219 for(i
= 0;i
< SamplesToDo
;i
++)
1221 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1222 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1224 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1225 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1226 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1227 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1229 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1230 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1231 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1232 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1234 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
]);
1235 ((ALshort
*)buffer
)[7] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
]);
1236 buffer
= ((ALshort
*)buffer
) + 8;
1244 size
-= SamplesToDo
;
1247 #if defined(HAVE_FESETROUND)
1248 fesetround(fpuState
);
1249 #elif defined(HAVE__CONTROLFP)
1250 _controlfp(fpuState
, 0xfffff);
1253 ProcessContext(ALContext
);