Free Electron
alu.h
1 #ifndef _ALU_H_
2 #define _ALU_H_
3 
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
12 
13 #include "alMain.h"
14 #include "alBuffer.h"
15 
16 #include "hrtf.h"
17 #include "align.h"
18 #include "math_defs.h"
19 #include "filters/defs.h"
20 #include "filters/nfc.h"
21 
22 
23 #define MAX_PITCH (255)
24 
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!
27  */
28 #define MAX_RESAMPLE_PADDING 24
29 
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 struct BSincTable;
36 struct ALsource;
37 struct ALbufferlistitem;
38 struct ALvoice;
39 struct ALeffectslot;
40 
41 
42 #define DITHER_RNG_SEED 22222
43 
44 
45 enum SpatializeMode {
46  SpatializeOff = AL_FALSE,
47  SpatializeOn = AL_TRUE,
48  SpatializeAuto = AL_AUTO_SOFT
49 };
50 
51 enum Resampler {
52  PointResampler,
53  LinearResampler,
54  FIR4Resampler,
55  BSinc12Resampler,
56  BSinc24Resampler,
57 
58  ResamplerMax = BSinc24Resampler
59 };
60 extern enum Resampler ResamplerDefault;
61 
62 /* The number of distinct scale and phase intervals within the bsinc filter
63  * table.
64  */
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)
69 
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.
73  */
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.
81  */
82  const ALfloat *filter;
83 } BsincState;
84 
85 typedef union InterpState {
86  BsincState bsinc;
87 } InterpState;
88 
89 typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
90  const ALfloat *restrict src, ALsizei frac, ALint increment,
91  ALfloat *restrict dst, ALsizei dstlen
92 );
93 
94 void BsincPrepare(const ALuint increment, BsincState *state, const struct BSincTable *table);
95 
96 extern const struct BSincTable bsinc12;
97 extern const struct BSincTable bsinc24;
98 
99 
100 typedef union aluVector {
101  alignas(16) ALfloat v[4];
102 } aluVector;
103 
104 inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
105 {
106  vector->v[0] = x;
107  vector->v[1] = y;
108  vector->v[2] = z;
109  vector->v[3] = w;
110 }
111 
112 
113 typedef union aluMatrixf {
114  alignas(16) ALfloat m[4][4];
115 } aluMatrixf;
116 extern const aluMatrixf IdentityMatrixf;
117 
118 inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
119  ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
120 {
121  matrix->m[row][0] = m0;
122  matrix->m[row][1] = m1;
123  matrix->m[row][2] = m2;
124  matrix->m[row][3] = m3;
125 }
126 
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)
131 {
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);
136 }
137 
138 
139 enum ActiveFilters {
140  AF_None = 0,
141  AF_LowPass = 1,
142  AF_HighPass = 2,
143  AF_BandPass = AF_LowPass | AF_HighPass
144 };
145 
146 
147 typedef struct MixHrtfParams {
148  const ALfloat (*Coeffs)[2];
149  ALsizei Delay[2];
150  ALfloat Gain;
151  ALfloat GainStep;
152 } MixHrtfParams;
153 
154 
155 typedef struct DirectParams {
156  BiquadFilter LowPass;
157  BiquadFilter HighPass;
158 
159  NfcFilter NFCtrlFilter;
160 
161  struct {
162  HrtfParams Old;
163  HrtfParams Target;
164  HrtfState State;
165  } Hrtf;
166 
167  struct {
168  ALfloat Current[MAX_OUTPUT_CHANNELS];
169  ALfloat Target[MAX_OUTPUT_CHANNELS];
170  } Gains;
171 } DirectParams;
172 
173 typedef struct SendParams {
174  BiquadFilter LowPass;
175  BiquadFilter HighPass;
176 
177  struct {
178  ALfloat Current[MAX_OUTPUT_CHANNELS];
179  ALfloat Target[MAX_OUTPUT_CHANNELS];
180  } Gains;
181 } SendParams;
182 
183 
184 struct ALvoiceProps {
185  ATOMIC(struct ALvoiceProps*) next;
186 
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;
206 
207  ALboolean DryGainHFAuto;
208  ALboolean WetGainAuto;
209  ALboolean WetGainHFAuto;
210  ALfloat OuterGainHF;
211 
212  ALfloat AirAbsorptionFactor;
213  ALfloat RoomRolloffFactor;
214  ALfloat DopplerFactor;
215 
216  ALfloat StereoPan[2];
217 
218  ALfloat Radius;
219 
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[];
236 };
237 
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)
242 
243 typedef struct ALvoice {
244  struct ALvoiceProps *Props;
245 
246  ATOMIC(struct ALvoiceProps*) Update;
247 
248  ATOMIC(struct ALsource*) Source;
249  ATOMIC(bool) Playing;
250 
251  /**
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.
255  */
256  ATOMIC(ALuint) position;
257  ATOMIC(ALsizei) position_fraction;
258 
259  /* Current buffer queue item being played. */
260  ATOMIC(struct ALbufferlistitem*) current_buffer;
261 
262  /* Buffer queue item to loop to at end of queue (will be NULL for non-
263  * looping voices).
264  */
265  ATOMIC(struct ALbufferlistitem*) loop_buffer;
266 
267  /**
268  * Number of channels and bytes-per-sample for the attached source's
269  * buffer(s).
270  */
271  ALsizei NumChannels;
272  ALsizei SampleSize;
273 
274  /** Current target parameters used for mixing. */
275  ALint Step;
276 
277  ResamplerFunc Resampler;
278 
279  ALuint Flags;
280 
281  ALuint Offset; /* Number of output samples mixed since starting. */
282 
283  alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_RESAMPLE_PADDING];
284 
285  InterpState ResampleState;
286 
287  struct {
288  enum ActiveFilters FilterType;
289  DirectParams Params[MAX_INPUT_CHANNELS];
290 
291  ALfloat (*Buffer)[BUFFERSIZE];
292  ALsizei Channels;
293  ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
294  } Direct;
295 
296  struct {
297  enum ActiveFilters FilterType;
298  SendParams Params[MAX_INPUT_CHANNELS];
299 
300  ALfloat (*Buffer)[BUFFERSIZE];
301  ALsizei Channels;
302  } Send[];
303 } ALvoice;
304 
305 void DeinitVoice(ALvoice *voice);
306 
307 
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);
328 
329 
330 #define GAIN_MIX_MAX (16.0f) /* +24dB */
331 
332 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
333 
334 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
335 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
336 
337 /* Target gain for the reverb decay feedback reaching the decay time. */
338 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
339 
340 #define FRACTIONBITS (12)
341 #define FRACTIONONE (1<<FRACTIONBITS)
342 #define FRACTIONMASK (FRACTIONONE-1)
343 
344 
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)); }
351 
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)); }
358 
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)); }
365 
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)); }
372 
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)); }
379 
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)); }
386 
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)); }
393 
394 
395 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
396 {
397  return val1 + (val2-val1)*mu;
398 }
399 inline ALfloat cubic(ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat mu)
400 {
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;
407 }
408 
409 
410 enum HrtfRequestMode {
411  Hrtf_Default = 0,
412  Hrtf_Enable = 1,
413  Hrtf_Disable = 2,
414 };
415 
416 void aluInit(void);
417 
418 void aluInitMixer(void);
419 
420 ResamplerFunc SelectResampler(enum Resampler resampler);
421 
422 /* aluInitRenderer
423  *
424  * Set up the appropriate panning method and mixing method given the device
425  * properties.
426  */
427 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
428 
429 void aluInitEffectPanning(struct ALeffectslot *slot);
430 
431 void aluSelectPostProcess(ALCdevice *device);
432 
433 /**
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).
437  *
438  * NOTE: The components use ambisonic coordinates. As a result:
439  *
440  * Ambisonic Y = OpenAL -X
441  * Ambisonic Z = OpenAL Y
442  * Ambisonic X = OpenAL -Z
443  *
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.
446  */
447 void CalcAmbiCoeffs(const ALfloat y, const ALfloat z, const ALfloat x, const ALfloat spread,
448  ALfloat coeffs[MAX_AMBI_COEFFS]);
449 
450 /**
451  * CalcDirectionCoeffs
452  *
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).
456  */
457 inline void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
458 {
459  /* Convert from OpenAL coords to Ambisonics. */
460  CalcAmbiCoeffs(-dir[0], dir[1], -dir[2], spread, coeffs);
461 }
462 
463 /**
464  * CalcAngleCoeffs
465  *
466  * Calculates ambisonic coefficients based on azimuth and elevation. The
467  * azimuth and elevation parameters are in radians, going right and up
468  * respectively.
469  */
470 inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
471 {
472  ALfloat x = -sinf(azimuth) * cosf(elevation);
473  ALfloat y = sinf(elevation);
474  ALfloat z = cosf(azimuth) * cosf(elevation);
475 
476  CalcAmbiCoeffs(x, y, z, spread, coeffs);
477 }
478 
479 /**
480  * ScaleAzimuthFront
481  *
482  * Scales the given azimuth toward the side (+/- pi/2 radians) for positions in
483  * front.
484  */
485 inline float ScaleAzimuthFront(float azimuth, float scale)
486 {
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;
491 }
492 
493 
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]);
496 
497 /**
498  * ComputePanGains
499  *
500  * Computes panning gains using the given channel decoder coefficients and the
501  * pre-calculated direction or angle coefficients. For B-Format sources, the
502  * coeffs are a 'slice' of a transform matrix for the input channel, used to
503  * scale and orient the sound samples.
504  */
505 inline void ComputePanGains(const MixParams *dry, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
506 {
507  if(dry->CoeffCount > 0)
508  ComputePanningGainsMC(dry->Ambi.Coeffs, dry->NumChannels, dry->CoeffCount,
509  coeffs, ingain, gains);
510  else
511  ComputePanningGainsBF(dry->Ambi.Map, dry->NumChannels, coeffs, ingain, gains);
512 }
513 
514 
515 ALboolean MixSource(struct ALvoice *voice, ALuint SourceID, ALCcontext *Context, ALsizei SamplesToDo);
516 
517 void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples);
518 /* Caller must lock the device, and the mixer must not be running. */
519 void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3);
520 
521 void UpdateContextProps(ALCcontext *context);
522 
523 extern MixerFunc MixSamples;
524 extern RowMixerFunc MixRowSamples;
525 
526 extern ALfloat ConeScale;
527 extern ALfloat ZScale;
528 extern ALboolean OverrideReverbSpeedOfSound;
529 
530 #ifdef __cplusplus
531 }
532 #endif
533 
534 #endif