16 #include "alAuxEffectSlot.h"
20 #include "nfcfilter.h"
21 #include "math_defs.h"
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 ALint 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
;
101 typedef union aluVector
{
102 alignas(16) ALfloat v
[4];
105 inline void aluVectorSet(aluVector
*vector
, ALfloat x
, ALfloat y
, ALfloat z
, ALfloat w
)
114 typedef union aluMatrixf
{
115 alignas(16) ALfloat m
[4][4];
117 extern const aluMatrixf IdentityMatrixf
;
119 inline void aluMatrixfSetRow(aluMatrixf
*matrix
, ALuint row
,
120 ALfloat m0
, ALfloat m1
, ALfloat m2
, ALfloat m3
)
122 matrix
->m
[row
][0] = m0
;
123 matrix
->m
[row
][1] = m1
;
124 matrix
->m
[row
][2] = m2
;
125 matrix
->m
[row
][3] = m3
;
128 inline void aluMatrixfSet(aluMatrixf
*matrix
, ALfloat m00
, ALfloat m01
, ALfloat m02
, ALfloat m03
,
129 ALfloat m10
, ALfloat m11
, ALfloat m12
, ALfloat m13
,
130 ALfloat m20
, ALfloat m21
, ALfloat m22
, ALfloat m23
,
131 ALfloat m30
, ALfloat m31
, ALfloat m32
, ALfloat m33
)
133 aluMatrixfSetRow(matrix
, 0, m00
, m01
, m02
, m03
);
134 aluMatrixfSetRow(matrix
, 1, m10
, m11
, m12
, m13
);
135 aluMatrixfSetRow(matrix
, 2, m20
, m21
, m22
, m23
);
136 aluMatrixfSetRow(matrix
, 3, m30
, m31
, m32
, m33
);
144 AF_BandPass
= AF_LowPass
| AF_HighPass
148 typedef struct MixHrtfParams
{
149 const ALfloat (*Coeffs
)[2];
156 typedef struct DirectParams
{
157 ALfilterState LowPass
;
158 ALfilterState HighPass
;
160 NfcFilter NFCtrlFilter
[MAX_AMBI_ORDER
];
169 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
170 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
174 typedef struct SendParams
{
175 ALfilterState LowPass
;
176 ALfilterState HighPass
;
179 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
180 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
185 struct ALvoiceProps
{
186 ATOMIC(struct ALvoiceProps
*) next
;
197 ALfloat RolloffFactor
;
200 ALfloat Direction
[3];
201 ALfloat Orientation
[2][3];
202 ALboolean HeadRelative
;
203 enum DistanceModel DistanceModel
;
204 enum Resampler Resampler
;
205 ALboolean DirectChannels
;
206 enum SpatializeMode SpatializeMode
;
208 ALboolean DryGainHFAuto
;
209 ALboolean WetGainAuto
;
210 ALboolean WetGainHFAuto
;
213 ALfloat AirAbsorptionFactor
;
214 ALfloat RoomRolloffFactor
;
215 ALfloat DopplerFactor
;
217 ALfloat StereoPan
[2];
221 /** Direct filter and auxiliary send info. */
230 struct ALeffectslot
*Slot
;
239 #define VOICE_IS_STATIC (1<<0)
240 #define VOICE_IS_FADING (1<<1) /* Fading sources use gain stepping for smooth transitions. */
241 #define VOICE_HAS_HRTF (1<<2)
242 #define VOICE_HAS_NFC (1<<3)
244 typedef struct ALvoice
{
245 struct ALvoiceProps
*Props
;
247 ATOMIC(struct ALvoiceProps
*) Update
;
249 ATOMIC(struct ALsource
*) Source
;
250 ATOMIC(bool) Playing
;
253 * Source offset in samples, relative to the currently playing buffer, NOT
254 * the whole queue, and the fractional (fixed-point) offset to the next
257 ATOMIC(ALuint
) position
;
258 ATOMIC(ALsizei
) position_fraction
;
260 /* Current buffer queue item being played. */
261 ATOMIC(struct ALbufferlistitem
*) current_buffer
;
263 /* Buffer queue item to loop to at end of queue (will be NULL for non-
266 ATOMIC(struct ALbufferlistitem
*) loop_buffer
;
269 * Number of channels and bytes-per-sample for the attached source's
275 /** Current target parameters used for mixing. */
278 ResamplerFunc Resampler
;
282 ALuint Offset
; /* Number of output samples mixed since starting. */
284 alignas(16) ALfloat PrevSamples
[MAX_INPUT_CHANNELS
][MAX_RESAMPLE_PADDING
];
286 InterpState ResampleState
;
289 enum ActiveFilters FilterType
;
290 DirectParams Params
[MAX_INPUT_CHANNELS
];
292 ALfloat (*Buffer
)[BUFFERSIZE
];
294 ALsizei ChannelsPerOrder
[MAX_AMBI_ORDER
+1];
298 enum ActiveFilters FilterType
;
299 SendParams Params
[MAX_INPUT_CHANNELS
];
301 ALfloat (*Buffer
)[BUFFERSIZE
];
306 void DeinitVoice(ALvoice
*voice
);
309 typedef void (*MixerFunc
)(const ALfloat
*data
, ALsizei OutChans
,
310 ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALfloat
*CurrentGains
,
311 const ALfloat
*TargetGains
, ALsizei Counter
, ALsizei OutPos
,
313 typedef void (*RowMixerFunc
)(ALfloat
*OutBuffer
, const ALfloat
*gains
,
314 const ALfloat (*restrict data
)[BUFFERSIZE
], ALsizei InChans
,
315 ALsizei InPos
, ALsizei BufferSize
);
316 typedef void (*HrtfMixerFunc
)(ALfloat
*restrict LeftOut
, ALfloat
*restrict RightOut
,
317 const ALfloat
*data
, ALsizei Offset
, ALsizei OutPos
,
318 const ALsizei IrSize
, MixHrtfParams
*hrtfparams
,
319 HrtfState
*hrtfstate
, ALsizei BufferSize
);
320 typedef void (*HrtfMixerBlendFunc
)(ALfloat
*restrict LeftOut
, ALfloat
*restrict RightOut
,
321 const ALfloat
*data
, ALsizei Offset
, ALsizei OutPos
,
322 const ALsizei IrSize
, const HrtfParams
*oldparams
,
323 MixHrtfParams
*newparams
, HrtfState
*hrtfstate
,
325 typedef void (*HrtfDirectMixerFunc
)(ALfloat
*restrict LeftOut
, ALfloat
*restrict RightOut
,
326 const ALfloat
*data
, ALsizei Offset
, const ALsizei IrSize
,
327 const ALfloat (*restrict Coeffs
)[2],
328 ALfloat (*restrict Values
)[2], ALsizei BufferSize
);
331 #define GAIN_MIX_MAX (16.0f) /* +24dB */
333 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
335 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
336 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
338 /* Target gain for the reverb decay feedback reaching the decay time. */
339 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
341 #define FRACTIONBITS (12)
342 #define FRACTIONONE (1<<FRACTIONBITS)
343 #define FRACTIONMASK (FRACTIONONE-1)
346 inline ALfloat
minf(ALfloat a
, ALfloat b
)
347 { return ((a
> b
) ? b
: a
); }
348 inline ALfloat
maxf(ALfloat a
, ALfloat b
)
349 { return ((a
> b
) ? a
: b
); }
350 inline ALfloat
clampf(ALfloat val
, ALfloat min
, ALfloat max
)
351 { return minf(max
, maxf(min
, val
)); }
353 inline ALdouble
mind(ALdouble a
, ALdouble b
)
354 { return ((a
> b
) ? b
: a
); }
355 inline ALdouble
maxd(ALdouble a
, ALdouble b
)
356 { return ((a
> b
) ? a
: b
); }
357 inline ALdouble
clampd(ALdouble val
, ALdouble min
, ALdouble max
)
358 { return mind(max
, maxd(min
, val
)); }
360 inline ALuint
minu(ALuint a
, ALuint b
)
361 { return ((a
> b
) ? b
: a
); }
362 inline ALuint
maxu(ALuint a
, ALuint b
)
363 { return ((a
> b
) ? a
: b
); }
364 inline ALuint
clampu(ALuint val
, ALuint min
, ALuint max
)
365 { return minu(max
, maxu(min
, val
)); }
367 inline ALint
mini(ALint a
, ALint b
)
368 { return ((a
> b
) ? b
: a
); }
369 inline ALint
maxi(ALint a
, ALint b
)
370 { return ((a
> b
) ? a
: b
); }
371 inline ALint
clampi(ALint val
, ALint min
, ALint max
)
372 { return mini(max
, maxi(min
, val
)); }
374 inline ALint64
mini64(ALint64 a
, ALint64 b
)
375 { return ((a
> b
) ? b
: a
); }
376 inline ALint64
maxi64(ALint64 a
, ALint64 b
)
377 { return ((a
> b
) ? a
: b
); }
378 inline ALint64
clampi64(ALint64 val
, ALint64 min
, ALint64 max
)
379 { return mini64(max
, maxi64(min
, val
)); }
381 inline ALuint64
minu64(ALuint64 a
, ALuint64 b
)
382 { return ((a
> b
) ? b
: a
); }
383 inline ALuint64
maxu64(ALuint64 a
, ALuint64 b
)
384 { return ((a
> b
) ? a
: b
); }
385 inline ALuint64
clampu64(ALuint64 val
, ALuint64 min
, ALuint64 max
)
386 { return minu64(max
, maxu64(min
, val
)); }
388 inline size_t minz(size_t a
, size_t b
)
389 { return ((a
> b
) ? b
: a
); }
390 inline size_t maxz(size_t a
, size_t b
)
391 { return ((a
> b
) ? a
: b
); }
392 inline size_t clampz(size_t val
, size_t min
, size_t max
)
393 { return minz(max
, maxz(min
, val
)); }
396 inline ALfloat
lerp(ALfloat val1
, ALfloat val2
, ALfloat mu
)
398 return val1
+ (val2
-val1
)*mu
;
400 inline ALfloat
cubic(ALfloat val1
, ALfloat val2
, ALfloat val3
, ALfloat val4
, ALfloat mu
)
402 ALfloat mu2
= mu
*mu
, mu3
= mu2
*mu
;
403 ALfloat a0
= -0.5f
*mu3
+ mu2
+ -0.5f
*mu
;
404 ALfloat a1
= 1.5f
*mu3
+ -2.5f
*mu2
+ 1.0f
;
405 ALfloat a2
= -1.5f
*mu3
+ 2.0f
*mu2
+ 0.5f
*mu
;
406 ALfloat a3
= 0.5f
*mu3
+ -0.5f
*mu2
;
407 return val1
*a0
+ val2
*a1
+ val3
*a2
+ val4
*a3
;
411 enum HrtfRequestMode
{
419 void aluInitMixer(void);
421 ResamplerFunc
SelectResampler(enum Resampler resampler
);
425 * Set up the appropriate panning method and mixing method given the device
428 void aluInitRenderer(ALCdevice
*device
, ALint hrtf_id
, enum HrtfRequestMode hrtf_appreq
, enum HrtfRequestMode hrtf_userreq
);
430 void aluInitEffectPanning(struct ALeffectslot
*slot
);
433 * CalcDirectionCoeffs
435 * Calculates ambisonic coefficients based on a direction vector. The vector
436 * must be normalized (unit length), and the spread is the angular width of the
439 void CalcDirectionCoeffs(const ALfloat dir
[3], ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
]);
444 * Calculates ambisonic coefficients based on azimuth and elevation. The
445 * azimuth and elevation parameters are in radians, going right and up
448 inline void CalcAngleCoeffs(ALfloat azimuth
, ALfloat elevation
, ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
])
451 sinf(azimuth
) * cosf(elevation
),
453 -cosf(azimuth
) * cosf(elevation
)
455 CalcDirectionCoeffs(dir
, spread
, coeffs
);
459 * CalcAnglePairwiseCoeffs
461 * Calculates ambisonic coefficients based on azimuth and elevation. The
462 * azimuth and elevation parameters are in radians, going right and up
463 * respectively. This pairwise variant warps the result such that +30 azimuth
464 * is full right, and -30 azimuth is full left.
466 void CalcAnglePairwiseCoeffs(ALfloat azimuth
, ALfloat elevation
, ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
]);
468 void ComputeAmbientGainsMC(const ChannelConfig
*chancoeffs
, ALsizei numchans
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
]);
469 void ComputeAmbientGainsBF(const BFChannelConfig
*chanmap
, ALsizei numchans
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
]);
471 * ComputeAmbientGains
473 * Computes channel gains for ambient, omni-directional sounds.
475 inline void ComputeAmbientGains(const DryMixParams
*dry
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
477 if(dry
->CoeffCount
> 0)
478 ComputeAmbientGainsMC(dry
->Ambi
.Coeffs
, dry
->NumChannels
, ingain
, gains
);
480 ComputeAmbientGainsBF(dry
->Ambi
.Map
, dry
->NumChannels
, ingain
, gains
);
484 void ComputePanningGainsMC(const ChannelConfig
*chancoeffs
, ALsizei numchans
, ALsizei numcoeffs
, const ALfloat coeffs
[MAX_AMBI_COEFFS
], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
]);
485 void ComputePanningGainsBF(const BFChannelConfig
*chanmap
, ALsizei numchans
, const ALfloat coeffs
[MAX_AMBI_COEFFS
], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
]);
489 * Computes panning gains using the given channel decoder coefficients and the
490 * pre-calculated direction or angle coefficients.
492 inline void ComputeDryPanGains(const DryMixParams
*dry
, const ALfloat coeffs
[MAX_AMBI_COEFFS
], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
494 if(dry
->CoeffCount
> 0)
495 ComputePanningGainsMC(dry
->Ambi
.Coeffs
, dry
->NumChannels
, dry
->CoeffCount
,
496 coeffs
, ingain
, gains
);
498 ComputePanningGainsBF(dry
->Ambi
.Map
, dry
->NumChannels
, coeffs
, ingain
, gains
);
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
]);
504 * ComputeFirstOrderGains
506 * Sets channel gains for a first-order ambisonics input channel. The matrix is
507 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
508 * orient the sound samples.
510 inline void ComputeFirstOrderGains(const BFMixParams
*foa
, const ALfloat mtx
[4], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
512 if(foa
->CoeffCount
> 0)
513 ComputeFirstOrderGainsMC(foa
->Ambi
.Coeffs
, foa
->NumChannels
, mtx
, ingain
, gains
);
515 ComputeFirstOrderGainsBF(foa
->Ambi
.Map
, foa
->NumChannels
, mtx
, ingain
, gains
);
519 ALboolean
MixSource(struct ALvoice
*voice
, ALuint SourceID
, ALCcontext
*Context
, ALsizei SamplesToDo
);
521 void aluMixData(ALCdevice
*device
, ALvoid
*OutBuffer
, ALsizei NumSamples
);
522 /* Caller must lock the device, and the mixer must not be running. */
523 void aluHandleDisconnect(ALCdevice
*device
, const char *msg
, ...) DECL_FORMAT(printf
, 2, 3);
525 void UpdateContextProps(ALCcontext
*context
);
527 extern MixerFunc MixSamples
;
528 extern RowMixerFunc MixRowSamples
;
530 extern ALfloat ConeScale
;
531 extern ALfloat ZScale
;
532 extern ALboolean OverrideReverbSpeedOfSound
;