Air absorption factor is applied to the dB value, not linear gain
[openal-soft.git] / Alc / ALu.c
blob9baf6cee3e9cd670b44add4cbfc96c15a4927816
1 /**
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
23 #include "config.h"
25 #include <math.h>
26 #include "alMain.h"
27 #include "AL/al.h"
28 #include "AL/alc.h"
29 #include "alSource.h"
30 #include "alBuffer.h"
31 #include "alThunk.h"
32 #include "alListener.h"
33 #include "alAuxEffectSlot.h"
34 #include "alu.h"
35 #include "bs2b.h"
37 #if defined(HAVE_STDINT_H)
38 #include <stdint.h>
39 typedef int64_t ALint64;
40 #elif defined(HAVE___INT64)
41 typedef __int64 ALint64;
42 #elif (SIZEOF_LONG == 8)
43 typedef long ALint64;
44 #elif (SIZEOF_LONG_LONG == 8)
45 typedef long long ALint64;
46 #endif
48 #ifdef HAVE_SQRTF
49 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
50 #else
51 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
52 #endif
54 #ifdef HAVE_ACOSF
55 #define aluAcos(x) ((ALfloat)acosf((float)(x)))
56 #else
57 #define aluAcos(x) ((ALfloat)acos((double)(x)))
58 #endif
60 // fixes for mingw32.
61 #if defined(max) && !defined(__max)
62 #define __max max
63 #endif
64 #if defined(min) && !defined(__min)
65 #define __min min
66 #endif
68 #define BUFFERSIZE 24000
69 #define FRACTIONBITS 14
70 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
71 #define MAX_PITCH 4
73 /* Minimum ramp length in milliseconds. The value below was chosen to
74 * adequately reduce clicks and pops from harsh gain changes. */
75 #define MIN_RAMP_LENGTH 16
77 ALboolean DuplicateStereo = AL_FALSE;
79 /* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
80 * converted to AL_FORMAT_QUAD* when loaded */
81 __inline ALuint aluBytesFromFormat(ALenum format)
83 switch(format)
85 case AL_FORMAT_MONO8:
86 case AL_FORMAT_STEREO8:
87 case AL_FORMAT_QUAD8_LOKI:
88 case AL_FORMAT_QUAD8:
89 case AL_FORMAT_51CHN8:
90 case AL_FORMAT_61CHN8:
91 case AL_FORMAT_71CHN8:
92 return 1;
94 case AL_FORMAT_MONO16:
95 case AL_FORMAT_STEREO16:
96 case AL_FORMAT_QUAD16_LOKI:
97 case AL_FORMAT_QUAD16:
98 case AL_FORMAT_51CHN16:
99 case AL_FORMAT_61CHN16:
100 case AL_FORMAT_71CHN16:
101 return 2;
103 case AL_FORMAT_MONO_FLOAT32:
104 case AL_FORMAT_STEREO_FLOAT32:
105 case AL_FORMAT_QUAD32:
106 case AL_FORMAT_51CHN32:
107 case AL_FORMAT_61CHN32:
108 case AL_FORMAT_71CHN32:
109 return 4;
111 default:
112 return 0;
116 __inline ALuint aluChannelsFromFormat(ALenum format)
118 switch(format)
120 case AL_FORMAT_MONO8:
121 case AL_FORMAT_MONO16:
122 case AL_FORMAT_MONO_FLOAT32:
123 return 1;
125 case AL_FORMAT_STEREO8:
126 case AL_FORMAT_STEREO16:
127 case AL_FORMAT_STEREO_FLOAT32:
128 return 2;
130 case AL_FORMAT_QUAD8_LOKI:
131 case AL_FORMAT_QUAD16_LOKI:
132 case AL_FORMAT_QUAD8:
133 case AL_FORMAT_QUAD16:
134 case AL_FORMAT_QUAD32:
135 return 4;
137 case AL_FORMAT_51CHN8:
138 case AL_FORMAT_51CHN16:
139 case AL_FORMAT_51CHN32:
140 return 6;
142 case AL_FORMAT_61CHN8:
143 case AL_FORMAT_61CHN16:
144 case AL_FORMAT_61CHN32:
145 return 7;
147 case AL_FORMAT_71CHN8:
148 case AL_FORMAT_71CHN16:
149 case AL_FORMAT_71CHN32:
150 return 8;
152 default:
153 return 0;
158 static __inline ALfloat lpFilter(FILTER *iir, ALfloat input)
160 float *hist1_ptr,*hist2_ptr,*coef_ptr;
161 ALfloat output,new_hist,history1,history2;
163 coef_ptr = iir->coef; /* coefficient pointer */
165 hist1_ptr = iir->history; /* first history */
166 hist2_ptr = hist1_ptr + 1; /* next history */
168 /* 1st number of coefficients array is overall input scale factor,
169 * or filter gain */
170 output = input * (*coef_ptr++);
172 history1 = *hist1_ptr; /* history values */
173 history2 = *hist2_ptr;
175 output = output - history1 * (*coef_ptr++);
176 new_hist = output - history2 * (*coef_ptr++); /* poles */
178 output = new_hist + history1 * (*coef_ptr++);
179 output = output + history2 * (*coef_ptr++); /* zeros */
181 *hist2_ptr++ = *hist1_ptr;
182 *hist1_ptr++ = new_hist;
183 hist1_ptr++;
184 hist2_ptr++;
186 return output;
190 static __inline ALshort aluF2S(ALfloat Value)
192 ALint i;
194 i = (ALint)Value;
195 i = __min( 32767, i);
196 i = __max(-32768, i);
197 return ((ALshort)i);
200 static __inline ALvoid aluCrossproduct(ALfloat *inVector1,ALfloat *inVector2,ALfloat *outVector)
202 outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
203 outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
204 outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
207 static __inline ALfloat aluDotproduct(ALfloat *inVector1,ALfloat *inVector2)
209 return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
210 inVector1[2]*inVector2[2];
213 static __inline ALvoid aluNormalize(ALfloat *inVector)
215 ALfloat length, inverse_length;
217 length = aluSqrt(aluDotproduct(inVector, inVector));
218 if(length != 0.0f)
220 inverse_length = 1.0f/length;
221 inVector[0] *= inverse_length;
222 inVector[1] *= inverse_length;
223 inVector[2] *= inverse_length;
227 static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
229 ALfloat result[3];
231 result[0] = vector[0]*matrix[0][0] + vector[1]*matrix[1][0] + vector[2]*matrix[2][0];
232 result[1] = vector[0]*matrix[0][1] + vector[1]*matrix[1][1] + vector[2]*matrix[2][1];
233 result[2] = vector[0]*matrix[0][2] + vector[1]*matrix[1][2] + vector[2]*matrix[2][2];
234 memcpy(vector, result, sizeof(result));
237 static __inline ALfloat aluComputeSample(ALfloat GainHF, ALfloat sample, ALfloat LowSample)
239 return LowSample + ((sample - LowSample) * GainHF);
242 static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
243 ALenum isMono, ALenum OutputFormat,
244 ALfloat *drysend, ALfloat *wetsend,
245 ALfloat *pitch, ALfloat *drygainhf,
246 ALfloat *wetgainhf)
248 ALfloat InnerAngle,OuterAngle,Angle,Distance,DryMix,WetMix=0.0f;
249 ALfloat Direction[3],Position[3],SourceToListener[3];
250 ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff,OuterGainHF;
251 ALfloat ConeVolume,SourceVolume,PanningFB,PanningLR,ListenerGain;
252 ALfloat U[3],V[3],N[3];
253 ALfloat DopplerFactor, DopplerVelocity, flSpeedOfSound, flMaxVelocity;
254 ALfloat Matrix[3][3];
255 ALfloat flAttenuation;
256 ALfloat RoomAttenuation;
257 ALfloat MetersPerUnit;
258 ALfloat RoomRolloff;
259 ALfloat DryGainHF = 1.0f;
260 ALfloat WetGainHF = 1.0f;
262 //Get context properties
263 DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
264 DopplerVelocity = ALContext->DopplerVelocity;
265 flSpeedOfSound = ALContext->flSpeedOfSound;
267 //Get listener properties
268 ListenerGain = ALContext->Listener.Gain;
269 MetersPerUnit = ALContext->Listener.MetersPerUnit;
271 //Get source properties
272 SourceVolume = ALSource->flGain;
273 memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition));
274 memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation));
275 MinVolume = ALSource->flMinGain;
276 MaxVolume = ALSource->flMaxGain;
277 MinDist = ALSource->flRefDistance;
278 MaxDist = ALSource->flMaxDistance;
279 Rolloff = ALSource->flRollOffFactor;
280 InnerAngle = ALSource->flInnerAngle;
281 OuterAngle = ALSource->flOuterAngle;
282 OuterGainHF = ALSource->OuterGainHF;
283 RoomRolloff = ALSource->RoomRolloffFactor;
285 //Only apply 3D calculations for mono buffers
286 if(isMono != AL_FALSE)
288 //1. Translate Listener to origin (convert to head relative)
289 // Note that Direction and SourceToListener are *not* transformed.
290 // SourceToListener is used with the source and listener velocities,
291 // which are untransformed, and Direction is used with SourceToListener
292 // for the sound cone
293 if(ALSource->bHeadRelative==AL_FALSE)
295 // Build transform matrix
296 aluCrossproduct(ALContext->Listener.Forward, ALContext->Listener.Up, U); // Right-vector
297 aluNormalize(U); // Normalized Right-vector
298 memcpy(V, ALContext->Listener.Up, sizeof(V)); // Up-vector
299 aluNormalize(V); // Normalized Up-vector
300 memcpy(N, ALContext->Listener.Forward, sizeof(N)); // At-vector
301 aluNormalize(N); // Normalized At-vector
302 Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0];
303 Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1];
304 Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
306 // Translate source position into listener space
307 Position[0] -= ALContext->Listener.Position[0];
308 Position[1] -= ALContext->Listener.Position[1];
309 Position[2] -= ALContext->Listener.Position[2];
311 SourceToListener[0] = -Position[0];
312 SourceToListener[1] = -Position[1];
313 SourceToListener[2] = -Position[2];
315 // Transform source position and direction into listener space
316 aluMatrixVector(Position, Matrix);
318 else
320 SourceToListener[0] = -Position[0];
321 SourceToListener[1] = -Position[1];
322 SourceToListener[2] = -Position[2];
324 aluNormalize(SourceToListener);
325 aluNormalize(Direction);
327 //2. Calculate distance attenuation
328 Distance = aluSqrt(aluDotproduct(Position, Position));
330 if(ALSource->Send[0].Slot)
332 if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
333 RoomRolloff += ALSource->Send[0].Slot->effect.Reverb.RoomRolloffFactor;
336 flAttenuation = 1.0f;
337 RoomAttenuation = 1.0f;
338 switch (ALContext->DistanceModel)
340 case AL_INVERSE_DISTANCE_CLAMPED:
341 Distance=__max(Distance,MinDist);
342 Distance=__min(Distance,MaxDist);
343 if (MaxDist < MinDist)
344 break;
345 //fall-through
346 case AL_INVERSE_DISTANCE:
347 if (MinDist > 0.0f)
349 if ((MinDist + (Rolloff * (Distance - MinDist))) > 0.0f)
350 flAttenuation = MinDist / (MinDist + (Rolloff * (Distance - MinDist)));
351 if ((MinDist + (RoomRolloff * (Distance - MinDist))) > 0.0f)
352 RoomAttenuation = MinDist / (MinDist + (RoomRolloff * (Distance - MinDist)));
354 break;
356 case AL_LINEAR_DISTANCE_CLAMPED:
357 Distance=__max(Distance,MinDist);
358 Distance=__min(Distance,MaxDist);
359 if (MaxDist < MinDist)
360 break;
361 //fall-through
362 case AL_LINEAR_DISTANCE:
363 Distance=__min(Distance,MaxDist);
364 if (MaxDist != MinDist)
366 flAttenuation = 1.0f - (Rolloff*(Distance-MinDist)/(MaxDist - MinDist));
367 RoomAttenuation = 1.0f - (RoomRolloff*(Distance-MinDist)/(MaxDist - MinDist));
369 break;
371 case AL_EXPONENT_DISTANCE_CLAMPED:
372 Distance=__max(Distance,MinDist);
373 Distance=__min(Distance,MaxDist);
374 if (MaxDist < MinDist)
375 break;
376 //fall-through
377 case AL_EXPONENT_DISTANCE:
378 if ((Distance > 0.0f) && (MinDist > 0.0f))
380 flAttenuation = (ALfloat)pow(Distance/MinDist, -Rolloff);
381 RoomAttenuation = (ALfloat)pow(Distance/MinDist, -RoomRolloff);
383 break;
385 case AL_NONE:
386 flAttenuation = 1.0f;
387 RoomAttenuation = 1.0f;
388 break;
391 // Distance-based air absorption
392 if(ALSource->AirAbsorptionFactor > 0.0f && ALContext->DistanceModel != AL_NONE)
394 ALfloat dist = Distance-MinDist;
395 ALfloat absorb;
397 if(dist < 0.0f) dist = 0.0f;
398 // Absorption calculation is done in dB
399 absorb = (ALSource->AirAbsorptionFactor*AIRABSORBGAINDBHF) *
400 (Distance*MetersPerUnit);
401 // Convert dB to linear gain before applying
402 absorb = pow(0.5, absorb/-6.0);
403 DryGainHF *= absorb;
404 WetGainHF *= absorb;
407 // Source Gain + Attenuation and clamp to Min/Max Gain
408 DryMix = SourceVolume * flAttenuation;
409 DryMix = __min(DryMix,MaxVolume);
410 DryMix = __max(DryMix,MinVolume);
412 WetMix = SourceVolume * RoomAttenuation;
413 WetMix = __min(WetMix,MaxVolume);
414 WetMix = __max(WetMix,MinVolume);
416 //3. Apply directional soundcones
417 Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * 180.0f /
418 3.141592654f;
419 if(Angle >= InnerAngle && Angle <= OuterAngle)
421 ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
422 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f)*scale);
423 DryMix *= ConeVolume;
424 if(ALSource->WetGainAuto)
425 WetMix *= ConeVolume;
426 if(ALSource->DryGainHFAuto)
427 DryGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
428 if(ALSource->WetGainHFAuto)
429 WetGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
431 else if(Angle > OuterAngle)
433 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f));
434 DryMix *= ConeVolume;
435 if(ALSource->WetGainAuto)
436 WetMix *= ConeVolume;
437 if(ALSource->DryGainHFAuto)
438 DryGainHF *= (1.0f+(OuterGainHF-1.0f));
439 if(ALSource->WetGainHFAuto)
440 WetGainHF *= (1.0f+(OuterGainHF-1.0f));
443 //4. Calculate Velocity
444 if(DopplerFactor != 0.0f)
446 ALfloat flVSS, flVLS = 0.0f;
448 if(ALSource->bHeadRelative==AL_FALSE)
449 flVLS = aluDotproduct(ALContext->Listener.Velocity, SourceToListener);
450 flVSS = aluDotproduct(ALSource->vVelocity, SourceToListener);
452 flMaxVelocity = (DopplerVelocity * flSpeedOfSound) / DopplerFactor;
454 if (flVSS >= flMaxVelocity)
455 flVSS = (flMaxVelocity - 1.0f);
456 else if (flVSS <= -flMaxVelocity)
457 flVSS = -flMaxVelocity + 1.0f;
459 if (flVLS >= flMaxVelocity)
460 flVLS = (flMaxVelocity - 1.0f);
461 else if (flVLS <= -flMaxVelocity)
462 flVLS = -flMaxVelocity + 1.0f;
464 pitch[0] = ALSource->flPitch *
465 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVLS)) /
466 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVSS));
468 else
469 pitch[0] = ALSource->flPitch;
471 if(ALSource->Send[0].Slot)
473 // If the slot's auxilliary send auto is off, the data sent to the
474 // effect slot is the same as the dry path, sans filter effects
475 if(!ALSource->Send[0].Slot->AuxSendAuto)
477 WetMix = DryMix;
478 WetGainHF = DryGainHF;
481 // Note that these are really applied by the effect slot. However,
482 // it's easier to handle them here (particularly the lowpass
483 // filter). Applying the gain to the individual sources going to
484 // the effect slot should have the same effect as applying the gain
485 // to the accumulated sources in the effect slot.
486 // vol1*g + vol2*g + ... voln*g = (vol1+vol2+...voln)*g
487 WetMix *= ALSource->Send[0].Slot->Gain;
488 if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
490 WetMix *= ALSource->Send[0].Slot->effect.Reverb.Gain;
491 WetGainHF *= ALSource->Send[0].Slot->effect.Reverb.GainHF;
492 WetGainHF *= pow(ALSource->Send[0].Slot->effect.Reverb.AirAbsorptionGainHF,
493 Distance * MetersPerUnit);
496 else
498 WetMix = 0.0f;
499 WetGainHF = 1.0f;
502 //5. Apply filter gains and filters
503 switch(ALSource->DirectFilter.type)
505 case AL_FILTER_LOWPASS:
506 DryMix *= ALSource->DirectFilter.Gain;
507 DryGainHF *= ALSource->DirectFilter.GainHF;
508 break;
511 switch(ALSource->Send[0].WetFilter.type)
513 case AL_FILTER_LOWPASS:
514 WetMix *= ALSource->Send[0].WetFilter.Gain;
515 WetGainHF *= ALSource->Send[0].WetFilter.GainHF;
516 break;
519 DryMix *= ListenerGain;
520 WetMix *= ListenerGain;
522 //6. Convert normalized position into pannings, then into channel volumes
523 aluNormalize(Position);
524 switch(aluChannelsFromFormat(OutputFormat))
526 case 1:
527 case 2:
528 PanningLR = 0.5f + 0.5f*Position[0];
529 drysend[FRONT_LEFT] = DryMix * aluSqrt(1.0f-PanningLR); //L Direct
530 drysend[FRONT_RIGHT] = DryMix * aluSqrt( PanningLR); //R Direct
531 drysend[BACK_LEFT] = drysend[FRONT_LEFT];
532 drysend[BACK_RIGHT] = drysend[FRONT_RIGHT];
533 drysend[SIDE_LEFT] = drysend[FRONT_LEFT];
534 drysend[SIDE_RIGHT] = drysend[FRONT_RIGHT];
535 wetsend[FRONT_LEFT] = WetMix * aluSqrt(1.0f-PanningLR); //L Room
536 wetsend[FRONT_RIGHT] = WetMix * aluSqrt( PanningLR); //R Room
537 wetsend[BACK_LEFT] = wetsend[FRONT_LEFT];
538 wetsend[BACK_RIGHT] = wetsend[FRONT_RIGHT];
539 wetsend[SIDE_LEFT] = wetsend[FRONT_LEFT];
540 wetsend[SIDE_RIGHT] = wetsend[FRONT_RIGHT];
541 break;
542 case 4:
543 /* TODO: Add center/lfe channel in spatial calculations? */
544 case 6:
545 // Apply a scalar so each individual speaker has more weight
546 PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f);
547 PanningLR = __min(1.0f, PanningLR);
548 PanningLR = __max(0.0f, PanningLR);
549 PanningFB = 0.5f + (0.5f*Position[2]*1.41421356f);
550 PanningFB = __min(1.0f, PanningFB);
551 PanningFB = __max(0.0f, PanningFB);
552 drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
553 drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
554 drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
555 drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
556 drysend[SIDE_LEFT] = (drysend[FRONT_LEFT] +drysend[BACK_LEFT]) * 0.5f;
557 drysend[SIDE_RIGHT] = (drysend[FRONT_RIGHT]+drysend[BACK_RIGHT]) * 0.5f;
558 wetsend[FRONT_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
559 wetsend[FRONT_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
560 wetsend[BACK_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
561 wetsend[BACK_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
562 wetsend[SIDE_LEFT] = (wetsend[FRONT_LEFT] +wetsend[BACK_LEFT]) * 0.5f;
563 wetsend[SIDE_RIGHT] = (wetsend[FRONT_RIGHT]+wetsend[BACK_RIGHT]) * 0.5f;
564 break;
565 case 7:
566 case 8:
567 PanningFB = 1.0f - fabs(Position[2]*1.15470054f);
568 PanningFB = __min(1.0f, PanningFB);
569 PanningFB = __max(0.0f, PanningFB);
570 PanningLR = 0.5f + (0.5*Position[0]*((1.0f-PanningFB)*2.0f));
571 PanningLR = __min(1.0f, PanningLR);
572 PanningLR = __max(0.0f, PanningLR);
573 if(Position[2] > 0.0f)
575 drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
576 drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
577 drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
578 drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
579 drysend[FRONT_LEFT] = 0.0f;
580 drysend[FRONT_RIGHT] = 0.0f;
581 wetsend[BACK_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
582 wetsend[BACK_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
583 wetsend[SIDE_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
584 wetsend[SIDE_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
585 wetsend[FRONT_LEFT] = 0.0f;
586 wetsend[FRONT_RIGHT] = 0.0f;
588 else
590 drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
591 drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
592 drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
593 drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
594 drysend[BACK_LEFT] = 0.0f;
595 drysend[BACK_RIGHT] = 0.0f;
596 wetsend[FRONT_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
597 wetsend[FRONT_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
598 wetsend[SIDE_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
599 wetsend[SIDE_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
600 wetsend[BACK_LEFT] = 0.0f;
601 wetsend[BACK_RIGHT] = 0.0f;
603 default:
604 break;
607 *drygainhf = DryGainHF;
608 *wetgainhf = WetGainHF;
610 else
612 //1. Multi-channel buffers always play "normal"
613 pitch[0] = ALSource->flPitch;
615 drysend[FRONT_LEFT] = SourceVolume * ListenerGain;
616 drysend[FRONT_RIGHT] = SourceVolume * ListenerGain;
617 drysend[SIDE_LEFT] = SourceVolume * ListenerGain;
618 drysend[SIDE_RIGHT] = SourceVolume * ListenerGain;
619 drysend[BACK_LEFT] = SourceVolume * ListenerGain;
620 drysend[BACK_RIGHT] = SourceVolume * ListenerGain;
621 drysend[CENTER] = SourceVolume * ListenerGain;
622 drysend[LFE] = SourceVolume * ListenerGain;
623 wetsend[FRONT_LEFT] = 0.0f;
624 wetsend[FRONT_RIGHT] = 0.0f;
625 wetsend[SIDE_LEFT] = 0.0f;
626 wetsend[SIDE_RIGHT] = 0.0f;
627 wetsend[BACK_LEFT] = 0.0f;
628 wetsend[BACK_RIGHT] = 0.0f;
629 wetsend[CENTER] = 0.0f;
630 wetsend[LFE] = 0.0f;
631 WetGainHF = 1.0f;
633 *drygainhf = DryGainHF;
634 *wetgainhf = WetGainHF;
638 ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
640 static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
641 static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS];
642 ALfloat newDrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
643 ALfloat newWetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
644 ALfloat DryGainHF = 0.0f;
645 ALfloat WetGainHF = 0.0f;
646 ALfloat *DrySend;
647 ALfloat *WetSend;
648 ALuint rampLength;
649 ALfloat dryGainStep[OUTPUTCHANNELS];
650 ALfloat wetGainStep[OUTPUTCHANNELS];
651 ALfloat dryGainHFStep;
652 ALfloat wetGainHFStep;
653 ALuint BlockAlign,BufferSize;
654 ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
655 ALuint Channels,Frequency,ulExtraSamples;
656 ALfloat Pitch;
657 ALint Looping,State;
658 ALint fraction,increment;
659 ALuint Buffer;
660 ALuint SamplesToDo;
661 ALsource *ALSource;
662 ALbuffer *ALBuffer;
663 ALeffectslot *ALEffectSlot;
664 ALfloat value;
665 ALshort *Data;
666 ALuint i,j,k;
667 ALbufferlistitem *BufferListItem;
668 ALuint loop;
669 ALint64 DataSize64,DataPos64;
670 FILTER *Filter;
671 int fpuState;
673 SuspendContext(ALContext);
675 #if defined(HAVE_FESETROUND)
676 fpuState = fegetround();
677 fesetround(FE_TOWARDZERO);
678 #elif defined(HAVE__CONTROLFP)
679 fpuState = _controlfp(0, 0);
680 _controlfp(_RC_CHOP, _MCW_RC);
681 #else
682 (void)fpuState;
683 #endif
685 //Figure output format variables
686 BlockAlign = aluChannelsFromFormat(format);
687 BlockAlign *= aluBytesFromFormat(format);
689 size /= BlockAlign;
690 while(size > 0)
692 //Setup variables
693 SamplesToDo = min(size, BUFFERSIZE);
694 if(ALContext)
696 ALEffectSlot = ALContext->AuxiliaryEffectSlot;
697 ALSource = ALContext->Source;
698 rampLength = ALContext->Frequency * MIN_RAMP_LENGTH / 1000;
700 else
702 ALEffectSlot = NULL;
703 ALSource = NULL;
704 rampLength = 0;
706 rampLength = max(rampLength, SamplesToDo);
708 //Clear mixing buffer
709 memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
710 memset(WetBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
712 //Actual mixing loop
713 while(ALSource)
715 j = 0;
716 State = ALSource->state;
718 while(State == AL_PLAYING && j < SamplesToDo)
720 DataSize = 0;
721 DataPosInt = 0;
722 DataPosFrac = 0;
724 //Get buffer info
725 if((Buffer = ALSource->ulBufferID))
727 ALBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(Buffer);
729 Data = ALBuffer->data;
730 Channels = aluChannelsFromFormat(ALBuffer->format);
731 DataSize = ALBuffer->size;
732 Frequency = ALBuffer->frequency;
734 CalcSourceParams(ALContext, ALSource,
735 (Channels==1) ? AL_TRUE : AL_FALSE,
736 format, newDrySend, newWetSend, &Pitch,
737 &DryGainHF, &WetGainHF);
739 Pitch = (Pitch*Frequency) / ALContext->Frequency;
740 DataSize /= Channels * aluBytesFromFormat(ALBuffer->format);
742 //Get source info
743 DataPosInt = ALSource->position;
744 DataPosFrac = ALSource->position_fraction;
745 Filter = &ALSource->iirFilter;
746 DrySend = ALSource->DryGains;
747 WetSend = ALSource->WetGains;
749 //Compute the gain steps for each output channel
750 for(i = 0;i < OUTPUTCHANNELS;i++)
752 dryGainStep[i] = (newDrySend[i]-DrySend[i]) / rampLength;
753 wetGainStep[i] = (newWetSend[i]-WetSend[i]) / rampLength;
755 dryGainHFStep = (DryGainHF-ALSource->DryGainHF) / rampLength;
756 wetGainHFStep = (WetGainHF-ALSource->WetGainHF) / rampLength;
757 DryGainHF = ALSource->DryGainHF;
758 WetGainHF = ALSource->WetGainHF;
760 //Compute 18.14 fixed point step
761 increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS));
762 if(increment > (MAX_PITCH<<FRACTIONBITS))
763 increment = (MAX_PITCH<<FRACTIONBITS);
764 else if(increment <= 0)
765 increment = (1<<FRACTIONBITS);
767 //Figure out how many samples we can mix.
768 DataSize64 = DataSize;
769 DataSize64 <<= FRACTIONBITS;
770 DataPos64 = DataPosInt;
771 DataPos64 <<= FRACTIONBITS;
772 DataPos64 += DataPosFrac;
773 BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
775 BufferListItem = ALSource->queue;
776 for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
778 if(BufferListItem)
779 BufferListItem = BufferListItem->next;
781 if (BufferListItem)
783 if (BufferListItem->next)
785 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer);
786 if(NextBuf && NextBuf->data)
788 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
789 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
792 else if (ALSource->bLooping)
794 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer);
795 if (NextBuf && NextBuf->data)
797 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
798 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
801 else
802 memset(&Data[DataSize*Channels], 0, (ALBuffer->padding*Channels*2));
804 BufferSize = min(BufferSize, (SamplesToDo-j));
806 //Actual sample mixing loop
807 Data += DataPosInt*Channels;
808 while(BufferSize--)
810 k = DataPosFrac>>FRACTIONBITS;
811 fraction = DataPosFrac&FRACTIONMASK;
813 for(i = 0;i < OUTPUTCHANNELS;i++)
815 DrySend[i] += dryGainStep[i];
816 WetSend[i] += wetGainStep[i];
818 DryGainHF += dryGainHFStep;
819 WetGainHF += wetGainHFStep;
821 if(Channels==1)
823 ALfloat sample, lowsamp, outsamp;
824 //First order interpolator
825 sample = (Data[k]*((1<<FRACTIONBITS)-fraction) +
826 Data[k+1]*fraction) >> FRACTIONBITS;
827 lowsamp = lpFilter(Filter, sample);
829 //Direct path final mix buffer and panning
830 outsamp = aluComputeSample(DryGainHF, sample, lowsamp);
831 DryBuffer[j][FRONT_LEFT] += outsamp*DrySend[FRONT_LEFT];
832 DryBuffer[j][FRONT_RIGHT] += outsamp*DrySend[FRONT_RIGHT];
833 DryBuffer[j][SIDE_LEFT] += outsamp*DrySend[SIDE_LEFT];
834 DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT];
835 DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT];
836 DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT];
837 //Room path final mix buffer and panning
838 outsamp = aluComputeSample(WetGainHF, sample, lowsamp);
839 WetBuffer[j][FRONT_LEFT] += outsamp*WetSend[FRONT_LEFT];
840 WetBuffer[j][FRONT_RIGHT] += outsamp*WetSend[FRONT_RIGHT];
841 WetBuffer[j][SIDE_LEFT] += outsamp*WetSend[SIDE_LEFT];
842 WetBuffer[j][SIDE_RIGHT] += outsamp*WetSend[SIDE_RIGHT];
843 WetBuffer[j][BACK_LEFT] += outsamp*WetSend[BACK_LEFT];
844 WetBuffer[j][BACK_RIGHT] += outsamp*WetSend[BACK_RIGHT];
846 else
848 ALfloat samp1, samp2;
849 //First order interpolator (front left)
850 samp1 = (Data[k*Channels]*((1<<FRACTIONBITS)-fraction) +
851 Data[(k+1)*Channels]*fraction) >> FRACTIONBITS;
852 DryBuffer[j][FRONT_LEFT] += samp1*DrySend[FRONT_LEFT];
853 WetBuffer[j][FRONT_LEFT] += samp1*WetSend[FRONT_LEFT];
854 //First order interpolator (front right)
855 samp2 = (Data[k*Channels+1]*((1<<FRACTIONBITS)-fraction) +
856 Data[(k+1)*Channels+1]*fraction) >> FRACTIONBITS;
857 DryBuffer[j][FRONT_RIGHT] += samp2*DrySend[FRONT_RIGHT];
858 WetBuffer[j][FRONT_RIGHT] += samp2*WetSend[FRONT_RIGHT];
859 if(Channels >= 4)
861 int i = 2;
862 if(Channels >= 6)
864 if(Channels != 7)
866 //First order interpolator (center)
867 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
868 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
869 DryBuffer[j][CENTER] += value*DrySend[CENTER];
870 WetBuffer[j][CENTER] += value*WetSend[CENTER];
871 i++;
873 //First order interpolator (lfe)
874 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
875 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
876 DryBuffer[j][LFE] += value*DrySend[LFE];
877 WetBuffer[j][LFE] += value*WetSend[LFE];
878 i++;
880 //First order interpolator (back left)
881 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
882 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
883 DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT];
884 WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT];
885 i++;
886 //First order interpolator (back right)
887 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
888 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
889 DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT];
890 WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT];
891 i++;
892 if(Channels >= 7)
894 //First order interpolator (side left)
895 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
896 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
897 DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT];
898 WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT];
899 i++;
900 //First order interpolator (side right)
901 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
902 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
903 DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT];
904 WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT];
905 i++;
908 else if(DuplicateStereo)
910 //Duplicate stereo channels on the back speakers
911 DryBuffer[j][BACK_LEFT] += samp1*DrySend[BACK_LEFT];
912 WetBuffer[j][BACK_LEFT] += samp1*WetSend[BACK_LEFT];
913 DryBuffer[j][BACK_RIGHT] += samp2*DrySend[BACK_RIGHT];
914 WetBuffer[j][BACK_RIGHT] += samp2*WetSend[BACK_RIGHT];
917 DataPosFrac += increment;
918 j++;
920 DataPosInt += (DataPosFrac>>FRACTIONBITS);
921 DataPosFrac = (DataPosFrac&FRACTIONMASK);
923 //Update source info
924 ALSource->position = DataPosInt;
925 ALSource->position_fraction = DataPosFrac;
926 ALSource->DryGainHF = DryGainHF;
927 ALSource->WetGainHF = WetGainHF;
930 //Handle looping sources
931 if(!Buffer || DataPosInt >= DataSize)
933 //queueing
934 if(ALSource->queue)
936 Looping = ALSource->bLooping;
937 if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
939 BufferListItem = ALSource->queue;
940 for(loop = 0; loop <= ALSource->BuffersPlayed; loop++)
942 if(BufferListItem)
944 if(!Looping)
945 BufferListItem->bufferstate = PROCESSED;
946 BufferListItem = BufferListItem->next;
949 if(BufferListItem)
950 ALSource->ulBufferID = BufferListItem->buffer;
951 ALSource->position = DataPosInt-DataSize;
952 ALSource->position_fraction = DataPosFrac;
953 ALSource->BuffersPlayed++;
955 else
957 if(!Looping)
959 /* alSourceStop */
960 ALSource->state = AL_STOPPED;
961 ALSource->inuse = AL_FALSE;
962 ALSource->BuffersPlayed = ALSource->BuffersInQueue;
963 BufferListItem = ALSource->queue;
964 while(BufferListItem != NULL)
966 BufferListItem->bufferstate = PROCESSED;
967 BufferListItem = BufferListItem->next;
970 else
972 /* alSourceRewind */
973 /* alSourcePlay */
974 ALSource->state = AL_PLAYING;
975 ALSource->inuse = AL_TRUE;
976 ALSource->play = AL_TRUE;
977 ALSource->BuffersPlayed = 0;
978 ALSource->BufferPosition = 0;
979 ALSource->lBytesPlayed = 0;
980 BufferListItem = ALSource->queue;
981 while(BufferListItem != NULL)
983 BufferListItem->bufferstate = PENDING;
984 BufferListItem = BufferListItem->next;
986 ALSource->ulBufferID = ALSource->queue->buffer;
988 ALSource->position = DataPosInt-DataSize;
989 ALSource->position_fraction = DataPosFrac;
995 //Get source state
996 State = ALSource->state;
999 ALSource = ALSource->next;
1002 // effect slot processing
1003 while(ALEffectSlot)
1005 if(ALEffectSlot->effect.type == AL_EFFECT_REVERB)
1007 ALfloat *DelayBuffer = ALEffectSlot->ReverbBuffer;
1008 ALuint Pos = ALEffectSlot->ReverbPos;
1009 ALuint LatePos = ALEffectSlot->ReverbLatePos;
1010 ALuint ReflectPos = ALEffectSlot->ReverbReflectPos;
1011 ALuint Length = ALEffectSlot->ReverbLength;
1012 ALfloat DecayGain = ALEffectSlot->ReverbDecayGain;
1013 ALfloat DecayHFRatio = ALEffectSlot->effect.Reverb.DecayHFRatio;
1014 ALfloat ReflectGain = ALEffectSlot->effect.Reverb.ReflectionsGain;
1015 ALfloat LateReverbGain = ALEffectSlot->effect.Reverb.LateReverbGain;
1016 ALfloat sample, lowsample;
1018 Filter = &ALEffectSlot->iirFilter;
1019 for(i = 0;i < SamplesToDo;i++)
1021 sample = WetBuffer[i][FRONT_LEFT] +WetBuffer[i][SIDE_LEFT] +WetBuffer[i][BACK_LEFT];
1022 sample += WetBuffer[i][FRONT_RIGHT]+WetBuffer[i][SIDE_RIGHT]+WetBuffer[i][BACK_RIGHT];
1023 DelayBuffer[Pos] = sample / 6.0f;
1025 sample = DelayBuffer[ReflectPos] * ReflectGain;
1027 DelayBuffer[LatePos] *= LateReverbGain;
1029 Pos = (Pos+1) % Length;
1030 lowsample = lpFilter(Filter, DelayBuffer[Pos]);
1031 lowsample += (DelayBuffer[Pos]-lowsample) * DecayHFRatio;
1033 DelayBuffer[LatePos] += lowsample * DecayGain;
1035 sample += DelayBuffer[LatePos];
1037 WetBuffer[i][FRONT_LEFT] = sample;
1038 WetBuffer[i][FRONT_RIGHT] = sample;
1039 WetBuffer[i][SIDE_LEFT] = sample;
1040 WetBuffer[i][SIDE_RIGHT] = sample;
1041 WetBuffer[i][BACK_LEFT] = sample;
1042 WetBuffer[i][BACK_RIGHT] = sample;
1044 LatePos = (LatePos+1) % Length;
1045 ReflectPos = (ReflectPos+1) % Length;
1048 ALEffectSlot->ReverbPos = Pos;
1049 ALEffectSlot->ReverbLatePos = LatePos;
1050 ALEffectSlot->ReverbReflectPos = ReflectPos;
1053 ALEffectSlot = ALEffectSlot->next;
1056 //Post processing loop
1057 switch(format)
1059 case AL_FORMAT_MONO8:
1060 for(i = 0;i < SamplesToDo;i++)
1062 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
1063 WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1064 buffer = ((ALubyte*)buffer) + 1;
1066 break;
1067 case AL_FORMAT_STEREO8:
1068 if(ALContext && ALContext->bs2b)
1070 for(i = 0;i < SamplesToDo;i++)
1072 float samples[2];
1073 samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
1074 samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
1075 bs2b_cross_feed(ALContext->bs2b, samples);
1076 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(samples[0])>>8)+128);
1077 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(samples[1])>>8)+128);
1078 buffer = ((ALubyte*)buffer) + 2;
1081 else
1083 for(i = 0;i < SamplesToDo;i++)
1085 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1086 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1087 buffer = ((ALubyte*)buffer) + 2;
1090 break;
1091 case AL_FORMAT_QUAD8:
1092 for(i = 0;i < SamplesToDo;i++)
1094 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1095 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1096 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1097 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1098 buffer = ((ALubyte*)buffer) + 4;
1100 break;
1101 case AL_FORMAT_51CHN8:
1102 for(i = 0;i < SamplesToDo;i++)
1104 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1105 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1106 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1107 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1108 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1109 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1110 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1111 #else
1112 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1113 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1114 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1115 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1116 #endif
1117 buffer = ((ALubyte*)buffer) + 6;
1119 break;
1120 case AL_FORMAT_61CHN8:
1121 for(i = 0;i < SamplesToDo;i++)
1123 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1124 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1125 #ifdef _WIN32
1126 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1127 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1128 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1129 #else
1130 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1131 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1132 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1133 #endif
1134 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128);
1135 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128);
1136 buffer = ((ALubyte*)buffer) + 7;
1138 break;
1139 case AL_FORMAT_71CHN8:
1140 for(i = 0;i < SamplesToDo;i++)
1142 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1143 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1144 #ifdef _WIN32
1145 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1146 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1147 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1148 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1149 #else
1150 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1151 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1152 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1153 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1154 #endif
1155 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128);
1156 ((ALubyte*)buffer)[7] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128);
1157 buffer = ((ALubyte*)buffer) + 8;
1159 break;
1161 case AL_FORMAT_MONO16:
1162 for(i = 0;i < SamplesToDo;i++)
1164 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
1165 WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT]);
1166 buffer = ((ALshort*)buffer) + 1;
1168 break;
1169 case AL_FORMAT_STEREO16:
1170 if(ALContext && ALContext->bs2b)
1172 for(i = 0;i < SamplesToDo;i++)
1174 float samples[2];
1175 samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
1176 samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
1177 bs2b_cross_feed(ALContext->bs2b, samples);
1178 ((ALshort*)buffer)[0] = aluF2S(samples[0]);
1179 ((ALshort*)buffer)[1] = aluF2S(samples[1]);
1180 buffer = ((ALshort*)buffer) + 2;
1183 else
1185 for(i = 0;i < SamplesToDo;i++)
1187 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1188 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1189 buffer = ((ALshort*)buffer) + 2;
1192 break;
1193 case AL_FORMAT_QUAD16:
1194 for(i = 0;i < SamplesToDo;i++)
1196 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1197 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1198 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1199 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1200 buffer = ((ALshort*)buffer) + 4;
1202 break;
1203 case AL_FORMAT_51CHN16:
1204 for(i = 0;i < SamplesToDo;i++)
1206 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1207 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1208 #ifdef _WIN32
1209 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1210 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1211 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1212 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1213 #else
1214 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1215 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1216 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1217 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1218 #endif
1219 buffer = ((ALshort*)buffer) + 6;
1221 break;
1222 case AL_FORMAT_61CHN16:
1223 for(i = 0;i < SamplesToDo;i++)
1225 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1226 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1227 #ifdef _WIN32
1228 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1229 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1230 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1231 #else
1232 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1233 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1234 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1235 #endif
1236 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]);
1237 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]);
1238 buffer = ((ALshort*)buffer) + 7;
1240 break;
1241 case AL_FORMAT_71CHN16:
1242 for(i = 0;i < SamplesToDo;i++)
1244 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1245 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1246 #ifdef _WIN32
1247 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1248 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1249 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1250 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1251 #else
1252 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1253 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1254 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1255 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1256 #endif
1257 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]);
1258 ((ALshort*)buffer)[7] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]);
1259 buffer = ((ALshort*)buffer) + 8;
1261 break;
1263 default:
1264 break;
1267 size -= SamplesToDo;
1270 #if defined(HAVE_FESETROUND)
1271 fesetround(fpuState);
1272 #elif defined(HAVE__CONTROLFP)
1273 _controlfp(fpuState, 0xfffff);
1274 #endif
1276 ProcessContext(ALContext);