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
30 #if defined(HAVE_STDINT_H)
32 typedef int64_t ALint64
;
33 #elif defined(HAVE___INT64)
34 typedef __int64 ALint64
;
35 #elif (SIZEOF_LONG == 8)
37 #elif (SIZEOF_LONG_LONG == 8)
38 typedef long long ALint64
;
42 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
44 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
48 #if defined(max) && !defined(__max)
51 #if defined(min) && !defined(__min)
55 __inline ALuint
aluBytesFromFormat(ALenum format
)
60 case AL_FORMAT_STEREO8
:
64 case AL_FORMAT_MONO16
:
65 case AL_FORMAT_STEREO16
:
66 case AL_FORMAT_QUAD16
:
74 __inline ALuint
aluChannelsFromFormat(ALenum format
)
79 case AL_FORMAT_MONO16
:
82 case AL_FORMAT_STEREO8
:
83 case AL_FORMAT_STEREO16
:
87 case AL_FORMAT_QUAD16
:
95 static __inline ALint
aluF2L(ALfloat Value
)
97 if(sizeof(ALint
) == 4 && sizeof(double) == 8)
100 temp
= Value
+ (((65536.0*65536.0*16.0)+(65536.0*65536.0*8.0))*65536.0);
101 return *((ALint
*)&temp
);
106 static __inline ALshort
aluF2S(ALfloat Value
)
111 i
= __min( 32767, i
);
112 i
= __max(-32768, i
);
116 static __inline ALvoid
aluCrossproduct(ALfloat
*inVector1
,ALfloat
*inVector2
,ALfloat
*outVector
)
118 outVector
[0] = inVector1
[1]*inVector2
[2] - inVector1
[2]*inVector2
[1];
119 outVector
[1] = inVector1
[2]*inVector2
[0] - inVector1
[0]*inVector2
[2];
120 outVector
[2] = inVector1
[0]*inVector2
[1] - inVector1
[1]*inVector2
[0];
123 static __inline ALfloat
aluDotproduct(ALfloat
*inVector1
,ALfloat
*inVector2
)
125 return inVector1
[0]*inVector2
[0] + inVector1
[1]*inVector2
[1] +
126 inVector1
[2]*inVector2
[2];
129 static __inline ALvoid
aluNormalize(ALfloat
*inVector
)
131 ALfloat length
, inverse_length
;
133 length
= (ALfloat
)aluSqrt(aluDotproduct(inVector
, inVector
));
136 inverse_length
= 1.0f
/length
;
137 inVector
[0] *= inverse_length
;
138 inVector
[1] *= inverse_length
;
139 inVector
[2] *= inverse_length
;
143 static __inline ALvoid
aluMatrixVector(ALfloat
*vector
,ALfloat matrix
[3][3])
147 result
[0] = vector
[0]*matrix
[0][0] + vector
[1]*matrix
[1][0] + vector
[2]*matrix
[2][0];
148 result
[1] = vector
[0]*matrix
[0][1] + vector
[1]*matrix
[1][1] + vector
[2]*matrix
[2][1];
149 result
[2] = vector
[0]*matrix
[0][2] + vector
[1]*matrix
[1][2] + vector
[2]*matrix
[2][2];
150 memcpy(vector
, result
, sizeof(result
));
153 static __inline ALfloat
aluComputeDrySample(ALsource
*source
, ALfloat DryGainHF
, ALfloat sample
)
158 sample
+= source
->LastDrySample
* (1.0f
- DryGainHF
);
161 source
->LastDrySample
= sample
;
165 static __inline ALfloat
aluComputeWetSample(ALsource
*source
, ALfloat WetGainHF
, ALfloat sample
)
170 sample
+= source
->LastWetSample
* (1.0f
- WetGainHF
);
173 source
->LastWetSample
= sample
;
177 static ALvoid
CalcSourceParams(ALCcontext
*ALContext
, ALsource
*ALSource
,
178 ALenum isMono
, ALenum OutputFormat
,
179 ALfloat
*drysend
, ALfloat
*wetsend
,
180 ALfloat
*pitch
, ALfloat
*drygainhf
,
183 ALfloat ListenerOrientation
[6],ListenerPosition
[3],ListenerVelocity
[3];
184 ALfloat InnerAngle
,OuterAngle
,OuterGain
,Angle
,Distance
,DryMix
,WetMix
;
185 ALfloat Direction
[3],Position
[3],Velocity
[3],SourceToListener
[3];
186 ALfloat MinVolume
,MaxVolume
,MinDist
,MaxDist
,Rolloff
,OuterGainHF
;
187 ALfloat Pitch
,ConeVolume
,SourceVolume
,PanningFB
,PanningLR
,ListenerGain
;
188 ALfloat U
[3],V
[3],N
[3];
189 ALfloat DopplerFactor
, DopplerVelocity
, flSpeedOfSound
, flMaxVelocity
;
190 ALfloat flVSS
, flVLS
;
192 ALfloat Matrix
[3][3];
194 ALfloat flAttenuation
;
195 ALfloat RoomAttenuation
;
196 ALfloat MetersPerUnit
;
198 ALfloat DryGainHF
= 1.0f
;
199 ALfloat WetGainHF
= 1.0f
;
201 //Get context properties
202 DopplerFactor
= ALContext
->DopplerFactor
;
203 DistanceModel
= ALContext
->DistanceModel
;
204 DopplerVelocity
= ALContext
->DopplerVelocity
;
205 flSpeedOfSound
= ALContext
->flSpeedOfSound
;
207 //Get listener properties
208 ListenerGain
= ALContext
->Listener
.Gain
;
209 MetersPerUnit
= ALContext
->Listener
.MetersPerUnit
;
210 memcpy(ListenerPosition
, ALContext
->Listener
.Position
, sizeof(ALContext
->Listener
.Position
));
211 memcpy(ListenerVelocity
, ALContext
->Listener
.Velocity
, sizeof(ALContext
->Listener
.Velocity
));
212 memcpy(&ListenerOrientation
[0], ALContext
->Listener
.Forward
, sizeof(ALContext
->Listener
.Forward
));
213 memcpy(&ListenerOrientation
[3], ALContext
->Listener
.Up
, sizeof(ALContext
->Listener
.Up
));
215 //Get source properties
216 Pitch
= ALSource
->flPitch
;
217 SourceVolume
= ALSource
->flGain
;
218 memcpy(Position
, ALSource
->vPosition
, sizeof(ALSource
->vPosition
));
219 memcpy(Velocity
, ALSource
->vVelocity
, sizeof(ALSource
->vVelocity
));
220 memcpy(Direction
, ALSource
->vOrientation
, sizeof(ALSource
->vOrientation
));
221 MinVolume
= ALSource
->flMinGain
;
222 MaxVolume
= ALSource
->flMaxGain
;
223 MinDist
= ALSource
->flRefDistance
;
224 MaxDist
= ALSource
->flMaxDistance
;
225 Rolloff
= ALSource
->flRollOffFactor
;
226 OuterGain
= ALSource
->flOuterGain
;
227 InnerAngle
= ALSource
->flInnerAngle
;
228 OuterAngle
= ALSource
->flOuterAngle
;
229 HeadRelative
= ALSource
->bHeadRelative
;
230 OuterGainHF
= ALSource
->OuterGainHF
;
231 RoomRolloff
= ALSource
->RoomRolloffFactor
;
233 //Only apply 3D calculations for mono buffers
234 if(isMono
!= AL_FALSE
)
236 //1. Translate Listener to origin (convert to head relative)
237 if(HeadRelative
==AL_FALSE
)
239 Position
[0] -= ListenerPosition
[0];
240 Position
[1] -= ListenerPosition
[1];
241 Position
[2] -= ListenerPosition
[2];
244 //2. Calculate distance attenuation
245 Distance
= aluSqrt(aluDotproduct(Position
, Position
));
247 flAttenuation
= 1.0f
;
248 RoomAttenuation
= 1.0f
;
249 switch (DistanceModel
)
251 case AL_INVERSE_DISTANCE_CLAMPED
:
252 Distance
=__max(Distance
,MinDist
);
253 Distance
=__min(Distance
,MaxDist
);
254 if (MaxDist
< MinDist
)
257 case AL_INVERSE_DISTANCE
:
260 if ((MinDist
+ (Rolloff
* (Distance
- MinDist
))) > 0.0f
)
261 flAttenuation
= MinDist
/ (MinDist
+ (Rolloff
* (Distance
- MinDist
)));
262 if ((MinDist
+ (RoomRolloff
* (Distance
- MinDist
))) > 0.0f
)
263 RoomAttenuation
= MinDist
/ (MinDist
+ (RoomRolloff
* (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
)
277 flAttenuation
= 1.0f
- (Rolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
278 RoomAttenuation
= 1.0f
- (RoomRolloff
*(Distance
-MinDist
)/(MaxDist
- MinDist
));
282 case AL_EXPONENT_DISTANCE_CLAMPED
:
283 Distance
=__max(Distance
,MinDist
);
284 Distance
=__min(Distance
,MaxDist
);
285 if (MaxDist
< MinDist
)
288 case AL_EXPONENT_DISTANCE
:
289 if ((Distance
> 0.0f
) && (MinDist
> 0.0f
))
291 flAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -Rolloff
);
292 RoomAttenuation
= (ALfloat
)pow(Distance
/MinDist
, -RoomRolloff
);
298 flAttenuation
= 1.0f
;
299 RoomAttenuation
= 1.0f
;
303 // Source Gain + Attenuation
304 DryMix
= SourceVolume
* flAttenuation
;
305 WetMix
= SourceVolume
* ((ALSource
->WetGainAuto
&&
306 ALSource
->Send
[0].Slot
.AuxSendAuto
) ?
307 RoomAttenuation
: 1.0f
);
309 // Clamp to Min/Max Gain
310 DryMix
= __min(DryMix
,MaxVolume
);
311 DryMix
= __max(DryMix
,MinVolume
);
312 WetMix
= __min(WetMix
,MaxVolume
);
313 WetMix
= __max(WetMix
,MinVolume
);
314 //3. Apply directional soundcones
315 SourceToListener
[0] = -Position
[0];
316 SourceToListener
[1] = -Position
[1];
317 SourceToListener
[2] = -Position
[2];
318 aluNormalize(Direction
);
319 aluNormalize(SourceToListener
);
320 Angle
= (ALfloat
)(180.0*acos(aluDotproduct(Direction
,SourceToListener
))/3.141592654f
);
321 if(Angle
>= InnerAngle
&& Angle
<= OuterAngle
)
323 ALfloat scale
= (Angle
-InnerAngle
) / (OuterAngle
-InnerAngle
);
324 ConeVolume
= (1.0f
+(OuterGain
-1.0f
)*scale
);
325 if(ALSource
->WetGainAuto
)
326 WetMix
*= ConeVolume
;
327 if(ALSource
->DryGainHFAuto
)
328 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
329 if(ALSource
->WetGainHFAuto
)
330 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
)*scale
);
332 else if(Angle
> OuterAngle
)
334 ConeVolume
= (1.0f
+(OuterGain
-1.0f
));
335 if(ALSource
->WetGainAuto
)
336 WetMix
*= ConeVolume
;
337 if(ALSource
->DryGainHFAuto
)
338 DryGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
339 if(ALSource
->WetGainHFAuto
)
340 WetGainHF
*= (1.0f
+(OuterGainHF
-1.0f
));
345 //4. Calculate Velocity
346 if(DopplerFactor
!= 0.0f
)
348 flVLS
= aluDotproduct(ListenerVelocity
, SourceToListener
);
349 flVSS
= aluDotproduct(Velocity
, SourceToListener
);
351 flMaxVelocity
= (DopplerVelocity
* flSpeedOfSound
) / DopplerFactor
;
353 if (flVSS
>= flMaxVelocity
)
354 flVSS
= (flMaxVelocity
- 1.0f
);
355 else if (flVSS
<= -flMaxVelocity
)
356 flVSS
= -flMaxVelocity
+ 1.0f
;
358 if (flVLS
>= flMaxVelocity
)
359 flVLS
= (flMaxVelocity
- 1.0f
);
360 else if (flVLS
<= -flMaxVelocity
)
361 flVLS
= -flMaxVelocity
+ 1.0f
;
363 pitch
[0] = Pitch
* ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVLS
)) /
364 ((flSpeedOfSound
* DopplerVelocity
) - (DopplerFactor
* flVSS
));
369 //5. Align coordinate system axes
370 aluCrossproduct(&ListenerOrientation
[0], &ListenerOrientation
[3], U
); // Right-vector
371 aluNormalize(U
); // Normalized Right-vector
372 memcpy(V
, &ListenerOrientation
[3], sizeof(V
)); // Up-vector
373 aluNormalize(V
); // Normalized Up-vector
374 memcpy(N
, &ListenerOrientation
[0], sizeof(N
)); // At-vector
375 aluNormalize(N
); // Normalized At-vector
376 Matrix
[0][0] = U
[0]; Matrix
[0][1] = V
[0]; Matrix
[0][2] = -N
[0];
377 Matrix
[1][0] = U
[1]; Matrix
[1][1] = V
[1]; Matrix
[1][2] = -N
[1];
378 Matrix
[2][0] = U
[2]; Matrix
[2][1] = V
[2]; Matrix
[2][2] = -N
[2];
379 aluMatrixVector(Position
, Matrix
);
381 //6. Convert normalized position into left/right front/back pannings
384 aluNormalize(Position
);
385 PanningLR
= 0.5f
+ 0.5f
*Position
[0];
386 PanningFB
= 0.5f
+ 0.5f
*Position
[2];
394 //7. Apply filter gains and filters
395 switch(ALSource
->DirectFilter
.filter
)
397 case AL_FILTER_LOWPASS
:
398 DryMix
*= ALSource
->DirectFilter
.Gain
;
399 DryGainHF
*= ALSource
->DirectFilter
.GainHF
;
403 switch(ALSource
->Send
[0].WetFilter
.filter
)
405 case AL_FILTER_LOWPASS
:
406 WetMix
*= ALSource
->Send
[0].WetFilter
.Gain
;
407 WetGainHF
*= ALSource
->Send
[0].WetFilter
.GainHF
;
411 if(ALSource
->AirAbsorptionFactor
> 0.0f
)
412 DryGainHF
*= pow(ALSource
->AirAbsorptionFactor
* AIRABSORBGAINHF
,
413 Distance
* MetersPerUnit
);
415 *drygainhf
= DryGainHF
;
416 *wetgainhf
= WetGainHF
;
418 //8. Convert pannings into channel volumes
419 WetMix
*= ALSource
->Send
[0].Slot
.Gain
;
422 case AL_FORMAT_MONO8
:
423 case AL_FORMAT_MONO16
:
424 drysend
[0] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
); //Direct
425 drysend
[1] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
); //Direct
426 wetsend
[0] = ListenerGain
* WetMix
* aluSqrt(1.0f
); //Room
427 wetsend
[1] = ListenerGain
* WetMix
* aluSqrt(1.0f
); //Room
429 case AL_FORMAT_STEREO8
:
430 case AL_FORMAT_STEREO16
:
431 drysend
[0] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(1.0f
-PanningLR
); //L Direct
432 drysend
[1] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt( PanningLR
); //R Direct
433 wetsend
[0] = ListenerGain
* WetMix
* aluSqrt(1.0f
-PanningLR
); //L Room
434 wetsend
[1] = ListenerGain
* WetMix
* aluSqrt( PanningLR
); //R Room
436 case AL_FORMAT_QUAD8
:
437 case AL_FORMAT_QUAD16
:
438 drysend
[0] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
)); //FL Direct
439 drysend
[1] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
)); //FR Direct
440 drysend
[2] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
)); //BL Direct
441 drysend
[3] = ConeVolume
* ListenerGain
* DryMix
* aluSqrt(( PanningLR
)*( PanningFB
)); //BR Direct
442 wetsend
[0] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*(1.0f
-PanningFB
)); //FL Room
443 wetsend
[1] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*(1.0f
-PanningFB
)); //FR Room
444 wetsend
[2] = ListenerGain
* WetMix
* aluSqrt((1.0f
-PanningLR
)*( PanningFB
)); //BL Room
445 wetsend
[3] = ListenerGain
* WetMix
* aluSqrt(( PanningLR
)*( PanningFB
)); //BR Room
453 //1. Multi-channel buffers always play "normal"
454 drysend
[0] = SourceVolume
* 1.0f
* ListenerGain
;
455 drysend
[1] = SourceVolume
* 1.0f
* ListenerGain
;
456 drysend
[2] = SourceVolume
* 1.0f
* ListenerGain
;
457 drysend
[3] = SourceVolume
* 1.0f
* ListenerGain
;
458 wetsend
[0] = SourceVolume
* 0.0f
* ListenerGain
;
459 wetsend
[1] = SourceVolume
* 0.0f
* ListenerGain
;
460 wetsend
[2] = SourceVolume
* 0.0f
* ListenerGain
;
461 wetsend
[3] = SourceVolume
* 0.0f
* ListenerGain
;
465 *drygainhf
= DryGainHF
;
466 *wetgainhf
= WetGainHF
;
470 ALvoid
aluMixData(ALCcontext
*ALContext
,ALvoid
*buffer
,ALsizei size
,ALenum format
)
472 static float DryBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
473 static float WetBuffer
[BUFFERSIZE
][OUTPUTCHANNELS
];
474 ALfloat DrySend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
};
475 ALfloat WetSend
[OUTPUTCHANNELS
] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
};
476 ALfloat DryGainHF
= 0.0f
;
477 ALfloat WetGainHF
= 0.0f
;
478 ALuint BlockAlign
,BufferSize
;
479 ALuint DataSize
=0,DataPosInt
=0,DataPosFrac
=0;
480 ALuint Channels
,Bits
,Frequency
,ulExtraSamples
;
482 ALint Looping
,increment
,State
;
483 ALuint Buffer
,fraction
;
490 ALbufferlistitem
*BufferListItem
;
492 ALint64 DataSize64
,DataPos64
;
494 SuspendContext(ALContext
);
498 //Figure output format variables
499 BlockAlign
= aluChannelsFromFormat(format
);
500 BlockAlign
*= aluBytesFromFormat(format
);
506 ALSource
= (ALContext
? ALContext
->Source
: NULL
);
507 SamplesToDo
= min(size
, BUFFERSIZE
);
509 //Clear mixing buffer
510 memset(DryBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
511 memset(WetBuffer
, 0, SamplesToDo
*OUTPUTCHANNELS
*sizeof(ALfloat
));
517 State
= ALSource
->state
;
518 while(State
== AL_PLAYING
&& j
< SamplesToDo
)
525 if((Buffer
= ALSource
->ulBufferID
))
527 ALBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(Buffer
);
529 Data
= ALBuffer
->data
;
530 Bits
= aluBytesFromFormat(ALBuffer
->format
) * 8;
531 Channels
= aluChannelsFromFormat(ALBuffer
->format
);
532 DataSize
= ALBuffer
->size
;
533 Frequency
= ALBuffer
->frequency
;
535 CalcSourceParams(ALContext
, ALSource
,
536 (Channels
==1) ? AL_TRUE
: AL_FALSE
,
537 format
, DrySend
, WetSend
, &Pitch
,
538 &DryGainHF
, &WetGainHF
);
541 Pitch
= (Pitch
*Frequency
) / ALContext
->Frequency
;
542 DataSize
= DataSize
/ (Bits
*Channels
/8);
545 DataPosInt
= ALSource
->position
;
546 DataPosFrac
= ALSource
->position_fraction
;
548 //Compute 18.14 fixed point step
549 increment
= aluF2L(Pitch
*(1L<<FRACTIONBITS
));
550 if(increment
> (MAX_PITCH
<<FRACTIONBITS
))
551 increment
= (MAX_PITCH
<<FRACTIONBITS
);
553 //Figure out how many samples we can mix.
554 //Pitch must be <= 4 (the number below !)
555 DataSize64
= DataSize
+MAX_PITCH
;
556 DataSize64
<<= FRACTIONBITS
;
557 DataPos64
= DataPosInt
;
558 DataPos64
<<= FRACTIONBITS
;
559 DataPos64
+= DataPosFrac
;
560 BufferSize
= (ALuint
)((DataSize64
-DataPos64
) / increment
);
561 BufferListItem
= ALSource
->queue
;
562 for(loop
= 0; loop
< ALSource
->BuffersPlayed
; loop
++)
565 BufferListItem
= BufferListItem
->next
;
569 if (BufferListItem
->next
)
571 if(BufferListItem
->next
->buffer
&&
572 ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->data
)
574 ulExtraSamples
= min(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->size
, (ALint
)(16*Channels
));
575 memcpy(&Data
[DataSize
*Channels
], ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(BufferListItem
->next
->buffer
))->data
, ulExtraSamples
);
578 else if (ALSource
->bLooping
)
580 if (ALSource
->queue
->buffer
)
582 if(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->data
)
584 ulExtraSamples
= min(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->size
, (ALint
)(16*Channels
));
585 memcpy(&Data
[DataSize
*Channels
], ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALSource
->queue
->buffer
))->data
, ulExtraSamples
);
590 BufferSize
= min(BufferSize
, (SamplesToDo
-j
));
592 //Actual sample mixing loop
593 Data
+= DataPosInt
*Channels
;
596 k
= DataPosFrac
>>FRACTIONBITS
;
597 fraction
= DataPosFrac
&FRACTIONMASK
;
600 //First order interpolator
601 ALfloat sample
= (ALfloat
)((ALshort
)(((Data
[k
]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[k
+1]*(fraction
)))>>FRACTIONBITS
));
603 //Direct path final mix buffer and panning
604 value
= aluComputeDrySample(ALSource
, DryGainHF
, sample
);
605 DryBuffer
[j
][0] += value
*DrySend
[0];
606 DryBuffer
[j
][1] += value
*DrySend
[1];
607 DryBuffer
[j
][2] += value
*DrySend
[2];
608 DryBuffer
[j
][3] += value
*DrySend
[3];
610 if(ALSource
->Send
[0].Slot
.effectslot
)
612 //Room path final mix buffer and panning
613 value
= aluComputeWetSample(ALSource
, WetGainHF
, sample
);
614 WetBuffer
[j
][0] += value
*WetSend
[0];
615 WetBuffer
[j
][1] += value
*WetSend
[1];
616 WetBuffer
[j
][2] += value
*WetSend
[2];
617 WetBuffer
[j
][3] += value
*WetSend
[3];
622 //First order interpolator (left)
623 value
= (ALfloat
)((ALshort
)(((Data
[k
*2 ]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[k
*2+2]*(fraction
)))>>FRACTIONBITS
));
624 //Direct path final mix buffer and panning (left)
625 DryBuffer
[j
][0] += value
*DrySend
[0];
626 //Room path final mix buffer and panning (left)
627 WetBuffer
[j
][0] += value
*WetSend
[0];
628 //First order interpolator (right)
629 value
= (ALfloat
)((ALshort
)(((Data
[k
*2+1]*((1L<<FRACTIONBITS
)-fraction
))+(Data
[k
*2+3]*(fraction
)))>>FRACTIONBITS
));
630 //Direct path final mix buffer and panning (right)
631 DryBuffer
[j
][1] += value
*DrySend
[1];
632 //Room path final mix buffer and panning (right)
633 WetBuffer
[j
][1] += value
*WetSend
[1];
635 DataPosFrac
+= increment
;
638 DataPosInt
+= (DataPosFrac
>>FRACTIONBITS
);
639 DataPosFrac
= (DataPosFrac
&FRACTIONMASK
);
642 ALSource
->position
= DataPosInt
;
643 ALSource
->position_fraction
= DataPosFrac
;
646 //Handle looping sources
647 if(!Buffer
|| DataPosInt
>= DataSize
)
652 Looping
= ALSource
->bLooping
;
653 if(ALSource
->BuffersPlayed
< (ALSource
->BuffersInQueue
-1))
655 BufferListItem
= ALSource
->queue
;
656 for(loop
= 0; loop
<= ALSource
->BuffersPlayed
; loop
++)
661 BufferListItem
->bufferstate
= PROCESSED
;
662 BufferListItem
= BufferListItem
->next
;
666 ALSource
->BuffersProcessed
++;
668 ALSource
->ulBufferID
= BufferListItem
->buffer
;
669 ALSource
->position
= DataPosInt
-DataSize
;
670 ALSource
->position_fraction
= DataPosFrac
;
671 ALSource
->BuffersPlayed
++;
678 ALSource
->state
= AL_STOPPED
;
679 ALSource
->inuse
= AL_FALSE
;
680 ALSource
->BuffersPlayed
= ALSource
->BuffersProcessed
= ALSource
->BuffersInQueue
;
681 BufferListItem
= ALSource
->queue
;
682 while(BufferListItem
!= NULL
)
684 BufferListItem
->bufferstate
= PROCESSED
;
685 BufferListItem
= BufferListItem
->next
;
692 ALSource
->state
= AL_PLAYING
;
693 ALSource
->inuse
= AL_TRUE
;
694 ALSource
->play
= AL_TRUE
;
695 ALSource
->BuffersPlayed
= 0;
696 ALSource
->BufferPosition
= 0;
697 ALSource
->lBytesPlayed
= 0;
698 ALSource
->BuffersProcessed
= 0;
699 BufferListItem
= ALSource
->queue
;
700 while(BufferListItem
!= NULL
)
702 BufferListItem
->bufferstate
= PENDING
;
703 BufferListItem
= BufferListItem
->next
;
705 ALSource
->ulBufferID
= ALSource
->queue
->buffer
;
707 ALSource
->position
= DataPosInt
-DataSize
;
708 ALSource
->position_fraction
= DataPosFrac
;
715 State
= ALSource
->state
;
718 ALSource
= ALSource
->next
;
721 //Post processing loop
724 case AL_FORMAT_MONO8
:
725 for(i
= 0;i
< SamplesToDo
;i
++)
727 *((ALubyte
*)buffer
) = (ALubyte
)((aluF2S(DryBuffer
[i
][0]+DryBuffer
[i
][1]+WetBuffer
[i
][0]+WetBuffer
[i
][1])>>8)+128);
728 buffer
= ((ALubyte
*)buffer
) + 1;
731 case AL_FORMAT_STEREO8
:
732 for(i
= 0;i
< SamplesToDo
*2;i
++)
734 *((ALubyte
*)buffer
) = (ALubyte
)((aluF2S(DryBuffer
[i
>>1][i
&1]+WetBuffer
[i
>>1][i
&1])>>8)+128);
735 buffer
= ((ALubyte
*)buffer
) + 1;
738 case AL_FORMAT_QUAD8
:
739 for(i
= 0;i
< SamplesToDo
*4;i
++)
741 *((ALubyte
*)buffer
) = (ALubyte
)((aluF2S(DryBuffer
[i
>>2][i
&3]+WetBuffer
[i
>>2][i
&3])>>8)+128);
742 buffer
= ((ALubyte
*)buffer
) + 1;
745 case AL_FORMAT_MONO16
:
746 for(i
= 0;i
< SamplesToDo
;i
++)
748 *((ALshort
*)buffer
) = aluF2S(DryBuffer
[i
][0]+DryBuffer
[i
][1]+WetBuffer
[i
][0]+WetBuffer
[i
][1]);
749 buffer
= ((ALshort
*)buffer
) + 1;
752 case AL_FORMAT_STEREO16
:
754 for(i
= 0;i
< SamplesToDo
*2;i
++)
756 *((ALshort
*)buffer
) = aluF2S(DryBuffer
[i
>>1][i
&1]+WetBuffer
[i
>>1][i
&1]);
757 buffer
= ((ALshort
*)buffer
) + 1;
760 case AL_FORMAT_QUAD16
:
761 for(i
= 0;i
< SamplesToDo
*4;i
++)
763 *((ALshort
*)buffer
) = aluF2S(DryBuffer
[i
>>2][i
&3]+WetBuffer
[i
>>2][i
&3]);
764 buffer
= ((ALshort
*)buffer
) + 1;
773 ProcessContext(ALContext
);