rlm@0
|
1 /**
|
rlm@0
|
2 * OpenAL cross platform audio library
|
rlm@0
|
3 * Copyright (C) 1999-2007 by authors.
|
rlm@0
|
4 * This library is free software; you can redistribute it and/or
|
rlm@0
|
5 * modify it under the terms of the GNU Library General Public
|
rlm@0
|
6 * License as published by the Free Software Foundation; either
|
rlm@0
|
7 * version 2 of the License, or (at your option) any later version.
|
rlm@0
|
8 *
|
rlm@0
|
9 * This library is distributed in the hope that it will be useful,
|
rlm@0
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
rlm@0
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
rlm@0
|
12 * Library General Public License for more details.
|
rlm@0
|
13 *
|
rlm@0
|
14 * You should have received a copy of the GNU Library General Public
|
rlm@0
|
15 * License along with this library; if not, write to the
|
rlm@0
|
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
rlm@0
|
17 * Boston, MA 02111-1307, USA.
|
rlm@0
|
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
|
rlm@0
|
19 */
|
rlm@0
|
20
|
rlm@0
|
21 #include "config.h"
|
rlm@0
|
22
|
rlm@0
|
23 #include <math.h>
|
rlm@0
|
24 #include <stdlib.h>
|
rlm@0
|
25 #include <string.h>
|
rlm@0
|
26 #include <ctype.h>
|
rlm@0
|
27 #include <assert.h>
|
rlm@0
|
28
|
rlm@0
|
29 #include "alMain.h"
|
rlm@0
|
30 #include "AL/al.h"
|
rlm@0
|
31 #include "AL/alc.h"
|
rlm@0
|
32 #include "alSource.h"
|
rlm@0
|
33 #include "alBuffer.h"
|
rlm@0
|
34 #include "alListener.h"
|
rlm@0
|
35 #include "alAuxEffectSlot.h"
|
rlm@0
|
36 #include "alu.h"
|
rlm@0
|
37 #include "bs2b.h"
|
rlm@0
|
38
|
rlm@0
|
39
|
rlm@0
|
40 static __inline ALdouble point32(const ALfloat *vals, ALint step, ALint frac)
|
rlm@0
|
41 { return vals[0]; (void)step; (void)frac; }
|
rlm@0
|
42 static __inline ALdouble lerp32(const ALfloat *vals, ALint step, ALint frac)
|
rlm@0
|
43 { return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)); }
|
rlm@0
|
44 static __inline ALdouble cubic32(const ALfloat *vals, ALint step, ALint frac)
|
rlm@0
|
45 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
|
rlm@0
|
46 frac * (1.0/FRACTIONONE)); }
|
rlm@0
|
47
|
rlm@0
|
48 static __inline ALdouble point16(const ALshort *vals, ALint step, ALint frac)
|
rlm@0
|
49 { return vals[0] * (1.0/32767.0); (void)step; (void)frac; }
|
rlm@0
|
50 static __inline ALdouble lerp16(const ALshort *vals, ALint step, ALint frac)
|
rlm@0
|
51 { return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)) * (1.0/32767.0); }
|
rlm@0
|
52 static __inline ALdouble cubic16(const ALshort *vals, ALint step, ALint frac)
|
rlm@0
|
53 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
|
rlm@0
|
54 frac * (1.0/FRACTIONONE)) * (1.0/32767.0); }
|
rlm@0
|
55
|
rlm@0
|
56 static __inline ALdouble point8(const ALbyte *vals, ALint step, ALint frac)
|
rlm@0
|
57 { return vals[0] * (1.0/127.0); (void)step; (void)frac; }
|
rlm@0
|
58 static __inline ALdouble lerp8(const ALbyte *vals, ALint step, ALint frac)
|
rlm@0
|
59 { return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)) * (1.0/127.0); }
|
rlm@0
|
60 static __inline ALdouble cubic8(const ALbyte *vals, ALint step, ALint frac)
|
rlm@0
|
61 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
|
rlm@0
|
62 frac * (1.0/FRACTIONONE)) * (1.0/127.0); }
|
rlm@0
|
63
|
rlm@0
|
64 #ifdef __GNUC__
|
rlm@0
|
65 #define LIKELY(x) __builtin_expect(!!(x), 1)
|
rlm@0
|
66 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
|
rlm@0
|
67 #else
|
rlm@0
|
68 #define LIKELY(x) (x)
|
rlm@0
|
69 #define UNLIKELY(x) (x)
|
rlm@0
|
70 #endif
|
rlm@0
|
71
|
rlm@0
|
72 #if defined(__ARM_NEON__) && defined(HAVE_ARM_NEON_H)
|
rlm@0
|
73 #include <arm_neon.h>
|
rlm@0
|
74
|
rlm@0
|
75 static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
|
rlm@0
|
76 ALfloat (*RESTRICT Coeffs)[2],
|
rlm@0
|
77 ALfloat left, ALfloat right)
|
rlm@0
|
78 {
|
rlm@0
|
79 ALuint c;
|
rlm@0
|
80 float32x4_t leftright4;
|
rlm@0
|
81 {
|
rlm@0
|
82 float32x2_t leftright2 = vdup_n_f32(0.0);
|
rlm@0
|
83 leftright2 = vset_lane_f32(left, leftright2, 0);
|
rlm@0
|
84 leftright2 = vset_lane_f32(right, leftright2, 1);
|
rlm@0
|
85 leftright4 = vcombine_f32(leftright2, leftright2);
|
rlm@0
|
86 }
|
rlm@0
|
87 for(c = 0;c < HRIR_LENGTH;c += 2)
|
rlm@0
|
88 {
|
rlm@0
|
89 const ALuint o0 = (Offset+c)&HRIR_MASK;
|
rlm@0
|
90 const ALuint o1 = (o0+1)&HRIR_MASK;
|
rlm@0
|
91 float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
|
rlm@0
|
92 vld1_f32((float32_t*)&Values[o1][0]));
|
rlm@0
|
93 float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
|
rlm@0
|
94
|
rlm@0
|
95 vals = vmlaq_f32(vals, coefs, leftright4);
|
rlm@0
|
96
|
rlm@0
|
97 vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
|
rlm@0
|
98 vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
|
rlm@0
|
99 }
|
rlm@0
|
100 }
|
rlm@0
|
101
|
rlm@0
|
102 #else
|
rlm@0
|
103
|
rlm@0
|
104 static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
|
rlm@0
|
105 ALfloat (*RESTRICT Coeffs)[2],
|
rlm@0
|
106 ALfloat left, ALfloat right)
|
rlm@0
|
107 {
|
rlm@0
|
108 ALuint c;
|
rlm@0
|
109 for(c = 0;c < HRIR_LENGTH;c++)
|
rlm@0
|
110 {
|
rlm@0
|
111 const ALuint off = (Offset+c)&HRIR_MASK;
|
rlm@0
|
112 Values[off][0] += Coeffs[c][0] * left;
|
rlm@0
|
113 Values[off][1] += Coeffs[c][1] * right;
|
rlm@0
|
114 }
|
rlm@0
|
115 }
|
rlm@0
|
116
|
rlm@0
|
117 #endif
|
rlm@0
|
118
|
rlm@0
|
119 #define DECL_TEMPLATE(T, sampler) \
|
rlm@0
|
120 static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
|
rlm@0
|
121 const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
|
rlm@0
|
122 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
|
rlm@0
|
123 { \
|
rlm@0
|
124 const ALuint NumChannels = Source->NumChannels; \
|
rlm@0
|
125 const T *RESTRICT data = srcdata; \
|
rlm@0
|
126 const ALint *RESTRICT DelayStep = Source->Params.HrtfDelayStep; \
|
rlm@0
|
127 ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
|
rlm@0
|
128 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
|
rlm@0
|
129 ALfloat (*RESTRICT CoeffStep)[2] = Source->Params.HrtfCoeffStep; \
|
rlm@0
|
130 ALuint pos, frac; \
|
rlm@0
|
131 FILTER *DryFilter; \
|
rlm@0
|
132 ALuint BufferIdx; \
|
rlm@0
|
133 ALuint increment; \
|
rlm@0
|
134 ALuint i, out, c; \
|
rlm@0
|
135 ALfloat value; \
|
rlm@0
|
136 \
|
rlm@0
|
137 increment = Source->Params.Step; \
|
rlm@0
|
138 \
|
rlm@0
|
139 DryBuffer = Device->DryBuffer; \
|
rlm@0
|
140 ClickRemoval = Device->ClickRemoval; \
|
rlm@0
|
141 PendingClicks = Device->PendingClicks; \
|
rlm@0
|
142 DryFilter = &Source->Params.iirFilter; \
|
rlm@0
|
143 \
|
rlm@0
|
144 pos = 0; \
|
rlm@0
|
145 frac = *DataPosFrac; \
|
rlm@0
|
146 \
|
rlm@0
|
147 for(i = 0;i < NumChannels;i++) \
|
rlm@0
|
148 { \
|
rlm@0
|
149 ALfloat (*RESTRICT TargetCoeffs)[2] = Source->Params.HrtfCoeffs[i]; \
|
rlm@0
|
150 ALuint *RESTRICT TargetDelay = Source->Params.HrtfDelay[i]; \
|
rlm@0
|
151 ALfloat *RESTRICT History = Source->HrtfHistory[i]; \
|
rlm@0
|
152 ALfloat (*RESTRICT Values)[2] = Source->HrtfValues[i]; \
|
rlm@0
|
153 ALint Counter = maxu(Source->HrtfCounter, OutPos) - OutPos; \
|
rlm@0
|
154 ALuint Offset = Source->HrtfOffset + OutPos; \
|
rlm@0
|
155 ALfloat Coeffs[HRIR_LENGTH][2]; \
|
rlm@0
|
156 ALuint Delay[2]; \
|
rlm@0
|
157 ALfloat left, right; \
|
rlm@0
|
158 \
|
rlm@0
|
159 pos = 0; \
|
rlm@0
|
160 frac = *DataPosFrac; \
|
rlm@0
|
161 \
|
rlm@0
|
162 for(c = 0;c < HRIR_LENGTH;c++) \
|
rlm@0
|
163 { \
|
rlm@0
|
164 Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter); \
|
rlm@0
|
165 Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter); \
|
rlm@0
|
166 } \
|
rlm@0
|
167 \
|
rlm@0
|
168 Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter) + 32768; \
|
rlm@0
|
169 Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter) + 32768; \
|
rlm@0
|
170 \
|
rlm@0
|
171 if(LIKELY(OutPos == 0)) \
|
rlm@0
|
172 { \
|
rlm@0
|
173 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
|
rlm@0
|
174 value = lpFilter2PC(DryFilter, i, value); \
|
rlm@0
|
175 \
|
rlm@0
|
176 History[Offset&SRC_HISTORY_MASK] = value; \
|
rlm@0
|
177 left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
|
rlm@0
|
178 right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
|
rlm@0
|
179 \
|
rlm@0
|
180 ClickRemoval[FRONT_LEFT] -= Values[(Offset+1)&HRIR_MASK][0] + \
|
rlm@0
|
181 Coeffs[0][0] * left; \
|
rlm@0
|
182 ClickRemoval[FRONT_RIGHT] -= Values[(Offset+1)&HRIR_MASK][1] + \
|
rlm@0
|
183 Coeffs[0][1] * right; \
|
rlm@0
|
184 } \
|
rlm@0
|
185 for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++) \
|
rlm@0
|
186 { \
|
rlm@0
|
187 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
|
rlm@0
|
188 value = lpFilter2P(DryFilter, i, value); \
|
rlm@0
|
189 \
|
rlm@0
|
190 History[Offset&SRC_HISTORY_MASK] = value; \
|
rlm@0
|
191 left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
|
rlm@0
|
192 right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
|
rlm@0
|
193 \
|
rlm@0
|
194 Delay[0] += DelayStep[0]; \
|
rlm@0
|
195 Delay[1] += DelayStep[1]; \
|
rlm@0
|
196 \
|
rlm@0
|
197 Values[Offset&HRIR_MASK][0] = 0.0f; \
|
rlm@0
|
198 Values[Offset&HRIR_MASK][1] = 0.0f; \
|
rlm@0
|
199 Offset++; \
|
rlm@0
|
200 \
|
rlm@0
|
201 for(c = 0;c < HRIR_LENGTH;c++) \
|
rlm@0
|
202 { \
|
rlm@0
|
203 const ALuint off = (Offset+c)&HRIR_MASK; \
|
rlm@0
|
204 Values[off][0] += Coeffs[c][0] * left; \
|
rlm@0
|
205 Values[off][1] += Coeffs[c][1] * right; \
|
rlm@0
|
206 Coeffs[c][0] += CoeffStep[c][0]; \
|
rlm@0
|
207 Coeffs[c][1] += CoeffStep[c][1]; \
|
rlm@0
|
208 } \
|
rlm@0
|
209 \
|
rlm@0
|
210 DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
|
rlm@0
|
211 DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
|
rlm@0
|
212 \
|
rlm@0
|
213 frac += increment; \
|
rlm@0
|
214 pos += frac>>FRACTIONBITS; \
|
rlm@0
|
215 frac &= FRACTIONMASK; \
|
rlm@0
|
216 OutPos++; \
|
rlm@0
|
217 Counter--; \
|
rlm@0
|
218 } \
|
rlm@0
|
219 \
|
rlm@0
|
220 Delay[0] >>= 16; \
|
rlm@0
|
221 Delay[1] >>= 16; \
|
rlm@0
|
222 for(;BufferIdx < BufferSize;BufferIdx++) \
|
rlm@0
|
223 { \
|
rlm@0
|
224 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
|
rlm@0
|
225 value = lpFilter2P(DryFilter, i, value); \
|
rlm@0
|
226 \
|
rlm@0
|
227 History[Offset&SRC_HISTORY_MASK] = value; \
|
rlm@0
|
228 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
|
rlm@0
|
229 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
|
rlm@0
|
230 \
|
rlm@0
|
231 Values[Offset&HRIR_MASK][0] = 0.0f; \
|
rlm@0
|
232 Values[Offset&HRIR_MASK][1] = 0.0f; \
|
rlm@0
|
233 Offset++; \
|
rlm@0
|
234 \
|
rlm@0
|
235 ApplyCoeffs(Offset, Values, Coeffs, left, right); \
|
rlm@0
|
236 DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
|
rlm@0
|
237 DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
|
rlm@0
|
238 \
|
rlm@0
|
239 frac += increment; \
|
rlm@0
|
240 pos += frac>>FRACTIONBITS; \
|
rlm@0
|
241 frac &= FRACTIONMASK; \
|
rlm@0
|
242 OutPos++; \
|
rlm@0
|
243 } \
|
rlm@0
|
244 if(LIKELY(OutPos == SamplesToDo)) \
|
rlm@0
|
245 { \
|
rlm@0
|
246 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
|
rlm@0
|
247 value = lpFilter2PC(DryFilter, i, value); \
|
rlm@0
|
248 \
|
rlm@0
|
249 History[Offset&SRC_HISTORY_MASK] = value; \
|
rlm@0
|
250 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
|
rlm@0
|
251 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
|
rlm@0
|
252 \
|
rlm@0
|
253 PendingClicks[FRONT_LEFT] += Values[(Offset+1)&HRIR_MASK][0] + \
|
rlm@0
|
254 Coeffs[0][0] * left; \
|
rlm@0
|
255 PendingClicks[FRONT_RIGHT] += Values[(Offset+1)&HRIR_MASK][1] + \
|
rlm@0
|
256 Coeffs[0][1] * right; \
|
rlm@0
|
257 } \
|
rlm@0
|
258 OutPos -= BufferSize; \
|
rlm@0
|
259 } \
|
rlm@0
|
260 \
|
rlm@0
|
261 for(out = 0;out < Device->NumAuxSends;out++) \
|
rlm@0
|
262 { \
|
rlm@0
|
263 ALeffectslot *Slot = Source->Params.Send[out].Slot; \
|
rlm@0
|
264 ALfloat WetSend; \
|
rlm@0
|
265 ALfloat *RESTRICT WetBuffer; \
|
rlm@0
|
266 ALfloat *RESTRICT WetClickRemoval; \
|
rlm@0
|
267 ALfloat *RESTRICT WetPendingClicks; \
|
rlm@0
|
268 FILTER *WetFilter; \
|
rlm@0
|
269 \
|
rlm@0
|
270 if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \
|
rlm@0
|
271 continue; \
|
rlm@0
|
272 \
|
rlm@0
|
273 WetBuffer = Slot->WetBuffer; \
|
rlm@0
|
274 WetClickRemoval = Slot->ClickRemoval; \
|
rlm@0
|
275 WetPendingClicks = Slot->PendingClicks; \
|
rlm@0
|
276 WetFilter = &Source->Params.Send[out].iirFilter; \
|
rlm@0
|
277 WetSend = Source->Params.Send[out].WetGain; \
|
rlm@0
|
278 \
|
rlm@0
|
279 for(i = 0;i < NumChannels;i++) \
|
rlm@0
|
280 { \
|
rlm@0
|
281 pos = 0; \
|
rlm@0
|
282 frac = *DataPosFrac; \
|
rlm@0
|
283 \
|
rlm@0
|
284 if(LIKELY(OutPos == 0)) \
|
rlm@0
|
285 { \
|
rlm@0
|
286 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
|
rlm@0
|
287 value = lpFilter1PC(WetFilter, i, value); \
|
rlm@0
|
288 \
|
rlm@0
|
289 WetClickRemoval[0] -= value * WetSend; \
|
rlm@0
|
290 } \
|
rlm@0
|
291 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
|
rlm@0
|
292 { \
|
rlm@0
|
293 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
|
rlm@0
|
294 value = lpFilter1P(WetFilter, i, value); \
|
rlm@0
|
295 \
|
rlm@0
|
296 WetBuffer[OutPos] += value * WetSend; \
|
rlm@0
|
297 \
|
rlm@0
|
298 frac += increment; \
|
rlm@0
|
299 pos += frac>>FRACTIONBITS; \
|
rlm@0
|
300 frac &= FRACTIONMASK; \
|
rlm@0
|
301 OutPos++; \
|
rlm@0
|
302 } \
|
rlm@0
|
303 if(LIKELY(OutPos == SamplesToDo)) \
|
rlm@0
|
304 { \
|
rlm@0
|
305 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
|
rlm@0
|
306 value = lpFilter1PC(WetFilter, i, value); \
|
rlm@0
|
307 \
|
rlm@0
|
308 WetPendingClicks[0] += value * WetSend; \
|
rlm@0
|
309 } \
|
rlm@0
|
310 OutPos -= BufferSize; \
|
rlm@0
|
311 } \
|
rlm@0
|
312 } \
|
rlm@0
|
313 *DataPosInt += pos; \
|
rlm@0
|
314 *DataPosFrac = frac; \
|
rlm@0
|
315 }
|
rlm@0
|
316
|
rlm@0
|
317 DECL_TEMPLATE(ALfloat, point32)
|
rlm@0
|
318 DECL_TEMPLATE(ALfloat, lerp32)
|
rlm@0
|
319 DECL_TEMPLATE(ALfloat, cubic32)
|
rlm@0
|
320
|
rlm@0
|
321 DECL_TEMPLATE(ALshort, point16)
|
rlm@0
|
322 DECL_TEMPLATE(ALshort, lerp16)
|
rlm@0
|
323 DECL_TEMPLATE(ALshort, cubic16)
|
rlm@0
|
324
|
rlm@0
|
325 DECL_TEMPLATE(ALbyte, point8)
|
rlm@0
|
326 DECL_TEMPLATE(ALbyte, lerp8)
|
rlm@0
|
327 DECL_TEMPLATE(ALbyte, cubic8)
|
rlm@0
|
328
|
rlm@0
|
329 #undef DECL_TEMPLATE
|
rlm@0
|
330
|
rlm@0
|
331
|
rlm@0
|
332 #define DECL_TEMPLATE(T, sampler) \
|
rlm@0
|
333 static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
|
rlm@0
|
334 const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
|
rlm@0
|
335 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
|
rlm@0
|
336 { \
|
rlm@0
|
337 const ALuint NumChannels = Source->NumChannels; \
|
rlm@0
|
338 const T *RESTRICT data = srcdata; \
|
rlm@0
|
339 ALfloat (*DryBuffer)[MAXCHANNELS]; \
|
rlm@0
|
340 ALfloat *ClickRemoval, *PendingClicks; \
|
rlm@0
|
341 ALuint pos, frac; \
|
rlm@0
|
342 ALfloat DrySend[MAXCHANNELS][MAXCHANNELS]; \
|
rlm@0
|
343 FILTER *DryFilter; \
|
rlm@0
|
344 ALuint BufferIdx; \
|
rlm@0
|
345 ALuint increment; \
|
rlm@0
|
346 ALuint i, out, c; \
|
rlm@0
|
347 ALfloat value; \
|
rlm@0
|
348 \
|
rlm@0
|
349 increment = Source->Params.Step; \
|
rlm@0
|
350 \
|
rlm@0
|
351 DryBuffer = Device->DryBuffer; \
|
rlm@0
|
352 ClickRemoval = Device->ClickRemoval; \
|
rlm@0
|
353 PendingClicks = Device->PendingClicks; \
|
rlm@0
|
354 DryFilter = &Source->Params.iirFilter; \
|
rlm@0
|
355 for(i = 0;i < NumChannels;i++) \
|
rlm@0
|
356 { \
|
rlm@0
|
357 for(c = 0;c < MAXCHANNELS;c++) \
|
rlm@0
|
358 DrySend[i][c] = Source->Params.DryGains[i][c]; \
|
rlm@0
|
359 } \
|
rlm@0
|
360 \
|
rlm@0
|
361 pos = 0; \
|
rlm@0
|
362 frac = *DataPosFrac; \
|
rlm@0
|
363 \
|
rlm@0
|
364 for(i = 0;i < NumChannels;i++) \
|
rlm@0
|
365 { \
|
rlm@0
|
366 pos = 0; \
|
rlm@0
|
367 frac = *DataPosFrac; \
|
rlm@0
|
368 \
|
rlm@0
|
369 if(OutPos == 0) \
|
rlm@0
|
370 { \
|
rlm@0
|
371 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
|
rlm@0
|
372 \
|
rlm@0
|
373 value = lpFilter2PC(DryFilter, i, value); \
|
rlm@0
|
374 for(c = 0;c < MAXCHANNELS;c++) \
|
rlm@0
|
375 ClickRemoval[c] -= value*DrySend[i][c]; \
|
rlm@0
|
376 } \
|
rlm@0
|
377 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
|
rlm@0
|
378 { \
|
rlm@0
|
379 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
|
rlm@0
|
380 \
|
rlm@0
|
381 value = lpFilter2P(DryFilter, i, value); \
|
rlm@0
|
382 for(c = 0;c < MAXCHANNELS;c++) \
|
rlm@0
|
383 DryBuffer[OutPos][c] += value*DrySend[i][c]; \
|
rlm@0
|
384 \
|
rlm@0
|
385 frac += increment; \
|
rlm@0
|
386 pos += frac>>FRACTIONBITS; \
|
rlm@0
|
387 frac &= FRACTIONMASK; \
|
rlm@0
|
388 OutPos++; \
|
rlm@0
|
389 } \
|
rlm@0
|
390 if(OutPos == SamplesToDo) \
|
rlm@0
|
391 { \
|
rlm@0
|
392 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
|
rlm@0
|
393 \
|
rlm@0
|
394 value = lpFilter2PC(DryFilter, i, value); \
|
rlm@0
|
395 for(c = 0;c < MAXCHANNELS;c++) \
|
rlm@0
|
396 PendingClicks[c] += value*DrySend[i][c]; \
|
rlm@0
|
397 } \
|
rlm@0
|
398 OutPos -= BufferSize; \
|
rlm@0
|
399 } \
|
rlm@0
|
400 \
|
rlm@0
|
401 for(out = 0;out < Device->NumAuxSends;out++) \
|
rlm@0
|
402 { \
|
rlm@0
|
403 ALeffectslot *Slot = Source->Params.Send[out].Slot; \
|
rlm@0
|
404 ALfloat WetSend; \
|
rlm@0
|
405 ALfloat *WetBuffer; \
|
rlm@0
|
406 ALfloat *WetClickRemoval; \
|
rlm@0
|
407 ALfloat *WetPendingClicks; \
|
rlm@0
|
408 FILTER *WetFilter; \
|
rlm@0
|
409 \
|
rlm@0
|
410 if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \
|
rlm@0
|
411 continue; \
|
rlm@0
|
412 \
|
rlm@0
|
413 WetBuffer = Slot->WetBuffer; \
|
rlm@0
|
414 WetClickRemoval = Slot->ClickRemoval; \
|
rlm@0
|
415 WetPendingClicks = Slot->PendingClicks; \
|
rlm@0
|
416 WetFilter = &Source->Params.Send[out].iirFilter; \
|
rlm@0
|
417 WetSend = Source->Params.Send[out].WetGain; \
|
rlm@0
|
418 \
|
rlm@0
|
419 for(i = 0;i < NumChannels;i++) \
|
rlm@0
|
420 { \
|
rlm@0
|
421 pos = 0; \
|
rlm@0
|
422 frac = *DataPosFrac; \
|
rlm@0
|
423 \
|
rlm@0
|
424 if(OutPos == 0) \
|
rlm@0
|
425 { \
|
rlm@0
|
426 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
|
rlm@0
|
427 \
|
rlm@0
|
428 value = lpFilter1PC(WetFilter, i, value); \
|
rlm@0
|
429 WetClickRemoval[0] -= value * WetSend; \
|
rlm@0
|
430 } \
|
rlm@0
|
431 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
|
rlm@0
|
432 { \
|
rlm@0
|
433 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
|
rlm@0
|
434 \
|
rlm@0
|
435 value = lpFilter1P(WetFilter, i, value); \
|
rlm@0
|
436 WetBuffer[OutPos] += value * WetSend; \
|
rlm@0
|
437 \
|
rlm@0
|
438 frac += increment; \
|
rlm@0
|
439 pos += frac>>FRACTIONBITS; \
|
rlm@0
|
440 frac &= FRACTIONMASK; \
|
rlm@0
|
441 OutPos++; \
|
rlm@0
|
442 } \
|
rlm@0
|
443 if(OutPos == SamplesToDo) \
|
rlm@0
|
444 { \
|
rlm@0
|
445 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
|
rlm@0
|
446 \
|
rlm@0
|
447 value = lpFilter1PC(WetFilter, i, value); \
|
rlm@0
|
448 WetPendingClicks[0] += value * WetSend; \
|
rlm@0
|
449 } \
|
rlm@0
|
450 OutPos -= BufferSize; \
|
rlm@0
|
451 } \
|
rlm@0
|
452 } \
|
rlm@0
|
453 *DataPosInt += pos; \
|
rlm@0
|
454 *DataPosFrac = frac; \
|
rlm@0
|
455 }
|
rlm@0
|
456
|
rlm@0
|
457 DECL_TEMPLATE(ALfloat, point32)
|
rlm@0
|
458 DECL_TEMPLATE(ALfloat, lerp32)
|
rlm@0
|
459 DECL_TEMPLATE(ALfloat, cubic32)
|
rlm@0
|
460
|
rlm@0
|
461 DECL_TEMPLATE(ALshort, point16)
|
rlm@0
|
462 DECL_TEMPLATE(ALshort, lerp16)
|
rlm@0
|
463 DECL_TEMPLATE(ALshort, cubic16)
|
rlm@0
|
464
|
rlm@0
|
465 DECL_TEMPLATE(ALbyte, point8)
|
rlm@0
|
466 DECL_TEMPLATE(ALbyte, lerp8)
|
rlm@0
|
467 DECL_TEMPLATE(ALbyte, cubic8)
|
rlm@0
|
468
|
rlm@0
|
469 #undef DECL_TEMPLATE
|
rlm@0
|
470
|
rlm@0
|
471
|
rlm@0
|
472 #define DECL_TEMPLATE(sampler) \
|
rlm@0
|
473 static MixerFunc Select_##sampler(enum FmtType FmtType) \
|
rlm@0
|
474 { \
|
rlm@0
|
475 switch(FmtType) \
|
rlm@0
|
476 { \
|
rlm@0
|
477 case FmtByte: \
|
rlm@0
|
478 return Mix_ALbyte_##sampler##8; \
|
rlm@0
|
479 case FmtShort: \
|
rlm@0
|
480 return Mix_ALshort_##sampler##16; \
|
rlm@0
|
481 case FmtFloat: \
|
rlm@0
|
482 return Mix_ALfloat_##sampler##32; \
|
rlm@0
|
483 } \
|
rlm@0
|
484 return NULL; \
|
rlm@0
|
485 }
|
rlm@0
|
486
|
rlm@0
|
487 DECL_TEMPLATE(point)
|
rlm@0
|
488 DECL_TEMPLATE(lerp)
|
rlm@0
|
489 DECL_TEMPLATE(cubic)
|
rlm@0
|
490
|
rlm@0
|
491 #undef DECL_TEMPLATE
|
rlm@0
|
492
|
rlm@0
|
493 MixerFunc SelectMixer(ALbuffer *Buffer, enum Resampler Resampler)
|
rlm@0
|
494 {
|
rlm@0
|
495 switch(Resampler)
|
rlm@0
|
496 {
|
rlm@0
|
497 case POINT_RESAMPLER:
|
rlm@0
|
498 return Select_point(Buffer->FmtType);
|
rlm@0
|
499 case LINEAR_RESAMPLER:
|
rlm@0
|
500 return Select_lerp(Buffer->FmtType);
|
rlm@0
|
501 case CUBIC_RESAMPLER:
|
rlm@0
|
502 return Select_cubic(Buffer->FmtType);
|
rlm@0
|
503 case RESAMPLER_MIN:
|
rlm@0
|
504 case RESAMPLER_MAX:
|
rlm@0
|
505 break;
|
rlm@0
|
506 }
|
rlm@0
|
507 return NULL;
|
rlm@0
|
508 }
|
rlm@0
|
509
|
rlm@0
|
510 #define DECL_TEMPLATE(sampler) \
|
rlm@0
|
511 static MixerFunc Select_Hrtf_##sampler(enum FmtType FmtType) \
|
rlm@0
|
512 { \
|
rlm@0
|
513 switch(FmtType) \
|
rlm@0
|
514 { \
|
rlm@0
|
515 case FmtByte: \
|
rlm@0
|
516 return Mix_Hrtf_ALbyte_##sampler##8; \
|
rlm@0
|
517 case FmtShort: \
|
rlm@0
|
518 return Mix_Hrtf_ALshort_##sampler##16; \
|
rlm@0
|
519 case FmtFloat: \
|
rlm@0
|
520 return Mix_Hrtf_ALfloat_##sampler##32; \
|
rlm@0
|
521 } \
|
rlm@0
|
522 return NULL; \
|
rlm@0
|
523 }
|
rlm@0
|
524
|
rlm@0
|
525 DECL_TEMPLATE(point)
|
rlm@0
|
526 DECL_TEMPLATE(lerp)
|
rlm@0
|
527 DECL_TEMPLATE(cubic)
|
rlm@0
|
528
|
rlm@0
|
529 #undef DECL_TEMPLATE
|
rlm@0
|
530
|
rlm@0
|
531 MixerFunc SelectHrtfMixer(ALbuffer *Buffer, enum Resampler Resampler)
|
rlm@0
|
532 {
|
rlm@0
|
533 switch(Resampler)
|
rlm@0
|
534 {
|
rlm@0
|
535 case POINT_RESAMPLER:
|
rlm@0
|
536 return Select_Hrtf_point(Buffer->FmtType);
|
rlm@0
|
537 case LINEAR_RESAMPLER:
|
rlm@0
|
538 return Select_Hrtf_lerp(Buffer->FmtType);
|
rlm@0
|
539 case CUBIC_RESAMPLER:
|
rlm@0
|
540 return Select_Hrtf_cubic(Buffer->FmtType);
|
rlm@0
|
541 case RESAMPLER_MIN:
|
rlm@0
|
542 case RESAMPLER_MAX:
|
rlm@0
|
543 break;
|
rlm@0
|
544 }
|
rlm@0
|
545 return NULL;
|
rlm@0
|
546 }
|
rlm@0
|
547
|
rlm@0
|
548
|
rlm@0
|
549 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
|
rlm@0
|
550 {
|
rlm@0
|
551 ALbufferlistitem *BufferListItem;
|
rlm@0
|
552 ALuint DataPosInt, DataPosFrac;
|
rlm@0
|
553 ALuint BuffersPlayed;
|
rlm@0
|
554 ALboolean Looping;
|
rlm@0
|
555 ALuint increment;
|
rlm@0
|
556 enum Resampler Resampler;
|
rlm@0
|
557 ALenum State;
|
rlm@0
|
558 ALuint OutPos;
|
rlm@0
|
559 ALuint FrameSize;
|
rlm@0
|
560 ALint64 DataSize64;
|
rlm@0
|
561 ALuint i;
|
rlm@0
|
562
|
rlm@0
|
563 /* Get source info */
|
rlm@0
|
564 State = Source->state;
|
rlm@0
|
565 BuffersPlayed = Source->BuffersPlayed;
|
rlm@0
|
566 DataPosInt = Source->position;
|
rlm@0
|
567 DataPosFrac = Source->position_fraction;
|
rlm@0
|
568 Looping = Source->bLooping;
|
rlm@0
|
569 increment = Source->Params.Step;
|
rlm@0
|
570 Resampler = Source->Resampler;
|
rlm@0
|
571 FrameSize = Source->NumChannels * Source->SampleSize;
|
rlm@0
|
572
|
rlm@0
|
573 /* Get current buffer queue item */
|
rlm@0
|
574 BufferListItem = Source->queue;
|
rlm@0
|
575 for(i = 0;i < BuffersPlayed;i++)
|
rlm@0
|
576 BufferListItem = BufferListItem->next;
|
rlm@0
|
577
|
rlm@0
|
578 OutPos = 0;
|
rlm@0
|
579 do {
|
rlm@0
|
580 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
|
rlm@0
|
581 const ALuint BufferPadding = ResamplerPadding[Resampler];
|
rlm@0
|
582 ALubyte StackData[STACK_DATA_SIZE];
|
rlm@0
|
583 ALubyte *SrcData = StackData;
|
rlm@0
|
584 ALuint SrcDataSize = 0;
|
rlm@0
|
585 ALuint BufferSize;
|
rlm@0
|
586
|
rlm@0
|
587 /* Figure out how many buffer bytes will be needed */
|
rlm@0
|
588 DataSize64 = SamplesToDo-OutPos+1;
|
rlm@0
|
589 DataSize64 *= increment;
|
rlm@0
|
590 DataSize64 += DataPosFrac+FRACTIONMASK;
|
rlm@0
|
591 DataSize64 >>= FRACTIONBITS;
|
rlm@0
|
592 DataSize64 += BufferPadding+BufferPrePadding;
|
rlm@0
|
593 DataSize64 *= FrameSize;
|
rlm@0
|
594
|
rlm@0
|
595 BufferSize = ((DataSize64 > STACK_DATA_SIZE) ? STACK_DATA_SIZE : DataSize64);
|
rlm@0
|
596 BufferSize -= BufferSize%FrameSize;
|
rlm@0
|
597
|
rlm@0
|
598 if(Source->lSourceType == AL_STATIC)
|
rlm@0
|
599 {
|
rlm@0
|
600 const ALbuffer *ALBuffer = Source->Buffer;
|
rlm@0
|
601 const ALubyte *Data = ALBuffer->data;
|
rlm@0
|
602 ALuint DataSize;
|
rlm@0
|
603 ALuint pos;
|
rlm@0
|
604
|
rlm@0
|
605 /* If current pos is beyond the loop range, do not loop */
|
rlm@0
|
606 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
|
rlm@0
|
607 {
|
rlm@0
|
608 Looping = AL_FALSE;
|
rlm@0
|
609
|
rlm@0
|
610 if(DataPosInt >= BufferPrePadding)
|
rlm@0
|
611 pos = (DataPosInt-BufferPrePadding)*FrameSize;
|
rlm@0
|
612 else
|
rlm@0
|
613 {
|
rlm@0
|
614 DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
|
rlm@0
|
615 DataSize = minu(BufferSize, DataSize);
|
rlm@0
|
616
|
rlm@0
|
617 memset(&SrcData[SrcDataSize], 0, DataSize);
|
rlm@0
|
618 SrcDataSize += DataSize;
|
rlm@0
|
619 BufferSize -= DataSize;
|
rlm@0
|
620
|
rlm@0
|
621 pos = 0;
|
rlm@0
|
622 }
|
rlm@0
|
623
|
rlm@0
|
624 /* Copy what's left to play in the source buffer, and clear the
|
rlm@0
|
625 * rest of the temp buffer */
|
rlm@0
|
626 DataSize = ALBuffer->size - pos;
|
rlm@0
|
627 DataSize = minu(BufferSize, DataSize);
|
rlm@0
|
628
|
rlm@0
|
629 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
|
rlm@0
|
630 SrcDataSize += DataSize;
|
rlm@0
|
631 BufferSize -= DataSize;
|
rlm@0
|
632
|
rlm@0
|
633 memset(&SrcData[SrcDataSize], 0, BufferSize);
|
rlm@0
|
634 SrcDataSize += BufferSize;
|
rlm@0
|
635 BufferSize -= BufferSize;
|
rlm@0
|
636 }
|
rlm@0
|
637 else
|
rlm@0
|
638 {
|
rlm@0
|
639 ALuint LoopStart = ALBuffer->LoopStart;
|
rlm@0
|
640 ALuint LoopEnd = ALBuffer->LoopEnd;
|
rlm@0
|
641
|
rlm@0
|
642 if(DataPosInt >= LoopStart)
|
rlm@0
|
643 {
|
rlm@0
|
644 pos = DataPosInt-LoopStart;
|
rlm@0
|
645 while(pos < BufferPrePadding)
|
rlm@0
|
646 pos += LoopEnd-LoopStart;
|
rlm@0
|
647 pos -= BufferPrePadding;
|
rlm@0
|
648 pos += LoopStart;
|
rlm@0
|
649 pos *= FrameSize;
|
rlm@0
|
650 }
|
rlm@0
|
651 else if(DataPosInt >= BufferPrePadding)
|
rlm@0
|
652 pos = (DataPosInt-BufferPrePadding)*FrameSize;
|
rlm@0
|
653 else
|
rlm@0
|
654 {
|
rlm@0
|
655 DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
|
rlm@0
|
656 DataSize = minu(BufferSize, DataSize);
|
rlm@0
|
657
|
rlm@0
|
658 memset(&SrcData[SrcDataSize], 0, DataSize);
|
rlm@0
|
659 SrcDataSize += DataSize;
|
rlm@0
|
660 BufferSize -= DataSize;
|
rlm@0
|
661
|
rlm@0
|
662 pos = 0;
|
rlm@0
|
663 }
|
rlm@0
|
664
|
rlm@0
|
665 /* Copy what's left of this loop iteration, then copy repeats
|
rlm@0
|
666 * of the loop section */
|
rlm@0
|
667 DataSize = LoopEnd*FrameSize - pos;
|
rlm@0
|
668 DataSize = minu(BufferSize, DataSize);
|
rlm@0
|
669
|
rlm@0
|
670 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
|
rlm@0
|
671 SrcDataSize += DataSize;
|
rlm@0
|
672 BufferSize -= DataSize;
|
rlm@0
|
673
|
rlm@0
|
674 DataSize = (LoopEnd-LoopStart) * FrameSize;
|
rlm@0
|
675 while(BufferSize > 0)
|
rlm@0
|
676 {
|
rlm@0
|
677 DataSize = minu(BufferSize, DataSize);
|
rlm@0
|
678
|
rlm@0
|
679 memcpy(&SrcData[SrcDataSize], &Data[LoopStart*FrameSize], DataSize);
|
rlm@0
|
680 SrcDataSize += DataSize;
|
rlm@0
|
681 BufferSize -= DataSize;
|
rlm@0
|
682 }
|
rlm@0
|
683 }
|
rlm@0
|
684 }
|
rlm@0
|
685 else
|
rlm@0
|
686 {
|
rlm@0
|
687 /* Crawl the buffer queue to fill in the temp buffer */
|
rlm@0
|
688 ALbufferlistitem *BufferListIter = BufferListItem;
|
rlm@0
|
689 ALuint pos;
|
rlm@0
|
690
|
rlm@0
|
691 if(DataPosInt >= BufferPrePadding)
|
rlm@0
|
692 pos = (DataPosInt-BufferPrePadding)*FrameSize;
|
rlm@0
|
693 else
|
rlm@0
|
694 {
|
rlm@0
|
695 pos = (BufferPrePadding-DataPosInt)*FrameSize;
|
rlm@0
|
696 while(pos > 0)
|
rlm@0
|
697 {
|
rlm@0
|
698 if(!BufferListIter->prev && !Looping)
|
rlm@0
|
699 {
|
rlm@0
|
700 ALuint DataSize = minu(BufferSize, pos);
|
rlm@0
|
701
|
rlm@0
|
702 memset(&SrcData[SrcDataSize], 0, DataSize);
|
rlm@0
|
703 SrcDataSize += DataSize;
|
rlm@0
|
704 BufferSize -= DataSize;
|
rlm@0
|
705
|
rlm@0
|
706 pos = 0;
|
rlm@0
|
707 break;
|
rlm@0
|
708 }
|
rlm@0
|
709
|
rlm@0
|
710 if(BufferListIter->prev)
|
rlm@0
|
711 BufferListIter = BufferListIter->prev;
|
rlm@0
|
712 else
|
rlm@0
|
713 {
|
rlm@0
|
714 while(BufferListIter->next)
|
rlm@0
|
715 BufferListIter = BufferListIter->next;
|
rlm@0
|
716 }
|
rlm@0
|
717
|
rlm@0
|
718 if(BufferListIter->buffer)
|
rlm@0
|
719 {
|
rlm@0
|
720 if((ALuint)BufferListIter->buffer->size > pos)
|
rlm@0
|
721 {
|
rlm@0
|
722 pos = BufferListIter->buffer->size - pos;
|
rlm@0
|
723 break;
|
rlm@0
|
724 }
|
rlm@0
|
725 pos -= BufferListIter->buffer->size;
|
rlm@0
|
726 }
|
rlm@0
|
727 }
|
rlm@0
|
728 }
|
rlm@0
|
729
|
rlm@0
|
730 while(BufferListIter && BufferSize > 0)
|
rlm@0
|
731 {
|
rlm@0
|
732 const ALbuffer *ALBuffer;
|
rlm@0
|
733 if((ALBuffer=BufferListIter->buffer) != NULL)
|
rlm@0
|
734 {
|
rlm@0
|
735 const ALubyte *Data = ALBuffer->data;
|
rlm@0
|
736 ALuint DataSize = ALBuffer->size;
|
rlm@0
|
737
|
rlm@0
|
738 /* Skip the data already played */
|
rlm@0
|
739 if(DataSize <= pos)
|
rlm@0
|
740 pos -= DataSize;
|
rlm@0
|
741 else
|
rlm@0
|
742 {
|
rlm@0
|
743 Data += pos;
|
rlm@0
|
744 DataSize -= pos;
|
rlm@0
|
745 pos -= pos;
|
rlm@0
|
746
|
rlm@0
|
747 DataSize = minu(BufferSize, DataSize);
|
rlm@0
|
748 memcpy(&SrcData[SrcDataSize], Data, DataSize);
|
rlm@0
|
749 SrcDataSize += DataSize;
|
rlm@0
|
750 BufferSize -= DataSize;
|
rlm@0
|
751 }
|
rlm@0
|
752 }
|
rlm@0
|
753 BufferListIter = BufferListIter->next;
|
rlm@0
|
754 if(!BufferListIter && Looping)
|
rlm@0
|
755 BufferListIter = Source->queue;
|
rlm@0
|
756 else if(!BufferListIter)
|
rlm@0
|
757 {
|
rlm@0
|
758 memset(&SrcData[SrcDataSize], 0, BufferSize);
|
rlm@0
|
759 SrcDataSize += BufferSize;
|
rlm@0
|
760 BufferSize -= BufferSize;
|
rlm@0
|
761 }
|
rlm@0
|
762 }
|
rlm@0
|
763 }
|
rlm@0
|
764
|
rlm@0
|
765 /* Figure out how many samples we can mix. */
|
rlm@0
|
766 DataSize64 = SrcDataSize / FrameSize;
|
rlm@0
|
767 DataSize64 -= BufferPadding+BufferPrePadding;
|
rlm@0
|
768 DataSize64 <<= FRACTIONBITS;
|
rlm@0
|
769 DataSize64 -= increment;
|
rlm@0
|
770 DataSize64 -= DataPosFrac;
|
rlm@0
|
771
|
rlm@0
|
772 BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
|
rlm@0
|
773 BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
|
rlm@0
|
774
|
rlm@0
|
775 SrcData += BufferPrePadding*FrameSize;
|
rlm@0
|
776 Source->Params.DoMix(Source, Device, SrcData, &DataPosInt, &DataPosFrac,
|
rlm@0
|
777 OutPos, SamplesToDo, BufferSize);
|
rlm@0
|
778 OutPos += BufferSize;
|
rlm@0
|
779
|
rlm@0
|
780 /* Handle looping sources */
|
rlm@0
|
781 while(1)
|
rlm@0
|
782 {
|
rlm@0
|
783 const ALbuffer *ALBuffer;
|
rlm@0
|
784 ALuint DataSize = 0;
|
rlm@0
|
785 ALuint LoopStart = 0;
|
rlm@0
|
786 ALuint LoopEnd = 0;
|
rlm@0
|
787
|
rlm@0
|
788 if((ALBuffer=BufferListItem->buffer) != NULL)
|
rlm@0
|
789 {
|
rlm@0
|
790 DataSize = ALBuffer->size / FrameSize;
|
rlm@0
|
791 LoopStart = ALBuffer->LoopStart;
|
rlm@0
|
792 LoopEnd = ALBuffer->LoopEnd;
|
rlm@0
|
793 if(LoopEnd > DataPosInt)
|
rlm@0
|
794 break;
|
rlm@0
|
795 }
|
rlm@0
|
796
|
rlm@0
|
797 if(Looping && Source->lSourceType == AL_STATIC)
|
rlm@0
|
798 {
|
rlm@0
|
799 BufferListItem = Source->queue;
|
rlm@0
|
800 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
|
rlm@0
|
801 break;
|
rlm@0
|
802 }
|
rlm@0
|
803
|
rlm@0
|
804 if(DataSize > DataPosInt)
|
rlm@0
|
805 break;
|
rlm@0
|
806
|
rlm@0
|
807 if(BufferListItem->next)
|
rlm@0
|
808 {
|
rlm@0
|
809 BufferListItem = BufferListItem->next;
|
rlm@0
|
810 BuffersPlayed++;
|
rlm@0
|
811 }
|
rlm@0
|
812 else if(Looping)
|
rlm@0
|
813 {
|
rlm@0
|
814 BufferListItem = Source->queue;
|
rlm@0
|
815 BuffersPlayed = 0;
|
rlm@0
|
816 }
|
rlm@0
|
817 else
|
rlm@0
|
818 {
|
rlm@0
|
819 State = AL_STOPPED;
|
rlm@0
|
820 BufferListItem = Source->queue;
|
rlm@0
|
821 BuffersPlayed = Source->BuffersInQueue;
|
rlm@0
|
822 DataPosInt = 0;
|
rlm@0
|
823 DataPosFrac = 0;
|
rlm@0
|
824 break;
|
rlm@0
|
825 }
|
rlm@0
|
826
|
rlm@0
|
827 DataPosInt -= DataSize;
|
rlm@0
|
828 }
|
rlm@0
|
829 } while(State == AL_PLAYING && OutPos < SamplesToDo);
|
rlm@0
|
830
|
rlm@0
|
831 /* Update source info */
|
rlm@0
|
832 Source->state = State;
|
rlm@0
|
833 Source->BuffersPlayed = BuffersPlayed;
|
rlm@0
|
834 Source->position = DataPosInt;
|
rlm@0
|
835 Source->position_fraction = DataPosFrac;
|
rlm@0
|
836 Source->Buffer = BufferListItem->buffer;
|
rlm@0
|
837 Source->HrtfOffset += OutPos;
|
rlm@0
|
838 if(State == AL_PLAYING)
|
rlm@0
|
839 {
|
rlm@0
|
840 Source->HrtfCounter = maxu(Source->HrtfCounter, OutPos) - OutPos;
|
rlm@0
|
841 Source->HrtfMoving = AL_TRUE;
|
rlm@0
|
842 }
|
rlm@0
|
843 else
|
rlm@0
|
844 {
|
rlm@0
|
845 Source->HrtfCounter = 0;
|
rlm@0
|
846 Source->HrtfMoving = AL_FALSE;
|
rlm@0
|
847 }
|
rlm@0
|
848 }
|