Provide more descriptive messages to disconnection events
[openal-soft.git] / OpenAL32 / Include / alu.h
blob920b7b44776fd733a1c87b5d3bd9af10c33738b4
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 samples to pad on either end of a buffer for resampling.
27 * Note that both the beginning and end need padding!
29 #define MAX_RESAMPLE_PADDING 24
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
36 struct BSincTable;
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 BSinc12Resampler,
57 BSinc24Resampler,
59 ResamplerMax = BSinc24Resampler
61 extern enum Resampler ResamplerDefault;
63 /* The number of distinct scale and phase intervals within the bsinc filter
64 * table.
66 #define BSINC_SCALE_BITS 4
67 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
68 #define BSINC_PHASE_BITS 4
69 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
71 /* Interpolator state. Kind of a misnomer since the interpolator itself is
72 * stateless. This just keeps it from having to recompute scale-related
73 * mappings for every sample.
75 typedef struct BsincState {
76 ALfloat sf; /* Scale interpolation factor. */
77 ALsizei m; /* Coefficient count. */
78 ALint l; /* Left coefficient offset. */
79 /* Filter coefficients, followed by the scale, phase, and scale-phase
80 * delta coefficients. Starting at phase index 0, each subsequent phase
81 * index follows contiguously.
83 const ALfloat *filter;
84 } BsincState;
86 typedef union InterpState {
87 BsincState bsinc;
88 } InterpState;
90 typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
91 const ALfloat *restrict src, ALsizei frac, ALint increment,
92 ALfloat *restrict dst, ALsizei dstlen
95 void BsincPrepare(const ALuint increment, BsincState *state, const struct BSincTable *table);
97 extern const struct BSincTable bsinc12;
98 extern const struct BSincTable bsinc24;
101 typedef union aluVector {
102 alignas(16) ALfloat v[4];
103 } aluVector;
105 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
107 vector->v[0] = x;
108 vector->v[1] = y;
109 vector->v[2] = z;
110 vector->v[3] = w;
114 typedef union aluMatrixf {
115 alignas(16) ALfloat m[4][4];
116 } aluMatrixf;
117 extern const aluMatrixf IdentityMatrixf;
119 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
120 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
122 matrix->m[row][0] = m0;
123 matrix->m[row][1] = m1;
124 matrix->m[row][2] = m2;
125 matrix->m[row][3] = m3;
128 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
129 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
130 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
131 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
133 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
134 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
135 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
136 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
140 enum ActiveFilters {
141 AF_None = 0,
142 AF_LowPass = 1,
143 AF_HighPass = 2,
144 AF_BandPass = AF_LowPass | AF_HighPass
148 typedef struct MixHrtfParams {
149 const ALfloat (*Coeffs)[2];
150 ALsizei Delay[2];
151 ALfloat Gain;
152 ALfloat GainStep;
153 } MixHrtfParams;
156 typedef struct DirectParams {
157 ALfilterState LowPass;
158 ALfilterState HighPass;
160 NfcFilter NFCtrlFilter[MAX_AMBI_ORDER];
162 struct {
163 HrtfParams Old;
164 HrtfParams Target;
165 HrtfState State;
166 } Hrtf;
168 struct {
169 ALfloat Current[MAX_OUTPUT_CHANNELS];
170 ALfloat Target[MAX_OUTPUT_CHANNELS];
171 } Gains;
172 } DirectParams;
174 typedef struct SendParams {
175 ALfilterState LowPass;
176 ALfilterState HighPass;
178 struct {
179 ALfloat Current[MAX_OUTPUT_CHANNELS];
180 ALfloat Target[MAX_OUTPUT_CHANNELS];
181 } Gains;
182 } SendParams;
185 struct ALvoiceProps {
186 ATOMIC(struct ALvoiceProps*) next;
188 ALfloat Pitch;
189 ALfloat Gain;
190 ALfloat OuterGain;
191 ALfloat MinGain;
192 ALfloat MaxGain;
193 ALfloat InnerAngle;
194 ALfloat OuterAngle;
195 ALfloat RefDistance;
196 ALfloat MaxDistance;
197 ALfloat RolloffFactor;
198 ALfloat Position[3];
199 ALfloat Velocity[3];
200 ALfloat Direction[3];
201 ALfloat Orientation[2][3];
202 ALboolean HeadRelative;
203 enum DistanceModel DistanceModel;
204 enum Resampler Resampler;
205 ALboolean DirectChannels;
206 enum SpatializeMode SpatializeMode;
208 ALboolean DryGainHFAuto;
209 ALboolean WetGainAuto;
210 ALboolean WetGainHFAuto;
211 ALfloat OuterGainHF;
213 ALfloat AirAbsorptionFactor;
214 ALfloat RoomRolloffFactor;
215 ALfloat DopplerFactor;
217 ALfloat StereoPan[2];
219 ALfloat Radius;
221 /** Direct filter and auxiliary send info. */
222 struct {
223 ALfloat Gain;
224 ALfloat GainHF;
225 ALfloat HFReference;
226 ALfloat GainLF;
227 ALfloat LFReference;
228 } Direct;
229 struct {
230 struct ALeffectslot *Slot;
231 ALfloat Gain;
232 ALfloat GainHF;
233 ALfloat HFReference;
234 ALfloat GainLF;
235 ALfloat LFReference;
236 } Send[];
239 #define VOICE_IS_STATIC (1<<0)
240 #define VOICE_IS_FADING (1<<1) /* Fading sources use gain stepping for smooth transitions. */
241 #define VOICE_HAS_HRTF (1<<2)
242 #define VOICE_HAS_NFC (1<<3)
244 typedef struct ALvoice {
245 struct ALvoiceProps *Props;
247 ATOMIC(struct ALvoiceProps*) Update;
249 ATOMIC(struct ALsource*) Source;
250 ATOMIC(bool) Playing;
253 * Source offset in samples, relative to the currently playing buffer, NOT
254 * the whole queue, and the fractional (fixed-point) offset to the next
255 * sample.
257 ATOMIC(ALuint) position;
258 ATOMIC(ALsizei) position_fraction;
260 /* Current buffer queue item being played. */
261 ATOMIC(struct ALbufferlistitem*) current_buffer;
263 /* Buffer queue item to loop to at end of queue (will be NULL for non-
264 * looping voices).
266 ATOMIC(struct ALbufferlistitem*) loop_buffer;
269 * Number of channels and bytes-per-sample for the attached source's
270 * buffer(s).
272 ALsizei NumChannels;
273 ALsizei SampleSize;
275 /** Current target parameters used for mixing. */
276 ALint Step;
278 ResamplerFunc Resampler;
280 ALuint Flags;
282 ALuint Offset; /* Number of output samples mixed since starting. */
284 alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_RESAMPLE_PADDING];
286 InterpState ResampleState;
288 struct {
289 enum ActiveFilters FilterType;
290 DirectParams Params[MAX_INPUT_CHANNELS];
292 ALfloat (*Buffer)[BUFFERSIZE];
293 ALsizei Channels;
294 ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
295 } Direct;
297 struct {
298 enum ActiveFilters FilterType;
299 SendParams Params[MAX_INPUT_CHANNELS];
301 ALfloat (*Buffer)[BUFFERSIZE];
302 ALsizei Channels;
303 } Send[];
304 } ALvoice;
306 void DeinitVoice(ALvoice *voice);
309 typedef void (*MixerFunc)(const ALfloat *data, ALsizei OutChans,
310 ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
311 const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
312 ALsizei BufferSize);
313 typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
314 const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
315 ALsizei InPos, ALsizei BufferSize);
316 typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
317 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
318 const ALsizei IrSize, MixHrtfParams *hrtfparams,
319 HrtfState *hrtfstate, ALsizei BufferSize);
320 typedef void (*HrtfMixerBlendFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
321 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
322 const ALsizei IrSize, const HrtfParams *oldparams,
323 MixHrtfParams *newparams, HrtfState *hrtfstate,
324 ALsizei BufferSize);
325 typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
326 const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
327 const ALfloat (*restrict Coeffs)[2],
328 ALfloat (*restrict Values)[2], ALsizei BufferSize);
331 #define GAIN_MIX_MAX (16.0f) /* +24dB */
333 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
335 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
336 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
338 /* Target gain for the reverb decay feedback reaching the decay time. */
339 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
341 #define FRACTIONBITS (12)
342 #define FRACTIONONE (1<<FRACTIONBITS)
343 #define FRACTIONMASK (FRACTIONONE-1)
346 inline ALfloat minf(ALfloat a, ALfloat b)
347 { return ((a > b) ? b : a); }
348 inline ALfloat maxf(ALfloat a, ALfloat b)
349 { return ((a > b) ? a : b); }
350 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
351 { return minf(max, maxf(min, val)); }
353 inline ALdouble mind(ALdouble a, ALdouble b)
354 { return ((a > b) ? b : a); }
355 inline ALdouble maxd(ALdouble a, ALdouble b)
356 { return ((a > b) ? a : b); }
357 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
358 { return mind(max, maxd(min, val)); }
360 inline ALuint minu(ALuint a, ALuint b)
361 { return ((a > b) ? b : a); }
362 inline ALuint maxu(ALuint a, ALuint b)
363 { return ((a > b) ? a : b); }
364 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
365 { return minu(max, maxu(min, val)); }
367 inline ALint mini(ALint a, ALint b)
368 { return ((a > b) ? b : a); }
369 inline ALint maxi(ALint a, ALint b)
370 { return ((a > b) ? a : b); }
371 inline ALint clampi(ALint val, ALint min, ALint max)
372 { return mini(max, maxi(min, val)); }
374 inline ALint64 mini64(ALint64 a, ALint64 b)
375 { return ((a > b) ? b : a); }
376 inline ALint64 maxi64(ALint64 a, ALint64 b)
377 { return ((a > b) ? a : b); }
378 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
379 { return mini64(max, maxi64(min, val)); }
381 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
382 { return ((a > b) ? b : a); }
383 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
384 { return ((a > b) ? a : b); }
385 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
386 { return minu64(max, maxu64(min, val)); }
388 inline size_t minz(size_t a, size_t b)
389 { return ((a > b) ? b : a); }
390 inline size_t maxz(size_t a, size_t b)
391 { return ((a > b) ? a : b); }
392 inline size_t clampz(size_t val, size_t min, size_t max)
393 { return minz(max, maxz(min, val)); }
396 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
398 return val1 + (val2-val1)*mu;
400 inline ALfloat cubic(ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat mu)
402 ALfloat mu2 = mu*mu, mu3 = mu2*mu;
403 ALfloat a0 = -0.5f*mu3 + mu2 + -0.5f*mu;
404 ALfloat a1 = 1.5f*mu3 + -2.5f*mu2 + 1.0f;
405 ALfloat a2 = -1.5f*mu3 + 2.0f*mu2 + 0.5f*mu;
406 ALfloat a3 = 0.5f*mu3 + -0.5f*mu2;
407 return val1*a0 + val2*a1 + val3*a2 + val4*a3;
411 enum HrtfRequestMode {
412 Hrtf_Default = 0,
413 Hrtf_Enable = 1,
414 Hrtf_Disable = 2,
417 void aluInit(void);
419 void aluInitMixer(void);
421 ResamplerFunc SelectResampler(enum Resampler resampler);
423 /* aluInitRenderer
425 * Set up the appropriate panning method and mixing method given the device
426 * properties.
428 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
430 void aluInitEffectPanning(struct ALeffectslot *slot);
433 * CalcDirectionCoeffs
435 * Calculates ambisonic coefficients based on a direction vector. The vector
436 * must be normalized (unit length), and the spread is the angular width of the
437 * sound (0...tau).
439 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
442 * CalcAngleCoeffs
444 * Calculates ambisonic coefficients based on azimuth and elevation. The
445 * azimuth and elevation parameters are in radians, going right and up
446 * respectively.
448 inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
450 ALfloat dir[3] = {
451 sinf(azimuth) * cosf(elevation),
452 sinf(elevation),
453 -cosf(azimuth) * cosf(elevation)
455 CalcDirectionCoeffs(dir, spread, coeffs);
459 * CalcAnglePairwiseCoeffs
461 * Calculates ambisonic coefficients based on azimuth and elevation. The
462 * azimuth and elevation parameters are in radians, going right and up
463 * respectively. This pairwise variant warps the result such that +30 azimuth
464 * is full right, and -30 azimuth is full left.
466 void CalcAnglePairwiseCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
468 void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
469 void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
471 * ComputeAmbientGains
473 * Computes channel gains for ambient, omni-directional sounds.
475 inline void ComputeAmbientGains(const DryMixParams *dry, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
477 if(dry->CoeffCount > 0)
478 ComputeAmbientGainsMC(dry->Ambi.Coeffs, dry->NumChannels, ingain, gains);
479 else
480 ComputeAmbientGainsBF(dry->Ambi.Map, dry->NumChannels, ingain, gains);
484 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
485 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
487 * ComputeDryPanGains
489 * Computes panning gains using the given channel decoder coefficients and the
490 * pre-calculated direction or angle coefficients.
492 inline void ComputeDryPanGains(const DryMixParams *dry, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
494 if(dry->CoeffCount > 0)
495 ComputePanningGainsMC(dry->Ambi.Coeffs, dry->NumChannels, dry->CoeffCount,
496 coeffs, ingain, gains);
497 else
498 ComputePanningGainsBF(dry->Ambi.Map, dry->NumChannels, coeffs, ingain, gains);
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]);
504 * ComputeFirstOrderGains
506 * Sets channel gains for a first-order ambisonics input channel. The matrix is
507 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
508 * orient the sound samples.
510 inline void ComputeFirstOrderGains(const BFMixParams *foa, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
512 if(foa->CoeffCount > 0)
513 ComputeFirstOrderGainsMC(foa->Ambi.Coeffs, foa->NumChannels, mtx, ingain, gains);
514 else
515 ComputeFirstOrderGainsBF(foa->Ambi.Map, foa->NumChannels, mtx, ingain, gains);
519 ALboolean MixSource(struct ALvoice *voice, ALuint SourceID, ALCcontext *Context, ALsizei SamplesToDo);
521 void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples);
522 /* Caller must lock the device, and the mixer must not be running. */
523 void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3);
525 void UpdateContextProps(ALCcontext *context);
527 extern MixerFunc MixSamples;
528 extern RowMixerFunc MixRowSamples;
530 extern ALfloat ConeScale;
531 extern ALfloat ZScale;
532 extern ALboolean OverrideReverbSpeedOfSound;
534 #ifdef __cplusplus
536 #endif
538 #endif