Add wrapper methods to ensure aligned allocations
[openal-soft/openal-hmr.git] / Alc / mixer_inc.c
blobb7051f640157476cd18baa12382a0f874e0a7688
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 for(c = 0;c < HRIR_LENGTH;c++)
112 const ALuint off = (Offset+c)&HRIR_MASK;
113 Values[off][0] += Coeffs[c][0] * left;
114 Values[off][1] += Coeffs[c][1] * right;
115 Coeffs[c][0] += CoeffStep[c][0];
116 Coeffs[c][1] += CoeffStep[c][1];
119 DryBuffer[OutPos][FrontLeft] += Values[Offset&HRIR_MASK][0];
120 DryBuffer[OutPos][FrontRight] += Values[Offset&HRIR_MASK][1];
122 frac += increment;
123 pos += frac>>FRACTIONBITS;
124 frac &= FRACTIONMASK;
125 OutPos++;
126 Counter--;
129 Delay[0] >>= HRTFDELAY_BITS;
130 Delay[1] >>= HRTFDELAY_BITS;
131 for(;BufferIdx < BufferSize;BufferIdx++)
133 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
134 value = lpFilter2P(DryFilter, i, value);
136 History[Offset&SRC_HISTORY_MASK] = value;
137 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
138 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
140 Values[Offset&HRIR_MASK][0] = 0.0f;
141 Values[Offset&HRIR_MASK][1] = 0.0f;
142 Offset++;
144 ApplyCoeffs(Offset, Values, Coeffs, left, right);
145 DryBuffer[OutPos][FrontLeft] += Values[Offset&HRIR_MASK][0];
146 DryBuffer[OutPos][FrontRight] += Values[Offset&HRIR_MASK][1];
148 frac += increment;
149 pos += frac>>FRACTIONBITS;
150 frac &= FRACTIONMASK;
151 OutPos++;
153 if(LIKELY(OutPos == SamplesToDo))
155 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
156 value = lpFilter2PC(DryFilter, i, value);
158 History[Offset&SRC_HISTORY_MASK] = value;
159 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
160 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
162 PendingClicks[FrontLeft] += Values[(Offset+1)&HRIR_MASK][0] +
163 Coeffs[0][0] * left;
164 PendingClicks[FrontRight] += Values[(Offset+1)&HRIR_MASK][1] +
165 Coeffs[0][1] * right;
167 OutPos -= BufferSize;
172 void MERGE4(MixDirect_,SAMPLER,_,SUFFIX)(
173 ALsource *Source, ALCdevice *Device, DirectParams *params,
174 const ALfloat *RESTRICT data, ALuint srcfrac,
175 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
177 const ALuint NumChannels = Source->NumChannels;
178 ALfloat (*RESTRICT DryBuffer)[MaxChannels];
179 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;
180 ALfloat DrySend[MaxChannels];
181 FILTER *DryFilter;
182 ALuint pos, frac;
183 ALuint BufferIdx;
184 ALuint increment;
185 ALfloat value;
186 ALuint i, c;
188 increment = Source->Params.Step;
190 DryBuffer = Device->DryBuffer;
191 ClickRemoval = Device->ClickRemoval;
192 PendingClicks = Device->PendingClicks;
193 DryFilter = &params->iirFilter;
195 for(i = 0;i < NumChannels;i++)
197 for(c = 0;c < MaxChannels;c++)
198 DrySend[c] = params->Gains[i][c];
200 pos = 0;
201 frac = srcfrac;
203 if(OutPos == 0)
205 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
207 value = lpFilter2PC(DryFilter, i, value);
208 for(c = 0;c < MaxChannels;c++)
209 ClickRemoval[c] -= value*DrySend[c];
211 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++)
213 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
215 value = lpFilter2P(DryFilter, i, value);
216 for(c = 0;c < MaxChannels;c++)
217 DryBuffer[OutPos][c] += value*DrySend[c];
219 frac += increment;
220 pos += frac>>FRACTIONBITS;
221 frac &= FRACTIONMASK;
222 OutPos++;
224 if(OutPos == SamplesToDo)
226 value = SAMPLER(data + pos*NumChannels + i, NumChannels, frac);
228 value = lpFilter2PC(DryFilter, i, value);
229 for(c = 0;c < MaxChannels;c++)
230 PendingClicks[c] += value*DrySend[c];
232 OutPos -= BufferSize;
237 void MERGE4(MixSend_,SAMPLER,_,SUFFIX)(
238 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 MERGE4
300 #undef REAL_MERGE4
301 #undef MERGE2
302 #undef REAL_MERGE2
304 #undef UNLIKELY
305 #undef LIKELY