Update HRTF code
[openal-soft/openal-hmr.git] / Alc / mixer_inc.c
blobc3df342e92eb144fcdc838004df19e5476d9ff59
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)
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],
27 const ALuint irSize,
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 const ALuint irSize,
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];
54 ALuint Delay[2];
55 ALfloat left, right;
56 FILTER *DryFilter;
57 ALfloat value;
58 ALuint pos;
59 ALuint c;
61 DryBuffer = Device->DryBuffer;
62 ClickRemoval = Device->ClickRemoval;
63 PendingClicks = Device->PendingClicks;
64 DryFilter = &params->iirFilter;
66 pos = 0;
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] +
89 Coeffs[0][0] * left;
90 ClickRemoval[FrontRight] -= Values[(Offset+1)&HRIR_MASK][1] +
91 Coeffs[0][1] * right;
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;
110 Offset++;
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];
116 OutPos++;
117 Counter--;
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;
132 Offset++;
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];
138 OutPos++;
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] +
149 Coeffs[0][0] * left;
150 PendingClicks[FrontRight] += Values[(Offset+1)&HRIR_MASK][1] +
151 Coeffs[0][1] * right;
154 #endif
156 #ifndef NO_MIXDIRECT
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];
164 FILTER *DryFilter;
165 ALuint pos;
166 ALfloat value;
167 ALuint c;
168 (void)Source;
170 DryBuffer = Device->DryBuffer;
171 ClickRemoval = Device->ClickRemoval;
172 PendingClicks = Device->PendingClicks;
173 DryFilter = &params->iirFilter;
175 for(c = 0;c < MaxChannels;c++)
176 DrySend[c] = params->Gains[srcchan][c];
178 pos = 0;
179 if(OutPos == 0)
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];
190 OutPos++;
192 if(OutPos == SamplesToDo)
194 value = lpFilter2PC(DryFilter, srcchan, data[pos]);
195 for(c = 0;c < MaxChannels;c++)
196 PendingClicks[c] += value*DrySend[c];
199 #endif
201 #ifndef NO_MIXSEND
202 void MixSend(SendParams *params, const ALfloat *RESTRICT data, ALuint srcchan,
203 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
205 ALeffectslot *Slot;
206 ALfloat WetSend;
207 ALfloat *WetBuffer;
208 ALfloat *WetClickRemoval;
209 ALfloat *WetPendingClicks;
210 FILTER *WetFilter;
211 ALuint pos;
212 ALfloat value;
214 Slot = params->Slot;
215 WetBuffer = Slot->WetBuffer;
216 WetClickRemoval = Slot->ClickRemoval;
217 WetPendingClicks = Slot->PendingClicks;
218 WetFilter = &params->iirFilter;
219 WetSend = params->Gain;
221 pos = 0;
222 if(OutPos == 0)
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;
231 OutPos++;
233 if(OutPos == SamplesToDo)
235 value = lpFilter2PC(WetFilter, srcchan, data[pos]);
236 WetPendingClicks[0] += value * WetSend;
239 #endif
242 #undef MixSend
243 #undef MixDirect
244 #undef MixDirect_Hrtf
246 #undef MERGE2
247 #undef REAL_MERGE2
249 #undef UNLIKELY
250 #undef LIKELY