Don't limit IMA4 decoding to 2 channels
[openal-soft.git] / Alc / mixer.c
blobbe1e226880e918efefc8a18c8faf560c33db66ed
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/FRACTIONONE)); }
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/FRACTIONONE)); }
48 static __inline ALdouble point16(const ALshort *vals, ALint step, ALint frac)
49 { return vals[0] * (1.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/FRACTIONONE)) * (1.0/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/FRACTIONONE)) * (1.0/32767.0); }
56 static __inline ALdouble point8(const ALubyte *vals, ALint step, ALint frac)
57 { return (vals[0]-128.0) * (1.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],
60 frac * (1.0/FRACTIONONE))-128.0) * (1.0/127.0); }
61 static __inline ALdouble cubic8(const ALubyte *vals, ALint step, ALint frac)
62 { return (cubic(vals[-step], vals[0], vals[step], vals[step+step],
63 frac * (1.0/FRACTIONONE))-128.0) * (1.0/127.0); }
66 #define DECL_TEMPLATE(T, sampler) \
67 static void Mix_##T##_Mono_##sampler(ALsource *Source, ALCdevice *Device, \
68 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
69 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
70 { \
71 ALfloat (*DryBuffer)[MAXCHANNELS]; \
72 ALfloat *ClickRemoval, *PendingClicks; \
73 ALuint pos, frac; \
74 ALfloat DrySend[MAXCHANNELS]; \
75 FILTER *DryFilter; \
76 ALuint BufferIdx; \
77 ALuint increment; \
78 ALuint i, out; \
79 ALfloat value; \
81 increment = Source->Params.Step; \
83 DryBuffer = Device->DryBuffer; \
84 ClickRemoval = Device->ClickRemoval; \
85 PendingClicks = Device->PendingClicks; \
86 DryFilter = &Source->Params.iirFilter; \
87 for(i = 0;i < MAXCHANNELS;i++) \
88 DrySend[i] = Source->Params.DryGains[i]; \
90 pos = 0; \
91 frac = *DataPosFrac; \
93 if(OutPos == 0) \
94 { \
95 value = sampler(data+pos, 1, frac); \
97 value = lpFilter4PC(DryFilter, 0, value); \
98 ClickRemoval[FRONT_LEFT] -= value*DrySend[FRONT_LEFT]; \
99 ClickRemoval[FRONT_RIGHT] -= value*DrySend[FRONT_RIGHT]; \
100 ClickRemoval[SIDE_LEFT] -= value*DrySend[SIDE_LEFT]; \
101 ClickRemoval[SIDE_RIGHT] -= value*DrySend[SIDE_RIGHT]; \
102 ClickRemoval[BACK_LEFT] -= value*DrySend[BACK_LEFT]; \
103 ClickRemoval[BACK_RIGHT] -= value*DrySend[BACK_RIGHT]; \
104 ClickRemoval[FRONT_CENTER] -= value*DrySend[FRONT_CENTER]; \
105 ClickRemoval[BACK_CENTER] -= value*DrySend[BACK_CENTER]; \
107 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
109 /* First order interpolator */ \
110 value = sampler(data+pos, 1, frac); \
112 /* Direct path final mix buffer and panning */ \
113 value = lpFilter4P(DryFilter, 0, value); \
114 DryBuffer[OutPos][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; \
115 DryBuffer[OutPos][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; \
116 DryBuffer[OutPos][SIDE_LEFT] += value*DrySend[SIDE_LEFT]; \
117 DryBuffer[OutPos][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; \
118 DryBuffer[OutPos][BACK_LEFT] += value*DrySend[BACK_LEFT]; \
119 DryBuffer[OutPos][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; \
120 DryBuffer[OutPos][FRONT_CENTER] += value*DrySend[FRONT_CENTER]; \
121 DryBuffer[OutPos][BACK_CENTER] += value*DrySend[BACK_CENTER]; \
123 frac += increment; \
124 pos += frac>>FRACTIONBITS; \
125 frac &= FRACTIONMASK; \
126 OutPos++; \
128 if(OutPos == SamplesToDo) \
130 value = sampler(data+pos, 1, frac); \
132 value = lpFilter4PC(DryFilter, 0, value); \
133 PendingClicks[FRONT_LEFT] += value*DrySend[FRONT_LEFT]; \
134 PendingClicks[FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; \
135 PendingClicks[SIDE_LEFT] += value*DrySend[SIDE_LEFT]; \
136 PendingClicks[SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; \
137 PendingClicks[BACK_LEFT] += value*DrySend[BACK_LEFT]; \
138 PendingClicks[BACK_RIGHT] += value*DrySend[BACK_RIGHT]; \
139 PendingClicks[FRONT_CENTER] += value*DrySend[FRONT_CENTER]; \
140 PendingClicks[BACK_CENTER] += value*DrySend[BACK_CENTER]; \
143 for(out = 0;out < Device->NumAuxSends;out++) \
145 ALfloat WetSend; \
146 ALfloat *WetBuffer; \
147 ALfloat *WetClickRemoval; \
148 ALfloat *WetPendingClicks; \
149 FILTER *WetFilter; \
151 if(!Source->Send[out].Slot || \
152 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
153 continue; \
155 WetBuffer = Source->Send[out].Slot->WetBuffer; \
156 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
157 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
158 WetFilter = &Source->Params.Send[out].iirFilter; \
159 WetSend = Source->Params.Send[out].WetGain; \
161 pos = 0; \
162 frac = *DataPosFrac; \
163 OutPos -= BufferSize; \
165 if(OutPos == 0) \
167 value = sampler(data+pos, 1, frac); \
169 value = lpFilter2PC(WetFilter, 0, value); \
170 WetClickRemoval[0] -= value*WetSend; \
172 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
174 /* First order interpolator */ \
175 value = sampler(data+pos, 1, frac); \
177 /* Room path final mix buffer and panning */ \
178 value = lpFilter2P(WetFilter, 0, value); \
179 WetBuffer[OutPos] += value*WetSend; \
181 frac += increment; \
182 pos += frac>>FRACTIONBITS; \
183 frac &= FRACTIONMASK; \
184 OutPos++; \
186 if(OutPos == SamplesToDo) \
188 value = sampler(data+pos, 1, frac); \
190 value = lpFilter2PC(WetFilter, 0, value); \
191 WetPendingClicks[0] += value*WetSend; \
194 *DataPosInt += pos; \
195 *DataPosFrac = frac; \
198 DECL_TEMPLATE(ALfloat, point32)
199 DECL_TEMPLATE(ALfloat, lerp32)
200 DECL_TEMPLATE(ALfloat, cubic32)
202 DECL_TEMPLATE(ALshort, point16)
203 DECL_TEMPLATE(ALshort, lerp16)
204 DECL_TEMPLATE(ALshort, cubic16)
206 DECL_TEMPLATE(ALubyte, point8)
207 DECL_TEMPLATE(ALubyte, lerp8)
208 DECL_TEMPLATE(ALubyte, cubic8)
210 #undef DECL_TEMPLATE
213 #define DECL_TEMPLATE(T, sampler) \
214 static void Mix_##T##_Stereo_##sampler(ALsource *Source, ALCdevice *Device, \
215 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
216 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
218 static const ALuint Channels = 2; \
219 static const Channel chans[] = { \
220 FRONT_LEFT, FRONT_RIGHT, \
221 SIDE_LEFT, SIDE_RIGHT, \
222 BACK_LEFT, BACK_RIGHT \
223 }; \
224 const ALfloat scaler = 1.0f/Channels; \
225 ALfloat (*DryBuffer)[MAXCHANNELS]; \
226 ALfloat *ClickRemoval, *PendingClicks; \
227 ALuint pos, frac; \
228 ALfloat DrySend[MAXCHANNELS]; \
229 FILTER *DryFilter; \
230 ALuint BufferIdx; \
231 ALuint increment; \
232 ALuint i, out; \
233 ALfloat value; \
235 increment = Source->Params.Step; \
237 DryBuffer = Device->DryBuffer; \
238 ClickRemoval = Device->ClickRemoval; \
239 PendingClicks = Device->PendingClicks; \
240 DryFilter = &Source->Params.iirFilter; \
241 for(i = 0;i < MAXCHANNELS;i++) \
242 DrySend[i] = Source->Params.DryGains[i]; \
244 pos = 0; \
245 frac = *DataPosFrac; \
247 if(OutPos == 0) \
249 for(i = 0;i < Channels;i++) \
251 value = sampler(data + pos*Channels + i, Channels, frac); \
253 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
254 ClickRemoval[chans[i+0]] -= value*DrySend[chans[i+0]]; \
255 ClickRemoval[chans[i+2]] -= value*DrySend[chans[i+2]]; \
256 ClickRemoval[chans[i+4]] -= value*DrySend[chans[i+4]]; \
259 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
261 for(i = 0;i < Channels;i++) \
263 value = sampler(data + pos*Channels + i, Channels, frac); \
265 value = lpFilter2P(DryFilter, chans[i]*2, value); \
266 DryBuffer[OutPos][chans[i+0]] += value*DrySend[chans[i+0]]; \
267 DryBuffer[OutPos][chans[i+2]] += value*DrySend[chans[i+2]]; \
268 DryBuffer[OutPos][chans[i+4]] += value*DrySend[chans[i+4]]; \
271 frac += increment; \
272 pos += frac>>FRACTIONBITS; \
273 frac &= FRACTIONMASK; \
274 OutPos++; \
276 if(OutPos == SamplesToDo) \
278 for(i = 0;i < Channels;i++) \
280 value = sampler(data + pos*Channels + i, Channels, frac); \
282 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
283 PendingClicks[chans[i+0]] += value*DrySend[chans[i+0]]; \
284 PendingClicks[chans[i+2]] += value*DrySend[chans[i+2]]; \
285 PendingClicks[chans[i+4]] += value*DrySend[chans[i+4]]; \
289 for(out = 0;out < Device->NumAuxSends;out++) \
291 ALfloat WetSend; \
292 ALfloat *WetBuffer; \
293 ALfloat *WetClickRemoval; \
294 ALfloat *WetPendingClicks; \
295 FILTER *WetFilter; \
297 if(!Source->Send[out].Slot || \
298 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
299 continue; \
301 WetBuffer = Source->Send[out].Slot->WetBuffer; \
302 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
303 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
304 WetFilter = &Source->Params.Send[out].iirFilter; \
305 WetSend = Source->Params.Send[out].WetGain; \
307 pos = 0; \
308 frac = *DataPosFrac; \
309 OutPos -= BufferSize; \
311 if(OutPos == 0) \
313 for(i = 0;i < Channels;i++) \
315 value = sampler(data + pos*Channels + i, Channels, frac); \
317 value = lpFilter1PC(WetFilter, chans[i], value); \
318 WetClickRemoval[0] -= value*WetSend * scaler; \
321 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
323 for(i = 0;i < Channels;i++) \
325 value = sampler(data + pos*Channels + i, Channels, frac); \
327 value = lpFilter1P(WetFilter, chans[i], value); \
328 WetBuffer[OutPos] += value*WetSend * scaler; \
331 frac += increment; \
332 pos += frac>>FRACTIONBITS; \
333 frac &= FRACTIONMASK; \
334 OutPos++; \
336 if(OutPos == SamplesToDo) \
338 for(i = 0;i < Channels;i++) \
340 value = sampler(data + pos*Channels + i, Channels, frac); \
342 value = lpFilter1PC(WetFilter, chans[i], value); \
343 WetPendingClicks[0] += value*WetSend * scaler; \
347 *DataPosInt += pos; \
348 *DataPosFrac = frac; \
351 DECL_TEMPLATE(ALfloat, point32)
352 DECL_TEMPLATE(ALfloat, lerp32)
353 DECL_TEMPLATE(ALfloat, cubic32)
355 DECL_TEMPLATE(ALshort, point16)
356 DECL_TEMPLATE(ALshort, lerp16)
357 DECL_TEMPLATE(ALshort, cubic16)
359 DECL_TEMPLATE(ALubyte, point8)
360 DECL_TEMPLATE(ALubyte, lerp8)
361 DECL_TEMPLATE(ALubyte, cubic8)
363 #undef DECL_TEMPLATE
366 #define DECL_TEMPLATE(T, chans, sampler) \
367 static void Mix_##T##_##chans##_##sampler(ALsource *Source, ALCdevice *Device,\
368 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
369 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
371 static const ALuint Channels = sizeof(chans)/sizeof(chans[0]); \
372 const ALfloat scaler = 1.0f/Channels; \
373 ALfloat (*DryBuffer)[MAXCHANNELS]; \
374 ALfloat *ClickRemoval, *PendingClicks; \
375 ALuint pos, frac; \
376 ALfloat DrySend[MAXCHANNELS]; \
377 FILTER *DryFilter; \
378 ALuint BufferIdx; \
379 ALuint increment; \
380 ALuint i, out; \
381 ALfloat value; \
383 increment = Source->Params.Step; \
385 DryBuffer = Device->DryBuffer; \
386 ClickRemoval = Device->ClickRemoval; \
387 PendingClicks = Device->PendingClicks; \
388 DryFilter = &Source->Params.iirFilter; \
389 for(i = 0;i < MAXCHANNELS;i++) \
390 DrySend[i] = Source->Params.DryGains[i]; \
392 pos = 0; \
393 frac = *DataPosFrac; \
395 if(OutPos == 0) \
397 for(i = 0;i < Channels;i++) \
399 value = sampler(data + pos*Channels + i, Channels, frac); \
401 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
402 ClickRemoval[chans[i]] -= value*DrySend[chans[i]]; \
405 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
407 for(i = 0;i < Channels;i++) \
409 value = sampler(data + pos*Channels + i, Channels, frac); \
411 value = lpFilter2P(DryFilter, chans[i]*2, value); \
412 DryBuffer[OutPos][chans[i]] += value*DrySend[chans[i]]; \
415 frac += increment; \
416 pos += frac>>FRACTIONBITS; \
417 frac &= FRACTIONMASK; \
418 OutPos++; \
420 if(OutPos == SamplesToDo) \
422 for(i = 0;i < Channels;i++) \
424 value = sampler(data + pos*Channels + i, Channels, frac); \
426 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
427 PendingClicks[chans[i]] += value*DrySend[chans[i]]; \
431 for(out = 0;out < Device->NumAuxSends;out++) \
433 ALfloat WetSend; \
434 ALfloat *WetBuffer; \
435 ALfloat *WetClickRemoval; \
436 ALfloat *WetPendingClicks; \
437 FILTER *WetFilter; \
439 if(!Source->Send[out].Slot || \
440 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
441 continue; \
443 WetBuffer = Source->Send[out].Slot->WetBuffer; \
444 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
445 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
446 WetFilter = &Source->Params.Send[out].iirFilter; \
447 WetSend = Source->Params.Send[out].WetGain; \
449 pos = 0; \
450 frac = *DataPosFrac; \
451 OutPos -= BufferSize; \
453 if(OutPos == 0) \
455 for(i = 0;i < Channels;i++) \
457 value = sampler(data + pos*Channels + i, Channels, frac); \
459 value = lpFilter1PC(WetFilter, chans[i], value); \
460 WetClickRemoval[0] -= value*WetSend * scaler; \
463 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
465 for(i = 0;i < Channels;i++) \
467 value = sampler(data + pos*Channels + i, Channels, frac); \
469 value = lpFilter1P(WetFilter, chans[i], value); \
470 WetBuffer[OutPos] += value*WetSend * scaler; \
473 frac += increment; \
474 pos += frac>>FRACTIONBITS; \
475 frac &= FRACTIONMASK; \
476 OutPos++; \
478 if(OutPos == SamplesToDo) \
480 for(i = 0;i < Channels;i++) \
482 value = sampler(data + pos*Channels + i, Channels, frac); \
484 value = lpFilter1PC(WetFilter, chans[i], value); \
485 WetPendingClicks[0] += value*WetSend * scaler; \
489 *DataPosInt += pos; \
490 *DataPosFrac = frac; \
493 static const Channel QuadChans[] = { FRONT_LEFT, FRONT_RIGHT,
494 BACK_LEFT, BACK_RIGHT };
495 DECL_TEMPLATE(ALfloat, QuadChans, point32)
496 DECL_TEMPLATE(ALfloat, QuadChans, lerp32)
497 DECL_TEMPLATE(ALfloat, QuadChans, cubic32)
499 DECL_TEMPLATE(ALshort, QuadChans, point16)
500 DECL_TEMPLATE(ALshort, QuadChans, lerp16)
501 DECL_TEMPLATE(ALshort, QuadChans, cubic16)
503 DECL_TEMPLATE(ALubyte, QuadChans, point8)
504 DECL_TEMPLATE(ALubyte, QuadChans, lerp8)
505 DECL_TEMPLATE(ALubyte, QuadChans, cubic8)
508 static const Channel RearChans[] = { BACK_LEFT, BACK_RIGHT };
509 DECL_TEMPLATE(ALfloat, RearChans, point32)
510 DECL_TEMPLATE(ALfloat, RearChans, lerp32)
511 DECL_TEMPLATE(ALfloat, RearChans, cubic32)
513 DECL_TEMPLATE(ALshort, RearChans, point16)
514 DECL_TEMPLATE(ALshort, RearChans, lerp16)
515 DECL_TEMPLATE(ALshort, RearChans, cubic16)
517 DECL_TEMPLATE(ALubyte, RearChans, point8)
518 DECL_TEMPLATE(ALubyte, RearChans, lerp8)
519 DECL_TEMPLATE(ALubyte, RearChans, cubic8)
522 static const Channel X51Chans[] = { FRONT_LEFT, FRONT_RIGHT,
523 FRONT_CENTER, LFE,
524 BACK_LEFT, BACK_RIGHT };
525 DECL_TEMPLATE(ALfloat, X51Chans, point32)
526 DECL_TEMPLATE(ALfloat, X51Chans, lerp32)
527 DECL_TEMPLATE(ALfloat, X51Chans, cubic32)
529 DECL_TEMPLATE(ALshort, X51Chans, point16)
530 DECL_TEMPLATE(ALshort, X51Chans, lerp16)
531 DECL_TEMPLATE(ALshort, X51Chans, cubic16)
533 DECL_TEMPLATE(ALubyte, X51Chans, point8)
534 DECL_TEMPLATE(ALubyte, X51Chans, lerp8)
535 DECL_TEMPLATE(ALubyte, X51Chans, cubic8)
538 static const Channel X61Chans[] = { FRONT_LEFT, FRONT_RIGHT,
539 FRONT_CENTER, LFE,
540 BACK_CENTER,
541 SIDE_LEFT, SIDE_RIGHT };
542 DECL_TEMPLATE(ALfloat, X61Chans, point32)
543 DECL_TEMPLATE(ALfloat, X61Chans, lerp32)
544 DECL_TEMPLATE(ALfloat, X61Chans, cubic32)
546 DECL_TEMPLATE(ALshort, X61Chans, point16)
547 DECL_TEMPLATE(ALshort, X61Chans, lerp16)
548 DECL_TEMPLATE(ALshort, X61Chans, cubic16)
550 DECL_TEMPLATE(ALubyte, X61Chans, point8)
551 DECL_TEMPLATE(ALubyte, X61Chans, lerp8)
552 DECL_TEMPLATE(ALubyte, X61Chans, cubic8)
555 static const Channel X71Chans[] = { FRONT_LEFT, FRONT_RIGHT,
556 FRONT_CENTER, LFE,
557 BACK_LEFT, BACK_RIGHT,
558 SIDE_LEFT, SIDE_RIGHT };
559 DECL_TEMPLATE(ALfloat, X71Chans, point32)
560 DECL_TEMPLATE(ALfloat, X71Chans, lerp32)
561 DECL_TEMPLATE(ALfloat, X71Chans, cubic32)
563 DECL_TEMPLATE(ALshort, X71Chans, point16)
564 DECL_TEMPLATE(ALshort, X71Chans, lerp16)
565 DECL_TEMPLATE(ALshort, X71Chans, cubic16)
567 DECL_TEMPLATE(ALubyte, X71Chans, point8)
568 DECL_TEMPLATE(ALubyte, X71Chans, lerp8)
569 DECL_TEMPLATE(ALubyte, X71Chans, cubic8)
571 #undef DECL_TEMPLATE
574 #define DECL_TEMPLATE(T, sampler) \
575 static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
576 enum FmtChannels FmtChannels, \
577 const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
578 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
580 switch(FmtChannels) \
582 case FmtMono: \
583 Mix_##T##_Mono_##sampler(Source, Device, \
584 Data, DataPosInt, DataPosFrac, \
585 OutPos, SamplesToDo, BufferSize); \
586 break; \
587 case FmtStereo: \
588 Mix_##T##_Stereo_##sampler(Source, Device, \
589 Data, DataPosInt, DataPosFrac, \
590 OutPos, SamplesToDo, BufferSize); \
591 break; \
592 case FmtQuad: \
593 Mix_##T##_QuadChans_##sampler(Source, Device, \
594 Data, DataPosInt, DataPosFrac, \
595 OutPos, SamplesToDo, BufferSize); \
596 break; \
597 case FmtRear: \
598 Mix_##T##_RearChans_##sampler(Source, Device, \
599 Data, DataPosInt, DataPosFrac, \
600 OutPos, SamplesToDo, BufferSize); \
601 break; \
602 case FmtX51: \
603 Mix_##T##_X51Chans_##sampler(Source, Device, \
604 Data, DataPosInt, DataPosFrac, \
605 OutPos, SamplesToDo, BufferSize); \
606 break; \
607 case FmtX61: \
608 Mix_##T##_X61Chans_##sampler(Source, Device, \
609 Data, DataPosInt, DataPosFrac, \
610 OutPos, SamplesToDo, BufferSize); \
611 break; \
612 case FmtX71: \
613 Mix_##T##_X71Chans_##sampler(Source, Device, \
614 Data, DataPosInt, DataPosFrac, \
615 OutPos, SamplesToDo, BufferSize); \
616 break; \
620 DECL_TEMPLATE(ALfloat, point32)
621 DECL_TEMPLATE(ALfloat, lerp32)
622 DECL_TEMPLATE(ALfloat, cubic32)
624 DECL_TEMPLATE(ALshort, point16)
625 DECL_TEMPLATE(ALshort, lerp16)
626 DECL_TEMPLATE(ALshort, cubic16)
628 DECL_TEMPLATE(ALubyte, point8)
629 DECL_TEMPLATE(ALubyte, lerp8)
630 DECL_TEMPLATE(ALubyte, cubic8)
632 #undef DECL_TEMPLATE
635 #define DECL_TEMPLATE(sampler) \
636 static void Mix_##sampler(ALsource *Source, ALCdevice *Device, \
637 enum FmtChannels FmtChannels, enum FmtType FmtType, \
638 const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
639 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
641 switch(FmtType) \
643 case FmtUByte: \
644 Mix_ALubyte_##sampler##8(Source, Device, FmtChannels, \
645 Data, DataPosInt, DataPosFrac, \
646 OutPos, SamplesToDo, BufferSize); \
647 break; \
649 case FmtShort: \
650 Mix_ALshort_##sampler##16(Source, Device, FmtChannels, \
651 Data, DataPosInt, DataPosFrac, \
652 OutPos, SamplesToDo, BufferSize); \
653 break; \
655 case FmtFloat: \
656 Mix_ALfloat_##sampler##32(Source, Device, FmtChannels, \
657 Data, DataPosInt, DataPosFrac, \
658 OutPos, SamplesToDo, BufferSize); \
659 break; \
663 DECL_TEMPLATE(point)
664 DECL_TEMPLATE(lerp)
665 DECL_TEMPLATE(cubic)
667 #undef DECL_TEMPLATE
670 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
672 ALbufferlistitem *BufferListItem;
673 ALuint DataPosInt, DataPosFrac;
674 enum FmtChannels FmtChannels;
675 enum FmtType FmtType;
676 ALuint BuffersPlayed;
677 ALboolean Looping;
678 ALuint increment;
679 resampler_t Resampler;
680 ALenum State;
681 ALuint OutPos;
682 ALuint FrameSize;
683 ALint64 DataSize64;
684 ALuint i;
686 /* Get source info */
687 State = Source->state;
688 BuffersPlayed = Source->BuffersPlayed;
689 DataPosInt = Source->position;
690 DataPosFrac = Source->position_fraction;
691 Looping = Source->bLooping;
692 increment = Source->Params.Step;
693 Resampler = (increment == FRACTIONONE) ? POINT_RESAMPLER :
694 Source->Resampler;
696 /* Get buffer info */
697 FrameSize = 0;
698 FmtChannels = FmtMono;
699 FmtType = FmtUByte;
700 BufferListItem = Source->queue;
701 for(i = 0;i < Source->BuffersInQueue;i++)
703 const ALbuffer *ALBuffer;
704 if((ALBuffer=BufferListItem->buffer) != NULL)
706 FmtChannels = ALBuffer->FmtChannels;
707 FmtType = ALBuffer->FmtType;
708 FrameSize = FrameSizeFromFmt(FmtChannels, FmtType);
709 break;
711 BufferListItem = BufferListItem->next;
714 /* Get current buffer queue item */
715 BufferListItem = Source->queue;
716 for(i = 0;i < BuffersPlayed;i++)
717 BufferListItem = BufferListItem->next;
719 OutPos = 0;
720 do {
721 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
722 const ALuint BufferPadding = ResamplerPadding[Resampler];
723 ALubyte StackData[STACK_DATA_SIZE];
724 ALubyte *SrcData = StackData;
725 ALuint SrcDataSize = 0;
726 ALuint BufferSize;
728 /* Figure out how many buffer bytes will be needed */
729 DataSize64 = SamplesToDo-OutPos+1;
730 DataSize64 *= increment;
731 DataSize64 += DataPosFrac+FRACTIONMASK;
732 DataSize64 >>= FRACTIONBITS;
733 DataSize64 += BufferPadding+BufferPrePadding;
734 DataSize64 *= FrameSize;
736 BufferSize = min(DataSize64, STACK_DATA_SIZE);
737 BufferSize -= BufferSize%FrameSize;
739 if(Source->lSourceType == AL_STATIC)
741 const ALbuffer *ALBuffer = Source->Buffer;
742 const ALubyte *Data = ALBuffer->data;
743 ALuint DataSize;
744 ALuint pos;
746 /* If current pos is beyond the loop range, do not loop */
747 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
749 Looping = AL_FALSE;
751 if(DataPosInt >= BufferPrePadding)
752 pos = (DataPosInt-BufferPrePadding)*FrameSize;
753 else
755 DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
756 DataSize = min(BufferSize, DataSize);
758 memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, DataSize);
759 SrcDataSize += DataSize;
760 BufferSize -= DataSize;
762 pos = 0;
765 /* Copy what's left to play in the source buffer, and clear the
766 * rest of the temp buffer */
767 DataSize = ALBuffer->size - pos;
768 DataSize = min(BufferSize, DataSize);
770 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
771 SrcDataSize += DataSize;
772 BufferSize -= DataSize;
774 memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, BufferSize);
775 SrcDataSize += BufferSize;
776 BufferSize -= BufferSize;
778 else
780 ALuint LoopStart = ALBuffer->LoopStart;
781 ALuint LoopEnd = ALBuffer->LoopEnd;
783 if(DataPosInt >= LoopStart)
785 pos = DataPosInt-LoopStart;
786 while(pos < BufferPrePadding)
787 pos += LoopEnd-LoopStart;
788 pos -= BufferPrePadding;
789 pos += LoopStart;
790 pos *= FrameSize;
792 else if(DataPosInt >= BufferPrePadding)
793 pos = (DataPosInt-BufferPrePadding)*FrameSize;
794 else
796 DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
797 DataSize = min(BufferSize, DataSize);
799 memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, DataSize);
800 SrcDataSize += DataSize;
801 BufferSize -= DataSize;
803 pos = 0;
806 /* Copy what's left of this loop iteration, then copy repeats
807 * of the loop section */
808 DataSize = LoopEnd*FrameSize - pos;
809 DataSize = min(BufferSize, DataSize);
811 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
812 SrcDataSize += DataSize;
813 BufferSize -= DataSize;
815 DataSize = (LoopEnd-LoopStart) * FrameSize;
816 while(BufferSize > 0)
818 DataSize = min(BufferSize, DataSize);
820 memcpy(&SrcData[SrcDataSize], &Data[LoopStart*FrameSize], DataSize);
821 SrcDataSize += DataSize;
822 BufferSize -= DataSize;
826 else
828 /* Crawl the buffer queue to fill in the temp buffer */
829 ALbufferlistitem *BufferListIter = BufferListItem;
830 ALuint pos;
832 if(DataPosInt >= BufferPrePadding)
833 pos = (DataPosInt-BufferPrePadding)*FrameSize;
834 else
836 pos = (BufferPrePadding-DataPosInt)*FrameSize;
837 while(pos > 0)
839 if(!BufferListIter->prev && !Looping)
841 ALuint DataSize = min(BufferSize, pos);
843 memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, DataSize);
844 SrcDataSize += DataSize;
845 BufferSize -= DataSize;
847 pos = 0;
848 break;
851 if(Looping)
853 while(BufferListIter->next)
854 BufferListIter = BufferListIter->next;
856 else
857 BufferListIter = BufferListIter->prev;
859 if(BufferListIter->buffer)
861 if((ALuint)BufferListIter->buffer->size > pos)
863 pos = BufferListIter->buffer->size - pos;
864 break;
866 pos -= BufferListIter->buffer->size;
871 while(BufferListIter && BufferSize > 0)
873 const ALbuffer *ALBuffer;
874 if((ALBuffer=BufferListIter->buffer) != NULL)
876 const ALubyte *Data = ALBuffer->data;
877 ALuint DataSize = ALBuffer->size;
879 /* Skip the data already played */
880 if(DataSize <= pos)
881 pos -= DataSize;
882 else
884 Data += pos;
885 DataSize -= pos;
886 pos -= pos;
888 DataSize = min(BufferSize, DataSize);
889 memcpy(&SrcData[SrcDataSize], Data, DataSize);
890 SrcDataSize += DataSize;
891 BufferSize -= DataSize;
894 BufferListIter = BufferListIter->next;
895 if(!BufferListIter && Looping)
896 BufferListIter = Source->queue;
897 else if(!BufferListIter)
899 memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, BufferSize);
900 SrcDataSize += BufferSize;
901 BufferSize -= BufferSize;
906 /* Figure out how many samples we can mix. */
907 DataSize64 = SrcDataSize / FrameSize;
908 DataSize64 -= BufferPadding+BufferPrePadding;
909 DataSize64 <<= FRACTIONBITS;
910 DataSize64 -= increment;
911 DataSize64 -= DataPosFrac;
913 BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
914 BufferSize = min(BufferSize, (SamplesToDo-OutPos));
916 SrcData += BufferPrePadding*FrameSize;
917 switch(Resampler)
919 case POINT_RESAMPLER:
920 Mix_point(Source, Device, FmtChannels, FmtType,
921 SrcData, &DataPosInt, &DataPosFrac,
922 OutPos, SamplesToDo, BufferSize);
923 break;
924 case LINEAR_RESAMPLER:
925 Mix_lerp(Source, Device, FmtChannels, FmtType,
926 SrcData, &DataPosInt, &DataPosFrac,
927 OutPos, SamplesToDo, BufferSize);
928 break;
929 case CUBIC_RESAMPLER:
930 Mix_cubic(Source, Device, FmtChannels, FmtType,
931 SrcData, &DataPosInt, &DataPosFrac,
932 OutPos, SamplesToDo, BufferSize);
933 break;
934 case RESAMPLER_MIN:
935 case RESAMPLER_MAX:
936 break;
938 OutPos += BufferSize;
940 /* Handle looping sources */
941 while(1)
943 const ALbuffer *ALBuffer;
944 ALuint DataSize = 0;
945 ALuint LoopStart = 0;
946 ALuint LoopEnd = 0;
948 if((ALBuffer=BufferListItem->buffer) != NULL)
950 DataSize = ALBuffer->size / FrameSize;
951 if(DataSize > DataPosInt)
952 break;
953 LoopStart = ALBuffer->LoopStart;
954 LoopEnd = ALBuffer->LoopEnd;
957 if(BufferListItem->next)
959 BufferListItem = BufferListItem->next;
960 BuffersPlayed++;
962 else if(Looping)
964 BufferListItem = Source->queue;
965 BuffersPlayed = 0;
966 if(Source->lSourceType == AL_STATIC)
968 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
969 break;
972 else
974 State = AL_STOPPED;
975 BufferListItem = Source->queue;
976 BuffersPlayed = Source->BuffersInQueue;
977 DataPosInt = 0;
978 DataPosFrac = 0;
979 break;
982 DataPosInt -= DataSize;
984 } while(State == AL_PLAYING && OutPos < SamplesToDo);
986 /* Update source info */
987 Source->state = State;
988 Source->BuffersPlayed = BuffersPlayed;
989 Source->position = DataPosInt;
990 Source->position_fraction = DataPosFrac;
991 Source->Buffer = BufferListItem->buffer;