Use a macro to specify the ambisonic periphonic channel mask
[openal-soft.git] / OpenAL32 / Include / alu.h
blobfca60b158f15e57a47023a692a80b9c672b97c34
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 enum ActiveFilters {
105 AF_None = 0,
106 AF_LowPass = 1,
107 AF_HighPass = 2,
108 AF_BandPass = AF_LowPass | AF_HighPass
112 typedef struct MixGains {
113 ALfloat Current;
114 ALfloat Step;
115 ALfloat Target;
116 } MixGains;
118 typedef struct MixHrtfParams {
119 const HrtfParams *Target;
120 HrtfParams *Current;
121 struct {
122 alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
123 ALint Delay[2];
124 } Steps;
125 } MixHrtfParams;
127 typedef struct DirectParams {
128 ALfloat (*OutBuffer)[BUFFERSIZE];
129 ALuint OutChannels;
131 struct {
132 enum ActiveFilters ActiveType;
133 ALfilterState LowPass;
134 ALfilterState HighPass;
135 } Filters[MAX_INPUT_CHANNELS];
137 struct {
138 HrtfParams Current;
139 HrtfParams Target;
140 HrtfState State;
141 } Hrtf[MAX_INPUT_CHANNELS];
143 struct {
144 ALfloat Current[MAX_OUTPUT_CHANNELS];
145 ALfloat Target[MAX_OUTPUT_CHANNELS];
146 } Gains[MAX_INPUT_CHANNELS];
147 } DirectParams;
149 typedef struct SendParams {
150 ALfloat (*OutBuffer)[BUFFERSIZE];
151 ALuint OutChannels;
153 struct {
154 enum ActiveFilters ActiveType;
155 ALfilterState LowPass;
156 ALfilterState HighPass;
157 } Filters[MAX_INPUT_CHANNELS];
159 struct {
160 ALfloat Current[MAX_OUTPUT_CHANNELS];
161 ALfloat Target[MAX_OUTPUT_CHANNELS];
162 } Gains[MAX_INPUT_CHANNELS];
163 } SendParams;
166 typedef const ALfloat* (*ResamplerFunc)(const BsincState *state,
167 const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen
170 typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
171 ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
172 ALuint Counter, ALuint OutPos, ALuint BufferSize);
173 typedef void (*MatrixMixerFunc)(ALfloat *OutBuffer, const ALfloat *Mtx,
174 ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans,
175 ALuint BufferSize);
176 typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx,
177 const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos,
178 const ALuint IrSize, const MixHrtfParams *hrtfparams,
179 HrtfState *hrtfstate, ALuint BufferSize);
182 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
184 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
185 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
187 #define FRACTIONBITS (12)
188 #define FRACTIONONE (1<<FRACTIONBITS)
189 #define FRACTIONMASK (FRACTIONONE-1)
192 inline ALfloat minf(ALfloat a, ALfloat b)
193 { return ((a > b) ? b : a); }
194 inline ALfloat maxf(ALfloat a, ALfloat b)
195 { return ((a > b) ? a : b); }
196 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
197 { return minf(max, maxf(min, val)); }
199 inline ALdouble mind(ALdouble a, ALdouble b)
200 { return ((a > b) ? b : a); }
201 inline ALdouble maxd(ALdouble a, ALdouble b)
202 { return ((a > b) ? a : b); }
203 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
204 { return mind(max, maxd(min, val)); }
206 inline ALuint minu(ALuint a, ALuint b)
207 { return ((a > b) ? b : a); }
208 inline ALuint maxu(ALuint a, ALuint b)
209 { return ((a > b) ? a : b); }
210 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
211 { return minu(max, maxu(min, val)); }
213 inline ALint mini(ALint a, ALint b)
214 { return ((a > b) ? b : a); }
215 inline ALint maxi(ALint a, ALint b)
216 { return ((a > b) ? a : b); }
217 inline ALint clampi(ALint val, ALint min, ALint max)
218 { return mini(max, maxi(min, val)); }
220 inline ALint64 mini64(ALint64 a, ALint64 b)
221 { return ((a > b) ? b : a); }
222 inline ALint64 maxi64(ALint64 a, ALint64 b)
223 { return ((a > b) ? a : b); }
224 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
225 { return mini64(max, maxi64(min, val)); }
227 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
228 { return ((a > b) ? b : a); }
229 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
230 { return ((a > b) ? a : b); }
231 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
232 { return minu64(max, maxu64(min, val)); }
235 union ResamplerCoeffs {
236 ALfloat FIR4[FRACTIONONE][4];
237 ALfloat FIR8[FRACTIONONE][8];
239 extern alignas(16) union ResamplerCoeffs ResampleCoeffs;
241 extern alignas(16) const ALfloat bsincTab[18840];
244 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
246 return val1 + (val2-val1)*mu;
248 inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac)
250 const ALfloat *k = ResampleCoeffs.FIR4[frac];
251 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3;
253 inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint frac)
255 const ALfloat *k = ResampleCoeffs.FIR8[frac];
256 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3 +
257 k[4]*val4 + k[5]*val5 + k[6]*val6 + k[7]*val7;
261 enum HrtfRequestMode {
262 Hrtf_Default = 0,
263 Hrtf_Enable = 1,
264 Hrtf_Disable = 2,
268 void aluInitMixer(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