Make some pointer-to-array parameters const
[openal-soft.git] / OpenAL32 / Include / alu.h
blob3ced96289e7e50b079be333cfa2b97db17046c37
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 MixGains {
114 ALfloat Current;
115 ALfloat Step;
116 ALfloat Target;
117 } MixGains;
119 typedef struct MixHrtfParams {
120 const HrtfParams *Target;
121 HrtfParams *Current;
122 struct {
123 alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
124 ALint Delay[2];
125 } Steps;
126 } MixHrtfParams;
128 typedef struct DirectParams {
129 enum ActiveFilters FilterType;
130 ALfilterState LowPass;
131 ALfilterState HighPass;
133 struct {
134 HrtfParams Current;
135 HrtfParams Target;
136 HrtfState State;
137 } Hrtf;
139 struct {
140 ALfloat Current[MAX_OUTPUT_CHANNELS];
141 ALfloat Target[MAX_OUTPUT_CHANNELS];
142 } Gains;
143 } DirectParams;
145 typedef struct SendParams {
146 enum ActiveFilters FilterType;
147 ALfilterState LowPass;
148 ALfilterState HighPass;
150 struct {
151 ALfloat Current[MAX_OUTPUT_CHANNELS];
152 ALfloat Target[MAX_OUTPUT_CHANNELS];
153 } Gains;
154 } SendParams;
157 typedef const ALfloat* (*ResamplerFunc)(const BsincState *state,
158 const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen
161 typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
162 ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
163 ALuint Counter, ALuint OutPos, ALuint BufferSize);
164 typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
165 const ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans,
166 ALuint InPos, ALuint BufferSize);
167 typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx,
168 const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos,
169 const ALuint IrSize, const MixHrtfParams *hrtfparams,
170 HrtfState *hrtfstate, ALuint BufferSize);
171 typedef void (*HrtfDirectMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE],
172 ALuint lidx, ALuint ridx, const ALfloat *data, ALuint Offset,
173 const ALuint IrSize, ALfloat (*restrict Coeffs)[2],
174 ALfloat (*restrict Values)[2], ALuint BufferSize);
177 #define GAIN_MIX_MAX (16.0f) /* +24dB */
179 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
181 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
182 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
184 #define FRACTIONBITS (12)
185 #define FRACTIONONE (1<<FRACTIONBITS)
186 #define FRACTIONMASK (FRACTIONONE-1)
189 inline ALfloat minf(ALfloat a, ALfloat b)
190 { return ((a > b) ? b : a); }
191 inline ALfloat maxf(ALfloat a, ALfloat b)
192 { return ((a > b) ? a : b); }
193 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
194 { return minf(max, maxf(min, val)); }
196 inline ALdouble mind(ALdouble a, ALdouble b)
197 { return ((a > b) ? b : a); }
198 inline ALdouble maxd(ALdouble a, ALdouble b)
199 { return ((a > b) ? a : b); }
200 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
201 { return mind(max, maxd(min, val)); }
203 inline ALuint minu(ALuint a, ALuint b)
204 { return ((a > b) ? b : a); }
205 inline ALuint maxu(ALuint a, ALuint b)
206 { return ((a > b) ? a : b); }
207 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
208 { return minu(max, maxu(min, val)); }
210 inline ALint mini(ALint a, ALint b)
211 { return ((a > b) ? b : a); }
212 inline ALint maxi(ALint a, ALint b)
213 { return ((a > b) ? a : b); }
214 inline ALint clampi(ALint val, ALint min, ALint max)
215 { return mini(max, maxi(min, val)); }
217 inline ALint64 mini64(ALint64 a, ALint64 b)
218 { return ((a > b) ? b : a); }
219 inline ALint64 maxi64(ALint64 a, ALint64 b)
220 { return ((a > b) ? a : b); }
221 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
222 { return mini64(max, maxi64(min, val)); }
224 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
225 { return ((a > b) ? b : a); }
226 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
227 { return ((a > b) ? a : b); }
228 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
229 { return minu64(max, maxu64(min, val)); }
232 union ResamplerCoeffs {
233 ALfloat FIR4[FRACTIONONE][4];
234 ALfloat FIR8[FRACTIONONE][8];
236 extern alignas(16) union ResamplerCoeffs ResampleCoeffs;
238 extern alignas(16) const ALfloat bsincTab[18840];
241 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
243 return val1 + (val2-val1)*mu;
245 inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac)
247 const ALfloat *k = ResampleCoeffs.FIR4[frac];
248 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3;
250 inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint frac)
252 const ALfloat *k = ResampleCoeffs.FIR8[frac];
253 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3 +
254 k[4]*val4 + k[5]*val5 + k[6]*val6 + k[7]*val7;
258 enum HrtfRequestMode {
259 Hrtf_Default = 0,
260 Hrtf_Enable = 1,
261 Hrtf_Disable = 2,
265 void aluInitMixer(void);
267 MixerFunc SelectMixer(void);
268 RowMixerFunc SelectRowMixer(void);
270 /* aluInitRenderer
272 * Set up the appropriate panning method and mixing method given the device
273 * properties.
275 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
277 void aluInitEffectPanning(struct ALeffectslot *slot);
280 * CalcDirectionCoeffs
282 * Calculates ambisonic coefficients based on a direction vector. The vector
283 * must be normalized (unit length), and the spread is the angular width of the
284 * sound (0...tau).
286 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
289 * CalcXYZCoeffs
291 * Same as CalcDirectionCoeffs except the direction is specified as separate x,
292 * y, and z parameters instead of an array.
294 inline void CalcXYZCoeffs(ALfloat x, ALfloat y, ALfloat z, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
296 ALfloat dir[3] = { x, y, z };
297 CalcDirectionCoeffs(dir, spread, coeffs);
301 * CalcAngleCoeffs
303 * Calculates ambisonic coefficients based on azimuth and elevation. The
304 * azimuth and elevation parameters are in radians, going right and up
305 * respectively.
307 void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
310 * ComputeAmbientGains
312 * Computes channel gains for ambient, omni-directional sounds.
314 #define ComputeAmbientGains(b, g, o) do { \
315 if((b).CoeffCount > 0) \
316 ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o); \
317 else \
318 ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
319 } while (0)
320 void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
321 void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
324 * ComputePanningGains
326 * Computes panning gains using the given channel decoder coefficients and the
327 * pre-calculated direction or angle coefficients.
329 #define ComputePanningGains(b, c, g, o) do { \
330 if((b).CoeffCount > 0) \
331 ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\
332 else \
333 ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
334 } while (0)
335 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALuint numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
336 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
339 * ComputeFirstOrderGains
341 * Sets channel gains for a first-order ambisonics input channel. The matrix is
342 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
343 * orient the sound samples.
345 #define ComputeFirstOrderGains(b, m, g, o) do { \
346 if((b).CoeffCount > 0) \
347 ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o); \
348 else \
349 ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
350 } while (0)
351 void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
352 void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
355 ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo);
357 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
358 /* Caller must lock the device. */
359 ALvoid aluHandleDisconnect(ALCdevice *device);
361 extern ALfloat ConeScale;
362 extern ALfloat ZScale;
364 #ifdef __cplusplus
366 #endif
368 #endif