Overwrite the input wet sample with the output
[openal-soft.git] / Alc / ALu.c
blob1aaa18324c2ea39ea2270245cf1eebca3ad13a30
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 unsigned int i;
161 float *hist1_ptr,*hist2_ptr,*coef_ptr;
162 ALfloat output,new_hist,history1,history2;
164 coef_ptr = iir->coef; /* coefficient pointer */
166 hist1_ptr = iir->history; /* first history */
167 hist2_ptr = hist1_ptr + 1; /* next history */
169 /* 1st number of coefficients array is overall input scale factor,
170 * or filter gain */
171 output = input * (*coef_ptr++);
173 for(i = 0;i < FILTER_SECTIONS;i++)
175 history1 = *hist1_ptr; /* history values */
176 history2 = *hist2_ptr;
178 output = output - history1 * (*coef_ptr++);
179 new_hist = output - history2 * (*coef_ptr++); /* poles */
181 output = new_hist + history1 * (*coef_ptr++);
182 output = output + history2 * (*coef_ptr++); /* zeros */
184 *hist2_ptr++ = *hist1_ptr;
185 *hist1_ptr++ = new_hist;
186 hist1_ptr++;
187 hist2_ptr++;
190 return output;
194 static __inline ALshort aluF2S(ALfloat Value)
196 ALint i;
198 i = (ALint)Value;
199 i = __min( 32767, i);
200 i = __max(-32768, i);
201 return ((ALshort)i);
204 static __inline ALvoid aluCrossproduct(ALfloat *inVector1,ALfloat *inVector2,ALfloat *outVector)
206 outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
207 outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
208 outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
211 static __inline ALfloat aluDotproduct(ALfloat *inVector1,ALfloat *inVector2)
213 return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
214 inVector1[2]*inVector2[2];
217 static __inline ALvoid aluNormalize(ALfloat *inVector)
219 ALfloat length, inverse_length;
221 length = aluSqrt(aluDotproduct(inVector, inVector));
222 if(length != 0.0f)
224 inverse_length = 1.0f/length;
225 inVector[0] *= inverse_length;
226 inVector[1] *= inverse_length;
227 inVector[2] *= inverse_length;
231 static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
233 ALfloat result[3];
235 result[0] = vector[0]*matrix[0][0] + vector[1]*matrix[1][0] + vector[2]*matrix[2][0];
236 result[1] = vector[0]*matrix[0][1] + vector[1]*matrix[1][1] + vector[2]*matrix[2][1];
237 result[2] = vector[0]*matrix[0][2] + vector[1]*matrix[1][2] + vector[2]*matrix[2][2];
238 memcpy(vector, result, sizeof(result));
241 static __inline ALfloat aluComputeSample(ALfloat GainHF, ALfloat sample, ALfloat LowSample)
243 return LowSample + ((sample - LowSample) * GainHF);
246 static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
247 ALenum isMono, ALenum OutputFormat,
248 ALfloat *drysend, ALfloat *wetsend,
249 ALfloat *pitch, ALfloat *drygainhf,
250 ALfloat *wetgainhf)
252 ALfloat InnerAngle,OuterAngle,Angle,Distance,DryMix,WetMix=0.0f;
253 ALfloat Direction[3],Position[3],SourceToListener[3];
254 ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff,OuterGainHF;
255 ALfloat ConeVolume,SourceVolume,PanningFB,PanningLR,ListenerGain;
256 ALfloat U[3],V[3],N[3];
257 ALfloat DopplerFactor, DopplerVelocity, flSpeedOfSound, flMaxVelocity;
258 ALfloat Matrix[3][3];
259 ALfloat flAttenuation;
260 ALfloat RoomAttenuation;
261 ALfloat MetersPerUnit;
262 ALfloat RoomRolloff;
263 ALfloat DryGainHF = 1.0f;
264 ALfloat WetGainHF = 1.0f;
266 //Get context properties
267 DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
268 DopplerVelocity = ALContext->DopplerVelocity;
269 flSpeedOfSound = ALContext->flSpeedOfSound;
271 //Get listener properties
272 ListenerGain = ALContext->Listener.Gain;
273 MetersPerUnit = ALContext->Listener.MetersPerUnit;
275 //Get source properties
276 SourceVolume = ALSource->flGain;
277 memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition));
278 memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation));
279 MinVolume = ALSource->flMinGain;
280 MaxVolume = ALSource->flMaxGain;
281 MinDist = ALSource->flRefDistance;
282 MaxDist = ALSource->flMaxDistance;
283 Rolloff = ALSource->flRollOffFactor;
284 InnerAngle = ALSource->flInnerAngle;
285 OuterAngle = ALSource->flOuterAngle;
286 OuterGainHF = ALSource->OuterGainHF;
287 RoomRolloff = ALSource->RoomRolloffFactor;
289 //Only apply 3D calculations for mono buffers
290 if(isMono != AL_FALSE)
292 //1. Translate Listener to origin (convert to head relative)
293 // Note that Direction and SourceToListener are *not* transformed.
294 // SourceToListener is used with the source and listener velocities,
295 // which are untransformed, and Direction is used with SourceToListener
296 // for the sound cone
297 if(ALSource->bHeadRelative==AL_FALSE)
299 // Build transform matrix
300 aluCrossproduct(ALContext->Listener.Forward, ALContext->Listener.Up, U); // Right-vector
301 aluNormalize(U); // Normalized Right-vector
302 memcpy(V, ALContext->Listener.Up, sizeof(V)); // Up-vector
303 aluNormalize(V); // Normalized Up-vector
304 memcpy(N, ALContext->Listener.Forward, sizeof(N)); // At-vector
305 aluNormalize(N); // Normalized At-vector
306 Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0];
307 Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1];
308 Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
310 // Translate source position into listener space
311 Position[0] -= ALContext->Listener.Position[0];
312 Position[1] -= ALContext->Listener.Position[1];
313 Position[2] -= ALContext->Listener.Position[2];
315 SourceToListener[0] = -Position[0];
316 SourceToListener[1] = -Position[1];
317 SourceToListener[2] = -Position[2];
319 // Transform source position and direction into listener space
320 aluMatrixVector(Position, Matrix);
322 else
324 SourceToListener[0] = -Position[0];
325 SourceToListener[1] = -Position[1];
326 SourceToListener[2] = -Position[2];
328 aluNormalize(SourceToListener);
329 aluNormalize(Direction);
331 //2. Calculate distance attenuation
332 Distance = aluSqrt(aluDotproduct(Position, Position));
334 if(ALSource->Send[0].Slot && !ALSource->Send[0].Slot->AuxSendAuto)
336 if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
337 RoomRolloff += ALSource->Send[0].Slot->effect.Reverb.RoomRolloffFactor;
340 flAttenuation = 1.0f;
341 RoomAttenuation = 1.0f;
342 switch (ALContext->DistanceModel)
344 case AL_INVERSE_DISTANCE_CLAMPED:
345 Distance=__max(Distance,MinDist);
346 Distance=__min(Distance,MaxDist);
347 if (MaxDist < MinDist)
348 break;
349 //fall-through
350 case AL_INVERSE_DISTANCE:
351 if (MinDist > 0.0f)
353 if ((MinDist + (Rolloff * (Distance - MinDist))) > 0.0f)
354 flAttenuation = MinDist / (MinDist + (Rolloff * (Distance - MinDist)));
355 if ((MinDist + (RoomRolloff * (Distance - MinDist))) > 0.0f)
356 RoomAttenuation = MinDist / (MinDist + (RoomRolloff * (Distance - MinDist)));
358 break;
360 case AL_LINEAR_DISTANCE_CLAMPED:
361 Distance=__max(Distance,MinDist);
362 Distance=__min(Distance,MaxDist);
363 if (MaxDist < MinDist)
364 break;
365 //fall-through
366 case AL_LINEAR_DISTANCE:
367 Distance=__min(Distance,MaxDist);
368 if (MaxDist != MinDist)
370 flAttenuation = 1.0f - (Rolloff*(Distance-MinDist)/(MaxDist - MinDist));
371 RoomAttenuation = 1.0f - (RoomRolloff*(Distance-MinDist)/(MaxDist - MinDist));
373 break;
375 case AL_EXPONENT_DISTANCE_CLAMPED:
376 Distance=__max(Distance,MinDist);
377 Distance=__min(Distance,MaxDist);
378 if (MaxDist < MinDist)
379 break;
380 //fall-through
381 case AL_EXPONENT_DISTANCE:
382 if ((Distance > 0.0f) && (MinDist > 0.0f))
384 flAttenuation = (ALfloat)pow(Distance/MinDist, -Rolloff);
385 RoomAttenuation = (ALfloat)pow(Distance/MinDist, -RoomRolloff);
387 break;
389 case AL_NONE:
390 default:
391 flAttenuation = 1.0f;
392 RoomAttenuation = 1.0f;
393 break;
396 // Source Gain + Attenuation and clamp to Min/Max Gain
397 DryMix = SourceVolume * flAttenuation;
398 DryMix = __min(DryMix,MaxVolume);
399 DryMix = __max(DryMix,MinVolume);
401 WetMix = SourceVolume * (ALSource->WetGainAuto ?
402 RoomAttenuation : 1.0f);
403 WetMix = __min(WetMix,MaxVolume);
404 WetMix = __max(WetMix,MinVolume);
406 //3. Apply directional soundcones
407 Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * 180.0f /
408 3.141592654f;
409 if(Angle >= InnerAngle && Angle <= OuterAngle)
411 ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
412 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f)*scale);
413 if(ALSource->WetGainAuto)
414 WetMix *= ConeVolume;
415 if(ALSource->DryGainHFAuto)
416 DryGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
417 if(ALSource->WetGainHFAuto)
418 WetGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
420 else if(Angle > OuterAngle)
422 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f));
423 if(ALSource->WetGainAuto)
424 WetMix *= ConeVolume;
425 if(ALSource->DryGainHFAuto)
426 DryGainHF *= (1.0f+(OuterGainHF-1.0f));
427 if(ALSource->WetGainHFAuto)
428 WetGainHF *= (1.0f+(OuterGainHF-1.0f));
430 else
431 ConeVolume = 1.0f;
433 //4. Calculate Velocity
434 if(DopplerFactor != 0.0f)
436 ALfloat flVSS, flVLS = 0.0f;
438 if(ALSource->bHeadRelative==AL_FALSE)
439 flVLS = aluDotproduct(ALContext->Listener.Velocity, SourceToListener);
440 flVSS = aluDotproduct(ALSource->vVelocity, SourceToListener);
442 flMaxVelocity = (DopplerVelocity * flSpeedOfSound) / DopplerFactor;
444 if (flVSS >= flMaxVelocity)
445 flVSS = (flMaxVelocity - 1.0f);
446 else if (flVSS <= -flMaxVelocity)
447 flVSS = -flMaxVelocity + 1.0f;
449 if (flVLS >= flMaxVelocity)
450 flVLS = (flMaxVelocity - 1.0f);
451 else if (flVLS <= -flMaxVelocity)
452 flVLS = -flMaxVelocity + 1.0f;
454 pitch[0] = ALSource->flPitch *
455 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVLS)) /
456 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVSS));
458 else
459 pitch[0] = ALSource->flPitch;
461 //5. Apply filter gains and filters
462 switch(ALSource->DirectFilter.type)
464 case AL_FILTER_LOWPASS:
465 DryMix *= ALSource->DirectFilter.Gain;
466 DryGainHF *= ALSource->DirectFilter.GainHF;
467 break;
470 switch(ALSource->Send[0].WetFilter.type)
472 case AL_FILTER_LOWPASS:
473 WetMix *= ALSource->Send[0].WetFilter.Gain;
474 WetGainHF *= ALSource->Send[0].WetFilter.GainHF;
475 break;
478 if(ALSource->AirAbsorptionFactor > 0.0f)
479 DryGainHF *= pow(ALSource->AirAbsorptionFactor * AIRABSORBGAINHF,
480 Distance * MetersPerUnit);
482 if(ALSource->Send[0].Slot)
484 WetMix *= ALSource->Send[0].Slot->Gain;
486 if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
488 WetMix *= ALSource->Send[0].Slot->effect.Reverb.Gain;
489 WetGainHF *= ALSource->Send[0].Slot->effect.Reverb.GainHF;
490 WetGainHF *= pow(ALSource->Send[0].Slot->effect.Reverb.AirAbsorptionGainHF,
491 Distance * MetersPerUnit);
494 else
496 WetMix = 0.0f;
497 WetGainHF = 1.0f;
500 DryMix *= ListenerGain * ConeVolume;
501 WetMix *= ListenerGain;
503 //6. Convert normalized position into pannings, then into channel volumes
504 aluNormalize(Position);
505 switch(aluChannelsFromFormat(OutputFormat))
507 case 1:
508 case 2:
509 PanningLR = 0.5f + 0.5f*Position[0];
510 drysend[FRONT_LEFT] = DryMix * aluSqrt(1.0f-PanningLR); //L Direct
511 drysend[FRONT_RIGHT] = DryMix * aluSqrt( PanningLR); //R Direct
512 drysend[BACK_LEFT] = drysend[FRONT_LEFT];
513 drysend[BACK_RIGHT] = drysend[FRONT_RIGHT];
514 drysend[SIDE_LEFT] = drysend[FRONT_LEFT];
515 drysend[SIDE_RIGHT] = drysend[FRONT_RIGHT];
516 wetsend[FRONT_LEFT] = WetMix * aluSqrt(1.0f-PanningLR); //L Room
517 wetsend[FRONT_RIGHT] = WetMix * aluSqrt( PanningLR); //R Room
518 wetsend[BACK_LEFT] = wetsend[FRONT_LEFT];
519 wetsend[BACK_RIGHT] = wetsend[FRONT_RIGHT];
520 wetsend[SIDE_LEFT] = wetsend[FRONT_LEFT];
521 wetsend[SIDE_RIGHT] = wetsend[FRONT_RIGHT];
522 break;
523 case 4:
524 /* TODO: Add center/lfe channel in spatial calculations? */
525 case 6:
526 // Apply a scalar so each individual speaker has more weight
527 PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f);
528 PanningLR = __min(1.0f, PanningLR);
529 PanningLR = __max(0.0f, PanningLR);
530 PanningFB = 0.5f + (0.5f*Position[2]*1.41421356f);
531 PanningFB = __min(1.0f, PanningFB);
532 PanningFB = __max(0.0f, PanningFB);
533 drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
534 drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
535 drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
536 drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
537 drysend[SIDE_LEFT] = (drysend[FRONT_LEFT] +drysend[BACK_LEFT]) * 0.5f;
538 drysend[SIDE_RIGHT] = (drysend[FRONT_RIGHT]+drysend[BACK_RIGHT]) * 0.5f;
539 wetsend[FRONT_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
540 wetsend[FRONT_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
541 wetsend[BACK_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
542 wetsend[BACK_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
543 wetsend[SIDE_LEFT] = (wetsend[FRONT_LEFT] +wetsend[BACK_LEFT]) * 0.5f;
544 wetsend[SIDE_RIGHT] = (wetsend[FRONT_RIGHT]+wetsend[BACK_RIGHT]) * 0.5f;
545 break;
546 case 7:
547 case 8:
548 PanningFB = 1.0f - fabs(Position[2]*1.15470054f);
549 PanningFB = __min(1.0f, PanningFB);
550 PanningFB = __max(0.0f, PanningFB);
551 PanningLR = 0.5f + (0.5*Position[0]*((1.0f-PanningFB)*2.0f));
552 PanningLR = __min(1.0f, PanningLR);
553 PanningLR = __max(0.0f, PanningLR);
554 if(Position[2] > 0.0f)
556 drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
557 drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
558 drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
559 drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
560 drysend[FRONT_LEFT] = 0.0f;
561 drysend[FRONT_RIGHT] = 0.0f;
562 wetsend[BACK_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
563 wetsend[BACK_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
564 wetsend[SIDE_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
565 wetsend[SIDE_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
566 wetsend[FRONT_LEFT] = 0.0f;
567 wetsend[FRONT_RIGHT] = 0.0f;
569 else
571 drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
572 drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
573 drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
574 drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
575 drysend[BACK_LEFT] = 0.0f;
576 drysend[BACK_RIGHT] = 0.0f;
577 wetsend[FRONT_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
578 wetsend[FRONT_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
579 wetsend[SIDE_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
580 wetsend[SIDE_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
581 wetsend[BACK_LEFT] = 0.0f;
582 wetsend[BACK_RIGHT] = 0.0f;
584 default:
585 break;
588 *drygainhf = DryGainHF;
589 *wetgainhf = WetGainHF;
591 else
593 //1. Multi-channel buffers always play "normal"
594 pitch[0] = ALSource->flPitch;
596 drysend[FRONT_LEFT] = SourceVolume * ListenerGain;
597 drysend[FRONT_RIGHT] = SourceVolume * ListenerGain;
598 drysend[SIDE_LEFT] = SourceVolume * ListenerGain;
599 drysend[SIDE_RIGHT] = SourceVolume * ListenerGain;
600 drysend[BACK_LEFT] = SourceVolume * ListenerGain;
601 drysend[BACK_RIGHT] = SourceVolume * ListenerGain;
602 drysend[CENTER] = SourceVolume * ListenerGain;
603 drysend[LFE] = SourceVolume * ListenerGain;
604 wetsend[FRONT_LEFT] = 0.0f;
605 wetsend[FRONT_RIGHT] = 0.0f;
606 wetsend[SIDE_LEFT] = 0.0f;
607 wetsend[SIDE_RIGHT] = 0.0f;
608 wetsend[BACK_LEFT] = 0.0f;
609 wetsend[BACK_RIGHT] = 0.0f;
610 wetsend[CENTER] = 0.0f;
611 wetsend[LFE] = 0.0f;
612 WetGainHF = 1.0f;
614 *drygainhf = DryGainHF;
615 *wetgainhf = WetGainHF;
619 ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
621 static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
622 static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS];
623 ALfloat newDrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
624 ALfloat newWetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
625 ALfloat DryGainHF = 0.0f;
626 ALfloat WetGainHF = 0.0f;
627 ALfloat *DrySend;
628 ALfloat *WetSend;
629 ALuint rampLength;
630 ALfloat dryGainStep[OUTPUTCHANNELS];
631 ALfloat wetGainStep[OUTPUTCHANNELS];
632 ALfloat dryGainHFStep;
633 ALfloat wetGainHFStep;
634 ALuint BlockAlign,BufferSize;
635 ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
636 ALuint Channels,Frequency,ulExtraSamples;
637 ALfloat Pitch;
638 ALint Looping,State;
639 ALint fraction,increment;
640 ALuint Buffer;
641 ALuint SamplesToDo;
642 ALsource *ALSource;
643 ALbuffer *ALBuffer;
644 ALeffectslot *ALEffectSlot;
645 ALfloat value;
646 ALshort *Data;
647 ALuint i,j,k;
648 ALbufferlistitem *BufferListItem;
649 ALuint loop;
650 ALint64 DataSize64,DataPos64;
651 FILTER *Filter;
652 int fpuState;
654 SuspendContext(ALContext);
656 #if defined(HAVE_FESETROUND)
657 fpuState = fegetround();
658 fesetround(FE_TOWARDZERO);
659 #elif defined(HAVE__CONTROLFP)
660 fpuState = _controlfp(0, 0);
661 _controlfp(_RC_CHOP, _MCW_RC);
662 #else
663 (void)fpuState;
664 #endif
666 //Figure output format variables
667 BlockAlign = aluChannelsFromFormat(format);
668 BlockAlign *= aluBytesFromFormat(format);
670 size /= BlockAlign;
671 while(size > 0)
673 //Setup variables
674 SamplesToDo = min(size, BUFFERSIZE);
675 if(ALContext)
677 ALEffectSlot = ALContext->AuxiliaryEffectSlot;
678 ALSource = ALContext->Source;
679 rampLength = ALContext->Frequency * MIN_RAMP_LENGTH / 1000;
681 else
683 ALEffectSlot = NULL;
684 ALSource = NULL;
685 rampLength = 0;
687 rampLength = max(rampLength, SamplesToDo);
689 //Clear mixing buffer
690 memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
691 memset(WetBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
693 //Actual mixing loop
694 while(ALSource)
696 j = 0;
697 State = ALSource->state;
699 while(State == AL_PLAYING && j < SamplesToDo)
701 DataSize = 0;
702 DataPosInt = 0;
703 DataPosFrac = 0;
705 //Get buffer info
706 if((Buffer = ALSource->ulBufferID))
708 ALBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(Buffer);
710 Data = ALBuffer->data;
711 Channels = aluChannelsFromFormat(ALBuffer->format);
712 DataSize = ALBuffer->size;
713 Frequency = ALBuffer->frequency;
715 CalcSourceParams(ALContext, ALSource,
716 (Channels==1) ? AL_TRUE : AL_FALSE,
717 format, newDrySend, newWetSend, &Pitch,
718 &DryGainHF, &WetGainHF);
720 Pitch = (Pitch*Frequency) / ALContext->Frequency;
721 DataSize /= Channels * aluBytesFromFormat(ALBuffer->format);
723 //Get source info
724 DataPosInt = ALSource->position;
725 DataPosFrac = ALSource->position_fraction;
726 Filter = &ALSource->iirFilter;
727 DrySend = ALSource->DryGains;
728 WetSend = ALSource->WetGains;
730 //Compute the gain steps for each output channel
731 for(i = 0;i < OUTPUTCHANNELS;i++)
733 dryGainStep[i] = (newDrySend[i]-DrySend[i]) / rampLength;
734 wetGainStep[i] = (newWetSend[i]-WetSend[i]) / rampLength;
736 dryGainHFStep = (DryGainHF-ALSource->DryGainHF) / rampLength;
737 wetGainHFStep = (WetGainHF-ALSource->WetGainHF) / rampLength;
738 DryGainHF = ALSource->DryGainHF;
739 WetGainHF = ALSource->WetGainHF;
741 //Compute 18.14 fixed point step
742 increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS));
743 if(increment > (MAX_PITCH<<FRACTIONBITS))
744 increment = (MAX_PITCH<<FRACTIONBITS);
745 else if(increment <= 0)
746 increment = (1<<FRACTIONBITS);
748 //Figure out how many samples we can mix.
749 DataSize64 = DataSize;
750 DataSize64 <<= FRACTIONBITS;
751 DataPos64 = DataPosInt;
752 DataPos64 <<= FRACTIONBITS;
753 DataPos64 += DataPosFrac;
754 BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
756 BufferListItem = ALSource->queue;
757 for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
759 if(BufferListItem)
760 BufferListItem = BufferListItem->next;
762 if (BufferListItem)
764 if (BufferListItem->next)
766 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer);
767 if(NextBuf && NextBuf->data)
769 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
770 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
773 else if (ALSource->bLooping)
775 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer);
776 if (NextBuf && NextBuf->data)
778 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
779 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
783 BufferSize = min(BufferSize, (SamplesToDo-j));
785 //Actual sample mixing loop
786 Data += DataPosInt*Channels;
787 while(BufferSize--)
789 k = DataPosFrac>>FRACTIONBITS;
790 fraction = DataPosFrac&FRACTIONMASK;
792 for(i = 0;i < OUTPUTCHANNELS;i++)
794 DrySend[i] += dryGainStep[i];
795 WetSend[i] += wetGainStep[i];
797 DryGainHF += dryGainHFStep;
798 WetGainHF += wetGainHFStep;
800 if(Channels==1)
802 ALfloat sample, lowsamp, outsamp;
803 //First order interpolator
804 sample = (Data[k]*((1<<FRACTIONBITS)-fraction) +
805 Data[k+1]*fraction) >> FRACTIONBITS;
806 lowsamp = lpFilter(Filter, sample);
808 //Direct path final mix buffer and panning
809 outsamp = aluComputeSample(DryGainHF, sample, lowsamp);
810 DryBuffer[j][FRONT_LEFT] += outsamp*DrySend[FRONT_LEFT];
811 DryBuffer[j][FRONT_RIGHT] += outsamp*DrySend[FRONT_RIGHT];
812 DryBuffer[j][SIDE_LEFT] += outsamp*DrySend[SIDE_LEFT];
813 DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT];
814 DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT];
815 DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT];
816 //Room path final mix buffer and panning
817 outsamp = aluComputeSample(WetGainHF, sample, lowsamp);
818 WetBuffer[j][FRONT_LEFT] += outsamp*WetSend[FRONT_LEFT];
819 WetBuffer[j][FRONT_RIGHT] += outsamp*WetSend[FRONT_RIGHT];
820 WetBuffer[j][SIDE_LEFT] += outsamp*WetSend[SIDE_LEFT];
821 WetBuffer[j][SIDE_RIGHT] += outsamp*WetSend[SIDE_RIGHT];
822 WetBuffer[j][BACK_LEFT] += outsamp*WetSend[BACK_LEFT];
823 WetBuffer[j][BACK_RIGHT] += outsamp*WetSend[BACK_RIGHT];
825 else
827 ALfloat samp1, samp2;
828 //First order interpolator (front left)
829 samp1 = (Data[k*Channels]*((1<<FRACTIONBITS)-fraction) +
830 Data[(k+1)*Channels]*fraction) >> FRACTIONBITS;
831 DryBuffer[j][FRONT_LEFT] += samp1*DrySend[FRONT_LEFT];
832 WetBuffer[j][FRONT_LEFT] += samp1*WetSend[FRONT_LEFT];
833 //First order interpolator (front right)
834 samp2 = (Data[k*Channels+1]*((1<<FRACTIONBITS)-fraction) +
835 Data[(k+1)*Channels+1]*fraction) >> FRACTIONBITS;
836 DryBuffer[j][FRONT_RIGHT] += samp2*DrySend[FRONT_RIGHT];
837 WetBuffer[j][FRONT_RIGHT] += samp2*WetSend[FRONT_RIGHT];
838 if(Channels >= 4)
840 int i = 2;
841 if(Channels >= 6)
843 if(Channels != 7)
845 //First order interpolator (center)
846 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
847 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
848 DryBuffer[j][CENTER] += value*DrySend[CENTER];
849 WetBuffer[j][CENTER] += value*WetSend[CENTER];
850 i++;
852 //First order interpolator (lfe)
853 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
854 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
855 DryBuffer[j][LFE] += value*DrySend[LFE];
856 WetBuffer[j][LFE] += value*WetSend[LFE];
857 i++;
859 //First order interpolator (back left)
860 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
861 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
862 DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT];
863 WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT];
864 i++;
865 //First order interpolator (back right)
866 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
867 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
868 DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT];
869 WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT];
870 i++;
871 if(Channels >= 7)
873 //First order interpolator (side left)
874 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
875 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
876 DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT];
877 WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT];
878 i++;
879 //First order interpolator (side right)
880 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
881 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
882 DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT];
883 WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT];
884 i++;
887 else if(DuplicateStereo)
889 //Duplicate stereo channels on the back speakers
890 DryBuffer[j][BACK_LEFT] += samp1*DrySend[BACK_LEFT];
891 WetBuffer[j][BACK_LEFT] += samp1*WetSend[BACK_LEFT];
892 DryBuffer[j][BACK_RIGHT] += samp2*DrySend[BACK_RIGHT];
893 WetBuffer[j][BACK_RIGHT] += samp2*WetSend[BACK_RIGHT];
896 DataPosFrac += increment;
897 j++;
899 DataPosInt += (DataPosFrac>>FRACTIONBITS);
900 DataPosFrac = (DataPosFrac&FRACTIONMASK);
902 //Update source info
903 ALSource->position = DataPosInt;
904 ALSource->position_fraction = DataPosFrac;
905 ALSource->DryGainHF = DryGainHF;
906 ALSource->WetGainHF = WetGainHF;
909 //Handle looping sources
910 if(!Buffer || DataPosInt >= DataSize)
912 //queueing
913 if(ALSource->queue)
915 Looping = ALSource->bLooping;
916 if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
918 BufferListItem = ALSource->queue;
919 for(loop = 0; loop <= ALSource->BuffersPlayed; loop++)
921 if(BufferListItem)
923 if(!Looping)
924 BufferListItem->bufferstate = PROCESSED;
925 BufferListItem = BufferListItem->next;
928 if(!Looping)
929 ALSource->BuffersProcessed++;
930 if(BufferListItem)
931 ALSource->ulBufferID = BufferListItem->buffer;
932 ALSource->position = DataPosInt-DataSize;
933 ALSource->position_fraction = DataPosFrac;
934 ALSource->BuffersPlayed++;
936 else
938 if(!Looping)
940 /* alSourceStop */
941 ALSource->state = AL_STOPPED;
942 ALSource->inuse = AL_FALSE;
943 ALSource->BuffersPlayed = ALSource->BuffersProcessed = ALSource->BuffersInQueue;
944 BufferListItem = ALSource->queue;
945 while(BufferListItem != NULL)
947 BufferListItem->bufferstate = PROCESSED;
948 BufferListItem = BufferListItem->next;
951 else
953 /* alSourceRewind */
954 /* alSourcePlay */
955 ALSource->state = AL_PLAYING;
956 ALSource->inuse = AL_TRUE;
957 ALSource->play = AL_TRUE;
958 ALSource->BuffersPlayed = 0;
959 ALSource->BufferPosition = 0;
960 ALSource->lBytesPlayed = 0;
961 ALSource->BuffersProcessed = 0;
962 BufferListItem = ALSource->queue;
963 while(BufferListItem != NULL)
965 BufferListItem->bufferstate = PENDING;
966 BufferListItem = BufferListItem->next;
968 ALSource->ulBufferID = ALSource->queue->buffer;
970 ALSource->position = DataPosInt-DataSize;
971 ALSource->position_fraction = DataPosFrac;
977 //Get source state
978 State = ALSource->state;
981 ALSource = ALSource->next;
984 // effect slot processing
985 while(ALEffectSlot)
987 if(ALEffectSlot->effect.type == AL_EFFECT_REVERB)
989 ALfloat *DelayBuffer = ALEffectSlot->ReverbBuffer;
990 ALuint Pos = ALEffectSlot->ReverbPos;
991 ALuint LatePos = ALEffectSlot->ReverbLatePos;
992 ALuint ReflectPos = ALEffectSlot->ReverbReflectPos;
993 ALuint Length = ALEffectSlot->ReverbLength;
994 ALfloat DecayGain = ALEffectSlot->ReverbDecayGain;
995 ALfloat DecayHFRatio = ALEffectSlot->effect.Reverb.DecayHFRatio;
996 ALfloat ReflectGain = ALEffectSlot->effect.Reverb.ReflectionsGain;
997 ALfloat LateReverbGain = ALEffectSlot->effect.Reverb.LateReverbGain;
998 ALfloat sample, lowsample;
1000 Filter = &ALEffectSlot->iirFilter;
1001 for(i = 0;i < SamplesToDo;i++)
1003 sample = WetBuffer[i][FRONT_LEFT] +WetBuffer[i][SIDE_LEFT] +WetBuffer[i][BACK_LEFT];
1004 sample += WetBuffer[i][FRONT_RIGHT]+WetBuffer[i][SIDE_RIGHT]+WetBuffer[i][BACK_RIGHT];
1005 DelayBuffer[Pos] = sample / 6.0f;
1007 sample = DelayBuffer[ReflectPos] * ReflectGain;
1009 DelayBuffer[LatePos] *= LateReverbGain;
1011 Pos = (Pos+1) % Length;
1012 lowsample = lpFilter(Filter, DelayBuffer[Pos]);
1013 lowsample += (DelayBuffer[Pos]-lowsample) * DecayHFRatio;
1015 DelayBuffer[LatePos] += lowsample * DecayGain;
1017 sample += DelayBuffer[LatePos];
1019 WetBuffer[i][FRONT_LEFT] = sample;
1020 WetBuffer[i][FRONT_RIGHT] = sample;
1021 WetBuffer[i][SIDE_LEFT] = sample;
1022 WetBuffer[i][SIDE_RIGHT] = sample;
1023 WetBuffer[i][BACK_LEFT] = sample;
1024 WetBuffer[i][BACK_RIGHT] = sample;
1026 LatePos = (LatePos+1) % Length;
1027 ReflectPos = (ReflectPos+1) % Length;
1030 ALEffectSlot->ReverbPos = Pos;
1031 ALEffectSlot->ReverbLatePos = LatePos;
1032 ALEffectSlot->ReverbReflectPos = ReflectPos;
1035 ALEffectSlot = ALEffectSlot->next;
1038 //Post processing loop
1039 switch(format)
1041 case AL_FORMAT_MONO8:
1042 for(i = 0;i < SamplesToDo;i++)
1044 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
1045 WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1046 buffer = ((ALubyte*)buffer) + 1;
1048 break;
1049 case AL_FORMAT_STEREO8:
1050 if(ALContext && ALContext->bs2b)
1052 for(i = 0;i < SamplesToDo;i++)
1054 float samples[2];
1055 samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
1056 samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
1057 bs2b_cross_feed(ALContext->bs2b, samples);
1058 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(samples[0])>>8)+128);
1059 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(samples[1])>>8)+128);
1060 buffer = ((ALubyte*)buffer) + 2;
1063 else
1065 for(i = 0;i < SamplesToDo;i++)
1067 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1068 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1069 buffer = ((ALubyte*)buffer) + 2;
1072 break;
1073 case AL_FORMAT_QUAD8:
1074 for(i = 0;i < SamplesToDo;i++)
1076 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1077 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1078 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1079 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1080 buffer = ((ALubyte*)buffer) + 4;
1082 break;
1083 case AL_FORMAT_51CHN8:
1084 for(i = 0;i < SamplesToDo;i++)
1086 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1087 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1088 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1089 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1090 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1091 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1092 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1093 #else
1094 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1095 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1096 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1097 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1098 #endif
1099 buffer = ((ALubyte*)buffer) + 6;
1101 break;
1102 case AL_FORMAT_61CHN8:
1103 for(i = 0;i < SamplesToDo;i++)
1105 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1106 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1107 #ifdef _WIN32
1108 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1109 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1110 ((ALubyte*)buffer)[4] = (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][LFE] +WetBuffer[i][LFE])>>8)+128);
1115 #endif
1116 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128);
1117 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128);
1118 buffer = ((ALubyte*)buffer) + 7;
1120 break;
1121 case AL_FORMAT_71CHN8:
1122 for(i = 0;i < SamplesToDo;i++)
1124 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1125 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1126 #ifdef _WIN32
1127 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1128 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1129 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1130 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1131 #else
1132 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1133 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1134 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1135 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1136 #endif
1137 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128);
1138 ((ALubyte*)buffer)[7] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128);
1139 buffer = ((ALubyte*)buffer) + 8;
1141 break;
1143 case AL_FORMAT_MONO16:
1144 for(i = 0;i < SamplesToDo;i++)
1146 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
1147 WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT]);
1148 buffer = ((ALshort*)buffer) + 1;
1150 break;
1151 case AL_FORMAT_STEREO16:
1152 if(ALContext && ALContext->bs2b)
1154 for(i = 0;i < SamplesToDo;i++)
1156 float samples[2];
1157 samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
1158 samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
1159 bs2b_cross_feed(ALContext->bs2b, samples);
1160 ((ALshort*)buffer)[0] = aluF2S(samples[0]);
1161 ((ALshort*)buffer)[1] = aluF2S(samples[1]);
1162 buffer = ((ALshort*)buffer) + 2;
1165 else
1167 for(i = 0;i < SamplesToDo;i++)
1169 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1170 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1171 buffer = ((ALshort*)buffer) + 2;
1174 break;
1175 case AL_FORMAT_QUAD16:
1176 for(i = 0;i < SamplesToDo;i++)
1178 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1179 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1180 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1181 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1182 buffer = ((ALshort*)buffer) + 4;
1184 break;
1185 case AL_FORMAT_51CHN16:
1186 for(i = 0;i < SamplesToDo;i++)
1188 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1189 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1190 #ifdef _WIN32
1191 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1192 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1193 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1194 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1195 #else
1196 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1197 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1198 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1199 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1200 #endif
1201 buffer = ((ALshort*)buffer) + 6;
1203 break;
1204 case AL_FORMAT_61CHN16:
1205 for(i = 0;i < SamplesToDo;i++)
1207 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1208 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1209 #ifdef _WIN32
1210 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1211 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1212 ((ALshort*)buffer)[4] = 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][LFE] +WetBuffer[i][LFE]);
1217 #endif
1218 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]);
1219 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]);
1220 buffer = ((ALshort*)buffer) + 7;
1222 break;
1223 case AL_FORMAT_71CHN16:
1224 for(i = 0;i < SamplesToDo;i++)
1226 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1227 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1228 #ifdef _WIN32
1229 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1230 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1231 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1232 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1233 #else
1234 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1235 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1236 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1237 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1238 #endif
1239 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]);
1240 ((ALshort*)buffer)[7] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]);
1241 buffer = ((ALshort*)buffer) + 8;
1243 break;
1245 default:
1246 break;
1249 size -= SamplesToDo;
1252 #if defined(HAVE_FESETROUND)
1253 fesetround(fpuState);
1254 #elif defined(HAVE__CONTROLFP)
1255 _controlfp(fpuState, 0xfffff);
1256 #endif
1258 ProcessContext(ALContext);