Add a dual-band ambisonic decoder
[openal-soft.git] / OpenAL32 / Include / alu.h
blobdfc9284fd868fd936926bd7b852d54849cb2522b
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 AmbDecConf;
37 struct ALsource;
38 struct ALvoice;
39 struct ALeffectslot;
42 /* The number of distinct scale and phase intervals within the filter table. */
43 #define BSINC_SCALE_BITS 4
44 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
45 #define BSINC_PHASE_BITS 4
46 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
48 /* Interpolator state. Kind of a misnomer since the interpolator itself is
49 * stateless. This just keeps it from having to recompute scale-related
50 * mappings for every sample.
52 typedef struct BsincState {
53 ALfloat sf; /* Scale interpolation factor. */
54 ALuint m; /* Coefficient count. */
55 ALint l; /* Left coefficient offset. */
56 struct {
57 const ALfloat *filter; /* Filter coefficients. */
58 const ALfloat *scDelta; /* Scale deltas. */
59 const ALfloat *phDelta; /* Phase deltas. */
60 const ALfloat *spDelta; /* Scale-phase deltas. */
61 } coeffs[BSINC_PHASE_COUNT];
62 } BsincState;
65 typedef union aluVector {
66 alignas(16) ALfloat v[4];
67 } aluVector;
69 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
71 vector->v[0] = x;
72 vector->v[1] = y;
73 vector->v[2] = z;
74 vector->v[3] = w;
78 typedef union aluMatrixf {
79 alignas(16) ALfloat m[4][4];
80 } aluMatrixf;
82 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
83 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
85 matrix->m[row][0] = m0;
86 matrix->m[row][1] = m1;
87 matrix->m[row][2] = m2;
88 matrix->m[row][3] = m3;
91 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
92 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
93 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
94 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
96 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
97 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
98 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
99 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
103 typedef union aluMatrixd {
104 alignas(16) ALdouble m[4][4];
105 } aluMatrixd;
107 inline void aluMatrixdSetRow(aluMatrixd *matrix, ALuint row,
108 ALdouble m0, ALdouble m1, ALdouble m2, ALdouble m3)
110 matrix->m[row][0] = m0;
111 matrix->m[row][1] = m1;
112 matrix->m[row][2] = m2;
113 matrix->m[row][3] = m3;
116 inline void aluMatrixdSet(aluMatrixd *matrix, ALdouble m00, ALdouble m01, ALdouble m02, ALdouble m03,
117 ALdouble m10, ALdouble m11, ALdouble m12, ALdouble m13,
118 ALdouble m20, ALdouble m21, ALdouble m22, ALdouble m23,
119 ALdouble m30, ALdouble m31, ALdouble m32, ALdouble m33)
121 aluMatrixdSetRow(matrix, 0, m00, m01, m02, m03);
122 aluMatrixdSetRow(matrix, 1, m10, m11, m12, m13);
123 aluMatrixdSetRow(matrix, 2, m20, m21, m22, m23);
124 aluMatrixdSetRow(matrix, 3, m30, m31, m32, m33);
128 enum ActiveFilters {
129 AF_None = 0,
130 AF_LowPass = 1,
131 AF_HighPass = 2,
132 AF_BandPass = AF_LowPass | AF_HighPass
136 typedef struct MixGains {
137 ALfloat Current;
138 ALfloat Step;
139 ALfloat Target;
140 } MixGains;
142 typedef struct MixHrtfParams {
143 const HrtfParams *Target;
144 HrtfParams *Current;
145 struct {
146 alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
147 ALint Delay[2];
148 } Steps;
149 } MixHrtfParams;
151 typedef struct DirectParams {
152 ALfloat (*OutBuffer)[BUFFERSIZE];
153 ALuint OutChannels;
155 struct {
156 enum ActiveFilters ActiveType;
157 ALfilterState LowPass;
158 ALfilterState HighPass;
159 } Filters[MAX_INPUT_CHANNELS];
161 struct {
162 HrtfParams Current;
163 HrtfParams Target;
164 HrtfState State;
165 } Hrtf[MAX_INPUT_CHANNELS];
167 struct {
168 ALfloat Current[MAX_OUTPUT_CHANNELS];
169 ALfloat Target[MAX_OUTPUT_CHANNELS];
170 } Gains[MAX_INPUT_CHANNELS];
171 } DirectParams;
173 typedef struct SendParams {
174 ALfloat (*OutBuffer)[BUFFERSIZE];
175 ALuint OutChannels;
177 struct {
178 enum ActiveFilters ActiveType;
179 ALfilterState LowPass;
180 ALfilterState HighPass;
181 } Filters[MAX_INPUT_CHANNELS];
183 struct {
184 ALfloat Current[MAX_OUTPUT_CHANNELS];
185 ALfloat Target[MAX_OUTPUT_CHANNELS];
186 } Gains[MAX_INPUT_CHANNELS];
187 } SendParams;
190 typedef const ALfloat* (*ResamplerFunc)(const BsincState *state,
191 const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen
194 typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
195 ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
196 ALuint Counter, ALuint OutPos, ALuint BufferSize);
197 typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx,
198 const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos,
199 const ALuint IrSize, const MixHrtfParams *hrtfparams,
200 HrtfState *hrtfstate, ALuint BufferSize);
203 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
205 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
206 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
208 #define FRACTIONBITS (12)
209 #define FRACTIONONE (1<<FRACTIONBITS)
210 #define FRACTIONMASK (FRACTIONONE-1)
213 inline ALfloat minf(ALfloat a, ALfloat b)
214 { return ((a > b) ? b : a); }
215 inline ALfloat maxf(ALfloat a, ALfloat b)
216 { return ((a > b) ? a : b); }
217 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
218 { return minf(max, maxf(min, val)); }
220 inline ALdouble mind(ALdouble a, ALdouble b)
221 { return ((a > b) ? b : a); }
222 inline ALdouble maxd(ALdouble a, ALdouble b)
223 { return ((a > b) ? a : b); }
224 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
225 { return mind(max, maxd(min, val)); }
227 inline ALuint minu(ALuint a, ALuint b)
228 { return ((a > b) ? b : a); }
229 inline ALuint maxu(ALuint a, ALuint b)
230 { return ((a > b) ? a : b); }
231 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
232 { return minu(max, maxu(min, val)); }
234 inline ALint mini(ALint a, ALint b)
235 { return ((a > b) ? b : a); }
236 inline ALint maxi(ALint a, ALint b)
237 { return ((a > b) ? a : b); }
238 inline ALint clampi(ALint val, ALint min, ALint max)
239 { return mini(max, maxi(min, val)); }
241 inline ALint64 mini64(ALint64 a, ALint64 b)
242 { return ((a > b) ? b : a); }
243 inline ALint64 maxi64(ALint64 a, ALint64 b)
244 { return ((a > b) ? a : b); }
245 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
246 { return mini64(max, maxi64(min, val)); }
248 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
249 { return ((a > b) ? b : a); }
250 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
251 { return ((a > b) ? a : b); }
252 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
253 { return minu64(max, maxu64(min, val)); }
256 union ResamplerCoeffs {
257 ALfloat FIR4[FRACTIONONE][4];
258 ALfloat FIR8[FRACTIONONE][8];
260 extern alignas(16) union ResamplerCoeffs ResampleCoeffs;
262 extern alignas(16) const ALfloat bsincTab[18840];
265 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
267 return val1 + (val2-val1)*mu;
269 inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac)
271 const ALfloat *k = ResampleCoeffs.FIR4[frac];
272 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3;
274 inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint frac)
276 const ALfloat *k = ResampleCoeffs.FIR8[frac];
277 return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3 +
278 k[4]*val4 + k[5]*val5 + k[6]*val6 + k[7]*val7;
282 void aluInitMixer(void);
284 ALvoid aluInitPanning(ALCdevice *Device, const struct AmbDecConf *conf);
286 void aluInitEffectPanning(struct ALeffectslot *slot);
289 * CalcDirectionCoeffs
291 * Calculates ambisonic coefficients based on a direction vector. The vector
292 * must not be longer than 1 unit.
294 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat coeffs[MAX_AMBI_COEFFS]);
297 * CalcXYZCoeffs
299 * Same as CalcDirectionCoeffs except the direction is specified as separate x,
300 * y, and z parameters instead of an array.
302 inline void CalcXYZCoeffs(ALfloat x, ALfloat y, ALfloat z, ALfloat coeffs[MAX_AMBI_COEFFS])
304 ALfloat dir[3] = { x, y, z };
305 CalcDirectionCoeffs(dir, coeffs);
309 * CalcAngleCoeffs
311 * Calculates ambisonic coefficients based on angle and elevation. The angle
312 * and elevation parameters are in radians, going right and up respectively.
314 void CalcAngleCoeffs(ALfloat angle, ALfloat elevation, ALfloat coeffs[MAX_AMBI_COEFFS]);
317 * ComputeAmbientGains
319 * Computes channel gains for ambient, omni-directional sounds.
321 void ComputeAmbientGains(const ChannelConfig *chancoeffs, 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 void ComputePanningGains(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
332 * ComputeFirstOrderGains
334 * Sets channel gains for a first-order ambisonics input channel. The matrix is
335 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
336 * orient the sound samples.
338 void ComputeFirstOrderGains(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
341 ALvoid UpdateContextSources(ALCcontext *context);
343 ALvoid CalcSourceParams(struct ALvoice *voice, const struct ALsource *source, const ALCcontext *ALContext);
344 ALvoid CalcNonAttnSourceParams(struct ALvoice *voice, const struct ALsource *source, const ALCcontext *ALContext);
346 ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo);
348 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
349 /* Caller must lock the device. */
350 ALvoid aluHandleDisconnect(ALCdevice *device);
352 extern ALfloat ConeScale;
353 extern ALfloat ZScale;
355 #ifdef __cplusplus
357 #endif
359 #endif