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 #define aluAcos(x) ((ALfloat)acosf((float)(x)))
55 #define aluAcos(x) ((ALfloat)acos((double)(x)))
59 #if defined(max) && !defined(__max)
62 #if defined(min) && !defined(__min)
66 #define BUFFERSIZE 48000
67 #define FRACTIONBITS 14
68 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
84 /* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
85 * converted to AL_FORMAT_QUAD* when loaded */
86 __inline ALuint
aluBytesFromFormat(ALenum format
)
91 case AL_FORMAT_STEREO8
:
92 case AL_FORMAT_QUAD8_LOKI
:
94 case AL_FORMAT_51CHN8
:
95 case AL_FORMAT_61CHN8
:
96 case AL_FORMAT_71CHN8
:
99 case AL_FORMAT_MONO16
:
100 case AL_FORMAT_STEREO16
:
101 case AL_FORMAT_QUAD16_LOKI
:
102 case AL_FORMAT_QUAD16
:
103 case AL_FORMAT_51CHN16
:
104 case AL_FORMAT_61CHN16
:
105 case AL_FORMAT_71CHN16
:
108 case AL_FORMAT_MONO_FLOAT32
:
109 case AL_FORMAT_STEREO_FLOAT32
:
110 case AL_FORMAT_QUAD32
:
111 case AL_FORMAT_51CHN32
:
112 case AL_FORMAT_61CHN32
:
113 case AL_FORMAT_71CHN32
:
121 __inline ALuint
aluChannelsFromFormat(ALenum format
)
125 case AL_FORMAT_MONO8
:
126 case AL_FORMAT_MONO16
:
127 case AL_FORMAT_MONO_FLOAT32
:
130 case AL_FORMAT_STEREO8
:
131 case AL_FORMAT_STEREO16
:
132 case AL_FORMAT_STEREO_FLOAT32
:
135 case AL_FORMAT_QUAD8_LOKI
:
136 case AL_FORMAT_QUAD16_LOKI
:
137 case AL_FORMAT_QUAD8
:
138 case AL_FORMAT_QUAD16
:
139 case AL_FORMAT_QUAD32
:
142 case AL_FORMAT_51CHN8
:
143 case AL_FORMAT_51CHN16
:
144 case AL_FORMAT_51CHN32
:
147 case AL_FORMAT_61CHN8
:
148 case AL_FORMAT_61CHN16
:
149 case AL_FORMAT_61CHN32
:
152 case AL_FORMAT_71CHN8
:
153 case AL_FORMAT_71CHN16
:
154 case AL_FORMAT_71CHN32
:
162 static __inline ALint
aluF2L(ALfloat Value
)
165 if(sizeof(ALint
) == 4 && sizeof(double) == 8)
168 temp
= Value
+ (((65536.0*65536.0*16.0)+(65536.0*65536.0*8.0))*65536.0);
169 return *((ALint
*)&temp
);
175 static __inline ALshort
aluF2S(ALfloat Value
)
180 i
= __min( 32767, i
);
181 i
= __max(-32768, i
);
185 static __inline ALvoid
aluCrossproduct(ALfloat
*inVector1
,ALfloat
*inVector2
,ALfloat
*outVector
)
187 outVector
[0] = inVector1
[1]*inVector2
[2] - inVector1
[2]*inVector2
[1];
188 outVector
[1] = inVector1
[2]*inVector2
[0] - inVector1
[0]*inVector2
[2];
189 outVector
[2] = inVector1
[0]*inVector2
[1] - inVector1
[1]*inVector2
[0];
192 static __inline ALfloat
aluDotproduct(ALfloat
*inVector1
,ALfloat
*inVector2
)
194 return inVector1
[0]*inVector2
[0] + inVector1
[1]*inVector2
[1] +
195 inVector1
[2]*inVector2
[2];
198 static __inline ALvoid
aluNormalize(ALfloat
*inVector
)
200 ALfloat length
, inverse_length
;
202 length
= (ALfloat
)aluSqrt(aluDotproduct(inVector
, inVector
));
205 inverse_length
= 1.0f
/length
;
206 inVector
[0] *= inverse_length
;
207 inVector
[1] *= inverse_length
;
208 inVector
[2] *= inverse_length
;
212 static __inline ALvoid
aluMatrixVector(ALfloat
*vector
,ALfloat matrix
[3][3])
216 result
[0] = vector
[0]*matrix
[0][0] + vector
[1]*matrix
[1][0] + vector
[2]*matrix
[2][0];
217 result
[1] = vector
[0]*matrix
[0][1] + vector
[1]*matrix
[1][1] + vector
[2]*matrix
[2][1];
218 result
[2] = vector
[0]*matrix
[0][2] + vector
[1]*matrix
[1][2] + vector
[2]*matrix
[2][2];
219 memcpy(vector
, result
, sizeof(result
));
222 static __inline ALfloat
aluComputeDrySample(ALsource
*source
, ALfloat DryGainHF
, ALfloat sample
)
229 sample
+= source
->LastDrySample
* (1.0f
-DryGainHF
);
235 source
->LastDrySample
= sample
;
239 static __inline ALfloat
aluComputeWetSample(ALsource
*source
, ALfloat WetGainHF
, ALfloat sample
)
246 sample
+= source
->LastWetSample
* (1.0f
-WetGainHF
);
252 source
->LastWetSample
= sample
;
256 static ALvoid
CalcSourceParams(ALCcontext
*ALContext
, ALsource
*ALSource
,
257 ALenum isMono
, ALenum OutputFormat
,
258 ALfloat
*drysend
, ALfloat
*wetsend
,
259 ALfloat
*pitch
, ALfloat
*drygainhf
,
262 ALfloat InnerAngle
,OuterAngle
,Angle
,Distance
,DryMix
,WetMix
;
263 ALfloat Direction
[3],Position
[3],SourceToListener
[3];
264 ALfloat MinVolume
,MaxVolume
,MinDist
,MaxDist
,Rolloff
,OuterGainHF
;
265 ALfloat ConeVolume
,SourceVolume
,PanningFB
,PanningLR
,ListenerGain
;
266 ALfloat U
[3],V
[3],N
[3];
267 ALfloat DopplerFactor
, DopplerVelocity
, flSpeedOfSound
, flMaxVelocity
;
268 ALfloat Matrix
[3][3];
269 ALfloat flAttenuation
;
270 ALfloat RoomAttenuation
;
271 ALfloat MetersPerUnit
;
273 ALfloat DryGainHF
= 1.0f
;
274 ALfloat WetGainHF
= 1.0f
;
276 //Get context properties
277 DopplerFactor
= ALContext
->DopplerFactor
;
278 DopplerVelocity
= ALContext
->DopplerVelocity
;
279 flSpeedOfSound
= ALContext
->flSpeedOfSound
;
281 //Get listener properties
282 ListenerGain
= ALContext
->Listener
.Gain
;
283 MetersPerUnit
= ALContext
->Listener
.MetersPerUnit
;
285 //Get source properties
286 SourceVolume
= ALSource
->flGain
;
287 memcpy(Position
, ALSource
->vPosition
, sizeof(ALSource
->vPosition
));
288 memcpy(Direction
, ALSource
->vOrientation
, sizeof(ALSource
->vOrientation
));
289 MinVolume
= ALSource
->flMinGain
;
290 MaxVolume
= ALSource
->flMaxGain
;
291 MinDist
= ALSource
->flRefDistance
;
292 MaxDist
= ALSource
->flMaxDistance
;
293 Rolloff
= ALSource
->flRollOffFactor
;
294 InnerAngle
= ALSource
->flInnerAngle
;
295 OuterAngle
= ALSource
->flOuterAngle
;
296 OuterGainHF
= ALSource
->OuterGainHF
;
297 RoomRolloff
= ALSource
->RoomRolloffFactor
;
299 //Only apply 3D calculations for mono buffers
300 if(isMono
!= AL_FALSE
)
302 //1. Translate Listener to origin (convert to head relative)
303 if(ALSource
->bHeadRelative
==AL_FALSE
)
305 Position
[0] -= ALContext
->Listener
.Position
[0];
306 Position
[1] -= ALContext
->Listener
.Position
[1];
307 Position
[2] -= ALContext
->Listener
.Position
[2];
310 //2. Calculate distance attenuation
311 Distance
= aluSqrt(aluDotproduct(Position
, Position
));
313 flAttenuation
= 1.0f
;
314 RoomAttenuation
= 1.0f
;
315 switch (ALContext
->DistanceModel
)
317 case AL_INVERSE_DISTANCE_CLAMPED
:
318 Distance
=__max(Distance
,MinDist
);
319 Distance
=__min(Distance
,MaxDist
);
320 if (MaxDist
< MinDist
)
323 case AL_INVERSE_DISTANCE
:
326 if ((MinDist
+ (Rolloff
* (Distance
- MinDist
))) > 0.0f
)
327 flAttenuation
= MinDist
/ (MinDist
+ (Rolloff
* (Distance
- MinDist
)));
328 if ((MinDist
+ (RoomRolloff
* (Distance
- MinDist
))) > 0.0f
)
329 RoomAttenuation
= MinDist
/ (MinDist
+ (RoomRolloff
* (Distance
- MinDist
)));
333 case AL_LINEAR_DISTANCE_CLAMPED
:
334 Distance
=__max(Distance
,MinDist
);
335 Distance
=__min(Distance
,MaxDist
);
336 if (MaxDist
< MinDist
)
339 case AL_LINEAR_DISTANCE
:
340 Distance
=__min(Distance
,MaxDist
);
341 if (MaxDist
!= MinDist
)
343 flAttenuation
= 1.0f
- (Rolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
344 RoomAttenuation
= 1.0f
- (RoomRolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
348 case AL_EXPONENT_DISTANCE_CLAMPED
:
349 Distance
=__max(Distance
,MinDist
);
350 Distance
=__min(Distance
,MaxDist
);
351 if (MaxDist
< MinDist
)
354 case AL_EXPONENT_DISTANCE
:
355 if ((Distance
> 0.0f
) && (MinDist
> 0.0f
))
357 flAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -Rolloff
);
358 RoomAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -RoomRolloff
);
364 flAttenuation
= 1.0f
;
365 RoomAttenuation
= 1.0f
;
369 // Source Gain + Attenuation
370 DryMix
= SourceVolume
* flAttenuation
;
371 WetMix
= SourceVolume
* ((ALSource
->WetGainAuto
&&
372 ALSource
->Send
[0].Slot
.AuxSendAuto
) ?
373 RoomAttenuation
: 1.0f
);
375 // Clamp to Min/Max Gain
376 DryMix
= __min(DryMix
,MaxVolume
);
377 DryMix
= __max(DryMix
,MinVolume
);
378 WetMix
= __min(WetMix
,MaxVolume
);
379 WetMix
= __max(WetMix
,MinVolume
);
380 //3. Apply directional soundcones
381 SourceToListener
[0] = -Position
[0];
382 SourceToListener
[1] = -Position
[1];
383 SourceToListener
[2] = -Position
[2];
384 aluNormalize(Direction
);
385 aluNormalize(SourceToListener
);
386 Angle
= aluAcos(aluDotproduct(Direction
,SourceToListener
)) * 180.0f
/
388 if(Angle
>= InnerAngle
&& Angle
<= OuterAngle
)
390 ALfloat scale
= (Angle
-InnerAngle
) / (OuterAngle
-InnerAngle
);
391 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
)*scale
);
392 if(ALSource
->WetGainAuto
)
393 WetMix
*= ConeVolume
;
394 if(ALSource
->DryGainHFAuto
)
395 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
396 if(ALSource
->WetGainHFAuto
)
397 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
399 else if(Angle
> OuterAngle
)
401 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
));
402 if(ALSource
->WetGainAuto
)
403 WetMix
*= ConeVolume
;
404 if(ALSource
->DryGainHFAuto
)
405 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
406 if(ALSource
->WetGainHFAuto
)
407 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
412 //4. Calculate Velocity
413 if(DopplerFactor
!= 0.0f
)
415 ALfloat flVSS
, flVLS
;
417 flVLS
= aluDotproduct(ALContext
->Listener
.Velocity
,
419 flVSS
= aluDotproduct(ALSource
->vVelocity
, SourceToListener
);
421 flMaxVelocity
= (DopplerVelocity
* flSpeedOfSound
) / DopplerFactor
;
423 if (flVSS
>= flMaxVelocity
)
424 flVSS
= (flMaxVelocity
- 1.0f
);
425 else if (flVSS
<= -flMaxVelocity
)
426 flVSS
= -flMaxVelocity
+ 1.0f
;
428 if (flVLS
>= flMaxVelocity
)
429 flVLS
= (flMaxVelocity
- 1.0f
);
430 else if (flVLS
<= -flMaxVelocity
)
431 flVLS
= -flMaxVelocity
+ 1.0f
;
433 pitch
[0] = ALSource
->flPitch
*
434 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVLS
)) /
435 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVSS
));
438 pitch
[0] = ALSource
->flPitch
;
440 //5. Align coordinate system axes
441 aluCrossproduct(ALContext
->Listener
.Forward
, ALContext
->Listener
.Up
, U
); // Right-vector
442 aluNormalize(U
); // Normalized Right-vector
443 memcpy(V
, ALContext
->Listener
.Up
, sizeof(V
)); // Up-vector
444 aluNormalize(V
); // Normalized Up-vector
445 memcpy(N
, ALContext
->Listener
.Forward
, sizeof(N
)); // At-vector
446 aluNormalize(N
); // Normalized At-vector
447 Matrix
[0][0] = U
[0]; Matrix
[0][1] = V
[0]; Matrix
[0][2] = -N
[0];
448 Matrix
[1][0] = U
[1]; Matrix
[1][1] = V
[1]; Matrix
[1][2] = -N
[1];
449 Matrix
[2][0] = U
[2]; Matrix
[2][1] = V
[2]; Matrix
[2][2] = -N
[2];
450 aluMatrixVector(Position
, Matrix
);
452 //6. Apply filter gains and filters
453 switch(ALSource
->DirectFilter
.filter
)
455 case AL_FILTER_LOWPASS
:
456 DryMix
*= ALSource
->DirectFilter
.Gain
;
457 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
461 switch(ALSource
->Send
[0].WetFilter
.filter
)
463 case AL_FILTER_LOWPASS
:
464 WetMix
*= ALSource
->Send
[0].WetFilter
.Gain
;
465 WetGainHF
*= ALSource
->Send
[0].WetFilter
.GainHF
;
469 if(ALSource
->AirAbsorptionFactor
> 0.0f
)
470 DryGainHF
*= pow(ALSource
->AirAbsorptionFactor
* AIRABSORBGAINHF
,
471 Distance
* MetersPerUnit
);
473 WetMix
*= ALSource
->Send
[0].Slot
.Gain
;
475 //7. Convert normalized position into pannings, then into channel volumes
476 aluNormalize(Position
);
477 switch(aluChannelsFromFormat(OutputFormat
))
480 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
); //Direct
481 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
); //Direct
482 if(ALSource
->Send
[0].Slot
.effectslot
)
484 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt(1.0f
); //Room
485 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(1.0f
); //Room
489 wetsend
[FRONT_LEFT
] = 0.0f
;
490 wetsend
[FRONT_RIGHT
] = 0.0f
;
495 PanningLR
= 0.5f
+ 0.5f
*Position
[0];
496 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
-PanningLR
); //L Direct
497 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt( PanningLR
); //R Direct
498 if(ALSource
->Send
[0].Slot
.effectslot
)
500 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt(1.0f
-PanningLR
); //L Room
501 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt( PanningLR
); //R Room
505 wetsend
[FRONT_LEFT
] = 0.0f
;
506 wetsend
[FRONT_RIGHT
] = 0.0f
;
511 /* TODO: Add center/lfe channel in spatial calculations? */
513 // Apply a scalar so each individual speaker has more weight
514 PanningLR
= 0.5f
+ (0.5f
*Position
[0]*1.41421356f
);
515 PanningLR
= __min(1.0f
, PanningLR
);
516 PanningLR
= __max(0.0f
, PanningLR
);
517 PanningFB
= 0.5f
+ (0.5f
*Position
[2]*1.41421356f
);
518 PanningFB
= __min(1.0f
, PanningFB
);
519 PanningFB
= __max(0.0f
, PanningFB
);
520 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
521 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
522 drysend
[BACK_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
523 drysend
[BACK_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
524 if(ALSource
->Send
[0].Slot
.effectslot
)
526 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
527 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
528 wetsend
[BACK_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
529 wetsend
[BACK_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
533 wetsend
[FRONT_LEFT
] = 0.0f
;
534 wetsend
[FRONT_RIGHT
] = 0.0f
;
535 wetsend
[BACK_LEFT
] = 0.0f
;
536 wetsend
[BACK_RIGHT
] = 0.0f
;
542 PanningFB
= 1.0f
- fabs(Position
[2]*1.15470054f
);
543 PanningFB
= __min(1.0f
, PanningFB
);
544 PanningFB
= __max(0.0f
, PanningFB
);
545 PanningLR
= 0.5f
+ (0.5*Position
[0]*((1.0f
-PanningFB
)*2.0f
));
546 PanningLR
= __min(1.0f
, PanningLR
);
547 PanningLR
= __max(0.0f
, PanningLR
);
548 if(Position
[2] > 0.0f
)
550 drysend
[BACK_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
551 drysend
[BACK_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
552 drysend
[SIDE_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
553 drysend
[SIDE_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
554 drysend
[FRONT_LEFT
] = 0.0f
;
555 drysend
[FRONT_RIGHT
] = 0.0f
;
556 if(ALSource
->Send
[0].Slot
.effectslot
)
558 wetsend
[BACK_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
559 wetsend
[BACK_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
560 wetsend
[SIDE_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
561 wetsend
[SIDE_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
562 wetsend
[FRONT_LEFT
] = 0.0f
;
563 wetsend
[FRONT_RIGHT
] = 0.0f
;
567 wetsend
[FRONT_LEFT
] = 0.0f
;
568 wetsend
[FRONT_RIGHT
] = 0.0f
;
569 wetsend
[SIDE_LEFT
] = 0.0f
;
570 wetsend
[SIDE_RIGHT
] = 0.0f
;
571 wetsend
[BACK_LEFT
] = 0.0f
;
572 wetsend
[BACK_RIGHT
] = 0.0f
;
578 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
579 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
580 drysend
[SIDE_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
581 drysend
[SIDE_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
582 drysend
[BACK_LEFT
] = 0.0f
;
583 drysend
[BACK_RIGHT
] = 0.0f
;
584 if(ALSource
->Send
[0].Slot
.effectslot
)
586 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
587 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
588 wetsend
[SIDE_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
589 wetsend
[SIDE_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
590 wetsend
[BACK_LEFT
] = 0.0f
;
591 wetsend
[BACK_RIGHT
] = 0.0f
;
595 wetsend
[FRONT_LEFT
] = 0.0f
;
596 wetsend
[FRONT_RIGHT
] = 0.0f
;
597 wetsend
[SIDE_LEFT
] = 0.0f
;
598 wetsend
[SIDE_RIGHT
] = 0.0f
;
599 wetsend
[BACK_LEFT
] = 0.0f
;
600 wetsend
[BACK_RIGHT
] = 0.0f
;
608 *drygainhf
= DryGainHF
;
609 *wetgainhf
= WetGainHF
;
613 *drygainhf
= DryGainHF
;
614 *wetgainhf
= WetGainHF
;
616 //1. Multi-channel buffers always play "normal"
617 drysend
[FRONT_LEFT
] = SourceVolume
* 1.0f
* ListenerGain
;
618 drysend
[FRONT_RIGHT
] = SourceVolume
* 1.0f
* ListenerGain
;
619 drysend
[SIDE_LEFT
] = SourceVolume
* 1.0f
* ListenerGain
;
620 drysend
[SIDE_RIGHT
] = SourceVolume
* 1.0f
* ListenerGain
;
621 drysend
[BACK_LEFT
] = SourceVolume
* 1.0f
* ListenerGain
;
622 drysend
[BACK_RIGHT
] = SourceVolume
* 1.0f
* ListenerGain
;
623 drysend
[CENTER
] = SourceVolume
* 1.0f
* ListenerGain
;
624 drysend
[LFE
] = SourceVolume
* 1.0f
* ListenerGain
;
625 if(ALSource
->Send
[0].Slot
.effectslot
)
627 wetsend
[FRONT_LEFT
] = SourceVolume
* 0.0f
* ListenerGain
;
628 wetsend
[FRONT_RIGHT
] = SourceVolume
* 0.0f
* ListenerGain
;
629 wetsend
[SIDE_LEFT
] = SourceVolume
* 0.0f
* ListenerGain
;
630 wetsend
[SIDE_RIGHT
] = SourceVolume
* 0.0f
* ListenerGain
;
631 wetsend
[BACK_LEFT
] = SourceVolume
* 0.0f
* ListenerGain
;
632 wetsend
[BACK_RIGHT
] = SourceVolume
* 0.0f
* ListenerGain
;
633 wetsend
[CENTER
] = SourceVolume
* 0.0f
* ListenerGain
;
634 wetsend
[LFE
] = SourceVolume
* 0.0f
* ListenerGain
;
638 wetsend
[FRONT_LEFT
] = 0.0f
;
639 wetsend
[FRONT_RIGHT
] = 0.0f
;
640 wetsend
[SIDE_LEFT
] = 0.0f
;
641 wetsend
[SIDE_RIGHT
] = 0.0f
;
642 wetsend
[BACK_LEFT
] = 0.0f
;
643 wetsend
[BACK_RIGHT
] = 0.0f
;
644 wetsend
[CENTER
] = 0.0f
;
649 pitch
[0] = ALSource
->flPitch
;
653 ALvoid
aluMixData(ALCcontext
*ALContext
,ALvoid
*buffer
,ALsizei size
,ALenum format
)
655 static float DryBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
656 static float WetBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
657 ALfloat DrySend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
658 ALfloat WetSend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
659 ALfloat DryGainHF
= 0.0f
;
660 ALfloat WetGainHF
= 0.0f
;
661 ALuint BlockAlign
,BufferSize
;
662 ALuint DataSize
=0,DataPosInt
=0,DataPosFrac
=0;
663 ALuint Channels
,Frequency
,ulExtraSamples
;
665 ALint Looping
,increment
,State
;
666 ALuint Buffer
,fraction
;
673 ALbufferlistitem
*BufferListItem
;
675 ALint64 DataSize64
,DataPos64
;
677 SuspendContext(ALContext
);
681 //Figure output format variables
682 BlockAlign
= aluChannelsFromFormat(format
);
683 BlockAlign
*= aluBytesFromFormat(format
);
689 ALSource
= (ALContext
? ALContext
->Source
: NULL
);
690 SamplesToDo
= min(size
, BUFFERSIZE
);
692 //Clear mixing buffer
693 memset(DryBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
694 memset(WetBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
700 State
= ALSource
->state
;
701 while(State
== AL_PLAYING
&& j
< SamplesToDo
)
708 if((Buffer
= ALSource
->ulBufferID
))
710 ALBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(Buffer
);
712 Data
= ALBuffer
->data
;
713 Channels
= aluChannelsFromFormat(ALBuffer
->format
);
714 DataSize
= ALBuffer
->size
;
715 Frequency
= ALBuffer
->frequency
;
717 CalcSourceParams(ALContext
, ALSource
,
718 (Channels
==1) ? AL_TRUE
: AL_FALSE
,
719 format
, DrySend
, WetSend
, &Pitch
,
720 &DryGainHF
, &WetGainHF
);
723 Pitch
= (Pitch
*Frequency
) / ALContext
->Frequency
;
724 DataSize
/= Channels
* aluBytesFromFormat(ALBuffer
->format
);
727 DataPosInt
= ALSource
->position
;
728 DataPosFrac
= ALSource
->position_fraction
;
730 //Compute 18.14 fixed point step
731 increment
= aluF2L(Pitch
*(1L<<FRACTIONBITS
));
732 if(increment
> (MAX_PITCH
<<FRACTIONBITS
))
733 increment
= (MAX_PITCH
<<FRACTIONBITS
);
735 //Figure out how many samples we can mix.
736 //Pitch must be <= 4 (the number below !)
737 DataSize64
= DataSize
+MAX_PITCH
;
738 DataSize64
<<= FRACTIONBITS
;
739 DataPos64
= DataPosInt
;
740 DataPos64
<<= FRACTIONBITS
;
741 DataPos64
+= DataPosFrac
;
742 BufferSize
= (ALuint
)((DataSize64
-DataPos64
) / increment
);
743 BufferListItem
= ALSource
->queue
;
744 for(loop
= 0; loop
< ALSource
->BuffersPlayed
; loop
++)
747 BufferListItem
= BufferListItem
->next
;
751 if (BufferListItem
->next
)
753 if(BufferListItem
->next
->buffer
&&
754 ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->data
)
756 ulExtraSamples
= min(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->size
, (ALint
)(16*Channels
));
757 memcpy(&Data
[DataSize
*Channels
], ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->data
, ulExtraSamples
);
760 else if (ALSource
->bLooping
)
762 if (ALSource
->queue
->buffer
)
764 if(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->data
)
766 ulExtraSamples
= min(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->size
, (ALint
)(16*Channels
));
767 memcpy(&Data
[DataSize
*Channels
], ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->data
, ulExtraSamples
);
772 BufferSize
= min(BufferSize
, (SamplesToDo
-j
));
774 //Actual sample mixing loop
775 Data
+= DataPosInt
*Channels
;
778 k
= DataPosFrac
>>FRACTIONBITS
;
779 fraction
= DataPosFrac
&FRACTIONMASK
;
782 //First order interpolator
783 ALfloat sample
= (ALfloat
)((ALshort
)(((Data
[k
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[k
+1]*(fraction
)))>>FRACTIONBITS
));
785 //Direct path final mix buffer and panning
786 value
= aluComputeDrySample(ALSource
, DryGainHF
, sample
);
787 DryBuffer
[j
][FRONT_LEFT
] += value
*DrySend
[FRONT_LEFT
];
788 DryBuffer
[j
][FRONT_RIGHT
] += value
*DrySend
[FRONT_RIGHT
];
789 DryBuffer
[j
][SIDE_LEFT
] += value
*DrySend
[SIDE_LEFT
];
790 DryBuffer
[j
][SIDE_RIGHT
] += value
*DrySend
[SIDE_RIGHT
];
791 DryBuffer
[j
][BACK_LEFT
] += value
*DrySend
[BACK_LEFT
];
792 DryBuffer
[j
][BACK_RIGHT
] += value
*DrySend
[BACK_RIGHT
];
793 //Room path final mix buffer and panning
794 value
= aluComputeWetSample(ALSource
, WetGainHF
, sample
);
795 WetBuffer
[j
][FRONT_LEFT
] += value
*WetSend
[FRONT_LEFT
];
796 WetBuffer
[j
][FRONT_RIGHT
] += value
*WetSend
[FRONT_RIGHT
];
797 WetBuffer
[j
][SIDE_LEFT
] += value
*WetSend
[SIDE_LEFT
];
798 WetBuffer
[j
][SIDE_RIGHT
] += value
*WetSend
[SIDE_RIGHT
];
799 WetBuffer
[j
][BACK_LEFT
] += value
*WetSend
[BACK_LEFT
];
800 WetBuffer
[j
][BACK_RIGHT
] += value
*WetSend
[BACK_RIGHT
];
804 //First order interpolator (front left)
805 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
]*(fraction
)))>>FRACTIONBITS
));
806 DryBuffer
[j
][FRONT_LEFT
] += value
*DrySend
[FRONT_LEFT
];
807 WetBuffer
[j
][FRONT_LEFT
] += value
*WetSend
[FRONT_LEFT
];
808 //First order interpolator (front right)
809 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+1]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+1]*(fraction
)))>>FRACTIONBITS
));
810 DryBuffer
[j
][FRONT_RIGHT
] += value
*DrySend
[FRONT_RIGHT
];
811 WetBuffer
[j
][FRONT_RIGHT
] += value
*WetSend
[FRONT_RIGHT
];
819 //First order interpolator (center)
820 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
821 DryBuffer
[j
][CENTER
] += value
*DrySend
[CENTER
];
822 WetBuffer
[j
][CENTER
] += value
*WetSend
[CENTER
];
825 //First order interpolator (lfe)
826 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
827 DryBuffer
[j
][LFE
] += value
*DrySend
[LFE
];
828 WetBuffer
[j
][LFE
] += value
*WetSend
[LFE
];
831 //First order interpolator (back left)
832 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
833 DryBuffer
[j
][BACK_LEFT
] += value
*DrySend
[BACK_LEFT
];
834 WetBuffer
[j
][BACK_LEFT
] += value
*WetSend
[BACK_LEFT
];
836 //First order interpolator (back right)
837 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
838 DryBuffer
[j
][BACK_RIGHT
] += value
*DrySend
[BACK_RIGHT
];
839 WetBuffer
[j
][BACK_RIGHT
] += value
*WetSend
[BACK_RIGHT
];
843 //First order interpolator (side left)
844 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
845 DryBuffer
[j
][SIDE_LEFT
] += value
*DrySend
[SIDE_LEFT
];
846 WetBuffer
[j
][SIDE_LEFT
] += value
*WetSend
[SIDE_LEFT
];
848 //First order interpolator (side right)
849 value
= (ALfloat
)((ALshort
)(((Data
[k
*Channels
+i
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[(k
+1)*Channels
+i
]*(fraction
)))>>FRACTIONBITS
));
850 DryBuffer
[j
][SIDE_RIGHT
] += value
*DrySend
[SIDE_RIGHT
];
851 WetBuffer
[j
][SIDE_RIGHT
] += value
*WetSend
[SIDE_RIGHT
];
856 DataPosFrac
+= increment
;
859 DataPosInt
+= (DataPosFrac
>>FRACTIONBITS
);
860 DataPosFrac
= (DataPosFrac
&FRACTIONMASK
);
863 ALSource
->position
= DataPosInt
;
864 ALSource
->position_fraction
= DataPosFrac
;
867 //Handle looping sources
868 if(!Buffer
|| DataPosInt
>= DataSize
)
873 Looping
= ALSource
->bLooping
;
874 if(ALSource
->BuffersPlayed
< (ALSource
->BuffersInQueue
-1))
876 BufferListItem
= ALSource
->queue
;
877 for(loop
= 0; loop
<= ALSource
->BuffersPlayed
; loop
++)
882 BufferListItem
->bufferstate
= PROCESSED
;
883 BufferListItem
= BufferListItem
->next
;
887 ALSource
->BuffersProcessed
++;
889 ALSource
->ulBufferID
= BufferListItem
->buffer
;
890 ALSource
->position
= DataPosInt
-DataSize
;
891 ALSource
->position_fraction
= DataPosFrac
;
892 ALSource
->BuffersPlayed
++;
899 ALSource
->state
= AL_STOPPED
;
900 ALSource
->inuse
= AL_FALSE
;
901 ALSource
->BuffersPlayed
= ALSource
->BuffersProcessed
= ALSource
->BuffersInQueue
;
902 BufferListItem
= ALSource
->queue
;
903 while(BufferListItem
!= NULL
)
905 BufferListItem
->bufferstate
= PROCESSED
;
906 BufferListItem
= BufferListItem
->next
;
913 ALSource
->state
= AL_PLAYING
;
914 ALSource
->inuse
= AL_TRUE
;
915 ALSource
->play
= AL_TRUE
;
916 ALSource
->BuffersPlayed
= 0;
917 ALSource
->BufferPosition
= 0;
918 ALSource
->lBytesPlayed
= 0;
919 ALSource
->BuffersProcessed
= 0;
920 BufferListItem
= ALSource
->queue
;
921 while(BufferListItem
!= NULL
)
923 BufferListItem
->bufferstate
= PENDING
;
924 BufferListItem
= BufferListItem
->next
;
926 ALSource
->ulBufferID
= ALSource
->queue
->buffer
;
928 ALSource
->position
= DataPosInt
-DataSize
;
929 ALSource
->position_fraction
= DataPosFrac
;
936 State
= ALSource
->state
;
939 ALSource
= ALSource
->next
;
942 //Post processing loop
945 case AL_FORMAT_MONO8
:
946 for(i
= 0;i
< SamplesToDo
;i
++)
948 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
949 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
950 buffer
= ((ALubyte
*)buffer
) + 1;
953 case AL_FORMAT_STEREO8
:
956 for(i
= 0;i
< SamplesToDo
;i
++)
959 samples
[0] = DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
];
960 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
];
961 bs2b_cross_feed(ALContext
->bs2b
, samples
);
962 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(samples
[0])>>8)+128);
963 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(samples
[1])>>8)+128);
964 buffer
= ((ALubyte
*)buffer
) + 2;
969 for(i
= 0;i
< SamplesToDo
;i
++)
971 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
972 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
973 buffer
= ((ALubyte
*)buffer
) + 2;
977 case AL_FORMAT_QUAD8
:
978 for(i
= 0;i
< SamplesToDo
;i
++)
980 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
981 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
982 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
983 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
984 buffer
= ((ALubyte
*)buffer
) + 4;
987 case AL_FORMAT_51CHN8
:
988 for(i
= 0;i
< SamplesToDo
;i
++)
990 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
991 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
992 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
993 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
994 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
995 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
996 buffer
= ((ALubyte
*)buffer
) + 6;
999 case AL_FORMAT_61CHN8
:
1000 for(i
= 0;i
< SamplesToDo
;i
++)
1002 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1003 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1004 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
])>>8)+128);
1005 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1006 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1007 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1008 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1009 buffer
= ((ALubyte
*)buffer
) + 7;
1012 case AL_FORMAT_71CHN8
:
1013 for(i
= 0;i
< SamplesToDo
;i
++)
1015 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
1016 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1017 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
])>>8)+128);
1018 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1019 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
1020 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
1021 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
1022 ((ALubyte
*)buffer
)[7] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
1023 buffer
= ((ALubyte
*)buffer
) + 8;
1027 case AL_FORMAT_MONO16
:
1028 for(i
= 0;i
< SamplesToDo
;i
++)
1030 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
1031 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1032 buffer
= ((ALshort
*)buffer
) + 1;
1035 case AL_FORMAT_STEREO16
:
1038 for(i
= 0;i
< SamplesToDo
;i
++)
1041 samples
[0] = DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
];
1042 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
];
1043 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1044 ((ALshort
*)buffer
)[0] = aluF2S(samples
[0]);
1045 ((ALshort
*)buffer
)[1] = aluF2S(samples
[1]);
1046 buffer
= ((ALshort
*)buffer
) + 2;
1051 for(i
= 0;i
< SamplesToDo
;i
++)
1053 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1054 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1055 buffer
= ((ALshort
*)buffer
) + 2;
1059 case AL_FORMAT_QUAD16
:
1060 for(i
= 0;i
< SamplesToDo
;i
++)
1062 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1063 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1064 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1065 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1066 buffer
= ((ALshort
*)buffer
) + 4;
1069 case AL_FORMAT_51CHN16
:
1070 for(i
= 0;i
< SamplesToDo
;i
++)
1072 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1073 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1074 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1075 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1076 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1077 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1078 buffer
= ((ALshort
*)buffer
) + 6;
1081 case AL_FORMAT_61CHN16
:
1082 for(i
= 0;i
< SamplesToDo
;i
++)
1084 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1085 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1086 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
]);
1087 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
]);
1088 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1089 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1090 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1091 buffer
= ((ALshort
*)buffer
) + 7;
1094 case AL_FORMAT_71CHN16
:
1095 for(i
= 0;i
< SamplesToDo
;i
++)
1097 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
1098 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
1099 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][SIDE_LEFT
] +WetBuffer
[i
][SIDE_LEFT
]);
1100 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
] +WetBuffer
[i
][SIDE_RIGHT
]);
1101 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
1102 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
1103 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
1104 ((ALshort
*)buffer
)[7] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
1105 buffer
= ((ALshort
*)buffer
) + 8;
1113 size
-= SamplesToDo
;
1117 ProcessContext(ALContext
);