Apply HRTF mixer coefficients with stepping using SSE
[openal-soft.git] / Alc / mixer_inc.c
blob3e9d7f465c23fc2a441747e9dfb96d95b03b0379
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)
24 void MERGE4(MixDirect_Hrtf_,SAMPLER,_,SUFFIX)(
25 ALsource *Source, ALCdevice *Device, DirectParams *params,
26 const ALfloat *RESTRICT data, ALuint srcfrac,
27 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
29 const ALuint NumChannels = Source->NumChannels;
30 const ALint *RESTRICT DelayStep = params->Hrtf.DelayStep;
31 ALfloat (*RESTRICT DryBuffer)[MaxChannels];
32 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;
33 ALfloat (*RESTRICT CoeffStep)[2] = params->Hrtf.CoeffStep;
34 ALuint pos, frac;
35 FILTER *DryFilter;
36 ALuint BufferIdx;
37 ALuint increment;
38 ALfloat value;
39 ALuint i, c;
41 increment = Source->Params.Step;
43 DryBuffer = Device->DryBuffer;
44 ClickRemoval = Device->ClickRemoval;
45 PendingClicks = Device->PendingClicks;
46 DryFilter = &params->iirFilter;
48 for(i = 0;i < NumChannels;i++)
50 ALfloat (*RESTRICT TargetCoeffs)[2] = params->Hrtf.Coeffs[i];
51 ALuint *RESTRICT TargetDelay = params->Hrtf.Delay[i];
52 ALfloat *RESTRICT History = Source->Hrtf.History[i];
53 ALfloat (*RESTRICT Values)[2] = Source->Hrtf.Values[i];
54 ALint Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
55 ALuint Offset = Source->Hrtf.Offset + OutPos;
56 ALfloat Coeffs[HRIR_LENGTH][2] ALIGN(16);
57 ALuint Delay[2];
58 ALfloat left, right;
60 pos = 0;
61 frac = srcfrac;
63 for(c = 0;c < HRIR_LENGTH;c++)
65 Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter);
66 Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter);
69 Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter);
70 Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter);
72 if(LIKELY(OutPos == 0))
74 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
75 value = lpFilter2PC(DryFilter, i, value);
77 History[Offset&SRC_HISTORY_MASK] = value;
78 left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
79 History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
80 (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
81 right = lerp(History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
82 History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
83 (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
85 ClickRemoval[FrontLeft] -= Values[(Offset+1)&HRIR_MASK][0] +
86 Coeffs[0][0] * left;
87 ClickRemoval[FrontRight] -= Values[(Offset+1)&HRIR_MASK][1] +
88 Coeffs[0][1] * right;
90 for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++)
92 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
93 value = lpFilter2P(DryFilter, i, value);
95 History[Offset&SRC_HISTORY_MASK] = value;
96 left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
97 History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
98 (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
99 right = lerp(History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
100 History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
101 (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
103 Delay[0] += DelayStep[0];
104 Delay[1] += DelayStep[1];
106 Values[Offset&HRIR_MASK][0] = 0.0f;
107 Values[Offset&HRIR_MASK][1] = 0.0f;
108 Offset++;
110 ApplyCoeffsStep(Offset, Values, Coeffs, CoeffStep, left, right);
111 DryBuffer[OutPos][FrontLeft] += Values[Offset&HRIR_MASK][0];
112 DryBuffer[OutPos][FrontRight] += Values[Offset&HRIR_MASK][1];
114 frac += increment;
115 pos += frac>>FRACTIONBITS;
116 frac &= FRACTIONMASK;
117 OutPos++;
118 Counter--;
121 Delay[0] >>= HRTFDELAY_BITS;
122 Delay[1] >>= HRTFDELAY_BITS;
123 for(;BufferIdx < BufferSize;BufferIdx++)
125 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
126 value = lpFilter2P(DryFilter, i, value);
128 History[Offset&SRC_HISTORY_MASK] = value;
129 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
130 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
132 Values[Offset&HRIR_MASK][0] = 0.0f;
133 Values[Offset&HRIR_MASK][1] = 0.0f;
134 Offset++;
136 ApplyCoeffs(Offset, Values, Coeffs, left, right);
137 DryBuffer[OutPos][FrontLeft] += Values[Offset&HRIR_MASK][0];
138 DryBuffer[OutPos][FrontRight] += Values[Offset&HRIR_MASK][1];
140 frac += increment;
141 pos += frac>>FRACTIONBITS;
142 frac &= FRACTIONMASK;
143 OutPos++;
145 if(LIKELY(OutPos == SamplesToDo))
147 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
148 value = lpFilter2PC(DryFilter, i, value);
150 History[Offset&SRC_HISTORY_MASK] = value;
151 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
152 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
154 PendingClicks[FrontLeft] += Values[(Offset+1)&HRIR_MASK][0] +
155 Coeffs[0][0] * left;
156 PendingClicks[FrontRight] += Values[(Offset+1)&HRIR_MASK][1] +
157 Coeffs[0][1] * right;
159 OutPos -= BufferSize;
164 void MERGE4(MixDirect_,SAMPLER,_,SUFFIX)(
165 ALsource *Source, ALCdevice *Device, DirectParams *params,
166 const ALfloat *RESTRICT data, ALuint srcfrac,
167 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
169 const ALuint NumChannels = Source->NumChannels;
170 ALfloat (*RESTRICT DryBuffer)[MaxChannels];
171 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;
172 ALfloat DrySend[MaxChannels];
173 FILTER *DryFilter;
174 ALuint pos, frac;
175 ALuint BufferIdx;
176 ALuint increment;
177 ALfloat value;
178 ALuint i, c;
180 increment = Source->Params.Step;
182 DryBuffer = Device->DryBuffer;
183 ClickRemoval = Device->ClickRemoval;
184 PendingClicks = Device->PendingClicks;
185 DryFilter = &params->iirFilter;
187 for(i = 0;i < NumChannels;i++)
189 for(c = 0;c < MaxChannels;c++)
190 DrySend[c] = params->Gains[i][c];
192 pos = 0;
193 frac = srcfrac;
195 if(OutPos == 0)
197 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
199 value = lpFilter2PC(DryFilter, i, value);
200 for(c = 0;c < MaxChannels;c++)
201 ClickRemoval[c] -= value*DrySend[c];
203 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++)
205 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
207 value = lpFilter2P(DryFilter, i, value);
208 for(c = 0;c < MaxChannels;c++)
209 DryBuffer[OutPos][c] += value*DrySend[c];
211 frac += increment;
212 pos += frac>>FRACTIONBITS;
213 frac &= FRACTIONMASK;
214 OutPos++;
216 if(OutPos == SamplesToDo)
218 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
220 value = lpFilter2PC(DryFilter, i, value);
221 for(c = 0;c < MaxChannels;c++)
222 PendingClicks[c] += value*DrySend[c];
224 OutPos -= BufferSize;
229 void MERGE4(MixSend_,SAMPLER,_,SUFFIX)(
230 ALsource *Source, ALuint sendidx, SendParams *params,
231 const ALfloat *RESTRICT data, ALuint srcfrac,
232 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
234 const ALuint NumChannels = Source->NumChannels;
235 ALeffectslot *Slot;
236 ALfloat WetSend;
237 ALfloat *WetBuffer;
238 ALfloat *WetClickRemoval;
239 ALfloat *WetPendingClicks;
240 FILTER *WetFilter;
241 ALuint pos, frac;
242 ALuint BufferIdx;
243 ALuint increment;
244 ALfloat value;
245 ALuint i;
247 increment = Source->Params.Step;
249 Slot = Source->Params.Slot[sendidx];
250 WetBuffer = Slot->WetBuffer;
251 WetClickRemoval = Slot->ClickRemoval;
252 WetPendingClicks = Slot->PendingClicks;
253 WetFilter = &params->iirFilter;
254 WetSend = params->Gain;
256 for(i = 0;i < NumChannels;i++)
258 pos = 0;
259 frac = srcfrac;
261 if(OutPos == 0)
263 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
265 value = lpFilter2PC(WetFilter, i, value);
266 WetClickRemoval[0] -= value * WetSend;
268 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++)
270 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
272 value = lpFilter2P(WetFilter, i, value);
273 WetBuffer[OutPos] += value * WetSend;
275 frac += increment;
276 pos += frac>>FRACTIONBITS;
277 frac &= FRACTIONMASK;
278 OutPos++;
280 if(OutPos == SamplesToDo)
282 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
284 value = lpFilter2PC(WetFilter, i, value);
285 WetPendingClicks[0] += value * WetSend;
287 OutPos -= BufferSize;
291 #undef MERGE4
292 #undef REAL_MERGE4
293 #undef MERGE2
294 #undef REAL_MERGE2
296 #undef UNLIKELY
297 #undef LIKELY