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
34 #include "alListener.h"
35 #include "alAuxEffectSlot.h"
40 #if defined (HAVE_FLOAT_H)
45 #define M_PI 3.14159265358979323846 /* pi */
46 #define M_PI_2 1.57079632679489661923 /* pi/2 */
49 #if defined(HAVE_STDINT_H)
51 typedef int64_t ALint64
;
52 #elif defined(HAVE___INT64)
53 typedef __int64 ALint64
;
54 #elif (SIZEOF_LONG == 8)
56 #elif (SIZEOF_LONG_LONG == 8)
57 typedef long long ALint64
;
61 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
63 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
67 #define aluAcos(x) ((ALfloat)acosf((float)(x)))
69 #define aluAcos(x) ((ALfloat)acos((double)(x)))
73 #define aluAtan(x) ((ALfloat)atanf((float)(x)))
75 #define aluAtan(x) ((ALfloat)atan((double)(x)))
79 #define aluFabs(x) ((ALfloat)fabsf((float)(x)))
81 #define aluFabs(x) ((ALfloat)fabs((double)(x)))
85 #if defined(max) && !defined(__max)
88 #if defined(min) && !defined(__min)
92 #define BUFFERSIZE 24000
93 #define FRACTIONBITS 14
94 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
95 #define MAX_PITCH 65536
97 /* Minimum ramp length in milliseconds. The value below was chosen to
98 * adequately reduce clicks and pops from harsh gain changes. */
99 #define MIN_RAMP_LENGTH 16
101 ALboolean DuplicateStereo
= AL_FALSE
;
103 /* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
104 * converted to AL_FORMAT_QUAD* when loaded */
105 __inline ALuint
aluBytesFromFormat(ALenum format
)
109 case AL_FORMAT_MONO8
:
110 case AL_FORMAT_STEREO8
:
111 case AL_FORMAT_QUAD8_LOKI
:
112 case AL_FORMAT_QUAD8
:
113 case AL_FORMAT_51CHN8
:
114 case AL_FORMAT_61CHN8
:
115 case AL_FORMAT_71CHN8
:
118 case AL_FORMAT_MONO16
:
119 case AL_FORMAT_STEREO16
:
120 case AL_FORMAT_QUAD16_LOKI
:
121 case AL_FORMAT_QUAD16
:
122 case AL_FORMAT_51CHN16
:
123 case AL_FORMAT_61CHN16
:
124 case AL_FORMAT_71CHN16
:
127 case AL_FORMAT_MONO_FLOAT32
:
128 case AL_FORMAT_STEREO_FLOAT32
:
129 case AL_FORMAT_QUAD32
:
130 case AL_FORMAT_51CHN32
:
131 case AL_FORMAT_61CHN32
:
132 case AL_FORMAT_71CHN32
:
140 __inline ALuint
aluChannelsFromFormat(ALenum format
)
144 case AL_FORMAT_MONO8
:
145 case AL_FORMAT_MONO16
:
146 case AL_FORMAT_MONO_FLOAT32
:
149 case AL_FORMAT_STEREO8
:
150 case AL_FORMAT_STEREO16
:
151 case AL_FORMAT_STEREO_FLOAT32
:
154 case AL_FORMAT_QUAD8_LOKI
:
155 case AL_FORMAT_QUAD16_LOKI
:
156 case AL_FORMAT_QUAD8
:
157 case AL_FORMAT_QUAD16
:
158 case AL_FORMAT_QUAD32
:
161 case AL_FORMAT_51CHN8
:
162 case AL_FORMAT_51CHN16
:
163 case AL_FORMAT_51CHN32
:
166 case AL_FORMAT_61CHN8
:
167 case AL_FORMAT_61CHN16
:
168 case AL_FORMAT_61CHN32
:
171 case AL_FORMAT_71CHN8
:
172 case AL_FORMAT_71CHN16
:
173 case AL_FORMAT_71CHN32
:
182 static __inline ALfloat
lpFilter(FILTER
*iir
, ALfloat input
)
184 ALfloat
*history
= iir
->history
;
185 ALfloat a
= iir
->coeff
;
186 ALfloat output
= input
;
188 output
= output
+ (history
[0]-output
)*a
;
190 output
= output
+ (history
[1]-output
)*a
;
192 output
= output
+ (history
[2]-output
)*a
;
194 output
= output
+ (history
[3]-output
)*a
;
200 static __inline ALfloat
lpFilterMC(FILTER
*iir
, ALuint chan
, ALfloat input
)
202 ALfloat
*history
= &iir
->history
[chan
*2];
203 ALfloat a
= iir
->coeff
;
204 ALfloat output
= input
;
206 output
= output
+ (history
[0]-output
)*a
;
208 output
= output
+ (history
[1]-output
)*a
;
215 static __inline ALshort
aluF2S(ALfloat Value
)
220 i
= __min( 32767, i
);
221 i
= __max(-32768, i
);
225 static __inline ALvoid
aluCrossproduct(ALfloat
*inVector1
,ALfloat
*inVector2
,ALfloat
*outVector
)
227 outVector
[0] = inVector1
[1]*inVector2
[2] - inVector1
[2]*inVector2
[1];
228 outVector
[1] = inVector1
[2]*inVector2
[0] - inVector1
[0]*inVector2
[2];
229 outVector
[2] = inVector1
[0]*inVector2
[1] - inVector1
[1]*inVector2
[0];
232 static __inline ALfloat
aluDotproduct(ALfloat
*inVector1
,ALfloat
*inVector2
)
234 return inVector1
[0]*inVector2
[0] + inVector1
[1]*inVector2
[1] +
235 inVector1
[2]*inVector2
[2];
238 static __inline ALvoid
aluNormalize(ALfloat
*inVector
)
240 ALfloat length
, inverse_length
;
242 length
= aluSqrt(aluDotproduct(inVector
, inVector
));
245 inverse_length
= 1.0f
/length
;
246 inVector
[0] *= inverse_length
;
247 inVector
[1] *= inverse_length
;
248 inVector
[2] *= inverse_length
;
252 static __inline ALvoid
aluMatrixVector(ALfloat
*vector
,ALfloat matrix
[3][3])
256 result
[0] = vector
[0]*matrix
[0][0] + vector
[1]*matrix
[1][0] + vector
[2]*matrix
[2][0];
257 result
[1] = vector
[0]*matrix
[0][1] + vector
[1]*matrix
[1][1] + vector
[2]*matrix
[2][1];
258 result
[2] = vector
[0]*matrix
[0][2] + vector
[1]*matrix
[1][2] + vector
[2]*matrix
[2][2];
259 memcpy(vector
, result
, sizeof(result
));
262 static __inline ALfloat
aluLUTpos2Angle(ALint pos
)
264 if(pos
< QUADRANT_NUM
)
265 return aluAtan((ALfloat
)pos
/ (ALfloat
)(QUADRANT_NUM
- pos
));
266 if(pos
< 2 * QUADRANT_NUM
)
267 return M_PI_2
+ aluAtan((ALfloat
)(pos
- QUADRANT_NUM
) / (ALfloat
)(2 * QUADRANT_NUM
- pos
));
268 if(pos
< 3 * QUADRANT_NUM
)
269 return aluAtan((ALfloat
)(pos
- 2 * QUADRANT_NUM
) / (ALfloat
)(3 * QUADRANT_NUM
- pos
)) - M_PI
;
270 return aluAtan((ALfloat
)(pos
- 3 * QUADRANT_NUM
) / (ALfloat
)(4 * QUADRANT_NUM
- pos
)) - M_PI_2
;
273 ALvoid
aluInitPanning(ALCcontext
*Context
)
275 ALint pos
, offset
, s
;
276 ALfloat Alpha
, Theta
;
277 ALfloat SpeakerAngle
[OUTPUTCHANNELS
];
278 ALint Speaker2Chan
[OUTPUTCHANNELS
];
280 switch(Context
->Device
->Format
)
282 /* Mono is rendered as stereo, then downmixed during post-process */
283 case AL_FORMAT_MONO8
:
284 case AL_FORMAT_MONO16
:
285 case AL_FORMAT_MONO_FLOAT32
:
286 case AL_FORMAT_STEREO8
:
287 case AL_FORMAT_STEREO16
:
288 case AL_FORMAT_STEREO_FLOAT32
:
289 Context
->NumChan
= 2;
290 Speaker2Chan
[0] = FRONT_LEFT
;
291 Speaker2Chan
[1] = FRONT_RIGHT
;
292 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
293 SpeakerAngle
[1] = 90.0f
* M_PI
/180.0f
;
295 case AL_FORMAT_QUAD8
:
296 case AL_FORMAT_QUAD16
:
297 case AL_FORMAT_QUAD32
:
298 Context
->NumChan
= 4;
299 Speaker2Chan
[0] = BACK_LEFT
;
300 Speaker2Chan
[1] = FRONT_LEFT
;
301 Speaker2Chan
[2] = FRONT_RIGHT
;
302 Speaker2Chan
[3] = BACK_RIGHT
;
303 SpeakerAngle
[0] = -135.0f
* M_PI
/180.0f
;
304 SpeakerAngle
[1] = -45.0f
* M_PI
/180.0f
;
305 SpeakerAngle
[2] = 45.0f
* M_PI
/180.0f
;
306 SpeakerAngle
[3] = 135.0f
* M_PI
/180.0f
;
309 case AL_FORMAT_51CHN8
:
310 case AL_FORMAT_51CHN16
:
311 case AL_FORMAT_51CHN32
:
312 Context
->NumChan
= 5;
313 Speaker2Chan
[0] = BACK_LEFT
;
314 Speaker2Chan
[1] = FRONT_LEFT
;
315 Speaker2Chan
[2] = CENTER
;
316 Speaker2Chan
[3] = FRONT_RIGHT
;
317 Speaker2Chan
[4] = BACK_RIGHT
;
318 SpeakerAngle
[0] = -110.0f
* M_PI
/180.0f
;
319 SpeakerAngle
[1] = -30.0f
* M_PI
/180.0f
;
320 SpeakerAngle
[2] = 0.0f
* M_PI
/180.0f
;
321 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
322 SpeakerAngle
[4] = 110.0f
* M_PI
/180.0f
;
325 case AL_FORMAT_61CHN8
:
326 case AL_FORMAT_61CHN16
:
327 case AL_FORMAT_61CHN32
:
328 Context
->NumChan
= 6;
329 Speaker2Chan
[0] = BACK_LEFT
;
330 Speaker2Chan
[1] = SIDE_LEFT
;
331 Speaker2Chan
[2] = FRONT_LEFT
;
332 Speaker2Chan
[3] = FRONT_RIGHT
;
333 Speaker2Chan
[4] = SIDE_RIGHT
;
334 Speaker2Chan
[5] = BACK_RIGHT
;
335 SpeakerAngle
[0] = -150.0f
* M_PI
/180.0f
;
336 SpeakerAngle
[1] = -90.0f
* M_PI
/180.0f
;
337 SpeakerAngle
[2] = -30.0f
* M_PI
/180.0f
;
338 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
339 SpeakerAngle
[4] = 90.0f
* M_PI
/180.0f
;
340 SpeakerAngle
[5] = 150.0f
* M_PI
/180.0f
;
343 case AL_FORMAT_71CHN8
:
344 case AL_FORMAT_71CHN16
:
345 case AL_FORMAT_71CHN32
:
346 Context
->NumChan
= 7;
347 Speaker2Chan
[0] = BACK_LEFT
;
348 Speaker2Chan
[1] = SIDE_LEFT
;
349 Speaker2Chan
[2] = FRONT_LEFT
;
350 Speaker2Chan
[3] = CENTER
;
351 Speaker2Chan
[4] = FRONT_RIGHT
;
352 Speaker2Chan
[5] = SIDE_RIGHT
;
353 Speaker2Chan
[6] = BACK_RIGHT
;
354 SpeakerAngle
[0] = -150.0f
* M_PI
/180.0f
;
355 SpeakerAngle
[1] = -90.0f
* M_PI
/180.0f
;
356 SpeakerAngle
[2] = -30.0f
* M_PI
/180.0f
;
357 SpeakerAngle
[3] = 0.0f
* M_PI
/180.0f
;
358 SpeakerAngle
[4] = 30.0f
* M_PI
/180.0f
;
359 SpeakerAngle
[5] = 90.0f
* M_PI
/180.0f
;
360 SpeakerAngle
[6] = 150.0f
* M_PI
/180.0f
;
367 for(pos
= 0; pos
< LUT_NUM
; pos
++)
370 Theta
= aluLUTpos2Angle(pos
);
372 /* clear all values */
373 offset
= OUTPUTCHANNELS
* pos
;
374 for(s
= 0; s
< OUTPUTCHANNELS
; s
++)
375 Context
->PanningLUT
[offset
+s
] = 0.0f
;
377 /* set panning values */
378 for(s
= 0; s
< Context
->NumChan
- 1; s
++)
380 if(Theta
>= SpeakerAngle
[s
] && Theta
< SpeakerAngle
[s
+1])
382 /* source between speaker s and speaker s+1 */
383 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
384 (SpeakerAngle
[s
+1]-SpeakerAngle
[s
]);
385 Context
->PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
386 Context
->PanningLUT
[offset
+ Speaker2Chan
[s
+1]] = sin(Alpha
);
390 if(s
== Context
->NumChan
- 1)
392 /* source between last and first speaker */
393 if(Theta
< SpeakerAngle
[0])
394 Theta
+= 2.0f
* M_PI
;
395 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
396 (2.0f
* M_PI
+ SpeakerAngle
[0]-SpeakerAngle
[s
]);
397 Context
->PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
398 Context
->PanningLUT
[offset
+ Speaker2Chan
[0]] = sin(Alpha
);
403 static __inline ALint
aluCart2LUTpos(ALfloat re
, ALfloat im
)
406 ALfloat denom
= aluFabs(re
) + aluFabs(im
);
408 pos
= (ALint
)(QUADRANT_NUM
*aluFabs(im
) / denom
+ 0.5);
411 pos
= 2 * QUADRANT_NUM
- pos
;
417 static ALvoid
CalcSourceParams(ALCcontext
*ALContext
, ALsource
*ALSource
,
418 ALenum isMono
, ALfloat
*drysend
,
419 ALfloat
*wetsend
, ALfloat
*pitch
,
420 ALfloat
*drygainhf
, ALfloat
*wetgainhf
)
422 ALfloat InnerAngle
,OuterAngle
,Angle
,Distance
,DryMix
,WetMix
=0.0f
;
423 ALfloat Direction
[3],Position
[3],SourceToListener
[3];
424 ALfloat MinVolume
,MaxVolume
,MinDist
,MaxDist
,Rolloff
,OuterGainHF
;
425 ALfloat ConeVolume
,SourceVolume
,ListenerGain
;
426 ALfloat U
[3],V
[3],N
[3];
427 ALfloat DopplerFactor
, DopplerVelocity
, flSpeedOfSound
, flMaxVelocity
;
428 ALfloat Matrix
[3][3];
429 ALfloat flAttenuation
;
430 ALfloat RoomAttenuation
;
431 ALfloat MetersPerUnit
;
433 ALfloat DryGainHF
= 1.0f
;
434 ALfloat WetGainHF
= 1.0f
;
435 ALfloat DirGain
, AmbientGain
;
436 const ALfloat
*SpeakerGain
;
440 //Get context properties
441 DopplerFactor
= ALContext
->DopplerFactor
* ALSource
->DopplerFactor
;
442 DopplerVelocity
= ALContext
->DopplerVelocity
;
443 flSpeedOfSound
= ALContext
->flSpeedOfSound
;
445 //Get listener properties
446 ListenerGain
= ALContext
->Listener
.Gain
;
447 MetersPerUnit
= ALContext
->Listener
.MetersPerUnit
;
449 //Get source properties
450 SourceVolume
= ALSource
->flGain
;
451 memcpy(Position
, ALSource
->vPosition
, sizeof(ALSource
->vPosition
));
452 memcpy(Direction
, ALSource
->vOrientation
, sizeof(ALSource
->vOrientation
));
453 MinVolume
= ALSource
->flMinGain
;
454 MaxVolume
= ALSource
->flMaxGain
;
455 MinDist
= ALSource
->flRefDistance
;
456 MaxDist
= ALSource
->flMaxDistance
;
457 Rolloff
= ALSource
->flRollOffFactor
;
458 InnerAngle
= ALSource
->flInnerAngle
;
459 OuterAngle
= ALSource
->flOuterAngle
;
460 OuterGainHF
= ALSource
->OuterGainHF
;
461 RoomRolloff
= ALSource
->RoomRolloffFactor
;
463 //Only apply 3D calculations for mono buffers
464 if(isMono
!= AL_FALSE
)
466 //1. Translate Listener to origin (convert to head relative)
467 // Note that Direction and SourceToListener are *not* transformed.
468 // SourceToListener is used with the source and listener velocities,
469 // which are untransformed, and Direction is used with SourceToListener
470 // for the sound cone
471 if(ALSource
->bHeadRelative
==AL_FALSE
)
473 // Build transform matrix
474 aluCrossproduct(ALContext
->Listener
.Forward
, ALContext
->Listener
.Up
, U
); // Right-vector
475 aluNormalize(U
); // Normalized Right-vector
476 memcpy(V
, ALContext
->Listener
.Up
, sizeof(V
)); // Up-vector
477 aluNormalize(V
); // Normalized Up-vector
478 memcpy(N
, ALContext
->Listener
.Forward
, sizeof(N
)); // At-vector
479 aluNormalize(N
); // Normalized At-vector
480 Matrix
[0][0] = U
[0]; Matrix
[0][1] = V
[0]; Matrix
[0][2] = -N
[0];
481 Matrix
[1][0] = U
[1]; Matrix
[1][1] = V
[1]; Matrix
[1][2] = -N
[1];
482 Matrix
[2][0] = U
[2]; Matrix
[2][1] = V
[2]; Matrix
[2][2] = -N
[2];
484 // Translate source position into listener space
485 Position
[0] -= ALContext
->Listener
.Position
[0];
486 Position
[1] -= ALContext
->Listener
.Position
[1];
487 Position
[2] -= ALContext
->Listener
.Position
[2];
489 SourceToListener
[0] = -Position
[0];
490 SourceToListener
[1] = -Position
[1];
491 SourceToListener
[2] = -Position
[2];
493 // Transform source position and direction into listener space
494 aluMatrixVector(Position
, Matrix
);
498 SourceToListener
[0] = -Position
[0];
499 SourceToListener
[1] = -Position
[1];
500 SourceToListener
[2] = -Position
[2];
502 aluNormalize(SourceToListener
);
503 aluNormalize(Direction
);
505 //2. Calculate distance attenuation
506 Distance
= aluSqrt(aluDotproduct(Position
, Position
));
508 if(ALSource
->Send
[0].Slot
)
510 if(ALSource
->Send
[0].Slot
->effect
.type
== AL_EFFECT_REVERB
)
511 RoomRolloff
+= ALSource
->Send
[0].Slot
->effect
.Reverb
.RoomRolloffFactor
;
514 flAttenuation
= 1.0f
;
515 RoomAttenuation
= 1.0f
;
516 switch (ALSource
->DistanceModel
)
518 case AL_INVERSE_DISTANCE_CLAMPED
:
519 Distance
=__max(Distance
,MinDist
);
520 Distance
=__min(Distance
,MaxDist
);
521 if (MaxDist
< MinDist
)
524 case AL_INVERSE_DISTANCE
:
527 if ((MinDist
+ (Rolloff
* (Distance
- MinDist
))) > 0.0f
)
528 flAttenuation
= MinDist
/ (MinDist
+ (Rolloff
* (Distance
- MinDist
)));
529 if ((MinDist
+ (RoomRolloff
* (Distance
- MinDist
))) > 0.0f
)
530 RoomAttenuation
= MinDist
/ (MinDist
+ (RoomRolloff
* (Distance
- MinDist
)));
534 case AL_LINEAR_DISTANCE_CLAMPED
:
535 Distance
=__max(Distance
,MinDist
);
536 Distance
=__min(Distance
,MaxDist
);
537 if (MaxDist
< MinDist
)
540 case AL_LINEAR_DISTANCE
:
541 Distance
=__min(Distance
,MaxDist
);
542 if (MaxDist
!= MinDist
)
544 flAttenuation
= 1.0f
- (Rolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
545 RoomAttenuation
= 1.0f
- (RoomRolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
549 case AL_EXPONENT_DISTANCE_CLAMPED
:
550 Distance
=__max(Distance
,MinDist
);
551 Distance
=__min(Distance
,MaxDist
);
552 if (MaxDist
< MinDist
)
555 case AL_EXPONENT_DISTANCE
:
556 if ((Distance
> 0.0f
) && (MinDist
> 0.0f
))
558 flAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -Rolloff
);
559 RoomAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -RoomRolloff
);
564 flAttenuation
= 1.0f
;
565 RoomAttenuation
= 1.0f
;
569 // Distance-based air absorption
570 if(ALSource
->AirAbsorptionFactor
> 0.0f
&& ALContext
->DistanceModel
!= AL_NONE
)
572 ALfloat dist
= Distance
-MinDist
;
575 if(dist
< 0.0f
) dist
= 0.0f
;
576 // Absorption calculation is done in dB
577 absorb
= (ALSource
->AirAbsorptionFactor
*AIRABSORBGAINDBHF
) *
578 (Distance
*MetersPerUnit
);
579 // Convert dB to linear gain before applying
580 absorb
= pow(10.0, absorb
/20.0);
585 // Source Gain + Attenuation and clamp to Min/Max Gain
586 DryMix
= SourceVolume
* flAttenuation
;
587 DryMix
= __min(DryMix
,MaxVolume
);
588 DryMix
= __max(DryMix
,MinVolume
);
590 WetMix
= SourceVolume
* RoomAttenuation
;
591 WetMix
= __min(WetMix
,MaxVolume
);
592 WetMix
= __max(WetMix
,MinVolume
);
594 //3. Apply directional soundcones
595 Angle
= aluAcos(aluDotproduct(Direction
,SourceToListener
)) * 180.0f
/
597 if(Angle
>= InnerAngle
&& Angle
<= OuterAngle
)
599 ALfloat scale
= (Angle
-InnerAngle
) / (OuterAngle
-InnerAngle
);
600 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
)*scale
);
601 DryMix
*= ConeVolume
;
602 if(ALSource
->WetGainAuto
)
603 WetMix
*= ConeVolume
;
604 if(ALSource
->DryGainHFAuto
)
605 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
606 if(ALSource
->WetGainHFAuto
)
607 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
609 else if(Angle
> OuterAngle
)
611 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
));
612 DryMix
*= ConeVolume
;
613 if(ALSource
->WetGainAuto
)
614 WetMix
*= ConeVolume
;
615 if(ALSource
->DryGainHFAuto
)
616 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
617 if(ALSource
->WetGainHFAuto
)
618 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
621 //4. Calculate Velocity
622 if(DopplerFactor
!= 0.0f
)
624 ALfloat flVSS
, flVLS
= 0.0f
;
626 if(ALSource
->bHeadRelative
==AL_FALSE
)
627 flVLS
= aluDotproduct(ALContext
->Listener
.Velocity
, SourceToListener
);
628 flVSS
= aluDotproduct(ALSource
->vVelocity
, SourceToListener
);
630 flMaxVelocity
= (DopplerVelocity
* flSpeedOfSound
) / DopplerFactor
;
632 if (flVSS
>= flMaxVelocity
)
633 flVSS
= (flMaxVelocity
- 1.0f
);
634 else if (flVSS
<= -flMaxVelocity
)
635 flVSS
= -flMaxVelocity
+ 1.0f
;
637 if (flVLS
>= flMaxVelocity
)
638 flVLS
= (flMaxVelocity
- 1.0f
);
639 else if (flVLS
<= -flMaxVelocity
)
640 flVLS
= -flMaxVelocity
+ 1.0f
;
642 pitch
[0] = ALSource
->flPitch
*
643 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVLS
)) /
644 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVSS
));
647 pitch
[0] = ALSource
->flPitch
;
649 if(ALSource
->Send
[0].Slot
&&
650 ALSource
->Send
[0].Slot
->effect
.type
!= AL_EFFECT_NULL
)
652 if(ALSource
->Send
[0].Slot
->AuxSendAuto
)
654 // Apply minimal attenuation in place of missing statistical
656 WetMix
*= pow(DryMix
, 1.0f
/ 2.0f
);
660 // If the slot's auxilliary send auto is off, the data sent to the
661 // effect slot is the same as the dry path, sans filter effects
663 WetGainHF
= DryGainHF
;
666 // Note that this is really applied by the effect slot. However,
667 // it's easier (more optimal) to handle it here.
668 if(ALSource
->Send
[0].Slot
->effect
.type
== AL_EFFECT_REVERB
)
669 WetGainHF
*= ALSource
->Send
[0].Slot
->effect
.Reverb
.GainHF
;
677 //5. Apply filter gains and filters
678 switch(ALSource
->DirectFilter
.type
)
680 case AL_FILTER_LOWPASS
:
681 DryMix
*= ALSource
->DirectFilter
.Gain
;
682 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
686 switch(ALSource
->Send
[0].WetFilter
.type
)
688 case AL_FILTER_LOWPASS
:
689 WetMix
*= ALSource
->Send
[0].WetFilter
.Gain
;
690 WetGainHF
*= ALSource
->Send
[0].WetFilter
.GainHF
;
694 DryMix
*= ListenerGain
;
695 WetMix
*= ListenerGain
;
697 // Use energy-preserving panning algorithm for multi-speaker playback
698 aluNormalize(Position
);
700 pos
= aluCart2LUTpos(-Position
[2], Position
[0]);
701 SpeakerGain
= &ALContext
->PanningLUT
[OUTPUTCHANNELS
* pos
];
703 DirGain
= aluSqrt(Position
[0]*Position
[0] + Position
[2]*Position
[2]);
704 // elevation adjustment for directional gain. this sucks, but
705 // has low complexity
706 AmbientGain
= 1.0/aluSqrt(ALContext
->NumChan
) * (1.0-DirGain
);
707 for(s
= 0; s
< OUTPUTCHANNELS
; s
++)
709 ALfloat gain
= SpeakerGain
[s
]*DirGain
+ AmbientGain
;
710 drysend
[s
] = DryMix
* gain
;
714 // Update filter coefficients. Calculations based on the I3DL2 spec.
715 cw
= cos(2.0f
*3.141592654f
* LOWPASSFREQCUTOFF
/ ALContext
->Frequency
);
716 // We use four chained one-pole filters, so we need to take the fourth
717 // root of the squared gain, which is the same as the square root of
719 // Be careful with gains < 0.0001, as that causes the coefficient to
720 // head towards 1, which will flatten the signal
721 g
= aluSqrt(__max(DryGainHF
, 0.0001f
));
723 if(g
< 0.9999f
) // 1-epsilon
724 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
725 ALSource
->iirFilter
.coeff
= a
;
727 g
= aluSqrt(__max(WetGainHF
, 0.0001f
));
729 if(g
< 0.9999f
) // 1-epsilon
730 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
731 ALSource
->Send
[0].iirFilter
.coeff
= a
;
733 *drygainhf
= DryGainHF
;
734 *wetgainhf
= WetGainHF
;
738 //1. Multi-channel buffers always play "normal"
739 pitch
[0] = ALSource
->flPitch
;
741 DryMix
= SourceVolume
;
743 switch(ALSource
->DirectFilter
.type
)
745 case AL_FILTER_LOWPASS
:
746 DryMix
*= ALSource
->DirectFilter
.Gain
;
747 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
751 drysend
[FRONT_LEFT
] = DryMix
* ListenerGain
;
752 drysend
[FRONT_RIGHT
] = DryMix
* ListenerGain
;
753 drysend
[SIDE_LEFT
] = DryMix
* ListenerGain
;
754 drysend
[SIDE_RIGHT
] = DryMix
* ListenerGain
;
755 drysend
[BACK_LEFT
] = DryMix
* ListenerGain
;
756 drysend
[BACK_RIGHT
] = DryMix
* ListenerGain
;
757 drysend
[CENTER
] = DryMix
* ListenerGain
;
758 drysend
[LFE
] = DryMix
* ListenerGain
;
761 cw
= cos(2.0f
*3.141592654f
* LOWPASSFREQCUTOFF
/ ALContext
->Frequency
);
762 g
= __max(DryGainHF
, 0.01f
);
764 if(g
< 0.9999f
) // 1-epsilon
765 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
766 ALSource
->iirFilter
.coeff
= a
;
767 ALSource
->Send
[0].iirFilter
.coeff
= 0.0f
;
769 *drygainhf
= DryGainHF
;
770 *wetgainhf
= WetGainHF
;
774 static __inline ALshort
lerp(ALshort val1
, ALshort val2
, ALint frac
)
776 return val1
+ (((val2
-val1
)*frac
)>>FRACTIONBITS
);
779 ALvoid
aluMixData(ALCcontext
*ALContext
,ALvoid
*buffer
,ALsizei size
,ALenum format
)
781 static float DryBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
782 static float WetBuffer
[BUFFERSIZE
];
783 ALfloat newDrySend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
784 ALfloat newWetSend
= 0.0f
;
785 ALfloat DryGainHF
= 0.0f
;
786 ALfloat WetGainHF
= 0.0f
;
790 ALfloat dryGainStep
[OUTPUTCHANNELS
];
792 ALuint BlockAlign
,BufferSize
;
793 ALuint DataSize
=0,DataPosInt
=0,DataPosFrac
=0;
794 ALuint Channels
,Frequency
,ulExtraSamples
;
802 ALeffectslot
*ALEffectSlot
;
806 ALbufferlistitem
*BufferListItem
;
808 ALint64 DataSize64
,DataPos64
;
809 FILTER
*DryFilter
, *WetFilter
;
812 SuspendContext(ALContext
);
814 #if defined(HAVE_FESETROUND)
815 fpuState
= fegetround();
816 fesetround(FE_TOWARDZERO
);
817 #elif defined(HAVE__CONTROLFP)
818 fpuState
= _controlfp(0, 0);
819 _controlfp(_RC_CHOP
, _MCW_RC
);
824 //Figure output format variables
825 BlockAlign
= aluChannelsFromFormat(format
);
826 BlockAlign
*= aluBytesFromFormat(format
);
832 SamplesToDo
= min(size
, BUFFERSIZE
);
835 ALEffectSlot
= ALContext
->AuxiliaryEffectSlot
;
836 ALSource
= ALContext
->Source
;
837 rampLength
= ALContext
->Frequency
* MIN_RAMP_LENGTH
/ 1000;
845 rampLength
= max(rampLength
, SamplesToDo
);
847 //Clear mixing buffer
848 memset(WetBuffer
, 0, SamplesToDo
*sizeof(ALfloat
));
849 memset(DryBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
855 State
= ALSource
->state
;
857 while(State
== AL_PLAYING
&& j
< SamplesToDo
)
864 if((Buffer
= ALSource
->ulBufferID
))
866 ALBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(Buffer
);
868 Data
= ALBuffer
->data
;
869 Channels
= aluChannelsFromFormat(ALBuffer
->format
);
870 DataSize
= ALBuffer
->size
;
871 DataSize
/= Channels
* aluBytesFromFormat(ALBuffer
->format
);
872 Frequency
= ALBuffer
->frequency
;
873 DataPosInt
= ALSource
->position
;
874 DataPosFrac
= ALSource
->position_fraction
;
876 if(DataPosInt
>= DataSize
)
879 CalcSourceParams(ALContext
, ALSource
,
880 (Channels
==1) ? AL_TRUE
: AL_FALSE
,
881 newDrySend
, &newWetSend
, &Pitch
,
882 &DryGainHF
, &WetGainHF
);
884 Pitch
= (Pitch
*Frequency
) / ALContext
->Frequency
;
887 DryFilter
= &ALSource
->iirFilter
;
888 WetFilter
= &ALSource
->Send
[0].iirFilter
;
889 DrySend
= ALSource
->DryGains
;
890 WetSend
= &ALSource
->WetGain
;
892 //Compute the gain steps for each output channel
893 if(ALSource
->FirstStart
&& DataPosInt
== 0 && DataPosFrac
== 0)
895 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
897 DrySend
[i
] = newDrySend
[i
];
900 *WetSend
= newWetSend
;
905 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
906 dryGainStep
[i
] = (newDrySend
[i
]-DrySend
[i
]) / rampLength
;
907 wetGainStep
= (newWetSend
-(*WetSend
)) / rampLength
;
909 ALSource
->FirstStart
= AL_FALSE
;
911 //Compute 18.14 fixed point step
912 if(Pitch
> (float)MAX_PITCH
)
913 Pitch
= (float)MAX_PITCH
;
914 increment
= (ALint
)(Pitch
*(ALfloat
)(1L<<FRACTIONBITS
));
916 increment
= (1<<FRACTIONBITS
);
918 //Figure out how many samples we can mix.
919 DataSize64
= DataSize
;
920 DataSize64
<<= FRACTIONBITS
;
921 DataPos64
= DataPosInt
;
922 DataPos64
<<= FRACTIONBITS
;
923 DataPos64
+= DataPosFrac
;
924 BufferSize
= (ALuint
)((DataSize64
-DataPos64
+(increment
-1)) / increment
);
926 BufferListItem
= ALSource
->queue
;
927 for(loop
= 0; loop
< ALSource
->BuffersPlayed
; loop
++)
930 BufferListItem
= BufferListItem
->next
;
934 if (BufferListItem
->next
)
936 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
);
937 if(NextBuf
&& NextBuf
->data
)
939 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
940 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
943 else if (ALSource
->bLooping
)
945 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
);
946 if (NextBuf
&& NextBuf
->data
)
948 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
949 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
953 memset(&Data
[DataSize
*Channels
], 0, (ALBuffer
->padding
*Channels
*2));
955 BufferSize
= min(BufferSize
, (SamplesToDo
-j
));
957 //Actual sample mixing loop
959 Data
+= DataPosInt
*Channels
;
962 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
963 DrySend
[i
] += dryGainStep
[i
];
964 *WetSend
+= wetGainStep
;
968 ALfloat sample
, outsamp
;
969 //First order interpolator
970 sample
= lerp(Data
[k
], Data
[k
+1], DataPosFrac
);
972 //Direct path final mix buffer and panning
973 outsamp
= lpFilter(DryFilter
, sample
);
974 DryBuffer
[j
][FRONT_LEFT
] += outsamp
*DrySend
[FRONT_LEFT
];
975 DryBuffer
[j
][FRONT_RIGHT
] += outsamp
*DrySend
[FRONT_RIGHT
];
976 DryBuffer
[j
][SIDE_LEFT
] += outsamp
*DrySend
[SIDE_LEFT
];
977 DryBuffer
[j
][SIDE_RIGHT
] += outsamp
*DrySend
[SIDE_RIGHT
];
978 DryBuffer
[j
][BACK_LEFT
] += outsamp
*DrySend
[BACK_LEFT
];
979 DryBuffer
[j
][BACK_RIGHT
] += outsamp
*DrySend
[BACK_RIGHT
];
980 DryBuffer
[j
][CENTER
] += outsamp
*DrySend
[CENTER
];
981 //Room path final mix buffer and panning
982 outsamp
= lpFilter(WetFilter
, sample
);
983 WetBuffer
[j
] += outsamp
*(*WetSend
);
987 ALfloat samp1
, samp2
;
988 //First order interpolator (front left)
989 samp1
= lerp(Data
[k
*Channels
], Data
[(k
+1)*Channels
], DataPosFrac
);
990 samp1
= lpFilterMC(DryFilter
, FRONT_LEFT
, samp1
);
991 DryBuffer
[j
][FRONT_LEFT
] += samp1
*DrySend
[FRONT_LEFT
];
992 //First order interpolator (front right)
993 samp2
= lerp(Data
[k
*Channels
+1], Data
[(k
+1)*Channels
+1], DataPosFrac
);
994 samp2
= lpFilterMC(DryFilter
, FRONT_RIGHT
, samp2
);
995 DryBuffer
[j
][FRONT_RIGHT
] += samp2
*DrySend
[FRONT_RIGHT
];
1003 //First order interpolator (center)
1004 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
1005 DryBuffer
[j
][CENTER
] += lpFilterMC(DryFilter
, CENTER
, value
)*DrySend
[CENTER
];
1008 //First order interpolator (lfe)
1009 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
1010 DryBuffer
[j
][LFE
] += lpFilterMC(DryFilter
, LFE
, value
)*DrySend
[LFE
];
1013 //First order interpolator (back left)
1014 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
1015 DryBuffer
[j
][BACK_LEFT
] += lpFilterMC(DryFilter
, BACK_LEFT
, value
)*DrySend
[BACK_LEFT
];
1017 //First order interpolator (back right)
1018 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
1019 DryBuffer
[j
][BACK_RIGHT
] += lpFilterMC(DryFilter
, BACK_RIGHT
, value
)*DrySend
[BACK_RIGHT
];
1023 //First order interpolator (side left)
1024 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
1025 DryBuffer
[j
][SIDE_LEFT
] += lpFilterMC(DryFilter
, SIDE_LEFT
, value
)*DrySend
[SIDE_LEFT
];
1027 //First order interpolator (side right)
1028 value
= lerp(Data
[k
*Channels
+i
], Data
[(k
+1)*Channels
+i
], DataPosFrac
);
1029 DryBuffer
[j
][SIDE_RIGHT
] += lpFilterMC(DryFilter
, SIDE_RIGHT
, value
)*DrySend
[SIDE_RIGHT
];
1033 else if(DuplicateStereo
)
1035 //Duplicate stereo channels on the back speakers
1036 DryBuffer
[j
][BACK_LEFT
] += samp1
*DrySend
[BACK_LEFT
];
1037 DryBuffer
[j
][BACK_RIGHT
] += samp2
*DrySend
[BACK_RIGHT
];
1040 DataPosFrac
+= increment
;
1041 k
+= DataPosFrac
>>FRACTIONBITS
;
1042 DataPosFrac
&= FRACTIONMASK
;
1047 //Update source info
1048 ALSource
->position
= DataPosInt
;
1049 ALSource
->position_fraction
= DataPosFrac
;
1054 //Handle looping sources
1055 if(!Buffer
|| DataPosInt
>= DataSize
)
1060 Looping
= ALSource
->bLooping
;
1061 if(ALSource
->BuffersPlayed
< (ALSource
->BuffersInQueue
-1))
1063 BufferListItem
= ALSource
->queue
;
1064 for(loop
= 0; loop
<= ALSource
->BuffersPlayed
; loop
++)
1069 BufferListItem
->bufferstate
= PROCESSED
;
1070 BufferListItem
= BufferListItem
->next
;
1074 ALSource
->ulBufferID
= BufferListItem
->buffer
;
1075 ALSource
->position
= DataPosInt
-DataSize
;
1076 ALSource
->position_fraction
= DataPosFrac
;
1077 ALSource
->BuffersPlayed
++;
1084 ALSource
->state
= AL_STOPPED
;
1085 ALSource
->inuse
= AL_FALSE
;
1086 ALSource
->BuffersPlayed
= ALSource
->BuffersInQueue
;
1087 BufferListItem
= ALSource
->queue
;
1088 while(BufferListItem
!= NULL
)
1090 BufferListItem
->bufferstate
= PROCESSED
;
1091 BufferListItem
= BufferListItem
->next
;
1093 ALSource
->position
= DataSize
;
1094 ALSource
->position_fraction
= 0;
1098 /* alSourceRewind */
1100 ALSource
->state
= AL_PLAYING
;
1101 ALSource
->inuse
= AL_TRUE
;
1102 ALSource
->play
= AL_TRUE
;
1103 ALSource
->BuffersPlayed
= 0;
1104 BufferListItem
= ALSource
->queue
;
1105 while(BufferListItem
!= NULL
)
1107 BufferListItem
->bufferstate
= PENDING
;
1108 BufferListItem
= BufferListItem
->next
;
1110 ALSource
->ulBufferID
= ALSource
->queue
->buffer
;
1112 if(ALSource
->BuffersInQueue
== 1)
1113 ALSource
->position
= DataPosInt
%DataSize
;
1115 ALSource
->position
= DataPosInt
-DataSize
;
1116 ALSource
->position_fraction
= DataPosFrac
;
1123 State
= ALSource
->state
;
1126 ALSource
= ALSource
->next
;
1129 // effect slot processing
1132 if(ALEffectSlot
->effect
.type
== AL_EFFECT_REVERB
)
1133 VerbProcess(ALEffectSlot
->ReverbState
, SamplesToDo
, WetBuffer
, DryBuffer
);
1135 ALEffectSlot
= ALEffectSlot
->next
;
1138 //Post processing loop
1141 case AL_FORMAT_MONO8
:
1142 for(i
= 0;i
< SamplesToDo
;i
++)
1144 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1145 buffer
= ((ALubyte
*)buffer
) + 1;
1148 case AL_FORMAT_STEREO8
:
1149 if(ALContext
&& ALContext
->bs2b
)
1151 for(i
= 0;i
< SamplesToDo
;i
++)
1154 samples
[0] = DryBuffer
[i
][FRONT_LEFT
];
1155 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
];
1156 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1157 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(samples
[0])>>8)+128);
1158 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(samples
[1])>>8)+128);
1159 buffer
= ((ALubyte
*)buffer
) + 2;
1164 for(i
= 0;i
< SamplesToDo
;i
++)
1166 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1167 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1168 buffer
= ((ALubyte
*)buffer
) + 2;
1172 case AL_FORMAT_QUAD8
:
1173 for(i
= 0;i
< SamplesToDo
;i
++)
1175 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1176 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1177 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1178 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1179 buffer
= ((ALubyte
*)buffer
) + 4;
1182 case AL_FORMAT_51CHN8
:
1183 for(i
= 0;i
< SamplesToDo
;i
++)
1185 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1186 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1187 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1188 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
])>>8)+128);
1189 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1190 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1191 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1193 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1194 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1195 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
])>>8)+128);
1196 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1198 buffer
= ((ALubyte
*)buffer
) + 6;
1201 case AL_FORMAT_61CHN8
:
1202 for(i
= 0;i
< SamplesToDo
;i
++)
1204 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1205 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1207 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1208 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1209 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1211 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1212 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1213 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1215 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
])>>8)+128);
1216 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1217 buffer
= ((ALubyte
*)buffer
) + 7;
1220 case AL_FORMAT_71CHN8
:
1221 for(i
= 0;i
< SamplesToDo
;i
++)
1223 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1224 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1226 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
])>>8)+128);
1227 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1228 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1229 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1231 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1232 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1233 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
])>>8)+128);
1234 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1236 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
])>>8)+128);
1237 ((ALubyte
*)buffer
)[7] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1238 buffer
= ((ALubyte
*)buffer
) + 8;
1242 case AL_FORMAT_MONO16
:
1243 for(i
= 0;i
< SamplesToDo
;i
++)
1245 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]);
1246 buffer
= ((ALshort
*)buffer
) + 1;
1249 case AL_FORMAT_STEREO16
:
1250 if(ALContext
&& ALContext
->bs2b
)
1252 for(i
= 0;i
< SamplesToDo
;i
++)
1255 samples
[0] = DryBuffer
[i
][FRONT_LEFT
];
1256 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
];
1257 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1258 ((ALshort
*)buffer
)[0] = aluF2S(samples
[0]);
1259 ((ALshort
*)buffer
)[1] = aluF2S(samples
[1]);
1260 buffer
= ((ALshort
*)buffer
) + 2;
1265 for(i
= 0;i
< SamplesToDo
;i
++)
1267 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1268 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1269 buffer
= ((ALshort
*)buffer
) + 2;
1273 case AL_FORMAT_QUAD16
:
1274 for(i
= 0;i
< SamplesToDo
;i
++)
1276 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1277 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1278 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1279 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1280 buffer
= ((ALshort
*)buffer
) + 4;
1283 case AL_FORMAT_51CHN16
:
1284 for(i
= 0;i
< SamplesToDo
;i
++)
1286 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1287 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1289 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][CENTER
]);
1290 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
]);
1291 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1292 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1294 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1295 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1296 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
]);
1297 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
]);
1299 buffer
= ((ALshort
*)buffer
) + 6;
1302 case AL_FORMAT_61CHN16
:
1303 for(i
= 0;i
< SamplesToDo
;i
++)
1305 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1306 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1308 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][LFE
]);
1309 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1310 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1312 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1313 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1314 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][LFE
]);
1316 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][SIDE_LEFT
]);
1317 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
]);
1318 buffer
= ((ALshort
*)buffer
) + 7;
1321 case AL_FORMAT_71CHN16
:
1322 for(i
= 0;i
< SamplesToDo
;i
++)
1324 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1325 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1327 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][CENTER
]);
1328 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
]);
1329 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1330 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1332 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1333 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1334 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
]);
1335 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
]);
1337 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_LEFT
]);
1338 ((ALshort
*)buffer
)[7] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
]);
1339 buffer
= ((ALshort
*)buffer
) + 8;
1347 size
-= SamplesToDo
;
1350 #if defined(HAVE_FESETROUND)
1351 fesetround(fpuState
);
1352 #elif defined(HAVE__CONTROLFP)
1353 _controlfp(fpuState
, 0xfffff);
1356 ProcessContext(ALContext
);