Workaround MinGW __declspec(align(x)) bug
[openal-soft.git] / Alc / mixer_inc.c
blob64fe0cdb88ef0d84d3194917214a164537e0fa80
1 #include "config.h"
3 #include "AL/alc.h"
4 #include "AL/al.h"
5 #include "alMain.h"
6 #include "alSource.h"
7 #include "alAuxEffectSlot.h"
8 #include "mixer_defs.h"
10 #ifdef __GNUC__
11 #define LIKELY(x) __builtin_expect(!!(x), 1)
12 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
13 #else
14 #define LIKELY(x) (x)
15 #define UNLIKELY(x) (x)
16 #endif
18 #define REAL_MERGE2(a,b) a##b
19 #define MERGE2(a,b) REAL_MERGE2(a,b)
20 #define REAL_MERGE4(a,b,c,d) a##b##c##d
21 #define MERGE4(a,b,c,d) REAL_MERGE4(a,b,c,d)
23 #define MixDirect_Hrtf MERGE4(MixDirect_Hrtf_,Sampler,_,SUFFIX)
24 #define MixDirect MERGE4(MixDirect_,Sampler,_,SUFFIX)
25 #define MixSend MERGE4(MixSend_,Sampler,_,SUFFIX)
27 static __inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*RESTRICT Values)[2],
28 ALfloat (*RESTRICT Coeffs)[2],
29 ALfloat (*RESTRICT CoeffStep)[2],
30 ALfloat left, ALfloat right);
31 static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
32 ALfloat (*RESTRICT Coeffs)[2],
33 ALfloat left, ALfloat right);
34 static __inline void ApplyValue(ALfloat *RESTRICT Output, ALfloat value,
35 const ALfloat *DrySend);
36 static __inline ALfloat Sampler(const ALfloat *vals, ALint step, ALint frac);
38 void MixDirect_Hrtf(ALsource *Source, ALCdevice *Device, DirectParams *params,
39 const ALfloat *RESTRICT data, ALuint srcfrac,
40 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
42 const ALuint NumChannels = Source->NumChannels;
43 const ALint *RESTRICT DelayStep = params->Hrtf.DelayStep;
44 ALfloat (*RESTRICT DryBuffer)[MaxChannels];
45 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;
46 ALfloat (*RESTRICT CoeffStep)[2] = params->Hrtf.CoeffStep;
47 ALuint pos, frac;
48 FILTER *DryFilter;
49 ALuint BufferIdx;
50 ALuint increment;
51 ALfloat value;
52 ALuint i, c;
54 increment = Source->Params.Step;
56 DryBuffer = Device->DryBuffer;
57 ClickRemoval = Device->ClickRemoval;
58 PendingClicks = Device->PendingClicks;
59 DryFilter = &params->iirFilter;
61 for(i = 0;i < NumChannels;i++)
63 ALfloat (*RESTRICT TargetCoeffs)[2] = params->Hrtf.Coeffs[i];
64 ALuint *RESTRICT TargetDelay = params->Hrtf.Delay[i];
65 ALfloat *RESTRICT History = Source->Hrtf.History[i];
66 ALfloat (*RESTRICT Values)[2] = Source->Hrtf.Values[i];
67 ALint Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
68 ALuint Offset = Source->Hrtf.Offset + OutPos;
69 ALIGN(16) ALfloat Coeffs[HRIR_LENGTH][2];
70 ALuint Delay[2];
71 ALfloat left, right;
73 pos = 0;
74 frac = srcfrac;
76 for(c = 0;c < HRIR_LENGTH;c++)
78 Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter);
79 Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter);
82 Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter);
83 Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter);
85 if(LIKELY(OutPos == 0))
87 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
88 value = lpFilter2PC(DryFilter, i, value);
90 History[Offset&SRC_HISTORY_MASK] = value;
91 left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
92 History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
93 (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
94 right = lerp(History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
95 History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
96 (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
98 ClickRemoval[FrontLeft] -= Values[(Offset+1)&HRIR_MASK][0] +
99 Coeffs[0][0] * left;
100 ClickRemoval[FrontRight] -= Values[(Offset+1)&HRIR_MASK][1] +
101 Coeffs[0][1] * right;
103 for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++)
105 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
106 value = lpFilter2P(DryFilter, i, value);
108 History[Offset&SRC_HISTORY_MASK] = value;
109 left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
110 History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
111 (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
112 right = lerp(History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
113 History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
114 (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
116 Delay[0] += DelayStep[0];
117 Delay[1] += DelayStep[1];
119 Values[Offset&HRIR_MASK][0] = 0.0f;
120 Values[Offset&HRIR_MASK][1] = 0.0f;
121 Offset++;
123 ApplyCoeffsStep(Offset, Values, Coeffs, CoeffStep, left, right);
124 DryBuffer[OutPos][FrontLeft] += Values[Offset&HRIR_MASK][0];
125 DryBuffer[OutPos][FrontRight] += Values[Offset&HRIR_MASK][1];
127 frac += increment;
128 pos += frac>>FRACTIONBITS;
129 frac &= FRACTIONMASK;
130 OutPos++;
131 Counter--;
134 Delay[0] >>= HRTFDELAY_BITS;
135 Delay[1] >>= HRTFDELAY_BITS;
136 for(;BufferIdx < BufferSize;BufferIdx++)
138 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
139 value = lpFilter2P(DryFilter, i, value);
141 History[Offset&SRC_HISTORY_MASK] = value;
142 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
143 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
145 Values[Offset&HRIR_MASK][0] = 0.0f;
146 Values[Offset&HRIR_MASK][1] = 0.0f;
147 Offset++;
149 ApplyCoeffs(Offset, Values, Coeffs, left, right);
150 DryBuffer[OutPos][FrontLeft] += Values[Offset&HRIR_MASK][0];
151 DryBuffer[OutPos][FrontRight] += Values[Offset&HRIR_MASK][1];
153 frac += increment;
154 pos += frac>>FRACTIONBITS;
155 frac &= FRACTIONMASK;
156 OutPos++;
158 if(LIKELY(OutPos == SamplesToDo))
160 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
161 value = lpFilter2PC(DryFilter, i, value);
163 History[Offset&SRC_HISTORY_MASK] = value;
164 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
165 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
167 PendingClicks[FrontLeft] += Values[(Offset+1)&HRIR_MASK][0] +
168 Coeffs[0][0] * left;
169 PendingClicks[FrontRight] += Values[(Offset+1)&HRIR_MASK][1] +
170 Coeffs[0][1] * right;
172 OutPos -= BufferSize;
177 void MixDirect(ALsource *Source, ALCdevice *Device, DirectParams *params,
178 const ALfloat *RESTRICT data, ALuint srcfrac,
179 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
181 const ALuint NumChannels = Source->NumChannels;
182 ALfloat (*RESTRICT DryBuffer)[MaxChannels];
183 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;
184 ALIGN(16) ALfloat DrySend[MaxChannels];
185 FILTER *DryFilter;
186 ALuint pos, frac;
187 ALuint BufferIdx;
188 ALuint increment;
189 ALfloat value;
190 ALuint i, c;
192 increment = Source->Params.Step;
194 DryBuffer = Device->DryBuffer;
195 ClickRemoval = Device->ClickRemoval;
196 PendingClicks = Device->PendingClicks;
197 DryFilter = &params->iirFilter;
199 for(i = 0;i < NumChannels;i++)
201 for(c = 0;c < MaxChannels;c++)
202 DrySend[c] = params->Gains[i][c];
204 pos = 0;
205 frac = srcfrac;
207 if(OutPos == 0)
209 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
211 value = lpFilter2PC(DryFilter, i, value);
212 ApplyValue(ClickRemoval, -value, DrySend);
214 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++)
216 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
218 value = lpFilter2P(DryFilter, i, value);
219 ApplyValue(DryBuffer[OutPos], value, DrySend);
221 frac += increment;
222 pos += frac>>FRACTIONBITS;
223 frac &= FRACTIONMASK;
224 OutPos++;
226 if(OutPos == SamplesToDo)
228 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
230 value = lpFilter2PC(DryFilter, i, value);
231 ApplyValue(PendingClicks, value, DrySend);
233 OutPos -= BufferSize;
238 void MixSend(ALsource *Source, ALuint sendidx, SendParams *params,
239 const ALfloat *RESTRICT data, ALuint srcfrac,
240 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
242 const ALuint NumChannels = Source->NumChannels;
243 ALeffectslot *Slot;
244 ALfloat WetSend;
245 ALfloat *WetBuffer;
246 ALfloat *WetClickRemoval;
247 ALfloat *WetPendingClicks;
248 FILTER *WetFilter;
249 ALuint pos, frac;
250 ALuint BufferIdx;
251 ALuint increment;
252 ALfloat value;
253 ALuint i;
255 increment = Source->Params.Step;
257 Slot = Source->Params.Slot[sendidx];
258 WetBuffer = Slot->WetBuffer;
259 WetClickRemoval = Slot->ClickRemoval;
260 WetPendingClicks = Slot->PendingClicks;
261 WetFilter = &params->iirFilter;
262 WetSend = params->Gain;
264 for(i = 0;i < NumChannels;i++)
266 pos = 0;
267 frac = srcfrac;
269 if(OutPos == 0)
271 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
273 value = lpFilter2PC(WetFilter, i, value);
274 WetClickRemoval[0] -= value * WetSend;
276 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++)
278 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
280 value = lpFilter2P(WetFilter, i, value);
281 WetBuffer[OutPos] += value * WetSend;
283 frac += increment;
284 pos += frac>>FRACTIONBITS;
285 frac &= FRACTIONMASK;
286 OutPos++;
288 if(OutPos == SamplesToDo)
290 value = Sampler(data + pos*NumChannels + i, NumChannels, frac);
292 value = lpFilter2PC(WetFilter, i, value);
293 WetPendingClicks[0] += value * WetSend;
295 OutPos -= BufferSize;
299 #undef MixSend
300 #undef MixDirect
301 #undef MixDirect_Hrtf
303 #undef MERGE4
304 #undef REAL_MERGE4
305 #undef MERGE2
306 #undef REAL_MERGE2
308 #undef UNLIKELY
309 #undef LIKELY