Add some more 'restrict' keywords
[openal-soft.git] / OpenAL32 / Include / alu.h
blobae8645fa70982152a22af7a88f7394d92c1818f0
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;
82 extern const aluMatrixf IdentityMatrixf;
84 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
85 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
87 matrix->m[row][0] = m0;
88 matrix->m[row][1] = m1;
89 matrix->m[row][2] = m2;
90 matrix->m[row][3] = m3;
93 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
94 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
95 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
96 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
98 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
99 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
100 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
101 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
105 enum ActiveFilters {
106 AF_None = 0,
107 AF_LowPass = 1,
108 AF_HighPass = 2,
109 AF_BandPass = AF_LowPass | AF_HighPass
113 typedef struct MixHrtfParams {
114 const HrtfParams *Target;
115 HrtfParams *Current;
116 struct {
117 alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
118 ALint Delay[2];
119 } Steps;
120 } MixHrtfParams;
122 typedef struct DirectParams {
123 enum ActiveFilters FilterType;
124 ALfilterState LowPass;
125 ALfilterState HighPass;
127 struct {
128 HrtfParams Current;
129 HrtfParams Target;
130 HrtfState State;
131 } Hrtf;
133 struct {
134 ALfloat Current[MAX_OUTPUT_CHANNELS];
135 ALfloat Target[MAX_OUTPUT_CHANNELS];
136 } Gains;
137 } DirectParams;
139 typedef struct SendParams {
140 enum ActiveFilters FilterType;
141 ALfilterState LowPass;
142 ALfilterState HighPass;
144 struct {
145 ALfloat Current[MAX_OUTPUT_CHANNELS];
146 ALfloat Target[MAX_OUTPUT_CHANNELS];
147 } Gains;
148 } SendParams;
151 typedef const ALfloat* (*ResamplerFunc)(const BsincState *state,
152 const ALfloat *restrict src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen
155 typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
156 ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
157 const ALfloat *TargetGains, ALuint Counter, ALuint OutPos,
158 ALuint BufferSize);
159 typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
160 const ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans,
161 ALuint InPos, ALuint BufferSize);
162 typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx,
163 const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos,
164 const ALuint IrSize, const MixHrtfParams *hrtfparams,
165 HrtfState *hrtfstate, ALuint BufferSize);
166 typedef void (*HrtfDirectMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE],
167 ALuint lidx, ALuint ridx, const ALfloat *data, ALuint Offset,
168 const ALuint IrSize, ALfloat (*restrict Coeffs)[2],
169 ALfloat (*restrict Values)[2], ALuint BufferSize);
172 #define GAIN_MIX_MAX (16.0f) /* +24dB */
174 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
176 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
177 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
179 #define FRACTIONBITS (12)
180 #define FRACTIONONE (1<<FRACTIONBITS)
181 #define FRACTIONMASK (FRACTIONONE-1)
184 inline ALfloat minf(ALfloat a, ALfloat b)
185 { return ((a > b) ? b : a); }
186 inline ALfloat maxf(ALfloat a, ALfloat b)
187 { return ((a > b) ? a : b); }
188 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
189 { return minf(max, maxf(min, val)); }
191 inline ALdouble mind(ALdouble a, ALdouble b)
192 { return ((a > b) ? b : a); }
193 inline ALdouble maxd(ALdouble a, ALdouble b)
194 { return ((a > b) ? a : b); }
195 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
196 { return mind(max, maxd(min, val)); }
198 inline ALuint minu(ALuint a, ALuint b)
199 { return ((a > b) ? b : a); }
200 inline ALuint maxu(ALuint a, ALuint b)
201 { return ((a > b) ? a : b); }
202 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
203 { return minu(max, maxu(min, val)); }
205 inline ALint mini(ALint a, ALint b)
206 { return ((a > b) ? b : a); }
207 inline ALint maxi(ALint a, ALint b)
208 { return ((a > b) ? a : b); }
209 inline ALint clampi(ALint val, ALint min, ALint max)
210 { return mini(max, maxi(min, val)); }
212 inline ALint64 mini64(ALint64 a, ALint64 b)
213 { return ((a > b) ? b : a); }
214 inline ALint64 maxi64(ALint64 a, ALint64 b)
215 { return ((a > b) ? a : b); }
216 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
217 { return mini64(max, maxi64(min, val)); }
219 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
220 { return ((a > b) ? b : a); }
221 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
222 { return ((a > b) ? a : b); }
223 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
224 { return minu64(max, maxu64(min, val)); }
227 union ResamplerCoeffs {
228 ALfloat FIR4[FRACTIONONE][4];
229 ALfloat FIR8[FRACTIONONE][8];
231 extern alignas(16) union ResamplerCoeffs ResampleCoeffs;
233 extern alignas(16) const ALfloat bsincTab[18840];
236 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
238 return val1 + (val2-val1)*mu;
240 inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac)
242 const ALfloat *k = ResampleCoeffs.FIR4[frac];
243 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3;
245 inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint frac)
247 const ALfloat *k = ResampleCoeffs.FIR8[frac];
248 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3 +
249 k[4]*val4 + k[5]*val5 + k[6]*val6 + k[7]*val7;
253 enum HrtfRequestMode {
254 Hrtf_Default = 0,
255 Hrtf_Enable = 1,
256 Hrtf_Disable = 2,
260 void aluInitMixer(void);
262 MixerFunc SelectMixer(void);
263 RowMixerFunc SelectRowMixer(void);
265 /* aluInitRenderer
267 * Set up the appropriate panning method and mixing method given the device
268 * properties.
270 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
272 void aluInitEffectPanning(struct ALeffectslot *slot);
275 * CalcDirectionCoeffs
277 * Calculates ambisonic coefficients based on a direction vector. The vector
278 * must be normalized (unit length), and the spread is the angular width of the
279 * sound (0...tau).
281 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
284 * CalcXYZCoeffs
286 * Same as CalcDirectionCoeffs except the direction is specified as separate x,
287 * y, and z parameters instead of an array.
289 inline void CalcXYZCoeffs(ALfloat x, ALfloat y, ALfloat z, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
291 ALfloat dir[3] = { x, y, z };
292 CalcDirectionCoeffs(dir, spread, coeffs);
296 * CalcAngleCoeffs
298 * Calculates ambisonic coefficients based on azimuth and elevation. The
299 * azimuth and elevation parameters are in radians, going right and up
300 * respectively.
302 void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
305 * ComputeAmbientGains
307 * Computes channel gains for ambient, omni-directional sounds.
309 #define ComputeAmbientGains(b, g, o) do { \
310 if((b).CoeffCount > 0) \
311 ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o); \
312 else \
313 ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
314 } while (0)
315 void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
316 void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
319 * ComputePanningGains
321 * Computes panning gains using the given channel decoder coefficients and the
322 * pre-calculated direction or angle coefficients.
324 #define ComputePanningGains(b, c, g, o) do { \
325 if((b).CoeffCount > 0) \
326 ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\
327 else \
328 ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
329 } while (0)
330 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALuint numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
331 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
334 * ComputeFirstOrderGains
336 * Sets channel gains for a first-order ambisonics input channel. The matrix is
337 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
338 * orient the sound samples.
340 #define ComputeFirstOrderGains(b, m, g, o) do { \
341 if((b).CoeffCount > 0) \
342 ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o); \
343 else \
344 ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
345 } while (0)
346 void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
347 void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
350 ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo);
352 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
353 /* Caller must lock the device. */
354 ALvoid aluHandleDisconnect(ALCdevice *device);
356 extern ALfloat ConeScale;
357 extern ALfloat ZScale;
359 #ifdef __cplusplus
361 #endif
363 #endif