Add initial AL_EXTX_buffer_sub_data support
[openal-soft/openal-hmr.git] / Alc / ALu.c
blob5371d3b5151ff55d3170dd869c645c3910930fac
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_FLOAT_H)
38 #include <float.h>
39 #endif
41 #if defined(HAVE_STDINT_H)
42 #include <stdint.h>
43 typedef int64_t ALint64;
44 #elif defined(HAVE___INT64)
45 typedef __int64 ALint64;
46 #elif (SIZEOF_LONG == 8)
47 typedef long ALint64;
48 #elif (SIZEOF_LONG_LONG == 8)
49 typedef long long ALint64;
50 #endif
52 #ifdef HAVE_SQRTF
53 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
54 #else
55 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
56 #endif
58 #ifdef HAVE_ACOSF
59 #define aluAcos(x) ((ALfloat)acosf((float)(x)))
60 #else
61 #define aluAcos(x) ((ALfloat)acos((double)(x)))
62 #endif
64 // fixes for mingw32.
65 #if defined(max) && !defined(__max)
66 #define __max max
67 #endif
68 #if defined(min) && !defined(__min)
69 #define __min min
70 #endif
72 #define BUFFERSIZE 24000
73 #define FRACTIONBITS 14
74 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
75 #define MAX_PITCH 65536
77 /* Minimum ramp length in milliseconds. The value below was chosen to
78 * adequately reduce clicks and pops from harsh gain changes. */
79 #define MIN_RAMP_LENGTH 16
81 ALboolean DuplicateStereo = AL_FALSE;
83 /* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
84 * converted to AL_FORMAT_QUAD* when loaded */
85 __inline ALuint aluBytesFromFormat(ALenum format)
87 switch(format)
89 case AL_FORMAT_MONO8:
90 case AL_FORMAT_STEREO8:
91 case AL_FORMAT_QUAD8_LOKI:
92 case AL_FORMAT_QUAD8:
93 case AL_FORMAT_51CHN8:
94 case AL_FORMAT_61CHN8:
95 case AL_FORMAT_71CHN8:
96 return 1;
98 case AL_FORMAT_MONO16:
99 case AL_FORMAT_STEREO16:
100 case AL_FORMAT_QUAD16_LOKI:
101 case AL_FORMAT_QUAD16:
102 case AL_FORMAT_51CHN16:
103 case AL_FORMAT_61CHN16:
104 case AL_FORMAT_71CHN16:
105 return 2;
107 case AL_FORMAT_MONO_FLOAT32:
108 case AL_FORMAT_STEREO_FLOAT32:
109 case AL_FORMAT_QUAD32:
110 case AL_FORMAT_51CHN32:
111 case AL_FORMAT_61CHN32:
112 case AL_FORMAT_71CHN32:
113 return 4;
115 default:
116 return 0;
120 __inline ALuint aluChannelsFromFormat(ALenum format)
122 switch(format)
124 case AL_FORMAT_MONO8:
125 case AL_FORMAT_MONO16:
126 case AL_FORMAT_MONO_FLOAT32:
127 return 1;
129 case AL_FORMAT_STEREO8:
130 case AL_FORMAT_STEREO16:
131 case AL_FORMAT_STEREO_FLOAT32:
132 return 2;
134 case AL_FORMAT_QUAD8_LOKI:
135 case AL_FORMAT_QUAD16_LOKI:
136 case AL_FORMAT_QUAD8:
137 case AL_FORMAT_QUAD16:
138 case AL_FORMAT_QUAD32:
139 return 4;
141 case AL_FORMAT_51CHN8:
142 case AL_FORMAT_51CHN16:
143 case AL_FORMAT_51CHN32:
144 return 6;
146 case AL_FORMAT_61CHN8:
147 case AL_FORMAT_61CHN16:
148 case AL_FORMAT_61CHN32:
149 return 7;
151 case AL_FORMAT_71CHN8:
152 case AL_FORMAT_71CHN16:
153 case AL_FORMAT_71CHN32:
154 return 8;
156 default:
157 return 0;
162 static __inline ALfloat lpFilter(FILTER *iir, ALfloat input)
164 ALfloat *history = iir->history;
165 ALfloat a = iir->coeff;
166 ALfloat output = input;
168 output = output + (history[0]-output)*a;
169 history[0] = output;
170 output = output + (history[1]-output)*a;
171 history[1] = output;
172 output = output + (history[2]-output)*a;
173 history[2] = output;
174 output = output + (history[3]-output)*a;
175 history[3] = output;
177 return output;
181 static __inline ALshort aluF2S(ALfloat Value)
183 ALint i;
185 i = (ALint)Value;
186 i = __min( 32767, i);
187 i = __max(-32768, i);
188 return ((ALshort)i);
191 static __inline ALvoid aluCrossproduct(ALfloat *inVector1,ALfloat *inVector2,ALfloat *outVector)
193 outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
194 outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
195 outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
198 static __inline ALfloat aluDotproduct(ALfloat *inVector1,ALfloat *inVector2)
200 return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
201 inVector1[2]*inVector2[2];
204 static __inline ALvoid aluNormalize(ALfloat *inVector)
206 ALfloat length, inverse_length;
208 length = aluSqrt(aluDotproduct(inVector, inVector));
209 if(length != 0.0f)
211 inverse_length = 1.0f/length;
212 inVector[0] *= inverse_length;
213 inVector[1] *= inverse_length;
214 inVector[2] *= inverse_length;
218 static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
220 ALfloat result[3];
222 result[0] = vector[0]*matrix[0][0] + vector[1]*matrix[1][0] + vector[2]*matrix[2][0];
223 result[1] = vector[0]*matrix[0][1] + vector[1]*matrix[1][1] + vector[2]*matrix[2][1];
224 result[2] = vector[0]*matrix[0][2] + vector[1]*matrix[1][2] + vector[2]*matrix[2][2];
225 memcpy(vector, result, sizeof(result));
229 static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
230 ALenum isMono, ALenum OutputFormat,
231 ALfloat *drysend, ALfloat *wetsend,
232 ALfloat *pitch, ALfloat *drygainhf,
233 ALfloat *wetgainhf)
235 ALfloat InnerAngle,OuterAngle,Angle,Distance,DryMix,WetMix=0.0f;
236 ALfloat Direction[3],Position[3],SourceToListener[3];
237 ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff,OuterGainHF;
238 ALfloat ConeVolume,SourceVolume,PanningFB,PanningLR,ListenerGain;
239 ALfloat U[3],V[3],N[3];
240 ALfloat DopplerFactor, DopplerVelocity, flSpeedOfSound, flMaxVelocity;
241 ALfloat Matrix[3][3];
242 ALfloat flAttenuation;
243 ALfloat RoomAttenuation;
244 ALfloat MetersPerUnit;
245 ALfloat RoomRolloff;
246 ALfloat DryGainHF = 1.0f;
247 ALfloat WetGainHF = 1.0f;
248 ALfloat cw, a, g;
250 //Get context properties
251 DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
252 DopplerVelocity = ALContext->DopplerVelocity;
253 flSpeedOfSound = ALContext->flSpeedOfSound;
255 //Get listener properties
256 ListenerGain = ALContext->Listener.Gain;
257 MetersPerUnit = ALContext->Listener.MetersPerUnit;
259 //Get source properties
260 SourceVolume = ALSource->flGain;
261 memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition));
262 memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation));
263 MinVolume = ALSource->flMinGain;
264 MaxVolume = ALSource->flMaxGain;
265 MinDist = ALSource->flRefDistance;
266 MaxDist = ALSource->flMaxDistance;
267 Rolloff = ALSource->flRollOffFactor;
268 InnerAngle = ALSource->flInnerAngle;
269 OuterAngle = ALSource->flOuterAngle;
270 OuterGainHF = ALSource->OuterGainHF;
271 RoomRolloff = ALSource->RoomRolloffFactor;
273 //Only apply 3D calculations for mono buffers
274 if(isMono != AL_FALSE)
276 //1. Translate Listener to origin (convert to head relative)
277 // Note that Direction and SourceToListener are *not* transformed.
278 // SourceToListener is used with the source and listener velocities,
279 // which are untransformed, and Direction is used with SourceToListener
280 // for the sound cone
281 if(ALSource->bHeadRelative==AL_FALSE)
283 // Build transform matrix
284 aluCrossproduct(ALContext->Listener.Forward, ALContext->Listener.Up, U); // Right-vector
285 aluNormalize(U); // Normalized Right-vector
286 memcpy(V, ALContext->Listener.Up, sizeof(V)); // Up-vector
287 aluNormalize(V); // Normalized Up-vector
288 memcpy(N, ALContext->Listener.Forward, sizeof(N)); // At-vector
289 aluNormalize(N); // Normalized At-vector
290 Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0];
291 Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1];
292 Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
294 // Translate source position into listener space
295 Position[0] -= ALContext->Listener.Position[0];
296 Position[1] -= ALContext->Listener.Position[1];
297 Position[2] -= ALContext->Listener.Position[2];
299 SourceToListener[0] = -Position[0];
300 SourceToListener[1] = -Position[1];
301 SourceToListener[2] = -Position[2];
303 // Transform source position and direction into listener space
304 aluMatrixVector(Position, Matrix);
306 else
308 SourceToListener[0] = -Position[0];
309 SourceToListener[1] = -Position[1];
310 SourceToListener[2] = -Position[2];
312 aluNormalize(SourceToListener);
313 aluNormalize(Direction);
315 //2. Calculate distance attenuation
316 Distance = aluSqrt(aluDotproduct(Position, Position));
318 if(ALSource->Send[0].Slot)
320 if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
321 RoomRolloff += ALSource->Send[0].Slot->effect.Reverb.RoomRolloffFactor;
324 flAttenuation = 1.0f;
325 RoomAttenuation = 1.0f;
326 switch (ALContext->DistanceModel)
328 case AL_INVERSE_DISTANCE_CLAMPED:
329 Distance=__max(Distance,MinDist);
330 Distance=__min(Distance,MaxDist);
331 if (MaxDist < MinDist)
332 break;
333 //fall-through
334 case AL_INVERSE_DISTANCE:
335 if (MinDist > 0.0f)
337 if ((MinDist + (Rolloff * (Distance - MinDist))) > 0.0f)
338 flAttenuation = MinDist / (MinDist + (Rolloff * (Distance - MinDist)));
339 if ((MinDist + (RoomRolloff * (Distance - MinDist))) > 0.0f)
340 RoomAttenuation = MinDist / (MinDist + (RoomRolloff * (Distance - MinDist)));
342 break;
344 case AL_LINEAR_DISTANCE_CLAMPED:
345 Distance=__max(Distance,MinDist);
346 Distance=__min(Distance,MaxDist);
347 if (MaxDist < MinDist)
348 break;
349 //fall-through
350 case AL_LINEAR_DISTANCE:
351 Distance=__min(Distance,MaxDist);
352 if (MaxDist != MinDist)
354 flAttenuation = 1.0f - (Rolloff*(Distance-MinDist)/(MaxDist - MinDist));
355 RoomAttenuation = 1.0f - (RoomRolloff*(Distance-MinDist)/(MaxDist - MinDist));
357 break;
359 case AL_EXPONENT_DISTANCE_CLAMPED:
360 Distance=__max(Distance,MinDist);
361 Distance=__min(Distance,MaxDist);
362 if (MaxDist < MinDist)
363 break;
364 //fall-through
365 case AL_EXPONENT_DISTANCE:
366 if ((Distance > 0.0f) && (MinDist > 0.0f))
368 flAttenuation = (ALfloat)pow(Distance/MinDist, -Rolloff);
369 RoomAttenuation = (ALfloat)pow(Distance/MinDist, -RoomRolloff);
371 break;
373 case AL_NONE:
374 flAttenuation = 1.0f;
375 RoomAttenuation = 1.0f;
376 break;
379 // Distance-based air absorption
380 if(ALSource->AirAbsorptionFactor > 0.0f && ALContext->DistanceModel != AL_NONE)
382 ALfloat dist = Distance-MinDist;
383 ALfloat absorb;
385 if(dist < 0.0f) dist = 0.0f;
386 // Absorption calculation is done in dB
387 absorb = (ALSource->AirAbsorptionFactor*AIRABSORBGAINDBHF) *
388 (Distance*MetersPerUnit);
389 // Convert dB to linear gain before applying
390 absorb = pow(0.5, absorb/-6.0);
391 DryGainHF *= absorb;
392 WetGainHF *= absorb;
395 // Source Gain + Attenuation and clamp to Min/Max Gain
396 DryMix = SourceVolume * flAttenuation;
397 DryMix = __min(DryMix,MaxVolume);
398 DryMix = __max(DryMix,MinVolume);
400 WetMix = SourceVolume * RoomAttenuation;
401 WetMix = __min(WetMix,MaxVolume);
402 WetMix = __max(WetMix,MinVolume);
404 //3. Apply directional soundcones
405 Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * 180.0f /
406 3.141592654f;
407 if(Angle >= InnerAngle && Angle <= OuterAngle)
409 ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
410 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f)*scale);
411 DryMix *= ConeVolume;
412 if(ALSource->WetGainAuto)
413 WetMix *= ConeVolume;
414 if(ALSource->DryGainHFAuto)
415 DryGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
416 if(ALSource->WetGainHFAuto)
417 WetGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
419 else if(Angle > OuterAngle)
421 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f));
422 DryMix *= ConeVolume;
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));
431 //4. Calculate Velocity
432 if(DopplerFactor != 0.0f)
434 ALfloat flVSS, flVLS = 0.0f;
436 if(ALSource->bHeadRelative==AL_FALSE)
437 flVLS = aluDotproduct(ALContext->Listener.Velocity, SourceToListener);
438 flVSS = aluDotproduct(ALSource->vVelocity, SourceToListener);
440 flMaxVelocity = (DopplerVelocity * flSpeedOfSound) / DopplerFactor;
442 if (flVSS >= flMaxVelocity)
443 flVSS = (flMaxVelocity - 1.0f);
444 else if (flVSS <= -flMaxVelocity)
445 flVSS = -flMaxVelocity + 1.0f;
447 if (flVLS >= flMaxVelocity)
448 flVLS = (flMaxVelocity - 1.0f);
449 else if (flVLS <= -flMaxVelocity)
450 flVLS = -flMaxVelocity + 1.0f;
452 pitch[0] = ALSource->flPitch *
453 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVLS)) /
454 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVSS));
456 else
457 pitch[0] = ALSource->flPitch;
459 if(ALSource->Send[0].Slot &&
460 ALSource->Send[0].Slot->effect.type != AL_EFFECT_NULL)
462 // If the slot's auxilliary send auto is off, the data sent to the
463 // effect slot is the same as the dry path, sans filter effects
464 if(!ALSource->Send[0].Slot->AuxSendAuto)
466 WetMix = DryMix;
467 WetGainHF = DryGainHF;
470 // Note that these are really applied by the effect slot. However,
471 // it's easier to handle them here (particularly the lowpass
472 // filter). Applying the gain to the individual sources going to
473 // the effect slot should have the same effect as applying the gain
474 // to the accumulated sources in the effect slot.
475 // vol1*g + vol2*g + ... voln*g = (vol1+vol2+...voln)*g
476 WetMix *= ALSource->Send[0].Slot->Gain;
477 if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
479 WetMix *= ALSource->Send[0].Slot->effect.Reverb.Gain;
480 WetGainHF *= ALSource->Send[0].Slot->effect.Reverb.GainHF;
481 WetGainHF *= pow(ALSource->Send[0].Slot->effect.Reverb.AirAbsorptionGainHF,
482 Distance * MetersPerUnit);
485 else
487 WetMix = 0.0f;
488 WetGainHF = 1.0f;
491 //5. Apply filter gains and filters
492 switch(ALSource->DirectFilter.type)
494 case AL_FILTER_LOWPASS:
495 DryMix *= ALSource->DirectFilter.Gain;
496 DryGainHF *= ALSource->DirectFilter.GainHF;
497 break;
500 switch(ALSource->Send[0].WetFilter.type)
502 case AL_FILTER_LOWPASS:
503 WetMix *= ALSource->Send[0].WetFilter.Gain;
504 WetGainHF *= ALSource->Send[0].WetFilter.GainHF;
505 break;
508 DryMix *= ListenerGain;
509 WetMix *= ListenerGain;
511 //6. Convert normalized position into pannings, then into channel volumes
512 aluNormalize(Position);
513 switch(aluChannelsFromFormat(OutputFormat))
515 case 1:
516 case 2:
517 PanningLR = 0.5f + 0.5f*Position[0];
518 drysend[FRONT_LEFT] = DryMix * aluSqrt(1.0f-PanningLR); //L Direct
519 drysend[FRONT_RIGHT] = DryMix * aluSqrt( PanningLR); //R Direct
520 drysend[BACK_LEFT] = 0.0f;
521 drysend[BACK_RIGHT] = 0.0f;
522 drysend[SIDE_LEFT] = 0.0f;
523 drysend[SIDE_RIGHT] = 0.0f;
524 break;
525 case 4:
526 /* TODO: Add center/lfe channel in spatial calculations? */
527 case 6:
528 // Apply a scalar so each individual speaker has more weight
529 PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f);
530 PanningLR = __min(1.0f, PanningLR);
531 PanningLR = __max(0.0f, PanningLR);
532 PanningFB = 0.5f + (0.5f*Position[2]*1.41421356f);
533 PanningFB = __min(1.0f, PanningFB);
534 PanningFB = __max(0.0f, PanningFB);
535 drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
536 drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
537 drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
538 drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
539 drysend[SIDE_LEFT] = 0.0f;
540 drysend[SIDE_RIGHT] = 0.0f;
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;
559 else
561 drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
562 drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
563 drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
564 drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
565 drysend[BACK_LEFT] = 0.0f;
566 drysend[BACK_RIGHT] = 0.0f;
568 default:
569 break;
571 *wetsend = WetMix;
573 // Update filter coefficients. Calculations based on the I3DL2 spec.
574 cw = cos(2.0f*3.141592654f * LOWPASSFREQCUTOFF / ALContext->Frequency);
575 // We use four chained one-pole filters, so we need to take the fourth
576 // root of the squared gain, which is the same as the square root of
577 // the base gain.
578 // Be careful with gains < 0.0001, as that causes the coefficient to
579 // head towards 1, which will flatten the signal
580 g = aluSqrt(__max(DryGainHF, 0.0001f));
581 a = 0.0f;
582 if(g < 0.9999f) // 1-epsilon
583 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
584 ALSource->iirFilter.coeff = a;
586 g = aluSqrt(__max(WetGainHF, 0.0001f));
587 a = 0.0f;
588 if(g < 0.9999f) // 1-epsilon
589 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
590 ALSource->Send[0].iirFilter.coeff = a;
592 *drygainhf = DryGainHF;
593 *wetgainhf = WetGainHF;
595 else
597 //1. Multi-channel buffers always play "normal"
598 pitch[0] = ALSource->flPitch;
600 drysend[FRONT_LEFT] = SourceVolume * ListenerGain;
601 drysend[FRONT_RIGHT] = SourceVolume * ListenerGain;
602 drysend[SIDE_LEFT] = SourceVolume * ListenerGain;
603 drysend[SIDE_RIGHT] = SourceVolume * ListenerGain;
604 drysend[BACK_LEFT] = SourceVolume * ListenerGain;
605 drysend[BACK_RIGHT] = SourceVolume * ListenerGain;
606 drysend[CENTER] = SourceVolume * ListenerGain;
607 drysend[LFE] = SourceVolume * ListenerGain;
608 *wetsend = 0.0f;
609 WetGainHF = 1.0f;
611 *drygainhf = DryGainHF;
612 *wetgainhf = WetGainHF;
616 static __inline ALshort lerp(ALshort val1, ALshort val2, ALint frac)
618 return val1 + (((val2-val1)*frac)>>FRACTIONBITS);
621 ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
623 static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
624 static float WetBuffer[BUFFERSIZE];
625 ALfloat newDrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
626 ALfloat newWetSend = 0.0f;
627 ALfloat DryGainHF = 0.0f;
628 ALfloat WetGainHF = 0.0f;
629 ALfloat *DrySend;
630 ALfloat *WetSend;
631 ALuint rampLength;
632 ALfloat dryGainStep[OUTPUTCHANNELS];
633 ALfloat wetGainStep;
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 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 *DryFilter, *WetFilter;
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(WetBuffer, 0, SamplesToDo*sizeof(ALfloat));
691 memset(DryBuffer, 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 DataSize /= Channels * aluBytesFromFormat(ALBuffer->format);
714 Frequency = ALBuffer->frequency;
715 DataPosInt = ALSource->position;
716 DataPosFrac = ALSource->position_fraction;
718 if(DataPosInt >= DataSize)
719 goto skipmix;
721 CalcSourceParams(ALContext, ALSource,
722 (Channels==1) ? AL_TRUE : AL_FALSE,
723 format, newDrySend, &newWetSend, &Pitch,
724 &DryGainHF, &WetGainHF);
726 Pitch = (Pitch*Frequency) / ALContext->Frequency;
728 //Get source info
729 DryFilter = &ALSource->iirFilter;
730 WetFilter = &ALSource->Send[0].iirFilter;
731 DrySend = ALSource->DryGains;
732 WetSend = &ALSource->WetGain;
734 //Compute the gain steps for each output channel
735 for(i = 0;i < OUTPUTCHANNELS;i++)
736 dryGainStep[i] = (newDrySend[i]-DrySend[i]) / rampLength;
737 wetGainStep = (newWetSend-(*WetSend)) / rampLength;
739 //Compute 18.14 fixed point step
740 if(Pitch > (float)MAX_PITCH)
741 Pitch = (float)MAX_PITCH;
742 increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS));
743 if(increment <= 0)
744 increment = (1<<FRACTIONBITS);
746 //Figure out how many samples we can mix.
747 DataSize64 = DataSize;
748 DataSize64 <<= FRACTIONBITS;
749 DataPos64 = DataPosInt;
750 DataPos64 <<= FRACTIONBITS;
751 DataPos64 += DataPosFrac;
752 BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
754 BufferListItem = ALSource->queue;
755 for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
757 if(BufferListItem)
758 BufferListItem = BufferListItem->next;
760 if (BufferListItem)
762 if (BufferListItem->next)
764 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer);
765 if(NextBuf && NextBuf->data)
767 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
768 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
771 else if (ALSource->bLooping)
773 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer);
774 if (NextBuf && NextBuf->data)
776 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
777 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
780 else
781 memset(&Data[DataSize*Channels], 0, (ALBuffer->padding*Channels*2));
783 BufferSize = min(BufferSize, (SamplesToDo-j));
785 //Actual sample mixing loop
786 k = 0;
787 Data += DataPosInt*Channels;
788 while(BufferSize--)
790 for(i = 0;i < OUTPUTCHANNELS;i++)
791 DrySend[i] += dryGainStep[i];
792 *WetSend += wetGainStep;
794 if(Channels==1)
796 ALfloat sample, outsamp;
797 //First order interpolator
798 sample = lerp(Data[k], Data[k+1], DataPosFrac);
800 //Direct path final mix buffer and panning
801 outsamp = lpFilter(DryFilter, sample);
802 DryBuffer[j][FRONT_LEFT] += outsamp*DrySend[FRONT_LEFT];
803 DryBuffer[j][FRONT_RIGHT] += outsamp*DrySend[FRONT_RIGHT];
804 DryBuffer[j][SIDE_LEFT] += outsamp*DrySend[SIDE_LEFT];
805 DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT];
806 DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT];
807 DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT];
808 //Room path final mix buffer and panning
809 outsamp = lpFilter(WetFilter, sample);
810 WetBuffer[j] += outsamp*(*WetSend);
812 else
814 ALfloat samp1, samp2;
815 //First order interpolator (front left)
816 samp1 = lerp(Data[k*Channels], Data[(k+1)*Channels], DataPosFrac);
817 DryBuffer[j][FRONT_LEFT] += samp1*DrySend[FRONT_LEFT];
818 //First order interpolator (front right)
819 samp2 = lerp(Data[k*Channels+1], Data[(k+1)*Channels+1], DataPosFrac);
820 DryBuffer[j][FRONT_RIGHT] += samp2*DrySend[FRONT_RIGHT];
821 if(Channels >= 4)
823 int i = 2;
824 if(Channels >= 6)
826 if(Channels != 7)
828 //First order interpolator (center)
829 value = lerp(Data[k*Channels+i], Data[(k+1)*Channels+i], DataPosFrac);
830 DryBuffer[j][CENTER] += value*DrySend[CENTER];
831 i++;
833 //First order interpolator (lfe)
834 value = lerp(Data[k*Channels+i], Data[(k+1)*Channels+i], DataPosFrac);
835 DryBuffer[j][LFE] += value*DrySend[LFE];
836 i++;
838 //First order interpolator (back left)
839 value = lerp(Data[k*Channels+i], Data[(k+1)*Channels+i], DataPosFrac);
840 DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT];
841 i++;
842 //First order interpolator (back right)
843 value = lerp(Data[k*Channels+i], Data[(k+1)*Channels+i], DataPosFrac);
844 DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT];
845 i++;
846 if(Channels >= 7)
848 //First order interpolator (side left)
849 value = lerp(Data[k*Channels+i], Data[(k+1)*Channels+i], DataPosFrac);
850 DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT];
851 i++;
852 //First order interpolator (side right)
853 value = lerp(Data[k*Channels+i], Data[(k+1)*Channels+i], DataPosFrac);
854 DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT];
855 i++;
858 else if(DuplicateStereo)
860 //Duplicate stereo channels on the back speakers
861 DryBuffer[j][BACK_LEFT] += samp1*DrySend[BACK_LEFT];
862 DryBuffer[j][BACK_RIGHT] += samp2*DrySend[BACK_RIGHT];
865 DataPosFrac += increment;
866 k += DataPosFrac>>FRACTIONBITS;
867 DataPosFrac &= FRACTIONMASK;
868 j++;
870 DataPosInt += k;
872 //Update source info
873 ALSource->position = DataPosInt;
874 ALSource->position_fraction = DataPosFrac;
876 skipmix: ;
879 //Handle looping sources
880 if(!Buffer || DataPosInt >= DataSize)
882 //queueing
883 if(ALSource->queue)
885 Looping = ALSource->bLooping;
886 if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
888 BufferListItem = ALSource->queue;
889 for(loop = 0; loop <= ALSource->BuffersPlayed; loop++)
891 if(BufferListItem)
893 if(!Looping)
894 BufferListItem->bufferstate = PROCESSED;
895 BufferListItem = BufferListItem->next;
898 if(BufferListItem)
899 ALSource->ulBufferID = BufferListItem->buffer;
900 ALSource->position = DataPosInt-DataSize;
901 ALSource->position_fraction = DataPosFrac;
902 ALSource->BuffersPlayed++;
904 else
906 if(!Looping)
908 /* alSourceStop */
909 ALSource->state = AL_STOPPED;
910 ALSource->inuse = AL_FALSE;
911 ALSource->BuffersPlayed = ALSource->BuffersInQueue;
912 BufferListItem = ALSource->queue;
913 while(BufferListItem != NULL)
915 BufferListItem->bufferstate = PROCESSED;
916 BufferListItem = BufferListItem->next;
918 ALSource->position = DataSize;
919 ALSource->position_fraction = 0;
921 else
923 /* alSourceRewind */
924 /* alSourcePlay */
925 ALSource->state = AL_PLAYING;
926 ALSource->inuse = AL_TRUE;
927 ALSource->play = AL_TRUE;
928 ALSource->BuffersPlayed = 0;
929 BufferListItem = ALSource->queue;
930 while(BufferListItem != NULL)
932 BufferListItem->bufferstate = PENDING;
933 BufferListItem = BufferListItem->next;
935 ALSource->ulBufferID = ALSource->queue->buffer;
937 if(ALSource->BuffersInQueue == 1)
938 ALSource->position = DataPosInt%DataSize;
939 else
940 ALSource->position = DataPosInt-DataSize;
941 ALSource->position_fraction = DataPosFrac;
947 //Get source state
948 State = ALSource->state;
951 ALSource = ALSource->next;
954 // effect slot processing
955 while(ALEffectSlot)
957 if(ALEffectSlot->effect.type == AL_EFFECT_REVERB)
959 ALfloat *DelayBuffer = ALEffectSlot->ReverbBuffer;
960 ALuint Pos = ALEffectSlot->ReverbPos;
961 ALuint LatePos = ALEffectSlot->ReverbLatePos;
962 ALuint ReflectPos = ALEffectSlot->ReverbReflectPos;
963 ALuint Length = ALEffectSlot->ReverbLength;
964 ALfloat DecayGain = ALEffectSlot->ReverbDecayGain;
965 ALfloat DecayHFRatio = ALEffectSlot->effect.Reverb.DecayHFRatio;
966 ALfloat ReflectGain = ALEffectSlot->effect.Reverb.ReflectionsGain;
967 ALfloat LateReverbGain = ALEffectSlot->effect.Reverb.LateReverbGain;
968 ALfloat sample, lowsample;
970 WetFilter = &ALEffectSlot->iirFilter;
971 for(i = 0;i < SamplesToDo;i++)
973 DelayBuffer[Pos] = WetBuffer[i];
975 sample = DelayBuffer[ReflectPos] * ReflectGain;
977 DelayBuffer[LatePos] *= LateReverbGain;
979 Pos = (Pos+1) % Length;
980 lowsample = lpFilter(WetFilter, DelayBuffer[Pos]);
981 lowsample += (DelayBuffer[Pos]-lowsample) * DecayHFRatio;
983 DelayBuffer[LatePos] += lowsample * DecayGain;
985 sample += DelayBuffer[LatePos];
987 DryBuffer[i][FRONT_LEFT] += sample;
988 DryBuffer[i][FRONT_RIGHT] += sample;
989 DryBuffer[i][SIDE_LEFT] += sample;
990 DryBuffer[i][SIDE_RIGHT] += sample;
991 DryBuffer[i][BACK_LEFT] += sample;
992 DryBuffer[i][BACK_RIGHT] += sample;
994 LatePos = (LatePos+1) % Length;
995 ReflectPos = (ReflectPos+1) % Length;
998 ALEffectSlot->ReverbPos = Pos;
999 ALEffectSlot->ReverbLatePos = LatePos;
1000 ALEffectSlot->ReverbReflectPos = ReflectPos;
1003 ALEffectSlot = ALEffectSlot->next;
1006 //Post processing loop
1007 switch(format)
1009 case AL_FORMAT_MONO8:
1010 for(i = 0;i < SamplesToDo;i++)
1012 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT])>>8)+128);
1013 buffer = ((ALubyte*)buffer) + 1;
1015 break;
1016 case AL_FORMAT_STEREO8:
1017 if(ALContext && ALContext->bs2b)
1019 for(i = 0;i < SamplesToDo;i++)
1021 float samples[2];
1022 samples[0] = DryBuffer[i][FRONT_LEFT];
1023 samples[1] = DryBuffer[i][FRONT_RIGHT];
1024 bs2b_cross_feed(ALContext->bs2b, samples);
1025 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(samples[0])>>8)+128);
1026 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(samples[1])>>8)+128);
1027 buffer = ((ALubyte*)buffer) + 2;
1030 else
1032 for(i = 0;i < SamplesToDo;i++)
1034 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1035 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1036 buffer = ((ALubyte*)buffer) + 2;
1039 break;
1040 case AL_FORMAT_QUAD8:
1041 for(i = 0;i < SamplesToDo;i++)
1043 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1044 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1045 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1046 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1047 buffer = ((ALubyte*)buffer) + 4;
1049 break;
1050 case AL_FORMAT_51CHN8:
1051 for(i = 0;i < SamplesToDo;i++)
1053 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1054 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1055 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1056 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER])>>8)+128);
1057 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1058 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1059 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1060 #else
1061 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1062 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1063 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER])>>8)+128);
1064 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1065 #endif
1066 buffer = ((ALubyte*)buffer) + 6;
1068 break;
1069 case AL_FORMAT_61CHN8:
1070 for(i = 0;i < SamplesToDo;i++)
1072 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1073 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1074 #ifdef _WIN32
1075 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1076 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1077 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1078 #else
1079 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1080 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1081 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1082 #endif
1083 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT])>>8)+128);
1084 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT])>>8)+128);
1085 buffer = ((ALubyte*)buffer) + 7;
1087 break;
1088 case AL_FORMAT_71CHN8:
1089 for(i = 0;i < SamplesToDo;i++)
1091 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1092 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1093 #ifdef _WIN32
1094 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER])>>8)+128);
1095 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1096 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1097 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1098 #else
1099 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1100 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1101 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER])>>8)+128);
1102 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1103 #endif
1104 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT])>>8)+128);
1105 ((ALubyte*)buffer)[7] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT])>>8)+128);
1106 buffer = ((ALubyte*)buffer) + 8;
1108 break;
1110 case AL_FORMAT_MONO16:
1111 for(i = 0;i < SamplesToDo;i++)
1113 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]);
1114 buffer = ((ALshort*)buffer) + 1;
1116 break;
1117 case AL_FORMAT_STEREO16:
1118 if(ALContext && ALContext->bs2b)
1120 for(i = 0;i < SamplesToDo;i++)
1122 float samples[2];
1123 samples[0] = DryBuffer[i][FRONT_LEFT];
1124 samples[1] = DryBuffer[i][FRONT_RIGHT];
1125 bs2b_cross_feed(ALContext->bs2b, samples);
1126 ((ALshort*)buffer)[0] = aluF2S(samples[0]);
1127 ((ALshort*)buffer)[1] = aluF2S(samples[1]);
1128 buffer = ((ALshort*)buffer) + 2;
1131 else
1133 for(i = 0;i < SamplesToDo;i++)
1135 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1136 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1137 buffer = ((ALshort*)buffer) + 2;
1140 break;
1141 case AL_FORMAT_QUAD16:
1142 for(i = 0;i < SamplesToDo;i++)
1144 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1145 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1146 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT]);
1147 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1148 buffer = ((ALshort*)buffer) + 4;
1150 break;
1151 case AL_FORMAT_51CHN16:
1152 for(i = 0;i < SamplesToDo;i++)
1154 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1155 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1156 #ifdef _WIN32
1157 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER]);
1158 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE]);
1159 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT]);
1160 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1161 #else
1162 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT]);
1163 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1164 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER]);
1165 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE]);
1166 #endif
1167 buffer = ((ALshort*)buffer) + 6;
1169 break;
1170 case AL_FORMAT_61CHN16:
1171 for(i = 0;i < SamplesToDo;i++)
1173 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1174 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1175 #ifdef _WIN32
1176 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][LFE]);
1177 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_LEFT]);
1178 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1179 #else
1180 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT]);
1181 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1182 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][LFE]);
1183 #endif
1184 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][SIDE_LEFT]);
1185 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_RIGHT]);
1186 buffer = ((ALshort*)buffer) + 7;
1188 break;
1189 case AL_FORMAT_71CHN16:
1190 for(i = 0;i < SamplesToDo;i++)
1192 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1193 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1194 #ifdef _WIN32
1195 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER]);
1196 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE]);
1197 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT]);
1198 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1199 #else
1200 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT]);
1201 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1202 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER]);
1203 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE]);
1204 #endif
1205 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_LEFT]);
1206 ((ALshort*)buffer)[7] = aluF2S(DryBuffer[i][SIDE_RIGHT]);
1207 buffer = ((ALshort*)buffer) + 8;
1209 break;
1211 default:
1212 break;
1215 size -= SamplesToDo;
1218 #if defined(HAVE_FESETROUND)
1219 fesetround(fpuState);
1220 #elif defined(HAVE__CONTROLFP)
1221 _controlfp(fpuState, 0xfffff);
1222 #endif
1224 ProcessContext(ALContext);