16 #include "alAuxEffectSlot.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
39 struct ALbufferlistitem
;
44 #define DITHER_RNG_SEED 22222
48 SpatializeOff
= AL_FALSE
,
49 SpatializeOn
= AL_TRUE
,
50 SpatializeAuto
= AL_AUTO_SOFT
60 ResamplerMax
= BSinc24Resampler
62 extern enum Resampler ResamplerDefault
;
64 /* The number of distinct scale and phase intervals within the bsinc filter
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
;
87 typedef struct Sinc4State
{
88 const ALfloat (*filter
)[4];
91 typedef union 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];
111 inline void aluVectorSet(aluVector
*vector
, ALfloat x
, ALfloat y
, ALfloat z
, ALfloat w
)
120 typedef union aluMatrixf
{
121 alignas(16) ALfloat m
[4][4];
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
);
150 AF_BandPass
= AF_LowPass
| AF_HighPass
154 typedef struct MixHrtfParams
{
155 const ALfloat (*Coeffs
)[2];
162 typedef struct DirectParams
{
163 ALfilterState LowPass
;
164 ALfilterState HighPass
;
166 NfcFilter NFCtrlFilter
[MAX_AMBI_ORDER
];
175 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
176 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
180 typedef struct SendParams
{
181 ALfilterState LowPass
;
182 ALfilterState HighPass
;
185 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
186 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
191 struct ALvoiceProps
{
192 ATOMIC(struct ALvoiceProps
*) next
;
203 ALfloat RolloffFactor
;
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
;
219 ALfloat AirAbsorptionFactor
;
220 ALfloat RoomRolloffFactor
;
221 ALfloat DopplerFactor
;
223 ALfloat StereoPan
[2];
227 /** Direct filter and auxiliary send info. */
236 struct ALeffectslot
*Slot
;
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
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-
272 ATOMIC(struct ALbufferlistitem
*) loop_buffer
;
275 * Number of channels and bytes-per-sample for the attached source's
281 /** Current target parameters used for mixing. */
284 ResamplerFunc Resampler
;
288 ALuint Offset
; /* Number of output samples mixed since starting. */
290 alignas(16) ALfloat PrevSamples
[MAX_INPUT_CHANNELS
][MAX_PRE_SAMPLES
];
292 InterpState ResampleState
;
295 enum ActiveFilters FilterType
;
296 DirectParams Params
[MAX_INPUT_CHANNELS
];
298 ALfloat (*Buffer
)[BUFFERSIZE
];
300 ALsizei ChannelsPerOrder
[MAX_AMBI_ORDER
+1];
304 enum ActiveFilters FilterType
;
305 SendParams Params
[MAX_INPUT_CHANNELS
];
307 ALfloat (*Buffer
)[BUFFERSIZE
];
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
,
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
,
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
{
409 void aluInitMixer(void);
411 RowMixerFunc
SelectRowMixer(void);
412 ResamplerFunc
SelectResampler(enum Resampler resampler
);
416 * Set up the appropriate panning method and mixing method given the device
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
430 void CalcDirectionCoeffs(const ALfloat dir
[3], ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
]);
435 * Calculates ambisonic coefficients based on azimuth and elevation. The
436 * azimuth and elevation parameters are in radians, going right and up
439 inline void CalcAngleCoeffs(ALfloat azimuth
, ALfloat elevation
, ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
])
442 sinf(azimuth
) * cosf(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); \
468 ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
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);\
483 ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
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); \
499 ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
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
;