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"
34 #if defined(HAVE_STDINT_H)
36 typedef int64_t ALint64
;
37 #elif defined(HAVE___INT64)
38 typedef __int64 ALint64
;
39 #elif (SIZEOF_LONG == 8)
41 #elif (SIZEOF_LONG_LONG == 8)
42 typedef long long ALint64
;
46 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
48 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
52 #if defined(max) && !defined(__max)
55 #if defined(min) && !defined(__min)
59 #define BUFFERSIZE 48000
60 #define FRACTIONBITS 14
61 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
75 __inline ALuint
aluBytesFromFormat(ALenum format
)
80 case AL_FORMAT_STEREO8
:
82 case AL_FORMAT_51CHN8
:
85 case AL_FORMAT_MONO16
:
86 case AL_FORMAT_STEREO16
:
87 case AL_FORMAT_QUAD16
:
88 case AL_FORMAT_51CHN16
:
91 case AL_FORMAT_MONO_FLOAT32
:
92 case AL_FORMAT_STEREO_FLOAT32
:
100 __inline ALuint
aluChannelsFromFormat(ALenum format
)
104 case AL_FORMAT_MONO8
:
105 case AL_FORMAT_MONO16
:
106 case AL_FORMAT_MONO_FLOAT32
:
109 case AL_FORMAT_STEREO8
:
110 case AL_FORMAT_STEREO16
:
111 case AL_FORMAT_STEREO_FLOAT32
:
114 case AL_FORMAT_QUAD8
:
115 case AL_FORMAT_QUAD16
:
118 case AL_FORMAT_51CHN8
:
119 case AL_FORMAT_51CHN16
:
127 static __inline ALint
aluF2L(ALfloat Value
)
129 if(sizeof(ALint
) == 4 && sizeof(double) == 8)
132 temp
= Value
+ (((65536.0*65536.0*16.0)+(65536.0*65536.0*8.0))*65536.0);
133 return *((ALint
*)&temp
);
138 static __inline ALshort
aluF2S(ALfloat Value
)
143 i
= __min( 32767, i
);
144 i
= __max(-32768, i
);
148 static __inline ALvoid
aluCrossproduct(ALfloat
*inVector1
,ALfloat
*inVector2
,ALfloat
*outVector
)
150 outVector
[0] = inVector1
[1]*inVector2
[2] - inVector1
[2]*inVector2
[1];
151 outVector
[1] = inVector1
[2]*inVector2
[0] - inVector1
[0]*inVector2
[2];
152 outVector
[2] = inVector1
[0]*inVector2
[1] - inVector1
[1]*inVector2
[0];
155 static __inline ALfloat
aluDotproduct(ALfloat
*inVector1
,ALfloat
*inVector2
)
157 return inVector1
[0]*inVector2
[0] + inVector1
[1]*inVector2
[1] +
158 inVector1
[2]*inVector2
[2];
161 static __inline ALvoid
aluNormalize(ALfloat
*inVector
)
163 ALfloat length
, inverse_length
;
165 length
= (ALfloat
)aluSqrt(aluDotproduct(inVector
, inVector
));
168 inverse_length
= 1.0f
/length
;
169 inVector
[0] *= inverse_length
;
170 inVector
[1] *= inverse_length
;
171 inVector
[2] *= inverse_length
;
175 static __inline ALvoid
aluMatrixVector(ALfloat
*vector
,ALfloat matrix
[3][3])
179 result
[0] = vector
[0]*matrix
[0][0] + vector
[1]*matrix
[1][0] + vector
[2]*matrix
[2][0];
180 result
[1] = vector
[0]*matrix
[0][1] + vector
[1]*matrix
[1][1] + vector
[2]*matrix
[2][1];
181 result
[2] = vector
[0]*matrix
[0][2] + vector
[1]*matrix
[1][2] + vector
[2]*matrix
[2][2];
182 memcpy(vector
, result
, sizeof(result
));
185 static ALvoid
CalcSourceParams(ALCcontext
*ALContext
, ALsource
*ALSource
,
186 ALenum isMono
, ALenum OutputFormat
,
187 ALfloat
*drysend
, ALfloat
*wetsend
,
190 ALfloat ListenerOrientation
[6],ListenerPosition
[3],ListenerVelocity
[3];
191 ALfloat InnerAngle
,OuterAngle
,OuterGain
,Angle
,Distance
,DryMix
,WetMix
;
192 ALfloat Direction
[3],Position
[3],Velocity
[3],SourceToListener
[3];
193 ALfloat MinVolume
,MaxVolume
,MinDist
,MaxDist
,Rolloff
;
194 ALfloat Pitch
,ConeVolume
,SourceVolume
,PanningFB
,PanningLR
,ListenerGain
;
195 ALfloat U
[3],V
[3],N
[3];
196 ALfloat DopplerFactor
, DopplerVelocity
, flSpeedOfSound
, flMaxVelocity
;
197 ALfloat flVSS
, flVLS
;
199 ALfloat Matrix
[3][3];
201 ALfloat flAttenuation
;
203 //Get context properties
204 DopplerFactor
= ALContext
->DopplerFactor
;
205 DistanceModel
= ALContext
->DistanceModel
;
206 DopplerVelocity
= ALContext
->DopplerVelocity
;
207 flSpeedOfSound
= ALContext
->flSpeedOfSound
;
209 //Get listener properties
210 ListenerGain
= ALContext
->Listener
.Gain
;
211 memcpy(ListenerPosition
, ALContext
->Listener
.Position
, sizeof(ALContext
->Listener
.Position
));
212 memcpy(ListenerVelocity
, ALContext
->Listener
.Velocity
, sizeof(ALContext
->Listener
.Velocity
));
213 memcpy(&ListenerOrientation
[0], ALContext
->Listener
.Forward
, sizeof(ALContext
->Listener
.Forward
));
214 memcpy(&ListenerOrientation
[3], ALContext
->Listener
.Up
, sizeof(ALContext
->Listener
.Up
));
216 //Get source properties
217 Pitch
= ALSource
->flPitch
;
218 SourceVolume
= ALSource
->flGain
;
219 memcpy(Position
, ALSource
->vPosition
, sizeof(ALSource
->vPosition
));
220 memcpy(Velocity
, ALSource
->vVelocity
, sizeof(ALSource
->vVelocity
));
221 memcpy(Direction
, ALSource
->vOrientation
, sizeof(ALSource
->vOrientation
));
222 MinVolume
= ALSource
->flMinGain
;
223 MaxVolume
= ALSource
->flMaxGain
;
224 MinDist
= ALSource
->flRefDistance
;
225 MaxDist
= ALSource
->flMaxDistance
;
226 Rolloff
= ALSource
->flRollOffFactor
;
227 OuterGain
= ALSource
->flOuterGain
;
228 InnerAngle
= ALSource
->flInnerAngle
;
229 OuterAngle
= ALSource
->flOuterAngle
;
230 HeadRelative
= ALSource
->bHeadRelative
;
232 //Set working variables
233 DryMix
= (ALfloat
)(1.0f
);
234 WetMix
= (ALfloat
)(0.0f
);
236 //Only apply 3D calculations for mono buffers
237 if(isMono
!= AL_FALSE
)
239 //1. Translate Listener to origin (convert to head relative)
240 if(HeadRelative
==AL_FALSE
)
242 Position
[0] -= ListenerPosition
[0];
243 Position
[1] -= ListenerPosition
[1];
244 Position
[2] -= ListenerPosition
[2];
247 //2. Calculate distance attenuation
248 Distance
= aluSqrt(aluDotproduct(Position
, Position
));
250 flAttenuation
= 1.0f
;
251 switch (DistanceModel
)
253 case AL_INVERSE_DISTANCE_CLAMPED
:
254 Distance
=__max(Distance
,MinDist
);
255 Distance
=__min(Distance
,MaxDist
);
256 if (MaxDist
< MinDist
)
259 case AL_INVERSE_DISTANCE
:
262 if ((MinDist
+ (Rolloff
* (Distance
- MinDist
))) > 0.0f
)
263 flAttenuation
= MinDist
/ (MinDist
+ (Rolloff
* (Distance
- MinDist
)));
267 case AL_LINEAR_DISTANCE_CLAMPED
:
268 Distance
=__max(Distance
,MinDist
);
269 Distance
=__min(Distance
,MaxDist
);
270 if (MaxDist
< MinDist
)
273 case AL_LINEAR_DISTANCE
:
274 Distance
=__min(Distance
,MaxDist
);
275 if (MaxDist
!= MinDist
)
276 flAttenuation
= 1.0f
- (Rolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
279 case AL_EXPONENT_DISTANCE_CLAMPED
:
280 Distance
=__max(Distance
,MinDist
);
281 Distance
=__min(Distance
,MaxDist
);
282 if (MaxDist
< MinDist
)
285 case AL_EXPONENT_DISTANCE
:
286 if ((Distance
> 0.0f
) && (MinDist
> 0.0f
))
287 flAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -Rolloff
);
292 flAttenuation
= 1.0f
;
296 // Source Gain + Attenuation
297 DryMix
= SourceVolume
* flAttenuation
;
299 // Clamp to Min/Max Gain
300 DryMix
= __min(DryMix
,MaxVolume
);
301 DryMix
= __max(DryMix
,MinVolume
);
302 WetMix
= __min(WetMix
,MaxVolume
);
303 WetMix
= __max(WetMix
,MinVolume
);
304 //3. Apply directional soundcones
305 SourceToListener
[0] = -Position
[0];
306 SourceToListener
[1] = -Position
[1];
307 SourceToListener
[2] = -Position
[2];
308 aluNormalize(Direction
);
309 aluNormalize(SourceToListener
);
310 Angle
= (ALfloat
)(180.0*acos(aluDotproduct(Direction
,SourceToListener
))/3.141592654f
);
311 if(Angle
>= InnerAngle
&& Angle
<= OuterAngle
)
312 ConeVolume
= (1.0f
+(OuterGain
-1.0f
)*(Angle
-InnerAngle
)/(OuterAngle
-InnerAngle
));
313 else if(Angle
> OuterAngle
)
314 ConeVolume
= (1.0f
+(OuterGain
-1.0f
) );
318 //4. Calculate Velocity
319 if(DopplerFactor
!= 0.0f
)
321 flVLS
= aluDotproduct(ListenerVelocity
, SourceToListener
);
322 flVSS
= aluDotproduct(Velocity
, SourceToListener
);
324 flMaxVelocity
= (DopplerVelocity
* flSpeedOfSound
) / DopplerFactor
;
326 if (flVSS
>= flMaxVelocity
)
327 flVSS
= (flMaxVelocity
- 1.0f
);
328 else if (flVSS
<= -flMaxVelocity
)
329 flVSS
= -flMaxVelocity
+ 1.0f
;
331 if (flVLS
>= flMaxVelocity
)
332 flVLS
= (flMaxVelocity
- 1.0f
);
333 else if (flVLS
<= -flMaxVelocity
)
334 flVLS
= -flMaxVelocity
+ 1.0f
;
336 pitch
[0] = Pitch
* ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVLS
)) /
337 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVSS
));
342 //5. Align coordinate system axes
343 aluCrossproduct(&ListenerOrientation
[0], &ListenerOrientation
[3], U
); // Right-vector
344 aluNormalize(U
); // Normalized Right-vector
345 memcpy(V
, &ListenerOrientation
[3], sizeof(V
)); // Up-vector
346 aluNormalize(V
); // Normalized Up-vector
347 memcpy(N
, &ListenerOrientation
[0], sizeof(N
)); // At-vector
348 aluNormalize(N
); // Normalized At-vector
349 Matrix
[0][0] = U
[0]; Matrix
[0][1] = V
[0]; Matrix
[0][2] = -N
[0];
350 Matrix
[1][0] = U
[1]; Matrix
[1][1] = V
[1]; Matrix
[1][2] = -N
[1];
351 Matrix
[2][0] = U
[2]; Matrix
[2][1] = V
[2]; Matrix
[2][2] = -N
[2];
352 aluMatrixVector(Position
, Matrix
);
354 //6. Convert normalized position into pannings, then into channel volumes
355 aluNormalize(Position
);
356 switch(aluChannelsFromFormat(OutputFormat
))
359 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
); //Direct
360 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
); //Direct
361 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt(1.0f
); //Room
362 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(1.0f
); //Room
365 PanningLR
= 0.5f
+ 0.5f
*Position
[0];
366 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
-PanningLR
);
367 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt( PanningLR
);
368 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt(1.0f
-PanningLR
);
369 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt( PanningLR
);
372 /* TODO: Add center/lfe channel in spatial calculations? */
374 // Apply a scalar so each individual speaker has more weight
375 PanningLR
= 0.5f
+ (0.5f
*Position
[0]*1.41421356f
);
376 PanningLR
= __min(1.0f
, PanningLR
);
377 PanningLR
= __max(0.0f
, PanningLR
);
378 PanningFB
= 0.5f
+ (0.5f
*Position
[2]*1.41421356f
);
379 PanningFB
= __min(1.0f
, PanningFB
);
380 PanningFB
= __max(0.0f
, PanningFB
);
381 drysend
[FRONT_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
382 drysend
[FRONT_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
383 drysend
[BACK_LEFT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
384 drysend
[BACK_RIGHT
] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*( PanningFB
));
385 wetsend
[FRONT_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
));
386 wetsend
[FRONT_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
));
387 wetsend
[BACK_LEFT
] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
));
388 wetsend
[BACK_RIGHT
] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*( PanningFB
));
396 //1. Multi-channel buffers always play "normal"
397 drysend
[FRONT_LEFT
] = SourceVolume
* 1.0f
* ListenerGain
;
398 drysend
[FRONT_RIGHT
] = SourceVolume
* 1.0f
* ListenerGain
;
399 drysend
[BACK_LEFT
] = SourceVolume
* 1.0f
* ListenerGain
;
400 drysend
[BACK_RIGHT
] = SourceVolume
* 1.0f
* ListenerGain
;
401 drysend
[CENTER
] = SourceVolume
* 1.0f
* ListenerGain
;
402 drysend
[LFE
] = SourceVolume
* 1.0f
* ListenerGain
;
403 wetsend
[FRONT_LEFT
] = SourceVolume
* 0.0f
* ListenerGain
;
404 wetsend
[FRONT_RIGHT
] = SourceVolume
* 0.0f
* ListenerGain
;
405 wetsend
[BACK_LEFT
] = SourceVolume
* 0.0f
* ListenerGain
;
406 wetsend
[BACK_RIGHT
] = SourceVolume
* 0.0f
* ListenerGain
;
407 wetsend
[CENTER
] = SourceVolume
* 0.0f
* ListenerGain
;
408 wetsend
[LFE
] = SourceVolume
* 0.0f
* ListenerGain
;
414 ALvoid
aluMixData(ALCcontext
*ALContext
,ALvoid
*buffer
,ALsizei size
,ALenum format
)
416 static float DryBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
417 static float WetBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
418 ALfloat DrySend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
419 ALfloat WetSend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
};
420 ALuint BlockAlign
,BufferSize
;
421 ALuint DataSize
=0,DataPosInt
=0,DataPosFrac
=0;
422 ALuint Channels
,Bits
,Frequency
,ulExtraSamples
;
424 ALint Looping
,increment
,State
;
425 ALuint Buffer
,fraction
;
432 ALbufferlistitem
*BufferListItem
;
434 ALint64 DataSize64
,DataPos64
;
436 SuspendContext(ALContext
);
440 //Figure output format variables
441 BlockAlign
= aluChannelsFromFormat(format
);
442 BlockAlign
*= aluBytesFromFormat(format
);
448 ALSource
= (ALContext
? ALContext
->Source
: NULL
);
449 SamplesToDo
= min(size
, BUFFERSIZE
);
451 //Clear mixing buffer
452 memset(DryBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
453 memset(WetBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
459 State
= ALSource
->state
;
460 while(State
== AL_PLAYING
&& j
< SamplesToDo
)
467 if((Buffer
= ALSource
->ulBufferID
))
469 ALBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(Buffer
);
471 Data
= ALBuffer
->data
;
472 Bits
= aluBytesFromFormat(ALBuffer
->format
) * 8;
473 Channels
= aluChannelsFromFormat(ALBuffer
->format
);
474 DataSize
= ALBuffer
->size
;
475 Frequency
= ALBuffer
->frequency
;
477 CalcSourceParams(ALContext
, ALSource
,
478 (Channels
==1) ? AL_TRUE
: AL_FALSE
,
479 format
, DrySend
, WetSend
, &Pitch
);
482 Pitch
= (Pitch
*Frequency
) / ALContext
->Frequency
;
483 DataSize
= DataSize
/ (Bits
*Channels
/8);
486 DataPosInt
= ALSource
->position
;
487 DataPosFrac
= ALSource
->position_fraction
;
489 //Compute 18.14 fixed point step
490 increment
= aluF2L(Pitch
*(1L<<FRACTIONBITS
));
491 if(increment
> (MAX_PITCH
<<FRACTIONBITS
))
492 increment
= (MAX_PITCH
<<FRACTIONBITS
);
494 //Figure out how many samples we can mix.
495 //Pitch must be <= 4 (the number below !)
496 DataSize64
= DataSize
+MAX_PITCH
;
497 DataSize64
<<= FRACTIONBITS
;
498 DataPos64
= DataPosInt
;
499 DataPos64
<<= FRACTIONBITS
;
500 DataPos64
+= DataPosFrac
;
501 BufferSize
= (ALuint
)((DataSize64
-DataPos64
) / increment
);
502 BufferListItem
= ALSource
->queue
;
503 for(loop
= 0; loop
< ALSource
->BuffersPlayed
; loop
++)
506 BufferListItem
= BufferListItem
->next
;
510 if (BufferListItem
->next
)
512 if(BufferListItem
->next
->buffer
&&
513 ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->data
)
515 ulExtraSamples
= min(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->size
, (ALint
)(16*Channels
));
516 memcpy(&Data
[DataSize
*Channels
], ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->data
, ulExtraSamples
);
519 else if (ALSource
->bLooping
)
521 if (ALSource
->queue
->buffer
)
523 if(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->data
)
525 ulExtraSamples
= min(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->size
, (ALint
)(16*Channels
));
526 memcpy(&Data
[DataSize
*Channels
], ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->data
, ulExtraSamples
);
531 BufferSize
= min(BufferSize
, (SamplesToDo
-j
));
533 //Actual sample mixing loop
534 Data
+= DataPosInt
*Channels
;
537 k
= DataPosFrac
>>FRACTIONBITS
;
538 fraction
= DataPosFrac
&FRACTIONMASK
;
541 //First order interpolator
542 value
= (ALfloat
)((ALshort
)(((Data
[k
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[k
+1]*(fraction
)))>>FRACTIONBITS
));
543 //Direct path final mix buffer and panning
544 DryBuffer
[j
][FRONT_LEFT
] += value
*DrySend
[FRONT_LEFT
];
545 DryBuffer
[j
][FRONT_RIGHT
] += value
*DrySend
[FRONT_RIGHT
];
546 DryBuffer
[j
][BACK_LEFT
] += value
*DrySend
[BACK_LEFT
];
547 DryBuffer
[j
][BACK_RIGHT
] += value
*DrySend
[BACK_RIGHT
];
548 //Room path final mix buffer and panning
549 WetBuffer
[j
][FRONT_LEFT
] += value
*WetSend
[FRONT_LEFT
];
550 WetBuffer
[j
][FRONT_RIGHT
] += value
*WetSend
[FRONT_RIGHT
];
551 WetBuffer
[j
][BACK_LEFT
] += value
*WetSend
[BACK_LEFT
];
552 WetBuffer
[j
][BACK_RIGHT
] += value
*WetSend
[BACK_RIGHT
];
556 //First order interpolator (left)
557 value
= (ALfloat
)((ALshort
)(((Data
[k
*2 ]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[k
*2+2]*(fraction
)))>>FRACTIONBITS
));
558 //Direct path final mix buffer and panning (left)
559 DryBuffer
[j
][FRONT_LEFT
] += value
*DrySend
[FRONT_LEFT
];
560 //Room path final mix buffer and panning (left)
561 WetBuffer
[j
][FRONT_LEFT
] += value
*WetSend
[FRONT_LEFT
];
562 //First order interpolator (right)
563 value
= (ALfloat
)((ALshort
)(((Data
[k
*2+1]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[k
*2+3]*(fraction
)))>>FRACTIONBITS
));
564 //Direct path final mix buffer and panning (right)
565 DryBuffer
[j
][FRONT_RIGHT
] += value
*DrySend
[FRONT_RIGHT
];
566 //Room path final mix buffer and panning (right)
567 WetBuffer
[j
][FRONT_RIGHT
] += value
*WetSend
[FRONT_RIGHT
];
569 DataPosFrac
+= increment
;
572 DataPosInt
+= (DataPosFrac
>>FRACTIONBITS
);
573 DataPosFrac
= (DataPosFrac
&FRACTIONMASK
);
576 ALSource
->position
= DataPosInt
;
577 ALSource
->position_fraction
= DataPosFrac
;
580 //Handle looping sources
581 if(!Buffer
|| DataPosInt
>= DataSize
)
586 Looping
= ALSource
->bLooping
;
587 if(ALSource
->BuffersPlayed
< (ALSource
->BuffersInQueue
-1))
589 BufferListItem
= ALSource
->queue
;
590 for(loop
= 0; loop
<= ALSource
->BuffersPlayed
; loop
++)
595 BufferListItem
->bufferstate
= PROCESSED
;
596 BufferListItem
= BufferListItem
->next
;
600 ALSource
->BuffersProcessed
++;
602 ALSource
->ulBufferID
= BufferListItem
->buffer
;
603 ALSource
->position
= DataPosInt
-DataSize
;
604 ALSource
->position_fraction
= DataPosFrac
;
605 ALSource
->BuffersPlayed
++;
612 ALSource
->state
= AL_STOPPED
;
613 ALSource
->inuse
= AL_FALSE
;
614 ALSource
->BuffersPlayed
= ALSource
->BuffersProcessed
= ALSource
->BuffersInQueue
;
615 BufferListItem
= ALSource
->queue
;
616 while(BufferListItem
!= NULL
)
618 BufferListItem
->bufferstate
= PROCESSED
;
619 BufferListItem
= BufferListItem
->next
;
626 ALSource
->state
= AL_PLAYING
;
627 ALSource
->inuse
= AL_TRUE
;
628 ALSource
->play
= AL_TRUE
;
629 ALSource
->BuffersPlayed
= 0;
630 ALSource
->BufferPosition
= 0;
631 ALSource
->lBytesPlayed
= 0;
632 ALSource
->BuffersProcessed
= 0;
633 BufferListItem
= ALSource
->queue
;
634 while(BufferListItem
!= NULL
)
636 BufferListItem
->bufferstate
= PENDING
;
637 BufferListItem
= BufferListItem
->next
;
639 ALSource
->ulBufferID
= ALSource
->queue
->buffer
;
641 ALSource
->position
= DataPosInt
-DataSize
;
642 ALSource
->position_fraction
= DataPosFrac
;
649 State
= ALSource
->state
;
652 ALSource
= ALSource
->next
;
655 //Post processing loop
658 case AL_FORMAT_MONO8
:
659 for(i
= 0;i
< SamplesToDo
;i
++)
661 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
662 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
663 buffer
= ((ALubyte
*)buffer
) + 1;
666 case AL_FORMAT_STEREO8
:
667 for(i
= 0;i
< SamplesToDo
;i
++)
669 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
670 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
671 buffer
= ((ALubyte
*)buffer
) + 2;
674 case AL_FORMAT_QUAD8
:
675 for(i
= 0;i
< SamplesToDo
;i
++)
677 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
678 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
679 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
680 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
681 buffer
= ((ALubyte
*)buffer
) + 4;
684 case AL_FORMAT_51CHN8
:
685 for(i
= 0;i
< SamplesToDo
;i
++)
687 ((ALubyte
*)buffer
)[0] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
])>>8)+128);
688 ((ALubyte
*)buffer
)[1] = (ALubyte
)((aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
])>>8)+128);
689 ((ALubyte
*)buffer
)[2] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
])>>8)+128);
690 ((ALubyte
*)buffer
)[3] = (ALubyte
)((aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
])>>8)+128);
691 ((ALubyte
*)buffer
)[4] = (ALubyte
)((aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
])>>8)+128);
692 ((ALubyte
*)buffer
)[5] = (ALubyte
)((aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
])>>8)+128);
693 buffer
= ((ALubyte
*)buffer
) + 6;
696 case AL_FORMAT_MONO16
:
697 for(i
= 0;i
< SamplesToDo
;i
++)
699 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
]+DryBuffer
[i
][FRONT_RIGHT
]+
700 WetBuffer
[i
][FRONT_LEFT
]+WetBuffer
[i
][FRONT_RIGHT
]);
701 buffer
= ((ALshort
*)buffer
) + 1;
704 case AL_FORMAT_STEREO16
:
705 for(i
= 0;i
< SamplesToDo
;i
++)
707 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
708 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
709 buffer
= ((ALshort
*)buffer
) + 2;
712 case AL_FORMAT_QUAD16
:
713 for(i
= 0;i
< SamplesToDo
;i
++)
715 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
716 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
717 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
718 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
719 buffer
= ((ALshort
*)buffer
) + 4;
722 case AL_FORMAT_51CHN16
:
723 for(i
= 0;i
< SamplesToDo
;i
++)
725 ((ALshort
*)buffer
)[0] = aluF2S(DryBuffer
[i
][FRONT_LEFT
] +WetBuffer
[i
][FRONT_LEFT
]);
726 ((ALshort
*)buffer
)[1] = aluF2S(DryBuffer
[i
][FRONT_RIGHT
]+WetBuffer
[i
][FRONT_RIGHT
]);
727 ((ALshort
*)buffer
)[2] = aluF2S(DryBuffer
[i
][BACK_LEFT
] +WetBuffer
[i
][BACK_LEFT
]);
728 ((ALshort
*)buffer
)[3] = aluF2S(DryBuffer
[i
][BACK_RIGHT
] +WetBuffer
[i
][BACK_RIGHT
]);
729 ((ALshort
*)buffer
)[4] = aluF2S(DryBuffer
[i
][CENTER
] +WetBuffer
[i
][CENTER
]);
730 ((ALshort
*)buffer
)[5] = aluF2S(DryBuffer
[i
][LFE
] +WetBuffer
[i
][LFE
]);
731 buffer
= ((ALshort
*)buffer
) + 6;
743 ProcessContext(ALContext
);