Make the filter functions global inline, and use it for echo
[openal-soft.git] / Alc / ALu.c
blob8d4b9c0a912c8a715a1bb1f63aefc72501ada0ae
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 <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <assert.h>
31 #include "alMain.h"
32 #include "AL/al.h"
33 #include "AL/alc.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alThunk.h"
37 #include "alListener.h"
38 #include "alAuxEffectSlot.h"
39 #include "alu.h"
40 #include "bs2b.h"
41 #include "alReverb.h"
43 #if defined(HAVE_STDINT_H)
44 #include <stdint.h>
45 typedef int64_t ALint64;
46 #elif defined(HAVE___INT64)
47 typedef __int64 ALint64;
48 #elif (SIZEOF_LONG == 8)
49 typedef long ALint64;
50 #elif (SIZEOF_LONG_LONG == 8)
51 typedef long long ALint64;
52 #endif
54 #define FRACTIONBITS 14
55 #define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
56 #define MAX_PITCH 65536
58 /* Minimum ramp length in milliseconds. The value below was chosen to
59 * adequately reduce clicks and pops from harsh gain changes. */
60 #define MIN_RAMP_LENGTH 16
62 ALboolean DuplicateStereo = AL_FALSE;
64 /* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
65 * converted to AL_FORMAT_QUAD* when loaded */
66 __inline ALuint aluBytesFromFormat(ALenum format)
68 switch(format)
70 case AL_FORMAT_MONO8:
71 case AL_FORMAT_STEREO8:
72 case AL_FORMAT_QUAD8_LOKI:
73 case AL_FORMAT_QUAD8:
74 case AL_FORMAT_51CHN8:
75 case AL_FORMAT_61CHN8:
76 case AL_FORMAT_71CHN8:
77 return 1;
79 case AL_FORMAT_MONO16:
80 case AL_FORMAT_STEREO16:
81 case AL_FORMAT_QUAD16_LOKI:
82 case AL_FORMAT_QUAD16:
83 case AL_FORMAT_51CHN16:
84 case AL_FORMAT_61CHN16:
85 case AL_FORMAT_71CHN16:
86 return 2;
88 case AL_FORMAT_MONO_FLOAT32:
89 case AL_FORMAT_STEREO_FLOAT32:
90 case AL_FORMAT_QUAD32:
91 case AL_FORMAT_51CHN32:
92 case AL_FORMAT_61CHN32:
93 case AL_FORMAT_71CHN32:
94 return 4;
96 default:
97 return 0;
101 __inline ALuint aluChannelsFromFormat(ALenum format)
103 switch(format)
105 case AL_FORMAT_MONO8:
106 case AL_FORMAT_MONO16:
107 case AL_FORMAT_MONO_FLOAT32:
108 return 1;
110 case AL_FORMAT_STEREO8:
111 case AL_FORMAT_STEREO16:
112 case AL_FORMAT_STEREO_FLOAT32:
113 return 2;
115 case AL_FORMAT_QUAD8_LOKI:
116 case AL_FORMAT_QUAD16_LOKI:
117 case AL_FORMAT_QUAD8:
118 case AL_FORMAT_QUAD16:
119 case AL_FORMAT_QUAD32:
120 return 4;
122 case AL_FORMAT_51CHN8:
123 case AL_FORMAT_51CHN16:
124 case AL_FORMAT_51CHN32:
125 return 6;
127 case AL_FORMAT_61CHN8:
128 case AL_FORMAT_61CHN16:
129 case AL_FORMAT_61CHN32:
130 return 7;
132 case AL_FORMAT_71CHN8:
133 case AL_FORMAT_71CHN16:
134 case AL_FORMAT_71CHN32:
135 return 8;
137 default:
138 return 0;
143 static __inline ALshort aluF2S(ALfloat Value)
145 ALint i;
147 i = (ALint)Value;
148 i = __min( 32767, i);
149 i = __max(-32768, i);
150 return ((ALshort)i);
153 static __inline ALvoid aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
155 outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
156 outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
157 outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
160 static __inline ALfloat aluDotproduct(const ALfloat *inVector1, const ALfloat *inVector2)
162 return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
163 inVector1[2]*inVector2[2];
166 static __inline ALvoid aluNormalize(ALfloat *inVector)
168 ALfloat length, inverse_length;
170 length = aluSqrt(aluDotproduct(inVector, inVector));
171 if(length != 0.0f)
173 inverse_length = 1.0f/length;
174 inVector[0] *= inverse_length;
175 inVector[1] *= inverse_length;
176 inVector[2] *= inverse_length;
180 static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
182 ALfloat result[3];
184 result[0] = vector[0]*matrix[0][0] + vector[1]*matrix[1][0] + vector[2]*matrix[2][0];
185 result[1] = vector[0]*matrix[0][1] + vector[1]*matrix[1][1] + vector[2]*matrix[2][1];
186 result[2] = vector[0]*matrix[0][2] + vector[1]*matrix[1][2] + vector[2]*matrix[2][2];
187 memcpy(vector, result, sizeof(result));
190 static ALvoid SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[OUTPUTCHANNELS],
191 ALint Speaker2Chan[OUTPUTCHANNELS], ALint chans)
193 const char *confkey;
194 const char *next;
195 const char *sep;
196 const char *end;
197 int i, val;
199 confkey = GetConfigValue(NULL, name, "");
200 next = confkey;
201 while(next && *next)
203 confkey = next;
204 next = strchr(confkey, ',');
205 if(next)
207 do {
208 next++;
209 } while(isspace(*next));
212 sep = strchr(confkey, '=');
213 if(!sep || confkey == sep)
214 continue;
216 end = sep - 1;
217 while(isspace(*end) && end != confkey)
218 end--;
220 if(strncmp(confkey, "fl", end-confkey) == 0)
221 val = FRONT_LEFT;
222 else if(strncmp(confkey, "fr", end-confkey) == 0)
223 val = FRONT_RIGHT;
224 else if(strncmp(confkey, "fc", end-confkey) == 0)
225 val = FRONT_CENTER;
226 else if(strncmp(confkey, "bl", end-confkey) == 0)
227 val = BACK_LEFT;
228 else if(strncmp(confkey, "br", end-confkey) == 0)
229 val = BACK_RIGHT;
230 else if(strncmp(confkey, "bc", end-confkey) == 0)
231 val = BACK_CENTER;
232 else if(strncmp(confkey, "sl", end-confkey) == 0)
233 val = SIDE_LEFT;
234 else if(strncmp(confkey, "sr", end-confkey) == 0)
235 val = SIDE_RIGHT;
236 else
238 AL_PRINT("Unknown speaker for %s: \"%c%c\"\n", name, confkey[0], confkey[1]);
239 continue;
242 sep++;
243 while(isspace(*sep))
244 sep++;
246 for(i = 0;i < chans;i++)
248 if(Speaker2Chan[i] == val)
250 val = strtol(sep, NULL, 10);
251 if(val >= -180 && val <= 180)
252 SpeakerAngle[i] = val * M_PI/180.0f;
253 else
254 AL_PRINT("Invalid angle for speaker \"%c%c\": %d\n", confkey[0], confkey[1], val);
255 break;
260 for(i = 1;i < chans;i++)
262 if(SpeakerAngle[i] <= SpeakerAngle[i-1])
264 AL_PRINT("Speaker %d of %d does not follow previous: %f > %f\n", i, chans,
265 SpeakerAngle[i-1] * 180.0f/M_PI, SpeakerAngle[i] * 180.0f/M_PI);
266 SpeakerAngle[i] = SpeakerAngle[i-1] + 1 * 180.0f/M_PI;
271 static __inline ALfloat aluLUTpos2Angle(ALint pos)
273 if(pos < QUADRANT_NUM)
274 return aluAtan((ALfloat)pos / (ALfloat)(QUADRANT_NUM - pos));
275 if(pos < 2 * QUADRANT_NUM)
276 return M_PI_2 + aluAtan((ALfloat)(pos - QUADRANT_NUM) / (ALfloat)(2 * QUADRANT_NUM - pos));
277 if(pos < 3 * QUADRANT_NUM)
278 return aluAtan((ALfloat)(pos - 2 * QUADRANT_NUM) / (ALfloat)(3 * QUADRANT_NUM - pos)) - M_PI;
279 return aluAtan((ALfloat)(pos - 3 * QUADRANT_NUM) / (ALfloat)(4 * QUADRANT_NUM - pos)) - M_PI_2;
282 ALvoid aluInitPanning(ALCcontext *Context)
284 ALint pos, offset, s;
285 ALfloat Alpha, Theta;
286 ALfloat SpeakerAngle[OUTPUTCHANNELS];
287 ALint Speaker2Chan[OUTPUTCHANNELS];
289 for(s = 0;s < OUTPUTCHANNELS;s++)
291 int s2;
292 for(s2 = 0;s2 < OUTPUTCHANNELS;s2++)
293 Context->ChannelMatrix[s][s2] = ((s==s2) ? 1.0f : 0.0f);
296 switch(Context->Device->Format)
298 /* Mono is rendered as stereo, then downmixed during post-process */
299 case AL_FORMAT_MONO8:
300 case AL_FORMAT_MONO16:
301 case AL_FORMAT_MONO_FLOAT32:
302 Context->ChannelMatrix[FRONT_CENTER][FRONT_LEFT] = aluSqrt(0.5);
303 Context->ChannelMatrix[FRONT_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
304 Context->ChannelMatrix[SIDE_LEFT][FRONT_LEFT] = 1.0f;
305 Context->ChannelMatrix[SIDE_RIGHT][FRONT_RIGHT] = 1.0f;
306 Context->ChannelMatrix[BACK_LEFT][FRONT_LEFT] = 1.0f;
307 Context->ChannelMatrix[BACK_RIGHT][FRONT_RIGHT] = 1.0f;
308 Context->ChannelMatrix[BACK_CENTER][FRONT_LEFT] = aluSqrt(0.5);
309 Context->ChannelMatrix[BACK_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
310 Context->NumChan = 2;
311 Speaker2Chan[0] = FRONT_LEFT;
312 Speaker2Chan[1] = FRONT_RIGHT;
313 SpeakerAngle[0] = -90.0f * M_PI/180.0f;
314 SpeakerAngle[1] = 90.0f * M_PI/180.0f;
315 break;
317 case AL_FORMAT_STEREO8:
318 case AL_FORMAT_STEREO16:
319 case AL_FORMAT_STEREO_FLOAT32:
320 Context->ChannelMatrix[FRONT_CENTER][FRONT_LEFT] = aluSqrt(0.5);
321 Context->ChannelMatrix[FRONT_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
322 Context->ChannelMatrix[SIDE_LEFT][FRONT_LEFT] = 1.0f;
323 Context->ChannelMatrix[SIDE_RIGHT][FRONT_RIGHT] = 1.0f;
324 Context->ChannelMatrix[BACK_LEFT][FRONT_LEFT] = 1.0f;
325 Context->ChannelMatrix[BACK_RIGHT][FRONT_RIGHT] = 1.0f;
326 Context->ChannelMatrix[BACK_CENTER][FRONT_LEFT] = aluSqrt(0.5);
327 Context->ChannelMatrix[BACK_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
328 Context->NumChan = 2;
329 Speaker2Chan[0] = FRONT_LEFT;
330 Speaker2Chan[1] = FRONT_RIGHT;
331 SpeakerAngle[0] = -90.0f * M_PI/180.0f;
332 SpeakerAngle[1] = 90.0f * M_PI/180.0f;
333 SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Context->NumChan);
334 break;
336 case AL_FORMAT_QUAD8:
337 case AL_FORMAT_QUAD16:
338 case AL_FORMAT_QUAD32:
339 Context->ChannelMatrix[FRONT_CENTER][FRONT_LEFT] = aluSqrt(0.5);
340 Context->ChannelMatrix[FRONT_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
341 Context->ChannelMatrix[SIDE_LEFT][FRONT_LEFT] = aluSqrt(0.5);
342 Context->ChannelMatrix[SIDE_LEFT][BACK_LEFT] = aluSqrt(0.5);
343 Context->ChannelMatrix[SIDE_RIGHT][FRONT_RIGHT] = aluSqrt(0.5);
344 Context->ChannelMatrix[SIDE_RIGHT][BACK_RIGHT] = aluSqrt(0.5);
345 Context->ChannelMatrix[BACK_CENTER][BACK_LEFT] = aluSqrt(0.5);
346 Context->ChannelMatrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5);
347 Context->NumChan = 4;
348 Speaker2Chan[0] = BACK_LEFT;
349 Speaker2Chan[1] = FRONT_LEFT;
350 Speaker2Chan[2] = FRONT_RIGHT;
351 Speaker2Chan[3] = BACK_RIGHT;
352 SpeakerAngle[0] = -135.0f * M_PI/180.0f;
353 SpeakerAngle[1] = -45.0f * M_PI/180.0f;
354 SpeakerAngle[2] = 45.0f * M_PI/180.0f;
355 SpeakerAngle[3] = 135.0f * M_PI/180.0f;
356 SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Context->NumChan);
357 break;
359 case AL_FORMAT_51CHN8:
360 case AL_FORMAT_51CHN16:
361 case AL_FORMAT_51CHN32:
362 Context->ChannelMatrix[SIDE_LEFT][FRONT_LEFT] = aluSqrt(0.5);
363 Context->ChannelMatrix[SIDE_LEFT][BACK_LEFT] = aluSqrt(0.5);
364 Context->ChannelMatrix[SIDE_RIGHT][FRONT_RIGHT] = aluSqrt(0.5);
365 Context->ChannelMatrix[SIDE_RIGHT][BACK_RIGHT] = aluSqrt(0.5);
366 Context->ChannelMatrix[BACK_CENTER][BACK_LEFT] = aluSqrt(0.5);
367 Context->ChannelMatrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5);
368 Context->NumChan = 5;
369 Speaker2Chan[0] = BACK_LEFT;
370 Speaker2Chan[1] = FRONT_LEFT;
371 Speaker2Chan[2] = FRONT_CENTER;
372 Speaker2Chan[3] = FRONT_RIGHT;
373 Speaker2Chan[4] = BACK_RIGHT;
374 SpeakerAngle[0] = -110.0f * M_PI/180.0f;
375 SpeakerAngle[1] = -30.0f * M_PI/180.0f;
376 SpeakerAngle[2] = 0.0f * M_PI/180.0f;
377 SpeakerAngle[3] = 30.0f * M_PI/180.0f;
378 SpeakerAngle[4] = 110.0f * M_PI/180.0f;
379 SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Context->NumChan);
380 break;
382 case AL_FORMAT_61CHN8:
383 case AL_FORMAT_61CHN16:
384 case AL_FORMAT_61CHN32:
385 Context->ChannelMatrix[BACK_LEFT][BACK_CENTER] = aluSqrt(0.5);
386 Context->ChannelMatrix[BACK_LEFT][SIDE_LEFT] = aluSqrt(0.5);
387 Context->ChannelMatrix[BACK_RIGHT][BACK_CENTER] = aluSqrt(0.5);
388 Context->ChannelMatrix[BACK_RIGHT][SIDE_RIGHT] = aluSqrt(0.5);
389 Context->NumChan = 6;
390 Speaker2Chan[0] = SIDE_LEFT;
391 Speaker2Chan[1] = FRONT_LEFT;
392 Speaker2Chan[2] = FRONT_CENTER;
393 Speaker2Chan[3] = FRONT_RIGHT;
394 Speaker2Chan[4] = SIDE_RIGHT;
395 Speaker2Chan[5] = BACK_CENTER;
396 SpeakerAngle[0] = -90.0f * M_PI/180.0f;
397 SpeakerAngle[1] = -30.0f * M_PI/180.0f;
398 SpeakerAngle[2] = 0.0f * M_PI/180.0f;
399 SpeakerAngle[3] = 30.0f * M_PI/180.0f;
400 SpeakerAngle[4] = 90.0f * M_PI/180.0f;
401 SpeakerAngle[5] = 180.0f * M_PI/180.0f;
402 SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Context->NumChan);
403 break;
405 case AL_FORMAT_71CHN8:
406 case AL_FORMAT_71CHN16:
407 case AL_FORMAT_71CHN32:
408 Context->ChannelMatrix[BACK_CENTER][BACK_LEFT] = aluSqrt(0.5);
409 Context->ChannelMatrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5);
410 Context->NumChan = 7;
411 Speaker2Chan[0] = BACK_LEFT;
412 Speaker2Chan[1] = SIDE_LEFT;
413 Speaker2Chan[2] = FRONT_LEFT;
414 Speaker2Chan[3] = FRONT_CENTER;
415 Speaker2Chan[4] = FRONT_RIGHT;
416 Speaker2Chan[5] = SIDE_RIGHT;
417 Speaker2Chan[6] = BACK_RIGHT;
418 SpeakerAngle[0] = -150.0f * M_PI/180.0f;
419 SpeakerAngle[1] = -90.0f * M_PI/180.0f;
420 SpeakerAngle[2] = -30.0f * M_PI/180.0f;
421 SpeakerAngle[3] = 0.0f * M_PI/180.0f;
422 SpeakerAngle[4] = 30.0f * M_PI/180.0f;
423 SpeakerAngle[5] = 90.0f * M_PI/180.0f;
424 SpeakerAngle[6] = 150.0f * M_PI/180.0f;
425 SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Context->NumChan);
426 break;
428 default:
429 assert(0);
432 for(pos = 0; pos < LUT_NUM; pos++)
434 /* source angle */
435 Theta = aluLUTpos2Angle(pos);
437 /* clear all values */
438 offset = OUTPUTCHANNELS * pos;
439 for(s = 0; s < OUTPUTCHANNELS; s++)
440 Context->PanningLUT[offset+s] = 0.0f;
442 /* set panning values */
443 for(s = 0; s < Context->NumChan - 1; s++)
445 if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1])
447 /* source between speaker s and speaker s+1 */
448 Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) /
449 (SpeakerAngle[s+1]-SpeakerAngle[s]);
450 Context->PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha);
451 Context->PanningLUT[offset + Speaker2Chan[s+1]] = sin(Alpha);
452 break;
455 if(s == Context->NumChan - 1)
457 /* source between last and first speaker */
458 if(Theta < SpeakerAngle[0])
459 Theta += 2.0f * M_PI;
460 Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) /
461 (2.0f * M_PI + SpeakerAngle[0]-SpeakerAngle[s]);
462 Context->PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha);
463 Context->PanningLUT[offset + Speaker2Chan[0]] = sin(Alpha);
468 static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im)
470 ALint pos = 0;
471 ALfloat denom = aluFabs(re) + aluFabs(im);
472 if(denom > 0.0f)
473 pos = (ALint)(QUADRANT_NUM*aluFabs(im) / denom + 0.5);
475 if(re < 0.0)
476 pos = 2 * QUADRANT_NUM - pos;
477 if(im < 0.0)
478 pos = LUT_NUM - pos;
479 return pos%LUT_NUM;
482 static ALvoid CalcSourceParams(const ALCcontext *ALContext,
483 const ALsource *ALSource, ALenum isMono,
484 ALfloat *drysend, ALfloat *wetsend,
485 ALfloat *pitch, ALfloat *drygainhf,
486 ALfloat *wetgainhf)
488 ALfloat InnerAngle,OuterAngle,Angle,Distance,DryMix;
489 ALfloat Direction[3],Position[3],SourceToListener[3];
490 ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff,OuterGainHF;
491 ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain;
492 ALfloat U[3],V[3],N[3];
493 ALfloat DopplerFactor, DopplerVelocity, flSpeedOfSound, flMaxVelocity;
494 ALfloat Matrix[3][3];
495 ALfloat flAttenuation;
496 ALfloat RoomAttenuation[MAX_SENDS];
497 ALfloat MetersPerUnit;
498 ALfloat RoomRolloff[MAX_SENDS];
499 ALfloat DryGainHF = 1.0f;
500 ALfloat DirGain, AmbientGain;
501 ALfloat length;
502 const ALfloat *SpeakerGain;
503 ALint NumSends;
504 ALint pos, s, i;
506 //Get context properties
507 DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
508 DopplerVelocity = ALContext->DopplerVelocity;
509 flSpeedOfSound = ALContext->flSpeedOfSound;
510 NumSends = ALContext->NumSends;
512 //Get listener properties
513 ListenerGain = ALContext->Listener.Gain;
514 MetersPerUnit = ALContext->Listener.MetersPerUnit;
516 //Get source properties
517 SourceVolume = ALSource->flGain;
518 memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition));
519 memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation));
520 MinVolume = ALSource->flMinGain;
521 MaxVolume = ALSource->flMaxGain;
522 MinDist = ALSource->flRefDistance;
523 MaxDist = ALSource->flMaxDistance;
524 Rolloff = ALSource->flRollOffFactor;
525 InnerAngle = ALSource->flInnerAngle;
526 OuterAngle = ALSource->flOuterAngle;
527 OuterGainHF = ALSource->OuterGainHF;
529 //Only apply 3D calculations for mono buffers
530 if(isMono != AL_FALSE)
532 //1. Translate Listener to origin (convert to head relative)
533 // Note that Direction and SourceToListener are *not* transformed.
534 // SourceToListener is used with the source and listener velocities,
535 // which are untransformed, and Direction is used with SourceToListener
536 // for the sound cone
537 if(ALSource->bHeadRelative==AL_FALSE)
539 // Build transform matrix
540 aluCrossproduct(ALContext->Listener.Forward, ALContext->Listener.Up, U); // Right-vector
541 aluNormalize(U); // Normalized Right-vector
542 memcpy(V, ALContext->Listener.Up, sizeof(V)); // Up-vector
543 aluNormalize(V); // Normalized Up-vector
544 memcpy(N, ALContext->Listener.Forward, sizeof(N)); // At-vector
545 aluNormalize(N); // Normalized At-vector
546 Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0];
547 Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1];
548 Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
550 // Translate source position into listener space
551 Position[0] -= ALContext->Listener.Position[0];
552 Position[1] -= ALContext->Listener.Position[1];
553 Position[2] -= ALContext->Listener.Position[2];
555 SourceToListener[0] = -Position[0];
556 SourceToListener[1] = -Position[1];
557 SourceToListener[2] = -Position[2];
559 // Transform source position into listener space
560 aluMatrixVector(Position, Matrix);
562 else
564 SourceToListener[0] = -Position[0];
565 SourceToListener[1] = -Position[1];
566 SourceToListener[2] = -Position[2];
568 aluNormalize(SourceToListener);
569 aluNormalize(Direction);
571 //2. Calculate distance attenuation
572 Distance = aluSqrt(aluDotproduct(Position, Position));
574 flAttenuation = 1.0f;
575 for(i = 0;i < MAX_SENDS;i++)
577 RoomAttenuation[i] = 1.0f;
579 RoomRolloff[i] = ALSource->RoomRolloffFactor;
580 if(ALSource->Send[i].Slot &&
581 ALSource->Send[i].Slot->effect.type == AL_EFFECT_REVERB)
582 RoomRolloff[i] += ALSource->Send[i].Slot->effect.Reverb.RoomRolloffFactor;
585 switch (ALSource->DistanceModel)
587 case AL_INVERSE_DISTANCE_CLAMPED:
588 Distance=__max(Distance,MinDist);
589 Distance=__min(Distance,MaxDist);
590 if (MaxDist < MinDist)
591 break;
592 //fall-through
593 case AL_INVERSE_DISTANCE:
594 if (MinDist > 0.0f)
596 if ((MinDist + (Rolloff * (Distance - MinDist))) > 0.0f)
597 flAttenuation = MinDist / (MinDist + (Rolloff * (Distance - MinDist)));
598 for(i = 0;i < NumSends;i++)
600 if ((MinDist + (RoomRolloff[i] * (Distance - MinDist))) > 0.0f)
601 RoomAttenuation[i] = MinDist / (MinDist + (RoomRolloff[i] * (Distance - MinDist)));
604 break;
606 case AL_LINEAR_DISTANCE_CLAMPED:
607 Distance=__max(Distance,MinDist);
608 Distance=__min(Distance,MaxDist);
609 if (MaxDist < MinDist)
610 break;
611 //fall-through
612 case AL_LINEAR_DISTANCE:
613 Distance=__min(Distance,MaxDist);
614 if (MaxDist != MinDist)
616 flAttenuation = 1.0f - (Rolloff*(Distance-MinDist)/(MaxDist - MinDist));
617 for(i = 0;i < NumSends;i++)
618 RoomAttenuation[i] = 1.0f - (RoomRolloff[i]*(Distance-MinDist)/(MaxDist - MinDist));
620 break;
622 case AL_EXPONENT_DISTANCE_CLAMPED:
623 Distance=__max(Distance,MinDist);
624 Distance=__min(Distance,MaxDist);
625 if (MaxDist < MinDist)
626 break;
627 //fall-through
628 case AL_EXPONENT_DISTANCE:
629 if ((Distance > 0.0f) && (MinDist > 0.0f))
631 flAttenuation = (ALfloat)pow(Distance/MinDist, -Rolloff);
632 for(i = 0;i < NumSends;i++)
633 RoomAttenuation[i] = (ALfloat)pow(Distance/MinDist, -RoomRolloff[i]);
635 break;
637 case AL_NONE:
638 break;
641 // Source Gain + Attenuation and clamp to Min/Max Gain
642 DryMix = SourceVolume * flAttenuation;
643 DryMix = __min(DryMix,MaxVolume);
644 DryMix = __max(DryMix,MinVolume);
646 for(i = 0;i < NumSends;i++)
648 ALfloat WetMix = SourceVolume * RoomAttenuation[i];
649 WetMix = __min(WetMix,MaxVolume);
650 wetsend[i] = __max(WetMix,MinVolume);
651 wetgainhf[i] = 1.0f;
654 // Distance-based air absorption
655 if(ALSource->AirAbsorptionFactor > 0.0f && ALSource->DistanceModel != AL_NONE)
657 ALfloat dist = Distance-MinDist;
658 ALfloat absorb;
660 if(dist < 0.0f) dist = 0.0f;
661 // Absorption calculation is done in dB
662 absorb = (ALSource->AirAbsorptionFactor*AIRABSORBGAINDBHF) *
663 (dist*MetersPerUnit);
664 // Convert dB to linear gain before applying
665 absorb = pow(10.0, absorb/20.0);
666 DryGainHF *= absorb;
667 for(i = 0;i < MAX_SENDS;i++)
668 wetgainhf[i] *= absorb;
671 //3. Apply directional soundcones
672 Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * 180.0f/M_PI;
673 if(Angle >= InnerAngle && Angle <= OuterAngle)
675 ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
676 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f)*scale);
677 ConeHF = (1.0f+(OuterGainHF-1.0f)*scale);
678 DryMix *= ConeVolume;
679 if(ALSource->DryGainHFAuto)
680 DryGainHF *= ConeHF;
682 else if(Angle > OuterAngle)
684 ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f));
685 ConeHF = (1.0f+(OuterGainHF-1.0f));
686 DryMix *= ConeVolume;
687 if(ALSource->DryGainHFAuto)
688 DryGainHF *= ConeHF;
690 else
692 ConeVolume = 1.0f;
693 ConeHF = 1.0f;
696 //4. Calculate Velocity
697 if(DopplerFactor != 0.0f)
699 ALfloat flVSS, flVLS = 0.0f;
701 if(ALSource->bHeadRelative==AL_FALSE)
702 flVLS = aluDotproduct(ALContext->Listener.Velocity, SourceToListener);
703 flVSS = aluDotproduct(ALSource->vVelocity, SourceToListener);
705 flMaxVelocity = (DopplerVelocity * flSpeedOfSound) / DopplerFactor;
707 if (flVSS >= flMaxVelocity)
708 flVSS = (flMaxVelocity - 1.0f);
709 else if (flVSS <= -flMaxVelocity)
710 flVSS = -flMaxVelocity + 1.0f;
712 if (flVLS >= flMaxVelocity)
713 flVLS = (flMaxVelocity - 1.0f);
714 else if (flVLS <= -flMaxVelocity)
715 flVLS = -flMaxVelocity + 1.0f;
717 pitch[0] = ALSource->flPitch *
718 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVLS)) /
719 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVSS));
721 else
722 pitch[0] = ALSource->flPitch;
724 for(i = 0;i < NumSends;i++)
726 if(ALSource->Send[i].Slot &&
727 ALSource->Send[i].Slot->effect.type != AL_EFFECT_NULL)
729 if(ALSource->WetGainAuto)
730 wetsend[i] *= ConeVolume;
731 if(ALSource->WetGainHFAuto)
732 wetgainhf[i] *= ConeHF;
734 if(ALSource->Send[i].Slot->AuxSendAuto)
736 // Apply minimal attenuation in place of missing
737 // statistical reverb model.
738 wetsend[i] *= pow(DryMix, 1.0f / 2.0f);
740 else
742 // If the slot's auxilliary send auto is off, the data sent to the
743 // effect slot is the same as the dry path, sans filter effects
744 wetsend[i] = DryMix;
745 wetgainhf[i] = DryGainHF;
748 // Note that this is really applied by the effect slot. However,
749 // it's easier (more optimal) to handle it here.
750 if(ALSource->Send[i].Slot->effect.type == AL_EFFECT_REVERB)
751 wetgainhf[i] *= ALSource->Send[0].Slot->effect.Reverb.GainHF;
753 switch(ALSource->Send[i].WetFilter.type)
755 case AL_FILTER_LOWPASS:
756 wetsend[i] *= ALSource->Send[i].WetFilter.Gain;
757 wetgainhf[i] *= ALSource->Send[i].WetFilter.GainHF;
758 break;
760 wetsend[i] *= ListenerGain;
762 else
764 wetsend[i] = 0.0f;
765 wetgainhf[i] = 1.0f;
768 for(i = NumSends;i < MAX_SENDS;i++)
770 wetsend[i] = 0.0f;
771 wetgainhf[i] = 1.0f;
774 //5. Apply filter gains and filters
775 switch(ALSource->DirectFilter.type)
777 case AL_FILTER_LOWPASS:
778 DryMix *= ALSource->DirectFilter.Gain;
779 DryGainHF *= ALSource->DirectFilter.GainHF;
780 break;
782 DryMix *= ListenerGain;
784 // Use energy-preserving panning algorithm for multi-speaker playback
785 length = aluSqrt(Position[0]*Position[0] + Position[1]*Position[1] +
786 Position[2]*Position[2]);
787 length = __max(length, MinDist);
788 if(length > 0.0f)
790 ALfloat invlen = 1.0f/length;
791 Position[0] *= invlen;
792 Position[1] *= invlen;
793 Position[2] *= invlen;
796 pos = aluCart2LUTpos(-Position[2], Position[0]);
797 SpeakerGain = &ALContext->PanningLUT[OUTPUTCHANNELS * pos];
799 DirGain = aluSqrt(Position[0]*Position[0] + Position[2]*Position[2]);
800 // elevation adjustment for directional gain. this sucks, but
801 // has low complexity
802 AmbientGain = 1.0/aluSqrt(ALContext->NumChan) * (1.0-DirGain);
803 for(s = 0; s < OUTPUTCHANNELS; s++)
805 ALfloat gain = SpeakerGain[s]*DirGain + AmbientGain;
806 drysend[s] = DryMix * gain;
808 *drygainhf = DryGainHF;
810 else
812 //1. Multi-channel buffers always play "normal"
813 pitch[0] = ALSource->flPitch;
815 DryMix = SourceVolume;
816 DryMix = __min(DryMix,MaxVolume);
817 DryMix = __max(DryMix,MinVolume);
819 switch(ALSource->DirectFilter.type)
821 case AL_FILTER_LOWPASS:
822 DryMix *= ALSource->DirectFilter.Gain;
823 DryGainHF *= ALSource->DirectFilter.GainHF;
824 break;
827 drysend[FRONT_LEFT] = DryMix * ListenerGain;
828 drysend[FRONT_RIGHT] = DryMix * ListenerGain;
829 drysend[SIDE_LEFT] = DryMix * ListenerGain;
830 drysend[SIDE_RIGHT] = DryMix * ListenerGain;
831 drysend[BACK_LEFT] = DryMix * ListenerGain;
832 drysend[BACK_RIGHT] = DryMix * ListenerGain;
833 drysend[FRONT_CENTER] = DryMix * ListenerGain;
834 drysend[BACK_CENTER] = DryMix * ListenerGain;
835 drysend[LFE] = DryMix * ListenerGain;
836 *drygainhf = DryGainHF;
838 for(i = 0;i < MAX_SENDS;i++)
840 wetsend[i] = 0.0f;
841 wetgainhf[i] = 1.0f;
846 static __inline ALshort lerp(ALshort val1, ALshort val2, ALint frac)
848 return val1 + (((val2-val1)*frac)>>FRACTIONBITS);
851 ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
853 static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
854 static float DummyBuffer[BUFFERSIZE];
855 ALfloat *WetBuffer[MAX_SENDS];
856 ALfloat (*Matrix)[OUTPUTCHANNELS] = ALContext->ChannelMatrix;
857 ALfloat newDrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
858 ALfloat newWetSend[MAX_SENDS];
859 ALfloat DryGainHF = 0.0f;
860 ALfloat WetGainHF[MAX_SENDS];
861 ALfloat *DrySend;
862 ALfloat *WetSend;
863 ALuint rampLength;
864 ALfloat dryGainStep[OUTPUTCHANNELS];
865 ALfloat wetGainStep[MAX_SENDS];
866 ALuint BlockAlign,BufferSize;
867 ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
868 ALuint Channels,Frequency,ulExtraSamples;
869 ALfloat Pitch;
870 ALint Looping,State;
871 ALint increment;
872 ALuint Buffer;
873 ALuint SamplesToDo;
874 ALsource *ALSource;
875 ALbuffer *ALBuffer;
876 ALeffectslot *ALEffectSlot;
877 ALfloat values[OUTPUTCHANNELS];
878 ALfloat value;
879 ALshort *Data;
880 ALuint i,j,k,out;
881 ALfloat cw, a, g;
882 ALbufferlistitem *BufferListItem;
883 ALuint loop;
884 ALint64 DataSize64,DataPos64;
885 FILTER *DryFilter, *WetFilter[MAX_SENDS];
886 int fpuState;
888 SuspendContext(ALContext);
890 #if defined(HAVE_FESETROUND)
891 fpuState = fegetround();
892 fesetround(FE_TOWARDZERO);
893 #elif defined(HAVE__CONTROLFP)
894 fpuState = _controlfp(0, 0);
895 _controlfp(_RC_CHOP, _MCW_RC);
896 #else
897 (void)fpuState;
898 #endif
900 //Figure output format variables
901 BlockAlign = aluChannelsFromFormat(format);
902 BlockAlign *= aluBytesFromFormat(format);
904 size /= BlockAlign;
905 while(size > 0)
907 //Setup variables
908 SamplesToDo = min(size, BUFFERSIZE);
909 if(ALContext)
911 ALEffectSlot = ALContext->AuxiliaryEffectSlot;
912 ALSource = ALContext->Source;
913 rampLength = ALContext->Frequency * MIN_RAMP_LENGTH / 1000;
915 else
917 ALEffectSlot = NULL;
918 ALSource = NULL;
919 rampLength = 0;
921 rampLength = max(rampLength, SamplesToDo);
923 //Clear mixing buffer
924 memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
926 //Actual mixing loop
927 while(ALSource)
929 j = 0;
930 State = ALSource->state;
932 while(State == AL_PLAYING && j < SamplesToDo)
934 DataSize = 0;
935 DataPosInt = 0;
936 DataPosFrac = 0;
938 //Get buffer info
939 if((Buffer = ALSource->ulBufferID))
941 ALBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(Buffer);
943 Data = ALBuffer->data;
944 Channels = aluChannelsFromFormat(ALBuffer->format);
945 DataSize = ALBuffer->size;
946 DataSize /= Channels * aluBytesFromFormat(ALBuffer->format);
947 Frequency = ALBuffer->frequency;
948 DataPosInt = ALSource->position;
949 DataPosFrac = ALSource->position_fraction;
951 if(DataPosInt >= DataSize)
952 goto skipmix;
954 //Get source info
955 DryFilter = &ALSource->iirFilter;
956 for(i = 0;i < MAX_SENDS;i++)
958 WetFilter[i] = &ALSource->Send[i].iirFilter;
959 WetBuffer[i] = (ALSource->Send[i].Slot ?
960 ALSource->Send[i].Slot->WetBuffer :
961 DummyBuffer);
963 DrySend = ALSource->DryGains;
964 WetSend = ALSource->WetGains;
966 CalcSourceParams(ALContext, ALSource,
967 (Channels==1) ? AL_TRUE : AL_FALSE,
968 newDrySend, newWetSend, &Pitch,
969 &DryGainHF, WetGainHF);
970 Pitch = (Pitch*Frequency) / ALContext->Frequency;
972 if(Channels == 1)
974 // Update filter coefficients. Calculations based on
975 // the I3DL2 spec.
976 cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / ALContext->Frequency);
977 // We use four chained one-pole filters, so we need to
978 // take the fourth root of the squared gain, which is
979 // the same as the square root of the base gain.
980 // Be careful with gains < 0.0001, as that causes the
981 // coefficient to head towards 1, which will flatten
982 // the signal
983 g = aluSqrt(__max(DryGainHF, 0.0001f));
984 a = 0.0f;
985 if(g < 0.9999f) // 1-epsilon
986 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
987 DryFilter->coeff = a;
989 for(i = 0;i < MAX_SENDS;i++)
991 // The wet path uses two chained one-pole filters,
992 // so take the base gain (square root of the
993 // squared gain)
994 g = __max(WetGainHF[i], 0.01f);
995 a = 0.0f;
996 if(g < 0.9999f) // 1-epsilon
997 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
998 WetFilter[i]->coeff = a;
1001 else
1003 // Multi-channel sources use two chained one-pole
1004 // filters
1005 cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / ALContext->Frequency);
1006 g = __max(DryGainHF, 0.01f);
1007 a = 0.0f;
1008 if(g < 0.9999f) // 1-epsilon
1009 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
1010 DryFilter->coeff = a;
1011 for(i = 0;i < MAX_SENDS;i++)
1012 WetFilter[i]->coeff = 0.0f;
1014 if(DuplicateStereo && Channels == 2)
1016 Matrix[FRONT_LEFT][SIDE_LEFT] = 1.0f;
1017 Matrix[FRONT_RIGHT][SIDE_RIGHT] = 1.0f;
1018 Matrix[FRONT_LEFT][BACK_LEFT] = 1.0f;
1019 Matrix[FRONT_RIGHT][BACK_RIGHT] = 1.0f;
1021 else if(DuplicateStereo)
1023 Matrix[FRONT_LEFT][SIDE_LEFT] = 0.0f;
1024 Matrix[FRONT_RIGHT][SIDE_RIGHT] = 0.0f;
1025 Matrix[FRONT_LEFT][BACK_LEFT] = 0.0f;
1026 Matrix[FRONT_RIGHT][BACK_RIGHT] = 0.0f;
1030 //Compute the gain steps for each output channel
1031 if(ALSource->FirstStart && DataPosInt == 0 && DataPosFrac == 0)
1033 for(i = 0;i < OUTPUTCHANNELS;i++)
1035 DrySend[i] = newDrySend[i];
1036 dryGainStep[i] = 0;
1038 for(i = 0;i < MAX_SENDS;i++)
1040 WetSend[i] = newWetSend[i];
1041 wetGainStep[i] = 0;
1044 else
1046 for(i = 0;i < OUTPUTCHANNELS;i++)
1047 dryGainStep[i] = (newDrySend[i]-DrySend[i]) / rampLength;
1048 for(i = 0;i < MAX_SENDS;i++)
1049 wetGainStep[i] = (newWetSend[i]-WetSend[i]) / rampLength;
1051 ALSource->FirstStart = AL_FALSE;
1053 //Compute 18.14 fixed point step
1054 if(Pitch > (float)MAX_PITCH)
1055 Pitch = (float)MAX_PITCH;
1056 increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS));
1057 if(increment <= 0)
1058 increment = (1<<FRACTIONBITS);
1060 //Figure out how many samples we can mix.
1061 DataSize64 = DataSize;
1062 DataSize64 <<= FRACTIONBITS;
1063 DataPos64 = DataPosInt;
1064 DataPos64 <<= FRACTIONBITS;
1065 DataPos64 += DataPosFrac;
1066 BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
1068 BufferListItem = ALSource->queue;
1069 for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
1071 if(BufferListItem)
1072 BufferListItem = BufferListItem->next;
1074 if (BufferListItem)
1076 if (BufferListItem->next)
1078 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer);
1079 if(NextBuf && NextBuf->data)
1081 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
1082 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
1085 else if (ALSource->bLooping)
1087 ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer);
1088 if (NextBuf && NextBuf->data)
1090 ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
1091 memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
1094 else
1095 memset(&Data[DataSize*Channels], 0, (ALBuffer->padding*Channels*2));
1097 BufferSize = min(BufferSize, (SamplesToDo-j));
1099 //Actual sample mixing loop
1100 k = 0;
1101 Data += DataPosInt*Channels;
1103 if(Channels == 1) /* Mono */
1105 ALfloat outsamp;
1107 while(BufferSize--)
1109 for(i = 0;i < OUTPUTCHANNELS;i++)
1110 DrySend[i] += dryGainStep[i];
1111 for(i = 0;i < MAX_SENDS;i++)
1112 WetSend[i] += wetGainStep[i];
1114 //First order interpolator
1115 value = lerp(Data[k], Data[k+1], DataPosFrac);
1117 //Direct path final mix buffer and panning
1118 outsamp = lpFilter4P(DryFilter, 0, value);
1119 DryBuffer[j][FRONT_LEFT] += outsamp*DrySend[FRONT_LEFT];
1120 DryBuffer[j][FRONT_RIGHT] += outsamp*DrySend[FRONT_RIGHT];
1121 DryBuffer[j][SIDE_LEFT] += outsamp*DrySend[SIDE_LEFT];
1122 DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT];
1123 DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT];
1124 DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT];
1125 DryBuffer[j][FRONT_CENTER] += outsamp*DrySend[FRONT_CENTER];
1126 DryBuffer[j][BACK_CENTER] += outsamp*DrySend[BACK_CENTER];
1128 //Room path final mix buffer and panning
1129 for(i = 0;i < MAX_SENDS;i++)
1131 outsamp = lpFilter2P(WetFilter[i], 0, value);
1132 WetBuffer[i][j] += outsamp*WetSend[i];
1135 DataPosFrac += increment;
1136 k += DataPosFrac>>FRACTIONBITS;
1137 DataPosFrac &= FRACTIONMASK;
1138 j++;
1141 else if(Channels == 2) /* Stereo */
1143 const int chans[] = {
1144 FRONT_LEFT, FRONT_RIGHT
1147 #define DO_MIX() do { \
1148 for(i = 0;i < MAX_SENDS;i++) \
1149 WetSend[i] += wetGainStep[i]*BufferSize; \
1150 while(BufferSize--) \
1152 for(i = 0;i < OUTPUTCHANNELS;i++) \
1153 DrySend[i] += dryGainStep[i]; \
1155 for(i = 0;i < Channels;i++) \
1157 value = lerp(Data[k*Channels + i], Data[(k+1)*Channels + i], DataPosFrac); \
1158 values[i] = lpFilter2P(DryFilter, chans[i]*2, value)*DrySend[chans[i]]; \
1160 for(out = 0;out < OUTPUTCHANNELS;out++) \
1162 ALfloat sum = 0.0f; \
1163 for(i = 0;i < Channels;i++) \
1164 sum += values[i]*Matrix[chans[i]][out]; \
1165 DryBuffer[j][out] += sum; \
1168 DataPosFrac += increment; \
1169 k += DataPosFrac>>FRACTIONBITS; \
1170 DataPosFrac &= FRACTIONMASK; \
1171 j++; \
1173 } while(0)
1175 DO_MIX();
1177 else if(Channels == 4) /* Quad */
1179 const int chans[] = {
1180 FRONT_LEFT, FRONT_RIGHT,
1181 BACK_LEFT, BACK_RIGHT
1184 DO_MIX();
1186 else if(Channels == 6) /* 5.1 */
1188 const int chans[] = {
1189 FRONT_LEFT, FRONT_RIGHT,
1190 FRONT_CENTER, LFE,
1191 BACK_LEFT, BACK_RIGHT
1194 DO_MIX();
1196 else if(Channels == 7) /* 6.1 */
1198 const int chans[] = {
1199 FRONT_LEFT, FRONT_RIGHT,
1200 FRONT_CENTER, LFE,
1201 BACK_CENTER,
1202 SIDE_LEFT, SIDE_RIGHT
1205 DO_MIX();
1207 else if(Channels == 8) /* 7.1 */
1209 const int chans[] = {
1210 FRONT_LEFT, FRONT_RIGHT,
1211 FRONT_CENTER, LFE,
1212 BACK_LEFT, BACK_RIGHT,
1213 SIDE_LEFT, SIDE_RIGHT
1216 DO_MIX();
1217 #undef DO_MIX
1219 else /* Unknown? */
1221 for(i = 0;i < OUTPUTCHANNELS;i++)
1222 DrySend[i] += dryGainStep[i]*BufferSize;
1223 for(i = 0;i < MAX_SENDS;i++)
1224 WetSend[i] += wetGainStep[i]*BufferSize;
1225 while(BufferSize--)
1227 DataPosFrac += increment;
1228 k += DataPosFrac>>FRACTIONBITS;
1229 DataPosFrac &= FRACTIONMASK;
1230 j++;
1233 DataPosInt += k;
1235 //Update source info
1236 ALSource->position = DataPosInt;
1237 ALSource->position_fraction = DataPosFrac;
1239 skipmix: ;
1242 //Handle looping sources
1243 if(!Buffer || DataPosInt >= DataSize)
1245 //queueing
1246 if(ALSource->queue)
1248 Looping = ALSource->bLooping;
1249 if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
1251 BufferListItem = ALSource->queue;
1252 for(loop = 0; loop <= ALSource->BuffersPlayed; loop++)
1254 if(BufferListItem)
1256 if(!Looping)
1257 BufferListItem->bufferstate = PROCESSED;
1258 BufferListItem = BufferListItem->next;
1261 if(BufferListItem)
1262 ALSource->ulBufferID = BufferListItem->buffer;
1263 ALSource->position = DataPosInt-DataSize;
1264 ALSource->position_fraction = DataPosFrac;
1265 ALSource->BuffersPlayed++;
1267 else
1269 if(!Looping)
1271 /* alSourceStop */
1272 ALSource->state = AL_STOPPED;
1273 ALSource->inuse = AL_FALSE;
1274 ALSource->BuffersPlayed = ALSource->BuffersInQueue;
1275 BufferListItem = ALSource->queue;
1276 while(BufferListItem != NULL)
1278 BufferListItem->bufferstate = PROCESSED;
1279 BufferListItem = BufferListItem->next;
1281 ALSource->position = DataSize;
1282 ALSource->position_fraction = 0;
1284 else
1286 /* alSourceRewind */
1287 /* alSourcePlay */
1288 ALSource->state = AL_PLAYING;
1289 ALSource->inuse = AL_TRUE;
1290 ALSource->play = AL_TRUE;
1291 ALSource->BuffersPlayed = 0;
1292 BufferListItem = ALSource->queue;
1293 while(BufferListItem != NULL)
1295 BufferListItem->bufferstate = PENDING;
1296 BufferListItem = BufferListItem->next;
1298 ALSource->ulBufferID = ALSource->queue->buffer;
1300 if(ALSource->BuffersInQueue == 1)
1301 ALSource->position = DataPosInt%DataSize;
1302 else
1303 ALSource->position = DataPosInt-DataSize;
1304 ALSource->position_fraction = DataPosFrac;
1310 //Get source state
1311 State = ALSource->state;
1314 ALSource = ALSource->next;
1317 // effect slot processing
1318 while(ALEffectSlot)
1320 if(ALEffectSlot->effect.type == AL_EFFECT_REVERB)
1321 VerbProcess(ALEffectSlot->ReverbState, SamplesToDo, ALEffectSlot->WetBuffer, DryBuffer);
1322 else if(ALEffectSlot->effect.type == AL_EFFECT_ECHO)
1323 EchoProcess(ALEffectSlot->EchoState, SamplesToDo, ALEffectSlot->WetBuffer, DryBuffer);
1325 for(i = 0;i < SamplesToDo;i++)
1326 ALEffectSlot->WetBuffer[i] = 0.0f;
1327 ALEffectSlot = ALEffectSlot->next;
1330 //Post processing loop
1331 switch(format)
1333 case AL_FORMAT_MONO8:
1334 for(i = 0;i < SamplesToDo;i++)
1336 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT])>>8)+128);
1337 buffer = ((ALubyte*)buffer) + 1;
1339 break;
1340 case AL_FORMAT_STEREO8:
1341 if(ALContext && ALContext->bs2b)
1343 for(i = 0;i < SamplesToDo;i++)
1345 float samples[2];
1346 samples[0] = DryBuffer[i][FRONT_LEFT];
1347 samples[1] = DryBuffer[i][FRONT_RIGHT];
1348 bs2b_cross_feed(ALContext->bs2b, samples);
1349 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(samples[0])>>8)+128);
1350 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(samples[1])>>8)+128);
1351 buffer = ((ALubyte*)buffer) + 2;
1354 else
1356 for(i = 0;i < SamplesToDo;i++)
1358 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1359 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1360 buffer = ((ALubyte*)buffer) + 2;
1363 break;
1364 case AL_FORMAT_QUAD8:
1365 for(i = 0;i < SamplesToDo;i++)
1367 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1368 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1369 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1370 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1371 buffer = ((ALubyte*)buffer) + 4;
1373 break;
1374 case AL_FORMAT_51CHN8:
1375 for(i = 0;i < SamplesToDo;i++)
1377 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1378 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1379 #ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
1380 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_CENTER])>>8)+128);
1381 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1382 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1383 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1384 #else
1385 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1386 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1387 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_CENTER])>>8)+128);
1388 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1389 #endif
1390 buffer = ((ALubyte*)buffer) + 6;
1392 break;
1393 case AL_FORMAT_61CHN8:
1394 for(i = 0;i < SamplesToDo;i++)
1396 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1397 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1398 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_CENTER])>>8)+128);
1399 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1400 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_CENTER])>>8)+128);
1401 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT])>>8)+128);
1402 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT])>>8)+128);
1403 buffer = ((ALubyte*)buffer) + 7;
1405 break;
1406 case AL_FORMAT_71CHN8:
1407 for(i = 0;i < SamplesToDo;i++)
1409 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT])>>8)+128);
1410 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT])>>8)+128);
1411 #ifdef _WIN32
1412 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_CENTER])>>8)+128);
1413 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1414 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1415 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1416 #else
1417 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT])>>8)+128);
1418 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT])>>8)+128);
1419 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_CENTER])>>8)+128);
1420 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE])>>8)+128);
1421 #endif
1422 ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT])>>8)+128);
1423 ((ALubyte*)buffer)[7] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT])>>8)+128);
1424 buffer = ((ALubyte*)buffer) + 8;
1426 break;
1428 case AL_FORMAT_MONO16:
1429 for(i = 0;i < SamplesToDo;i++)
1431 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]);
1432 buffer = ((ALshort*)buffer) + 1;
1434 break;
1435 case AL_FORMAT_STEREO16:
1436 if(ALContext && ALContext->bs2b)
1438 for(i = 0;i < SamplesToDo;i++)
1440 float samples[2];
1441 samples[0] = DryBuffer[i][FRONT_LEFT];
1442 samples[1] = DryBuffer[i][FRONT_RIGHT];
1443 bs2b_cross_feed(ALContext->bs2b, samples);
1444 ((ALshort*)buffer)[0] = aluF2S(samples[0]);
1445 ((ALshort*)buffer)[1] = aluF2S(samples[1]);
1446 buffer = ((ALshort*)buffer) + 2;
1449 else
1451 for(i = 0;i < SamplesToDo;i++)
1453 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1454 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1455 buffer = ((ALshort*)buffer) + 2;
1458 break;
1459 case AL_FORMAT_QUAD16:
1460 for(i = 0;i < SamplesToDo;i++)
1462 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1463 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1464 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT]);
1465 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1466 buffer = ((ALshort*)buffer) + 4;
1468 break;
1469 case AL_FORMAT_51CHN16:
1470 for(i = 0;i < SamplesToDo;i++)
1472 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1473 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1474 #ifdef _WIN32
1475 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][FRONT_CENTER]);
1476 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE]);
1477 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT]);
1478 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1479 #else
1480 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT]);
1481 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1482 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][FRONT_CENTER]);
1483 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE]);
1484 #endif
1485 buffer = ((ALshort*)buffer) + 6;
1487 break;
1488 case AL_FORMAT_61CHN16:
1489 for(i = 0;i < SamplesToDo;i++)
1491 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1492 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1493 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][FRONT_CENTER]);
1494 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE]);
1495 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_CENTER]);
1496 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][SIDE_LEFT]);
1497 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_RIGHT]);
1498 buffer = ((ALshort*)buffer) + 7;
1500 break;
1501 case AL_FORMAT_71CHN16:
1502 for(i = 0;i < SamplesToDo;i++)
1504 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]);
1505 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]);
1506 #ifdef _WIN32
1507 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][FRONT_CENTER]);
1508 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE]);
1509 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT]);
1510 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1511 #else
1512 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT]);
1513 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT]);
1514 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][FRONT_CENTER]);
1515 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE]);
1516 #endif
1517 ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_LEFT]);
1518 ((ALshort*)buffer)[7] = aluF2S(DryBuffer[i][SIDE_RIGHT]);
1519 buffer = ((ALshort*)buffer) + 8;
1521 break;
1523 default:
1524 break;
1527 size -= SamplesToDo;
1530 #if defined(HAVE_FESETROUND)
1531 fesetround(fpuState);
1532 #elif defined(HAVE__CONTROLFP)
1533 _controlfp(fpuState, 0xfffff);
1534 #endif
1536 ProcessContext(ALContext);