Remove the cosine resampler
[openal-soft.git] / Alc / mixer.c
blob5d7d828d9b4ce0560889ea436b080540620b8027
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 point(ALdouble val1, ALdouble val2, ALint frac)
42 return val1;
43 (void)val2;
44 (void)frac;
46 static __inline ALdouble lerp(ALdouble val1, ALdouble val2, ALint frac)
48 val1 += ((val2-val1) * (frac * (1.0/(1<<FRACTIONBITS))));
49 return val1;
52 static __inline ALdouble point16(ALdouble val1, ALdouble val2, ALint frac)
53 { return point(val1, val2, frac) / 32767.0; }
54 static __inline ALdouble lerp16(ALdouble val1, ALdouble val2, ALint frac)
55 { return lerp(val1, val2, frac) / 32767.0; }
57 static __inline ALdouble point8(ALdouble val1, ALdouble val2, ALint frac)
58 { return (point(val1, val2, frac)-128.0) / 127.0; }
59 static __inline ALdouble lerp8(ALdouble val1, ALdouble val2, ALint frac)
60 { return (lerp(val1, val2, frac)-128.0) / 127.0; }
64 #define DECL_MIX_MONO(T,sampler) \
65 static void Mix_##T##_Mono_##sampler(ALsource *Source, ALCdevice *Device, \
66 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
67 ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
68 { \
69 ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
70 ALfloat *ClickRemoval, *PendingClicks; \
71 ALuint pos, frac; \
72 ALfloat DrySend[OUTPUTCHANNELS]; \
73 FILTER *DryFilter; \
74 ALuint BufferIdx; \
75 ALuint increment; \
76 ALuint i, out; \
77 ALfloat value; \
79 increment = Source->Params.Step; \
81 DryBuffer = Device->DryBuffer; \
82 ClickRemoval = Device->ClickRemoval; \
83 PendingClicks = Device->PendingClicks; \
84 DryFilter = &Source->Params.iirFilter; \
85 for(i = 0;i < OUTPUTCHANNELS;i++) \
86 DrySend[i] = Source->Params.DryGains[i]; \
88 pos = 0; \
89 frac = *DataPosFrac; \
91 if(j == 0) \
92 { \
93 value = sampler(data[pos], data[pos+1], frac); \
95 value = lpFilter4PC(DryFilter, 0, value); \
96 ClickRemoval[FRONT_LEFT] -= value*DrySend[FRONT_LEFT]; \
97 ClickRemoval[FRONT_RIGHT] -= value*DrySend[FRONT_RIGHT]; \
98 ClickRemoval[SIDE_LEFT] -= value*DrySend[SIDE_LEFT]; \
99 ClickRemoval[SIDE_RIGHT] -= value*DrySend[SIDE_RIGHT]; \
100 ClickRemoval[BACK_LEFT] -= value*DrySend[BACK_LEFT]; \
101 ClickRemoval[BACK_RIGHT] -= value*DrySend[BACK_RIGHT]; \
102 ClickRemoval[FRONT_CENTER] -= value*DrySend[FRONT_CENTER]; \
103 ClickRemoval[BACK_CENTER] -= value*DrySend[BACK_CENTER]; \
105 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
107 /* First order interpolator */ \
108 value = sampler(data[pos], data[pos+1], frac); \
110 /* Direct path final mix buffer and panning */ \
111 value = lpFilter4P(DryFilter, 0, value); \
112 DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; \
113 DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; \
114 DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT]; \
115 DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; \
116 DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT]; \
117 DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; \
118 DryBuffer[j][FRONT_CENTER] += value*DrySend[FRONT_CENTER]; \
119 DryBuffer[j][BACK_CENTER] += value*DrySend[BACK_CENTER]; \
121 frac += increment; \
122 pos += frac>>FRACTIONBITS; \
123 frac &= FRACTIONMASK; \
124 j++; \
126 if(j == SamplesToDo) \
128 value = sampler(data[pos], data[pos+1], frac); \
130 value = lpFilter4PC(DryFilter, 0, value); \
131 PendingClicks[FRONT_LEFT] += value*DrySend[FRONT_LEFT]; \
132 PendingClicks[FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; \
133 PendingClicks[SIDE_LEFT] += value*DrySend[SIDE_LEFT]; \
134 PendingClicks[SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; \
135 PendingClicks[BACK_LEFT] += value*DrySend[BACK_LEFT]; \
136 PendingClicks[BACK_RIGHT] += value*DrySend[BACK_RIGHT]; \
137 PendingClicks[FRONT_CENTER] += value*DrySend[FRONT_CENTER]; \
138 PendingClicks[BACK_CENTER] += value*DrySend[BACK_CENTER]; \
141 for(out = 0;out < Device->NumAuxSends;out++) \
143 ALfloat WetSend; \
144 ALfloat *WetBuffer; \
145 ALfloat *WetClickRemoval; \
146 ALfloat *WetPendingClicks; \
147 FILTER *WetFilter; \
149 if(!Source->Send[out].Slot || \
150 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
151 continue; \
153 WetBuffer = Source->Send[out].Slot->WetBuffer; \
154 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
155 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
156 WetFilter = &Source->Params.Send[out].iirFilter; \
157 WetSend = Source->Params.Send[out].WetGain; \
159 pos = 0; \
160 frac = *DataPosFrac; \
161 j -= BufferSize; \
163 if(j == 0) \
165 value = sampler(data[pos], data[pos+1], frac); \
167 value = lpFilter2PC(WetFilter, 0, value); \
168 WetClickRemoval[0] -= value*WetSend; \
170 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
172 /* First order interpolator */ \
173 value = sampler(data[pos], data[pos+1], frac); \
175 /* Room path final mix buffer and panning */ \
176 value = lpFilter2P(WetFilter, 0, value); \
177 WetBuffer[j] += value*WetSend; \
179 frac += increment; \
180 pos += frac>>FRACTIONBITS; \
181 frac &= FRACTIONMASK; \
182 j++; \
184 if(j == SamplesToDo) \
186 value = sampler(data[pos], data[pos+1], frac); \
188 value = lpFilter2PC(WetFilter, 0, value); \
189 WetPendingClicks[0] += value*WetSend; \
192 *DataPosInt += pos; \
193 *DataPosFrac = frac; \
196 DECL_MIX_MONO(ALfloat, point)
197 DECL_MIX_MONO(ALfloat, lerp)
199 DECL_MIX_MONO(ALshort, point16)
200 DECL_MIX_MONO(ALshort, lerp16)
202 DECL_MIX_MONO(ALubyte, point8)
203 DECL_MIX_MONO(ALubyte, lerp8)
206 #define DECL_MIX_STEREO(T,sampler) \
207 static void Mix_##T##_Stereo_##sampler(ALsource *Source, ALCdevice *Device, \
208 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
209 ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
211 static const ALuint Channels = 2; \
212 static const Channel chans[] = { \
213 FRONT_LEFT, FRONT_RIGHT, \
214 SIDE_LEFT, SIDE_RIGHT, \
215 BACK_LEFT, BACK_RIGHT \
216 }; \
217 const ALfloat scaler = 1.0f/Channels; \
218 ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
219 ALfloat *ClickRemoval, *PendingClicks; \
220 ALuint pos, frac; \
221 ALfloat DrySend[OUTPUTCHANNELS]; \
222 FILTER *DryFilter; \
223 ALuint BufferIdx; \
224 ALuint increment; \
225 ALuint i, out; \
226 ALfloat value; \
228 increment = Source->Params.Step; \
230 DryBuffer = Device->DryBuffer; \
231 ClickRemoval = Device->ClickRemoval; \
232 PendingClicks = Device->PendingClicks; \
233 DryFilter = &Source->Params.iirFilter; \
234 for(i = 0;i < OUTPUTCHANNELS;i++) \
235 DrySend[i] = Source->Params.DryGains[i]; \
237 pos = 0; \
238 frac = *DataPosFrac; \
240 if(j == 0) \
242 for(i = 0;i < Channels;i++) \
244 value = sampler(data[pos*Channels + i], \
245 data[(pos+1)*Channels + i], frac); \
247 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
248 ClickRemoval[chans[i+0]] -= value*DrySend[chans[i+0]]; \
249 ClickRemoval[chans[i+2]] -= value*DrySend[chans[i+2]]; \
250 ClickRemoval[chans[i+4]] -= value*DrySend[chans[i+4]]; \
253 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
255 for(i = 0;i < Channels;i++) \
257 value = sampler(data[pos*Channels + i], \
258 data[(pos+1)*Channels + i], frac); \
260 value = lpFilter2P(DryFilter, chans[i]*2, value); \
261 DryBuffer[j][chans[i+0]] += value*DrySend[chans[i+0]]; \
262 DryBuffer[j][chans[i+2]] += value*DrySend[chans[i+2]]; \
263 DryBuffer[j][chans[i+4]] += value*DrySend[chans[i+4]]; \
266 frac += increment; \
267 pos += frac>>FRACTIONBITS; \
268 frac &= FRACTIONMASK; \
269 j++; \
271 if(j == SamplesToDo) \
273 for(i = 0;i < Channels;i++) \
275 value = sampler(data[pos*Channels + i], \
276 data[(pos+1)*Channels + i], frac); \
278 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
279 PendingClicks[chans[i+0]] += value*DrySend[chans[i+0]]; \
280 PendingClicks[chans[i+2]] += value*DrySend[chans[i+2]]; \
281 PendingClicks[chans[i+4]] += value*DrySend[chans[i+4]]; \
285 for(out = 0;out < Device->NumAuxSends;out++) \
287 ALfloat WetSend; \
288 ALfloat *WetBuffer; \
289 ALfloat *WetClickRemoval; \
290 ALfloat *WetPendingClicks; \
291 FILTER *WetFilter; \
293 if(!Source->Send[out].Slot || \
294 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
295 continue; \
297 WetBuffer = Source->Send[out].Slot->WetBuffer; \
298 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
299 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
300 WetFilter = &Source->Params.Send[out].iirFilter; \
301 WetSend = Source->Params.Send[out].WetGain; \
303 pos = 0; \
304 frac = *DataPosFrac; \
305 j -= BufferSize; \
307 if(j == 0) \
309 for(i = 0;i < Channels;i++) \
311 value = sampler(data[pos*Channels + i], \
312 data[(pos+1)*Channels + i], frac); \
314 value = lpFilter1PC(WetFilter, chans[i], value); \
315 WetClickRemoval[0] -= value*WetSend * scaler; \
318 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
320 for(i = 0;i < Channels;i++) \
322 value = sampler(data[pos*Channels + i], \
323 data[(pos+1)*Channels + i], frac); \
325 value = lpFilter1P(WetFilter, chans[i], value); \
326 WetBuffer[j] += value*WetSend * scaler; \
329 frac += increment; \
330 pos += frac>>FRACTIONBITS; \
331 frac &= FRACTIONMASK; \
332 j++; \
334 if(j == SamplesToDo) \
336 for(i = 0;i < Channels;i++) \
338 value = sampler(data[pos*Channels + i], \
339 data[(pos+1)*Channels + i], frac); \
341 value = lpFilter1PC(WetFilter, chans[i], value); \
342 WetPendingClicks[0] += value*WetSend * scaler; \
346 *DataPosInt += pos; \
347 *DataPosFrac = frac; \
350 DECL_MIX_STEREO(ALfloat, point)
351 DECL_MIX_STEREO(ALfloat, lerp)
353 DECL_MIX_STEREO(ALshort, point16)
354 DECL_MIX_STEREO(ALshort, lerp16)
356 DECL_MIX_STEREO(ALubyte, point8)
357 DECL_MIX_STEREO(ALubyte, lerp8)
360 #define DECL_MIX_MC(T,chans,sampler) \
361 static void Mix_##T##_##chans##_##sampler(ALsource *Source, ALCdevice *Device,\
362 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
363 ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
365 static const ALuint Channels = sizeof(chans)/sizeof(chans[0]); \
366 const ALfloat scaler = 1.0f/Channels; \
367 ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
368 ALfloat *ClickRemoval, *PendingClicks; \
369 ALuint pos, frac; \
370 ALfloat DrySend[OUTPUTCHANNELS]; \
371 FILTER *DryFilter; \
372 ALuint BufferIdx; \
373 ALuint increment; \
374 ALuint i, out; \
375 ALfloat value; \
377 increment = Source->Params.Step; \
379 DryBuffer = Device->DryBuffer; \
380 ClickRemoval = Device->ClickRemoval; \
381 PendingClicks = Device->PendingClicks; \
382 DryFilter = &Source->Params.iirFilter; \
383 for(i = 0;i < OUTPUTCHANNELS;i++) \
384 DrySend[i] = Source->Params.DryGains[i]; \
386 pos = 0; \
387 frac = *DataPosFrac; \
389 if(j == 0) \
391 for(i = 0;i < Channels;i++) \
393 value = sampler(data[pos*Channels + i], \
394 data[(pos+1)*Channels + i], frac); \
396 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
397 ClickRemoval[chans[i]] -= value*DrySend[chans[i]]; \
400 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
402 for(i = 0;i < Channels;i++) \
404 value = sampler(data[pos*Channels + i], \
405 data[(pos+1)*Channels + i], frac); \
407 value = lpFilter2P(DryFilter, chans[i]*2, value); \
408 DryBuffer[j][chans[i]] += value*DrySend[chans[i]]; \
411 frac += increment; \
412 pos += frac>>FRACTIONBITS; \
413 frac &= FRACTIONMASK; \
414 j++; \
416 if(j == SamplesToDo) \
418 for(i = 0;i < Channels;i++) \
420 value = sampler(data[pos*Channels + i], \
421 data[(pos+1)*Channels + i], frac); \
423 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
424 PendingClicks[chans[i]] += value*DrySend[chans[i]]; \
428 for(out = 0;out < Device->NumAuxSends;out++) \
430 ALfloat WetSend; \
431 ALfloat *WetBuffer; \
432 ALfloat *WetClickRemoval; \
433 ALfloat *WetPendingClicks; \
434 FILTER *WetFilter; \
436 if(!Source->Send[out].Slot || \
437 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
438 continue; \
440 WetBuffer = Source->Send[out].Slot->WetBuffer; \
441 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
442 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
443 WetFilter = &Source->Params.Send[out].iirFilter; \
444 WetSend = Source->Params.Send[out].WetGain; \
446 pos = 0; \
447 frac = *DataPosFrac; \
448 j -= BufferSize; \
450 if(j == 0) \
452 for(i = 0;i < Channels;i++) \
454 value = sampler(data[pos*Channels + i], \
455 data[(pos+1)*Channels + i], frac); \
457 value = lpFilter1PC(WetFilter, chans[i], value); \
458 WetClickRemoval[0] -= value*WetSend * scaler; \
461 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
463 for(i = 0;i < Channels;i++) \
465 value = sampler(data[pos*Channels + i], \
466 data[(pos+1)*Channels + i], 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], \
482 data[(pos+1)*Channels + i], 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_MIX_MC(ALfloat, QuadChans, point)
496 DECL_MIX_MC(ALfloat, QuadChans, lerp)
498 DECL_MIX_MC(ALshort, QuadChans, point16)
499 DECL_MIX_MC(ALshort, QuadChans, lerp16)
501 DECL_MIX_MC(ALubyte, QuadChans, point8)
502 DECL_MIX_MC(ALubyte, QuadChans, lerp8)
505 static const Channel X51Chans[] = { FRONT_LEFT, FRONT_RIGHT,
506 FRONT_CENTER, LFE,
507 BACK_LEFT, BACK_RIGHT };
508 DECL_MIX_MC(ALfloat, X51Chans, point)
509 DECL_MIX_MC(ALfloat, X51Chans, lerp)
511 DECL_MIX_MC(ALshort, X51Chans, point16)
512 DECL_MIX_MC(ALshort, X51Chans, lerp16)
514 DECL_MIX_MC(ALubyte, X51Chans, point8)
515 DECL_MIX_MC(ALubyte, X51Chans, lerp8)
518 static const Channel X61Chans[] = { FRONT_LEFT, FRONT_RIGHT,
519 FRONT_CENTER, LFE,
520 BACK_CENTER,
521 SIDE_LEFT, SIDE_RIGHT };
522 DECL_MIX_MC(ALfloat, X61Chans, point)
523 DECL_MIX_MC(ALfloat, X61Chans, lerp)
525 DECL_MIX_MC(ALshort, X61Chans, point16)
526 DECL_MIX_MC(ALshort, X61Chans, lerp16)
528 DECL_MIX_MC(ALubyte, X61Chans, point8)
529 DECL_MIX_MC(ALubyte, X61Chans, lerp8)
532 static const Channel X71Chans[] = { FRONT_LEFT, FRONT_RIGHT,
533 FRONT_CENTER, LFE,
534 BACK_LEFT, BACK_RIGHT,
535 SIDE_LEFT, SIDE_RIGHT };
536 DECL_MIX_MC(ALfloat, X71Chans, point)
537 DECL_MIX_MC(ALfloat, X71Chans, lerp)
539 DECL_MIX_MC(ALshort, X71Chans, point16)
540 DECL_MIX_MC(ALshort, X71Chans, lerp16)
542 DECL_MIX_MC(ALubyte, X71Chans, point8)
543 DECL_MIX_MC(ALubyte, X71Chans, lerp8)
546 #define DECL_MIX(T, sampler) \
547 static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, ALuint Channels, \
548 const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
549 ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
551 switch(Channels) \
553 case 1: /* Mono */ \
554 Mix_##T##_Mono_##sampler(Source, Device, \
555 Data, DataPosInt, DataPosFrac, \
556 j, SamplesToDo, BufferSize); \
557 break; \
558 case 2: /* Stereo */ \
559 Mix_##T##_Stereo_##sampler(Source, Device, \
560 Data, DataPosInt, DataPosFrac, \
561 j, SamplesToDo, BufferSize); \
562 break; \
563 case 4: /* Quad */ \
564 Mix_##T##_QuadChans_##sampler(Source, Device, \
565 Data, DataPosInt, DataPosFrac, \
566 j, SamplesToDo, BufferSize); \
567 break; \
568 case 6: /* 5.1 */ \
569 Mix_##T##_X51Chans_##sampler(Source, Device, \
570 Data, DataPosInt, DataPosFrac, \
571 j, SamplesToDo, BufferSize); \
572 break; \
573 case 7: /* 6.1 */ \
574 Mix_##T##_X61Chans_##sampler(Source, Device, \
575 Data, DataPosInt, DataPosFrac, \
576 j, SamplesToDo, BufferSize); \
577 break; \
578 case 8: /* 7.1 */ \
579 Mix_##T##_X71Chans_##sampler(Source, Device, \
580 Data, DataPosInt, DataPosFrac, \
581 j, SamplesToDo, BufferSize); \
582 break; \
586 DECL_MIX(ALfloat, point)
587 DECL_MIX(ALfloat, lerp)
589 DECL_MIX(ALshort, point16)
590 DECL_MIX(ALshort, lerp16)
592 DECL_MIX(ALubyte, point8)
593 DECL_MIX(ALubyte, lerp8)
596 /* Stack data size can be whatever. Larger values need more stack, while
597 * smaller values may need more iterations */
598 #ifndef STACK_DATA_SIZE
599 #define STACK_DATA_SIZE 16384
600 #endif
602 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
604 ALbufferlistitem *BufferListItem;
605 ALuint FrameSize, Channels, Bytes;
606 ALuint DataPosInt, DataPosFrac;
607 ALuint BuffersPlayed;
608 ALboolean Looping;
609 ALuint increment;
610 ALenum State;
611 ALuint i, j;
612 ALint64 DataSize64;
614 /* Get source info */
615 State = Source->state;
616 BuffersPlayed = Source->BuffersPlayed;
617 DataPosInt = Source->position;
618 DataPosFrac = Source->position_fraction;
619 Looping = Source->bLooping;
620 increment = Source->Params.Step;
622 /* Get buffer info */
623 FrameSize = Channels = Bytes = 0;
624 BufferListItem = Source->queue;
625 for(i = 0;i < Source->BuffersInQueue;i++)
627 const ALbuffer *ALBuffer;
628 if((ALBuffer=BufferListItem->buffer) != NULL)
630 FrameSize = aluFrameSizeFromFormat(ALBuffer->format);
631 Channels = aluChannelsFromFormat(ALBuffer->format);
632 Bytes = aluBytesFromFormat(ALBuffer->format);
633 break;
635 BufferListItem = BufferListItem->next;
638 /* Get current buffer queue item */
639 BufferListItem = Source->queue;
640 for(i = 0;i < BuffersPlayed;i++)
641 BufferListItem = BufferListItem->next;
643 j = 0;
644 do {
645 ALubyte SrcData[STACK_DATA_SIZE];
646 ALuint SrcDataSize = 0;
647 ALuint BufferSize;
649 /* Figure out how many buffer bytes will be needed */
650 DataSize64 = SamplesToDo-j+1;
651 DataSize64 *= increment;
652 DataSize64 += DataPosFrac+FRACTIONMASK;
653 DataSize64 >>= FRACTIONBITS;
654 DataSize64 += BUFFER_PADDING;
655 DataSize64 *= FrameSize;
657 BufferSize = sizeof(SrcData) - SrcDataSize;
658 BufferSize = min(DataSize64, BufferSize);
660 if(Source->lSourceType == AL_STATIC)
662 const ALbuffer *ALBuffer = Source->Buffer;
663 const ALubyte *Data = ALBuffer->data;
664 ALuint DataSize;
666 /* If current pos is beyond the loop range, do not loop */
667 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
669 Looping = AL_FALSE;
671 /* Copy what's left to play in the source buffer, and clear the
672 * rest of the temp buffer */
673 DataSize = ALBuffer->size - DataPosInt*FrameSize;
674 DataSize = min(BufferSize, DataSize);
676 memcpy(&SrcData[SrcDataSize], &Data[DataPosInt*FrameSize], DataSize);
677 SrcDataSize += DataSize;
678 BufferSize -= DataSize;
680 memset(&SrcData[SrcDataSize], (Bytes==1)?0x80:0, BufferSize);
681 SrcDataSize += BufferSize;
682 BufferSize -= BufferSize;
684 else
686 ALuint LoopStart = ALBuffer->LoopStart;
687 ALuint LoopEnd = ALBuffer->LoopEnd;
689 /* Copy what's left of this loop iteration, then copy repeats
690 * of the loop section */
691 DataSize = (LoopEnd-DataPosInt) * FrameSize;
692 DataSize = min(BufferSize, DataSize);
694 memcpy(&SrcData[SrcDataSize], &Data[DataPosInt*FrameSize], DataSize);
695 SrcDataSize += DataSize;
696 BufferSize -= DataSize;
698 DataSize = (LoopEnd-LoopStart) * FrameSize;
699 while(BufferSize > 0)
701 DataSize = min(BufferSize, DataSize);
703 memcpy(&SrcData[SrcDataSize], &Data[LoopStart*FrameSize], DataSize);
704 SrcDataSize += DataSize;
705 BufferSize -= DataSize;
709 else
711 /* Crawl the buffer queue to fill in the temp buffer */
712 ALbufferlistitem *BufferListIter = BufferListItem;
713 ALuint pos = DataPosInt*FrameSize;
715 while(BufferListIter && BufferSize > 0)
717 const ALbuffer *ALBuffer;
718 if((ALBuffer=BufferListIter->buffer) != NULL)
720 const ALubyte *Data = ALBuffer->data;
721 ALuint DataSize = ALBuffer->size;
723 /* Skip the data already played */
724 if(DataSize <= pos)
725 pos -= DataSize;
726 else
728 Data += pos;
729 DataSize -= pos;
730 pos -= pos;
732 DataSize = min(BufferSize, DataSize);
733 memcpy(&SrcData[SrcDataSize], Data, DataSize);
734 SrcDataSize += DataSize;
735 BufferSize -= DataSize;
738 BufferListIter = BufferListIter->next;
739 if(!BufferListIter && Looping)
740 BufferListIter = Source->queue;
741 else if(!BufferListIter)
743 memset(&SrcData[SrcDataSize], (Bytes==1)?0x80:0, BufferSize);
744 SrcDataSize += BufferSize;
745 BufferSize -= BufferSize;
750 /* Figure out how many samples we can mix. */
751 DataSize64 = SrcDataSize / FrameSize;
752 DataSize64 -= BUFFER_PADDING;
753 DataSize64 <<= FRACTIONBITS;
754 DataSize64 -= increment;
756 BufferSize = (ALuint)((DataSize64-DataPosFrac+(increment-1)) / increment);
757 BufferSize = min(BufferSize, (SamplesToDo-j));
758 if(BufferSize == 0)
760 AL_PRINT("No samples to mix! Pitch too high (%u, %g)?\n",
761 increment, increment/(double)(1<<FRACTIONBITS));
762 State = AL_STOPPED;
763 BufferListItem = Source->queue;
764 BuffersPlayed = Source->BuffersInQueue;
765 DataPosInt = 0;
766 DataPosFrac = 0;
767 break;
770 switch(Source->Resampler)
772 case POINT_RESAMPLER:
773 if(Bytes == 4)
774 Mix_ALfloat_point(Source, Device, Channels,
775 SrcData, &DataPosInt, &DataPosFrac,
776 j, SamplesToDo, BufferSize);
777 else if(Bytes == 2)
778 Mix_ALshort_point16(Source, Device, Channels,
779 SrcData, &DataPosInt, &DataPosFrac,
780 j, SamplesToDo, BufferSize);
781 else if(Bytes == 1)
782 Mix_ALubyte_point8(Source, Device, Channels,
783 SrcData, &DataPosInt, &DataPosFrac,
784 j, SamplesToDo, BufferSize);
785 break;
786 case LINEAR_RESAMPLER:
787 if(Bytes == 4)
788 Mix_ALfloat_lerp(Source, Device, Channels,
789 SrcData, &DataPosInt, &DataPosFrac,
790 j, SamplesToDo, BufferSize);
791 else if(Bytes == 2)
792 Mix_ALshort_lerp16(Source, Device, Channels,
793 SrcData, &DataPosInt, &DataPosFrac,
794 j, SamplesToDo, BufferSize);
795 else if(Bytes == 1)
796 Mix_ALubyte_lerp8(Source, Device, Channels,
797 SrcData, &DataPosInt, &DataPosFrac,
798 j, SamplesToDo, BufferSize);
799 break;
800 case RESAMPLER_MIN:
801 case RESAMPLER_MAX:
802 break;
804 j += BufferSize;
806 /* Handle looping sources */
807 while(1)
809 const ALbuffer *ALBuffer;
810 ALuint DataSize = 0;
811 ALuint LoopStart = 0;
812 ALuint LoopEnd = 0;
814 if((ALBuffer=BufferListItem->buffer) != NULL)
816 DataSize = ALBuffer->size / FrameSize;
817 if(DataSize > DataPosInt)
818 break;
819 LoopStart = ALBuffer->LoopStart;
820 LoopEnd = ALBuffer->LoopEnd;
823 if(BufferListItem->next)
825 BufferListItem = BufferListItem->next;
826 BuffersPlayed++;
828 else if(Looping)
830 BufferListItem = Source->queue;
831 BuffersPlayed = 0;
832 if(Source->lSourceType == AL_STATIC)
834 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
835 break;
838 else
840 State = AL_STOPPED;
841 BufferListItem = Source->queue;
842 BuffersPlayed = Source->BuffersInQueue;
843 DataPosInt = 0;
844 DataPosFrac = 0;
845 break;
848 DataPosInt -= DataSize;
850 } while(State == AL_PLAYING && j < SamplesToDo);
852 /* Update source info */
853 Source->state = State;
854 Source->BuffersPlayed = BuffersPlayed;
855 Source->position = DataPosInt;
856 Source->position_fraction = DataPosFrac;
857 Source->Buffer = BufferListItem->buffer;