Avoid re-selecting the direct HRTF mix function
[openal-soft.git] / OpenAL32 / Include / alu.h
blobb62bb024864e93041c14c814ee20066ed183682b
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 "nfcfilter.h"
21 #include "math_defs.h"
24 #define MAX_PITCH (255)
26 /* Maximum number of buffer samples before the current pos needed for resampling. */
27 #define MAX_PRE_SAMPLES 12
29 /* Maximum number of buffer samples after the current pos needed for resampling. */
30 #define MAX_POST_SAMPLES 12
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
37 struct ALsource;
38 struct ALbufferlistitem;
39 struct ALvoice;
40 struct ALeffectslot;
43 #define DITHER_RNG_SEED 22222
46 enum SpatializeMode {
47 SpatializeOff = AL_FALSE,
48 SpatializeOn = AL_TRUE,
49 SpatializeAuto = AL_AUTO_SOFT
52 enum Resampler {
53 PointResampler,
54 LinearResampler,
55 FIR4Resampler,
56 BSincResampler,
58 ResamplerMax = BSincResampler
60 extern enum Resampler ResamplerDefault;
62 /* The number of distinct scale and phase intervals within the filter table. */
63 #define BSINC_SCALE_BITS 4
64 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
65 #define BSINC_PHASE_BITS 4
66 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
68 /* Interpolator state. Kind of a misnomer since the interpolator itself is
69 * stateless. This just keeps it from having to recompute scale-related
70 * mappings for every sample.
72 typedef struct BsincState {
73 ALfloat sf; /* Scale interpolation factor. */
74 ALuint m; /* Coefficient count. */
75 ALint l; /* Left coefficient offset. */
76 struct {
77 const ALfloat *filter; /* Filter coefficients. */
78 const ALfloat *scDelta; /* Scale deltas. */
79 const ALfloat *phDelta; /* Phase deltas. */
80 const ALfloat *spDelta; /* Scale-phase deltas. */
81 } coeffs[BSINC_PHASE_COUNT];
82 } BsincState;
84 typedef union InterpState {
85 BsincState bsinc;
86 } InterpState;
88 ALboolean BsincPrepare(const ALuint increment, BsincState *state);
90 typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
91 const ALfloat *restrict src, ALsizei frac, ALint increment,
92 ALfloat *restrict dst, ALsizei dstlen
96 typedef union aluVector {
97 alignas(16) ALfloat v[4];
98 } aluVector;
100 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
102 vector->v[0] = x;
103 vector->v[1] = y;
104 vector->v[2] = z;
105 vector->v[3] = w;
109 typedef union aluMatrixf {
110 alignas(16) ALfloat m[4][4];
111 } aluMatrixf;
112 extern const aluMatrixf IdentityMatrixf;
114 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
115 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
117 matrix->m[row][0] = m0;
118 matrix->m[row][1] = m1;
119 matrix->m[row][2] = m2;
120 matrix->m[row][3] = m3;
123 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
124 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
125 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
126 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
128 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
129 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
130 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
131 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
135 enum ActiveFilters {
136 AF_None = 0,
137 AF_LowPass = 1,
138 AF_HighPass = 2,
139 AF_BandPass = AF_LowPass | AF_HighPass
143 typedef struct MixHrtfParams {
144 const ALfloat (*Coeffs)[2];
145 ALsizei Delay[2];
146 ALfloat Gain;
147 ALfloat GainStep;
148 } MixHrtfParams;
151 typedef struct DirectParams {
152 ALfilterState LowPass;
153 ALfilterState HighPass;
155 NfcFilter NFCtrlFilter[MAX_AMBI_ORDER];
157 struct {
158 HrtfParams Old;
159 HrtfParams Target;
160 HrtfState State;
161 } Hrtf;
163 struct {
164 ALfloat Current[MAX_OUTPUT_CHANNELS];
165 ALfloat Target[MAX_OUTPUT_CHANNELS];
166 } Gains;
167 } DirectParams;
169 typedef struct SendParams {
170 ALfilterState LowPass;
171 ALfilterState HighPass;
173 struct {
174 ALfloat Current[MAX_OUTPUT_CHANNELS];
175 ALfloat Target[MAX_OUTPUT_CHANNELS];
176 } Gains;
177 } SendParams;
180 struct ALvoiceProps {
181 ATOMIC(struct ALvoiceProps*) next;
183 ALfloat Pitch;
184 ALfloat Gain;
185 ALfloat OuterGain;
186 ALfloat MinGain;
187 ALfloat MaxGain;
188 ALfloat InnerAngle;
189 ALfloat OuterAngle;
190 ALfloat RefDistance;
191 ALfloat MaxDistance;
192 ALfloat RolloffFactor;
193 ALfloat Position[3];
194 ALfloat Velocity[3];
195 ALfloat Direction[3];
196 ALfloat Orientation[2][3];
197 ALboolean HeadRelative;
198 enum DistanceModel DistanceModel;
199 enum Resampler Resampler;
200 ALboolean DirectChannels;
201 enum SpatializeMode SpatializeMode;
203 ALboolean DryGainHFAuto;
204 ALboolean WetGainAuto;
205 ALboolean WetGainHFAuto;
206 ALfloat OuterGainHF;
208 ALfloat AirAbsorptionFactor;
209 ALfloat RoomRolloffFactor;
210 ALfloat DopplerFactor;
212 ALfloat StereoPan[2];
214 ALfloat Radius;
216 /** Direct filter and auxiliary send info. */
217 struct {
218 ALfloat Gain;
219 ALfloat GainHF;
220 ALfloat HFReference;
221 ALfloat GainLF;
222 ALfloat LFReference;
223 } Direct;
224 struct {
225 struct ALeffectslot *Slot;
226 ALfloat Gain;
227 ALfloat GainHF;
228 ALfloat HFReference;
229 ALfloat GainLF;
230 ALfloat LFReference;
231 } Send[];
234 /* If not 'fading', gain targets are used directly without fading. */
235 #define VOICE_IS_FADING (1<<0)
236 #define VOICE_HAS_HRTF (1<<1)
237 #define VOICE_HAS_NFC (1<<2)
239 typedef struct ALvoice {
240 struct ALvoiceProps *Props;
242 ATOMIC(struct ALvoiceProps*) Update;
243 ATOMIC(struct ALvoiceProps*) FreeList;
245 ATOMIC(struct ALsource*) Source;
246 ATOMIC(bool) Playing;
249 * Source offset in samples, relative to the currently playing buffer, NOT
250 * the whole queue, and the fractional (fixed-point) offset to the next
251 * sample.
253 ATOMIC(ALuint) position;
254 ATOMIC(ALsizei) position_fraction;
256 /* Current buffer queue item being played. */
257 ATOMIC(struct ALbufferlistitem*) current_buffer;
259 /* Buffer queue item to loop to at end of queue (will be NULL for non-
260 * looping voices).
262 ATOMIC(struct ALbufferlistitem*) loop_buffer;
265 * Number of channels and bytes-per-sample for the attached source's
266 * buffer(s).
268 ALsizei NumChannels;
269 ALsizei SampleSize;
271 /** Current target parameters used for mixing. */
272 ALint Step;
274 ResamplerFunc Resampler;
276 ALuint Flags;
278 ALuint Offset; /* Number of output samples mixed since starting. */
280 alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
282 InterpState ResampleState;
284 struct {
285 enum ActiveFilters FilterType;
286 DirectParams Params[MAX_INPUT_CHANNELS];
288 ALfloat (*Buffer)[BUFFERSIZE];
289 ALsizei Channels;
290 ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
291 } Direct;
293 struct {
294 enum ActiveFilters FilterType;
295 SendParams Params[MAX_INPUT_CHANNELS];
297 ALfloat (*Buffer)[BUFFERSIZE];
298 ALsizei Channels;
299 } Send[];
300 } ALvoice;
302 void DeinitVoice(ALvoice *voice);
305 typedef void (*MixerFunc)(const ALfloat *data, ALsizei OutChans,
306 ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
307 const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
308 ALsizei BufferSize);
309 typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
310 const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
311 ALsizei InPos, ALsizei BufferSize);
312 typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
313 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
314 const ALsizei IrSize, MixHrtfParams *hrtfparams,
315 HrtfState *hrtfstate, ALsizei BufferSize);
316 typedef void (*HrtfMixerBlendFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
317 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
318 const ALsizei IrSize, const HrtfParams *oldparams,
319 MixHrtfParams *newparams, HrtfState *hrtfstate,
320 ALsizei BufferSize);
321 typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
322 const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
323 const ALfloat (*restrict Coeffs)[2],
324 ALfloat (*restrict Values)[2], ALsizei BufferSize);
327 #define GAIN_MIX_MAX (16.0f) /* +24dB */
329 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
331 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
332 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
334 /* Target gain for the reverb decay feedback reaching the decay time. */
335 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
337 #define FRACTIONBITS (12)
338 #define FRACTIONONE (1<<FRACTIONBITS)
339 #define FRACTIONMASK (FRACTIONONE-1)
342 inline ALfloat minf(ALfloat a, ALfloat b)
343 { return ((a > b) ? b : a); }
344 inline ALfloat maxf(ALfloat a, ALfloat b)
345 { return ((a > b) ? a : b); }
346 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
347 { return minf(max, maxf(min, val)); }
349 inline ALdouble mind(ALdouble a, ALdouble b)
350 { return ((a > b) ? b : a); }
351 inline ALdouble maxd(ALdouble a, ALdouble b)
352 { return ((a > b) ? a : b); }
353 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
354 { return mind(max, maxd(min, val)); }
356 inline ALuint minu(ALuint a, ALuint b)
357 { return ((a > b) ? b : a); }
358 inline ALuint maxu(ALuint a, ALuint b)
359 { return ((a > b) ? a : b); }
360 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
361 { return minu(max, maxu(min, val)); }
363 inline ALint mini(ALint a, ALint b)
364 { return ((a > b) ? b : a); }
365 inline ALint maxi(ALint a, ALint b)
366 { return ((a > b) ? a : b); }
367 inline ALint clampi(ALint val, ALint min, ALint max)
368 { return mini(max, maxi(min, val)); }
370 inline ALint64 mini64(ALint64 a, ALint64 b)
371 { return ((a > b) ? b : a); }
372 inline ALint64 maxi64(ALint64 a, ALint64 b)
373 { return ((a > b) ? a : b); }
374 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
375 { return mini64(max, maxi64(min, val)); }
377 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
378 { return ((a > b) ? b : a); }
379 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
380 { return ((a > b) ? a : b); }
381 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
382 { return minu64(max, maxu64(min, val)); }
385 extern alignas(16) const ALfloat bsincTab[18840];
386 extern alignas(16) const ALfloat sinc4Tab[FRACTIONONE][4];
389 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
391 return val1 + (val2-val1)*mu;
393 inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALsizei frac)
395 return sinc4Tab[frac][0]*val0 + sinc4Tab[frac][1]*val1 +
396 sinc4Tab[frac][2]*val2 + sinc4Tab[frac][3]*val3;
400 enum HrtfRequestMode {
401 Hrtf_Default = 0,
402 Hrtf_Enable = 1,
403 Hrtf_Disable = 2,
406 void aluInit(void);
408 void aluInitMixer(void);
410 MixerFunc SelectMixer(void);
411 RowMixerFunc SelectRowMixer(void);
412 ResamplerFunc SelectResampler(enum Resampler resampler);
414 /* aluInitRenderer
416 * Set up the appropriate panning method and mixing method given the device
417 * properties.
419 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
421 void aluInitEffectPanning(struct ALeffectslot *slot);
424 * CalcDirectionCoeffs
426 * Calculates ambisonic coefficients based on a direction vector. The vector
427 * must be normalized (unit length), and the spread is the angular width of the
428 * sound (0...tau).
430 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
433 * CalcAngleCoeffs
435 * Calculates ambisonic coefficients based on azimuth and elevation. The
436 * azimuth and elevation parameters are in radians, going right and up
437 * respectively.
439 inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
441 ALfloat dir[3] = {
442 sinf(azimuth) * cosf(elevation),
443 sinf(elevation),
444 -cosf(azimuth) * cosf(elevation)
446 CalcDirectionCoeffs(dir, spread, coeffs);
450 * CalcAnglePairwiseCoeffs
452 * Calculates ambisonic coefficients based on azimuth and elevation. The
453 * azimuth and elevation parameters are in radians, going right and up
454 * respectively. This pairwise variant warps the result such that +30 azimuth
455 * is full right, and -30 azimuth is full left.
457 void CalcAnglePairwiseCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
460 * ComputeAmbientGains
462 * Computes channel gains for ambient, omni-directional sounds.
464 #define ComputeAmbientGains(b, g, o) do { \
465 if((b).CoeffCount > 0) \
466 ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o); \
467 else \
468 ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
469 } while (0)
470 void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
471 void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
474 * ComputePanningGains
476 * Computes panning gains using the given channel decoder coefficients and the
477 * pre-calculated direction or angle coefficients.
479 #define ComputePanningGains(b, c, g, o) do { \
480 if((b).CoeffCount > 0) \
481 ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\
482 else \
483 ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
484 } while (0)
485 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
486 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
489 * ComputeFirstOrderGains
491 * Sets channel gains for a first-order ambisonics input channel. The matrix is
492 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
493 * orient the sound samples.
495 #define ComputeFirstOrderGains(b, m, g, o) do { \
496 if((b).CoeffCount > 0) \
497 ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o); \
498 else \
499 ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
500 } while (0)
501 void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
502 void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
505 ALboolean MixSource(struct ALvoice *voice, struct ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo);
507 void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples);
508 /* Caller must lock the device. */
509 void aluHandleDisconnect(ALCdevice *device);
511 extern ALfloat ConeScale;
512 extern ALfloat ZScale;
514 #ifdef __cplusplus
516 #endif
518 #endif