Find a valid source buffer before updating the voice
[openal-soft.git] / OpenAL32 / Include / alu.h
blobc20c64042f366014a0c41448991dd1125f6a1ee5
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 ALvoice;
38 struct ALeffectslot;
39 struct ALbuffer;
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 enum HrtfRequestMode {
283 Hrtf_Default = 0,
284 Hrtf_Enable = 1,
285 Hrtf_Disable = 2,
289 void aluInitMixer(void);
291 /* aluInitRenderer
293 * Set up the appropriate panning method and mixing method given the device
294 * properties.
296 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
298 void aluInitEffectPanning(struct ALeffectslot *slot);
301 * CalcDirectionCoeffs
303 * Calculates ambisonic coefficients based on a direction vector. The vector
304 * must be normalized (unit length), and the spread is the angular width of the
305 * sound (0...tau).
307 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
310 * CalcXYZCoeffs
312 * Same as CalcDirectionCoeffs except the direction is specified as separate x,
313 * y, and z parameters instead of an array.
315 inline void CalcXYZCoeffs(ALfloat x, ALfloat y, ALfloat z, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
317 ALfloat dir[3] = { x, y, z };
318 CalcDirectionCoeffs(dir, spread, coeffs);
322 * CalcAngleCoeffs
324 * Calculates ambisonic coefficients based on azimuth and elevation. The
325 * azimuth and elevation parameters are in radians, going right and up
326 * respectively.
328 void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
331 * ComputeAmbientGains
333 * Computes channel gains for ambient, omni-directional sounds.
335 #define ComputeAmbientGains(b, g, o) do { \
336 if((b).CoeffCount > 0) \
337 ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o); \
338 else \
339 ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
340 } while (0)
341 void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
342 void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
345 * ComputePanningGains
347 * Computes panning gains using the given channel decoder coefficients and the
348 * pre-calculated direction or angle coefficients.
350 #define ComputePanningGains(b, c, g, o) do { \
351 if((b).CoeffCount > 0) \
352 ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\
353 else \
354 ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
355 } while (0)
356 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALuint numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
357 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
360 * ComputeFirstOrderGains
362 * Sets channel gains for a first-order ambisonics input channel. The matrix is
363 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
364 * orient the sound samples.
366 #define ComputeFirstOrderGains(b, m, g, o) do { \
367 if((b).CoeffCount > 0) \
368 ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o); \
369 else \
370 ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
371 } while (0)
372 void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
373 void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
376 ALvoid UpdateContextSources(ALCcontext *context);
378 ALvoid CalcSourceParams(struct ALvoice *voice, const struct ALsource *source, const struct ALbuffer *buffer, const ALCcontext *ALContext);
379 ALvoid CalcNonAttnSourceParams(struct ALvoice *voice, const struct ALsource *source, const struct ALbuffer *buffer, const ALCcontext *ALContext);
381 ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo);
383 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
384 /* Caller must lock the device. */
385 ALvoid aluHandleDisconnect(ALCdevice *device);
387 extern ALfloat ConeScale;
388 extern ALfloat ZScale;
390 #ifdef __cplusplus
392 #endif
394 #endif