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 12
29 /* Maximum number of buffer samples after the current pos needed for resampling. */
30 #define MAX_POST_SAMPLES 12
39 struct ALbufferlistitem
;
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. */
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
];
66 typedef union InterpState
{
71 typedef union aluVector
{
72 alignas(16) ALfloat v
[4];
75 inline void aluVectorSet(aluVector
*vector
, ALfloat x
, ALfloat y
, ALfloat z
, ALfloat w
)
84 typedef union aluMatrixf
{
85 alignas(16) ALfloat m
[4][4];
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
);
114 AF_BandPass
= AF_LowPass
| AF_HighPass
118 typedef struct MixHrtfParams
{
119 const ALfloat (*Coeffs
)[2];
126 typedef struct DirectParams
{
127 enum ActiveFilters FilterType
;
128 ALfilterState LowPass
;
129 ALfilterState HighPass
;
131 NfcFilter NFCtrlFilter
[MAX_AMBI_ORDER
];
140 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
141 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
145 typedef struct SendParams
{
146 enum ActiveFilters FilterType
;
147 ALfilterState LowPass
;
148 ALfilterState HighPass
;
151 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
152 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
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
175 ATOMIC(ALuint
) position
;
176 ATOMIC(ALsizei
) position_fraction
;
179 * Number of channels and bytes-per-sample for the attached source's
185 /** Current target parameters used for mixing. */
190 ALuint Offset
; /* Number of output samples mixed since starting. */
192 alignas(16) ALfloat PrevSamples
[MAX_INPUT_CHANNELS
][MAX_PRE_SAMPLES
];
194 InterpState ResampleState
;
197 DirectParams Params
[MAX_INPUT_CHANNELS
];
199 ALfloat (*Buffer
)[BUFFERSIZE
];
201 ALsizei ChannelsPerOrder
[MAX_AMBI_ORDER
+1];
205 SendParams Params
[MAX_INPUT_CHANNELS
];
207 ALfloat (*Buffer
)[BUFFERSIZE
];
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
,
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
;
311 ResamplerDefault
= LinearResampler
314 enum HrtfRequestMode
{
321 void aluInitMixer(void);
323 MixerFunc
SelectMixer(void);
324 RowMixerFunc
SelectRowMixer(void);
325 ResamplerFunc
SelectResampler(enum Resampler resampler
);
329 * Set up the appropriate panning method and mixing method given the device
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
343 void CalcDirectionCoeffs(const ALfloat dir
[3], ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
]);
348 * Calculates ambisonic coefficients based on azimuth and elevation. The
349 * azimuth and elevation parameters are in radians, going right and up
352 inline void CalcAngleCoeffs(ALfloat azimuth
, ALfloat elevation
, ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
])
355 sinf(azimuth
) * cosf(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); \
381 ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
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);\
396 ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
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); \
412 ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
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
;