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)
21 #define MixDirect_Hrtf MERGE2(MixDirect_Hrtf_,SUFFIX)
22 #define MixDirect MERGE2(MixDirect_,SUFFIX)
23 #define MixSend MERGE2(MixSend_,SUFFIX)
26 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],
33 ALfloat (*RESTRICT Coeffs
)[2],
34 ALfloat left
, ALfloat right
);
37 #ifndef NO_MIXDIRECT_HRTF
38 void MixDirect_Hrtf(ALsource
*Source
, ALCdevice
*Device
, DirectParams
*params
,
39 const ALfloat
*RESTRICT data
, ALuint srcchan
,
40 ALuint OutPos
, ALuint SamplesToDo
, ALuint BufferSize
)
42 const ALint
*RESTRICT DelayStep
= params
->Hrtf
.DelayStep
;
43 const ALuint IrSize
= GetHrtfIrSize(Device
->Hrtf
);
44 ALfloat (*RESTRICT DryBuffer
)[MaxChannels
];
45 ALfloat
*RESTRICT ClickRemoval
, *RESTRICT PendingClicks
;
46 ALfloat (*RESTRICT CoeffStep
)[2] = params
->Hrtf
.CoeffStep
;
47 ALfloat (*RESTRICT TargetCoeffs
)[2] = params
->Hrtf
.Coeffs
[srcchan
];
48 ALuint
*RESTRICT TargetDelay
= params
->Hrtf
.Delay
[srcchan
];
49 ALfloat
*RESTRICT History
= Source
->Hrtf
.History
[srcchan
];
50 ALfloat (*RESTRICT Values
)[2] = Source
->Hrtf
.Values
[srcchan
];
51 ALint Counter
= maxu(Source
->Hrtf
.Counter
, OutPos
) - OutPos
;
52 ALuint Offset
= Source
->Hrtf
.Offset
+ OutPos
;
53 ALIGN(16) ALfloat Coeffs
[HRIR_LENGTH
][2];
61 DryBuffer
= Device
->DryBuffer
;
62 ClickRemoval
= Device
->ClickRemoval
;
63 PendingClicks
= Device
->PendingClicks
;
64 DryFilter
= ¶ms
->iirFilter
;
67 for(c
= 0;c
< IrSize
;c
++)
69 Coeffs
[c
][0] = TargetCoeffs
[c
][0] - (CoeffStep
[c
][0]*Counter
);
70 Coeffs
[c
][1] = TargetCoeffs
[c
][1] - (CoeffStep
[c
][1]*Counter
);
73 Delay
[0] = TargetDelay
[0] - (DelayStep
[0]*Counter
);
74 Delay
[1] = TargetDelay
[1] - (DelayStep
[1]*Counter
);
76 if(LIKELY(OutPos
== 0))
78 value
= lpFilter2PC(DryFilter
, srcchan
, data
[pos
]);
80 History
[Offset
&SRC_HISTORY_MASK
] = value
;
81 left
= lerp(History
[(Offset
-(Delay
[0]>>HRTFDELAY_BITS
))&SRC_HISTORY_MASK
],
82 History
[(Offset
-(Delay
[0]>>HRTFDELAY_BITS
)-1)&SRC_HISTORY_MASK
],
83 (Delay
[0]&HRTFDELAY_MASK
)*(1.0f
/HRTFDELAY_FRACONE
));
84 right
= lerp(History
[(Offset
-(Delay
[1]>>HRTFDELAY_BITS
))&SRC_HISTORY_MASK
],
85 History
[(Offset
-(Delay
[1]>>HRTFDELAY_BITS
)-1)&SRC_HISTORY_MASK
],
86 (Delay
[1]&HRTFDELAY_MASK
)*(1.0f
/HRTFDELAY_FRACONE
));
88 ClickRemoval
[FrontLeft
] -= Values
[(Offset
+1)&HRIR_MASK
][0] +
90 ClickRemoval
[FrontRight
] -= Values
[(Offset
+1)&HRIR_MASK
][1] +
93 for(pos
= 0;pos
< BufferSize
&& Counter
> 0;pos
++)
95 value
= lpFilter2P(DryFilter
, srcchan
, data
[pos
]);
97 History
[Offset
&SRC_HISTORY_MASK
] = value
;
98 left
= lerp(History
[(Offset
-(Delay
[0]>>HRTFDELAY_BITS
))&SRC_HISTORY_MASK
],
99 History
[(Offset
-(Delay
[0]>>HRTFDELAY_BITS
)-1)&SRC_HISTORY_MASK
],
100 (Delay
[0]&HRTFDELAY_MASK
)*(1.0f
/HRTFDELAY_FRACONE
));
101 right
= lerp(History
[(Offset
-(Delay
[1]>>HRTFDELAY_BITS
))&SRC_HISTORY_MASK
],
102 History
[(Offset
-(Delay
[1]>>HRTFDELAY_BITS
)-1)&SRC_HISTORY_MASK
],
103 (Delay
[1]&HRTFDELAY_MASK
)*(1.0f
/HRTFDELAY_FRACONE
));
105 Delay
[0] += DelayStep
[0];
106 Delay
[1] += DelayStep
[1];
108 Values
[(Offset
+IrSize
)&HRIR_MASK
][0] = 0.0f
;
109 Values
[(Offset
+IrSize
)&HRIR_MASK
][1] = 0.0f
;
112 ApplyCoeffsStep(Offset
, Values
, IrSize
, Coeffs
, CoeffStep
, left
, right
);
113 DryBuffer
[OutPos
][FrontLeft
] += Values
[Offset
&HRIR_MASK
][0];
114 DryBuffer
[OutPos
][FrontRight
] += Values
[Offset
&HRIR_MASK
][1];
120 Delay
[0] >>= HRTFDELAY_BITS
;
121 Delay
[1] >>= HRTFDELAY_BITS
;
122 for(;pos
< BufferSize
;pos
++)
124 value
= lpFilter2P(DryFilter
, srcchan
, data
[pos
]);
126 History
[Offset
&SRC_HISTORY_MASK
] = value
;
127 left
= History
[(Offset
-Delay
[0])&SRC_HISTORY_MASK
];
128 right
= History
[(Offset
-Delay
[1])&SRC_HISTORY_MASK
];
130 Values
[(Offset
+IrSize
)&HRIR_MASK
][0] = 0.0f
;
131 Values
[(Offset
+IrSize
)&HRIR_MASK
][1] = 0.0f
;
134 ApplyCoeffs(Offset
, Values
, IrSize
, Coeffs
, left
, right
);
135 DryBuffer
[OutPos
][FrontLeft
] += Values
[Offset
&HRIR_MASK
][0];
136 DryBuffer
[OutPos
][FrontRight
] += Values
[Offset
&HRIR_MASK
][1];
140 if(LIKELY(OutPos
== SamplesToDo
))
142 value
= lpFilter2PC(DryFilter
, srcchan
, data
[pos
]);
144 History
[Offset
&SRC_HISTORY_MASK
] = value
;
145 left
= History
[(Offset
-Delay
[0])&SRC_HISTORY_MASK
];
146 right
= History
[(Offset
-Delay
[1])&SRC_HISTORY_MASK
];
148 PendingClicks
[FrontLeft
] += Values
[(Offset
+1)&HRIR_MASK
][0] +
150 PendingClicks
[FrontRight
] += Values
[(Offset
+1)&HRIR_MASK
][1] +
151 Coeffs
[0][1] * right
;
157 void MixDirect(ALsource
*Source
, ALCdevice
*Device
, DirectParams
*params
,
158 const ALfloat
*RESTRICT data
, ALuint srcchan
,
159 ALuint OutPos
, ALuint SamplesToDo
, ALuint BufferSize
)
161 ALfloat (*RESTRICT DryBuffer
)[MaxChannels
];
162 ALfloat
*RESTRICT ClickRemoval
, *RESTRICT PendingClicks
;
163 ALIGN(16) ALfloat DrySend
[MaxChannels
];
170 DryBuffer
= Device
->DryBuffer
;
171 ClickRemoval
= Device
->ClickRemoval
;
172 PendingClicks
= Device
->PendingClicks
;
173 DryFilter
= ¶ms
->iirFilter
;
175 for(c
= 0;c
< MaxChannels
;c
++)
176 DrySend
[c
] = params
->Gains
[srcchan
][c
];
181 value
= lpFilter2PC(DryFilter
, srcchan
, data
[pos
]);
182 for(c
= 0;c
< MaxChannels
;c
++)
183 ClickRemoval
[c
] -= value
*DrySend
[c
];
185 for(pos
= 0;pos
< BufferSize
;pos
++)
187 value
= lpFilter2P(DryFilter
, srcchan
, data
[pos
]);
188 for(c
= 0;c
< MaxChannels
;c
++)
189 DryBuffer
[OutPos
][c
] += value
*DrySend
[c
];
192 if(OutPos
== SamplesToDo
)
194 value
= lpFilter2PC(DryFilter
, srcchan
, data
[pos
]);
195 for(c
= 0;c
< MaxChannels
;c
++)
196 PendingClicks
[c
] += value
*DrySend
[c
];
202 void MixSend(SendParams
*params
, const ALfloat
*RESTRICT data
, ALuint srcchan
,
203 ALuint OutPos
, ALuint SamplesToDo
, ALuint BufferSize
)
208 ALfloat
*WetClickRemoval
;
209 ALfloat
*WetPendingClicks
;
215 WetBuffer
= Slot
->WetBuffer
;
216 WetClickRemoval
= Slot
->ClickRemoval
;
217 WetPendingClicks
= Slot
->PendingClicks
;
218 WetFilter
= ¶ms
->iirFilter
;
219 WetSend
= params
->Gain
;
224 value
= lpFilter2PC(WetFilter
, srcchan
, data
[pos
]);
225 WetClickRemoval
[0] -= value
* WetSend
;
227 for(pos
= 0;pos
< BufferSize
;pos
++)
229 value
= lpFilter2P(WetFilter
, srcchan
, data
[pos
]);
230 WetBuffer
[OutPos
] += value
* WetSend
;
233 if(OutPos
== SamplesToDo
)
235 value
= lpFilter2PC(WetFilter
, srcchan
, data
[pos
]);
236 WetPendingClicks
[0] += value
* WetSend
;
244 #undef MixDirect_Hrtf