Declare a variable where it's used
[openal-soft.git] / Alc / mixer.c
blobe5b48337f0c6753a8a276d0f7cfc362a900d00ce
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 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
29 #include "alMain.h"
30 #include "AL/al.h"
31 #include "AL/alc.h"
32 #include "alSource.h"
33 #include "alBuffer.h"
34 #include "alListener.h"
35 #include "alAuxEffectSlot.h"
36 #include "alu.h"
37 #include "bs2b.h"
40 static __inline ALfloat aluF2F(ALfloat Value)
42 return Value;
45 static __inline ALshort aluF2S(ALfloat Value)
47 ALint i;
49 if(Value <= -1.0f) i = -32768;
50 else if(Value >= 1.0f) i = 32767;
51 else i = (ALint)(Value*32767.0f);
53 return ((ALshort)i);
56 static __inline ALubyte aluF2UB(ALfloat Value)
58 ALshort i = aluF2S(Value);
59 return (i>>8)+128;
63 static __inline ALfloat point32(ALfloat val1, ALfloat val2, ALint frac)
65 return val1;
66 (void)val2;
67 (void)frac;
69 static __inline ALfloat lerp32(ALfloat val1, ALfloat val2, ALint frac)
71 return val1 + ((val2-val1)*(frac * (1.0f/(1<<FRACTIONBITS))));
73 static __inline ALfloat cos_lerp32(ALfloat val1, ALfloat val2, ALint frac)
75 ALfloat mult = (1.0f-cos(frac * (1.0f/(1<<FRACTIONBITS)) * M_PI)) * 0.5f;
76 return val1 + ((val2-val1)*mult);
79 static __inline ALfloat point16(ALfloat val1, ALfloat val2, ALint frac)
81 return val1 / 32767.0f;
82 (void)val2;
83 (void)frac;
85 static __inline ALfloat lerp16(ALfloat val1, ALfloat val2, ALint frac)
87 val1 += ((val2-val1)*(frac * (1.0f/(1<<FRACTIONBITS))));
88 return val1 / 32767.0f;
90 static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
92 ALfloat mult = (1.0f-cos(frac * (1.0f/(1<<FRACTIONBITS)) * M_PI)) * 0.5f;
93 val1 += ((val2-val1)*mult);
94 return val1 / 32767.0f;
98 #define DO_MIX_MONO(S,sampler) do { \
99 ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
100 ALfloat *ClickRemoval, *PendingClicks; \
101 ALuint pos = DataPosInt; \
102 ALuint frac = DataPosFrac; \
103 ALfloat DrySend[OUTPUTCHANNELS]; \
104 FILTER *DryFilter; \
105 ALuint BufferIdx; \
106 ALuint i, out; \
107 ALfloat value; \
109 DryBuffer = Device->DryBuffer; \
110 ClickRemoval = Device->ClickRemoval; \
111 PendingClicks = Device->PendingClicks; \
112 DryFilter = &Source->Params.iirFilter; \
113 for(i = 0;i < OUTPUTCHANNELS;i++) \
114 DrySend[i] = Source->Params.DryGains[i]; \
116 if(j == 0) \
118 value = sampler##S(Data.p##S[pos], Data.p##S[pos+1], frac); \
120 value = lpFilter4PC(DryFilter, 0, value); \
121 ClickRemoval[FRONT_LEFT] -= value*DrySend[FRONT_LEFT]; \
122 ClickRemoval[FRONT_RIGHT] -= value*DrySend[FRONT_RIGHT]; \
123 ClickRemoval[SIDE_LEFT] -= value*DrySend[SIDE_LEFT]; \
124 ClickRemoval[SIDE_RIGHT] -= value*DrySend[SIDE_RIGHT]; \
125 ClickRemoval[BACK_LEFT] -= value*DrySend[BACK_LEFT]; \
126 ClickRemoval[BACK_RIGHT] -= value*DrySend[BACK_RIGHT]; \
127 ClickRemoval[FRONT_CENTER] -= value*DrySend[FRONT_CENTER]; \
128 ClickRemoval[BACK_CENTER] -= value*DrySend[BACK_CENTER]; \
130 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
132 /* First order interpolator */ \
133 value = sampler##S(Data.p##S[pos], Data.p##S[pos+1], frac); \
135 /* Direct path final mix buffer and panning */ \
136 value = lpFilter4P(DryFilter, 0, value); \
137 DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; \
138 DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; \
139 DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT]; \
140 DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; \
141 DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT]; \
142 DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; \
143 DryBuffer[j][FRONT_CENTER] += value*DrySend[FRONT_CENTER]; \
144 DryBuffer[j][BACK_CENTER] += value*DrySend[BACK_CENTER]; \
146 frac += increment; \
147 pos += frac>>FRACTIONBITS; \
148 frac &= FRACTIONMASK; \
149 j++; \
151 if(j == SamplesToDo) \
153 ALuint p = pos; \
154 ALuint f = frac; \
155 if(p >= LoopEnd) \
157 ALuint64 pos64 = pos; \
158 pos64 <<= FRACTIONBITS; \
159 pos64 += frac; \
160 pos64 -= increment; \
161 p = pos64>>FRACTIONBITS; \
162 f = pos64&FRACTIONMASK; \
164 value = sampler##S(Data.p##S[p], Data.p##S[p+1], f); \
166 value = lpFilter4PC(DryFilter, 0, value); \
167 PendingClicks[FRONT_LEFT] += value*DrySend[FRONT_LEFT]; \
168 PendingClicks[FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; \
169 PendingClicks[SIDE_LEFT] += value*DrySend[SIDE_LEFT]; \
170 PendingClicks[SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; \
171 PendingClicks[BACK_LEFT] += value*DrySend[BACK_LEFT]; \
172 PendingClicks[BACK_RIGHT] += value*DrySend[BACK_RIGHT]; \
173 PendingClicks[FRONT_CENTER] += value*DrySend[FRONT_CENTER]; \
174 PendingClicks[BACK_CENTER] += value*DrySend[BACK_CENTER]; \
177 for(out = 0;out < MAX_SENDS;out++) \
179 ALfloat WetSend; \
180 ALfloat *WetBuffer; \
181 ALfloat *WetClickRemoval; \
182 ALfloat *WetPendingClicks; \
183 FILTER *WetFilter; \
185 if(!Source->Send[out].Slot || \
186 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
187 continue; \
189 WetSend = Source->Params.WetGains[out]; \
190 WetBuffer = Source->Send[out].Slot->WetBuffer; \
191 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
192 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
193 WetFilter = &Source->Params.Send[out].iirFilter; \
195 pos = DataPosInt; \
196 frac = DataPosFrac; \
197 j -= BufferSize; \
199 if(j == 0) \
201 value = sampler##S(Data.p##S[pos], Data.p##S[pos+1], frac); \
203 value = lpFilter2PC(WetFilter, 0, value); \
204 WetClickRemoval[0] -= value*WetSend; \
206 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
208 /* First order interpolator */ \
209 value = sampler##S(Data.p##S[pos], Data.p##S[pos+1], frac); \
211 /* Room path final mix buffer and panning */ \
212 value = lpFilter2P(WetFilter, 0, value); \
213 WetBuffer[j] += value*WetSend; \
215 frac += increment; \
216 pos += frac>>FRACTIONBITS; \
217 frac &= FRACTIONMASK; \
218 j++; \
220 if(j == SamplesToDo) \
222 ALuint p = pos; \
223 ALuint f = frac; \
224 if(p >= LoopEnd) \
226 ALuint64 pos64 = pos; \
227 pos64 <<= FRACTIONBITS; \
228 pos64 += frac; \
229 pos64 -= increment; \
230 p = pos64>>FRACTIONBITS; \
231 f = pos64&FRACTIONMASK; \
233 value = sampler##S(Data.p##S[p], Data.p##S[p+1], f); \
235 value = lpFilter2PC(WetFilter, 0, value); \
236 WetPendingClicks[0] += value*WetSend; \
239 DataPosInt = pos; \
240 DataPosFrac = frac; \
241 } while(0)
243 #define DO_MIX_STEREO(S,sampler) do { \
244 const ALfloat scaler = 1.0f/Channels; \
245 ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
246 ALfloat *ClickRemoval, *PendingClicks; \
247 ALuint pos = DataPosInt; \
248 ALuint frac = DataPosFrac; \
249 ALfloat DrySend[OUTPUTCHANNELS]; \
250 FILTER *DryFilter; \
251 ALuint BufferIdx; \
252 ALuint i, out; \
253 ALfloat value; \
255 DryBuffer = Device->DryBuffer; \
256 ClickRemoval = Device->ClickRemoval; \
257 PendingClicks = Device->PendingClicks; \
258 DryFilter = &Source->Params.iirFilter; \
259 for(i = 0;i < OUTPUTCHANNELS;i++) \
260 DrySend[i] = Source->Params.DryGains[i]; \
262 if(j == 0) \
264 for(i = 0;i < Channels;i++) \
266 value = sampler##S(Data.p##S[pos*Channels + i], \
267 Data.p##S[(pos+1)*Channels + i], frac); \
269 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
270 ClickRemoval[chans[i+0]] -= value*DrySend[chans[i+0]]; \
271 ClickRemoval[chans[i+2]] -= value*DrySend[chans[i+2]]; \
272 ClickRemoval[chans[i+4]] -= value*DrySend[chans[i+4]]; \
275 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
277 for(i = 0;i < Channels;i++) \
279 value = sampler##S(Data.p##S[pos*Channels + i], \
280 Data.p##S[(pos+1)*Channels + i], frac); \
282 value = lpFilter2P(DryFilter, chans[i]*2, value); \
283 DryBuffer[j][chans[i+0]] += value*DrySend[chans[i+0]]; \
284 DryBuffer[j][chans[i+2]] += value*DrySend[chans[i+2]]; \
285 DryBuffer[j][chans[i+4]] += value*DrySend[chans[i+4]]; \
288 frac += increment; \
289 pos += frac>>FRACTIONBITS; \
290 frac &= FRACTIONMASK; \
291 j++; \
293 if(j == SamplesToDo) \
295 ALuint p = pos; \
296 ALuint f = frac; \
297 if(p >= LoopEnd) \
299 ALuint64 pos64 = pos; \
300 pos64 <<= FRACTIONBITS; \
301 pos64 += frac; \
302 pos64 -= increment; \
303 p = pos64>>FRACTIONBITS; \
304 f = pos64&FRACTIONMASK; \
306 for(i = 0;i < Channels;i++) \
308 value = sampler##S(Data.p##S[p*Channels + i], \
309 Data.p##S[(p+1)*Channels + i], f); \
311 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
312 PendingClicks[chans[i+0]] += value*DrySend[chans[i+0]]; \
313 PendingClicks[chans[i+2]] += value*DrySend[chans[i+2]]; \
314 PendingClicks[chans[i+4]] += value*DrySend[chans[i+4]]; \
318 for(out = 0;out < MAX_SENDS;out++) \
320 ALfloat WetSend; \
321 ALfloat *WetBuffer; \
322 ALfloat *WetClickRemoval; \
323 ALfloat *WetPendingClicks; \
324 FILTER *WetFilter; \
326 if(!Source->Send[out].Slot || \
327 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
328 continue; \
330 WetSend = Source->Params.WetGains[out]; \
331 WetBuffer = Source->Send[out].Slot->WetBuffer; \
332 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
333 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
334 WetFilter = &Source->Params.Send[out].iirFilter; \
336 pos = DataPosInt; \
337 frac = DataPosFrac; \
338 j -= BufferSize; \
340 if(j == 0) \
342 for(i = 0;i < Channels;i++) \
344 value = sampler##S(Data.p##S[pos*Channels + i], \
345 Data.p##S[(pos+1)*Channels + i], frac); \
347 value = lpFilter1PC(WetFilter, chans[i], value); \
348 WetClickRemoval[0] -= value*WetSend * scaler; \
351 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
353 for(i = 0;i < Channels;i++) \
355 value = sampler##S(Data.p##S[pos*Channels + i], \
356 Data.p##S[(pos+1)*Channels + i], frac); \
358 value = lpFilter1P(WetFilter, chans[i], value); \
359 WetBuffer[j] += value*WetSend * scaler; \
362 frac += increment; \
363 pos += frac>>FRACTIONBITS; \
364 frac &= FRACTIONMASK; \
365 j++; \
367 if(j == SamplesToDo) \
369 ALuint p = pos; \
370 ALuint f = frac; \
371 if(p >= LoopEnd) \
373 ALuint64 pos64 = pos; \
374 pos64 <<= FRACTIONBITS; \
375 pos64 += frac; \
376 pos64 -= increment; \
377 p = pos64>>FRACTIONBITS; \
378 f = pos64&FRACTIONMASK; \
380 for(i = 0;i < Channels;i++) \
382 value = sampler##S(Data.p##S[p*Channels + i], \
383 Data.p##S[(p+1)*Channels + i], f); \
385 value = lpFilter1PC(WetFilter, chans[i], value); \
386 WetPendingClicks[0] += value*WetSend * scaler; \
390 DataPosInt = pos; \
391 DataPosFrac = frac; \
392 } while(0)
394 #define DO_MIX_MC(S,sampler) do { \
395 const ALfloat scaler = 1.0f/Channels; \
396 ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
397 ALfloat *ClickRemoval, *PendingClicks; \
398 ALuint pos = DataPosInt; \
399 ALuint frac = DataPosFrac; \
400 ALfloat DrySend[OUTPUTCHANNELS]; \
401 FILTER *DryFilter; \
402 ALuint BufferIdx; \
403 ALuint i, out; \
404 ALfloat value; \
406 DryBuffer = Device->DryBuffer; \
407 ClickRemoval = Device->ClickRemoval; \
408 PendingClicks = Device->PendingClicks; \
409 DryFilter = &Source->Params.iirFilter; \
410 for(i = 0;i < OUTPUTCHANNELS;i++) \
411 DrySend[i] = Source->Params.DryGains[i]; \
413 if(j == 0) \
415 for(i = 0;i < Channels;i++) \
417 value = sampler##S(Data.p##S[pos*Channels + i], \
418 Data.p##S[(pos+1)*Channels + i], frac); \
420 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
421 ClickRemoval[chans[i]] -= value*DrySend[chans[i]]; \
424 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
426 for(i = 0;i < Channels;i++) \
428 value = sampler##S(Data.p##S[pos*Channels + i], \
429 Data.p##S[(pos+1)*Channels + i], frac); \
431 value = lpFilter2P(DryFilter, chans[i]*2, value); \
432 DryBuffer[j][chans[i]] += value*DrySend[chans[i]]; \
435 frac += increment; \
436 pos += frac>>FRACTIONBITS; \
437 frac &= FRACTIONMASK; \
438 j++; \
440 if(j == SamplesToDo) \
442 ALuint p = pos; \
443 ALuint f = frac; \
444 if(p >= LoopEnd) \
446 ALuint64 pos64 = pos; \
447 pos64 <<= FRACTIONBITS; \
448 pos64 += frac; \
449 pos64 -= increment; \
450 p = pos64>>FRACTIONBITS; \
451 f = pos64&FRACTIONMASK; \
453 for(i = 0;i < Channels;i++) \
455 value = sampler##S(Data.p##S[p*Channels + i], \
456 Data.p##S[(p+1)*Channels + i], f); \
458 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
459 PendingClicks[chans[i]] += value*DrySend[chans[i]]; \
463 for(out = 0;out < MAX_SENDS;out++) \
465 ALfloat WetSend; \
466 ALfloat *WetBuffer; \
467 ALfloat *WetClickRemoval; \
468 ALfloat *WetPendingClicks; \
469 FILTER *WetFilter; \
471 if(!Source->Send[out].Slot || \
472 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
473 continue; \
475 WetSend = Source->Params.WetGains[out]; \
476 WetBuffer = Source->Send[out].Slot->WetBuffer; \
477 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
478 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
479 WetFilter = &Source->Params.Send[out].iirFilter; \
481 pos = DataPosInt; \
482 frac = DataPosFrac; \
483 j -= BufferSize; \
485 if(j == 0) \
487 for(i = 0;i < Channels;i++) \
489 value = sampler##S(Data.p##S[pos*Channels + i], \
490 Data.p##S[(pos+1)*Channels + i], frac); \
492 value = lpFilter1PC(WetFilter, chans[i], value); \
493 WetClickRemoval[0] -= value*WetSend * scaler; \
496 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
498 for(i = 0;i < Channels;i++) \
500 value = sampler##S(Data.p##S[pos*Channels + i], \
501 Data.p##S[(pos+1)*Channels + i], frac); \
503 value = lpFilter1P(WetFilter, chans[i], value); \
504 WetBuffer[j] += value*WetSend * scaler; \
507 frac += increment; \
508 pos += frac>>FRACTIONBITS; \
509 frac &= FRACTIONMASK; \
510 j++; \
512 if(j == SamplesToDo) \
514 ALuint p = pos; \
515 ALuint f = frac; \
516 if(p >= LoopEnd) \
518 ALuint64 pos64 = pos; \
519 pos64 <<= FRACTIONBITS; \
520 pos64 += frac; \
521 pos64 -= increment; \
522 p = pos64>>FRACTIONBITS; \
523 f = pos64&FRACTIONMASK; \
525 for(i = 0;i < Channels;i++) \
527 value = sampler##S(Data.p##S[p*Channels + i], \
528 Data.p##S[(p+1)*Channels + i], f); \
530 value = lpFilter1PC(WetFilter, chans[i], value); \
531 WetPendingClicks[0] += value*WetSend * scaler; \
535 DataPosInt = pos; \
536 DataPosFrac = frac; \
537 } while(0)
540 #define MIX_MONO(sampler) do { \
541 if(Bytes == 4) \
542 DO_MIX_MONO(32,sampler); \
543 else if(Bytes == 2) \
544 DO_MIX_MONO(16,sampler); \
545 } while(0)
547 #define MIX_STEREO(sampler) do { \
548 const int chans[] = { \
549 FRONT_LEFT, FRONT_RIGHT, \
550 SIDE_LEFT, SIDE_RIGHT, \
551 BACK_LEFT, BACK_RIGHT \
552 }; \
554 if(Bytes == 4) \
555 DO_MIX_STEREO(32,sampler); \
556 else if(Bytes == 2) \
557 DO_MIX_STEREO(16,sampler); \
558 } while(0)
560 #define MIX_MC(sampler,...) do { \
561 const int chans[] = { __VA_ARGS__ }; \
563 if(Bytes == 4) \
564 DO_MIX_MC(32,sampler); \
565 else if(Bytes == 2) \
566 DO_MIX_MC(16,sampler); \
567 } while(0)
570 #define MIX(sampler) do { \
571 if(Channels == 1) /* Mono */ \
572 MIX_MONO(sampler); \
573 else if(Channels == 2) /* Stereo */ \
574 MIX_STEREO(sampler); \
575 else if(Channels == 4) /* Quad */ \
576 MIX_MC(sampler, FRONT_LEFT, FRONT_RIGHT, \
577 BACK_LEFT, BACK_RIGHT); \
578 else if(Channels == 6) /* 5.1 */ \
579 MIX_MC(sampler, FRONT_LEFT, FRONT_RIGHT, \
580 FRONT_CENTER, LFE, \
581 BACK_LEFT, BACK_RIGHT); \
582 else if(Channels == 7) /* 6.1 */ \
583 MIX_MC(sampler, FRONT_LEFT, FRONT_RIGHT, \
584 FRONT_CENTER, LFE, \
585 BACK_CENTER, \
586 SIDE_LEFT, SIDE_RIGHT); \
587 else if(Channels == 8) /* 7.1 */ \
588 MIX_MC(sampler, FRONT_LEFT, FRONT_RIGHT, \
589 FRONT_CENTER, LFE, \
590 BACK_LEFT, BACK_RIGHT, \
591 SIDE_LEFT, SIDE_RIGHT); \
592 } while(0)
595 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
597 ALbufferlistitem *BufferListItem;
598 ALint64 DataSize64,DataPos64;
599 ALint increment;
600 ALuint DataPosInt, DataPosFrac;
601 ALuint BuffersPlayed;
602 ALboolean Looping;
603 ALenum State;
604 ALuint i, j;
606 /* Get source info */
607 State = Source->state;
608 BuffersPlayed = Source->BuffersPlayed;
609 DataPosInt = Source->position;
610 DataPosFrac = Source->position_fraction;
611 Looping = Source->bLooping;
613 /* Get current buffer queue item */
614 BufferListItem = Source->queue;
615 for(i = 0;i < BuffersPlayed;i++)
616 BufferListItem = BufferListItem->next;
618 j = 0;
619 do {
620 const ALbuffer *ALBuffer;
621 union {
622 ALfloat *p32;
623 ALshort *p16;
624 ALubyte *p8;
625 } Data = { NULL };
626 ALuint DataSize = 0;
627 ALuint LoopStart = 0;
628 ALuint LoopEnd = 0;
629 ALuint Channels, Bytes;
630 ALuint BufferSize;
632 /* Get buffer info */
633 if((ALBuffer=BufferListItem->buffer) != NULL)
635 Data.p8 = ALBuffer->data;
636 DataSize = ALBuffer->size;
637 DataSize /= aluFrameSizeFromFormat(ALBuffer->format);
638 Channels = aluChannelsFromFormat(ALBuffer->format);
639 Bytes = aluBytesFromFormat(ALBuffer->format);
641 LoopStart = 0;
642 LoopEnd = DataSize;
643 if(Looping && Source->lSourceType == AL_STATIC)
645 /* If current pos is beyond the loop range, do not loop */
646 if(DataPosInt >= LoopEnd)
647 Looping = AL_FALSE;
648 else
650 LoopStart = ALBuffer->LoopStart;
651 LoopEnd = ALBuffer->LoopEnd;
656 if(DataPosInt >= DataSize)
657 goto skipmix;
659 if(BufferListItem->next)
661 ALbuffer *NextBuf = BufferListItem->next->buffer;
662 if(NextBuf && NextBuf->size)
664 ALint ulExtraSamples = BUFFER_PADDING*Channels*Bytes;
665 ulExtraSamples = min(NextBuf->size, ulExtraSamples);
666 memcpy(&Data.p8[DataSize*Channels*Bytes],
667 NextBuf->data, ulExtraSamples);
670 else if(Looping)
672 ALbuffer *NextBuf = Source->queue->buffer;
673 if(NextBuf && NextBuf->size)
675 ALint ulExtraSamples = BUFFER_PADDING*Channels*Bytes;
676 ulExtraSamples = min(NextBuf->size, ulExtraSamples);
677 memcpy(&Data.p8[DataSize*Channels*Bytes],
678 &((ALubyte*)NextBuf->data)[LoopStart*Channels*Bytes],
679 ulExtraSamples);
682 else
683 memset(&Data.p8[DataSize*Channels*Bytes], 0, (BUFFER_PADDING*Channels*Bytes));
685 /* Figure out how many samples we can mix. */
686 increment = Source->Params.Step;
687 DataSize64 = LoopEnd;
688 DataSize64 <<= FRACTIONBITS;
689 DataPos64 = DataPosInt;
690 DataPos64 <<= FRACTIONBITS;
691 DataPos64 += DataPosFrac;
692 BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
694 BufferSize = min(BufferSize, (SamplesToDo-j));
696 switch(Source->Resampler)
698 case POINT_RESAMPLER:
699 MIX(point); break;
700 case LINEAR_RESAMPLER:
701 MIX(lerp); break;
702 case COSINE_RESAMPLER:
703 MIX(cos_lerp); break;
704 case RESAMPLER_MIN:
705 case RESAMPLER_MAX:
706 break;
709 skipmix:
710 /* Handle looping sources */
711 if(DataPosInt >= LoopEnd)
713 if(BufferListItem->next)
715 BufferListItem = BufferListItem->next;
716 BuffersPlayed++;
717 DataPosInt -= DataSize;
719 else if(Looping)
721 BufferListItem = Source->queue;
722 BuffersPlayed = 0;
723 if(Source->lSourceType == AL_STATIC)
724 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
725 else
726 DataPosInt -= DataSize;
728 else
730 State = AL_STOPPED;
731 BufferListItem = Source->queue;
732 BuffersPlayed = Source->BuffersInQueue;
733 DataPosInt = 0;
734 DataPosFrac = 0;
737 } while(State == AL_PLAYING && j < SamplesToDo);
739 /* Update source info */
740 Source->state = State;
741 Source->BuffersPlayed = BuffersPlayed;
742 Source->position = DataPosInt;
743 Source->position_fraction = DataPosFrac;
744 Source->Buffer = BufferListItem->buffer;
748 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
750 ALuint SamplesToDo;
751 ALeffectslot *ALEffectSlot;
752 ALCcontext **ctx, **ctx_end;
753 ALsource **src, **src_end;
754 int fpuState;
755 ALuint i, j, c;
756 ALsizei e;
758 #if defined(HAVE_FESETROUND)
759 fpuState = fegetround();
760 fesetround(FE_TOWARDZERO);
761 #elif defined(HAVE__CONTROLFP)
762 fpuState = _controlfp(_RC_CHOP, _MCW_RC);
763 #else
764 (void)fpuState;
765 #endif
767 while(size > 0)
769 /* Setup variables */
770 SamplesToDo = min(size, BUFFERSIZE);
772 /* Clear mixing buffer */
773 memset(device->DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
775 SuspendContext(NULL);
776 ctx = device->Contexts;
777 ctx_end = ctx + device->NumContexts;
778 while(ctx != ctx_end)
780 SuspendContext(*ctx);
782 src = (*ctx)->ActiveSources;
783 src_end = src + (*ctx)->ActiveSourceCount;
784 while(src != src_end)
786 if((*src)->state != AL_PLAYING)
788 --((*ctx)->ActiveSourceCount);
789 *src = *(--src_end);
790 continue;
793 if((*src)->NeedsUpdate)
795 ALsource_Update(*src, *ctx);
796 (*src)->NeedsUpdate = AL_FALSE;
799 ALsource_Mix(*src, device, SamplesToDo);
800 src++;
803 /* effect slot processing */
804 for(e = 0;e < (*ctx)->EffectSlotMap.size;e++)
806 ALEffectSlot = (*ctx)->EffectSlotMap.array[e].value;
808 for(i = 0;i < SamplesToDo;i++)
810 ALEffectSlot->ClickRemoval[0] -= ALEffectSlot->ClickRemoval[0] / 256.0f;
811 ALEffectSlot->WetBuffer[i] += ALEffectSlot->ClickRemoval[0];
813 for(i = 0;i < 1;i++)
815 ALEffectSlot->ClickRemoval[i] += ALEffectSlot->PendingClicks[i];
816 ALEffectSlot->PendingClicks[i] = 0.0f;
819 ALEffect_Process(ALEffectSlot->EffectState, ALEffectSlot,
820 SamplesToDo, ALEffectSlot->WetBuffer,
821 device->DryBuffer);
823 for(i = 0;i < SamplesToDo;i++)
824 ALEffectSlot->WetBuffer[i] = 0.0f;
827 ProcessContext(*ctx);
828 ctx++;
830 device->SamplesPlayed += SamplesToDo;
831 ProcessContext(NULL);
833 //Post processing loop
834 for(i = 0;i < SamplesToDo;i++)
836 for(c = 0;c < OUTPUTCHANNELS;c++)
838 device->ClickRemoval[c] -= device->ClickRemoval[c] / 256.0f;
839 device->DryBuffer[i][c] += device->ClickRemoval[c];
842 for(i = 0;i < OUTPUTCHANNELS;i++)
844 device->ClickRemoval[i] += device->PendingClicks[i];
845 device->PendingClicks[i] = 0.0f;
848 switch(device->Format)
850 #define DO_WRITE(T, func, N, ...) do { \
851 const Channel chans[] = { \
852 __VA_ARGS__ \
853 }; \
854 ALfloat (*DryBuffer)[OUTPUTCHANNELS] = device->DryBuffer; \
855 ALfloat (*Matrix)[OUTPUTCHANNELS] = device->ChannelMatrix; \
856 const ALuint *ChanMap = device->DevChannels; \
858 for(i = 0;i < SamplesToDo;i++) \
860 for(j = 0;j < N;j++) \
862 ALfloat samp = 0.0f; \
863 for(c = 0;c < OUTPUTCHANNELS;c++) \
864 samp += DryBuffer[i][c] * Matrix[c][chans[j]]; \
865 ((T*)buffer)[ChanMap[chans[j]]] = func(samp); \
867 buffer = ((T*)buffer) + N; \
869 } while(0)
871 #define CHECK_WRITE_FORMAT(bits, T, func) \
872 case AL_FORMAT_MONO##bits: \
873 DO_WRITE(T, func, 1, FRONT_CENTER); \
874 break; \
875 case AL_FORMAT_STEREO##bits: \
876 if(device->Bs2b) \
878 ALfloat (*DryBuffer)[OUTPUTCHANNELS] = device->DryBuffer; \
879 ALfloat (*Matrix)[OUTPUTCHANNELS] = device->ChannelMatrix; \
880 const ALuint *ChanMap = device->DevChannels; \
882 for(i = 0;i < SamplesToDo;i++) \
884 float samples[2] = { 0.0f, 0.0f }; \
885 for(c = 0;c < OUTPUTCHANNELS;c++) \
887 samples[0] += DryBuffer[i][c]*Matrix[c][FRONT_LEFT]; \
888 samples[1] += DryBuffer[i][c]*Matrix[c][FRONT_RIGHT]; \
890 bs2b_cross_feed(device->Bs2b, samples); \
891 ((T*)buffer)[ChanMap[FRONT_LEFT]] = func(samples[0]); \
892 ((T*)buffer)[ChanMap[FRONT_RIGHT]] = func(samples[1]); \
893 buffer = ((T*)buffer) + 2; \
896 else \
897 DO_WRITE(T, func, 2, FRONT_LEFT, FRONT_RIGHT); \
898 break; \
899 case AL_FORMAT_QUAD##bits: \
900 DO_WRITE(T, func, 4, FRONT_LEFT, FRONT_RIGHT, \
901 BACK_LEFT, BACK_RIGHT); \
902 break; \
903 case AL_FORMAT_51CHN##bits: \
904 DO_WRITE(T, func, 6, FRONT_LEFT, FRONT_RIGHT, \
905 FRONT_CENTER, LFE, \
906 BACK_LEFT, BACK_RIGHT); \
907 break; \
908 case AL_FORMAT_61CHN##bits: \
909 DO_WRITE(T, func, 7, FRONT_LEFT, FRONT_RIGHT, \
910 FRONT_CENTER, LFE, BACK_CENTER, \
911 SIDE_LEFT, SIDE_RIGHT); \
912 break; \
913 case AL_FORMAT_71CHN##bits: \
914 DO_WRITE(T, func, 8, FRONT_LEFT, FRONT_RIGHT, \
915 FRONT_CENTER, LFE, \
916 BACK_LEFT, BACK_RIGHT, \
917 SIDE_LEFT, SIDE_RIGHT); \
918 break;
920 #define AL_FORMAT_MONO32 AL_FORMAT_MONO_FLOAT32
921 #define AL_FORMAT_STEREO32 AL_FORMAT_STEREO_FLOAT32
922 CHECK_WRITE_FORMAT(8, ALubyte, aluF2UB)
923 CHECK_WRITE_FORMAT(16, ALshort, aluF2S)
924 CHECK_WRITE_FORMAT(32, ALfloat, aluF2F)
925 #undef AL_FORMAT_STEREO32
926 #undef AL_FORMAT_MONO32
927 #undef CHECK_WRITE_FORMAT
928 #undef DO_WRITE
930 default:
931 break;
934 size -= SamplesToDo;
937 #if defined(HAVE_FESETROUND)
938 fesetround(fpuState);
939 #elif defined(HAVE__CONTROLFP)
940 _controlfp(fpuState, _MCW_RC);
941 #endif