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"
35 #if defined(HAVE_STDINT_H)
37 typedef int64_t ALint64
;
38 #elif defined(HAVE___INT64)
39 typedef __int64 ALint64
;
40 #elif (SIZEOF_LONG == 8)
42 #elif (SIZEOF_LONG_LONG == 8)
43 typedef long long ALint64
;
47 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
49 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
53 #if defined(max) && !defined(__max)
56 #if defined(min) && !defined(__min)
60 #define BUFFERSIZE 48000
61 #define FRACTIONBITS 14
62 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
78 /* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
79 * converted to AL_FORMAT_QUAD* when loaded */
80 __inline ALuint
aluBytesFromFormat(ALenum format
)
85 case AL_FORMAT_STEREO8
:
86 case AL_FORMAT_QUAD8_LOKI
:
88 case AL_FORMAT_51CHN8
:
89 case AL_FORMAT_61CHN8
:
90 case AL_FORMAT_71CHN8
:
93 case AL_FORMAT_MONO16
:
94 case AL_FORMAT_STEREO16
:
95 case AL_FORMAT_QUAD16_LOKI
:
96 case AL_FORMAT_QUAD16
:
97 case AL_FORMAT_51CHN16
:
98 case AL_FORMAT_61CHN16
:
99 case AL_FORMAT_71CHN16
:
102 case AL_FORMAT_MONO_FLOAT32
:
103 case AL_FORMAT_STEREO_FLOAT32
:
104 case AL_FORMAT_QUAD32
:
105 case AL_FORMAT_51CHN32
:
106 case AL_FORMAT_61CHN32
:
107 case AL_FORMAT_71CHN32
:
115 __inline ALuint
aluChannelsFromFormat(ALenum format
)
119 case AL_FORMAT_MONO8
:
120 case AL_FORMAT_MONO16
:
121 case AL_FORMAT_MONO_FLOAT32
:
124 case AL_FORMAT_STEREO8
:
125 case AL_FORMAT_STEREO16
:
126 case AL_FORMAT_STEREO_FLOAT32
:
129 case AL_FORMAT_QUAD8_LOKI
:
130 case AL_FORMAT_QUAD16_LOKI
:
131 case AL_FORMAT_QUAD8
:
132 case AL_FORMAT_QUAD16
:
133 case AL_FORMAT_QUAD32
:
136 case AL_FORMAT_51CHN8
:
137 case AL_FORMAT_51CHN16
:
138 case AL_FORMAT_51CHN32
:
141 case AL_FORMAT_61CHN8
:
142 case AL_FORMAT_61CHN16
:
143 case AL_FORMAT_61CHN32
:
146 case AL_FORMAT_71CHN8
:
147 case AL_FORMAT_71CHN16
:
148 case AL_FORMAT_71CHN32
:
156 static __inline ALint
aluF2L(ALfloat Value
)
159 if(sizeof(ALint
) == 4 && sizeof(double) == 8)
162 temp
= Value
+ (((65536.0*65536.0*16.0)+(65536.0*65536.0*8.0))*65536.0);
163 return *((ALint
*)&temp
);
169 static __inline ALshort
aluF2S(ALfloat Value
)
174 i
= __min( 32767, i
);
175 i
= __max(-32768, i
);
179 static __inline ALvoid
aluCrossproduct(ALfloat
*inVector1
,ALfloat
*inVector2
,ALfloat
*outVector
)
181 outVector
[0] = inVector1
[1]*inVector2
[2] - inVector1
[2]*inVector2
[1];
182 outVector
[1] = inVector1
[2]*inVector2
[0] - inVector1
[0]*inVector2
[2];
183 outVector
[2] = inVector1
[0]*inVector2
[1] - inVector1
[1]*inVector2
[0];
186 static __inline ALfloat
aluDotproduct(ALfloat
*inVector1
,ALfloat
*inVector2
)
188 return inVector1
[0]*inVector2
[0] + inVector1
[1]*inVector2
[1] +
189 inVector1
[2]*inVector2
[2];
192 static __inline ALvoid
aluNormalize(ALfloat
*inVector
)
194 ALfloat length
, inverse_length
;
196 length
= (ALfloat
)aluSqrt(aluDotproduct(inVector
, inVector
));
199 inverse_length
= 1.0f
/length
;
200 inVector
[0] *= inverse_length
;
201 inVector
[1] *= inverse_length
;
202 inVector
[2] *= inverse_length
;
206 static __inline ALvoid
aluMatrixVector(ALfloat
*vector
,ALfloat matrix
[3][3])
210 result
[0] = vector
[0]*matrix
[0][0] + vector
[1]*matrix
[1][0] + vector
[2]*matrix
[2][0];
211 result
[1] = vector
[0]*matrix
[0][1] + vector
[1]*matrix
[1][1] + vector
[2]*matrix
[2][1];
212 result
[2] = vector
[0]*matrix
[0][2] + vector
[1]*matrix
[1][2] + vector
[2]*matrix
[2][2];
213 memcpy(vector
, result
, sizeof(result
));
216 static __inline ALfloat
aluComputeDrySample(ALsource
*source
, ALfloat DryGainHF
, ALfloat sample
)
220 ALfloat u
= sample
+ source
->LastDrySample
;
221 ALfloat v
= sample
- source
->LastDrySample
;
222 sample
= (u
+ (v
*DryGainHF
)) * 0.5;
225 source
->LastDrySample
= sample
;
229 static __inline ALfloat
aluComputeWetSample(ALsource
*source
, ALfloat WetGainHF
, ALfloat sample
)
233 ALfloat u
= sample
+ source
->LastWetSample
;
234 ALfloat v
= sample
- source
->LastWetSample
;
235 sample
= (u
+ (v
*WetGainHF
)) * 0.5;
238 source
->LastWetSample
= sample
;
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 ListenerOrientation
[6],ListenerPosition
[3],ListenerVelocity
[3];
249 ALfloat InnerAngle
,OuterAngle
,OuterGain
,Angle
,Distance
,DryMix
,WetMix
;
250 ALfloat Direction
[3],Position
[3],Velocity
[3],SourceToListener
[3];
251 ALfloat MinVolume
,MaxVolume
,MinDist
,MaxDist
,Rolloff
,OuterGainHF
;
252 ALfloat Pitch
,ConeVolume
,SourceVolume
,PanningFB
,PanningLR
,ListenerGain
;
253 ALfloat U
[3],V
[3],N
[3];
254 ALfloat DopplerFactor
, DopplerVelocity
, flSpeedOfSound
, flMaxVelocity
;
255 ALfloat flVSS
, flVLS
;
257 ALfloat Matrix
[3][3];
259 ALfloat flAttenuation
;
260 ALfloat RoomAttenuation
;
261 ALfloat MetersPerUnit
;
263 ALfloat DryGainHF
= 1.0f
;
264 ALfloat WetGainHF
= 1.0f
;
266 //Get context properties
267 DopplerFactor
= ALContext
->DopplerFactor
;
268 DistanceModel
= ALContext
->DistanceModel
;
269 DopplerVelocity
= ALContext
->DopplerVelocity
;
270 flSpeedOfSound
= ALContext
->flSpeedOfSound
;
272 //Get listener properties
273 ListenerGain
= ALContext
->Listener
.Gain
;
274 MetersPerUnit
= ALContext
->Listener
.MetersPerUnit
;
275 memcpy(ListenerPosition
, ALContext
->Listener
.Position
, sizeof(ALContext
->Listener
.Position
));
276 memcpy(ListenerVelocity
, ALContext
->Listener
.Velocity
, sizeof(ALContext
->Listener
.Velocity
));
277 memcpy(&ListenerOrientation
[0], ALContext
->Listener
.Forward
, sizeof(ALContext
->Listener
.Forward
));
278 memcpy(&ListenerOrientation
[3], ALContext
->Listener
.Up
, sizeof(ALContext
->Listener
.Up
));
280 //Get source properties
281 Pitch
= ALSource
->flPitch
;
282 SourceVolume
= ALSource
->flGain
;
283 memcpy(Position
, ALSource
->vPosition
, sizeof(ALSource
->vPosition
));
284 memcpy(Velocity
, ALSource
->vVelocity
, sizeof(ALSource
->vVelocity
));
285 memcpy(Direction
, ALSource
->vOrientation
, sizeof(ALSource
->vOrientation
));
286 MinVolume
= ALSource
->flMinGain
;
287 MaxVolume
= ALSource
->flMaxGain
;
288 MinDist
= ALSource
->flRefDistance
;
289 MaxDist
= ALSource
->flMaxDistance
;
290 Rolloff
= ALSource
->flRollOffFactor
;
291 OuterGain
= ALSource
->flOuterGain
;
292 InnerAngle
= ALSource
->flInnerAngle
;
293 OuterAngle
= ALSource
->flOuterAngle
;
294 HeadRelative
= ALSource
->bHeadRelative
;
295 OuterGainHF
= ALSource
->OuterGainHF
;
296 RoomRolloff
= ALSource
->RoomRolloffFactor
;
298 //Only apply 3D calculations for mono buffers
299 if(isMono
!= AL_FALSE
)
301 //1. Translate Listener to origin (convert to head relative)
302 if(HeadRelative
==AL_FALSE
)
304 Position
[0] -= ListenerPosition
[0];
305 Position
[1] -= ListenerPosition
[1];
306 Position
[2] -= ListenerPosition
[2];
309 //2. Calculate distance attenuation
310 Distance
= aluSqrt(aluDotproduct(Position
, Position
));
312 flAttenuation
= 1.0f
;
313 RoomAttenuation
= 1.0f
;
314 switch (DistanceModel
)
316 case AL_INVERSE_DISTANCE_CLAMPED
:
317 Distance
=__max(Distance
,MinDist
);
318 Distance
=__min(Distance
,MaxDist
);
319 if (MaxDist
< MinDist
)
322 case AL_INVERSE_DISTANCE
:
325 if ((MinDist
+ (Rolloff
* (Distance
- MinDist
))) > 0.0f
)
326 flAttenuation
= MinDist
/ (MinDist
+ (Rolloff
* (Distance
- MinDist
)));
327 if ((MinDist
+ (RoomRolloff
* (Distance
- MinDist
))) > 0.0f
)
328 RoomAttenuation
= MinDist
/ (MinDist
+ (RoomRolloff
* (Distance
- MinDist
)));
332 case AL_LINEAR_DISTANCE_CLAMPED
:
333 Distance
=__max(Distance
,MinDist
);
334 Distance
=__min(Distance
,MaxDist
);
335 if (MaxDist
< MinDist
)
338 case AL_LINEAR_DISTANCE
:
339 Distance
=__min(Distance
,MaxDist
);
340 if (MaxDist
!= MinDist
)
342 flAttenuation
= 1.0f
- (Rolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
343 RoomAttenuation
= 1.0f
- (RoomRolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
347 case AL_EXPONENT_DISTANCE_CLAMPED
:
348 Distance
=__max(Distance
,MinDist
);
349 Distance
=__min(Distance
,MaxDist
);
350 if (MaxDist
< MinDist
)
353 case AL_EXPONENT_DISTANCE
:
354 if ((Distance
> 0.0f
) && (MinDist
> 0.0f
))
356 flAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -Rolloff
);
357 RoomAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -RoomRolloff
);
363 flAttenuation
= 1.0f
;
364 RoomAttenuation
= 1.0f
;
368 // Source Gain + Attenuation
369 DryMix
= SourceVolume
* flAttenuation
;
370 WetMix
= SourceVolume
* ((ALSource
->WetGainAuto
&&
371 ALSource
->Send
[0].Slot
.AuxSendAuto
) ?
372 RoomAttenuation
: 1.0f
);
374 // Clamp to Min/Max Gain
375 DryMix
= __min(DryMix
,MaxVolume
);
376 DryMix
= __max(DryMix
,MinVolume
);
377 WetMix
= __min(WetMix
,MaxVolume
);
378 WetMix
= __max(WetMix
,MinVolume
);
379 //3. Apply directional soundcones
380 SourceToListener
[0] = -Position
[0];
381 SourceToListener
[1] = -Position
[1];
382 SourceToListener
[2] = -Position
[2];
383 aluNormalize(Direction
);
384 aluNormalize(SourceToListener
);
385 Angle
= (ALfloat
)(180.0*acos(aluDotproduct(Direction
,SourceToListener
))/3.141592654f
);
386 if(Angle
>= InnerAngle
&& Angle
<= OuterAngle
)
388 ALfloat scale
= (Angle
-InnerAngle
) / (OuterAngle
-InnerAngle
);
389 ConeVolume
= (1.0f
+(OuterGain
-1.0f
)*scale
);
390 if(ALSource
->WetGainAuto
)
391 WetMix
*= ConeVolume
;
392 if(ALSource
->DryGainHFAuto
)
393 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
394 if(ALSource
->WetGainHFAuto
)
395 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
397 else if(Angle
> OuterAngle
)
399 ConeVolume
= (1.0f
+(OuterGain
-1.0f
));
400 if(ALSource
->WetGainAuto
)
401 WetMix
*= ConeVolume
;
402 if(ALSource
->DryGainHFAuto
)
403 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
404 if(ALSource
->WetGainHFAuto
)
405 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
410 //4. Calculate Velocity
411 if(DopplerFactor
!= 0.0f
)
413 flVLS
= aluDotproduct(ListenerVelocity
, SourceToListener
);
414 flVSS
= aluDotproduct(Velocity
, SourceToListener
);
416 flMaxVelocity
= (DopplerVelocity
* flSpeedOfSound
) / DopplerFactor
;
418 if (flVSS
>= flMaxVelocity
)
419 flVSS
= (flMaxVelocity
- 1.0f
);
420 else if (flVSS
<= -flMaxVelocity
)
421 flVSS
= -flMaxVelocity
+ 1.0f
;
423 if (flVLS
>= flMaxVelocity
)
424 flVLS
= (flMaxVelocity
- 1.0f
);
425 else if (flVLS
<= -flMaxVelocity
)
426 flVLS
= -flMaxVelocity
+ 1.0f
;
428 pitch
[0] = Pitch
* ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVLS
)) /
429 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVSS
));
434 //5. Align coordinate system axes
435 aluCrossproduct(&ListenerOrientation
[0], &ListenerOrientation
[3], U
); // Right-vector
436 aluNormalize(U
); // Normalized Right-vector
437 memcpy(V
, &ListenerOrientation
[3], sizeof(V
)); // Up-vector
438 aluNormalize(V
); // Normalized Up-vector
439 memcpy(N
, &ListenerOrientation
[0], sizeof(N
)); // At-vector
440 aluNormalize(N
); // Normalized At-vector
441 Matrix
[0][0] = U
[0]; Matrix
[0][1] = V
[0]; Matrix
[0][2] = -N
[0];
442 Matrix
[1][0] = U
[1]; Matrix
[1][1] = V
[1]; Matrix
[1][2] = -N
[1];
443 Matrix
[2][0] = U
[2]; Matrix
[2][1] = V
[2]; Matrix
[2][2] = -N
[2];
444 aluMatrixVector(Position
, Matrix
);
446 //6. Apply filter gains and filters
447 switch(ALSource
->DirectFilter
.filter
)
449 case AL_FILTER_LOWPASS
:
450 DryMix
*= ALSource
->DirectFilter
.Gain
;
451 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
455 switch(ALSource
->Send
[0].WetFilter
.filter
)
457 case AL_FILTER_LOWPASS
:
458 WetMix
*= ALSource
->Send
[0].WetFilter
.Gain
;
459 WetGainHF
*= ALSource
->Send
[0].WetFilter
.GainHF
;
463 if(ALSource
->AirAbsorptionFactor
> 0.0f
)
464 DryGainHF
*= pow(ALSource
->AirAbsorptionFactor
* AIRABSORBGAINHF
,
465 Distance
* MetersPerUnit
);
467 WetMix
*= ALSource
->Send
[0].Slot
.Gain
;
469 //7. Convert normalized position into pannings, then into channel volumes
470 aluNormalize(Position
);
471 switch(aluChannelsFromFormat(OutputFormat
))
474 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
); //Direct
475 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
); //Direct
476 if(ALSource
->Send
[0].Slot
.effectslot
)
478 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt(1.0f
); //Room
479 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(1.0f
); //Room
483 wetsend
[FRONT_LEFT
] = 0.0f
;
484 wetsend
[FRONT_RIGHT
] = 0.0f
;
489 PanningLR
= 0.5f
+ 0.5f
*Position
[0];
490 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
-PanningLR
); //L Direct
491 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt( PanningLR
); //R Direct
492 if(ALSource
->Send
[0].Slot
.effectslot
)
494 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt(1.0f
-PanningLR
); //L Room
495 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt( PanningLR
); //R Room
499 wetsend
[FRONT_LEFT
] = 0.0f
;
500 wetsend
[FRONT_RIGHT
] = 0.0f
;
505 /* TODO: Add center/lfe channel in spatial calculations? */
507 // Apply a scalar so each individual speaker has more weight
508 PanningLR
= 0.5f
+ (0.5f
*Position
[0]*1.41421356f
);
509 PanningLR
= __min(1.0f
, PanningLR
);
510 PanningLR
= __max(0.0f
, PanningLR
);
511 PanningFB
= 0.5f
+ (0.5f
*Position
[2]*1.41421356f
);
512 PanningFB
= __min(1.0f
, PanningFB
);
513 PanningFB
= __max(0.0f
, PanningFB
);
514 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
515 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
516 drysend
[BACK_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
517 drysend
[BACK_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
518 if(ALSource
->Send
[0].Slot
.effectslot
)
520 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
521 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
522 wetsend
[BACK_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
523 wetsend
[BACK_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
527 wetsend
[FRONT_LEFT
] = 0.0f
;
528 wetsend
[FRONT_RIGHT
] = 0.0f
;
529 wetsend
[BACK_LEFT
] = 0.0f
;
530 wetsend
[BACK_RIGHT
] = 0.0f
;
536 PanningFB
= 1.0f
- fabs(Position
[2]*1.15470054f
);
537 PanningFB
= __min(1.0f
, PanningFB
);
538 PanningFB
= __max(0.0f
, PanningFB
);
539 PanningLR
= 0.5f
+ (0.5*Position
[0]*((1.0f
-PanningFB
)*2.0f
));
540 PanningLR
= __min(1.0f
, PanningLR
);
541 PanningLR
= __max(0.0f
, PanningLR
);
542 if(Position
[2] > 0.0f
)
544 drysend
[BACK_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
545 drysend
[BACK_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
546 drysend
[SIDE_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
547 drysend
[SIDE_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
548 drysend
[FRONT_LEFT
] = 0.0f
;
549 drysend
[FRONT_RIGHT
] = 0.0f
;
550 if(ALSource
->Send
[0].Slot
.effectslot
)
552 wetsend
[BACK_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
553 wetsend
[BACK_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
554 wetsend
[SIDE_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
555 wetsend
[SIDE_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
556 wetsend
[FRONT_LEFT
] = 0.0f
;
557 wetsend
[FRONT_RIGHT
] = 0.0f
;
561 wetsend
[FRONT_LEFT
] = 0.0f
;
562 wetsend
[FRONT_RIGHT
] = 0.0f
;
563 wetsend
[SIDE_LEFT
] = 0.0f
;
564 wetsend
[SIDE_RIGHT
] = 0.0f
;
565 wetsend
[BACK_LEFT
] = 0.0f
;
566 wetsend
[BACK_RIGHT
] = 0.0f
;
572 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
573 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
574 drysend
[SIDE_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
575 drysend
[SIDE_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
576 drysend
[BACK_LEFT
] = 0.0f
;
577 drysend
[BACK_RIGHT
] = 0.0f
;
578 if(ALSource
->Send
[0].Slot
.effectslot
)
580 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
581 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
582 wetsend
[SIDE_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
583 wetsend
[SIDE_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
584 wetsend
[BACK_LEFT
] = 0.0f
;
585 wetsend
[BACK_RIGHT
] = 0.0f
;
589 wetsend
[FRONT_LEFT
] = 0.0f
;
590 wetsend
[FRONT_RIGHT
] = 0.0f
;
591 wetsend
[SIDE_LEFT
] = 0.0f
;
592 wetsend
[SIDE_RIGHT
] = 0.0f
;
593 wetsend
[BACK_LEFT
] = 0.0f
;
594 wetsend
[BACK_RIGHT
] = 0.0f
;
602 *drygainhf
= DryGainHF
;
603 *wetgainhf
= WetGainHF
;
607 *drygainhf
= DryGainHF
;
608 *wetgainhf
= WetGainHF
;
610 //1. Multi-channel buffers always play "normal"
611 drysend
[FRONT_LEFT
] = SourceVolume
* 1.0f
* ListenerGain
;
612 drysend
[FRONT_RIGHT
] = SourceVolume
* 1.0f
* ListenerGain
;
613 drysend
[SIDE_LEFT
] = SourceVolume
* 1.0f
* ListenerGain
;
614 drysend
[SIDE_RIGHT
] = SourceVolume
* 1.0f
* ListenerGain
;
615 drysend
[BACK_LEFT
] = SourceVolume
* 1.0f
* ListenerGain
;
616 drysend
[BACK_RIGHT
] = SourceVolume
* 1.0f
* ListenerGain
;
617 drysend
[CENTER
] = SourceVolume
* 1.0f
* ListenerGain
;
618 drysend
[LFE
] = SourceVolume
* 1.0f
* ListenerGain
;
619 if(ALSource
->Send
[0].Slot
.effectslot
)
621 wetsend
[FRONT_LEFT
] = SourceVolume
* 0.0f
* ListenerGain
;
622 wetsend
[FRONT_RIGHT
] = SourceVolume
* 0.0f
* ListenerGain
;
623 wetsend
[SIDE_LEFT
] = SourceVolume
* 0.0f
* ListenerGain
;
624 wetsend
[SIDE_RIGHT
] = SourceVolume
* 0.0f
* ListenerGain
;
625 wetsend
[BACK_LEFT
] = SourceVolume
* 0.0f
* ListenerGain
;
626 wetsend
[BACK_RIGHT
] = SourceVolume
* 0.0f
* ListenerGain
;
627 wetsend
[CENTER
] = SourceVolume
* 0.0f
* ListenerGain
;
628 wetsend
[LFE
] = SourceVolume
* 0.0f
* ListenerGain
;
632 wetsend
[FRONT_LEFT
] = 0.0f
;
633 wetsend
[FRONT_RIGHT
] = 0.0f
;
634 wetsend
[SIDE_LEFT
] = 0.0f
;
635 wetsend
[SIDE_RIGHT
] = 0.0f
;
636 wetsend
[BACK_LEFT
] = 0.0f
;
637 wetsend
[BACK_RIGHT
] = 0.0f
;
638 wetsend
[CENTER
] = 0.0f
;
647 ALvoid
aluMixData(ALCcontext
*ALContext
,ALvoid
*buffer
,ALsizei size
,ALenum format
)
649 static float DryBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
650 static float WetBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
651 ALfloat DrySend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
652 ALfloat WetSend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
653 ALfloat DryGainHF
= 0.0f
;
654 ALfloat WetGainHF
= 0.0f
;
655 ALuint BlockAlign
,BufferSize
;
656 ALuint DataSize
=0,DataPosInt
=0,DataPosFrac
=0;
657 ALuint Channels
,Bits
,Frequency
,ulExtraSamples
;
659 ALint Looping
,increment
,State
;
660 ALuint Buffer
,fraction
;
667 ALbufferlistitem
*BufferListItem
;
669 ALint64 DataSize64
,DataPos64
;
671 SuspendContext(ALContext
);
675 //Figure output format variables
676 BlockAlign
= aluChannelsFromFormat(format
);
677 BlockAlign
*= aluBytesFromFormat(format
);
683 ALSource
= (ALContext
? ALContext
->Source
: NULL
);
684 SamplesToDo
= min(size
, BUFFERSIZE
);
686 //Clear mixing buffer
687 memset(DryBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
688 memset(WetBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
694 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 Bits
= aluBytesFromFormat(ALBuffer
->format
) * 8;
708 Channels
= aluChannelsFromFormat(ALBuffer
->format
);
709 DataSize
= ALBuffer
->size
;
710 Frequency
= ALBuffer
->frequency
;
712 CalcSourceParams(ALContext
, ALSource
,
713 (Channels
==1) ? AL_TRUE
: AL_FALSE
,
714 format
, DrySend
, WetSend
, &Pitch
,
715 &DryGainHF
, &WetGainHF
);
718 Pitch
= (Pitch
*Frequency
) / ALContext
->Frequency
;
719 DataSize
= DataSize
/ (Bits
*Channels
/8);
722 DataPosInt
= ALSource
->position
;
723 DataPosFrac
= ALSource
->position_fraction
;
725 //Compute 18.14 fixed point step
726 increment
= aluF2L(Pitch
*(1L<<FRACTIONBITS
));
727 if(increment
> (MAX_PITCH
<<FRACTIONBITS
))
728 increment
= (MAX_PITCH
<<FRACTIONBITS
);
730 //Figure out how many samples we can mix.
731 //Pitch must be <= 4 (the number below !)
732 DataSize64
= DataSize
+MAX_PITCH
;
733 DataSize64
<<= FRACTIONBITS
;
734 DataPos64
= DataPosInt
;
735 DataPos64
<<= FRACTIONBITS
;
736 DataPos64
+= DataPosFrac
;
737 BufferSize
= (ALuint
)((DataSize64
-DataPos64
) / increment
);
738 BufferListItem
= ALSource
->queue
;
739 for(loop
= 0; loop
< ALSource
->BuffersPlayed
; loop
++)
742 BufferListItem
= BufferListItem
->next
;
746 if (BufferListItem
->next
)
748 if(BufferListItem
->next
->buffer
&&
749 ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->data
)
751 ulExtraSamples
= min(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->size
, (ALint
)(16*Channels
));
752 memcpy(&Data
[DataSize
*Channels
], ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->data
, ulExtraSamples
);
755 else if (ALSource
->bLooping
)
757 if (ALSource
->queue
->buffer
)
759 if(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->data
)
761 ulExtraSamples
= min(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->size
, (ALint
)(16*Channels
));
762 memcpy(&Data
[DataSize
*Channels
], ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->data
, ulExtraSamples
);
767 BufferSize
= min(BufferSize
, (SamplesToDo
-j
));
769 //Actual sample mixing loop
770 Data
+= DataPosInt
*Channels
;
773 k
= DataPosFrac
>>FRACTIONBITS
;
774 fraction
= DataPosFrac
&FRACTIONMASK
;
777 //First order interpolator
778 ALfloat sample
= (ALfloat
)((ALshort
)(((Data
[k
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[k
+1]*(fraction
)))>>FRACTIONBITS
));
780 //Direct path final mix buffer and panning
781 value
= aluComputeDrySample(ALSource
, DryGainHF
, sample
);
782 DryBuffer
[j
][FRONT_LEFT
] += value
*DrySend
[FRONT_LEFT
];
783 DryBuffer
[j
][FRONT_RIGHT
] += value
*DrySend
[FRONT_RIGHT
];
784 DryBuffer
[j
][SIDE_LEFT
] += value
*DrySend
[SIDE_LEFT
];
785 DryBuffer
[j
][SIDE_RIGHT
] += value
*DrySend
[SIDE_RIGHT
];
786 DryBuffer
[j
][BACK_LEFT
] += value
*DrySend
[BACK_LEFT
];
787 DryBuffer
[j
][BACK_RIGHT
] += value
*DrySend
[BACK_RIGHT
];
788 //Room path final mix buffer and panning
789 value
= aluComputeWetSample(ALSource
, WetGainHF
, sample
);
790 WetBuffer
[j
][FRONT_LEFT
] += value
*WetSend
[FRONT_LEFT
];
791 WetBuffer
[j
][FRONT_RIGHT
] += value
*WetSend
[FRONT_RIGHT
];
792 WetBuffer
[j
][SIDE_LEFT
] += value
*WetSend
[SIDE_LEFT
];
793 WetBuffer
[j
][SIDE_RIGHT
] += value
*WetSend
[SIDE_RIGHT
];
794 WetBuffer
[j
][BACK_LEFT
] += value
*WetSend
[BACK_LEFT
];
795 WetBuffer
[j
][BACK_RIGHT
] += value
*WetSend
[BACK_RIGHT
];
799 //First order interpolator (front left)
800 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
]*(fraction
)))>>FRACTIONBITS
));
801 DryBuffer
[j
][FRONT_LEFT
] += value
*DrySend
[FRONT_LEFT
];
802 WetBuffer
[j
][FRONT_LEFT
] += value
*WetSend
[FRONT_LEFT
];
803 //First order interpolator (front right)
804 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+1]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+1]*(fraction
)))>>FRACTIONBITS
));
805 DryBuffer
[j
][FRONT_RIGHT
] += value
*DrySend
[FRONT_RIGHT
];
806 WetBuffer
[j
][FRONT_RIGHT
] += value
*WetSend
[FRONT_RIGHT
];
814 //First order interpolator (center)
815 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
816 DryBuffer
[j
][CENTER
] += value
*DrySend
[CENTER
];
817 WetBuffer
[j
][CENTER
] += value
*WetSend
[CENTER
];
820 //First order interpolator (lfe)
821 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
822 DryBuffer
[j
][LFE
] += value
*DrySend
[LFE
];
823 WetBuffer
[j
][LFE
] += value
*WetSend
[LFE
];
826 //First order interpolator (back left)
827 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
828 DryBuffer
[j
][BACK_LEFT
] += value
*DrySend
[BACK_LEFT
];
829 WetBuffer
[j
][BACK_LEFT
] += value
*WetSend
[BACK_LEFT
];
831 //First order interpolator (back right)
832 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
833 DryBuffer
[j
][BACK_RIGHT
] += value
*DrySend
[BACK_RIGHT
];
834 WetBuffer
[j
][BACK_RIGHT
] += value
*WetSend
[BACK_RIGHT
];
838 //First order interpolator (side left)
839 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
840 DryBuffer
[j
][SIDE_LEFT
] += value
*DrySend
[SIDE_LEFT
];
841 WetBuffer
[j
][SIDE_LEFT
] += value
*WetSend
[SIDE_LEFT
];
843 //First order interpolator (side right)
844 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
845 DryBuffer
[j
][SIDE_RIGHT
] += value
*DrySend
[SIDE_RIGHT
];
846 WetBuffer
[j
][SIDE_RIGHT
] += value
*WetSend
[SIDE_RIGHT
];
851 DataPosFrac
+= increment
;
854 DataPosInt
+= (DataPosFrac
>>FRACTIONBITS
);
855 DataPosFrac
= (DataPosFrac
&FRACTIONMASK
);
858 ALSource
->position
= DataPosInt
;
859 ALSource
->position_fraction
= DataPosFrac
;
862 //Handle looping sources
863 if(!Buffer
|| DataPosInt
>= DataSize
)
868 Looping
= ALSource
->bLooping
;
869 if(ALSource
->BuffersPlayed
< (ALSource
->BuffersInQueue
-1))
871 BufferListItem
= ALSource
->queue
;
872 for(loop
= 0; loop
<= ALSource
->BuffersPlayed
; loop
++)
877 BufferListItem
->bufferstate
= PROCESSED
;
878 BufferListItem
= BufferListItem
->next
;
882 ALSource
->BuffersProcessed
++;
884 ALSource
->ulBufferID
= BufferListItem
->buffer
;
885 ALSource
->position
= DataPosInt
-DataSize
;
886 ALSource
->position_fraction
= DataPosFrac
;
887 ALSource
->BuffersPlayed
++;
894 ALSource
->state
= AL_STOPPED
;
895 ALSource
->inuse
= AL_FALSE
;
896 ALSource
->BuffersPlayed
= ALSource
->BuffersProcessed
= ALSource
->BuffersInQueue
;
897 BufferListItem
= ALSource
->queue
;
898 while(BufferListItem
!= NULL
)
900 BufferListItem
->bufferstate
= PROCESSED
;
901 BufferListItem
= BufferListItem
->next
;
908 ALSource
->state
= AL_PLAYING
;
909 ALSource
->inuse
= AL_TRUE
;
910 ALSource
->play
= AL_TRUE
;
911 ALSource
->BuffersPlayed
= 0;
912 ALSource
->BufferPosition
= 0;
913 ALSource
->lBytesPlayed
= 0;
914 ALSource
->BuffersProcessed
= 0;
915 BufferListItem
= ALSource
->queue
;
916 while(BufferListItem
!= NULL
)
918 BufferListItem
->bufferstate
= PENDING
;
919 BufferListItem
= BufferListItem
->next
;
921 ALSource
->ulBufferID
= ALSource
->queue
->buffer
;
923 ALSource
->position
= DataPosInt
-DataSize
;
924 ALSource
->position_fraction
= DataPosFrac
;
931 State
= ALSource
->state
;
934 ALSource
= ALSource
->next
;
937 //Post processing loop
940 case AL_FORMAT_MONO8
:
941 for(i
= 0;i
< SamplesToDo
;i
++)
943 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
944 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
945 buffer
= ((ALubyte
*)buffer
) + 1;
948 case AL_FORMAT_STEREO8
:
951 for(i
= 0;i
< SamplesToDo
;i
++)
954 samples
[0] = DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
];
955 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
];
956 bs2b_cross_feed(ALContext
->bs2b
, samples
);
957 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(samples
[0])>>8)+128);
958 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(samples
[1])>>8)+128);
959 buffer
= ((ALubyte
*)buffer
) + 2;
964 for(i
= 0;i
< SamplesToDo
;i
++)
966 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
967 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
968 buffer
= ((ALubyte
*)buffer
) + 2;
972 case AL_FORMAT_QUAD8
:
973 for(i
= 0;i
< SamplesToDo
;i
++)
975 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
976 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
977 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
978 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
979 buffer
= ((ALubyte
*)buffer
) + 4;
982 case AL_FORMAT_51CHN8
:
983 for(i
= 0;i
< SamplesToDo
;i
++)
985 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
986 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
987 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
988 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
989 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
990 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
991 buffer
= ((ALubyte
*)buffer
) + 6;
994 case AL_FORMAT_61CHN8
:
995 for(i
= 0;i
< SamplesToDo
;i
++)
997 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
998 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
999 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
])>>8)+128);
1000 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1001 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1002 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1003 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1004 buffer
= ((ALubyte
*)buffer
) + 7;
1007 case AL_FORMAT_71CHN8
:
1008 for(i
= 0;i
< SamplesToDo
;i
++)
1010 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1011 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1012 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
])>>8)+128);
1013 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1014 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1015 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1016 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1017 ((ALubyte
*)buffer
)[7] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1018 buffer
= ((ALubyte
*)buffer
) + 8;
1022 case AL_FORMAT_MONO16
:
1023 for(i
= 0;i
< SamplesToDo
;i
++)
1025 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
1026 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1027 buffer
= ((ALshort
*)buffer
) + 1;
1030 case AL_FORMAT_STEREO16
:
1033 for(i
= 0;i
< SamplesToDo
;i
++)
1036 samples
[0] = DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
];
1037 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
];
1038 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1039 ((ALshort
*)buffer
)[0] = aluF2S(samples
[0]);
1040 ((ALshort
*)buffer
)[1] = aluF2S(samples
[1]);
1041 buffer
= ((ALshort
*)buffer
) + 2;
1046 for(i
= 0;i
< SamplesToDo
;i
++)
1048 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1049 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1050 buffer
= ((ALshort
*)buffer
) + 2;
1054 case AL_FORMAT_QUAD16
:
1055 for(i
= 0;i
< SamplesToDo
;i
++)
1057 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1058 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1059 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1060 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1061 buffer
= ((ALshort
*)buffer
) + 4;
1064 case AL_FORMAT_51CHN16
:
1065 for(i
= 0;i
< SamplesToDo
;i
++)
1067 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1068 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1069 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1070 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1071 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1072 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1073 buffer
= ((ALshort
*)buffer
) + 6;
1076 case AL_FORMAT_61CHN16
:
1077 for(i
= 0;i
< SamplesToDo
;i
++)
1079 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1080 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1081 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
]);
1082 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
]);
1083 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1084 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1085 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1086 buffer
= ((ALshort
*)buffer
) + 7;
1089 case AL_FORMAT_71CHN16
:
1090 for(i
= 0;i
< SamplesToDo
;i
++)
1092 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1093 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1094 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
]);
1095 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
]);
1096 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1097 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1098 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1099 ((ALshort
*)buffer
)[7] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1100 buffer
= ((ALshort
*)buffer
) + 8;
1108 size
-= SamplesToDo
;
1112 ProcessContext(ALContext
);