Combine nearly-duplicate structures
[openal-soft.git] / OpenAL32 / Include / alu.h
blobac0c866f93a764ff63ea9a13138b46a588f52fb3
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"
16 #include "hrtf.h"
17 #include "align.h"
18 #include "math_defs.h"
19 #include "filters/defs.h"
20 #include "filters/nfc.h"
23 #define MAX_PITCH (255)
25 /* Maximum number of samples to pad on either end of a buffer for resampling.
26 * Note that both the beginning and end need padding!
28 #define MAX_RESAMPLE_PADDING 24
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
35 struct BSincTable;
36 struct ALsource;
37 struct ALbufferlistitem;
38 struct ALvoice;
39 struct ALeffectslot;
42 #define DITHER_RNG_SEED 22222
45 enum SpatializeMode {
46 SpatializeOff = AL_FALSE,
47 SpatializeOn = AL_TRUE,
48 SpatializeAuto = AL_AUTO_SOFT
51 enum Resampler {
52 PointResampler,
53 LinearResampler,
54 FIR4Resampler,
55 BSinc12Resampler,
56 BSinc24Resampler,
58 ResamplerMax = BSinc24Resampler
60 extern enum Resampler ResamplerDefault;
62 /* The number of distinct scale and phase intervals within the bsinc filter
63 * table.
65 #define BSINC_SCALE_BITS 4
66 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
67 #define BSINC_PHASE_BITS 4
68 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
70 /* Interpolator state. Kind of a misnomer since the interpolator itself is
71 * stateless. This just keeps it from having to recompute scale-related
72 * mappings for every sample.
74 typedef struct BsincState {
75 ALfloat sf; /* Scale interpolation factor. */
76 ALsizei m; /* Coefficient count. */
77 ALsizei l; /* Left coefficient offset. */
78 /* Filter coefficients, followed by the scale, phase, and scale-phase
79 * delta coefficients. Starting at phase index 0, each subsequent phase
80 * index follows contiguously.
82 const ALfloat *filter;
83 } BsincState;
85 typedef union InterpState {
86 BsincState bsinc;
87 } InterpState;
89 typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
90 const ALfloat *restrict src, ALsizei frac, ALint increment,
91 ALfloat *restrict dst, ALsizei dstlen
94 void BsincPrepare(const ALuint increment, BsincState *state, const struct BSincTable *table);
96 extern const struct BSincTable bsinc12;
97 extern const struct BSincTable bsinc24;
100 typedef union aluVector {
101 alignas(16) ALfloat v[4];
102 } aluVector;
104 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
106 vector->v[0] = x;
107 vector->v[1] = y;
108 vector->v[2] = z;
109 vector->v[3] = w;
113 typedef union aluMatrixf {
114 alignas(16) ALfloat m[4][4];
115 } aluMatrixf;
116 extern const aluMatrixf IdentityMatrixf;
118 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
119 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
121 matrix->m[row][0] = m0;
122 matrix->m[row][1] = m1;
123 matrix->m[row][2] = m2;
124 matrix->m[row][3] = m3;
127 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
128 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
129 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
130 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
132 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
133 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
134 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
135 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
139 enum ActiveFilters {
140 AF_None = 0,
141 AF_LowPass = 1,
142 AF_HighPass = 2,
143 AF_BandPass = AF_LowPass | AF_HighPass
147 typedef struct MixHrtfParams {
148 const ALfloat (*Coeffs)[2];
149 ALsizei Delay[2];
150 ALfloat Gain;
151 ALfloat GainStep;
152 } MixHrtfParams;
155 typedef struct DirectParams {
156 BiquadFilter LowPass;
157 BiquadFilter HighPass;
159 NfcFilter NFCtrlFilter;
161 struct {
162 HrtfParams Old;
163 HrtfParams Target;
164 HrtfState State;
165 } Hrtf;
167 struct {
168 ALfloat Current[MAX_OUTPUT_CHANNELS];
169 ALfloat Target[MAX_OUTPUT_CHANNELS];
170 } Gains;
171 } DirectParams;
173 typedef struct SendParams {
174 BiquadFilter LowPass;
175 BiquadFilter HighPass;
177 struct {
178 ALfloat Current[MAX_OUTPUT_CHANNELS];
179 ALfloat Target[MAX_OUTPUT_CHANNELS];
180 } Gains;
181 } SendParams;
184 struct ALvoiceProps {
185 ATOMIC(struct ALvoiceProps*) next;
187 ALfloat Pitch;
188 ALfloat Gain;
189 ALfloat OuterGain;
190 ALfloat MinGain;
191 ALfloat MaxGain;
192 ALfloat InnerAngle;
193 ALfloat OuterAngle;
194 ALfloat RefDistance;
195 ALfloat MaxDistance;
196 ALfloat RolloffFactor;
197 ALfloat Position[3];
198 ALfloat Velocity[3];
199 ALfloat Direction[3];
200 ALfloat Orientation[2][3];
201 ALboolean HeadRelative;
202 enum DistanceModel DistanceModel;
203 enum Resampler Resampler;
204 ALboolean DirectChannels;
205 enum SpatializeMode SpatializeMode;
207 ALboolean DryGainHFAuto;
208 ALboolean WetGainAuto;
209 ALboolean WetGainHFAuto;
210 ALfloat OuterGainHF;
212 ALfloat AirAbsorptionFactor;
213 ALfloat RoomRolloffFactor;
214 ALfloat DopplerFactor;
216 ALfloat StereoPan[2];
218 ALfloat Radius;
220 /** Direct filter and auxiliary send info. */
221 struct {
222 ALfloat Gain;
223 ALfloat GainHF;
224 ALfloat HFReference;
225 ALfloat GainLF;
226 ALfloat LFReference;
227 } Direct;
228 struct {
229 struct ALeffectslot *Slot;
230 ALfloat Gain;
231 ALfloat GainHF;
232 ALfloat HFReference;
233 ALfloat GainLF;
234 ALfloat LFReference;
235 } Send[];
238 #define VOICE_IS_STATIC (1<<0)
239 #define VOICE_IS_FADING (1<<1) /* Fading sources use gain stepping for smooth transitions. */
240 #define VOICE_HAS_HRTF (1<<2)
241 #define VOICE_HAS_NFC (1<<3)
243 typedef struct ALvoice {
244 struct ALvoiceProps *Props;
246 ATOMIC(struct ALvoiceProps*) Update;
248 ATOMIC(struct ALsource*) Source;
249 ATOMIC(bool) Playing;
252 * Source offset in samples, relative to the currently playing buffer, NOT
253 * the whole queue, and the fractional (fixed-point) offset to the next
254 * sample.
256 ATOMIC(ALuint) position;
257 ATOMIC(ALsizei) position_fraction;
259 /* Current buffer queue item being played. */
260 ATOMIC(struct ALbufferlistitem*) current_buffer;
262 /* Buffer queue item to loop to at end of queue (will be NULL for non-
263 * looping voices).
265 ATOMIC(struct ALbufferlistitem*) loop_buffer;
268 * Number of channels and bytes-per-sample for the attached source's
269 * buffer(s).
271 ALsizei NumChannels;
272 ALsizei SampleSize;
274 /** Current target parameters used for mixing. */
275 ALint Step;
277 ResamplerFunc Resampler;
279 ALuint Flags;
281 ALuint Offset; /* Number of output samples mixed since starting. */
283 alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_RESAMPLE_PADDING];
285 InterpState ResampleState;
287 struct {
288 enum ActiveFilters FilterType;
289 DirectParams Params[MAX_INPUT_CHANNELS];
291 ALfloat (*Buffer)[BUFFERSIZE];
292 ALsizei Channels;
293 ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
294 } Direct;
296 struct {
297 enum ActiveFilters FilterType;
298 SendParams Params[MAX_INPUT_CHANNELS];
300 ALfloat (*Buffer)[BUFFERSIZE];
301 ALsizei Channels;
302 } Send[];
303 } ALvoice;
305 void DeinitVoice(ALvoice *voice);
308 typedef void (*MixerFunc)(const ALfloat *data, ALsizei OutChans,
309 ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
310 const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
311 ALsizei BufferSize);
312 typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
313 const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
314 ALsizei InPos, ALsizei BufferSize);
315 typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
316 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
317 const ALsizei IrSize, MixHrtfParams *hrtfparams,
318 HrtfState *hrtfstate, ALsizei BufferSize);
319 typedef void (*HrtfMixerBlendFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
320 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
321 const ALsizei IrSize, const HrtfParams *oldparams,
322 MixHrtfParams *newparams, HrtfState *hrtfstate,
323 ALsizei BufferSize);
324 typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
325 const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
326 const ALfloat (*restrict Coeffs)[2],
327 ALfloat (*restrict Values)[2], ALsizei BufferSize);
330 #define GAIN_MIX_MAX (16.0f) /* +24dB */
332 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
334 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
335 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
337 /* Target gain for the reverb decay feedback reaching the decay time. */
338 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
340 #define FRACTIONBITS (12)
341 #define FRACTIONONE (1<<FRACTIONBITS)
342 #define FRACTIONMASK (FRACTIONONE-1)
345 inline ALfloat minf(ALfloat a, ALfloat b)
346 { return ((a > b) ? b : a); }
347 inline ALfloat maxf(ALfloat a, ALfloat b)
348 { return ((a > b) ? a : b); }
349 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
350 { return minf(max, maxf(min, val)); }
352 inline ALdouble mind(ALdouble a, ALdouble b)
353 { return ((a > b) ? b : a); }
354 inline ALdouble maxd(ALdouble a, ALdouble b)
355 { return ((a > b) ? a : b); }
356 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
357 { return mind(max, maxd(min, val)); }
359 inline ALuint minu(ALuint a, ALuint b)
360 { return ((a > b) ? b : a); }
361 inline ALuint maxu(ALuint a, ALuint b)
362 { return ((a > b) ? a : b); }
363 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
364 { return minu(max, maxu(min, val)); }
366 inline ALint mini(ALint a, ALint b)
367 { return ((a > b) ? b : a); }
368 inline ALint maxi(ALint a, ALint b)
369 { return ((a > b) ? a : b); }
370 inline ALint clampi(ALint val, ALint min, ALint max)
371 { return mini(max, maxi(min, val)); }
373 inline ALint64 mini64(ALint64 a, ALint64 b)
374 { return ((a > b) ? b : a); }
375 inline ALint64 maxi64(ALint64 a, ALint64 b)
376 { return ((a > b) ? a : b); }
377 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
378 { return mini64(max, maxi64(min, val)); }
380 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
381 { return ((a > b) ? b : a); }
382 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
383 { return ((a > b) ? a : b); }
384 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
385 { return minu64(max, maxu64(min, val)); }
387 inline size_t minz(size_t a, size_t b)
388 { return ((a > b) ? b : a); }
389 inline size_t maxz(size_t a, size_t b)
390 { return ((a > b) ? a : b); }
391 inline size_t clampz(size_t val, size_t min, size_t max)
392 { return minz(max, maxz(min, val)); }
395 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
397 return val1 + (val2-val1)*mu;
399 inline ALfloat cubic(ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat mu)
401 ALfloat mu2 = mu*mu, mu3 = mu2*mu;
402 ALfloat a0 = -0.5f*mu3 + mu2 + -0.5f*mu;
403 ALfloat a1 = 1.5f*mu3 + -2.5f*mu2 + 1.0f;
404 ALfloat a2 = -1.5f*mu3 + 2.0f*mu2 + 0.5f*mu;
405 ALfloat a3 = 0.5f*mu3 + -0.5f*mu2;
406 return val1*a0 + val2*a1 + val3*a2 + val4*a3;
410 enum HrtfRequestMode {
411 Hrtf_Default = 0,
412 Hrtf_Enable = 1,
413 Hrtf_Disable = 2,
416 void aluInit(void);
418 void aluInitMixer(void);
420 ResamplerFunc SelectResampler(enum Resampler resampler);
422 /* aluInitRenderer
424 * Set up the appropriate panning method and mixing method given the device
425 * properties.
427 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
429 void aluInitEffectPanning(struct ALeffectslot *slot);
431 void aluSelectPostProcess(ALCdevice *device);
434 * Calculates ambisonic encoder coefficients using the X, Y, and Z direction
435 * components, which must represent a normalized (unit length) vector, and the
436 * spread is the angular width of the sound (0...tau).
438 * NOTE: The components use ambisonic coordinates. As a result:
440 * Ambisonic Y = OpenAL -X
441 * Ambisonic Z = OpenAL Y
442 * Ambisonic X = OpenAL -Z
444 * The components are ordered such that OpenAL's X, Y, and Z are the first,
445 * second, and third parameters respectively -- simply negate X and Z.
447 void CalcAmbiCoeffs(const ALfloat y, const ALfloat z, const ALfloat x, const ALfloat spread,
448 ALfloat coeffs[MAX_AMBI_COEFFS]);
451 * CalcDirectionCoeffs
453 * Calculates ambisonic coefficients based on an OpenAL direction vector. The
454 * vector must be normalized (unit length), and the spread is the angular width
455 * of the sound (0...tau).
457 inline void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
459 /* Convert from OpenAL coords to Ambisonics. */
460 CalcAmbiCoeffs(-dir[0], dir[1], -dir[2], spread, coeffs);
464 * CalcAngleCoeffs
466 * Calculates ambisonic coefficients based on azimuth and elevation. The
467 * azimuth and elevation parameters are in radians, going right and up
468 * respectively.
470 inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
472 ALfloat x = -sinf(azimuth) * cosf(elevation);
473 ALfloat y = sinf(elevation);
474 ALfloat z = cosf(azimuth) * cosf(elevation);
476 CalcAmbiCoeffs(x, y, z, spread, coeffs);
480 * ScaleAzimuthFront
482 * Scales the given azimuth toward the side (+/- pi/2 radians) for positions in
483 * front.
485 inline float ScaleAzimuthFront(float azimuth, float scale)
487 ALfloat sign = copysignf(1.0f, azimuth);
488 if(!(fabsf(azimuth) > F_PI_2))
489 return minf(fabsf(azimuth) * scale, F_PI_2) * sign;
490 return azimuth;
494 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
495 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
498 * ComputeDryPanGains
500 * Computes panning gains using the given channel decoder coefficients and the
501 * pre-calculated direction or angle coefficients.
503 inline void ComputeDryPanGains(const MixParams *dry, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
505 if(dry->CoeffCount > 0)
506 ComputePanningGainsMC(dry->Ambi.Coeffs, dry->NumChannels, dry->CoeffCount,
507 coeffs, ingain, gains);
508 else
509 ComputePanningGainsBF(dry->Ambi.Map, dry->NumChannels, coeffs, ingain, gains);
512 * ComputeFirstOrderGains
514 * Sets channel gains for a first-order ambisonics input channel. The matrix is
515 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
516 * orient the sound samples.
518 inline void ComputeFirstOrderGains(const MixParams *foa, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
520 if(foa->CoeffCount > 0)
521 ComputePanningGainsMC(foa->Ambi.Coeffs, foa->NumChannels, 4, mtx, ingain, gains);
522 else
523 ComputePanningGainsBF(foa->Ambi.Map, foa->NumChannels, mtx, ingain, gains);
527 ALboolean MixSource(struct ALvoice *voice, ALuint SourceID, ALCcontext *Context, ALsizei SamplesToDo);
529 void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples);
530 /* Caller must lock the device, and the mixer must not be running. */
531 void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3);
533 void UpdateContextProps(ALCcontext *context);
535 extern MixerFunc MixSamples;
536 extern RowMixerFunc MixRowSamples;
538 extern ALfloat ConeScale;
539 extern ALfloat ZScale;
540 extern ALboolean OverrideReverbSpeedOfSound;
542 #ifdef __cplusplus
544 #endif
546 #endif