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
37 #include "alListener.h"
38 #include "alAuxEffectSlot.h"
43 #if defined (HAVE_FLOAT_H)
48 #define M_PI 3.14159265358979323846 /* pi */
49 #define M_PI_2 1.57079632679489661923 /* pi/2 */
52 #if defined(HAVE_STDINT_H)
54 typedef int64_t ALint64
;
55 #elif defined(HAVE___INT64)
56 typedef __int64 ALint64
;
57 #elif (SIZEOF_LONG == 8)
59 #elif (SIZEOF_LONG_LONG == 8)
60 typedef long long ALint64
;
64 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
66 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
70 #define aluAcos(x) ((ALfloat)acosf((float)(x)))
72 #define aluAcos(x) ((ALfloat)acos((double)(x)))
76 #define aluAtan(x) ((ALfloat)atanf((float)(x)))
78 #define aluAtan(x) ((ALfloat)atan((double)(x)))
82 #define aluFabs(x) ((ALfloat)fabsf((float)(x)))
84 #define aluFabs(x) ((ALfloat)fabs((double)(x)))
88 #if defined(max) && !defined(__max)
91 #if defined(min) && !defined(__min)
95 #define FRACTIONBITS 14
96 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
97 #define MAX_PITCH 65536
99 /* Minimum ramp length in milliseconds. The value below was chosen to
100 * adequately reduce clicks and pops from harsh gain changes. */
101 #define MIN_RAMP_LENGTH 16
103 ALboolean DuplicateStereo
= AL_FALSE
;
105 /* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
106 * converted to AL_FORMAT_QUAD* when loaded */
107 __inline ALuint
aluBytesFromFormat(ALenum format
)
111 case AL_FORMAT_MONO8
:
112 case AL_FORMAT_STEREO8
:
113 case AL_FORMAT_QUAD8_LOKI
:
114 case AL_FORMAT_QUAD8
:
115 case AL_FORMAT_51CHN8
:
116 case AL_FORMAT_61CHN8
:
117 case AL_FORMAT_71CHN8
:
120 case AL_FORMAT_MONO16
:
121 case AL_FORMAT_STEREO16
:
122 case AL_FORMAT_QUAD16_LOKI
:
123 case AL_FORMAT_QUAD16
:
124 case AL_FORMAT_51CHN16
:
125 case AL_FORMAT_61CHN16
:
126 case AL_FORMAT_71CHN16
:
129 case AL_FORMAT_MONO_FLOAT32
:
130 case AL_FORMAT_STEREO_FLOAT32
:
131 case AL_FORMAT_QUAD32
:
132 case AL_FORMAT_51CHN32
:
133 case AL_FORMAT_61CHN32
:
134 case AL_FORMAT_71CHN32
:
142 __inline ALuint
aluChannelsFromFormat(ALenum format
)
146 case AL_FORMAT_MONO8
:
147 case AL_FORMAT_MONO16
:
148 case AL_FORMAT_MONO_FLOAT32
:
151 case AL_FORMAT_STEREO8
:
152 case AL_FORMAT_STEREO16
:
153 case AL_FORMAT_STEREO_FLOAT32
:
156 case AL_FORMAT_QUAD8_LOKI
:
157 case AL_FORMAT_QUAD16_LOKI
:
158 case AL_FORMAT_QUAD8
:
159 case AL_FORMAT_QUAD16
:
160 case AL_FORMAT_QUAD32
:
163 case AL_FORMAT_51CHN8
:
164 case AL_FORMAT_51CHN16
:
165 case AL_FORMAT_51CHN32
:
168 case AL_FORMAT_61CHN8
:
169 case AL_FORMAT_61CHN16
:
170 case AL_FORMAT_61CHN32
:
173 case AL_FORMAT_71CHN8
:
174 case AL_FORMAT_71CHN16
:
175 case AL_FORMAT_71CHN32
:
184 static __inline ALfloat
lpFilter(FILTER
*iir
, ALfloat input
)
186 ALfloat
*history
= iir
->history
;
187 ALfloat a
= iir
->coeff
;
188 ALfloat output
= input
;
190 output
= output
+ (history
[0]-output
)*a
;
192 output
= output
+ (history
[1]-output
)*a
;
194 output
= output
+ (history
[2]-output
)*a
;
196 output
= output
+ (history
[3]-output
)*a
;
202 static __inline ALfloat
lpFilterMC(FILTER
*iir
, ALuint chan
, ALfloat input
)
204 ALfloat
*history
= &iir
->history
[chan
*2];
205 ALfloat a
= iir
->coeff
;
206 ALfloat output
= input
;
208 output
= output
+ (history
[0]-output
)*a
;
210 output
= output
+ (history
[1]-output
)*a
;
217 static __inline ALshort
aluF2S(ALfloat Value
)
222 i
= __min( 32767, i
);
223 i
= __max(-32768, i
);
227 static __inline ALvoid
aluCrossproduct(const ALfloat
*inVector1
, const ALfloat
*inVector2
, ALfloat
*outVector
)
229 outVector
[0] = inVector1
[1]*inVector2
[2] - inVector1
[2]*inVector2
[1];
230 outVector
[1] = inVector1
[2]*inVector2
[0] - inVector1
[0]*inVector2
[2];
231 outVector
[2] = inVector1
[0]*inVector2
[1] - inVector1
[1]*inVector2
[0];
234 static __inline ALfloat
aluDotproduct(const ALfloat
*inVector1
, const ALfloat
*inVector2
)
236 return inVector1
[0]*inVector2
[0] + inVector1
[1]*inVector2
[1] +
237 inVector1
[2]*inVector2
[2];
240 static __inline ALvoid
aluNormalize(ALfloat
*inVector
)
242 ALfloat length
, inverse_length
;
244 length
= aluSqrt(aluDotproduct(inVector
, inVector
));
247 inverse_length
= 1.0f
/length
;
248 inVector
[0] *= inverse_length
;
249 inVector
[1] *= inverse_length
;
250 inVector
[2] *= inverse_length
;
254 static __inline ALvoid
aluMatrixVector(ALfloat
*vector
,ALfloat matrix
[3][3])
258 result
[0] = vector
[0]*matrix
[0][0] + vector
[1]*matrix
[1][0] + vector
[2]*matrix
[2][0];
259 result
[1] = vector
[0]*matrix
[0][1] + vector
[1]*matrix
[1][1] + vector
[2]*matrix
[2][1];
260 result
[2] = vector
[0]*matrix
[0][2] + vector
[1]*matrix
[1][2] + vector
[2]*matrix
[2][2];
261 memcpy(vector
, result
, sizeof(result
));
264 static ALvoid
SetSpeakerArrangement(const char *name
, ALfloat SpeakerAngle
[OUTPUTCHANNELS
],
265 ALint Speaker2Chan
[OUTPUTCHANNELS
], ALint chans
)
273 confkey
= GetConfigValue(NULL
, name
, "");
278 next
= strchr(confkey
, ',');
283 } while(isspace(*next
));
286 sep
= strchr(confkey
, '=');
287 if(!sep
|| confkey
== sep
)
291 while(isspace(*end
) && end
!= confkey
)
294 if(strncmp(confkey
, "fl", end
-confkey
) == 0)
296 else if(strncmp(confkey
, "fr", end
-confkey
) == 0)
298 else if(strncmp(confkey
, "fc", end
-confkey
) == 0)
300 else if(strncmp(confkey
, "bl", end
-confkey
) == 0)
302 else if(strncmp(confkey
, "br", end
-confkey
) == 0)
304 else if(strncmp(confkey
, "bc", end
-confkey
) == 0)
306 else if(strncmp(confkey
, "sl", end
-confkey
) == 0)
308 else if(strncmp(confkey
, "sr", end
-confkey
) == 0)
312 AL_PRINT("Unknown speaker for %s: \"%c%c\"\n", name
, confkey
[0], confkey
[1]);
320 for(i
= 0;i
< chans
;i
++)
322 if(Speaker2Chan
[i
] == val
)
324 val
= strtol(sep
, NULL
, 10);
325 if(val
>= -180 && val
<= 180)
326 SpeakerAngle
[i
] = val
* M_PI
/180.0f
;
328 AL_PRINT("Invalid angle for speaker \"%c%c\": %d\n", confkey
[0], confkey
[1], val
);
334 for(i
= 1;i
< chans
;i
++)
336 if(SpeakerAngle
[i
] <= SpeakerAngle
[i
-1])
338 AL_PRINT("Speaker %d of %d does not follow previous: %f > %f\n", i
, chans
,
339 SpeakerAngle
[i
-1] * 180.0f
/M_PI
, SpeakerAngle
[i
] * 180.0f
/M_PI
);
340 SpeakerAngle
[i
] = SpeakerAngle
[i
-1] + 1 * 180.0f
/M_PI
;
345 static __inline ALfloat
aluLUTpos2Angle(ALint pos
)
347 if(pos
< QUADRANT_NUM
)
348 return aluAtan((ALfloat
)pos
/ (ALfloat
)(QUADRANT_NUM
- pos
));
349 if(pos
< 2 * QUADRANT_NUM
)
350 return M_PI_2
+ aluAtan((ALfloat
)(pos
- QUADRANT_NUM
) / (ALfloat
)(2 * QUADRANT_NUM
- pos
));
351 if(pos
< 3 * QUADRANT_NUM
)
352 return aluAtan((ALfloat
)(pos
- 2 * QUADRANT_NUM
) / (ALfloat
)(3 * QUADRANT_NUM
- pos
)) - M_PI
;
353 return aluAtan((ALfloat
)(pos
- 3 * QUADRANT_NUM
) / (ALfloat
)(4 * QUADRANT_NUM
- pos
)) - M_PI_2
;
356 ALvoid
aluInitPanning(ALCcontext
*Context
)
358 ALint pos
, offset
, s
;
359 ALfloat Alpha
, Theta
;
360 ALfloat SpeakerAngle
[OUTPUTCHANNELS
];
361 ALint Speaker2Chan
[OUTPUTCHANNELS
];
363 for(s
= 0;s
< OUTPUTCHANNELS
;s
++)
366 for(s2
= 0;s2
< OUTPUTCHANNELS
;s2
++)
367 Context
->ChannelMatrix
[s
][s2
] = ((s
==s2
) ? 1.0f
: 0.0f
);
370 switch(Context
->Device
->Format
)
372 /* Mono is rendered as stereo, then downmixed during post-process */
373 case AL_FORMAT_MONO8
:
374 case AL_FORMAT_MONO16
:
375 case AL_FORMAT_MONO_FLOAT32
:
376 Context
->ChannelMatrix
[FRONT_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
377 Context
->ChannelMatrix
[FRONT_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
378 Context
->ChannelMatrix
[SIDE_LEFT
][FRONT_LEFT
] = 1.0f
;
379 Context
->ChannelMatrix
[SIDE_RIGHT
][FRONT_RIGHT
] = 1.0f
;
380 Context
->ChannelMatrix
[BACK_LEFT
][FRONT_LEFT
] = 1.0f
;
381 Context
->ChannelMatrix
[BACK_RIGHT
][FRONT_RIGHT
] = 1.0f
;
382 Context
->ChannelMatrix
[BACK_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
383 Context
->ChannelMatrix
[BACK_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
384 Context
->NumChan
= 2;
385 Speaker2Chan
[0] = FRONT_LEFT
;
386 Speaker2Chan
[1] = FRONT_RIGHT
;
387 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
388 SpeakerAngle
[1] = 90.0f
* M_PI
/180.0f
;
391 case AL_FORMAT_STEREO8
:
392 case AL_FORMAT_STEREO16
:
393 case AL_FORMAT_STEREO_FLOAT32
:
394 Context
->ChannelMatrix
[FRONT_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
395 Context
->ChannelMatrix
[FRONT_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
396 Context
->ChannelMatrix
[SIDE_LEFT
][FRONT_LEFT
] = 1.0f
;
397 Context
->ChannelMatrix
[SIDE_RIGHT
][FRONT_RIGHT
] = 1.0f
;
398 Context
->ChannelMatrix
[BACK_LEFT
][FRONT_LEFT
] = 1.0f
;
399 Context
->ChannelMatrix
[BACK_RIGHT
][FRONT_RIGHT
] = 1.0f
;
400 Context
->ChannelMatrix
[BACK_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
401 Context
->ChannelMatrix
[BACK_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
402 Context
->NumChan
= 2;
403 Speaker2Chan
[0] = FRONT_LEFT
;
404 Speaker2Chan
[1] = FRONT_RIGHT
;
405 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
406 SpeakerAngle
[1] = 90.0f
* M_PI
/180.0f
;
407 SetSpeakerArrangement("layout_STEREO", SpeakerAngle
, Speaker2Chan
, Context
->NumChan
);
410 case AL_FORMAT_QUAD8
:
411 case AL_FORMAT_QUAD16
:
412 case AL_FORMAT_QUAD32
:
413 Context
->ChannelMatrix
[FRONT_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
414 Context
->ChannelMatrix
[FRONT_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
415 Context
->ChannelMatrix
[SIDE_LEFT
][FRONT_LEFT
] = aluSqrt(0.5);
416 Context
->ChannelMatrix
[SIDE_LEFT
][BACK_LEFT
] = aluSqrt(0.5);
417 Context
->ChannelMatrix
[SIDE_RIGHT
][FRONT_RIGHT
] = aluSqrt(0.5);
418 Context
->ChannelMatrix
[SIDE_RIGHT
][BACK_RIGHT
] = aluSqrt(0.5);
419 Context
->ChannelMatrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
420 Context
->ChannelMatrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
421 Context
->NumChan
= 4;
422 Speaker2Chan
[0] = BACK_LEFT
;
423 Speaker2Chan
[1] = FRONT_LEFT
;
424 Speaker2Chan
[2] = FRONT_RIGHT
;
425 Speaker2Chan
[3] = BACK_RIGHT
;
426 SpeakerAngle
[0] = -135.0f
* M_PI
/180.0f
;
427 SpeakerAngle
[1] = -45.0f
* M_PI
/180.0f
;
428 SpeakerAngle
[2] = 45.0f
* M_PI
/180.0f
;
429 SpeakerAngle
[3] = 135.0f
* M_PI
/180.0f
;
430 SetSpeakerArrangement("layout_QUAD", SpeakerAngle
, Speaker2Chan
, Context
->NumChan
);
433 case AL_FORMAT_51CHN8
:
434 case AL_FORMAT_51CHN16
:
435 case AL_FORMAT_51CHN32
:
436 Context
->ChannelMatrix
[SIDE_LEFT
][FRONT_LEFT
] = aluSqrt(0.5);
437 Context
->ChannelMatrix
[SIDE_LEFT
][BACK_LEFT
] = aluSqrt(0.5);
438 Context
->ChannelMatrix
[SIDE_RIGHT
][FRONT_RIGHT
] = aluSqrt(0.5);
439 Context
->ChannelMatrix
[SIDE_RIGHT
][BACK_RIGHT
] = aluSqrt(0.5);
440 Context
->ChannelMatrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
441 Context
->ChannelMatrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
442 Context
->NumChan
= 5;
443 Speaker2Chan
[0] = BACK_LEFT
;
444 Speaker2Chan
[1] = FRONT_LEFT
;
445 Speaker2Chan
[2] = FRONT_CENTER
;
446 Speaker2Chan
[3] = FRONT_RIGHT
;
447 Speaker2Chan
[4] = BACK_RIGHT
;
448 SpeakerAngle
[0] = -110.0f
* M_PI
/180.0f
;
449 SpeakerAngle
[1] = -30.0f
* M_PI
/180.0f
;
450 SpeakerAngle
[2] = 0.0f
* M_PI
/180.0f
;
451 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
452 SpeakerAngle
[4] = 110.0f
* M_PI
/180.0f
;
453 SetSpeakerArrangement("layout_51CHN", SpeakerAngle
, Speaker2Chan
, Context
->NumChan
);
456 case AL_FORMAT_61CHN8
:
457 case AL_FORMAT_61CHN16
:
458 case AL_FORMAT_61CHN32
:
459 Context
->ChannelMatrix
[BACK_LEFT
][BACK_CENTER
] = aluSqrt(0.5);
460 Context
->ChannelMatrix
[BACK_LEFT
][SIDE_LEFT
] = aluSqrt(0.5);
461 Context
->ChannelMatrix
[BACK_RIGHT
][BACK_CENTER
] = aluSqrt(0.5);
462 Context
->ChannelMatrix
[BACK_RIGHT
][SIDE_RIGHT
] = aluSqrt(0.5);
463 Context
->NumChan
= 6;
464 Speaker2Chan
[0] = SIDE_LEFT
;
465 Speaker2Chan
[1] = FRONT_LEFT
;
466 Speaker2Chan
[2] = FRONT_CENTER
;
467 Speaker2Chan
[3] = FRONT_RIGHT
;
468 Speaker2Chan
[4] = SIDE_RIGHT
;
469 Speaker2Chan
[5] = BACK_CENTER
;
470 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
471 SpeakerAngle
[1] = -30.0f
* M_PI
/180.0f
;
472 SpeakerAngle
[2] = 0.0f
* M_PI
/180.0f
;
473 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
474 SpeakerAngle
[4] = 90.0f
* M_PI
/180.0f
;
475 SpeakerAngle
[5] = 180.0f
* M_PI
/180.0f
;
476 SetSpeakerArrangement("layout_61CHN", SpeakerAngle
, Speaker2Chan
, Context
->NumChan
);
479 case AL_FORMAT_71CHN8
:
480 case AL_FORMAT_71CHN16
:
481 case AL_FORMAT_71CHN32
:
482 Context
->ChannelMatrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
483 Context
->ChannelMatrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
484 Context
->NumChan
= 7;
485 Speaker2Chan
[0] = BACK_LEFT
;
486 Speaker2Chan
[1] = SIDE_LEFT
;
487 Speaker2Chan
[2] = FRONT_LEFT
;
488 Speaker2Chan
[3] = FRONT_CENTER
;
489 Speaker2Chan
[4] = FRONT_RIGHT
;
490 Speaker2Chan
[5] = SIDE_RIGHT
;
491 Speaker2Chan
[6] = BACK_RIGHT
;
492 SpeakerAngle
[0] = -150.0f
* M_PI
/180.0f
;
493 SpeakerAngle
[1] = -90.0f
* M_PI
/180.0f
;
494 SpeakerAngle
[2] = -30.0f
* M_PI
/180.0f
;
495 SpeakerAngle
[3] = 0.0f
* M_PI
/180.0f
;
496 SpeakerAngle
[4] = 30.0f
* M_PI
/180.0f
;
497 SpeakerAngle
[5] = 90.0f
* M_PI
/180.0f
;
498 SpeakerAngle
[6] = 150.0f
* M_PI
/180.0f
;
499 SetSpeakerArrangement("layout_71CHN", SpeakerAngle
, Speaker2Chan
, Context
->NumChan
);
506 for(pos
= 0; pos
< LUT_NUM
; pos
++)
509 Theta
= aluLUTpos2Angle(pos
);
511 /* clear all values */
512 offset
= OUTPUTCHANNELS
* pos
;
513 for(s
= 0; s
< OUTPUTCHANNELS
; s
++)
514 Context
->PanningLUT
[offset
+s
] = 0.0f
;
516 /* set panning values */
517 for(s
= 0; s
< Context
->NumChan
- 1; s
++)
519 if(Theta
>= SpeakerAngle
[s
] && Theta
< SpeakerAngle
[s
+1])
521 /* source between speaker s and speaker s+1 */
522 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
523 (SpeakerAngle
[s
+1]-SpeakerAngle
[s
]);
524 Context
->PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
525 Context
->PanningLUT
[offset
+ Speaker2Chan
[s
+1]] = sin(Alpha
);
529 if(s
== Context
->NumChan
- 1)
531 /* source between last and first speaker */
532 if(Theta
< SpeakerAngle
[0])
533 Theta
+= 2.0f
* M_PI
;
534 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
535 (2.0f
* M_PI
+ SpeakerAngle
[0]-SpeakerAngle
[s
]);
536 Context
->PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
537 Context
->PanningLUT
[offset
+ Speaker2Chan
[0]] = sin(Alpha
);
542 static __inline ALint
aluCart2LUTpos(ALfloat re
, ALfloat im
)
545 ALfloat denom
= aluFabs(re
) + aluFabs(im
);
547 pos
= (ALint
)(QUADRANT_NUM
*aluFabs(im
) / denom
+ 0.5);
550 pos
= 2 * QUADRANT_NUM
- pos
;
556 static ALvoid
CalcSourceParams(const ALCcontext
*ALContext
,
557 const ALsource
*ALSource
, ALenum isMono
,
558 ALfloat
*drysend
, ALfloat
*wetsend
,
559 ALfloat
*pitch
, ALfloat
*drygainhf
,
562 ALfloat InnerAngle
,OuterAngle
,Angle
,Distance
,DryMix
;
563 ALfloat Direction
[3],Position
[3],SourceToListener
[3];
564 ALfloat MinVolume
,MaxVolume
,MinDist
,MaxDist
,Rolloff
,OuterGainHF
;
565 ALfloat ConeVolume
,SourceVolume
,ListenerGain
;
566 ALfloat U
[3],V
[3],N
[3];
567 ALfloat DopplerFactor
, DopplerVelocity
, flSpeedOfSound
, flMaxVelocity
;
568 ALfloat Matrix
[3][3];
569 ALfloat flAttenuation
;
570 ALfloat RoomAttenuation
[MAX_SENDS
];
571 ALfloat MetersPerUnit
;
572 ALfloat RoomRolloff
[MAX_SENDS
];
573 ALfloat DryGainHF
= 1.0f
;
574 ALfloat DirGain
, AmbientGain
;
575 const ALfloat
*SpeakerGain
;
578 //Get context properties
579 DopplerFactor
= ALContext
->DopplerFactor
* ALSource
->DopplerFactor
;
580 DopplerVelocity
= ALContext
->DopplerVelocity
;
581 flSpeedOfSound
= ALContext
->flSpeedOfSound
;
583 //Get listener properties
584 ListenerGain
= ALContext
->Listener
.Gain
;
585 MetersPerUnit
= ALContext
->Listener
.MetersPerUnit
;
587 //Get source properties
588 SourceVolume
= ALSource
->flGain
;
589 memcpy(Position
, ALSource
->vPosition
, sizeof(ALSource
->vPosition
));
590 memcpy(Direction
, ALSource
->vOrientation
, sizeof(ALSource
->vOrientation
));
591 MinVolume
= ALSource
->flMinGain
;
592 MaxVolume
= ALSource
->flMaxGain
;
593 MinDist
= ALSource
->flRefDistance
;
594 MaxDist
= ALSource
->flMaxDistance
;
595 Rolloff
= ALSource
->flRollOffFactor
;
596 InnerAngle
= ALSource
->flInnerAngle
;
597 OuterAngle
= ALSource
->flOuterAngle
;
598 OuterGainHF
= ALSource
->OuterGainHF
;
599 for(i
= 0;i
< MAX_SENDS
;i
++)
600 RoomRolloff
[i
] = ALSource
->RoomRolloffFactor
;
602 //Only apply 3D calculations for mono buffers
603 if(isMono
!= AL_FALSE
)
605 //1. Translate Listener to origin (convert to head relative)
606 // Note that Direction and SourceToListener are *not* transformed.
607 // SourceToListener is used with the source and listener velocities,
608 // which are untransformed, and Direction is used with SourceToListener
609 // for the sound cone
610 if(ALSource
->bHeadRelative
==AL_FALSE
)
612 // Build transform matrix
613 aluCrossproduct(ALContext
->Listener
.Forward
, ALContext
->Listener
.Up
, U
); // Right-vector
614 aluNormalize(U
); // Normalized Right-vector
615 memcpy(V
, ALContext
->Listener
.Up
, sizeof(V
)); // Up-vector
616 aluNormalize(V
); // Normalized Up-vector
617 memcpy(N
, ALContext
->Listener
.Forward
, sizeof(N
)); // At-vector
618 aluNormalize(N
); // Normalized At-vector
619 Matrix
[0][0] = U
[0]; Matrix
[0][1] = V
[0]; Matrix
[0][2] = -N
[0];
620 Matrix
[1][0] = U
[1]; Matrix
[1][1] = V
[1]; Matrix
[1][2] = -N
[1];
621 Matrix
[2][0] = U
[2]; Matrix
[2][1] = V
[2]; Matrix
[2][2] = -N
[2];
623 // Translate source position into listener space
624 Position
[0] -= ALContext
->Listener
.Position
[0];
625 Position
[1] -= ALContext
->Listener
.Position
[1];
626 Position
[2] -= ALContext
->Listener
.Position
[2];
628 SourceToListener
[0] = -Position
[0];
629 SourceToListener
[1] = -Position
[1];
630 SourceToListener
[2] = -Position
[2];
632 // Transform source position into listener space
633 aluMatrixVector(Position
, Matrix
);
637 SourceToListener
[0] = -Position
[0];
638 SourceToListener
[1] = -Position
[1];
639 SourceToListener
[2] = -Position
[2];
641 aluNormalize(SourceToListener
);
642 aluNormalize(Direction
);
644 //2. Calculate distance attenuation
645 Distance
= aluSqrt(aluDotproduct(Position
, Position
));
647 for(i
= 0;i
< MAX_SENDS
;i
++)
649 if(ALSource
->Send
[i
].Slot
&&
650 ALSource
->Send
[i
].Slot
->effect
.type
== AL_EFFECT_REVERB
)
651 RoomRolloff
[i
] += ALSource
->Send
[i
].Slot
->effect
.Reverb
.RoomRolloffFactor
;
654 flAttenuation
= 1.0f
;
655 for(i
= 0;i
< MAX_SENDS
;i
++)
656 RoomAttenuation
[i
] = 1.0f
;
657 switch (ALSource
->DistanceModel
)
659 case AL_INVERSE_DISTANCE_CLAMPED
:
660 Distance
=__max(Distance
,MinDist
);
661 Distance
=__min(Distance
,MaxDist
);
662 if (MaxDist
< MinDist
)
665 case AL_INVERSE_DISTANCE
:
668 if ((MinDist
+ (Rolloff
* (Distance
- MinDist
))) > 0.0f
)
669 flAttenuation
= MinDist
/ (MinDist
+ (Rolloff
* (Distance
- MinDist
)));
670 for(i
= 0;i
< MAX_SENDS
;i
++)
672 if ((MinDist
+ (RoomRolloff
[i
] * (Distance
- MinDist
))) > 0.0f
)
673 RoomAttenuation
[i
] = MinDist
/ (MinDist
+ (RoomRolloff
[i
] * (Distance
- MinDist
)));
678 case AL_LINEAR_DISTANCE_CLAMPED
:
679 Distance
=__max(Distance
,MinDist
);
680 Distance
=__min(Distance
,MaxDist
);
681 if (MaxDist
< MinDist
)
684 case AL_LINEAR_DISTANCE
:
685 Distance
=__min(Distance
,MaxDist
);
686 if (MaxDist
!= MinDist
)
688 flAttenuation
= 1.0f
- (Rolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
689 for(i
= 0;i
< MAX_SENDS
;i
++)
690 RoomAttenuation
[i
] = 1.0f
- (RoomRolloff
[i
]*(Distance
-MinDist
)/(MaxDist
- MinDist
));
694 case AL_EXPONENT_DISTANCE_CLAMPED
:
695 Distance
=__max(Distance
,MinDist
);
696 Distance
=__min(Distance
,MaxDist
);
697 if (MaxDist
< MinDist
)
700 case AL_EXPONENT_DISTANCE
:
701 if ((Distance
> 0.0f
) && (MinDist
> 0.0f
))
703 flAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -Rolloff
);
704 for(i
= 0;i
< MAX_SENDS
;i
++)
705 RoomAttenuation
[i
] = (ALfloat
)pow(Distance
/MinDist
, -RoomRolloff
[i
]);
713 // Source Gain + Attenuation and clamp to Min/Max Gain
714 DryMix
= SourceVolume
* flAttenuation
;
715 DryMix
= __min(DryMix
,MaxVolume
);
716 DryMix
= __max(DryMix
,MinVolume
);
718 for(i
= 0;i
< MAX_SENDS
;i
++)
720 ALfloat WetMix
= SourceVolume
* RoomAttenuation
[i
];
721 WetMix
= __min(WetMix
,MaxVolume
);
722 wetsend
[i
] = __max(WetMix
,MinVolume
);
726 // Distance-based air absorption
727 if(ALSource
->AirAbsorptionFactor
> 0.0f
&& ALSource
->DistanceModel
!= AL_NONE
)
729 ALfloat dist
= Distance
-MinDist
;
732 if(dist
< 0.0f
) dist
= 0.0f
;
733 // Absorption calculation is done in dB
734 absorb
= (ALSource
->AirAbsorptionFactor
*AIRABSORBGAINDBHF
) *
735 (dist
*MetersPerUnit
);
736 // Convert dB to linear gain before applying
737 absorb
= pow(10.0, absorb
/20.0);
739 for(i
= 0;i
< MAX_SENDS
;i
++)
740 wetgainhf
[i
] *= absorb
;
743 //3. Apply directional soundcones
744 Angle
= aluAcos(aluDotproduct(Direction
,SourceToListener
)) * 180.0f
/M_PI
;
745 if(Angle
>= InnerAngle
&& Angle
<= OuterAngle
)
747 ALfloat scale
= (Angle
-InnerAngle
) / (OuterAngle
-InnerAngle
);
748 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
)*scale
);
749 DryMix
*= ConeVolume
;
750 if(ALSource
->DryGainHFAuto
)
751 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
752 if(ALSource
->WetGainAuto
)
754 for(i
= 0;i
< MAX_SENDS
;i
++)
755 wetsend
[i
] *= ConeVolume
;
757 if(ALSource
->WetGainHFAuto
)
759 for(i
= 0;i
< MAX_SENDS
;i
++)
760 wetgainhf
[i
] *= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
763 else if(Angle
> OuterAngle
)
765 ConeVolume
= (1.0f
+(ALSource
->flOuterGain
-1.0f
));
766 DryMix
*= ConeVolume
;
767 if(ALSource
->DryGainHFAuto
)
768 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
769 if(ALSource
->WetGainAuto
)
771 for(i
= 0;i
< MAX_SENDS
;i
++)
772 wetsend
[i
] *= ConeVolume
;
774 if(ALSource
->WetGainHFAuto
)
776 for(i
= 0;i
< MAX_SENDS
;i
++)
777 wetgainhf
[i
] *= (1.0f
+(OuterGainHF
-1.0f
));
781 //4. Calculate Velocity
782 if(DopplerFactor
!= 0.0f
)
784 ALfloat flVSS
, flVLS
= 0.0f
;
786 if(ALSource
->bHeadRelative
==AL_FALSE
)
787 flVLS
= aluDotproduct(ALContext
->Listener
.Velocity
, SourceToListener
);
788 flVSS
= aluDotproduct(ALSource
->vVelocity
, SourceToListener
);
790 flMaxVelocity
= (DopplerVelocity
* flSpeedOfSound
) / DopplerFactor
;
792 if (flVSS
>= flMaxVelocity
)
793 flVSS
= (flMaxVelocity
- 1.0f
);
794 else if (flVSS
<= -flMaxVelocity
)
795 flVSS
= -flMaxVelocity
+ 1.0f
;
797 if (flVLS
>= flMaxVelocity
)
798 flVLS
= (flMaxVelocity
- 1.0f
);
799 else if (flVLS
<= -flMaxVelocity
)
800 flVLS
= -flMaxVelocity
+ 1.0f
;
802 pitch
[0] = ALSource
->flPitch
*
803 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVLS
)) /
804 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVSS
));
807 pitch
[0] = ALSource
->flPitch
;
809 for(i
= 0;i
< MAX_SENDS
;i
++)
811 if(ALSource
->Send
[i
].Slot
&&
812 ALSource
->Send
[i
].Slot
->effect
.type
!= AL_EFFECT_NULL
)
814 if(ALSource
->Send
[i
].Slot
->AuxSendAuto
)
816 // Apply minimal attenuation in place of missing
817 // statistical reverb model.
818 wetsend
[i
] *= pow(DryMix
, 1.0f
/ 2.0f
);
822 // If the slot's auxilliary send auto is off, the data sent to the
823 // effect slot is the same as the dry path, sans filter effects
825 wetgainhf
[i
] = DryGainHF
;
828 // Note that this is really applied by the effect slot. However,
829 // it's easier (more optimal) to handle it here.
830 if(ALSource
->Send
[i
].Slot
->effect
.type
== AL_EFFECT_REVERB
)
831 wetgainhf
[i
] *= ALSource
->Send
[0].Slot
->effect
.Reverb
.GainHF
;
839 switch(ALSource
->Send
[i
].WetFilter
.type
)
841 case AL_FILTER_LOWPASS
:
842 wetsend
[i
] *= ALSource
->Send
[i
].WetFilter
.Gain
;
843 wetgainhf
[i
] *= ALSource
->Send
[i
].WetFilter
.GainHF
;
846 wetsend
[i
] *= ListenerGain
;
849 //5. Apply filter gains and filters
850 switch(ALSource
->DirectFilter
.type
)
852 case AL_FILTER_LOWPASS
:
853 DryMix
*= ALSource
->DirectFilter
.Gain
;
854 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
857 DryMix
*= ListenerGain
;
859 // Use energy-preserving panning algorithm for multi-speaker playback
860 aluNormalize(Position
);
862 pos
= aluCart2LUTpos(-Position
[2], Position
[0]);
863 SpeakerGain
= &ALContext
->PanningLUT
[OUTPUTCHANNELS
* pos
];
865 DirGain
= aluSqrt(Position
[0]*Position
[0] + Position
[2]*Position
[2]);
866 // elevation adjustment for directional gain. this sucks, but
867 // has low complexity
868 AmbientGain
= 1.0/aluSqrt(ALContext
->NumChan
) * (1.0-DirGain
);
869 for(s
= 0; s
< OUTPUTCHANNELS
; s
++)
871 ALfloat gain
= SpeakerGain
[s
]*DirGain
+ AmbientGain
;
872 drysend
[s
] = DryMix
* gain
;
874 *drygainhf
= DryGainHF
;
878 //1. Multi-channel buffers always play "normal"
879 pitch
[0] = ALSource
->flPitch
;
881 DryMix
= SourceVolume
;
882 DryMix
= __min(DryMix
,MaxVolume
);
883 DryMix
= __max(DryMix
,MinVolume
);
885 switch(ALSource
->DirectFilter
.type
)
887 case AL_FILTER_LOWPASS
:
888 DryMix
*= ALSource
->DirectFilter
.Gain
;
889 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
893 drysend
[FRONT_LEFT
] = DryMix
* ListenerGain
;
894 drysend
[FRONT_RIGHT
] = DryMix
* ListenerGain
;
895 drysend
[SIDE_LEFT
] = DryMix
* ListenerGain
;
896 drysend
[SIDE_RIGHT
] = DryMix
* ListenerGain
;
897 drysend
[BACK_LEFT
] = DryMix
* ListenerGain
;
898 drysend
[BACK_RIGHT
] = DryMix
* ListenerGain
;
899 drysend
[FRONT_CENTER
] = DryMix
* ListenerGain
;
900 drysend
[BACK_CENTER
] = DryMix
* ListenerGain
;
901 drysend
[LFE
] = DryMix
* ListenerGain
;
902 *drygainhf
= DryGainHF
;
904 for(i
= 0;i
< MAX_SENDS
;i
++)
912 static __inline ALshort
lerp(ALshort val1
, ALshort val2
, ALint frac
)
914 return val1
+ (((val2
-val1
)*frac
)>>FRACTIONBITS
);
917 ALvoid
aluMixData(ALCcontext
*ALContext
,ALvoid
*buffer
,ALsizei size
,ALenum format
)
919 static float DryBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
920 static float DummyBuffer
[BUFFERSIZE
];
921 ALfloat
*WetBuffer
[MAX_SENDS
];
922 ALfloat (*Matrix
)[OUTPUTCHANNELS
] = ALContext
->ChannelMatrix
;
923 ALfloat newDrySend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
924 ALfloat newWetSend
[MAX_SENDS
];
925 ALfloat DryGainHF
= 0.0f
;
926 ALfloat WetGainHF
[MAX_SENDS
];
930 ALfloat dryGainStep
[OUTPUTCHANNELS
];
931 ALfloat wetGainStep
[MAX_SENDS
];
932 ALuint BlockAlign
,BufferSize
;
933 ALuint DataSize
=0,DataPosInt
=0,DataPosFrac
=0;
934 ALuint Channels
,Frequency
,ulExtraSamples
;
942 ALeffectslot
*ALEffectSlot
;
943 ALfloat values
[OUTPUTCHANNELS
];
948 ALbufferlistitem
*BufferListItem
;
950 ALint64 DataSize64
,DataPos64
;
951 FILTER
*DryFilter
, *WetFilter
[MAX_SENDS
];
954 SuspendContext(ALContext
);
956 #if defined(HAVE_FESETROUND)
957 fpuState
= fegetround();
958 fesetround(FE_TOWARDZERO
);
959 #elif defined(HAVE__CONTROLFP)
960 fpuState
= _controlfp(0, 0);
961 _controlfp(_RC_CHOP
, _MCW_RC
);
966 //Figure output format variables
967 BlockAlign
= aluChannelsFromFormat(format
);
968 BlockAlign
*= aluBytesFromFormat(format
);
974 SamplesToDo
= min(size
, BUFFERSIZE
);
977 ALEffectSlot
= ALContext
->AuxiliaryEffectSlot
;
978 ALSource
= ALContext
->Source
;
979 rampLength
= ALContext
->Frequency
* MIN_RAMP_LENGTH
/ 1000;
987 rampLength
= max(rampLength
, SamplesToDo
);
989 //Clear mixing buffer
990 memset(DryBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
996 State
= ALSource
->state
;
998 while(State
== AL_PLAYING
&& j
< SamplesToDo
)
1005 if((Buffer
= ALSource
->ulBufferID
))
1007 ALBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(Buffer
);
1009 Data
= ALBuffer
->data
;
1010 Channels
= aluChannelsFromFormat(ALBuffer
->format
);
1011 DataSize
= ALBuffer
->size
;
1012 DataSize
/= Channels
* aluBytesFromFormat(ALBuffer
->format
);
1013 Frequency
= ALBuffer
->frequency
;
1014 DataPosInt
= ALSource
->position
;
1015 DataPosFrac
= ALSource
->position_fraction
;
1017 if(DataPosInt
>= DataSize
)
1021 DryFilter
= &ALSource
->iirFilter
;
1022 for(i
= 0;i
< MAX_SENDS
;i
++)
1024 WetFilter
[i
] = &ALSource
->Send
[i
].iirFilter
;
1025 WetBuffer
[i
] = (ALSource
->Send
[i
].Slot
?
1026 ALSource
->Send
[i
].Slot
->WetBuffer
:
1029 DrySend
= ALSource
->DryGains
;
1030 WetSend
= ALSource
->WetGains
;
1032 CalcSourceParams(ALContext
, ALSource
,
1033 (Channels
==1) ? AL_TRUE
: AL_FALSE
,
1034 newDrySend
, newWetSend
, &Pitch
,
1035 &DryGainHF
, WetGainHF
);
1036 Pitch
= (Pitch
*Frequency
) / ALContext
->Frequency
;
1040 // Update filter coefficients. Calculations based on
1042 cw
= cos(2.0*M_PI
* LOWPASSFREQCUTOFF
/ ALContext
->Frequency
);
1043 // We use four chained one-pole filters, so we need to
1044 // take the fourth root of the squared gain, which is
1045 // the same as the square root of the base gain.
1046 // Be careful with gains < 0.0001, as that causes the
1047 // coefficient to head towards 1, which will flatten
1049 g
= aluSqrt(__max(DryGainHF
, 0.0001f
));
1051 if(g
< 0.9999f
) // 1-epsilon
1052 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
1053 DryFilter
->coeff
= a
;
1055 for(i
= 0;i
< MAX_SENDS
;i
++)
1057 g
= aluSqrt(__max(WetGainHF
[i
], 0.0001f
));
1059 if(g
< 0.9999f
) // 1-epsilon
1060 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
1061 WetFilter
[i
]->coeff
= a
;
1066 // Multi-channel sources use two chained one-pole
1067 // filters, so take the base gain (square root of the
1069 cw
= cos(2.0*M_PI
* LOWPASSFREQCUTOFF
/ ALContext
->Frequency
);
1070 g
= __max(DryGainHF
, 0.01f
);
1072 if(g
< 0.9999f
) // 1-epsilon
1073 a
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
1074 DryFilter
->coeff
= a
;
1075 for(i
= 0;i
< MAX_SENDS
;i
++)
1076 WetFilter
[i
]->coeff
= 0.0f
;
1078 if(DuplicateStereo
&& Channels
== 2)
1080 Matrix
[FRONT_LEFT
][SIDE_LEFT
] = 1.0f
;
1081 Matrix
[FRONT_RIGHT
][SIDE_RIGHT
] = 1.0f
;
1082 Matrix
[FRONT_LEFT
][BACK_LEFT
] = 1.0f
;
1083 Matrix
[FRONT_RIGHT
][BACK_RIGHT
] = 1.0f
;
1085 else if(DuplicateStereo
)
1087 Matrix
[FRONT_LEFT
][SIDE_LEFT
] = 0.0f
;
1088 Matrix
[FRONT_RIGHT
][SIDE_RIGHT
] = 0.0f
;
1089 Matrix
[FRONT_LEFT
][BACK_LEFT
] = 0.0f
;
1090 Matrix
[FRONT_RIGHT
][BACK_RIGHT
] = 0.0f
;
1094 //Compute the gain steps for each output channel
1095 if(ALSource
->FirstStart
&& DataPosInt
== 0 && DataPosFrac
== 0)
1097 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
1099 DrySend
[i
] = newDrySend
[i
];
1102 for(i
= 0;i
< MAX_SENDS
;i
++)
1104 WetSend
[i
] = newWetSend
[i
];
1110 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
1111 dryGainStep
[i
] = (newDrySend
[i
]-DrySend
[i
]) / rampLength
;
1112 for(i
= 0;i
< MAX_SENDS
;i
++)
1113 wetGainStep
[i
] = (newWetSend
[i
]-WetSend
[i
]) / rampLength
;
1115 ALSource
->FirstStart
= AL_FALSE
;
1117 //Compute 18.14 fixed point step
1118 if(Pitch
> (float)MAX_PITCH
)
1119 Pitch
= (float)MAX_PITCH
;
1120 increment
= (ALint
)(Pitch
*(ALfloat
)(1L<<FRACTIONBITS
));
1122 increment
= (1<<FRACTIONBITS
);
1124 //Figure out how many samples we can mix.
1125 DataSize64
= DataSize
;
1126 DataSize64
<<= FRACTIONBITS
;
1127 DataPos64
= DataPosInt
;
1128 DataPos64
<<= FRACTIONBITS
;
1129 DataPos64
+= DataPosFrac
;
1130 BufferSize
= (ALuint
)((DataSize64
-DataPos64
+(increment
-1)) / increment
);
1132 BufferListItem
= ALSource
->queue
;
1133 for(loop
= 0; loop
< ALSource
->BuffersPlayed
; loop
++)
1136 BufferListItem
= BufferListItem
->next
;
1140 if (BufferListItem
->next
)
1142 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
);
1143 if(NextBuf
&& NextBuf
->data
)
1145 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
1146 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
1149 else if (ALSource
->bLooping
)
1151 ALbuffer
*NextBuf
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
);
1152 if (NextBuf
&& NextBuf
->data
)
1154 ulExtraSamples
= min(NextBuf
->size
, (ALint
)(ALBuffer
->padding
*Channels
*2));
1155 memcpy(&Data
[DataSize
*Channels
], NextBuf
->data
, ulExtraSamples
);
1159 memset(&Data
[DataSize
*Channels
], 0, (ALBuffer
->padding
*Channels
*2));
1161 BufferSize
= min(BufferSize
, (SamplesToDo
-j
));
1163 //Actual sample mixing loop
1165 Data
+= DataPosInt
*Channels
;
1167 if(Channels
== 1) /* Mono */
1173 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
1174 DrySend
[i
] += dryGainStep
[i
];
1175 for(i
= 0;i
< MAX_SENDS
;i
++)
1176 WetSend
[i
] += wetGainStep
[i
];
1178 //First order interpolator
1179 value
= lerp(Data
[k
], Data
[k
+1], DataPosFrac
);
1181 //Direct path final mix buffer and panning
1182 outsamp
= lpFilter(DryFilter
, value
);
1183 DryBuffer
[j
][FRONT_LEFT
] += outsamp
*DrySend
[FRONT_LEFT
];
1184 DryBuffer
[j
][FRONT_RIGHT
] += outsamp
*DrySend
[FRONT_RIGHT
];
1185 DryBuffer
[j
][SIDE_LEFT
] += outsamp
*DrySend
[SIDE_LEFT
];
1186 DryBuffer
[j
][SIDE_RIGHT
] += outsamp
*DrySend
[SIDE_RIGHT
];
1187 DryBuffer
[j
][BACK_LEFT
] += outsamp
*DrySend
[BACK_LEFT
];
1188 DryBuffer
[j
][BACK_RIGHT
] += outsamp
*DrySend
[BACK_RIGHT
];
1189 DryBuffer
[j
][FRONT_CENTER
] += outsamp
*DrySend
[FRONT_CENTER
];
1190 DryBuffer
[j
][BACK_CENTER
] += outsamp
*DrySend
[BACK_CENTER
];
1192 //Room path final mix buffer and panning
1193 for(i
= 0;i
< MAX_SENDS
;i
++)
1195 outsamp
= lpFilter(WetFilter
[i
], value
);
1196 WetBuffer
[i
][j
] += outsamp
*WetSend
[i
];
1199 DataPosFrac
+= increment
;
1200 k
+= DataPosFrac
>>FRACTIONBITS
;
1201 DataPosFrac
&= FRACTIONMASK
;
1205 else if(Channels
== 2) /* Stereo */
1207 const int chans
[] = {
1208 FRONT_LEFT
, FRONT_RIGHT
1211 #define DO_MIX() do { \
1212 for(i = 0;i < MAX_SENDS;i++) \
1213 WetSend[i] += wetGainStep[i]*BufferSize; \
1214 while(BufferSize--) \
1216 for(i = 0;i < OUTPUTCHANNELS;i++) \
1217 DrySend[i] += dryGainStep[i]; \
1219 for(i = 0;i < Channels;i++) \
1221 value = lerp(Data[k*Channels + i], Data[(k+1)*Channels + i], DataPosFrac); \
1222 values[i] = lpFilterMC(DryFilter, chans[i], value)*DrySend[chans[i]]; \
1224 for(out = 0;out < OUTPUTCHANNELS;out++) \
1226 ALfloat sum = 0.0f; \
1227 for(i = 0;i < Channels;i++) \
1228 sum += values[i]*Matrix[chans[i]][out]; \
1229 DryBuffer[j][out] += sum; \
1232 DataPosFrac += increment; \
1233 k += DataPosFrac>>FRACTIONBITS; \
1234 DataPosFrac &= FRACTIONMASK; \
1241 else if(Channels
== 4) /* Quad */
1243 const int chans
[] = {
1244 FRONT_LEFT
, FRONT_RIGHT
,
1245 BACK_LEFT
, BACK_RIGHT
1250 else if(Channels
== 6) /* 5.1 */
1252 const int chans
[] = {
1253 FRONT_LEFT
, FRONT_RIGHT
,
1255 BACK_LEFT
, BACK_RIGHT
1260 else if(Channels
== 7) /* 6.1 */
1262 const int chans
[] = {
1263 FRONT_LEFT
, FRONT_RIGHT
,
1266 SIDE_LEFT
, SIDE_RIGHT
1271 else if(Channels
== 8) /* 7.1 */
1273 const int chans
[] = {
1274 FRONT_LEFT
, FRONT_RIGHT
,
1276 BACK_LEFT
, BACK_RIGHT
,
1277 SIDE_LEFT
, SIDE_RIGHT
1285 for(i
= 0;i
< OUTPUTCHANNELS
;i
++)
1286 DrySend
[i
] += dryGainStep
[i
]*BufferSize
;
1287 for(i
= 0;i
< MAX_SENDS
;i
++)
1288 WetSend
[i
] += wetGainStep
[i
]*BufferSize
;
1291 DataPosFrac
+= increment
;
1292 k
+= DataPosFrac
>>FRACTIONBITS
;
1293 DataPosFrac
&= FRACTIONMASK
;
1299 //Update source info
1300 ALSource
->position
= DataPosInt
;
1301 ALSource
->position_fraction
= DataPosFrac
;
1306 //Handle looping sources
1307 if(!Buffer
|| DataPosInt
>= DataSize
)
1312 Looping
= ALSource
->bLooping
;
1313 if(ALSource
->BuffersPlayed
< (ALSource
->BuffersInQueue
-1))
1315 BufferListItem
= ALSource
->queue
;
1316 for(loop
= 0; loop
<= ALSource
->BuffersPlayed
; loop
++)
1321 BufferListItem
->bufferstate
= PROCESSED
;
1322 BufferListItem
= BufferListItem
->next
;
1326 ALSource
->ulBufferID
= BufferListItem
->buffer
;
1327 ALSource
->position
= DataPosInt
-DataSize
;
1328 ALSource
->position_fraction
= DataPosFrac
;
1329 ALSource
->BuffersPlayed
++;
1336 ALSource
->state
= AL_STOPPED
;
1337 ALSource
->inuse
= AL_FALSE
;
1338 ALSource
->BuffersPlayed
= ALSource
->BuffersInQueue
;
1339 BufferListItem
= ALSource
->queue
;
1340 while(BufferListItem
!= NULL
)
1342 BufferListItem
->bufferstate
= PROCESSED
;
1343 BufferListItem
= BufferListItem
->next
;
1345 ALSource
->position
= DataSize
;
1346 ALSource
->position_fraction
= 0;
1350 /* alSourceRewind */
1352 ALSource
->state
= AL_PLAYING
;
1353 ALSource
->inuse
= AL_TRUE
;
1354 ALSource
->play
= AL_TRUE
;
1355 ALSource
->BuffersPlayed
= 0;
1356 BufferListItem
= ALSource
->queue
;
1357 while(BufferListItem
!= NULL
)
1359 BufferListItem
->bufferstate
= PENDING
;
1360 BufferListItem
= BufferListItem
->next
;
1362 ALSource
->ulBufferID
= ALSource
->queue
->buffer
;
1364 if(ALSource
->BuffersInQueue
== 1)
1365 ALSource
->position
= DataPosInt
%DataSize
;
1367 ALSource
->position
= DataPosInt
-DataSize
;
1368 ALSource
->position_fraction
= DataPosFrac
;
1375 State
= ALSource
->state
;
1378 ALSource
= ALSource
->next
;
1381 // effect slot processing
1384 if(ALEffectSlot
->effect
.type
== AL_EFFECT_REVERB
)
1385 VerbProcess(ALEffectSlot
->ReverbState
, SamplesToDo
, ALEffectSlot
->WetBuffer
, DryBuffer
);
1386 else if(ALEffectSlot
->effect
.type
== AL_EFFECT_ECHO
)
1387 EchoProcess(ALEffectSlot
->EchoState
, SamplesToDo
, ALEffectSlot
->WetBuffer
, DryBuffer
);
1389 for(i
= 0;i
< SamplesToDo
;i
++)
1390 ALEffectSlot
->WetBuffer
[i
] = 0.0f
;
1391 ALEffectSlot
= ALEffectSlot
->next
;
1394 //Post processing loop
1397 case AL_FORMAT_MONO8
:
1398 for(i
= 0;i
< SamplesToDo
;i
++)
1400 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1401 buffer
= ((ALubyte
*)buffer
) + 1;
1404 case AL_FORMAT_STEREO8
:
1405 if(ALContext
&& ALContext
->bs2b
)
1407 for(i
= 0;i
< SamplesToDo
;i
++)
1410 samples
[0] = DryBuffer
[i
][FRONT_LEFT
];
1411 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
];
1412 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1413 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(samples
[0])>>8)+128);
1414 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(samples
[1])>>8)+128);
1415 buffer
= ((ALubyte
*)buffer
) + 2;
1420 for(i
= 0;i
< SamplesToDo
;i
++)
1422 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1423 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1424 buffer
= ((ALubyte
*)buffer
) + 2;
1428 case AL_FORMAT_QUAD8
:
1429 for(i
= 0;i
< SamplesToDo
;i
++)
1431 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1432 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1433 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1434 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1435 buffer
= ((ALubyte
*)buffer
) + 4;
1438 case AL_FORMAT_51CHN8
:
1439 for(i
= 0;i
< SamplesToDo
;i
++)
1441 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1442 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1443 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1444 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_CENTER
])>>8)+128);
1445 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1446 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1447 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1449 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1450 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1451 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_CENTER
])>>8)+128);
1452 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1454 buffer
= ((ALubyte
*)buffer
) + 6;
1457 case AL_FORMAT_61CHN8
:
1458 for(i
= 0;i
< SamplesToDo
;i
++)
1460 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1461 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1462 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_CENTER
])>>8)+128);
1463 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1464 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_CENTER
])>>8)+128);
1465 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
])>>8)+128);
1466 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1467 buffer
= ((ALubyte
*)buffer
) + 7;
1470 case AL_FORMAT_71CHN8
:
1471 for(i
= 0;i
< SamplesToDo
;i
++)
1473 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
])>>8)+128);
1474 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
])>>8)+128);
1476 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_CENTER
])>>8)+128);
1477 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1478 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1479 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1481 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
])>>8)+128);
1482 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
])>>8)+128);
1483 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_CENTER
])>>8)+128);
1484 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
])>>8)+128);
1486 ((ALubyte
*)buffer
)[6] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_LEFT
])>>8)+128);
1487 ((ALubyte
*)buffer
)[7] = (ALubyte
)((aluF2S(DryBuffer
[i
][SIDE_RIGHT
])>>8)+128);
1488 buffer
= ((ALubyte
*)buffer
) + 8;
1492 case AL_FORMAT_MONO16
:
1493 for(i
= 0;i
< SamplesToDo
;i
++)
1495 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]);
1496 buffer
= ((ALshort
*)buffer
) + 1;
1499 case AL_FORMAT_STEREO16
:
1500 if(ALContext
&& ALContext
->bs2b
)
1502 for(i
= 0;i
< SamplesToDo
;i
++)
1505 samples
[0] = DryBuffer
[i
][FRONT_LEFT
];
1506 samples
[1] = DryBuffer
[i
][FRONT_RIGHT
];
1507 bs2b_cross_feed(ALContext
->bs2b
, samples
);
1508 ((ALshort
*)buffer
)[0] = aluF2S(samples
[0]);
1509 ((ALshort
*)buffer
)[1] = aluF2S(samples
[1]);
1510 buffer
= ((ALshort
*)buffer
) + 2;
1515 for(i
= 0;i
< SamplesToDo
;i
++)
1517 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1518 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1519 buffer
= ((ALshort
*)buffer
) + 2;
1523 case AL_FORMAT_QUAD16
:
1524 for(i
= 0;i
< SamplesToDo
;i
++)
1526 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1527 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1528 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1529 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1530 buffer
= ((ALshort
*)buffer
) + 4;
1533 case AL_FORMAT_51CHN16
:
1534 for(i
= 0;i
< SamplesToDo
;i
++)
1536 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1537 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1539 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][FRONT_CENTER
]);
1540 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
]);
1541 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1542 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1544 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1545 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1546 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][FRONT_CENTER
]);
1547 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
]);
1549 buffer
= ((ALshort
*)buffer
) + 6;
1552 case AL_FORMAT_61CHN16
:
1553 for(i
= 0;i
< SamplesToDo
;i
++)
1555 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1556 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1557 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][FRONT_CENTER
]);
1558 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
]);
1559 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_CENTER
]);
1560 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][SIDE_LEFT
]);
1561 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
]);
1562 buffer
= ((ALshort
*)buffer
) + 7;
1565 case AL_FORMAT_71CHN16
:
1566 for(i
= 0;i
< SamplesToDo
;i
++)
1568 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]);
1569 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]);
1571 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][FRONT_CENTER
]);
1572 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][LFE
]);
1573 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1574 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1576 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
]);
1577 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
]);
1578 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][FRONT_CENTER
]);
1579 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
]);
1581 ((ALshort
*)buffer
)[6] = aluF2S(DryBuffer
[i
][SIDE_LEFT
]);
1582 ((ALshort
*)buffer
)[7] = aluF2S(DryBuffer
[i
][SIDE_RIGHT
]);
1583 buffer
= ((ALshort
*)buffer
) + 8;
1591 size
-= SamplesToDo
;
1594 #if defined(HAVE_FESETROUND)
1595 fesetround(fpuState
);
1596 #elif defined(HAVE__CONTROLFP)
1597 _controlfp(fpuState
, 0xfffff);
1600 ProcessContext(ALContext
);