Share the interpolation functions and use them in the reverb effect
[openal-soft.git] / Alc / mixer.c
blob74af356d7edcdd9febc7ba319962e8f6242f9461
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 ALdouble point32(const ALfloat *vals, ALint step, ALint frac)
41 { return vals[0]; (void)step; (void)frac; }
42 static __inline ALdouble lerp32(const ALfloat *vals, ALint step, ALint frac)
43 { return lerp(vals[0], vals[step], frac * (1.0/(1<<FRACTIONBITS))); }
44 static __inline ALdouble cubic32(const ALfloat *vals, ALint step, ALint frac)
45 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
46 frac * (1.0/(1<<FRACTIONBITS))); }
48 static __inline ALdouble point16(const ALshort *vals, ALint step, ALint frac)
49 { return vals[0] / 32767.0; (void)step; (void)frac; }
50 static __inline ALdouble lerp16(const ALshort *vals, ALint step, ALint frac)
51 { return lerp(vals[0], vals[step], frac * (1.0/(1<<FRACTIONBITS))) / 32767.0; }
52 static __inline ALdouble cubic16(const ALshort *vals, ALint step, ALint frac)
53 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
54 frac * (1.0/(1<<FRACTIONBITS))) / 32767.0; }
56 static __inline ALdouble point8(const ALubyte *vals, ALint step, ALint frac)
57 { return (vals[0]-128.0) / 127.0; (void)step; (void)frac; }
58 static __inline ALdouble lerp8(const ALubyte *vals, ALint step, ALint frac)
59 { return (lerp(vals[0], vals[step], frac * (1.0/(1<<FRACTIONBITS)))-128.0) / 127.0; }
60 static __inline ALdouble cubic8(const ALubyte *vals, ALint step, ALint frac)
61 { return (cubic(vals[-step], vals[0], vals[step], vals[step+step],
62 frac * (1.0/(1<<FRACTIONBITS)))-128.0) / 127.0; }
65 #define DECL_TEMPLATE(T, sampler) \
66 static void Mix_##T##_Mono_##sampler(ALsource *Source, ALCdevice *Device, \
67 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
68 ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
69 { \
70 ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
71 ALfloat *ClickRemoval, *PendingClicks; \
72 ALuint pos, frac; \
73 ALfloat DrySend[OUTPUTCHANNELS]; \
74 FILTER *DryFilter; \
75 ALuint BufferIdx; \
76 ALuint increment; \
77 ALuint i, out; \
78 ALfloat value; \
80 increment = Source->Params.Step; \
82 DryBuffer = Device->DryBuffer; \
83 ClickRemoval = Device->ClickRemoval; \
84 PendingClicks = Device->PendingClicks; \
85 DryFilter = &Source->Params.iirFilter; \
86 for(i = 0;i < OUTPUTCHANNELS;i++) \
87 DrySend[i] = Source->Params.DryGains[i]; \
89 pos = 0; \
90 frac = *DataPosFrac; \
92 if(j == 0) \
93 { \
94 value = sampler(data+pos, 1, frac); \
96 value = lpFilter4PC(DryFilter, 0, value); \
97 ClickRemoval[FRONT_LEFT] -= value*DrySend[FRONT_LEFT]; \
98 ClickRemoval[FRONT_RIGHT] -= value*DrySend[FRONT_RIGHT]; \
99 ClickRemoval[SIDE_LEFT] -= value*DrySend[SIDE_LEFT]; \
100 ClickRemoval[SIDE_RIGHT] -= value*DrySend[SIDE_RIGHT]; \
101 ClickRemoval[BACK_LEFT] -= value*DrySend[BACK_LEFT]; \
102 ClickRemoval[BACK_RIGHT] -= value*DrySend[BACK_RIGHT]; \
103 ClickRemoval[FRONT_CENTER] -= value*DrySend[FRONT_CENTER]; \
104 ClickRemoval[BACK_CENTER] -= value*DrySend[BACK_CENTER]; \
106 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
108 /* First order interpolator */ \
109 value = sampler(data+pos, 1, frac); \
111 /* Direct path final mix buffer and panning */ \
112 value = lpFilter4P(DryFilter, 0, value); \
113 DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; \
114 DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; \
115 DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT]; \
116 DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; \
117 DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT]; \
118 DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; \
119 DryBuffer[j][FRONT_CENTER] += value*DrySend[FRONT_CENTER]; \
120 DryBuffer[j][BACK_CENTER] += value*DrySend[BACK_CENTER]; \
122 frac += increment; \
123 pos += frac>>FRACTIONBITS; \
124 frac &= FRACTIONMASK; \
125 j++; \
127 if(j == SamplesToDo) \
129 value = sampler(data+pos, 1, frac); \
131 value = lpFilter4PC(DryFilter, 0, value); \
132 PendingClicks[FRONT_LEFT] += value*DrySend[FRONT_LEFT]; \
133 PendingClicks[FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; \
134 PendingClicks[SIDE_LEFT] += value*DrySend[SIDE_LEFT]; \
135 PendingClicks[SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; \
136 PendingClicks[BACK_LEFT] += value*DrySend[BACK_LEFT]; \
137 PendingClicks[BACK_RIGHT] += value*DrySend[BACK_RIGHT]; \
138 PendingClicks[FRONT_CENTER] += value*DrySend[FRONT_CENTER]; \
139 PendingClicks[BACK_CENTER] += value*DrySend[BACK_CENTER]; \
142 for(out = 0;out < Device->NumAuxSends;out++) \
144 ALfloat WetSend; \
145 ALfloat *WetBuffer; \
146 ALfloat *WetClickRemoval; \
147 ALfloat *WetPendingClicks; \
148 FILTER *WetFilter; \
150 if(!Source->Send[out].Slot || \
151 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
152 continue; \
154 WetBuffer = Source->Send[out].Slot->WetBuffer; \
155 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
156 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
157 WetFilter = &Source->Params.Send[out].iirFilter; \
158 WetSend = Source->Params.Send[out].WetGain; \
160 pos = 0; \
161 frac = *DataPosFrac; \
162 j -= BufferSize; \
164 if(j == 0) \
166 value = sampler(data+pos, 1, frac); \
168 value = lpFilter2PC(WetFilter, 0, value); \
169 WetClickRemoval[0] -= value*WetSend; \
171 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
173 /* First order interpolator */ \
174 value = sampler(data+pos, 1, frac); \
176 /* Room path final mix buffer and panning */ \
177 value = lpFilter2P(WetFilter, 0, value); \
178 WetBuffer[j] += value*WetSend; \
180 frac += increment; \
181 pos += frac>>FRACTIONBITS; \
182 frac &= FRACTIONMASK; \
183 j++; \
185 if(j == SamplesToDo) \
187 value = sampler(data+pos, 1, frac); \
189 value = lpFilter2PC(WetFilter, 0, value); \
190 WetPendingClicks[0] += value*WetSend; \
193 *DataPosInt += pos; \
194 *DataPosFrac = frac; \
197 DECL_TEMPLATE(ALfloat, point32)
198 DECL_TEMPLATE(ALfloat, lerp32)
199 DECL_TEMPLATE(ALfloat, cubic32)
201 DECL_TEMPLATE(ALshort, point16)
202 DECL_TEMPLATE(ALshort, lerp16)
203 DECL_TEMPLATE(ALshort, cubic16)
205 DECL_TEMPLATE(ALubyte, point8)
206 DECL_TEMPLATE(ALubyte, lerp8)
207 DECL_TEMPLATE(ALubyte, cubic8)
209 #undef DECL_TEMPLATE
212 #define DECL_TEMPLATE(T, sampler) \
213 static void Mix_##T##_Stereo_##sampler(ALsource *Source, ALCdevice *Device, \
214 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
215 ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
217 static const ALuint Channels = 2; \
218 static const Channel chans[] = { \
219 FRONT_LEFT, FRONT_RIGHT, \
220 SIDE_LEFT, SIDE_RIGHT, \
221 BACK_LEFT, BACK_RIGHT \
222 }; \
223 const ALfloat scaler = 1.0f/Channels; \
224 ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
225 ALfloat *ClickRemoval, *PendingClicks; \
226 ALuint pos, frac; \
227 ALfloat DrySend[OUTPUTCHANNELS]; \
228 FILTER *DryFilter; \
229 ALuint BufferIdx; \
230 ALuint increment; \
231 ALuint i, out; \
232 ALfloat value; \
234 increment = Source->Params.Step; \
236 DryBuffer = Device->DryBuffer; \
237 ClickRemoval = Device->ClickRemoval; \
238 PendingClicks = Device->PendingClicks; \
239 DryFilter = &Source->Params.iirFilter; \
240 for(i = 0;i < OUTPUTCHANNELS;i++) \
241 DrySend[i] = Source->Params.DryGains[i]; \
243 pos = 0; \
244 frac = *DataPosFrac; \
246 if(j == 0) \
248 for(i = 0;i < Channels;i++) \
250 value = sampler(data + pos*Channels + i, Channels, frac); \
252 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
253 ClickRemoval[chans[i+0]] -= value*DrySend[chans[i+0]]; \
254 ClickRemoval[chans[i+2]] -= value*DrySend[chans[i+2]]; \
255 ClickRemoval[chans[i+4]] -= value*DrySend[chans[i+4]]; \
258 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
260 for(i = 0;i < Channels;i++) \
262 value = sampler(data + pos*Channels + i, Channels, frac); \
264 value = lpFilter2P(DryFilter, chans[i]*2, value); \
265 DryBuffer[j][chans[i+0]] += value*DrySend[chans[i+0]]; \
266 DryBuffer[j][chans[i+2]] += value*DrySend[chans[i+2]]; \
267 DryBuffer[j][chans[i+4]] += value*DrySend[chans[i+4]]; \
270 frac += increment; \
271 pos += frac>>FRACTIONBITS; \
272 frac &= FRACTIONMASK; \
273 j++; \
275 if(j == SamplesToDo) \
277 for(i = 0;i < Channels;i++) \
279 value = sampler(data + pos*Channels + i, Channels, frac); \
281 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
282 PendingClicks[chans[i+0]] += value*DrySend[chans[i+0]]; \
283 PendingClicks[chans[i+2]] += value*DrySend[chans[i+2]]; \
284 PendingClicks[chans[i+4]] += value*DrySend[chans[i+4]]; \
288 for(out = 0;out < Device->NumAuxSends;out++) \
290 ALfloat WetSend; \
291 ALfloat *WetBuffer; \
292 ALfloat *WetClickRemoval; \
293 ALfloat *WetPendingClicks; \
294 FILTER *WetFilter; \
296 if(!Source->Send[out].Slot || \
297 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
298 continue; \
300 WetBuffer = Source->Send[out].Slot->WetBuffer; \
301 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
302 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
303 WetFilter = &Source->Params.Send[out].iirFilter; \
304 WetSend = Source->Params.Send[out].WetGain; \
306 pos = 0; \
307 frac = *DataPosFrac; \
308 j -= BufferSize; \
310 if(j == 0) \
312 for(i = 0;i < Channels;i++) \
314 value = sampler(data + pos*Channels + i, Channels, frac); \
316 value = lpFilter1PC(WetFilter, chans[i], value); \
317 WetClickRemoval[0] -= value*WetSend * scaler; \
320 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
322 for(i = 0;i < Channels;i++) \
324 value = sampler(data + pos*Channels + i, Channels, frac); \
326 value = lpFilter1P(WetFilter, chans[i], value); \
327 WetBuffer[j] += value*WetSend * scaler; \
330 frac += increment; \
331 pos += frac>>FRACTIONBITS; \
332 frac &= FRACTIONMASK; \
333 j++; \
335 if(j == SamplesToDo) \
337 for(i = 0;i < Channels;i++) \
339 value = sampler(data + pos*Channels + i, Channels, frac); \
341 value = lpFilter1PC(WetFilter, chans[i], value); \
342 WetPendingClicks[0] += value*WetSend * scaler; \
346 *DataPosInt += pos; \
347 *DataPosFrac = frac; \
350 DECL_TEMPLATE(ALfloat, point32)
351 DECL_TEMPLATE(ALfloat, lerp32)
352 DECL_TEMPLATE(ALfloat, cubic32)
354 DECL_TEMPLATE(ALshort, point16)
355 DECL_TEMPLATE(ALshort, lerp16)
356 DECL_TEMPLATE(ALshort, cubic16)
358 DECL_TEMPLATE(ALubyte, point8)
359 DECL_TEMPLATE(ALubyte, lerp8)
360 DECL_TEMPLATE(ALubyte, cubic8)
362 #undef DECL_TEMPLATE
365 #define DECL_TEMPLATE(T, chans, sampler) \
366 static void Mix_##T##_##chans##_##sampler(ALsource *Source, ALCdevice *Device,\
367 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
368 ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
370 static const ALuint Channels = sizeof(chans)/sizeof(chans[0]); \
371 const ALfloat scaler = 1.0f/Channels; \
372 ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
373 ALfloat *ClickRemoval, *PendingClicks; \
374 ALuint pos, frac; \
375 ALfloat DrySend[OUTPUTCHANNELS]; \
376 FILTER *DryFilter; \
377 ALuint BufferIdx; \
378 ALuint increment; \
379 ALuint i, out; \
380 ALfloat value; \
382 increment = Source->Params.Step; \
384 DryBuffer = Device->DryBuffer; \
385 ClickRemoval = Device->ClickRemoval; \
386 PendingClicks = Device->PendingClicks; \
387 DryFilter = &Source->Params.iirFilter; \
388 for(i = 0;i < OUTPUTCHANNELS;i++) \
389 DrySend[i] = Source->Params.DryGains[i]; \
391 pos = 0; \
392 frac = *DataPosFrac; \
394 if(j == 0) \
396 for(i = 0;i < Channels;i++) \
398 value = sampler(data + pos*Channels + i, Channels, frac); \
400 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
401 ClickRemoval[chans[i]] -= value*DrySend[chans[i]]; \
404 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
406 for(i = 0;i < Channels;i++) \
408 value = sampler(data + pos*Channels + i, Channels, frac); \
410 value = lpFilter2P(DryFilter, chans[i]*2, value); \
411 DryBuffer[j][chans[i]] += value*DrySend[chans[i]]; \
414 frac += increment; \
415 pos += frac>>FRACTIONBITS; \
416 frac &= FRACTIONMASK; \
417 j++; \
419 if(j == SamplesToDo) \
421 for(i = 0;i < Channels;i++) \
423 value = sampler(data + pos*Channels + i, Channels, frac); \
425 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
426 PendingClicks[chans[i]] += value*DrySend[chans[i]]; \
430 for(out = 0;out < Device->NumAuxSends;out++) \
432 ALfloat WetSend; \
433 ALfloat *WetBuffer; \
434 ALfloat *WetClickRemoval; \
435 ALfloat *WetPendingClicks; \
436 FILTER *WetFilter; \
438 if(!Source->Send[out].Slot || \
439 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
440 continue; \
442 WetBuffer = Source->Send[out].Slot->WetBuffer; \
443 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
444 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
445 WetFilter = &Source->Params.Send[out].iirFilter; \
446 WetSend = Source->Params.Send[out].WetGain; \
448 pos = 0; \
449 frac = *DataPosFrac; \
450 j -= BufferSize; \
452 if(j == 0) \
454 for(i = 0;i < Channels;i++) \
456 value = sampler(data + pos*Channels + i, Channels, frac); \
458 value = lpFilter1PC(WetFilter, chans[i], value); \
459 WetClickRemoval[0] -= value*WetSend * scaler; \
462 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
464 for(i = 0;i < Channels;i++) \
466 value = sampler(data + pos*Channels + i, Channels, frac); \
468 value = lpFilter1P(WetFilter, chans[i], value); \
469 WetBuffer[j] += value*WetSend * scaler; \
472 frac += increment; \
473 pos += frac>>FRACTIONBITS; \
474 frac &= FRACTIONMASK; \
475 j++; \
477 if(j == SamplesToDo) \
479 for(i = 0;i < Channels;i++) \
481 value = sampler(data + pos*Channels + i, Channels, frac); \
483 value = lpFilter1PC(WetFilter, chans[i], value); \
484 WetPendingClicks[0] += value*WetSend * scaler; \
488 *DataPosInt += pos; \
489 *DataPosFrac = frac; \
492 static const Channel QuadChans[] = { FRONT_LEFT, FRONT_RIGHT,
493 BACK_LEFT, BACK_RIGHT };
494 DECL_TEMPLATE(ALfloat, QuadChans, point32)
495 DECL_TEMPLATE(ALfloat, QuadChans, lerp32)
496 DECL_TEMPLATE(ALfloat, QuadChans, cubic32)
498 DECL_TEMPLATE(ALshort, QuadChans, point16)
499 DECL_TEMPLATE(ALshort, QuadChans, lerp16)
500 DECL_TEMPLATE(ALshort, QuadChans, cubic16)
502 DECL_TEMPLATE(ALubyte, QuadChans, point8)
503 DECL_TEMPLATE(ALubyte, QuadChans, lerp8)
504 DECL_TEMPLATE(ALubyte, QuadChans, cubic8)
507 static const Channel X51Chans[] = { FRONT_LEFT, FRONT_RIGHT,
508 FRONT_CENTER, LFE,
509 BACK_LEFT, BACK_RIGHT };
510 DECL_TEMPLATE(ALfloat, X51Chans, point32)
511 DECL_TEMPLATE(ALfloat, X51Chans, lerp32)
512 DECL_TEMPLATE(ALfloat, X51Chans, cubic32)
514 DECL_TEMPLATE(ALshort, X51Chans, point16)
515 DECL_TEMPLATE(ALshort, X51Chans, lerp16)
516 DECL_TEMPLATE(ALshort, X51Chans, cubic16)
518 DECL_TEMPLATE(ALubyte, X51Chans, point8)
519 DECL_TEMPLATE(ALubyte, X51Chans, lerp8)
520 DECL_TEMPLATE(ALubyte, X51Chans, cubic8)
523 static const Channel X61Chans[] = { FRONT_LEFT, FRONT_RIGHT,
524 FRONT_CENTER, LFE,
525 BACK_CENTER,
526 SIDE_LEFT, SIDE_RIGHT };
527 DECL_TEMPLATE(ALfloat, X61Chans, point32)
528 DECL_TEMPLATE(ALfloat, X61Chans, lerp32)
529 DECL_TEMPLATE(ALfloat, X61Chans, cubic32)
531 DECL_TEMPLATE(ALshort, X61Chans, point16)
532 DECL_TEMPLATE(ALshort, X61Chans, lerp16)
533 DECL_TEMPLATE(ALshort, X61Chans, cubic16)
535 DECL_TEMPLATE(ALubyte, X61Chans, point8)
536 DECL_TEMPLATE(ALubyte, X61Chans, lerp8)
537 DECL_TEMPLATE(ALubyte, X61Chans, cubic8)
540 static const Channel X71Chans[] = { FRONT_LEFT, FRONT_RIGHT,
541 FRONT_CENTER, LFE,
542 BACK_LEFT, BACK_RIGHT,
543 SIDE_LEFT, SIDE_RIGHT };
544 DECL_TEMPLATE(ALfloat, X71Chans, point32)
545 DECL_TEMPLATE(ALfloat, X71Chans, lerp32)
546 DECL_TEMPLATE(ALfloat, X71Chans, cubic32)
548 DECL_TEMPLATE(ALshort, X71Chans, point16)
549 DECL_TEMPLATE(ALshort, X71Chans, lerp16)
550 DECL_TEMPLATE(ALshort, X71Chans, cubic16)
552 DECL_TEMPLATE(ALubyte, X71Chans, point8)
553 DECL_TEMPLATE(ALubyte, X71Chans, lerp8)
554 DECL_TEMPLATE(ALubyte, X71Chans, cubic8)
556 #undef DECL_TEMPLATE
559 #define DECL_TEMPLATE(T, sampler) \
560 static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, ALuint Channels, \
561 const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
562 ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
564 switch(Channels) \
566 case 1: /* Mono */ \
567 Mix_##T##_Mono_##sampler(Source, Device, \
568 Data, DataPosInt, DataPosFrac, \
569 j, SamplesToDo, BufferSize); \
570 break; \
571 case 2: /* Stereo */ \
572 Mix_##T##_Stereo_##sampler(Source, Device, \
573 Data, DataPosInt, DataPosFrac, \
574 j, SamplesToDo, BufferSize); \
575 break; \
576 case 4: /* Quad */ \
577 Mix_##T##_QuadChans_##sampler(Source, Device, \
578 Data, DataPosInt, DataPosFrac, \
579 j, SamplesToDo, BufferSize); \
580 break; \
581 case 6: /* 5.1 */ \
582 Mix_##T##_X51Chans_##sampler(Source, Device, \
583 Data, DataPosInt, DataPosFrac, \
584 j, SamplesToDo, BufferSize); \
585 break; \
586 case 7: /* 6.1 */ \
587 Mix_##T##_X61Chans_##sampler(Source, Device, \
588 Data, DataPosInt, DataPosFrac, \
589 j, SamplesToDo, BufferSize); \
590 break; \
591 case 8: /* 7.1 */ \
592 Mix_##T##_X71Chans_##sampler(Source, Device, \
593 Data, DataPosInt, DataPosFrac, \
594 j, SamplesToDo, BufferSize); \
595 break; \
599 DECL_TEMPLATE(ALfloat, point32)
600 DECL_TEMPLATE(ALfloat, lerp32)
601 DECL_TEMPLATE(ALfloat, cubic32)
603 DECL_TEMPLATE(ALshort, point16)
604 DECL_TEMPLATE(ALshort, lerp16)
605 DECL_TEMPLATE(ALshort, cubic16)
607 DECL_TEMPLATE(ALubyte, point8)
608 DECL_TEMPLATE(ALubyte, lerp8)
609 DECL_TEMPLATE(ALubyte, cubic8)
611 #undef DECL_TEMPLATE
614 /* Stack data size can be whatever. Larger values need more stack, while
615 * smaller values may need more iterations */
616 #ifndef STACK_DATA_SIZE
617 #define STACK_DATA_SIZE 16384
618 #endif
620 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
622 ALbufferlistitem *BufferListItem;
623 ALuint FrameSize, Channels, Bytes;
624 ALuint DataPosInt, DataPosFrac;
625 ALuint BuffersPlayed;
626 ALboolean Looping;
627 ALuint increment;
628 ALenum State;
629 ALuint i, j;
630 ALint64 DataSize64;
632 /* Get source info */
633 State = Source->state;
634 BuffersPlayed = Source->BuffersPlayed;
635 DataPosInt = Source->position;
636 DataPosFrac = Source->position_fraction;
637 Looping = Source->bLooping;
638 increment = Source->Params.Step;
640 /* Get buffer info */
641 FrameSize = Channels = Bytes = 0;
642 BufferListItem = Source->queue;
643 for(i = 0;i < Source->BuffersInQueue;i++)
645 const ALbuffer *ALBuffer;
646 if((ALBuffer=BufferListItem->buffer) != NULL)
648 FrameSize = aluFrameSizeFromFormat(ALBuffer->format);
649 Channels = aluChannelsFromFormat(ALBuffer->format);
650 Bytes = aluBytesFromFormat(ALBuffer->format);
651 break;
653 BufferListItem = BufferListItem->next;
656 /* Get current buffer queue item */
657 BufferListItem = Source->queue;
658 for(i = 0;i < BuffersPlayed;i++)
659 BufferListItem = BufferListItem->next;
661 j = 0;
662 do {
663 ALubyte StackData[STACK_DATA_SIZE];
664 ALubyte *SrcData = StackData;
665 ALuint SrcDataSize = 0;
666 ALuint BufferSize;
668 /* Figure out how many buffer bytes will be needed */
669 DataSize64 = SamplesToDo-j+1;
670 DataSize64 *= increment;
671 DataSize64 += DataPosFrac+FRACTIONMASK;
672 DataSize64 >>= FRACTIONBITS;
673 DataSize64 += BUFFER_PADDING+BUFFER_PREPADDING;
674 DataSize64 *= FrameSize;
676 BufferSize = min(DataSize64, STACK_DATA_SIZE);
677 BufferSize -= BufferSize%FrameSize;
679 if(Source->lSourceType == AL_STATIC)
681 const ALbuffer *ALBuffer = Source->Buffer;
682 const ALubyte *Data = ALBuffer->data;
683 ALuint DataSize;
684 ALuint pos;
686 /* If current pos is beyond the loop range, do not loop */
687 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
689 Looping = AL_FALSE;
691 if(DataPosInt >= BUFFER_PREPADDING)
692 pos = (DataPosInt-BUFFER_PREPADDING)*FrameSize;
693 else
695 DataSize = (BUFFER_PREPADDING-DataPosInt)*FrameSize;
696 DataSize = min(BufferSize, DataSize);
698 memset(&SrcData[SrcDataSize], (Bytes==1)?0x80:0, DataSize);
699 SrcDataSize += DataSize;
700 BufferSize -= DataSize;
702 pos = 0;
705 /* Copy what's left to play in the source buffer, and clear the
706 * rest of the temp buffer */
707 DataSize = ALBuffer->size - pos;
708 DataSize = min(BufferSize, DataSize);
710 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
711 SrcDataSize += DataSize;
712 BufferSize -= DataSize;
714 memset(&SrcData[SrcDataSize], (Bytes==1)?0x80:0, BufferSize);
715 SrcDataSize += BufferSize;
716 BufferSize -= BufferSize;
718 else
720 ALuint LoopStart = ALBuffer->LoopStart;
721 ALuint LoopEnd = ALBuffer->LoopEnd;
723 if(DataPosInt >= LoopStart)
725 pos = DataPosInt-LoopStart;
726 while(pos < BUFFER_PREPADDING)
727 pos += LoopEnd-LoopStart;
728 pos -= BUFFER_PREPADDING;
729 pos += LoopStart;
730 pos *= FrameSize;
732 else if(DataPosInt >= BUFFER_PREPADDING)
733 pos = (DataPosInt-BUFFER_PREPADDING)*FrameSize;
734 else
736 DataSize = (BUFFER_PREPADDING-DataPosInt)*FrameSize;
737 DataSize = min(BufferSize, DataSize);
739 memset(&SrcData[SrcDataSize], (Bytes==1)?0x80:0, DataSize);
740 SrcDataSize += DataSize;
741 BufferSize -= DataSize;
743 pos = 0;
746 /* Copy what's left of this loop iteration, then copy repeats
747 * of the loop section */
748 DataSize = LoopEnd*FrameSize - pos;
749 DataSize = min(BufferSize, DataSize);
751 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
752 SrcDataSize += DataSize;
753 BufferSize -= DataSize;
755 DataSize = (LoopEnd-LoopStart) * FrameSize;
756 while(BufferSize > 0)
758 DataSize = min(BufferSize, DataSize);
760 memcpy(&SrcData[SrcDataSize], &Data[LoopStart*FrameSize], DataSize);
761 SrcDataSize += DataSize;
762 BufferSize -= DataSize;
766 else
768 /* Crawl the buffer queue to fill in the temp buffer */
769 ALbufferlistitem *BufferListIter = BufferListItem;
770 ALuint pos;
772 if(DataPosInt >= BUFFER_PREPADDING)
773 pos = (DataPosInt-BUFFER_PREPADDING)*FrameSize;
774 else
776 pos = (BUFFER_PREPADDING-DataPosInt)*FrameSize;
777 while(pos > 0)
779 if(!BufferListIter->prev && !Looping)
781 ALuint DataSize = min(BufferSize, pos);
783 memset(&SrcData[SrcDataSize], (Bytes==1)?0x80:0, DataSize);
784 SrcDataSize += DataSize;
785 BufferSize -= DataSize;
787 pos = 0;
788 break;
791 if(Looping)
793 while(BufferListIter->next)
794 BufferListIter = BufferListIter->next;
796 else
797 BufferListIter = BufferListIter->prev;
799 if(BufferListIter->buffer)
801 if((ALuint)BufferListIter->buffer->size > pos)
803 pos = BufferListIter->buffer->size - pos;
804 break;
806 pos -= BufferListIter->buffer->size;
811 while(BufferListIter && BufferSize > 0)
813 const ALbuffer *ALBuffer;
814 if((ALBuffer=BufferListIter->buffer) != NULL)
816 const ALubyte *Data = ALBuffer->data;
817 ALuint DataSize = ALBuffer->size;
819 /* Skip the data already played */
820 if(DataSize <= pos)
821 pos -= DataSize;
822 else
824 Data += pos;
825 DataSize -= pos;
826 pos -= pos;
828 DataSize = min(BufferSize, DataSize);
829 memcpy(&SrcData[SrcDataSize], Data, DataSize);
830 SrcDataSize += DataSize;
831 BufferSize -= DataSize;
834 BufferListIter = BufferListIter->next;
835 if(!BufferListIter && Looping)
836 BufferListIter = Source->queue;
837 else if(!BufferListIter)
839 memset(&SrcData[SrcDataSize], (Bytes==1)?0x80:0, BufferSize);
840 SrcDataSize += BufferSize;
841 BufferSize -= BufferSize;
846 /* Figure out how many samples we can mix. */
847 DataSize64 = SrcDataSize / FrameSize;
848 DataSize64 -= BUFFER_PADDING+BUFFER_PREPADDING;
849 DataSize64 <<= FRACTIONBITS;
850 DataSize64 -= increment;
852 BufferSize = (ALuint)((DataSize64-DataPosFrac+(increment-1)) / increment);
853 BufferSize = min(BufferSize, (SamplesToDo-j));
854 if(BufferSize == 0)
856 AL_PRINT("No samples to mix! Pitch too high (%u, %g)?\n",
857 increment, increment/(double)(1<<FRACTIONBITS));
858 State = AL_STOPPED;
859 BufferListItem = Source->queue;
860 BuffersPlayed = Source->BuffersInQueue;
861 DataPosInt = 0;
862 DataPosFrac = 0;
863 break;
866 SrcData += BUFFER_PREPADDING*FrameSize;
867 switch((increment != (1<<FRACTIONBITS)) ? Source->Resampler : POINT_RESAMPLER)
869 case POINT_RESAMPLER:
870 if(Bytes == 4)
871 Mix_ALfloat_point32(Source, Device, Channels,
872 SrcData, &DataPosInt, &DataPosFrac,
873 j, SamplesToDo, BufferSize);
874 else if(Bytes == 2)
875 Mix_ALshort_point16(Source, Device, Channels,
876 SrcData, &DataPosInt, &DataPosFrac,
877 j, SamplesToDo, BufferSize);
878 else if(Bytes == 1)
879 Mix_ALubyte_point8(Source, Device, Channels,
880 SrcData, &DataPosInt, &DataPosFrac,
881 j, SamplesToDo, BufferSize);
882 break;
883 case LINEAR_RESAMPLER:
884 if(Bytes == 4)
885 Mix_ALfloat_lerp32(Source, Device, Channels,
886 SrcData, &DataPosInt, &DataPosFrac,
887 j, SamplesToDo, BufferSize);
888 else if(Bytes == 2)
889 Mix_ALshort_lerp16(Source, Device, Channels,
890 SrcData, &DataPosInt, &DataPosFrac,
891 j, SamplesToDo, BufferSize);
892 else if(Bytes == 1)
893 Mix_ALubyte_lerp8(Source, Device, Channels,
894 SrcData, &DataPosInt, &DataPosFrac,
895 j, SamplesToDo, BufferSize);
896 break;
897 case CUBIC_RESAMPLER:
898 if(Bytes == 4)
899 Mix_ALfloat_cubic32(Source, Device, Channels,
900 SrcData, &DataPosInt, &DataPosFrac,
901 j, SamplesToDo, BufferSize);
902 else if(Bytes == 2)
903 Mix_ALshort_cubic16(Source, Device, Channels,
904 SrcData, &DataPosInt, &DataPosFrac,
905 j, SamplesToDo, BufferSize);
906 else if(Bytes == 1)
907 Mix_ALubyte_cubic8(Source, Device, Channels,
908 SrcData, &DataPosInt, &DataPosFrac,
909 j, SamplesToDo, BufferSize);
910 break;
911 case RESAMPLER_MIN:
912 case RESAMPLER_MAX:
913 break;
915 j += BufferSize;
917 /* Handle looping sources */
918 while(1)
920 const ALbuffer *ALBuffer;
921 ALuint DataSize = 0;
922 ALuint LoopStart = 0;
923 ALuint LoopEnd = 0;
925 if((ALBuffer=BufferListItem->buffer) != NULL)
927 DataSize = ALBuffer->size / FrameSize;
928 if(DataSize > DataPosInt)
929 break;
930 LoopStart = ALBuffer->LoopStart;
931 LoopEnd = ALBuffer->LoopEnd;
934 if(BufferListItem->next)
936 BufferListItem = BufferListItem->next;
937 BuffersPlayed++;
939 else if(Looping)
941 BufferListItem = Source->queue;
942 BuffersPlayed = 0;
943 if(Source->lSourceType == AL_STATIC)
945 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
946 break;
949 else
951 State = AL_STOPPED;
952 BufferListItem = Source->queue;
953 BuffersPlayed = Source->BuffersInQueue;
954 DataPosInt = 0;
955 DataPosFrac = 0;
956 break;
959 DataPosInt -= DataSize;
961 } while(State == AL_PLAYING && j < SamplesToDo);
963 /* Update source info */
964 Source->state = State;
965 Source->BuffersPlayed = BuffersPlayed;
966 Source->position = DataPosInt;
967 Source->position_fraction = DataPosFrac;
968 Source->Buffer = BufferListItem->buffer;