Alter how panpot/pair-wise panning works
[openal-soft.git] / OpenAL32 / Include / alu.h
blob402c3181ca486b1d222c82fb2a1e2c3aff1df48b
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;
65 typedef union InterpState {
66 BsincState bsinc;
67 } InterpState;
70 typedef union aluVector {
71 alignas(16) ALfloat v[4];
72 } aluVector;
74 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
76 vector->v[0] = x;
77 vector->v[1] = y;
78 vector->v[2] = z;
79 vector->v[3] = w;
83 typedef union aluMatrixf {
84 alignas(16) ALfloat m[4][4];
85 } aluMatrixf;
86 extern const aluMatrixf IdentityMatrixf;
88 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
89 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
91 matrix->m[row][0] = m0;
92 matrix->m[row][1] = m1;
93 matrix->m[row][2] = m2;
94 matrix->m[row][3] = m3;
97 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
98 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
99 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
100 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
102 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
103 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
104 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
105 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
109 enum ActiveFilters {
110 AF_None = 0,
111 AF_LowPass = 1,
112 AF_HighPass = 2,
113 AF_BandPass = AF_LowPass | AF_HighPass
117 typedef struct MixHrtfParams {
118 const HrtfParams *Target;
119 HrtfParams *Current;
120 struct {
121 alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
122 ALsizei Delay[2];
123 } Steps;
124 } MixHrtfParams;
126 typedef struct DirectParams {
127 enum ActiveFilters FilterType;
128 ALfilterState LowPass;
129 ALfilterState HighPass;
131 struct {
132 HrtfParams Current;
133 HrtfParams Target;
134 HrtfState State;
135 } Hrtf;
137 struct {
138 ALfloat Current[MAX_OUTPUT_CHANNELS];
139 ALfloat Target[MAX_OUTPUT_CHANNELS];
140 } Gains;
141 } DirectParams;
143 typedef struct SendParams {
144 enum ActiveFilters FilterType;
145 ALfilterState LowPass;
146 ALfilterState HighPass;
148 struct {
149 ALfloat Current[MAX_OUTPUT_CHANNELS];
150 ALfloat Target[MAX_OUTPUT_CHANNELS];
151 } Gains;
152 } SendParams;
155 typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
156 const ALfloat *restrict src, ALuint frac, ALint increment,
157 ALfloat *restrict dst, ALsizei dstlen
160 typedef void (*MixerFunc)(const ALfloat *data, ALsizei OutChans,
161 ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
162 const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
163 ALsizei BufferSize);
164 typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
165 const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
166 ALsizei InPos, ALsizei BufferSize);
167 typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
168 const ALfloat *data, ALsizei Counter, ALsizei Offset, ALsizei OutPos,
169 const ALsizei IrSize, const MixHrtfParams *hrtfparams,
170 HrtfState *hrtfstate, ALsizei BufferSize);
171 typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
172 const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
173 ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2],
174 ALsizei 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 extern alignas(16) ALfloat ResampleCoeffs_FIR4[FRACTIONONE][4];
234 extern alignas(16) const ALfloat bsincTab[18840];
237 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
239 return val1 + (val2-val1)*mu;
241 inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac)
243 const ALfloat *k = ResampleCoeffs_FIR4[frac];
244 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3;
248 enum HrtfRequestMode {
249 Hrtf_Default = 0,
250 Hrtf_Enable = 1,
251 Hrtf_Disable = 2,
255 void aluInitMixer(void);
257 MixerFunc SelectMixer(void);
258 RowMixerFunc SelectRowMixer(void);
260 /* aluInitRenderer
262 * Set up the appropriate panning method and mixing method given the device
263 * properties.
265 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
267 void aluInitEffectPanning(struct ALeffectslot *slot);
270 * CalcDirectionCoeffs
272 * Calculates ambisonic coefficients based on a direction vector. The vector
273 * must be normalized (unit length), and the spread is the angular width of the
274 * sound (0...tau).
276 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
279 * CalcXYZCoeffs
281 * Same as CalcDirectionCoeffs except the direction is specified as separate x,
282 * y, and z parameters instead of an array.
284 inline void CalcXYZCoeffs(ALfloat x, ALfloat y, ALfloat z, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
286 ALfloat dir[3] = { x, y, z };
287 CalcDirectionCoeffs(dir, spread, coeffs);
291 * CalcAngleCoeffs
293 * Calculates ambisonic coefficients based on azimuth and elevation. The
294 * azimuth and elevation parameters are in radians, going right and up
295 * respectively.
297 void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
300 * CalcAnglePairwiseCoeffs
302 * Calculates ambisonic coefficients based on azimuth and elevation. The
303 * azimuth and elevation parameters are in radians, going right and up
304 * respectively. This pairwise variant warps the result such that +30 azimuth
305 * is full right, and -30 azimuth is full left.
307 void CalcAnglePairwiseCoeffs(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, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
321 void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALsizei 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, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
336 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei 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, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
352 void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
355 void MixSource(struct ALvoice *voice, struct ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo);
357 void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
358 /* Caller must lock the device. */
359 void aluHandleDisconnect(ALCdevice *device);
361 extern ALfloat ConeScale;
362 extern ALfloat ZScale;
364 #ifdef __cplusplus
366 #endif
368 #endif