7 #include "alAuxEffectSlot.h"
8 #include "mixer_defs.h"
11 #define LIKELY(x) __builtin_expect(!!(x), 1)
12 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
15 #define UNLIKELY(x) (x)
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
;
54 increment
= Source
->Params
.Step
;
56 DryBuffer
= Device
->DryBuffer
;
57 ClickRemoval
= Device
->ClickRemoval
;
58 PendingClicks
= Device
->PendingClicks
;
59 DryFilter
= ¶ms
->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];
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] +
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
;
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];
128 pos
+= frac
>>FRACTIONBITS
;
129 frac
&= FRACTIONMASK
;
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
;
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];
154 pos
+= frac
>>FRACTIONBITS
;
155 frac
&= FRACTIONMASK
;
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] +
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
];
192 increment
= Source
->Params
.Step
;
194 DryBuffer
= Device
->DryBuffer
;
195 ClickRemoval
= Device
->ClickRemoval
;
196 PendingClicks
= Device
->PendingClicks
;
197 DryFilter
= ¶ms
->iirFilter
;
199 for(i
= 0;i
< NumChannels
;i
++)
201 for(c
= 0;c
< MaxChannels
;c
++)
202 DrySend
[c
] = params
->Gains
[i
][c
];
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
);
222 pos
+= frac
>>FRACTIONBITS
;
223 frac
&= FRACTIONMASK
;
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
;
246 ALfloat
*WetClickRemoval
;
247 ALfloat
*WetPendingClicks
;
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
= ¶ms
->iirFilter
;
262 WetSend
= params
->Gain
;
264 for(i
= 0;i
< NumChannels
;i
++)
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
;
284 pos
+= frac
>>FRACTIONBITS
;
285 frac
&= FRACTIONMASK
;
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
;
301 #undef MixDirect_Hrtf