Use a 12dB/oct rolloff instead of 24 for the lowpass filter
[openal-soft.git] / Alc / ALu.c
blob37d308510fcf117b810524cbb380be04e90acbf3
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 && !ALSource->Send[0].Slot->AuxSendAuto)
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 default:
387 flAttenuation = 1.0f;
388 RoomAttenuation = 1.0f;
389 break;
392 // Source Gain + Attenuation and clamp to Min/Max Gain
393 DryMix = SourceVolume * flAttenuation;
394 DryMix = __min(DryMix,MaxVolume);
395 DryMix = __max(DryMix,MinVolume);
397 WetMix = SourceVolume * (ALSource->WetGainAuto ?
398 RoomAttenuation : 1.0f);
399 WetMix = __min(WetMix,MaxVolume);
400 WetMix = __max(WetMix,MinVolume);
402 //3. Apply directional soundcones
403 Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * 180.0f /
404 3.141592654f;
405 if(Angle >= InnerAngle && Angle <= OuterAngle)
407 ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
408 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f)*scale);
409 if(ALSource->WetGainAuto)
410 WetMix *= ConeVolume;
411 if(ALSource->DryGainHFAuto)
412 DryGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
413 if(ALSource->WetGainHFAuto)
414 WetGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
416 else if(Angle > OuterAngle)
418 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f));
419 if(ALSource->WetGainAuto)
420 WetMix *= ConeVolume;
421 if(ALSource->DryGainHFAuto)
422 DryGainHF *= (1.0f+(OuterGainHF-1.0f));
423 if(ALSource->WetGainHFAuto)
424 WetGainHF *= (1.0f+(OuterGainHF-1.0f));
426 else
427 ConeVolume = 1.0f;
429 //4. Calculate Velocity
430 if(DopplerFactor != 0.0f)
432 ALfloat flVSS, flVLS = 0.0f;
434 if(ALSource->bHeadRelative==AL_FALSE)
435 flVLS = aluDotproduct(ALContext->Listener.Velocity, SourceToListener);
436 flVSS = aluDotproduct(ALSource->vVelocity, SourceToListener);
438 flMaxVelocity = (DopplerVelocity * flSpeedOfSound) / DopplerFactor;
440 if (flVSS >= flMaxVelocity)
441 flVSS = (flMaxVelocity - 1.0f);
442 else if (flVSS <= -flMaxVelocity)
443 flVSS = -flMaxVelocity + 1.0f;
445 if (flVLS >= flMaxVelocity)
446 flVLS = (flMaxVelocity - 1.0f);
447 else if (flVLS <= -flMaxVelocity)
448 flVLS = -flMaxVelocity + 1.0f;
450 pitch[0] = ALSource->flPitch *
451 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVLS)) /
452 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVSS));
454 else
455 pitch[0] = ALSource->flPitch;
457 //5. Apply filter gains and filters
458 switch(ALSource->DirectFilter.type)
460 case AL_FILTER_LOWPASS:
461 DryMix *= ALSource->DirectFilter.Gain;
462 DryGainHF *= ALSource->DirectFilter.GainHF;
463 break;
466 switch(ALSource->Send[0].WetFilter.type)
468 case AL_FILTER_LOWPASS:
469 WetMix *= ALSource->Send[0].WetFilter.Gain;
470 WetGainHF *= ALSource->Send[0].WetFilter.GainHF;
471 break;
474 if(ALSource->AirAbsorptionFactor > 0.0f)
475 DryGainHF *= pow(ALSource->AirAbsorptionFactor * AIRABSORBGAINHF,
476 Distance * MetersPerUnit);
478 if(ALSource->Send[0].Slot)
480 WetMix *= ALSource->Send[0].Slot->Gain;
482 if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
484 WetMix *= ALSource->Send[0].Slot->effect.Reverb.Gain;
485 WetGainHF *= ALSource->Send[0].Slot->effect.Reverb.GainHF;
486 WetGainHF *= pow(ALSource->Send[0].Slot->effect.Reverb.AirAbsorptionGainHF,
487 Distance * MetersPerUnit);
490 else
492 WetMix = 0.0f;
493 WetGainHF = 1.0f;
496 DryMix *= ListenerGain * ConeVolume;
497 WetMix *= ListenerGain;
499 //6. Convert normalized position into pannings, then into channel volumes
500 aluNormalize(Position);
501 switch(aluChannelsFromFormat(OutputFormat))
503 case 1:
504 case 2:
505 PanningLR = 0.5f + 0.5f*Position[0];
506 drysend[FRONT_LEFT] = DryMix * aluSqrt(1.0f-PanningLR); //L Direct
507 drysend[FRONT_RIGHT] = DryMix * aluSqrt( PanningLR); //R Direct
508 drysend[BACK_LEFT] = drysend[FRONT_LEFT];
509 drysend[BACK_RIGHT] = drysend[FRONT_RIGHT];
510 drysend[SIDE_LEFT] = drysend[FRONT_LEFT];
511 drysend[SIDE_RIGHT] = drysend[FRONT_RIGHT];
512 wetsend[FRONT_LEFT] = WetMix * aluSqrt(1.0f-PanningLR); //L Room
513 wetsend[FRONT_RIGHT] = WetMix * aluSqrt( PanningLR); //R Room
514 wetsend[BACK_LEFT] = wetsend[FRONT_LEFT];
515 wetsend[BACK_RIGHT] = wetsend[FRONT_RIGHT];
516 wetsend[SIDE_LEFT] = wetsend[FRONT_LEFT];
517 wetsend[SIDE_RIGHT] = wetsend[FRONT_RIGHT];
518 break;
519 case 4:
520 /* TODO: Add center/lfe channel in spatial calculations? */
521 case 6:
522 // Apply a scalar so each individual speaker has more weight
523 PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f);
524 PanningLR = __min(1.0f, PanningLR);
525 PanningLR = __max(0.0f, PanningLR);
526 PanningFB = 0.5f + (0.5f*Position[2]*1.41421356f);
527 PanningFB = __min(1.0f, PanningFB);
528 PanningFB = __max(0.0f, PanningFB);
529 drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
530 drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
531 drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
532 drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
533 drysend[SIDE_LEFT] = (drysend[FRONT_LEFT] +drysend[BACK_LEFT]) * 0.5f;
534 drysend[SIDE_RIGHT] = (drysend[FRONT_RIGHT]+drysend[BACK_RIGHT]) * 0.5f;
535 wetsend[FRONT_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
536 wetsend[FRONT_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
537 wetsend[BACK_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
538 wetsend[BACK_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
539 wetsend[SIDE_LEFT] = (wetsend[FRONT_LEFT] +wetsend[BACK_LEFT]) * 0.5f;
540 wetsend[SIDE_RIGHT] = (wetsend[FRONT_RIGHT]+wetsend[BACK_RIGHT]) * 0.5f;
541 break;
542 case 7:
543 case 8:
544 PanningFB = 1.0f - fabs(Position[2]*1.15470054f);
545 PanningFB = __min(1.0f, PanningFB);
546 PanningFB = __max(0.0f, PanningFB);
547 PanningLR = 0.5f + (0.5*Position[0]*((1.0f-PanningFB)*2.0f));
548 PanningLR = __min(1.0f, PanningLR);
549 PanningLR = __max(0.0f, PanningLR);
550 if(Position[2] > 0.0f)
552 drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
553 drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
554 drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
555 drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
556 drysend[FRONT_LEFT] = 0.0f;
557 drysend[FRONT_RIGHT] = 0.0f;
558 wetsend[BACK_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
559 wetsend[BACK_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
560 wetsend[SIDE_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
561 wetsend[SIDE_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
562 wetsend[FRONT_LEFT] = 0.0f;
563 wetsend[FRONT_RIGHT] = 0.0f;
565 else
567 drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
568 drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
569 drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
570 drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
571 drysend[BACK_LEFT] = 0.0f;
572 drysend[BACK_RIGHT] = 0.0f;
573 wetsend[FRONT_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
574 wetsend[FRONT_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
575 wetsend[SIDE_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
576 wetsend[SIDE_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
577 wetsend[BACK_LEFT] = 0.0f;
578 wetsend[BACK_RIGHT] = 0.0f;
580 default:
581 break;
584 *drygainhf = DryGainHF;
585 *wetgainhf = WetGainHF;
587 else
589 //1. Multi-channel buffers always play "normal"
590 pitch[0] = ALSource->flPitch;
592 drysend[FRONT_LEFT] = SourceVolume * ListenerGain;
593 drysend[FRONT_RIGHT] = SourceVolume * ListenerGain;
594 drysend[SIDE_LEFT] = SourceVolume * ListenerGain;
595 drysend[SIDE_RIGHT] = SourceVolume * ListenerGain;
596 drysend[BACK_LEFT] = SourceVolume * ListenerGain;
597 drysend[BACK_RIGHT] = SourceVolume * ListenerGain;
598 drysend[CENTER] = SourceVolume * ListenerGain;
599 drysend[LFE] = SourceVolume * ListenerGain;
600 wetsend[FRONT_LEFT] = 0.0f;
601 wetsend[FRONT_RIGHT] = 0.0f;
602 wetsend[SIDE_LEFT] = 0.0f;
603 wetsend[SIDE_RIGHT] = 0.0f;
604 wetsend[BACK_LEFT] = 0.0f;
605 wetsend[BACK_RIGHT] = 0.0f;
606 wetsend[CENTER] = 0.0f;
607 wetsend[LFE] = 0.0f;
608 WetGainHF = 1.0f;
610 *drygainhf = DryGainHF;
611 *wetgainhf = WetGainHF;
615 ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
617 static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
618 static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS];
619 ALfloat newDrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
620 ALfloat newWetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
621 ALfloat DryGainHF = 0.0f;
622 ALfloat WetGainHF = 0.0f;
623 ALfloat *DrySend;
624 ALfloat *WetSend;
625 ALuint rampLength;
626 ALfloat dryGainStep[OUTPUTCHANNELS];
627 ALfloat wetGainStep[OUTPUTCHANNELS];
628 ALfloat dryGainHFStep;
629 ALfloat wetGainHFStep;
630 ALuint BlockAlign,BufferSize;
631 ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
632 ALuint Channels,Frequency,ulExtraSamples;
633 ALfloat Pitch;
634 ALint Looping,State;
635 ALint fraction,increment;
636 ALuint Buffer;
637 ALuint SamplesToDo;
638 ALsource *ALSource;
639 ALbuffer *ALBuffer;
640 ALeffectslot *ALEffectSlot;
641 ALfloat value;
642 ALshort *Data;
643 ALuint i,j,k;
644 ALbufferlistitem *BufferListItem;
645 ALuint loop;
646 ALint64 DataSize64,DataPos64;
647 FILTER *Filter;
648 int fpuState;
650 SuspendContext(ALContext);
652 #if defined(HAVE_FESETROUND)
653 fpuState = fegetround();
654 fesetround(FE_TOWARDZERO);
655 #elif defined(HAVE__CONTROLFP)
656 fpuState = _controlfp(0, 0);
657 _controlfp(_RC_CHOP, _MCW_RC);
658 #else
659 (void)fpuState;
660 #endif
662 //Figure output format variables
663 BlockAlign = aluChannelsFromFormat(format);
664 BlockAlign *= aluBytesFromFormat(format);
666 size /= BlockAlign;
667 while(size > 0)
669 //Setup variables
670 SamplesToDo = min(size, BUFFERSIZE);
671 if(ALContext)
673 ALEffectSlot = ALContext->AuxiliaryEffectSlot;
674 ALSource = ALContext->Source;
675 rampLength = ALContext->Frequency * MIN_RAMP_LENGTH / 1000;
677 else
679 ALEffectSlot = NULL;
680 ALSource = NULL;
681 rampLength = 0;
683 rampLength = max(rampLength, SamplesToDo);
685 //Clear mixing buffer
686 memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
687 memset(WetBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
689 //Actual mixing loop
690 while(ALSource)
692 j = 0;
693 State = ALSource->state;
695 while(State == AL_PLAYING && j < SamplesToDo)
697 DataSize = 0;
698 DataPosInt = 0;
699 DataPosFrac = 0;
701 //Get buffer info
702 if((Buffer = ALSource->ulBufferID))
704 ALBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(Buffer);
706 Data = ALBuffer->data;
707 Channels = aluChannelsFromFormat(ALBuffer->format);
708 DataSize = ALBuffer->size;
709 Frequency = ALBuffer->frequency;
711 CalcSourceParams(ALContext, ALSource,
712 (Channels==1) ? AL_TRUE : AL_FALSE,
713 format, newDrySend, newWetSend, &Pitch,
714 &DryGainHF, &WetGainHF);
716 Pitch = (Pitch*Frequency) / ALContext->Frequency;
717 DataSize /= Channels * aluBytesFromFormat(ALBuffer->format);
719 //Get source info
720 DataPosInt = ALSource->position;
721 DataPosFrac = ALSource->position_fraction;
722 Filter = &ALSource->iirFilter;
723 DrySend = ALSource->DryGains;
724 WetSend = ALSource->WetGains;
726 //Compute the gain steps for each output channel
727 for(i = 0;i < OUTPUTCHANNELS;i++)
729 dryGainStep[i] = (newDrySend[i]-DrySend[i]) / rampLength;
730 wetGainStep[i] = (newWetSend[i]-WetSend[i]) / rampLength;
732 dryGainHFStep = (DryGainHF-ALSource->DryGainHF) / rampLength;
733 wetGainHFStep = (WetGainHF-ALSource->WetGainHF) / rampLength;
734 DryGainHF = ALSource->DryGainHF;
735 WetGainHF = ALSource->WetGainHF;
737 //Compute 18.14 fixed point step
738 increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS));
739 if(increment > (MAX_PITCH<<FRACTIONBITS))
740 increment = (MAX_PITCH<<FRACTIONBITS);
741 else if(increment <= 0)
742 increment = (1<<FRACTIONBITS);
744 //Figure out how many samples we can mix.
745 DataSize64 = DataSize;
746 DataSize64 <<= FRACTIONBITS;
747 DataPos64 = DataPosInt;
748 DataPos64 <<= FRACTIONBITS;
749 DataPos64 += DataPosFrac;
750 BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
752 BufferListItem = ALSource->queue;
753 for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
755 if(BufferListItem)
756 BufferListItem = BufferListItem->next;
758 if (BufferListItem)
760 if (BufferListItem->next)
762 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer);
763 if(NextBuf && NextBuf->data)
765 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
766 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
769 else if (ALSource->bLooping)
771 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer);
772 if (NextBuf && NextBuf->data)
774 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
775 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
778 else
779 memset(&Data[DataSize*Channels], 0, (ALBuffer->padding*Channels*2));
781 BufferSize = min(BufferSize, (SamplesToDo-j));
783 //Actual sample mixing loop
784 Data += DataPosInt*Channels;
785 while(BufferSize--)
787 k = DataPosFrac>>FRACTIONBITS;
788 fraction = DataPosFrac&FRACTIONMASK;
790 for(i = 0;i < OUTPUTCHANNELS;i++)
792 DrySend[i] += dryGainStep[i];
793 WetSend[i] += wetGainStep[i];
795 DryGainHF += dryGainHFStep;
796 WetGainHF += wetGainHFStep;
798 if(Channels==1)
800 ALfloat sample, lowsamp, outsamp;
801 //First order interpolator
802 sample = (Data[k]*((1<<FRACTIONBITS)-fraction) +
803 Data[k+1]*fraction) >> FRACTIONBITS;
804 lowsamp = lpFilter(Filter, sample);
806 //Direct path final mix buffer and panning
807 outsamp = aluComputeSample(DryGainHF, sample, lowsamp);
808 DryBuffer[j][FRONT_LEFT] += outsamp*DrySend[FRONT_LEFT];
809 DryBuffer[j][FRONT_RIGHT] += outsamp*DrySend[FRONT_RIGHT];
810 DryBuffer[j][SIDE_LEFT] += outsamp*DrySend[SIDE_LEFT];
811 DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT];
812 DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT];
813 DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT];
814 //Room path final mix buffer and panning
815 outsamp = aluComputeSample(WetGainHF, sample, lowsamp);
816 WetBuffer[j][FRONT_LEFT] += outsamp*WetSend[FRONT_LEFT];
817 WetBuffer[j][FRONT_RIGHT] += outsamp*WetSend[FRONT_RIGHT];
818 WetBuffer[j][SIDE_LEFT] += outsamp*WetSend[SIDE_LEFT];
819 WetBuffer[j][SIDE_RIGHT] += outsamp*WetSend[SIDE_RIGHT];
820 WetBuffer[j][BACK_LEFT] += outsamp*WetSend[BACK_LEFT];
821 WetBuffer[j][BACK_RIGHT] += outsamp*WetSend[BACK_RIGHT];
823 else
825 ALfloat samp1, samp2;
826 //First order interpolator (front left)
827 samp1 = (Data[k*Channels]*((1<<FRACTIONBITS)-fraction) +
828 Data[(k+1)*Channels]*fraction) >> FRACTIONBITS;
829 DryBuffer[j][FRONT_LEFT] += samp1*DrySend[FRONT_LEFT];
830 WetBuffer[j][FRONT_LEFT] += samp1*WetSend[FRONT_LEFT];
831 //First order interpolator (front right)
832 samp2 = (Data[k*Channels+1]*((1<<FRACTIONBITS)-fraction) +
833 Data[(k+1)*Channels+1]*fraction) >> FRACTIONBITS;
834 DryBuffer[j][FRONT_RIGHT] += samp2*DrySend[FRONT_RIGHT];
835 WetBuffer[j][FRONT_RIGHT] += samp2*WetSend[FRONT_RIGHT];
836 if(Channels >= 4)
838 int i = 2;
839 if(Channels >= 6)
841 if(Channels != 7)
843 //First order interpolator (center)
844 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
845 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
846 DryBuffer[j][CENTER] += value*DrySend[CENTER];
847 WetBuffer[j][CENTER] += value*WetSend[CENTER];
848 i++;
850 //First order interpolator (lfe)
851 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
852 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
853 DryBuffer[j][LFE] += value*DrySend[LFE];
854 WetBuffer[j][LFE] += value*WetSend[LFE];
855 i++;
857 //First order interpolator (back left)
858 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
859 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
860 DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT];
861 WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT];
862 i++;
863 //First order interpolator (back right)
864 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
865 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
866 DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT];
867 WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT];
868 i++;
869 if(Channels >= 7)
871 //First order interpolator (side left)
872 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
873 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
874 DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT];
875 WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT];
876 i++;
877 //First order interpolator (side right)
878 value = (Data[k*Channels+i]*((1<<FRACTIONBITS)-fraction) +
879 Data[(k+1)*Channels+i]*fraction) >> FRACTIONBITS;
880 DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT];
881 WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT];
882 i++;
885 else if(DuplicateStereo)
887 //Duplicate stereo channels on the back speakers
888 DryBuffer[j][BACK_LEFT] += samp1*DrySend[BACK_LEFT];
889 WetBuffer[j][BACK_LEFT] += samp1*WetSend[BACK_LEFT];
890 DryBuffer[j][BACK_RIGHT] += samp2*DrySend[BACK_RIGHT];
891 WetBuffer[j][BACK_RIGHT] += samp2*WetSend[BACK_RIGHT];
894 DataPosFrac += increment;
895 j++;
897 DataPosInt += (DataPosFrac>>FRACTIONBITS);
898 DataPosFrac = (DataPosFrac&FRACTIONMASK);
900 //Update source info
901 ALSource->position = DataPosInt;
902 ALSource->position_fraction = DataPosFrac;
903 ALSource->DryGainHF = DryGainHF;
904 ALSource->WetGainHF = WetGainHF;
907 //Handle looping sources
908 if(!Buffer || DataPosInt >= DataSize)
910 //queueing
911 if(ALSource->queue)
913 Looping = ALSource->bLooping;
914 if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
916 BufferListItem = ALSource->queue;
917 for(loop = 0; loop <= ALSource->BuffersPlayed; loop++)
919 if(BufferListItem)
921 if(!Looping)
922 BufferListItem->bufferstate = PROCESSED;
923 BufferListItem = BufferListItem->next;
926 if(BufferListItem)
927 ALSource->ulBufferID = BufferListItem->buffer;
928 ALSource->position = DataPosInt-DataSize;
929 ALSource->position_fraction = DataPosFrac;
930 ALSource->BuffersPlayed++;
932 else
934 if(!Looping)
936 /* alSourceStop */
937 ALSource->state = AL_STOPPED;
938 ALSource->inuse = AL_FALSE;
939 ALSource->BuffersPlayed = ALSource->BuffersInQueue;
940 BufferListItem = ALSource->queue;
941 while(BufferListItem != NULL)
943 BufferListItem->bufferstate = PROCESSED;
944 BufferListItem = BufferListItem->next;
947 else
949 /* alSourceRewind */
950 /* alSourcePlay */
951 ALSource->state = AL_PLAYING;
952 ALSource->inuse = AL_TRUE;
953 ALSource->play = AL_TRUE;
954 ALSource->BuffersPlayed = 0;
955 ALSource->BufferPosition = 0;
956 ALSource->lBytesPlayed = 0;
957 BufferListItem = ALSource->queue;
958 while(BufferListItem != NULL)
960 BufferListItem->bufferstate = PENDING;
961 BufferListItem = BufferListItem->next;
963 ALSource->ulBufferID = ALSource->queue->buffer;
965 ALSource->position = DataPosInt-DataSize;
966 ALSource->position_fraction = DataPosFrac;
972 //Get source state
973 State = ALSource->state;
976 ALSource = ALSource->next;
979 // effect slot processing
980 while(ALEffectSlot)
982 if(ALEffectSlot->effect.type == AL_EFFECT_REVERB)
984 ALfloat *DelayBuffer = ALEffectSlot->ReverbBuffer;
985 ALuint Pos = ALEffectSlot->ReverbPos;
986 ALuint LatePos = ALEffectSlot->ReverbLatePos;
987 ALuint ReflectPos = ALEffectSlot->ReverbReflectPos;
988 ALuint Length = ALEffectSlot->ReverbLength;
989 ALfloat DecayGain = ALEffectSlot->ReverbDecayGain;
990 ALfloat DecayHFRatio = ALEffectSlot->effect.Reverb.DecayHFRatio;
991 ALfloat ReflectGain = ALEffectSlot->effect.Reverb.ReflectionsGain;
992 ALfloat LateReverbGain = ALEffectSlot->effect.Reverb.LateReverbGain;
993 ALfloat sample, lowsample;
995 Filter = &ALEffectSlot->iirFilter;
996 for(i = 0;i < SamplesToDo;i++)
998 sample = WetBuffer[i][FRONT_LEFT] +WetBuffer[i][SIDE_LEFT] +WetBuffer[i][BACK_LEFT];
999 sample += WetBuffer[i][FRONT_RIGHT]+WetBuffer[i][SIDE_RIGHT]+WetBuffer[i][BACK_RIGHT];
1000 DelayBuffer[Pos] = sample / 6.0f;
1002 sample = DelayBuffer[ReflectPos] * ReflectGain;
1004 DelayBuffer[LatePos] *= LateReverbGain;
1006 Pos = (Pos+1) % Length;
1007 lowsample = lpFilter(Filter, DelayBuffer[Pos]);
1008 lowsample += (DelayBuffer[Pos]-lowsample) * DecayHFRatio;
1010 DelayBuffer[LatePos] += lowsample * DecayGain;
1012 sample += DelayBuffer[LatePos];
1014 WetBuffer[i][FRONT_LEFT] = sample;
1015 WetBuffer[i][FRONT_RIGHT] = sample;
1016 WetBuffer[i][SIDE_LEFT] = sample;
1017 WetBuffer[i][SIDE_RIGHT] = sample;
1018 WetBuffer[i][BACK_LEFT] = sample;
1019 WetBuffer[i][BACK_RIGHT] = sample;
1021 LatePos = (LatePos+1) % Length;
1022 ReflectPos = (ReflectPos+1) % Length;
1025 ALEffectSlot->ReverbPos = Pos;
1026 ALEffectSlot->ReverbLatePos = LatePos;
1027 ALEffectSlot->ReverbReflectPos = ReflectPos;
1030 ALEffectSlot = ALEffectSlot->next;
1033 //Post processing loop
1034 switch(format)
1036 case AL_FORMAT_MONO8:
1037 for(i = 0;i < SamplesToDo;i++)
1039 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
1040 WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1041 buffer = ((ALubyte*)buffer) + 1;
1043 break;
1044 case AL_FORMAT_STEREO8:
1045 if(ALContext && ALContext->bs2b)
1047 for(i = 0;i < SamplesToDo;i++)
1049 float samples[2];
1050 samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
1051 samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
1052 bs2b_cross_feed(ALContext->bs2b, samples);
1053 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(samples[0])>>8)+128);
1054 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(samples[1])>>8)+128);
1055 buffer = ((ALubyte*)buffer) + 2;
1058 else
1060 for(i = 0;i < SamplesToDo;i++)
1062 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1063 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1064 buffer = ((ALubyte*)buffer) + 2;
1067 break;
1068 case AL_FORMAT_QUAD8:
1069 for(i = 0;i < SamplesToDo;i++)
1071 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1072 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1073 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1074 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1075 buffer = ((ALubyte*)buffer) + 4;
1077 break;
1078 case AL_FORMAT_51CHN8:
1079 for(i = 0;i < SamplesToDo;i++)
1081 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1082 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1083 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1084 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1085 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1086 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1087 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1088 #else
1089 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1090 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1091 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1092 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1093 #endif
1094 buffer = ((ALubyte*)buffer) + 6;
1096 break;
1097 case AL_FORMAT_61CHN8:
1098 for(i = 0;i < SamplesToDo;i++)
1100 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1101 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1102 #ifdef _WIN32
1103 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1104 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1105 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1106 #else
1107 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1108 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1109 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1110 #endif
1111 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128);
1112 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128);
1113 buffer = ((ALubyte*)buffer) + 7;
1115 break;
1116 case AL_FORMAT_71CHN8:
1117 for(i = 0;i < SamplesToDo;i++)
1119 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
1120 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
1121 #ifdef _WIN32
1122 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1123 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1124 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1125 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1126 #else
1127 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
1128 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
1129 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
1130 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
1131 #endif
1132 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128);
1133 ((ALubyte*)buffer)[7] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128);
1134 buffer = ((ALubyte*)buffer) + 8;
1136 break;
1138 case AL_FORMAT_MONO16:
1139 for(i = 0;i < SamplesToDo;i++)
1141 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
1142 WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT]);
1143 buffer = ((ALshort*)buffer) + 1;
1145 break;
1146 case AL_FORMAT_STEREO16:
1147 if(ALContext && ALContext->bs2b)
1149 for(i = 0;i < SamplesToDo;i++)
1151 float samples[2];
1152 samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
1153 samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
1154 bs2b_cross_feed(ALContext->bs2b, samples);
1155 ((ALshort*)buffer)[0] = aluF2S(samples[0]);
1156 ((ALshort*)buffer)[1] = aluF2S(samples[1]);
1157 buffer = ((ALshort*)buffer) + 2;
1160 else
1162 for(i = 0;i < SamplesToDo;i++)
1164 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1165 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1166 buffer = ((ALshort*)buffer) + 2;
1169 break;
1170 case AL_FORMAT_QUAD16:
1171 for(i = 0;i < SamplesToDo;i++)
1173 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1174 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1175 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1176 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1177 buffer = ((ALshort*)buffer) + 4;
1179 break;
1180 case AL_FORMAT_51CHN16:
1181 for(i = 0;i < SamplesToDo;i++)
1183 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1184 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1185 #ifdef _WIN32
1186 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1187 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1188 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1189 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1190 #else
1191 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1192 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1193 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1194 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1195 #endif
1196 buffer = ((ALshort*)buffer) + 6;
1198 break;
1199 case AL_FORMAT_61CHN16:
1200 for(i = 0;i < SamplesToDo;i++)
1202 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1203 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1204 #ifdef _WIN32
1205 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1206 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1207 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1208 #else
1209 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1210 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1211 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1212 #endif
1213 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]);
1214 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]);
1215 buffer = ((ALshort*)buffer) + 7;
1217 break;
1218 case AL_FORMAT_71CHN16:
1219 for(i = 0;i < SamplesToDo;i++)
1221 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
1222 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
1223 #ifdef _WIN32
1224 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1225 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1226 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1227 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1228 #else
1229 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
1230 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
1231 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
1232 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
1233 #endif
1234 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]);
1235 ((ALshort*)buffer)[7] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]);
1236 buffer = ((ALshort*)buffer) + 8;
1238 break;
1240 default:
1241 break;
1244 size -= SamplesToDo;
1247 #if defined(HAVE_FESETROUND)
1248 fesetround(fpuState);
1249 #elif defined(HAVE__CONTROLFP)
1250 _controlfp(fpuState, 0xfffff);
1251 #endif
1253 ProcessContext(ALContext);