17 #include "math_defs.h"
18 #include "filters/defs.h"
19 #include "filters/nfc.h"
22 enum class DistanceModel
;
24 #define MAX_PITCH (255)
26 /* Maximum number of samples to pad on either end of a buffer for resampling.
27 * Note that both the beginning and end need padding!
29 #define MAX_RESAMPLE_PADDING 24
38 struct ALbufferlistitem
;
43 #define DITHER_RNG_SEED 22222
47 SpatializeOff
= AL_FALSE
,
48 SpatializeOn
= AL_TRUE
,
49 SpatializeAuto
= AL_AUTO_SOFT
59 ResamplerMax
= BSinc24Resampler
61 extern enum Resampler ResamplerDefault
;
63 /* The number of distinct scale and phase intervals within the bsinc filter
66 #define BSINC_SCALE_BITS 4
67 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
68 #define BSINC_PHASE_BITS 4
69 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
71 /* Interpolator state. Kind of a misnomer since the interpolator itself is
72 * stateless. This just keeps it from having to recompute scale-related
73 * mappings for every sample.
75 typedef struct BsincState
{
76 ALfloat sf
; /* Scale interpolation factor. */
77 ALsizei m
; /* Coefficient count. */
78 ALsizei l
; /* Left coefficient offset. */
79 /* Filter coefficients, followed by the scale, phase, and scale-phase
80 * delta coefficients. Starting at phase index 0, each subsequent phase
81 * index follows contiguously.
83 const ALfloat
*filter
;
86 typedef union InterpState
{
90 typedef const ALfloat
* (*ResamplerFunc
)(const InterpState
*state
,
91 const ALfloat
*RESTRICT src
, ALsizei frac
, ALint increment
,
92 ALfloat
*RESTRICT dst
, ALsizei dstlen
95 void BsincPrepare(const ALuint increment
, BsincState
*state
, const struct BSincTable
*table
);
97 extern const struct BSincTable bsinc12
;
98 extern const struct BSincTable bsinc24
;
105 AF_BandPass
= AF_LowPass
| AF_HighPass
109 typedef struct MixHrtfParams
{
110 const ALfloat (*Coeffs
)[2];
117 typedef struct DirectParams
{
118 BiquadFilter LowPass
;
119 BiquadFilter HighPass
;
121 NfcFilter NFCtrlFilter
;
130 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
131 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
135 typedef struct SendParams
{
136 BiquadFilter LowPass
;
137 BiquadFilter HighPass
;
140 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
141 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
146 struct ALvoiceProps
{
147 ATOMIC(struct ALvoiceProps
*) next
;
158 ALfloat RolloffFactor
;
161 ALfloat Direction
[3];
162 ALfloat Orientation
[2][3];
163 ALboolean HeadRelative
;
164 DistanceModel mDistanceModel
;
165 enum Resampler Resampler
;
166 ALboolean DirectChannels
;
167 enum SpatializeMode SpatializeMode
;
169 ALboolean DryGainHFAuto
;
170 ALboolean WetGainAuto
;
171 ALboolean WetGainHFAuto
;
174 ALfloat AirAbsorptionFactor
;
175 ALfloat RoomRolloffFactor
;
176 ALfloat DopplerFactor
;
178 ALfloat StereoPan
[2];
182 /** Direct filter and auxiliary send info. */
191 struct ALeffectslot
*Slot
;
200 #define VOICE_IS_STATIC (1<<0)
201 #define VOICE_IS_FADING (1<<1) /* Fading sources use gain stepping for smooth transitions. */
202 #define VOICE_HAS_HRTF (1<<2)
203 #define VOICE_HAS_NFC (1<<3)
205 typedef struct ALvoice
{
206 struct ALvoiceProps
*Props
;
208 ATOMIC(struct ALvoiceProps
*) Update
;
210 ATOMIC(struct ALsource
*) Source
;
211 ATOMIC(bool) Playing
;
214 * Source offset in samples, relative to the currently playing buffer, NOT
215 * the whole queue, and the fractional (fixed-point) offset to the next
218 ATOMIC(ALuint
) position
;
219 ATOMIC(ALsizei
) position_fraction
;
221 /* Current buffer queue item being played. */
222 ATOMIC(struct ALbufferlistitem
*) current_buffer
;
224 /* Buffer queue item to loop to at end of queue (will be NULL for non-
227 ATOMIC(struct ALbufferlistitem
*) loop_buffer
;
230 * Number of channels and bytes-per-sample for the attached source's
236 /** Current target parameters used for mixing. */
239 ResamplerFunc Resampler
;
243 ALuint Offset
; /* Number of output samples mixed since starting. */
245 alignas(16) ALfloat PrevSamples
[MAX_INPUT_CHANNELS
][MAX_RESAMPLE_PADDING
];
247 InterpState ResampleState
;
251 DirectParams Params
[MAX_INPUT_CHANNELS
];
253 ALfloat (*Buffer
)[BUFFERSIZE
];
255 ALsizei ChannelsPerOrder
[MAX_AMBI_ORDER
+1];
260 SendParams Params
[MAX_INPUT_CHANNELS
];
262 ALfloat (*Buffer
)[BUFFERSIZE
];
267 void DeinitVoice(ALvoice
*voice
);
270 typedef void (*MixerFunc
)(const ALfloat
*data
, ALsizei OutChans
,
271 ALfloat (*RESTRICT OutBuffer
)[BUFFERSIZE
], ALfloat
*CurrentGains
,
272 const ALfloat
*TargetGains
, ALsizei Counter
, ALsizei OutPos
,
274 typedef void (*RowMixerFunc
)(ALfloat
*OutBuffer
, const ALfloat
*gains
,
275 const ALfloat (*RESTRICT data
)[BUFFERSIZE
], ALsizei InChans
,
276 ALsizei InPos
, ALsizei BufferSize
);
277 typedef void (*HrtfMixerFunc
)(ALfloat
*RESTRICT LeftOut
, ALfloat
*RESTRICT RightOut
,
278 const ALfloat
*data
, ALsizei Offset
, ALsizei OutPos
,
279 const ALsizei IrSize
, MixHrtfParams
*hrtfparams
,
280 HrtfState
*hrtfstate
, ALsizei BufferSize
);
281 typedef void (*HrtfMixerBlendFunc
)(ALfloat
*RESTRICT LeftOut
, ALfloat
*RESTRICT RightOut
,
282 const ALfloat
*data
, ALsizei Offset
, ALsizei OutPos
,
283 const ALsizei IrSize
, const HrtfParams
*oldparams
,
284 MixHrtfParams
*newparams
, HrtfState
*hrtfstate
,
286 typedef void (*HrtfDirectMixerFunc
)(ALfloat
*RESTRICT LeftOut
, ALfloat
*RESTRICT RightOut
,
287 const ALfloat
*data
, ALsizei Offset
, const ALsizei IrSize
,
288 const ALfloat (*RESTRICT Coeffs
)[2],
289 ALfloat (*RESTRICT Values
)[2], ALsizei BufferSize
);
292 #define GAIN_MIX_MAX (16.0f) /* +24dB */
294 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
296 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
297 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
299 /* Target gain for the reverb decay feedback reaching the decay time. */
300 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
302 #define FRACTIONBITS (12)
303 #define FRACTIONONE (1<<FRACTIONBITS)
304 #define FRACTIONMASK (FRACTIONONE-1)
307 inline ALfloat
minf(ALfloat a
, ALfloat b
) noexcept
308 { return ((a
> b
) ? b
: a
); }
309 inline ALfloat
maxf(ALfloat a
, ALfloat b
) noexcept
310 { return ((a
> b
) ? a
: b
); }
311 inline ALfloat
clampf(ALfloat val
, ALfloat min
, ALfloat max
) noexcept
312 { return minf(max
, maxf(min
, val
)); }
314 inline ALdouble
mind(ALdouble a
, ALdouble b
) noexcept
315 { return ((a
> b
) ? b
: a
); }
316 inline ALdouble
maxd(ALdouble a
, ALdouble b
) noexcept
317 { return ((a
> b
) ? a
: b
); }
318 inline ALdouble
clampd(ALdouble val
, ALdouble min
, ALdouble max
) noexcept
319 { return mind(max
, maxd(min
, val
)); }
321 inline ALuint
minu(ALuint a
, ALuint b
) noexcept
322 { return ((a
> b
) ? b
: a
); }
323 inline ALuint
maxu(ALuint a
, ALuint b
) noexcept
324 { return ((a
> b
) ? a
: b
); }
325 inline ALuint
clampu(ALuint val
, ALuint min
, ALuint max
) noexcept
326 { return minu(max
, maxu(min
, val
)); }
328 inline ALint
mini(ALint a
, ALint b
) noexcept
329 { return ((a
> b
) ? b
: a
); }
330 inline ALint
maxi(ALint a
, ALint b
) noexcept
331 { return ((a
> b
) ? a
: b
); }
332 inline ALint
clampi(ALint val
, ALint min
, ALint max
) noexcept
333 { return mini(max
, maxi(min
, val
)); }
335 inline ALint64
mini64(ALint64 a
, ALint64 b
) noexcept
336 { return ((a
> b
) ? b
: a
); }
337 inline ALint64
maxi64(ALint64 a
, ALint64 b
) noexcept
338 { return ((a
> b
) ? a
: b
); }
339 inline ALint64
clampi64(ALint64 val
, ALint64 min
, ALint64 max
) noexcept
340 { return mini64(max
, maxi64(min
, val
)); }
342 inline ALuint64
minu64(ALuint64 a
, ALuint64 b
) noexcept
343 { return ((a
> b
) ? b
: a
); }
344 inline ALuint64
maxu64(ALuint64 a
, ALuint64 b
) noexcept
345 { return ((a
> b
) ? a
: b
); }
346 inline ALuint64
clampu64(ALuint64 val
, ALuint64 min
, ALuint64 max
) noexcept
347 { return minu64(max
, maxu64(min
, val
)); }
349 inline size_t minz(size_t a
, size_t b
) noexcept
350 { return ((a
> b
) ? b
: a
); }
351 inline size_t maxz(size_t a
, size_t b
) noexcept
352 { return ((a
> b
) ? a
: b
); }
353 inline size_t clampz(size_t val
, size_t min
, size_t max
) noexcept
354 { return minz(max
, maxz(min
, val
)); }
357 inline ALfloat
lerp(ALfloat val1
, ALfloat val2
, ALfloat mu
) noexcept
359 return val1
+ (val2
-val1
)*mu
;
361 inline ALfloat
cubic(ALfloat val1
, ALfloat val2
, ALfloat val3
, ALfloat val4
, ALfloat mu
) noexcept
363 ALfloat mu2
= mu
*mu
, mu3
= mu2
*mu
;
364 ALfloat a0
= -0.5f
*mu3
+ mu2
+ -0.5f
*mu
;
365 ALfloat a1
= 1.5f
*mu3
+ -2.5f
*mu2
+ 1.0f
;
366 ALfloat a2
= -1.5f
*mu3
+ 2.0f
*mu2
+ 0.5f
*mu
;
367 ALfloat a3
= 0.5f
*mu3
+ -0.5f
*mu2
;
368 return val1
*a0
+ val2
*a1
+ val3
*a2
+ val4
*a3
;
372 enum HrtfRequestMode
{
380 void aluInitMixer(void);
382 ResamplerFunc
SelectResampler(enum Resampler resampler
);
386 * Set up the appropriate panning method and mixing method given the device
389 void aluInitRenderer(ALCdevice
*device
, ALint hrtf_id
, enum HrtfRequestMode hrtf_appreq
, enum HrtfRequestMode hrtf_userreq
);
391 void aluInitEffectPanning(struct ALeffectslot
*slot
);
393 void aluSelectPostProcess(ALCdevice
*device
);
396 * Calculates ambisonic encoder coefficients using the X, Y, and Z direction
397 * components, which must represent a normalized (unit length) vector, and the
398 * spread is the angular width of the sound (0...tau).
400 * NOTE: The components use ambisonic coordinates. As a result:
402 * Ambisonic Y = OpenAL -X
403 * Ambisonic Z = OpenAL Y
404 * Ambisonic X = OpenAL -Z
406 * The components are ordered such that OpenAL's X, Y, and Z are the first,
407 * second, and third parameters respectively -- simply negate X and Z.
409 void CalcAmbiCoeffs(const ALfloat y
, const ALfloat z
, const ALfloat x
, const ALfloat spread
,
410 ALfloat coeffs
[MAX_AMBI_COEFFS
]);
413 * CalcDirectionCoeffs
415 * Calculates ambisonic coefficients based on an OpenAL direction vector. The
416 * vector must be normalized (unit length), and the spread is the angular width
417 * of the sound (0...tau).
419 inline void CalcDirectionCoeffs(const ALfloat dir
[3], ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
])
421 /* Convert from OpenAL coords to Ambisonics. */
422 CalcAmbiCoeffs(-dir
[0], dir
[1], -dir
[2], spread
, coeffs
);
428 * Calculates ambisonic coefficients based on azimuth and elevation. The
429 * azimuth and elevation parameters are in radians, going right and up
432 inline void CalcAngleCoeffs(ALfloat azimuth
, ALfloat elevation
, ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
])
434 ALfloat x
= -sinf(azimuth
) * cosf(elevation
);
435 ALfloat y
= sinf(elevation
);
436 ALfloat z
= cosf(azimuth
) * cosf(elevation
);
438 CalcAmbiCoeffs(x
, y
, z
, spread
, coeffs
);
444 * Scales the given azimuth toward the side (+/- pi/2 radians) for positions in
447 inline float ScaleAzimuthFront(float azimuth
, float scale
)
449 ALfloat sign
= copysignf(1.0f
, azimuth
);
450 if(!(fabsf(azimuth
) > F_PI_2
))
451 return minf(fabsf(azimuth
) * scale
, F_PI_2
) * sign
;
456 void ComputePanningGainsMC(const ChannelConfig
*chancoeffs
, ALsizei numchans
, ALsizei numcoeffs
, const ALfloat
*RESTRICT coeffs
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
]);
457 void ComputePanningGainsBF(const BFChannelConfig
*chanmap
, ALsizei numchans
, const ALfloat
*RESTRICT coeffs
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
]);
462 * Computes panning gains using the given channel decoder coefficients and the
463 * pre-calculated direction or angle coefficients. For B-Format sources, the
464 * coeffs are a 'slice' of a transform matrix for the input channel, used to
465 * scale and orient the sound samples.
467 inline void ComputePanGains(const MixParams
*dry
, const ALfloat
*RESTRICT coeffs
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
469 if(dry
->CoeffCount
> 0)
470 ComputePanningGainsMC(dry
->Ambi
.Coeffs
, dry
->NumChannels
, dry
->CoeffCount
,
471 coeffs
, ingain
, gains
);
473 ComputePanningGainsBF(dry
->Ambi
.Map
, dry
->NumChannels
, coeffs
, ingain
, gains
);
477 ALboolean
MixSource(struct ALvoice
*voice
, ALuint SourceID
, ALCcontext
*Context
, ALsizei SamplesToDo
);
479 void aluMixData(ALCdevice
*device
, ALvoid
*OutBuffer
, ALsizei NumSamples
);
480 /* Caller must lock the device, and the mixer must not be running. */
481 void aluHandleDisconnect(ALCdevice
*device
, const char *msg
, ...) DECL_FORMAT(printf
, 2, 3);
483 extern MixerFunc MixSamples
;
484 extern RowMixerFunc MixRowSamples
;
486 extern ALfloat ConeScale
;
487 extern ALfloat ZScale
;
488 extern ALboolean OverrideReverbSpeedOfSound
;