Simplify bsinc filter storage in the filter state
[openal-soft.git] / OpenAL32 / Include / alu.h
blob78f05b63923853e42be80682f74d9ebac55e15e4
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 ALsizei m; /* Coefficient count. */
75 ALint l; /* Left coefficient offset. */
76 /* Filter coefficients, followed by the scale, phase, and scale-phase
77 * delta coefficients. Starting at phase index 0, each subsequent phase
78 * index follows contiguously.
80 const ALfloat *filter;
81 } BsincState;
83 typedef union InterpState {
84 BsincState bsinc;
85 } InterpState;
87 ALboolean BsincPrepare(const ALuint increment, BsincState *state);
89 typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
90 const ALfloat *restrict src, ALsizei frac, ALint increment,
91 ALfloat *restrict dst, ALsizei dstlen
95 typedef union aluVector {
96 alignas(16) ALfloat v[4];
97 } aluVector;
99 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
101 vector->v[0] = x;
102 vector->v[1] = y;
103 vector->v[2] = z;
104 vector->v[3] = w;
108 typedef union aluMatrixf {
109 alignas(16) ALfloat m[4][4];
110 } aluMatrixf;
111 extern const aluMatrixf IdentityMatrixf;
113 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
114 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
116 matrix->m[row][0] = m0;
117 matrix->m[row][1] = m1;
118 matrix->m[row][2] = m2;
119 matrix->m[row][3] = m3;
122 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
123 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
124 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
125 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
127 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
128 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
129 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
130 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
134 enum ActiveFilters {
135 AF_None = 0,
136 AF_LowPass = 1,
137 AF_HighPass = 2,
138 AF_BandPass = AF_LowPass | AF_HighPass
142 typedef struct MixHrtfParams {
143 const ALfloat (*Coeffs)[2];
144 ALsizei Delay[2];
145 ALfloat Gain;
146 ALfloat GainStep;
147 } MixHrtfParams;
150 typedef struct DirectParams {
151 ALfilterState LowPass;
152 ALfilterState HighPass;
154 NfcFilter NFCtrlFilter[MAX_AMBI_ORDER];
156 struct {
157 HrtfParams Old;
158 HrtfParams Target;
159 HrtfState State;
160 } Hrtf;
162 struct {
163 ALfloat Current[MAX_OUTPUT_CHANNELS];
164 ALfloat Target[MAX_OUTPUT_CHANNELS];
165 } Gains;
166 } DirectParams;
168 typedef struct SendParams {
169 ALfilterState LowPass;
170 ALfilterState HighPass;
172 struct {
173 ALfloat Current[MAX_OUTPUT_CHANNELS];
174 ALfloat Target[MAX_OUTPUT_CHANNELS];
175 } Gains;
176 } SendParams;
179 struct ALvoiceProps {
180 ATOMIC(struct ALvoiceProps*) next;
182 ALfloat Pitch;
183 ALfloat Gain;
184 ALfloat OuterGain;
185 ALfloat MinGain;
186 ALfloat MaxGain;
187 ALfloat InnerAngle;
188 ALfloat OuterAngle;
189 ALfloat RefDistance;
190 ALfloat MaxDistance;
191 ALfloat RolloffFactor;
192 ALfloat Position[3];
193 ALfloat Velocity[3];
194 ALfloat Direction[3];
195 ALfloat Orientation[2][3];
196 ALboolean HeadRelative;
197 enum DistanceModel DistanceModel;
198 enum Resampler Resampler;
199 ALboolean DirectChannels;
200 enum SpatializeMode SpatializeMode;
202 ALboolean DryGainHFAuto;
203 ALboolean WetGainAuto;
204 ALboolean WetGainHFAuto;
205 ALfloat OuterGainHF;
207 ALfloat AirAbsorptionFactor;
208 ALfloat RoomRolloffFactor;
209 ALfloat DopplerFactor;
211 ALfloat StereoPan[2];
213 ALfloat Radius;
215 /** Direct filter and auxiliary send info. */
216 struct {
217 ALfloat Gain;
218 ALfloat GainHF;
219 ALfloat HFReference;
220 ALfloat GainLF;
221 ALfloat LFReference;
222 } Direct;
223 struct {
224 struct ALeffectslot *Slot;
225 ALfloat Gain;
226 ALfloat GainHF;
227 ALfloat HFReference;
228 ALfloat GainLF;
229 ALfloat LFReference;
230 } Send[];
233 /* If not 'fading', gain targets are used directly without fading. */
234 #define VOICE_IS_FADING (1<<0)
235 #define VOICE_HAS_HRTF (1<<1)
236 #define VOICE_HAS_NFC (1<<2)
238 typedef struct ALvoice {
239 struct ALvoiceProps *Props;
241 ATOMIC(struct ALvoiceProps*) Update;
242 ATOMIC(struct ALvoiceProps*) FreeList;
244 ATOMIC(struct ALsource*) Source;
245 ATOMIC(bool) Playing;
248 * Source offset in samples, relative to the currently playing buffer, NOT
249 * the whole queue, and the fractional (fixed-point) offset to the next
250 * sample.
252 ATOMIC(ALuint) position;
253 ATOMIC(ALsizei) position_fraction;
255 /* Current buffer queue item being played. */
256 ATOMIC(struct ALbufferlistitem*) current_buffer;
258 /* Buffer queue item to loop to at end of queue (will be NULL for non-
259 * looping voices).
261 ATOMIC(struct ALbufferlistitem*) loop_buffer;
264 * Number of channels and bytes-per-sample for the attached source's
265 * buffer(s).
267 ALsizei NumChannels;
268 ALsizei SampleSize;
270 /** Current target parameters used for mixing. */
271 ALint Step;
273 ResamplerFunc Resampler;
275 ALuint Flags;
277 ALuint Offset; /* Number of output samples mixed since starting. */
279 alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
281 InterpState ResampleState;
283 struct {
284 enum ActiveFilters FilterType;
285 DirectParams Params[MAX_INPUT_CHANNELS];
287 ALfloat (*Buffer)[BUFFERSIZE];
288 ALsizei Channels;
289 ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
290 } Direct;
292 struct {
293 enum ActiveFilters FilterType;
294 SendParams Params[MAX_INPUT_CHANNELS];
296 ALfloat (*Buffer)[BUFFERSIZE];
297 ALsizei Channels;
298 } Send[];
299 } ALvoice;
301 void DeinitVoice(ALvoice *voice);
304 typedef void (*MixerFunc)(const ALfloat *data, ALsizei OutChans,
305 ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
306 const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
307 ALsizei BufferSize);
308 typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
309 const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
310 ALsizei InPos, ALsizei BufferSize);
311 typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
312 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
313 const ALsizei IrSize, MixHrtfParams *hrtfparams,
314 HrtfState *hrtfstate, ALsizei BufferSize);
315 typedef void (*HrtfMixerBlendFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
316 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
317 const ALsizei IrSize, const HrtfParams *oldparams,
318 MixHrtfParams *newparams, HrtfState *hrtfstate,
319 ALsizei BufferSize);
320 typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
321 const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
322 const ALfloat (*restrict Coeffs)[2],
323 ALfloat (*restrict Values)[2], ALsizei BufferSize);
326 #define GAIN_MIX_MAX (16.0f) /* +24dB */
328 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
330 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
331 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
333 /* Target gain for the reverb decay feedback reaching the decay time. */
334 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
336 #define FRACTIONBITS (12)
337 #define FRACTIONONE (1<<FRACTIONBITS)
338 #define FRACTIONMASK (FRACTIONONE-1)
341 inline ALfloat minf(ALfloat a, ALfloat b)
342 { return ((a > b) ? b : a); }
343 inline ALfloat maxf(ALfloat a, ALfloat b)
344 { return ((a > b) ? a : b); }
345 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
346 { return minf(max, maxf(min, val)); }
348 inline ALdouble mind(ALdouble a, ALdouble b)
349 { return ((a > b) ? b : a); }
350 inline ALdouble maxd(ALdouble a, ALdouble b)
351 { return ((a > b) ? a : b); }
352 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
353 { return mind(max, maxd(min, val)); }
355 inline ALuint minu(ALuint a, ALuint b)
356 { return ((a > b) ? b : a); }
357 inline ALuint maxu(ALuint a, ALuint b)
358 { return ((a > b) ? a : b); }
359 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
360 { return minu(max, maxu(min, val)); }
362 inline ALint mini(ALint a, ALint b)
363 { return ((a > b) ? b : a); }
364 inline ALint maxi(ALint a, ALint b)
365 { return ((a > b) ? a : b); }
366 inline ALint clampi(ALint val, ALint min, ALint max)
367 { return mini(max, maxi(min, val)); }
369 inline ALint64 mini64(ALint64 a, ALint64 b)
370 { return ((a > b) ? b : a); }
371 inline ALint64 maxi64(ALint64 a, ALint64 b)
372 { return ((a > b) ? a : b); }
373 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
374 { return mini64(max, maxi64(min, val)); }
376 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
377 { return ((a > b) ? b : a); }
378 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
379 { return ((a > b) ? a : b); }
380 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
381 { return minu64(max, maxu64(min, val)); }
384 extern alignas(16) const ALfloat sinc4Tab[FRACTIONONE][4];
387 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
389 return val1 + (val2-val1)*mu;
391 inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALsizei frac)
393 return sinc4Tab[frac][0]*val0 + sinc4Tab[frac][1]*val1 +
394 sinc4Tab[frac][2]*val2 + sinc4Tab[frac][3]*val3;
398 enum HrtfRequestMode {
399 Hrtf_Default = 0,
400 Hrtf_Enable = 1,
401 Hrtf_Disable = 2,
404 void aluInit(void);
406 void aluInitMixer(void);
408 MixerFunc SelectMixer(void);
409 RowMixerFunc SelectRowMixer(void);
410 ResamplerFunc SelectResampler(enum Resampler resampler);
412 /* aluInitRenderer
414 * Set up the appropriate panning method and mixing method given the device
415 * properties.
417 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
419 void aluInitEffectPanning(struct ALeffectslot *slot);
422 * CalcDirectionCoeffs
424 * Calculates ambisonic coefficients based on a direction vector. The vector
425 * must be normalized (unit length), and the spread is the angular width of the
426 * sound (0...tau).
428 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
431 * CalcAngleCoeffs
433 * Calculates ambisonic coefficients based on azimuth and elevation. The
434 * azimuth and elevation parameters are in radians, going right and up
435 * respectively.
437 inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
439 ALfloat dir[3] = {
440 sinf(azimuth) * cosf(elevation),
441 sinf(elevation),
442 -cosf(azimuth) * cosf(elevation)
444 CalcDirectionCoeffs(dir, spread, coeffs);
448 * CalcAnglePairwiseCoeffs
450 * Calculates ambisonic coefficients based on azimuth and elevation. The
451 * azimuth and elevation parameters are in radians, going right and up
452 * respectively. This pairwise variant warps the result such that +30 azimuth
453 * is full right, and -30 azimuth is full left.
455 void CalcAnglePairwiseCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
458 * ComputeAmbientGains
460 * Computes channel gains for ambient, omni-directional sounds.
462 #define ComputeAmbientGains(b, g, o) do { \
463 if((b).CoeffCount > 0) \
464 ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o); \
465 else \
466 ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
467 } while (0)
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]);
472 * ComputePanningGains
474 * Computes panning gains using the given channel decoder coefficients and the
475 * pre-calculated direction or angle coefficients.
477 #define ComputePanningGains(b, c, g, o) do { \
478 if((b).CoeffCount > 0) \
479 ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\
480 else \
481 ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
482 } while (0)
483 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
484 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
487 * ComputeFirstOrderGains
489 * Sets channel gains for a first-order ambisonics input channel. The matrix is
490 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
491 * orient the sound samples.
493 #define ComputeFirstOrderGains(b, m, g, o) do { \
494 if((b).CoeffCount > 0) \
495 ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o); \
496 else \
497 ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
498 } while (0)
499 void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
500 void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
503 ALboolean MixSource(struct ALvoice *voice, struct ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo);
505 void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples);
506 /* Caller must lock the device. */
507 void aluHandleDisconnect(ALCdevice *device);
509 extern ALfloat ConeScale;
510 extern ALfloat ZScale;
512 #ifdef __cplusplus
514 #endif
516 #endif