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
34 #include "alListener.h"
35 #include "alAuxEffectSlot.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##_1_##sampler(ALsource *Source, ALCdevice *Device, \
68 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
69 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
71 ALfloat (*DryBuffer)[MAXCHANNELS]; \
72 ALfloat *ClickRemoval, *PendingClicks; \
74 ALfloat DrySend[MAXCHANNELS]; \
81 increment = Source->Params.Step; \
83 DryBuffer = Device->DryBuffer; \
84 ClickRemoval = Device->ClickRemoval; \
85 PendingClicks = Device->PendingClicks; \
86 DryFilter = &Source->Params.iirFilter; \
87 for(c = 0;c < MAXCHANNELS;c++) \
88 DrySend[c] = Source->Params.DryGains[0][c]; \
91 frac = *DataPosFrac; \
95 value = sampler(data+pos, 1, frac); \
97 value = lpFilter4PC(DryFilter, 0, value); \
98 for(c = 0;c < MAXCHANNELS;c++) \
99 ClickRemoval[c] -= value*DrySend[c]; \
101 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
103 /* First order interpolator */ \
104 value = sampler(data+pos, 1, frac); \
106 /* Direct path final mix buffer and panning */ \
107 value = lpFilter4P(DryFilter, 0, value); \
108 for(c = 0;c < MAXCHANNELS;c++) \
109 DryBuffer[OutPos][c] += value*DrySend[c]; \
112 pos += frac>>FRACTIONBITS; \
113 frac &= FRACTIONMASK; \
116 if(OutPos == SamplesToDo) \
118 value = sampler(data+pos, 1, frac); \
120 value = lpFilter4PC(DryFilter, 0, value); \
121 for(c = 0;c < MAXCHANNELS;c++) \
122 PendingClicks[c] += value*DrySend[c]; \
125 for(out = 0;out < Device->NumAuxSends;out++) \
128 ALfloat *WetBuffer; \
129 ALfloat *WetClickRemoval; \
130 ALfloat *WetPendingClicks; \
133 if(!Source->Send[out].Slot || \
134 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
137 WetBuffer = Source->Send[out].Slot->WetBuffer; \
138 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
139 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
140 WetFilter = &Source->Params.Send[out].iirFilter; \
141 WetSend = Source->Params.Send[out].WetGain; \
144 frac = *DataPosFrac; \
145 OutPos -= BufferSize; \
149 value = sampler(data+pos, 1, frac); \
151 value = lpFilter2PC(WetFilter, 0, value); \
152 WetClickRemoval[0] -= value*WetSend; \
154 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
156 /* First order interpolator */ \
157 value = sampler(data+pos, 1, frac); \
159 /* Room path final mix buffer and panning */ \
160 value = lpFilter2P(WetFilter, 0, value); \
161 WetBuffer[OutPos] += value*WetSend; \
164 pos += frac>>FRACTIONBITS; \
165 frac &= FRACTIONMASK; \
168 if(OutPos == SamplesToDo) \
170 value = sampler(data+pos, 1, frac); \
172 value = lpFilter2PC(WetFilter, 0, value); \
173 WetPendingClicks[0] += value*WetSend; \
176 *DataPosInt += pos; \
177 *DataPosFrac = frac; \
180 DECL_TEMPLATE(ALfloat
, point32
)
181 DECL_TEMPLATE(ALfloat
, lerp32
)
182 DECL_TEMPLATE(ALfloat
, cubic32
)
184 DECL_TEMPLATE(ALshort
, point16
)
185 DECL_TEMPLATE(ALshort
, lerp16
)
186 DECL_TEMPLATE(ALshort
, cubic16
)
188 DECL_TEMPLATE(ALubyte
, point8
)
189 DECL_TEMPLATE(ALubyte
, lerp8
)
190 DECL_TEMPLATE(ALubyte
, cubic8
)
195 #define DECL_TEMPLATE(T, count, sampler) \
196 static void Mix_##T##_##count##_##sampler(ALsource *Source, ALCdevice *Device,\
197 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
198 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
200 const ALuint Channels = count; \
201 const ALfloat scaler = 1.0f/Channels; \
202 ALfloat (*DryBuffer)[MAXCHANNELS]; \
203 ALfloat *ClickRemoval, *PendingClicks; \
205 ALfloat DrySend[Channels][MAXCHANNELS]; \
212 increment = Source->Params.Step; \
214 DryBuffer = Device->DryBuffer; \
215 ClickRemoval = Device->ClickRemoval; \
216 PendingClicks = Device->PendingClicks; \
217 DryFilter = &Source->Params.iirFilter; \
218 for(i = 0;i < Channels;i++) \
220 for(c = 0;c < MAXCHANNELS;c++) \
221 DrySend[i][c] = Source->Params.DryGains[i][c]; \
225 frac = *DataPosFrac; \
229 for(i = 0;i < Channels;i++) \
231 value = sampler(data + pos*Channels + i, Channels, frac); \
233 value = lpFilter2PC(DryFilter, i*2, value); \
234 for(c = 0;c < MAXCHANNELS;c++) \
235 ClickRemoval[c] -= value*DrySend[i][c]; \
238 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
240 for(i = 0;i < Channels;i++) \
242 value = sampler(data + pos*Channels + i, Channels, frac); \
244 value = lpFilter2P(DryFilter, i*2, value); \
245 for(c = 0;c < MAXCHANNELS;c++) \
246 DryBuffer[OutPos][c] += value*DrySend[i][c]; \
250 pos += frac>>FRACTIONBITS; \
251 frac &= FRACTIONMASK; \
254 if(OutPos == SamplesToDo) \
256 for(i = 0;i < Channels;i++) \
258 value = sampler(data + pos*Channels + i, Channels, frac); \
260 value = lpFilter2PC(DryFilter, i*2, value); \
261 for(c = 0;c < MAXCHANNELS;c++) \
262 PendingClicks[c] += value*DrySend[i][c]; \
266 for(out = 0;out < Device->NumAuxSends;out++) \
269 ALfloat *WetBuffer; \
270 ALfloat *WetClickRemoval; \
271 ALfloat *WetPendingClicks; \
274 if(!Source->Send[out].Slot || \
275 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
278 WetBuffer = Source->Send[out].Slot->WetBuffer; \
279 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
280 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
281 WetFilter = &Source->Params.Send[out].iirFilter; \
282 WetSend = Source->Params.Send[out].WetGain; \
285 frac = *DataPosFrac; \
286 OutPos -= BufferSize; \
290 for(i = 0;i < Channels;i++) \
292 value = sampler(data + pos*Channels + i, Channels, frac); \
294 value = lpFilter1PC(WetFilter, i, value); \
295 WetClickRemoval[0] -= value*WetSend * scaler; \
298 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
300 for(i = 0;i < Channels;i++) \
302 value = sampler(data + pos*Channels + i, Channels, frac); \
304 value = lpFilter1P(WetFilter, i, value); \
305 WetBuffer[OutPos] += value*WetSend * scaler; \
309 pos += frac>>FRACTIONBITS; \
310 frac &= FRACTIONMASK; \
313 if(OutPos == SamplesToDo) \
315 for(i = 0;i < Channels;i++) \
317 value = sampler(data + pos*Channels + i, Channels, frac); \
319 value = lpFilter1PC(WetFilter, i, value); \
320 WetPendingClicks[0] += value*WetSend * scaler; \
324 *DataPosInt += pos; \
325 *DataPosFrac = frac; \
328 DECL_TEMPLATE(ALfloat
, 2, point32
)
329 DECL_TEMPLATE(ALfloat
, 2, lerp32
)
330 DECL_TEMPLATE(ALfloat
, 2, cubic32
)
332 DECL_TEMPLATE(ALshort
, 2, point16
)
333 DECL_TEMPLATE(ALshort
, 2, lerp16
)
334 DECL_TEMPLATE(ALshort
, 2, cubic16
)
336 DECL_TEMPLATE(ALubyte
, 2, point8
)
337 DECL_TEMPLATE(ALubyte
, 2, lerp8
)
338 DECL_TEMPLATE(ALubyte
, 2, cubic8
)
341 DECL_TEMPLATE(ALfloat
, 4, point32
)
342 DECL_TEMPLATE(ALfloat
, 4, lerp32
)
343 DECL_TEMPLATE(ALfloat
, 4, cubic32
)
345 DECL_TEMPLATE(ALshort
, 4, point16
)
346 DECL_TEMPLATE(ALshort
, 4, lerp16
)
347 DECL_TEMPLATE(ALshort
, 4, cubic16
)
349 DECL_TEMPLATE(ALubyte
, 4, point8
)
350 DECL_TEMPLATE(ALubyte
, 4, lerp8
)
351 DECL_TEMPLATE(ALubyte
, 4, cubic8
)
354 DECL_TEMPLATE(ALfloat
, 6, point32
)
355 DECL_TEMPLATE(ALfloat
, 6, lerp32
)
356 DECL_TEMPLATE(ALfloat
, 6, cubic32
)
358 DECL_TEMPLATE(ALshort
, 6, point16
)
359 DECL_TEMPLATE(ALshort
, 6, lerp16
)
360 DECL_TEMPLATE(ALshort
, 6, cubic16
)
362 DECL_TEMPLATE(ALubyte
, 6, point8
)
363 DECL_TEMPLATE(ALubyte
, 6, lerp8
)
364 DECL_TEMPLATE(ALubyte
, 6, cubic8
)
367 DECL_TEMPLATE(ALfloat
, 7, point32
)
368 DECL_TEMPLATE(ALfloat
, 7, lerp32
)
369 DECL_TEMPLATE(ALfloat
, 7, cubic32
)
371 DECL_TEMPLATE(ALshort
, 7, point16
)
372 DECL_TEMPLATE(ALshort
, 7, lerp16
)
373 DECL_TEMPLATE(ALshort
, 7, cubic16
)
375 DECL_TEMPLATE(ALubyte
, 7, point8
)
376 DECL_TEMPLATE(ALubyte
, 7, lerp8
)
377 DECL_TEMPLATE(ALubyte
, 7, cubic8
)
380 DECL_TEMPLATE(ALfloat
, 8, point32
)
381 DECL_TEMPLATE(ALfloat
, 8, lerp32
)
382 DECL_TEMPLATE(ALfloat
, 8, cubic32
)
384 DECL_TEMPLATE(ALshort
, 8, point16
)
385 DECL_TEMPLATE(ALshort
, 8, lerp16
)
386 DECL_TEMPLATE(ALshort
, 8, cubic16
)
388 DECL_TEMPLATE(ALubyte
, 8, point8
)
389 DECL_TEMPLATE(ALubyte
, 8, lerp8
)
390 DECL_TEMPLATE(ALubyte
, 8, cubic8
)
395 #define DECL_TEMPLATE(T, sampler) \
396 static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
397 enum FmtChannels FmtChannels, \
398 const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
399 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
401 switch(FmtChannels) \
404 Mix_##T##_1_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
405 OutPos, SamplesToDo, BufferSize); \
409 Mix_##T##_2_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
410 OutPos, SamplesToDo, BufferSize); \
413 Mix_##T##_4_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
414 OutPos, SamplesToDo, BufferSize); \
417 Mix_##T##_6_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
418 OutPos, SamplesToDo, BufferSize); \
421 Mix_##T##_7_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
422 OutPos, SamplesToDo, BufferSize); \
425 Mix_##T##_8_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
426 OutPos, SamplesToDo, BufferSize); \
431 DECL_TEMPLATE(ALfloat
, point32
)
432 DECL_TEMPLATE(ALfloat
, lerp32
)
433 DECL_TEMPLATE(ALfloat
, cubic32
)
435 DECL_TEMPLATE(ALshort
, point16
)
436 DECL_TEMPLATE(ALshort
, lerp16
)
437 DECL_TEMPLATE(ALshort
, cubic16
)
439 DECL_TEMPLATE(ALubyte
, point8
)
440 DECL_TEMPLATE(ALubyte
, lerp8
)
441 DECL_TEMPLATE(ALubyte
, cubic8
)
446 #define DECL_TEMPLATE(sampler) \
447 static void Mix_##sampler(ALsource *Source, ALCdevice *Device, \
448 enum FmtChannels FmtChannels, enum FmtType FmtType, \
449 const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
450 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
455 Mix_ALubyte_##sampler##8(Source, Device, FmtChannels, \
456 Data, DataPosInt, DataPosFrac, \
457 OutPos, SamplesToDo, BufferSize); \
461 Mix_ALshort_##sampler##16(Source, Device, FmtChannels, \
462 Data, DataPosInt, DataPosFrac, \
463 OutPos, SamplesToDo, BufferSize); \
467 Mix_ALfloat_##sampler##32(Source, Device, FmtChannels, \
468 Data, DataPosInt, DataPosFrac, \
469 OutPos, SamplesToDo, BufferSize); \
481 ALvoid
MixSource(ALsource
*Source
, ALCdevice
*Device
, ALuint SamplesToDo
)
483 ALbufferlistitem
*BufferListItem
;
484 ALuint DataPosInt
, DataPosFrac
;
485 enum FmtChannels FmtChannels
;
486 enum FmtType FmtType
;
487 ALuint BuffersPlayed
;
490 resampler_t Resampler
;
497 /* Get source info */
498 State
= Source
->state
;
499 BuffersPlayed
= Source
->BuffersPlayed
;
500 DataPosInt
= Source
->position
;
501 DataPosFrac
= Source
->position_fraction
;
502 Looping
= Source
->bLooping
;
503 increment
= Source
->Params
.Step
;
504 Resampler
= (increment
== FRACTIONONE
) ? POINT_RESAMPLER
:
507 /* Get buffer info */
509 FmtChannels
= FmtMono
;
511 BufferListItem
= Source
->queue
;
512 for(i
= 0;i
< Source
->BuffersInQueue
;i
++)
514 const ALbuffer
*ALBuffer
;
515 if((ALBuffer
=BufferListItem
->buffer
) != NULL
)
517 FmtChannels
= ALBuffer
->FmtChannels
;
518 FmtType
= ALBuffer
->FmtType
;
519 FrameSize
= FrameSizeFromFmt(FmtChannels
, FmtType
);
522 BufferListItem
= BufferListItem
->next
;
525 /* Get current buffer queue item */
526 BufferListItem
= Source
->queue
;
527 for(i
= 0;i
< BuffersPlayed
;i
++)
528 BufferListItem
= BufferListItem
->next
;
532 const ALuint BufferPrePadding
= ResamplerPrePadding
[Resampler
];
533 const ALuint BufferPadding
= ResamplerPadding
[Resampler
];
534 ALubyte StackData
[STACK_DATA_SIZE
];
535 ALubyte
*SrcData
= StackData
;
536 ALuint SrcDataSize
= 0;
539 /* Figure out how many buffer bytes will be needed */
540 DataSize64
= SamplesToDo
-OutPos
+1;
541 DataSize64
*= increment
;
542 DataSize64
+= DataPosFrac
+FRACTIONMASK
;
543 DataSize64
>>= FRACTIONBITS
;
544 DataSize64
+= BufferPadding
+BufferPrePadding
;
545 DataSize64
*= FrameSize
;
547 BufferSize
= min(DataSize64
, STACK_DATA_SIZE
);
548 BufferSize
-= BufferSize
%FrameSize
;
550 if(Source
->lSourceType
== AL_STATIC
)
552 const ALbuffer
*ALBuffer
= Source
->Buffer
;
553 const ALubyte
*Data
= ALBuffer
->data
;
557 /* If current pos is beyond the loop range, do not loop */
558 if(Looping
== AL_FALSE
|| DataPosInt
>= (ALuint
)ALBuffer
->LoopEnd
)
562 if(DataPosInt
>= BufferPrePadding
)
563 pos
= (DataPosInt
-BufferPrePadding
)*FrameSize
;
566 DataSize
= (BufferPrePadding
-DataPosInt
)*FrameSize
;
567 DataSize
= min(BufferSize
, DataSize
);
569 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, DataSize
);
570 SrcDataSize
+= DataSize
;
571 BufferSize
-= DataSize
;
576 /* Copy what's left to play in the source buffer, and clear the
577 * rest of the temp buffer */
578 DataSize
= ALBuffer
->size
- pos
;
579 DataSize
= min(BufferSize
, DataSize
);
581 memcpy(&SrcData
[SrcDataSize
], &Data
[pos
], DataSize
);
582 SrcDataSize
+= DataSize
;
583 BufferSize
-= DataSize
;
585 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, BufferSize
);
586 SrcDataSize
+= BufferSize
;
587 BufferSize
-= BufferSize
;
591 ALuint LoopStart
= ALBuffer
->LoopStart
;
592 ALuint LoopEnd
= ALBuffer
->LoopEnd
;
594 if(DataPosInt
>= LoopStart
)
596 pos
= DataPosInt
-LoopStart
;
597 while(pos
< BufferPrePadding
)
598 pos
+= LoopEnd
-LoopStart
;
599 pos
-= BufferPrePadding
;
603 else if(DataPosInt
>= BufferPrePadding
)
604 pos
= (DataPosInt
-BufferPrePadding
)*FrameSize
;
607 DataSize
= (BufferPrePadding
-DataPosInt
)*FrameSize
;
608 DataSize
= min(BufferSize
, DataSize
);
610 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, DataSize
);
611 SrcDataSize
+= DataSize
;
612 BufferSize
-= DataSize
;
617 /* Copy what's left of this loop iteration, then copy repeats
618 * of the loop section */
619 DataSize
= LoopEnd
*FrameSize
- pos
;
620 DataSize
= min(BufferSize
, DataSize
);
622 memcpy(&SrcData
[SrcDataSize
], &Data
[pos
], DataSize
);
623 SrcDataSize
+= DataSize
;
624 BufferSize
-= DataSize
;
626 DataSize
= (LoopEnd
-LoopStart
) * FrameSize
;
627 while(BufferSize
> 0)
629 DataSize
= min(BufferSize
, DataSize
);
631 memcpy(&SrcData
[SrcDataSize
], &Data
[LoopStart
*FrameSize
], DataSize
);
632 SrcDataSize
+= DataSize
;
633 BufferSize
-= DataSize
;
639 /* Crawl the buffer queue to fill in the temp buffer */
640 ALbufferlistitem
*BufferListIter
= BufferListItem
;
643 if(DataPosInt
>= BufferPrePadding
)
644 pos
= (DataPosInt
-BufferPrePadding
)*FrameSize
;
647 pos
= (BufferPrePadding
-DataPosInt
)*FrameSize
;
650 if(!BufferListIter
->prev
&& !Looping
)
652 ALuint DataSize
= min(BufferSize
, pos
);
654 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, DataSize
);
655 SrcDataSize
+= DataSize
;
656 BufferSize
-= DataSize
;
664 while(BufferListIter
->next
)
665 BufferListIter
= BufferListIter
->next
;
668 BufferListIter
= BufferListIter
->prev
;
670 if(BufferListIter
->buffer
)
672 if((ALuint
)BufferListIter
->buffer
->size
> pos
)
674 pos
= BufferListIter
->buffer
->size
- pos
;
677 pos
-= BufferListIter
->buffer
->size
;
682 while(BufferListIter
&& BufferSize
> 0)
684 const ALbuffer
*ALBuffer
;
685 if((ALBuffer
=BufferListIter
->buffer
) != NULL
)
687 const ALubyte
*Data
= ALBuffer
->data
;
688 ALuint DataSize
= ALBuffer
->size
;
690 /* Skip the data already played */
699 DataSize
= min(BufferSize
, DataSize
);
700 memcpy(&SrcData
[SrcDataSize
], Data
, DataSize
);
701 SrcDataSize
+= DataSize
;
702 BufferSize
-= DataSize
;
705 BufferListIter
= BufferListIter
->next
;
706 if(!BufferListIter
&& Looping
)
707 BufferListIter
= Source
->queue
;
708 else if(!BufferListIter
)
710 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, BufferSize
);
711 SrcDataSize
+= BufferSize
;
712 BufferSize
-= BufferSize
;
717 /* Figure out how many samples we can mix. */
718 DataSize64
= SrcDataSize
/ FrameSize
;
719 DataSize64
-= BufferPadding
+BufferPrePadding
;
720 DataSize64
<<= FRACTIONBITS
;
721 DataSize64
-= increment
;
722 DataSize64
-= DataPosFrac
;
724 BufferSize
= (ALuint
)((DataSize64
+(increment
-1)) / increment
);
725 BufferSize
= min(BufferSize
, (SamplesToDo
-OutPos
));
727 SrcData
+= BufferPrePadding
*FrameSize
;
730 case POINT_RESAMPLER
:
731 Mix_point(Source
, Device
, FmtChannels
, FmtType
,
732 SrcData
, &DataPosInt
, &DataPosFrac
,
733 OutPos
, SamplesToDo
, BufferSize
);
735 case LINEAR_RESAMPLER
:
736 Mix_lerp(Source
, Device
, FmtChannels
, FmtType
,
737 SrcData
, &DataPosInt
, &DataPosFrac
,
738 OutPos
, SamplesToDo
, BufferSize
);
740 case CUBIC_RESAMPLER
:
741 Mix_cubic(Source
, Device
, FmtChannels
, FmtType
,
742 SrcData
, &DataPosInt
, &DataPosFrac
,
743 OutPos
, SamplesToDo
, BufferSize
);
749 OutPos
+= BufferSize
;
751 /* Handle looping sources */
754 const ALbuffer
*ALBuffer
;
756 ALuint LoopStart
= 0;
759 if((ALBuffer
=BufferListItem
->buffer
) != NULL
)
761 DataSize
= ALBuffer
->size
/ FrameSize
;
762 if(DataSize
> DataPosInt
)
764 LoopStart
= ALBuffer
->LoopStart
;
765 LoopEnd
= ALBuffer
->LoopEnd
;
768 if(BufferListItem
->next
)
770 BufferListItem
= BufferListItem
->next
;
775 BufferListItem
= Source
->queue
;
777 if(Source
->lSourceType
== AL_STATIC
)
779 DataPosInt
= ((DataPosInt
-LoopStart
)%(LoopEnd
-LoopStart
)) + LoopStart
;
786 BufferListItem
= Source
->queue
;
787 BuffersPlayed
= Source
->BuffersInQueue
;
793 DataPosInt
-= DataSize
;
795 } while(State
== AL_PLAYING
&& OutPos
< SamplesToDo
);
797 /* Update source info */
798 Source
->state
= State
;
799 Source
->BuffersPlayed
= BuffersPlayed
;
800 Source
->position
= DataPosInt
;
801 Source
->position_fraction
= DataPosFrac
;
802 Source
->Buffer
= BufferListItem
->buffer
;