Avoid separate updates to sources that should apply together
[openal-soft.git] / OpenAL32 / Include / alu.h
blobfc58bfb102ffa389f73ec1ebc6a730f7818c21cb
1 #ifndef _ALU_H_
2 #define _ALU_H_
4 #include <limits.h>
5 #include <math.h>
6 #ifdef HAVE_FLOAT_H
7 #include <float.h>
8 #endif
9 #ifdef HAVE_IEEEFP_H
10 #include <ieeefp.h>
11 #endif
13 #include "alMain.h"
14 #include "alBuffer.h"
15 #include "alFilter.h"
16 #include "alAuxEffectSlot.h"
18 #include "hrtf.h"
19 #include "align.h"
20 #include "math_defs.h"
23 #define MAX_PITCH (255)
25 /* Maximum number of buffer samples before the current pos needed for resampling. */
26 #define MAX_PRE_SAMPLES 12
28 /* Maximum number of buffer samples after the current pos needed for resampling. */
29 #define MAX_POST_SAMPLES 12
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
36 struct ALsource;
37 struct ALsourceProps;
38 struct ALvoice;
39 struct ALeffectslot;
40 struct ALbuffer;
43 /* The number of distinct scale and phase intervals within the filter table. */
44 #define BSINC_SCALE_BITS 4
45 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
46 #define BSINC_PHASE_BITS 4
47 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
49 /* Interpolator state. Kind of a misnomer since the interpolator itself is
50 * stateless. This just keeps it from having to recompute scale-related
51 * mappings for every sample.
53 typedef struct BsincState {
54 ALfloat sf; /* Scale interpolation factor. */
55 ALuint m; /* Coefficient count. */
56 ALint l; /* Left coefficient offset. */
57 struct {
58 const ALfloat *filter; /* Filter coefficients. */
59 const ALfloat *scDelta; /* Scale deltas. */
60 const ALfloat *phDelta; /* Phase deltas. */
61 const ALfloat *spDelta; /* Scale-phase deltas. */
62 } coeffs[BSINC_PHASE_COUNT];
63 } BsincState;
66 typedef union aluVector {
67 alignas(16) ALfloat v[4];
68 } aluVector;
70 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
72 vector->v[0] = x;
73 vector->v[1] = y;
74 vector->v[2] = z;
75 vector->v[3] = w;
79 typedef union aluMatrixf {
80 alignas(16) ALfloat m[4][4];
81 } aluMatrixf;
83 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
84 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
86 matrix->m[row][0] = m0;
87 matrix->m[row][1] = m1;
88 matrix->m[row][2] = m2;
89 matrix->m[row][3] = m3;
92 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
93 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
94 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
95 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
97 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
98 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
99 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
100 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
104 typedef union aluMatrixd {
105 alignas(16) ALdouble m[4][4];
106 } aluMatrixd;
108 inline void aluMatrixdSetRow(aluMatrixd *matrix, ALuint row,
109 ALdouble m0, ALdouble m1, ALdouble m2, ALdouble m3)
111 matrix->m[row][0] = m0;
112 matrix->m[row][1] = m1;
113 matrix->m[row][2] = m2;
114 matrix->m[row][3] = m3;
117 inline void aluMatrixdSet(aluMatrixd *matrix, ALdouble m00, ALdouble m01, ALdouble m02, ALdouble m03,
118 ALdouble m10, ALdouble m11, ALdouble m12, ALdouble m13,
119 ALdouble m20, ALdouble m21, ALdouble m22, ALdouble m23,
120 ALdouble m30, ALdouble m31, ALdouble m32, ALdouble m33)
122 aluMatrixdSetRow(matrix, 0, m00, m01, m02, m03);
123 aluMatrixdSetRow(matrix, 1, m10, m11, m12, m13);
124 aluMatrixdSetRow(matrix, 2, m20, m21, m22, m23);
125 aluMatrixdSetRow(matrix, 3, m30, m31, m32, m33);
129 enum ActiveFilters {
130 AF_None = 0,
131 AF_LowPass = 1,
132 AF_HighPass = 2,
133 AF_BandPass = AF_LowPass | AF_HighPass
137 typedef struct MixGains {
138 ALfloat Current;
139 ALfloat Step;
140 ALfloat Target;
141 } MixGains;
143 typedef struct MixHrtfParams {
144 const HrtfParams *Target;
145 HrtfParams *Current;
146 struct {
147 alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
148 ALint Delay[2];
149 } Steps;
150 } MixHrtfParams;
152 typedef struct DirectParams {
153 ALfloat (*OutBuffer)[BUFFERSIZE];
154 ALuint OutChannels;
156 struct {
157 enum ActiveFilters ActiveType;
158 ALfilterState LowPass;
159 ALfilterState HighPass;
160 } Filters[MAX_INPUT_CHANNELS];
162 struct {
163 HrtfParams Current;
164 HrtfParams Target;
165 HrtfState State;
166 } Hrtf[MAX_INPUT_CHANNELS];
168 struct {
169 ALfloat Current[MAX_OUTPUT_CHANNELS];
170 ALfloat Target[MAX_OUTPUT_CHANNELS];
171 } Gains[MAX_INPUT_CHANNELS];
172 } DirectParams;
174 typedef struct SendParams {
175 ALfloat (*OutBuffer)[BUFFERSIZE];
176 ALuint OutChannels;
178 struct {
179 enum ActiveFilters ActiveType;
180 ALfilterState LowPass;
181 ALfilterState HighPass;
182 } Filters[MAX_INPUT_CHANNELS];
184 struct {
185 ALfloat Current[MAX_OUTPUT_CHANNELS];
186 ALfloat Target[MAX_OUTPUT_CHANNELS];
187 } Gains[MAX_INPUT_CHANNELS];
188 } SendParams;
191 typedef const ALfloat* (*ResamplerFunc)(const BsincState *state,
192 const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen
195 typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
196 ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
197 ALuint Counter, ALuint OutPos, ALuint BufferSize);
198 typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx,
199 const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos,
200 const ALuint IrSize, const MixHrtfParams *hrtfparams,
201 HrtfState *hrtfstate, ALuint BufferSize);
204 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
206 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
207 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
209 #define FRACTIONBITS (12)
210 #define FRACTIONONE (1<<FRACTIONBITS)
211 #define FRACTIONMASK (FRACTIONONE-1)
214 inline ALfloat minf(ALfloat a, ALfloat b)
215 { return ((a > b) ? b : a); }
216 inline ALfloat maxf(ALfloat a, ALfloat b)
217 { return ((a > b) ? a : b); }
218 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
219 { return minf(max, maxf(min, val)); }
221 inline ALdouble mind(ALdouble a, ALdouble b)
222 { return ((a > b) ? b : a); }
223 inline ALdouble maxd(ALdouble a, ALdouble b)
224 { return ((a > b) ? a : b); }
225 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
226 { return mind(max, maxd(min, val)); }
228 inline ALuint minu(ALuint a, ALuint b)
229 { return ((a > b) ? b : a); }
230 inline ALuint maxu(ALuint a, ALuint b)
231 { return ((a > b) ? a : b); }
232 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
233 { return minu(max, maxu(min, val)); }
235 inline ALint mini(ALint a, ALint b)
236 { return ((a > b) ? b : a); }
237 inline ALint maxi(ALint a, ALint b)
238 { return ((a > b) ? a : b); }
239 inline ALint clampi(ALint val, ALint min, ALint max)
240 { return mini(max, maxi(min, val)); }
242 inline ALint64 mini64(ALint64 a, ALint64 b)
243 { return ((a > b) ? b : a); }
244 inline ALint64 maxi64(ALint64 a, ALint64 b)
245 { return ((a > b) ? a : b); }
246 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
247 { return mini64(max, maxi64(min, val)); }
249 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
250 { return ((a > b) ? b : a); }
251 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
252 { return ((a > b) ? a : b); }
253 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
254 { return minu64(max, maxu64(min, val)); }
257 union ResamplerCoeffs {
258 ALfloat FIR4[FRACTIONONE][4];
259 ALfloat FIR8[FRACTIONONE][8];
261 extern alignas(16) union ResamplerCoeffs ResampleCoeffs;
263 extern alignas(16) const ALfloat bsincTab[18840];
266 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
268 return val1 + (val2-val1)*mu;
270 inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac)
272 const ALfloat *k = ResampleCoeffs.FIR4[frac];
273 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3;
275 inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint frac)
277 const ALfloat *k = ResampleCoeffs.FIR8[frac];
278 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3 +
279 k[4]*val4 + k[5]*val5 + k[6]*val6 + k[7]*val7;
283 enum HrtfRequestMode {
284 Hrtf_Default = 0,
285 Hrtf_Enable = 1,
286 Hrtf_Disable = 2,
290 void aluInitMixer(void);
292 /* aluInitRenderer
294 * Set up the appropriate panning method and mixing method given the device
295 * properties.
297 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
299 void aluInitEffectPanning(struct ALeffectslot *slot);
302 * CalcDirectionCoeffs
304 * Calculates ambisonic coefficients based on a direction vector. The vector
305 * must be normalized (unit length), and the spread is the angular width of the
306 * sound (0...tau).
308 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
311 * CalcXYZCoeffs
313 * Same as CalcDirectionCoeffs except the direction is specified as separate x,
314 * y, and z parameters instead of an array.
316 inline void CalcXYZCoeffs(ALfloat x, ALfloat y, ALfloat z, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
318 ALfloat dir[3] = { x, y, z };
319 CalcDirectionCoeffs(dir, spread, coeffs);
323 * CalcAngleCoeffs
325 * Calculates ambisonic coefficients based on azimuth and elevation. The
326 * azimuth and elevation parameters are in radians, going right and up
327 * respectively.
329 void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
332 * ComputeAmbientGains
334 * Computes channel gains for ambient, omni-directional sounds.
336 #define ComputeAmbientGains(b, g, o) do { \
337 if((b).CoeffCount > 0) \
338 ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o); \
339 else \
340 ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
341 } while (0)
342 void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
343 void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
346 * ComputePanningGains
348 * Computes panning gains using the given channel decoder coefficients and the
349 * pre-calculated direction or angle coefficients.
351 #define ComputePanningGains(b, c, g, o) do { \
352 if((b).CoeffCount > 0) \
353 ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\
354 else \
355 ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
356 } while (0)
357 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALuint numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
358 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
361 * ComputeFirstOrderGains
363 * Sets channel gains for a first-order ambisonics input channel. The matrix is
364 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
365 * orient the sound samples.
367 #define ComputeFirstOrderGains(b, m, g, o) do { \
368 if((b).CoeffCount > 0) \
369 ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o); \
370 else \
371 ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
372 } while (0)
373 void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
374 void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
377 ALvoid CalcAttnSourceParams(struct ALvoice *voice, const struct ALsourceProps *props, const struct ALbuffer *buffer, const ALCcontext *ALContext);
378 ALvoid CalcNonAttnSourceParams(struct ALvoice *voice, const struct ALsourceProps *props, const struct ALbuffer *buffer, const ALCcontext *ALContext);
380 ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo);
382 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
383 /* Caller must lock the device. */
384 ALvoid aluHandleDisconnect(ALCdevice *device);
386 extern ALfloat ConeScale;
387 extern ALfloat ZScale;
389 #ifdef __cplusplus
391 #endif
393 #endif