Do the filtering separately from the mixing
[openal-soft.git] / Alc / mixer_inc.c
blobf60ade657cd251c143da8f060f5a83f7dba67674
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 ALuint pos;
57 ALuint c;
59 DryBuffer = Device->DryBuffer;
60 ClickRemoval = Device->ClickRemoval;
61 PendingClicks = Device->PendingClicks;
63 pos = 0;
64 for(c = 0;c < IrSize;c++)
66 Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter);
67 Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter);
70 Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter);
71 Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter);
73 if(LIKELY(OutPos == 0))
75 History[Offset&SRC_HISTORY_MASK] = data[pos];
76 left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
77 History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
78 (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
79 right = lerp(History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
80 History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
81 (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
83 ClickRemoval[FrontLeft] -= Values[(Offset+1)&HRIR_MASK][0] +
84 Coeffs[0][0] * left;
85 ClickRemoval[FrontRight] -= Values[(Offset+1)&HRIR_MASK][1] +
86 Coeffs[0][1] * right;
88 for(pos = 0;pos < BufferSize && Counter > 0;pos++)
90 History[Offset&SRC_HISTORY_MASK] = data[pos];
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 Delay[0] += DelayStep[0];
99 Delay[1] += DelayStep[1];
101 Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
102 Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
103 Offset++;
105 ApplyCoeffsStep(Offset, Values, IrSize, Coeffs, CoeffStep, left, right);
106 DryBuffer[OutPos][FrontLeft] += Values[Offset&HRIR_MASK][0];
107 DryBuffer[OutPos][FrontRight] += Values[Offset&HRIR_MASK][1];
109 OutPos++;
110 Counter--;
113 Delay[0] >>= HRTFDELAY_BITS;
114 Delay[1] >>= HRTFDELAY_BITS;
115 for(;pos < BufferSize;pos++)
117 History[Offset&SRC_HISTORY_MASK] = data[pos];
118 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
119 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
121 Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
122 Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
123 Offset++;
125 ApplyCoeffs(Offset, Values, IrSize, Coeffs, left, right);
126 DryBuffer[OutPos][FrontLeft] += Values[Offset&HRIR_MASK][0];
127 DryBuffer[OutPos][FrontRight] += Values[Offset&HRIR_MASK][1];
129 OutPos++;
131 if(LIKELY(OutPos == SamplesToDo))
133 History[Offset&SRC_HISTORY_MASK] = data[pos];
134 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
135 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
137 PendingClicks[FrontLeft] += Values[(Offset+1)&HRIR_MASK][0] +
138 Coeffs[0][0] * left;
139 PendingClicks[FrontRight] += Values[(Offset+1)&HRIR_MASK][1] +
140 Coeffs[0][1] * right;
143 #endif
145 #ifndef NO_MIXDIRECT
146 void MixDirect(ALsource *Source, ALCdevice *Device, DirectParams *params,
147 const ALfloat *RESTRICT data, ALuint srcchan,
148 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
150 ALfloat (*RESTRICT DryBuffer)[MaxChannels];
151 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;
152 ALIGN(16) ALfloat DrySend[MaxChannels];
153 ALuint pos;
154 ALuint c;
155 (void)Source;
157 DryBuffer = Device->DryBuffer;
158 ClickRemoval = Device->ClickRemoval;
159 PendingClicks = Device->PendingClicks;
161 for(c = 0;c < MaxChannels;c++)
162 DrySend[c] = params->Gains[srcchan][c];
164 pos = 0;
165 if(OutPos == 0)
167 for(c = 0;c < MaxChannels;c++)
168 ClickRemoval[c] -= data[pos]*DrySend[c];
170 for(pos = 0;pos < BufferSize;pos++)
172 for(c = 0;c < MaxChannels;c++)
173 DryBuffer[OutPos][c] += data[pos]*DrySend[c];
174 OutPos++;
176 if(OutPos == SamplesToDo)
178 for(c = 0;c < MaxChannels;c++)
179 PendingClicks[c] += data[pos]*DrySend[c];
182 #endif
184 #ifndef NO_MIXSEND
185 void MixSend(SendParams *params, const ALfloat *RESTRICT data,
186 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
188 ALeffectslot *Slot;
189 ALfloat WetSend;
190 ALfloat *WetBuffer;
191 ALfloat *WetClickRemoval;
192 ALfloat *WetPendingClicks;
193 ALuint pos;
195 Slot = params->Slot;
196 WetBuffer = Slot->WetBuffer;
197 WetClickRemoval = Slot->ClickRemoval;
198 WetPendingClicks = Slot->PendingClicks;
199 WetSend = params->Gain;
201 pos = 0;
202 if(OutPos == 0)
204 WetClickRemoval[0] -= data[pos] * WetSend;
206 for(pos = 0;pos < BufferSize;pos++)
208 WetBuffer[OutPos] += data[pos] * WetSend;
209 OutPos++;
211 if(OutPos == SamplesToDo)
213 WetPendingClicks[0] += data[pos] * WetSend;
216 #endif
219 #undef MixSend
220 #undef MixDirect
221 #undef MixDirect_Hrtf
223 #undef MERGE2
224 #undef REAL_MERGE2
226 #undef UNLIKELY
227 #undef LIKELY