Use ALsizei for the fir4 resampler fraction
[openal-soft.git] / OpenAL32 / Include / alu.h
blob6c3f3499750563cc602f1ab854f75ab657d4adf8
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 ALsourceProps;
39 struct ALbufferlistitem;
40 struct ALvoice;
41 struct ALeffectslot;
44 /* The number of distinct scale and phase intervals within the filter table. */
45 #define BSINC_SCALE_BITS 4
46 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
47 #define BSINC_PHASE_BITS 4
48 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
50 /* Interpolator state. Kind of a misnomer since the interpolator itself is
51 * stateless. This just keeps it from having to recompute scale-related
52 * mappings for every sample.
54 typedef struct BsincState {
55 ALfloat sf; /* Scale interpolation factor. */
56 ALuint m; /* Coefficient count. */
57 ALint l; /* Left coefficient offset. */
58 struct {
59 const ALfloat *filter; /* Filter coefficients. */
60 const ALfloat *scDelta; /* Scale deltas. */
61 const ALfloat *phDelta; /* Phase deltas. */
62 const ALfloat *spDelta; /* Scale-phase deltas. */
63 } coeffs[BSINC_PHASE_COUNT];
64 } BsincState;
66 typedef union InterpState {
67 BsincState bsinc;
68 } InterpState;
71 typedef union aluVector {
72 alignas(16) ALfloat v[4];
73 } aluVector;
75 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
77 vector->v[0] = x;
78 vector->v[1] = y;
79 vector->v[2] = z;
80 vector->v[3] = w;
84 typedef union aluMatrixf {
85 alignas(16) ALfloat m[4][4];
86 } aluMatrixf;
87 extern const aluMatrixf IdentityMatrixf;
89 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
90 ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
92 matrix->m[row][0] = m0;
93 matrix->m[row][1] = m1;
94 matrix->m[row][2] = m2;
95 matrix->m[row][3] = m3;
98 inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
99 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
100 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
101 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
103 aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
104 aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
105 aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
106 aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
110 enum ActiveFilters {
111 AF_None = 0,
112 AF_LowPass = 1,
113 AF_HighPass = 2,
114 AF_BandPass = AF_LowPass | AF_HighPass
118 typedef struct MixHrtfParams {
119 const ALfloat (*Coeffs)[2];
120 ALsizei Delay[2];
121 ALfloat Gain;
122 ALfloat GainStep;
123 } MixHrtfParams;
126 typedef struct DirectParams {
127 enum ActiveFilters FilterType;
128 ALfilterState LowPass;
129 ALfilterState HighPass;
131 NfcFilter NFCtrlFilter[MAX_AMBI_ORDER];
133 struct {
134 HrtfParams Old;
135 HrtfParams Target;
136 HrtfState State;
137 } Hrtf;
139 struct {
140 ALfloat Current[MAX_OUTPUT_CHANNELS];
141 ALfloat Target[MAX_OUTPUT_CHANNELS];
142 } Gains;
143 } DirectParams;
145 typedef struct SendParams {
146 enum ActiveFilters FilterType;
147 ALfilterState LowPass;
148 ALfilterState HighPass;
150 struct {
151 ALfloat Current[MAX_OUTPUT_CHANNELS];
152 ALfloat Target[MAX_OUTPUT_CHANNELS];
153 } Gains;
154 } SendParams;
156 /* If not 'moving', gain targets are used directly without fading. */
157 #define VOICE_IS_MOVING (1<<0)
158 #define VOICE_IS_HRTF (1<<1)
159 #define VOICE_HAS_NFC (1<<2)
161 typedef struct ALvoice {
162 struct ALsourceProps *Props;
164 ATOMIC(struct ALsource*) Source;
165 ATOMIC(bool) Playing;
167 /* Current buffer queue item being played. */
168 ATOMIC(struct ALbufferlistitem*) current_buffer;
171 * Source offset in samples, relative to the currently playing buffer, NOT
172 * the whole queue, and the fractional (fixed-point) offset to the next
173 * sample.
175 ATOMIC(ALuint) position;
176 ATOMIC(ALsizei) position_fraction;
179 * Number of channels and bytes-per-sample for the attached source's
180 * buffer(s).
182 ALsizei NumChannels;
183 ALsizei SampleSize;
185 /** Current target parameters used for mixing. */
186 ALint Step;
188 ALuint Flags;
190 ALuint Offset; /* Number of output samples mixed since starting. */
192 alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
194 InterpState ResampleState;
196 struct {
197 DirectParams Params[MAX_INPUT_CHANNELS];
199 ALfloat (*Buffer)[BUFFERSIZE];
200 ALsizei Channels;
201 ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
202 } Direct;
204 struct {
205 SendParams Params[MAX_INPUT_CHANNELS];
207 ALfloat (*Buffer)[BUFFERSIZE];
208 ALsizei Channels;
209 } Send[];
210 } ALvoice;
213 typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
214 const ALfloat *restrict src, ALsizei frac, ALint increment,
215 ALfloat *restrict dst, ALsizei dstlen
218 typedef void (*MixerFunc)(const ALfloat *data, ALsizei OutChans,
219 ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
220 const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
221 ALsizei BufferSize);
222 typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
223 const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
224 ALsizei InPos, ALsizei BufferSize);
225 typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
226 const ALfloat *data, ALsizei Offset, ALsizei OutPos,
227 const ALsizei IrSize, MixHrtfParams *hrtfparams,
228 HrtfState *hrtfstate, ALsizei BufferSize);
229 typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
230 const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
231 const ALfloat (*restrict Coeffs)[2],
232 ALfloat (*restrict Values)[2], ALsizei BufferSize);
235 #define GAIN_MIX_MAX (16.0f) /* +24dB */
237 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
239 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
240 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
242 #define FRACTIONBITS (12)
243 #define FRACTIONONE (1<<FRACTIONBITS)
244 #define FRACTIONMASK (FRACTIONONE-1)
247 inline ALfloat minf(ALfloat a, ALfloat b)
248 { return ((a > b) ? b : a); }
249 inline ALfloat maxf(ALfloat a, ALfloat b)
250 { return ((a > b) ? a : b); }
251 inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
252 { return minf(max, maxf(min, val)); }
254 inline ALdouble mind(ALdouble a, ALdouble b)
255 { return ((a > b) ? b : a); }
256 inline ALdouble maxd(ALdouble a, ALdouble b)
257 { return ((a > b) ? a : b); }
258 inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
259 { return mind(max, maxd(min, val)); }
261 inline ALuint minu(ALuint a, ALuint b)
262 { return ((a > b) ? b : a); }
263 inline ALuint maxu(ALuint a, ALuint b)
264 { return ((a > b) ? a : b); }
265 inline ALuint clampu(ALuint val, ALuint min, ALuint max)
266 { return minu(max, maxu(min, val)); }
268 inline ALint mini(ALint a, ALint b)
269 { return ((a > b) ? b : a); }
270 inline ALint maxi(ALint a, ALint b)
271 { return ((a > b) ? a : b); }
272 inline ALint clampi(ALint val, ALint min, ALint max)
273 { return mini(max, maxi(min, val)); }
275 inline ALint64 mini64(ALint64 a, ALint64 b)
276 { return ((a > b) ? b : a); }
277 inline ALint64 maxi64(ALint64 a, ALint64 b)
278 { return ((a > b) ? a : b); }
279 inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
280 { return mini64(max, maxi64(min, val)); }
282 inline ALuint64 minu64(ALuint64 a, ALuint64 b)
283 { return ((a > b) ? b : a); }
284 inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
285 { return ((a > b) ? a : b); }
286 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
287 { return minu64(max, maxu64(min, val)); }
290 extern alignas(16) const ALfloat bsincTab[18840];
291 extern alignas(16) const ALfloat sinc4Tab[FRACTIONONE][4];
294 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
296 return val1 + (val2-val1)*mu;
298 inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALsizei frac)
300 return sinc4Tab[frac][0]*val0 + sinc4Tab[frac][1]*val1 +
301 sinc4Tab[frac][2]*val2 + sinc4Tab[frac][3]*val3;
305 enum Resampler {
306 PointResampler,
307 LinearResampler,
308 FIR4Resampler,
309 BSincResampler,
311 ResamplerDefault = LinearResampler
314 enum HrtfRequestMode {
315 Hrtf_Default = 0,
316 Hrtf_Enable = 1,
317 Hrtf_Disable = 2,
321 void aluInitMixer(void);
323 MixerFunc SelectMixer(void);
324 RowMixerFunc SelectRowMixer(void);
325 ResamplerFunc SelectResampler(enum Resampler resampler);
327 /* aluInitRenderer
329 * Set up the appropriate panning method and mixing method given the device
330 * properties.
332 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
334 void aluInitEffectPanning(struct ALeffectslot *slot);
337 * CalcDirectionCoeffs
339 * Calculates ambisonic coefficients based on a direction vector. The vector
340 * must be normalized (unit length), and the spread is the angular width of the
341 * sound (0...tau).
343 void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
346 * CalcAngleCoeffs
348 * Calculates ambisonic coefficients based on azimuth and elevation. The
349 * azimuth and elevation parameters are in radians, going right and up
350 * respectively.
352 inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
354 ALfloat dir[3] = {
355 sinf(azimuth) * cosf(elevation),
356 sinf(elevation),
357 -cosf(azimuth) * cosf(elevation)
359 CalcDirectionCoeffs(dir, spread, coeffs);
363 * CalcAnglePairwiseCoeffs
365 * Calculates ambisonic coefficients based on azimuth and elevation. The
366 * azimuth and elevation parameters are in radians, going right and up
367 * respectively. This pairwise variant warps the result such that +30 azimuth
368 * is full right, and -30 azimuth is full left.
370 void CalcAnglePairwiseCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
373 * ComputeAmbientGains
375 * Computes channel gains for ambient, omni-directional sounds.
377 #define ComputeAmbientGains(b, g, o) do { \
378 if((b).CoeffCount > 0) \
379 ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o); \
380 else \
381 ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
382 } while (0)
383 void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
384 void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
387 * ComputePanningGains
389 * Computes panning gains using the given channel decoder coefficients and the
390 * pre-calculated direction or angle coefficients.
392 #define ComputePanningGains(b, c, g, o) do { \
393 if((b).CoeffCount > 0) \
394 ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\
395 else \
396 ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
397 } while (0)
398 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
399 void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
402 * ComputeFirstOrderGains
404 * Sets channel gains for a first-order ambisonics input channel. The matrix is
405 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
406 * orient the sound samples.
408 #define ComputeFirstOrderGains(b, m, g, o) do { \
409 if((b).CoeffCount > 0) \
410 ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o); \
411 else \
412 ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
413 } while (0)
414 void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
415 void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
418 ALboolean MixSource(struct ALvoice *voice, struct ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo);
420 void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
421 /* Caller must lock the device. */
422 void aluHandleDisconnect(ALCdevice *device);
424 extern ALfloat ConeScale;
425 extern ALfloat ZScale;
427 #ifdef __cplusplus
429 #endif
431 #endif