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##_Mono_##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(i = 0;i < MAXCHANNELS;i++) \
88 DrySend[i] = Source->Params.DryGains[i]; \
91 frac = *DataPosFrac; \
95 value = sampler(data+pos, 1, frac); \
97 value = lpFilter4PC(DryFilter, 0, value); \
98 for(i = 0;i < MAXCHANNELS;i++) \
99 ClickRemoval[i] -= value*DrySend[i]; \
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(i = 0;i < MAXCHANNELS;i++) \
109 DryBuffer[OutPos][i] += value*DrySend[i]; \
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(i = 0;i < MAXCHANNELS;i++) \
122 PendingClicks[i] += value*DrySend[i]; \
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, sampler) \
196 static void Mix_##T##_Stereo_##sampler(ALsource *Source, ALCdevice *Device, \
197 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
198 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
200 static const ALuint Channels = 2; \
201 static const Channel chans[] = { \
202 FRONT_LEFT, FRONT_RIGHT, \
203 SIDE_LEFT, SIDE_RIGHT, \
204 BACK_LEFT, BACK_RIGHT \
206 const ALfloat scaler = 1.0f/Channels; \
207 ALfloat (*DryBuffer)[MAXCHANNELS]; \
208 ALfloat *ClickRemoval, *PendingClicks; \
210 ALfloat DrySend[MAXCHANNELS]; \
217 increment = Source->Params.Step; \
219 DryBuffer = Device->DryBuffer; \
220 ClickRemoval = Device->ClickRemoval; \
221 PendingClicks = Device->PendingClicks; \
222 DryFilter = &Source->Params.iirFilter; \
223 for(i = 0;i < MAXCHANNELS;i++) \
224 DrySend[i] = Source->Params.DryGains[i]; \
227 frac = *DataPosFrac; \
231 for(i = 0;i < Channels;i++) \
233 value = sampler(data + pos*Channels + i, Channels, frac); \
235 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
236 ClickRemoval[chans[i+0]] -= value*DrySend[chans[i+0]]; \
237 ClickRemoval[chans[i+2]] -= value*DrySend[chans[i+2]]; \
238 ClickRemoval[chans[i+4]] -= value*DrySend[chans[i+4]]; \
241 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
243 for(i = 0;i < Channels;i++) \
245 value = sampler(data + pos*Channels + i, Channels, frac); \
247 value = lpFilter2P(DryFilter, chans[i]*2, value); \
248 DryBuffer[OutPos][chans[i+0]] += value*DrySend[chans[i+0]]; \
249 DryBuffer[OutPos][chans[i+2]] += value*DrySend[chans[i+2]]; \
250 DryBuffer[OutPos][chans[i+4]] += value*DrySend[chans[i+4]]; \
254 pos += frac>>FRACTIONBITS; \
255 frac &= FRACTIONMASK; \
258 if(OutPos == SamplesToDo) \
260 for(i = 0;i < Channels;i++) \
262 value = sampler(data + pos*Channels + i, Channels, frac); \
264 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
265 PendingClicks[chans[i+0]] += value*DrySend[chans[i+0]]; \
266 PendingClicks[chans[i+2]] += value*DrySend[chans[i+2]]; \
267 PendingClicks[chans[i+4]] += value*DrySend[chans[i+4]]; \
271 for(out = 0;out < Device->NumAuxSends;out++) \
274 ALfloat *WetBuffer; \
275 ALfloat *WetClickRemoval; \
276 ALfloat *WetPendingClicks; \
279 if(!Source->Send[out].Slot || \
280 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
283 WetBuffer = Source->Send[out].Slot->WetBuffer; \
284 WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
285 WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
286 WetFilter = &Source->Params.Send[out].iirFilter; \
287 WetSend = Source->Params.Send[out].WetGain; \
290 frac = *DataPosFrac; \
291 OutPos -= BufferSize; \
295 for(i = 0;i < Channels;i++) \
297 value = sampler(data + pos*Channels + i, Channels, frac); \
299 value = lpFilter1PC(WetFilter, chans[i], value); \
300 WetClickRemoval[0] -= value*WetSend * scaler; \
303 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
305 for(i = 0;i < Channels;i++) \
307 value = sampler(data + pos*Channels + i, Channels, frac); \
309 value = lpFilter1P(WetFilter, chans[i], value); \
310 WetBuffer[OutPos] += value*WetSend * scaler; \
314 pos += frac>>FRACTIONBITS; \
315 frac &= FRACTIONMASK; \
318 if(OutPos == SamplesToDo) \
320 for(i = 0;i < Channels;i++) \
322 value = sampler(data + pos*Channels + i, Channels, frac); \
324 value = lpFilter1PC(WetFilter, chans[i], value); \
325 WetPendingClicks[0] += value*WetSend * scaler; \
329 *DataPosInt += pos; \
330 *DataPosFrac = frac; \
333 DECL_TEMPLATE(ALfloat
, point32
)
334 DECL_TEMPLATE(ALfloat
, lerp32
)
335 DECL_TEMPLATE(ALfloat
, cubic32
)
337 DECL_TEMPLATE(ALshort
, point16
)
338 DECL_TEMPLATE(ALshort
, lerp16
)
339 DECL_TEMPLATE(ALshort
, cubic16
)
341 DECL_TEMPLATE(ALubyte
, point8
)
342 DECL_TEMPLATE(ALubyte
, lerp8
)
343 DECL_TEMPLATE(ALubyte
, cubic8
)
347 static const Channel RearChans
[] = { BACK_LEFT
, BACK_RIGHT
};
348 static const Channel QuadChans
[] = { FRONT_LEFT
, FRONT_RIGHT
,
349 BACK_LEFT
, BACK_RIGHT
};
350 static const Channel X51Chans
[] = { FRONT_LEFT
, FRONT_RIGHT
,
352 BACK_LEFT
, BACK_RIGHT
};
353 static const Channel X61Chans
[] = { FRONT_LEFT
, FRONT_RIGHT
,
356 SIDE_LEFT
, SIDE_RIGHT
};
357 static const Channel X71Chans
[] = { FRONT_LEFT
, FRONT_RIGHT
,
359 BACK_LEFT
, BACK_RIGHT
,
360 SIDE_LEFT
, SIDE_RIGHT
};
362 #define DECL_TEMPLATE(T, count, sampler) \
363 static void Mix_##T##_##count##_##sampler(ALsource *Source, ALCdevice *Device,\
364 const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
365 const Channel chans[count], \
366 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
368 const ALuint Channels = count; \
369 const ALfloat scaler = 1.0f/Channels; \
370 ALfloat (*DryBuffer)[MAXCHANNELS]; \
371 ALfloat *ClickRemoval, *PendingClicks; \
373 ALfloat DrySend[MAXCHANNELS]; \
380 increment = Source->Params.Step; \
382 DryBuffer = Device->DryBuffer; \
383 ClickRemoval = Device->ClickRemoval; \
384 PendingClicks = Device->PendingClicks; \
385 DryFilter = &Source->Params.iirFilter; \
386 for(i = 0;i < MAXCHANNELS;i++) \
387 DrySend[i] = Source->Params.DryGains[i]; \
390 frac = *DataPosFrac; \
394 for(i = 0;i < Channels;i++) \
396 value = sampler(data + pos*Channels + i, Channels, frac); \
398 value = lpFilter2PC(DryFilter, chans[i]*2, value); \
399 ClickRemoval[chans[i]] -= value*DrySend[chans[i]]; \
402 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
404 for(i = 0;i < Channels;i++) \
406 value = sampler(data + pos*Channels + i, Channels, frac); \
408 value = lpFilter2P(DryFilter, chans[i]*2, value); \
409 DryBuffer[OutPos][chans[i]] += value*DrySend[chans[i]]; \
413 pos += frac>>FRACTIONBITS; \
414 frac &= FRACTIONMASK; \
417 if(OutPos == SamplesToDo) \
419 for(i = 0;i < Channels;i++) \
421 value = sampler(data + pos*Channels + i, Channels, 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++) \
431 ALfloat *WetBuffer; \
432 ALfloat *WetClickRemoval; \
433 ALfloat *WetPendingClicks; \
436 if(!Source->Send[out].Slot || \
437 Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
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; \
447 frac = *DataPosFrac; \
448 OutPos -= BufferSize; \
452 for(i = 0;i < Channels;i++) \
454 value = sampler(data + pos*Channels + i, Channels, frac); \
456 value = lpFilter1PC(WetFilter, chans[i], value); \
457 WetClickRemoval[0] -= value*WetSend * scaler; \
460 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
462 for(i = 0;i < Channels;i++) \
464 value = sampler(data + pos*Channels + i, Channels, frac); \
466 value = lpFilter1P(WetFilter, chans[i], value); \
467 WetBuffer[OutPos] += value*WetSend * scaler; \
471 pos += frac>>FRACTIONBITS; \
472 frac &= FRACTIONMASK; \
475 if(OutPos == SamplesToDo) \
477 for(i = 0;i < Channels;i++) \
479 value = sampler(data + pos*Channels + i, Channels, frac); \
481 value = lpFilter1PC(WetFilter, chans[i], value); \
482 WetPendingClicks[0] += value*WetSend * scaler; \
486 *DataPosInt += pos; \
487 *DataPosFrac = frac; \
490 DECL_TEMPLATE(ALfloat
, 2, point32
)
491 DECL_TEMPLATE(ALfloat
, 2, lerp32
)
492 DECL_TEMPLATE(ALfloat
, 2, cubic32
)
494 DECL_TEMPLATE(ALshort
, 2, point16
)
495 DECL_TEMPLATE(ALshort
, 2, lerp16
)
496 DECL_TEMPLATE(ALshort
, 2, cubic16
)
498 DECL_TEMPLATE(ALubyte
, 2, point8
)
499 DECL_TEMPLATE(ALubyte
, 2, lerp8
)
500 DECL_TEMPLATE(ALubyte
, 2, cubic8
)
503 DECL_TEMPLATE(ALfloat
, 4, point32
)
504 DECL_TEMPLATE(ALfloat
, 4, lerp32
)
505 DECL_TEMPLATE(ALfloat
, 4, cubic32
)
507 DECL_TEMPLATE(ALshort
, 4, point16
)
508 DECL_TEMPLATE(ALshort
, 4, lerp16
)
509 DECL_TEMPLATE(ALshort
, 4, cubic16
)
511 DECL_TEMPLATE(ALubyte
, 4, point8
)
512 DECL_TEMPLATE(ALubyte
, 4, lerp8
)
513 DECL_TEMPLATE(ALubyte
, 4, cubic8
)
516 DECL_TEMPLATE(ALfloat
, 6, point32
)
517 DECL_TEMPLATE(ALfloat
, 6, lerp32
)
518 DECL_TEMPLATE(ALfloat
, 6, cubic32
)
520 DECL_TEMPLATE(ALshort
, 6, point16
)
521 DECL_TEMPLATE(ALshort
, 6, lerp16
)
522 DECL_TEMPLATE(ALshort
, 6, cubic16
)
524 DECL_TEMPLATE(ALubyte
, 6, point8
)
525 DECL_TEMPLATE(ALubyte
, 6, lerp8
)
526 DECL_TEMPLATE(ALubyte
, 6, cubic8
)
529 DECL_TEMPLATE(ALfloat
, 7, point32
)
530 DECL_TEMPLATE(ALfloat
, 7, lerp32
)
531 DECL_TEMPLATE(ALfloat
, 7, cubic32
)
533 DECL_TEMPLATE(ALshort
, 7, point16
)
534 DECL_TEMPLATE(ALshort
, 7, lerp16
)
535 DECL_TEMPLATE(ALshort
, 7, cubic16
)
537 DECL_TEMPLATE(ALubyte
, 7, point8
)
538 DECL_TEMPLATE(ALubyte
, 7, lerp8
)
539 DECL_TEMPLATE(ALubyte
, 7, cubic8
)
542 DECL_TEMPLATE(ALfloat
, 8, point32
)
543 DECL_TEMPLATE(ALfloat
, 8, lerp32
)
544 DECL_TEMPLATE(ALfloat
, 8, cubic32
)
546 DECL_TEMPLATE(ALshort
, 8, point16
)
547 DECL_TEMPLATE(ALshort
, 8, lerp16
)
548 DECL_TEMPLATE(ALshort
, 8, cubic16
)
550 DECL_TEMPLATE(ALubyte
, 8, point8
)
551 DECL_TEMPLATE(ALubyte
, 8, lerp8
)
552 DECL_TEMPLATE(ALubyte
, 8, cubic8
)
557 #define DECL_TEMPLATE(T, sampler) \
558 static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
559 enum FmtChannels FmtChannels, \
560 const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
561 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
563 switch(FmtChannels) \
566 Mix_##T##_Mono_##sampler(Source, Device, \
567 Data, DataPosInt, DataPosFrac, \
568 OutPos, SamplesToDo, BufferSize); \
571 Mix_##T##_Stereo_##sampler(Source, Device, \
572 Data, DataPosInt, DataPosFrac, \
573 OutPos, SamplesToDo, BufferSize); \
576 Mix_##T##_4_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
577 QuadChans, OutPos, SamplesToDo, BufferSize); \
580 Mix_##T##_2_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
581 RearChans, OutPos, SamplesToDo, BufferSize); \
584 Mix_##T##_6_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
585 X51Chans, OutPos, SamplesToDo, BufferSize); \
588 Mix_##T##_7_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
589 X61Chans, OutPos, SamplesToDo, BufferSize); \
592 Mix_##T##_8_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
593 X71Chans, OutPos, SamplesToDo, BufferSize); \
598 DECL_TEMPLATE(ALfloat
, point32
)
599 DECL_TEMPLATE(ALfloat
, lerp32
)
600 DECL_TEMPLATE(ALfloat
, cubic32
)
602 DECL_TEMPLATE(ALshort
, point16
)
603 DECL_TEMPLATE(ALshort
, lerp16
)
604 DECL_TEMPLATE(ALshort
, cubic16
)
606 DECL_TEMPLATE(ALubyte
, point8
)
607 DECL_TEMPLATE(ALubyte
, lerp8
)
608 DECL_TEMPLATE(ALubyte
, cubic8
)
613 #define DECL_TEMPLATE(sampler) \
614 static void Mix_##sampler(ALsource *Source, ALCdevice *Device, \
615 enum FmtChannels FmtChannels, enum FmtType FmtType, \
616 const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
617 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
622 Mix_ALubyte_##sampler##8(Source, Device, FmtChannels, \
623 Data, DataPosInt, DataPosFrac, \
624 OutPos, SamplesToDo, BufferSize); \
628 Mix_ALshort_##sampler##16(Source, Device, FmtChannels, \
629 Data, DataPosInt, DataPosFrac, \
630 OutPos, SamplesToDo, BufferSize); \
634 Mix_ALfloat_##sampler##32(Source, Device, FmtChannels, \
635 Data, DataPosInt, DataPosFrac, \
636 OutPos, SamplesToDo, BufferSize); \
648 ALvoid
MixSource(ALsource
*Source
, ALCdevice
*Device
, ALuint SamplesToDo
)
650 ALbufferlistitem
*BufferListItem
;
651 ALuint DataPosInt
, DataPosFrac
;
652 enum FmtChannels FmtChannels
;
653 enum FmtType FmtType
;
654 ALuint BuffersPlayed
;
657 resampler_t Resampler
;
664 /* Get source info */
665 State
= Source
->state
;
666 BuffersPlayed
= Source
->BuffersPlayed
;
667 DataPosInt
= Source
->position
;
668 DataPosFrac
= Source
->position_fraction
;
669 Looping
= Source
->bLooping
;
670 increment
= Source
->Params
.Step
;
671 Resampler
= (increment
== FRACTIONONE
) ? POINT_RESAMPLER
:
674 /* Get buffer info */
676 FmtChannels
= FmtMono
;
678 BufferListItem
= Source
->queue
;
679 for(i
= 0;i
< Source
->BuffersInQueue
;i
++)
681 const ALbuffer
*ALBuffer
;
682 if((ALBuffer
=BufferListItem
->buffer
) != NULL
)
684 FmtChannels
= ALBuffer
->FmtChannels
;
685 FmtType
= ALBuffer
->FmtType
;
686 FrameSize
= FrameSizeFromFmt(FmtChannels
, FmtType
);
689 BufferListItem
= BufferListItem
->next
;
692 /* Get current buffer queue item */
693 BufferListItem
= Source
->queue
;
694 for(i
= 0;i
< BuffersPlayed
;i
++)
695 BufferListItem
= BufferListItem
->next
;
699 const ALuint BufferPrePadding
= ResamplerPrePadding
[Resampler
];
700 const ALuint BufferPadding
= ResamplerPadding
[Resampler
];
701 ALubyte StackData
[STACK_DATA_SIZE
];
702 ALubyte
*SrcData
= StackData
;
703 ALuint SrcDataSize
= 0;
706 /* Figure out how many buffer bytes will be needed */
707 DataSize64
= SamplesToDo
-OutPos
+1;
708 DataSize64
*= increment
;
709 DataSize64
+= DataPosFrac
+FRACTIONMASK
;
710 DataSize64
>>= FRACTIONBITS
;
711 DataSize64
+= BufferPadding
+BufferPrePadding
;
712 DataSize64
*= FrameSize
;
714 BufferSize
= min(DataSize64
, STACK_DATA_SIZE
);
715 BufferSize
-= BufferSize
%FrameSize
;
717 if(Source
->lSourceType
== AL_STATIC
)
719 const ALbuffer
*ALBuffer
= Source
->Buffer
;
720 const ALubyte
*Data
= ALBuffer
->data
;
724 /* If current pos is beyond the loop range, do not loop */
725 if(Looping
== AL_FALSE
|| DataPosInt
>= (ALuint
)ALBuffer
->LoopEnd
)
729 if(DataPosInt
>= BufferPrePadding
)
730 pos
= (DataPosInt
-BufferPrePadding
)*FrameSize
;
733 DataSize
= (BufferPrePadding
-DataPosInt
)*FrameSize
;
734 DataSize
= min(BufferSize
, DataSize
);
736 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, DataSize
);
737 SrcDataSize
+= DataSize
;
738 BufferSize
-= DataSize
;
743 /* Copy what's left to play in the source buffer, and clear the
744 * rest of the temp buffer */
745 DataSize
= ALBuffer
->size
- pos
;
746 DataSize
= min(BufferSize
, DataSize
);
748 memcpy(&SrcData
[SrcDataSize
], &Data
[pos
], DataSize
);
749 SrcDataSize
+= DataSize
;
750 BufferSize
-= DataSize
;
752 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, BufferSize
);
753 SrcDataSize
+= BufferSize
;
754 BufferSize
-= BufferSize
;
758 ALuint LoopStart
= ALBuffer
->LoopStart
;
759 ALuint LoopEnd
= ALBuffer
->LoopEnd
;
761 if(DataPosInt
>= LoopStart
)
763 pos
= DataPosInt
-LoopStart
;
764 while(pos
< BufferPrePadding
)
765 pos
+= LoopEnd
-LoopStart
;
766 pos
-= BufferPrePadding
;
770 else if(DataPosInt
>= BufferPrePadding
)
771 pos
= (DataPosInt
-BufferPrePadding
)*FrameSize
;
774 DataSize
= (BufferPrePadding
-DataPosInt
)*FrameSize
;
775 DataSize
= min(BufferSize
, DataSize
);
777 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, DataSize
);
778 SrcDataSize
+= DataSize
;
779 BufferSize
-= DataSize
;
784 /* Copy what's left of this loop iteration, then copy repeats
785 * of the loop section */
786 DataSize
= LoopEnd
*FrameSize
- pos
;
787 DataSize
= min(BufferSize
, DataSize
);
789 memcpy(&SrcData
[SrcDataSize
], &Data
[pos
], DataSize
);
790 SrcDataSize
+= DataSize
;
791 BufferSize
-= DataSize
;
793 DataSize
= (LoopEnd
-LoopStart
) * FrameSize
;
794 while(BufferSize
> 0)
796 DataSize
= min(BufferSize
, DataSize
);
798 memcpy(&SrcData
[SrcDataSize
], &Data
[LoopStart
*FrameSize
], DataSize
);
799 SrcDataSize
+= DataSize
;
800 BufferSize
-= DataSize
;
806 /* Crawl the buffer queue to fill in the temp buffer */
807 ALbufferlistitem
*BufferListIter
= BufferListItem
;
810 if(DataPosInt
>= BufferPrePadding
)
811 pos
= (DataPosInt
-BufferPrePadding
)*FrameSize
;
814 pos
= (BufferPrePadding
-DataPosInt
)*FrameSize
;
817 if(!BufferListIter
->prev
&& !Looping
)
819 ALuint DataSize
= min(BufferSize
, pos
);
821 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, DataSize
);
822 SrcDataSize
+= DataSize
;
823 BufferSize
-= DataSize
;
831 while(BufferListIter
->next
)
832 BufferListIter
= BufferListIter
->next
;
835 BufferListIter
= BufferListIter
->prev
;
837 if(BufferListIter
->buffer
)
839 if((ALuint
)BufferListIter
->buffer
->size
> pos
)
841 pos
= BufferListIter
->buffer
->size
- pos
;
844 pos
-= BufferListIter
->buffer
->size
;
849 while(BufferListIter
&& BufferSize
> 0)
851 const ALbuffer
*ALBuffer
;
852 if((ALBuffer
=BufferListIter
->buffer
) != NULL
)
854 const ALubyte
*Data
= ALBuffer
->data
;
855 ALuint DataSize
= ALBuffer
->size
;
857 /* Skip the data already played */
866 DataSize
= min(BufferSize
, DataSize
);
867 memcpy(&SrcData
[SrcDataSize
], Data
, DataSize
);
868 SrcDataSize
+= DataSize
;
869 BufferSize
-= DataSize
;
872 BufferListIter
= BufferListIter
->next
;
873 if(!BufferListIter
&& Looping
)
874 BufferListIter
= Source
->queue
;
875 else if(!BufferListIter
)
877 memset(&SrcData
[SrcDataSize
], (FmtType
==FmtUByte
)?0x80:0, BufferSize
);
878 SrcDataSize
+= BufferSize
;
879 BufferSize
-= BufferSize
;
884 /* Figure out how many samples we can mix. */
885 DataSize64
= SrcDataSize
/ FrameSize
;
886 DataSize64
-= BufferPadding
+BufferPrePadding
;
887 DataSize64
<<= FRACTIONBITS
;
888 DataSize64
-= increment
;
889 DataSize64
-= DataPosFrac
;
891 BufferSize
= (ALuint
)((DataSize64
+(increment
-1)) / increment
);
892 BufferSize
= min(BufferSize
, (SamplesToDo
-OutPos
));
894 SrcData
+= BufferPrePadding
*FrameSize
;
897 case POINT_RESAMPLER
:
898 Mix_point(Source
, Device
, FmtChannels
, FmtType
,
899 SrcData
, &DataPosInt
, &DataPosFrac
,
900 OutPos
, SamplesToDo
, BufferSize
);
902 case LINEAR_RESAMPLER
:
903 Mix_lerp(Source
, Device
, FmtChannels
, FmtType
,
904 SrcData
, &DataPosInt
, &DataPosFrac
,
905 OutPos
, SamplesToDo
, BufferSize
);
907 case CUBIC_RESAMPLER
:
908 Mix_cubic(Source
, Device
, FmtChannels
, FmtType
,
909 SrcData
, &DataPosInt
, &DataPosFrac
,
910 OutPos
, SamplesToDo
, BufferSize
);
916 OutPos
+= BufferSize
;
918 /* Handle looping sources */
921 const ALbuffer
*ALBuffer
;
923 ALuint LoopStart
= 0;
926 if((ALBuffer
=BufferListItem
->buffer
) != NULL
)
928 DataSize
= ALBuffer
->size
/ FrameSize
;
929 if(DataSize
> DataPosInt
)
931 LoopStart
= ALBuffer
->LoopStart
;
932 LoopEnd
= ALBuffer
->LoopEnd
;
935 if(BufferListItem
->next
)
937 BufferListItem
= BufferListItem
->next
;
942 BufferListItem
= Source
->queue
;
944 if(Source
->lSourceType
== AL_STATIC
)
946 DataPosInt
= ((DataPosInt
-LoopStart
)%(LoopEnd
-LoopStart
)) + LoopStart
;
953 BufferListItem
= Source
->queue
;
954 BuffersPlayed
= Source
->BuffersInQueue
;
960 DataPosInt
-= DataSize
;
962 } while(State
== AL_PLAYING
&& OutPos
< SamplesToDo
);
964 /* Update source info */
965 Source
->state
= State
;
966 Source
->BuffersPlayed
= BuffersPlayed
;
967 Source
->position
= DataPosInt
;
968 Source
->position_fraction
= DataPosFrac
;
969 Source
->Buffer
= BufferListItem
->buffer
;