Replace the sinc4 resampler with cubic
[openal-soft.git] / OpenAL32 / Include / alu.h
blobc427df0cac92aaa7d73e766f22ecc9032476bc69
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 24
29 /* Maximum number of buffer samples after the current pos needed for resampling. */
30 #define MAX_POST_SAMPLES 24
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
37 struct BSincTable;
38 struct ALsource;
39 struct ALbufferlistitem;
40 struct ALvoice;
41 struct ALeffectslot;
44 #define DITHER_RNG_SEED 22222
47 enum SpatializeMode {
48 SpatializeOff = AL_FALSE,
49 SpatializeOn = AL_TRUE,
50 SpatializeAuto = AL_AUTO_SOFT
53 enum Resampler {
54 PointResampler,
55 LinearResampler,
56 FIR4Resampler,
57 BSinc12Resampler,
58 BSinc24Resampler,
60 ResamplerMax = BSinc24Resampler
62 extern enum Resampler ResamplerDefault;
64 /* The number of distinct scale and phase intervals within the bsinc filter
65 * table.
67 #define BSINC_SCALE_BITS 4
68 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
69 #define BSINC_PHASE_BITS 4
70 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
72 /* Interpolator state. Kind of a misnomer since the interpolator itself is
73 * stateless. This just keeps it from having to recompute scale-related
74 * mappings for every sample.
76 typedef struct BsincState {
77 ALfloat sf; /* Scale interpolation factor. */
78 ALsizei m; /* Coefficient count. */
79 ALint l; /* Left coefficient offset. */
80 /* Filter coefficients, followed by the scale, phase, and scale-phase
81 * delta coefficients. Starting at phase index 0, each subsequent phase
82 * index follows contiguously.
84 const ALfloat *filter;
85 } BsincState;
87 typedef struct Sinc4State {
88 const ALfloat (*filter)[4];
89 } Sinc4State;
91 typedef union InterpState {
92 BsincState bsinc;
93 Sinc4State sinc4;
94 } InterpState;
96 typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
97 const ALfloat *restrict src, ALsizei frac, ALint increment,
98 ALfloat *restrict dst, ALsizei dstlen
101 ALboolean BsincPrepare(const ALuint increment, BsincState *state, const struct BSincTable *table);
103 extern const struct BSincTable bsinc12;
104 extern const struct BSincTable bsinc24;
107 typedef union aluVector {
108 alignas(16) ALfloat v[4];
109 } aluVector;
111 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
113 vector->v[0] = x;
114 vector->v[1] = y;
115 vector->v[2] = z;
116 vector->v[3] = w;
120 typedef union aluMatrixf {
121 alignas(16) ALfloat m[4][4];
122 } aluMatrixf;
123 extern const aluMatrixf IdentityMatrixf;
125 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
126 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
128 matrix->m[row][0] = m0;
129 matrix->m[row][1] = m1;
130 matrix->m[row][2] = m2;
131 matrix->m[row][3] = m3;
134 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
135 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
136 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
137 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
139 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
140 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
141 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
142 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
146 enum ActiveFilters {
147 AF_None = 0,
148 AF_LowPass = 1,
149 AF_HighPass = 2,
150 AF_BandPass = AF_LowPass | AF_HighPass
154 typedef struct MixHrtfParams {
155 const ALfloat (*Coeffs)[2];
156 ALsizei Delay[2];
157 ALfloat Gain;
158 ALfloat GainStep;
159 } MixHrtfParams;
162 typedef struct DirectParams {
163 ALfilterState LowPass;
164 ALfilterState HighPass;
166 NfcFilter NFCtrlFilter[MAX_AMBI_ORDER];
168 struct {
169 HrtfParams Old;
170 HrtfParams Target;
171 HrtfState State;
172 } Hrtf;
174 struct {
175 ALfloat Current[MAX_OUTPUT_CHANNELS];
176 ALfloat Target[MAX_OUTPUT_CHANNELS];
177 } Gains;
178 } DirectParams;
180 typedef struct SendParams {
181 ALfilterState LowPass;
182 ALfilterState HighPass;
184 struct {
185 ALfloat Current[MAX_OUTPUT_CHANNELS];
186 ALfloat Target[MAX_OUTPUT_CHANNELS];
187 } Gains;
188 } SendParams;
191 struct ALvoiceProps {
192 ATOMIC(struct ALvoiceProps*) next;
194 ALfloat Pitch;
195 ALfloat Gain;
196 ALfloat OuterGain;
197 ALfloat MinGain;
198 ALfloat MaxGain;
199 ALfloat InnerAngle;
200 ALfloat OuterAngle;
201 ALfloat RefDistance;
202 ALfloat MaxDistance;
203 ALfloat RolloffFactor;
204 ALfloat Position[3];
205 ALfloat Velocity[3];
206 ALfloat Direction[3];
207 ALfloat Orientation[2][3];
208 ALboolean HeadRelative;
209 enum DistanceModel DistanceModel;
210 enum Resampler Resampler;
211 ALboolean DirectChannels;
212 enum SpatializeMode SpatializeMode;
214 ALboolean DryGainHFAuto;
215 ALboolean WetGainAuto;
216 ALboolean WetGainHFAuto;
217 ALfloat OuterGainHF;
219 ALfloat AirAbsorptionFactor;
220 ALfloat RoomRolloffFactor;
221 ALfloat DopplerFactor;
223 ALfloat StereoPan[2];
225 ALfloat Radius;
227 /** Direct filter and auxiliary send info. */
228 struct {
229 ALfloat Gain;
230 ALfloat GainHF;
231 ALfloat HFReference;
232 ALfloat GainLF;
233 ALfloat LFReference;
234 } Direct;
235 struct {
236 struct ALeffectslot *Slot;
237 ALfloat Gain;
238 ALfloat GainHF;
239 ALfloat HFReference;
240 ALfloat GainLF;
241 ALfloat LFReference;
242 } Send[];
245 /* If not 'fading', gain targets are used directly without fading. */
246 #define VOICE_IS_FADING (1<<0)
247 #define VOICE_HAS_HRTF (1<<1)
248 #define VOICE_HAS_NFC (1<<2)
250 typedef struct ALvoice {
251 struct ALvoiceProps *Props;
253 ATOMIC(struct ALvoiceProps*) Update;
255 ATOMIC(struct ALsource*) Source;
256 ATOMIC(bool) Playing;
259 * Source offset in samples, relative to the currently playing buffer, NOT
260 * the whole queue, and the fractional (fixed-point) offset to the next
261 * sample.
263 ATOMIC(ALuint) position;
264 ATOMIC(ALsizei) position_fraction;
266 /* Current buffer queue item being played. */
267 ATOMIC(struct ALbufferlistitem*) current_buffer;
269 /* Buffer queue item to loop to at end of queue (will be NULL for non-
270 * looping voices).
272 ATOMIC(struct ALbufferlistitem*) loop_buffer;
275 * Number of channels and bytes-per-sample for the attached source's
276 * buffer(s).
278 ALsizei NumChannels;
279 ALsizei SampleSize;
281 /** Current target parameters used for mixing. */
282 ALint Step;
284 ResamplerFunc Resampler;
286 ALuint Flags;
288 ALuint Offset; /* Number of output samples mixed since starting. */
290 alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
292 InterpState ResampleState;
294 struct {
295 enum ActiveFilters FilterType;
296 DirectParams Params[MAX_INPUT_CHANNELS];
298 ALfloat (*Buffer)[BUFFERSIZE];
299 ALsizei Channels;
300 ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
301 } Direct;
303 struct {
304 enum ActiveFilters FilterType;
305 SendParams Params[MAX_INPUT_CHANNELS];
307 ALfloat (*Buffer)[BUFFERSIZE];
308 ALsizei Channels;
309 } Send[];
310 } ALvoice;
312 void DeinitVoice(ALvoice *voice);
315 typedef void (*MixerFunc)(const ALfloat *data, ALsizei OutChans,
316 ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
317 const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
318 ALsizei BufferSize);
319 typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
320 const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
321 ALsizei InPos, ALsizei BufferSize);
322 typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
323 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
324 const ALsizei IrSize, MixHrtfParams *hrtfparams,
325 HrtfState *hrtfstate, ALsizei BufferSize);
326 typedef void (*HrtfMixerBlendFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
327 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
328 const ALsizei IrSize, const HrtfParams *oldparams,
329 MixHrtfParams *newparams, HrtfState *hrtfstate,
330 ALsizei BufferSize);
331 typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
332 const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
333 const ALfloat (*restrict Coeffs)[2],
334 ALfloat (*restrict Values)[2], ALsizei BufferSize);
337 #define GAIN_MIX_MAX (16.0f) /* +24dB */
339 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
341 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
342 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
344 /* Target gain for the reverb decay feedback reaching the decay time. */
345 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
347 #define FRACTIONBITS (12)
348 #define FRACTIONONE (1<<FRACTIONBITS)
349 #define FRACTIONMASK (FRACTIONONE-1)
352 inline ALfloat minf(ALfloat a, ALfloat b)
353 { return ((a > b) ? b : a); }
354 inline ALfloat maxf(ALfloat a, ALfloat b)
355 { return ((a > b) ? a : b); }
356 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
357 { return minf(max, maxf(min, val)); }
359 inline ALdouble mind(ALdouble a, ALdouble b)
360 { return ((a > b) ? b : a); }
361 inline ALdouble maxd(ALdouble a, ALdouble b)
362 { return ((a > b) ? a : b); }
363 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
364 { return mind(max, maxd(min, val)); }
366 inline ALuint minu(ALuint a, ALuint b)
367 { return ((a > b) ? b : a); }
368 inline ALuint maxu(ALuint a, ALuint b)
369 { return ((a > b) ? a : b); }
370 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
371 { return minu(max, maxu(min, val)); }
373 inline ALint mini(ALint a, ALint b)
374 { return ((a > b) ? b : a); }
375 inline ALint maxi(ALint a, ALint b)
376 { return ((a > b) ? a : b); }
377 inline ALint clampi(ALint val, ALint min, ALint max)
378 { return mini(max, maxi(min, val)); }
380 inline ALint64 mini64(ALint64 a, ALint64 b)
381 { return ((a > b) ? b : a); }
382 inline ALint64 maxi64(ALint64 a, ALint64 b)
383 { return ((a > b) ? a : b); }
384 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
385 { return mini64(max, maxi64(min, val)); }
387 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
388 { return ((a > b) ? b : a); }
389 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
390 { return ((a > b) ? a : b); }
391 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
392 { return minu64(max, maxu64(min, val)); }
395 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
397 return val1 + (val2-val1)*mu;
401 enum HrtfRequestMode {
402 Hrtf_Default = 0,
403 Hrtf_Enable = 1,
404 Hrtf_Disable = 2,
407 void aluInit(void);
409 void aluInitMixer(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 void UpdateContextProps(ALCcontext *context);
513 extern MixerFunc MixSamples;
515 extern ALfloat ConeScale;
516 extern ALfloat ZScale;
517 extern ALboolean OverrideReverbSpeedOfSound;
519 #ifdef __cplusplus
521 #endif
523 #endif