Add "fast" variants for the bsinc resamplers
[openal-soft.git] / alc / alu.h
blobe2b255565f62655c947c5ca6d294bd9c9e98bca9
1 #ifndef ALU_H
2 #define ALU_H
4 #include <array>
5 #include <atomic>
6 #include <cmath>
7 #include <cstddef>
9 #include "AL/al.h"
10 #include "AL/alc.h"
11 #include "AL/alext.h"
13 #include "al/buffer.h"
14 #include "alcmain.h"
15 #include "almalloc.h"
16 #include "alspan.h"
17 #include "ambidefs.h"
18 #include "devformat.h"
19 #include "filters/biquad.h"
20 #include "filters/nfc.h"
21 #include "filters/splitter.h"
22 #include "hrtf.h"
23 #include "logging.h"
25 struct ALbufferlistitem;
26 struct ALeffectslot;
27 struct BSincTable;
30 enum class DistanceModel;
32 #define MAX_PITCH 255
33 #define MAX_SENDS 16
36 #define DITHER_RNG_SEED 22222
39 enum SpatializeMode {
40 SpatializeOff = AL_FALSE,
41 SpatializeOn = AL_TRUE,
42 SpatializeAuto = AL_AUTO_SOFT
45 enum class Resampler {
46 Point,
47 Linear,
48 Cubic,
49 FastBSinc12,
50 BSinc12,
51 FastBSinc24,
52 BSinc24,
54 Max = BSinc24
56 extern Resampler ResamplerDefault;
58 /* The number of distinct scale and phase intervals within the bsinc filter
59 * table.
61 #define BSINC_SCALE_BITS 4
62 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
63 #define BSINC_PHASE_BITS 4
64 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
66 /* Interpolator state. Kind of a misnomer since the interpolator itself is
67 * stateless. This just keeps it from having to recompute scale-related
68 * mappings for every sample.
70 struct BsincState {
71 ALfloat sf; /* Scale interpolation factor. */
72 ALuint m; /* Coefficient count. */
73 ALuint l; /* Left coefficient offset. */
74 /* Filter coefficients, followed by the scale, phase, and scale-phase
75 * delta coefficients. Starting at phase index 0, each subsequent phase
76 * index follows contiguously.
78 const ALfloat *filter;
81 union InterpState {
82 BsincState bsinc;
85 using ResamplerFunc = const ALfloat*(*)(const InterpState *state, const ALfloat *RESTRICT src,
86 ALuint frac, ALuint increment, const al::span<float> dst);
88 void BsincPrepare(const ALuint increment, BsincState *state, const BSincTable *table);
90 extern const BSincTable bsinc12;
91 extern const BSincTable bsinc24;
94 enum {
95 AF_None = 0,
96 AF_LowPass = 1,
97 AF_HighPass = 2,
98 AF_BandPass = AF_LowPass | AF_HighPass
102 struct MixHrtfFilter {
103 const HrirArray *Coeffs;
104 ALsizei Delay[2];
105 ALfloat Gain;
106 ALfloat GainStep;
110 struct DirectParams {
111 BiquadFilter LowPass;
112 BiquadFilter HighPass;
114 NfcFilter NFCtrlFilter;
116 struct {
117 HrtfFilter Old;
118 HrtfFilter Target;
119 HrtfState State;
120 } Hrtf;
122 struct {
123 ALfloat Current[MAX_OUTPUT_CHANNELS];
124 ALfloat Target[MAX_OUTPUT_CHANNELS];
125 } Gains;
128 struct SendParams {
129 BiquadFilter LowPass;
130 BiquadFilter HighPass;
132 struct {
133 ALfloat Current[MAX_OUTPUT_CHANNELS];
134 ALfloat Target[MAX_OUTPUT_CHANNELS];
135 } Gains;
139 struct ALvoicePropsBase {
140 ALfloat Pitch;
141 ALfloat Gain;
142 ALfloat OuterGain;
143 ALfloat MinGain;
144 ALfloat MaxGain;
145 ALfloat InnerAngle;
146 ALfloat OuterAngle;
147 ALfloat RefDistance;
148 ALfloat MaxDistance;
149 ALfloat RolloffFactor;
150 std::array<ALfloat,3> Position;
151 std::array<ALfloat,3> Velocity;
152 std::array<ALfloat,3> Direction;
153 std::array<ALfloat,3> OrientAt;
154 std::array<ALfloat,3> OrientUp;
155 ALboolean HeadRelative;
156 DistanceModel mDistanceModel;
157 Resampler mResampler;
158 ALboolean DirectChannels;
159 SpatializeMode mSpatializeMode;
161 ALboolean DryGainHFAuto;
162 ALboolean WetGainAuto;
163 ALboolean WetGainHFAuto;
164 ALfloat OuterGainHF;
166 ALfloat AirAbsorptionFactor;
167 ALfloat RoomRolloffFactor;
168 ALfloat DopplerFactor;
170 std::array<ALfloat,2> StereoPan;
172 ALfloat Radius;
174 /** Direct filter and auxiliary send info. */
175 struct {
176 ALfloat Gain;
177 ALfloat GainHF;
178 ALfloat HFReference;
179 ALfloat GainLF;
180 ALfloat LFReference;
181 } Direct;
182 struct SendData {
183 ALeffectslot *Slot;
184 ALfloat Gain;
185 ALfloat GainHF;
186 ALfloat HFReference;
187 ALfloat GainLF;
188 ALfloat LFReference;
189 } Send[MAX_SENDS];
192 struct ALvoiceProps : public ALvoicePropsBase {
193 std::atomic<ALvoiceProps*> next{nullptr};
195 DEF_NEWDEL(ALvoiceProps)
198 #define VOICE_IS_STATIC (1u<<0)
199 #define VOICE_IS_FADING (1u<<1) /* Fading sources use gain stepping for smooth transitions. */
200 #define VOICE_IS_AMBISONIC (1u<<2) /* Voice needs HF scaling for ambisonic upsampling. */
201 #define VOICE_HAS_HRTF (1u<<3)
202 #define VOICE_HAS_NFC (1u<<4)
204 struct ALvoice {
205 enum State {
206 Stopped = 0,
207 Playing = 1,
208 Stopping = 2
211 std::atomic<ALvoiceProps*> mUpdate{nullptr};
213 std::atomic<ALuint> mSourceID{0u};
214 std::atomic<State> mPlayState{Stopped};
216 ALvoicePropsBase mProps;
219 * Source offset in samples, relative to the currently playing buffer, NOT
220 * the whole queue.
222 std::atomic<ALuint> mPosition;
223 /** Fractional (fixed-point) offset to the next sample. */
224 std::atomic<ALuint> mPositionFrac;
226 /* Current buffer queue item being played. */
227 std::atomic<ALbufferlistitem*> mCurrentBuffer;
229 /* Buffer queue item to loop to at end of queue (will be NULL for non-
230 * looping voices).
232 std::atomic<ALbufferlistitem*> mLoopBuffer;
234 /* Properties for the attached buffer(s). */
235 FmtChannels mFmtChannels;
236 ALuint mFrequency;
237 ALuint mNumChannels;
238 ALuint mSampleSize;
240 /** Current target parameters used for mixing. */
241 ALuint mStep;
243 ResamplerFunc mResampler;
245 InterpState mResampleState;
247 ALuint mFlags;
249 struct DirectData {
250 int FilterType;
251 al::span<FloatBufferLine> Buffer;
253 DirectData mDirect;
255 struct SendData {
256 int FilterType;
257 al::span<FloatBufferLine> Buffer;
259 std::array<SendData,MAX_SENDS> mSend;
261 struct ChannelData {
262 alignas(16) std::array<ALfloat,MAX_RESAMPLE_PADDING*2> mPrevSamples;
264 ALfloat mAmbiScale;
265 BandSplitter mAmbiSplitter;
267 DirectParams mDryParams;
268 std::array<SendParams,MAX_SENDS> mWetParams;
270 std::array<ChannelData,MAX_INPUT_CHANNELS> mChans;
272 ALvoice() = default;
273 ALvoice(const ALvoice&) = delete;
274 ALvoice(ALvoice&& rhs) noexcept { *this = std::move(rhs); }
275 ~ALvoice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
276 ALvoice& operator=(const ALvoice&) = delete;
277 ALvoice& operator=(ALvoice&& rhs) noexcept
279 ALvoiceProps *old_update{mUpdate.load(std::memory_order_relaxed)};
280 mUpdate.store(rhs.mUpdate.exchange(old_update, std::memory_order_relaxed),
281 std::memory_order_relaxed);
283 mSourceID.store(rhs.mSourceID.load(std::memory_order_relaxed), std::memory_order_relaxed);
284 mPlayState.store(rhs.mPlayState.load(std::memory_order_relaxed),
285 std::memory_order_relaxed);
287 mProps = rhs.mProps;
289 mPosition.store(rhs.mPosition.load(std::memory_order_relaxed), std::memory_order_relaxed);
290 mPositionFrac.store(rhs.mPositionFrac.load(std::memory_order_relaxed),
291 std::memory_order_relaxed);
293 mCurrentBuffer.store(rhs.mCurrentBuffer.load(std::memory_order_relaxed),
294 std::memory_order_relaxed);
295 mLoopBuffer.store(rhs.mLoopBuffer.load(std::memory_order_relaxed),
296 std::memory_order_relaxed);
298 mFmtChannels = rhs.mFmtChannels;
299 mFrequency = rhs.mFrequency;
300 mNumChannels = rhs.mNumChannels;
301 mSampleSize = rhs.mSampleSize;
303 mStep = rhs.mStep;
304 mResampler = rhs.mResampler;
306 mResampleState = rhs.mResampleState;
308 mFlags = rhs.mFlags;
310 mDirect = rhs.mDirect;
311 mSend = rhs.mSend;
312 mChans = rhs.mChans;
314 return *this;
317 void mix(ALvoice::State vstate, ALCcontext *Context, const ALuint SamplesToDo);
321 using MixerFunc = void(*)(const al::span<const float> InSamples,
322 const al::span<FloatBufferLine> OutBuffer, float *CurrentGains, const float *TargetGains,
323 const size_t Counter, const size_t OutPos);
324 using RowMixerFunc = void(*)(const al::span<float> OutBuffer, const al::span<const float> Gains,
325 const float *InSamples, const size_t InStride);
326 using HrtfMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
327 const ALfloat *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize,
328 MixHrtfFilter *hrtfparams, const size_t BufferSize);
329 using HrtfMixerBlendFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
330 const ALfloat *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize,
331 const HrtfFilter *oldparams, MixHrtfFilter *newparams, const size_t BufferSize);
332 using HrtfDirectMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
333 const al::span<const FloatBufferLine> InSamples, float2 *AccumSamples, DirectHrtfState *State,
334 const size_t BufferSize);
337 #define GAIN_MIX_MAX (1000.0f) /* +60dB */
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 lerp(ALfloat val1, ALfloat val2, ALfloat mu) noexcept
353 { return val1 + (val2-val1)*mu; }
354 inline ALfloat cubic(ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat mu) noexcept
356 ALfloat mu2 = mu*mu, mu3 = mu2*mu;
357 ALfloat a0 = -0.5f*mu3 + mu2 + -0.5f*mu;
358 ALfloat a1 = 1.5f*mu3 + -2.5f*mu2 + 1.0f;
359 ALfloat a2 = -1.5f*mu3 + 2.0f*mu2 + 0.5f*mu;
360 ALfloat a3 = 0.5f*mu3 + -0.5f*mu2;
361 return val1*a0 + val2*a1 + val3*a2 + val4*a3;
365 enum HrtfRequestMode {
366 Hrtf_Default = 0,
367 Hrtf_Enable = 1,
368 Hrtf_Disable = 2,
371 void aluInit(void);
373 void aluInitMixer(void);
375 ResamplerFunc SelectResampler(Resampler resampler, ALuint increment);
377 /* aluInitRenderer
379 * Set up the appropriate panning method and mixing method given the device
380 * properties.
382 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, HrtfRequestMode hrtf_appreq, HrtfRequestMode hrtf_userreq);
384 void aluInitEffectPanning(ALeffectslot *slot, ALCdevice *device);
387 * Calculates ambisonic encoder coefficients using the X, Y, and Z direction
388 * components, which must represent a normalized (unit length) vector, and the
389 * spread is the angular width of the sound (0...tau).
391 * NOTE: The components use ambisonic coordinates. As a result:
393 * Ambisonic Y = OpenAL -X
394 * Ambisonic Z = OpenAL Y
395 * Ambisonic X = OpenAL -Z
397 * The components are ordered such that OpenAL's X, Y, and Z are the first,
398 * second, and third parameters respectively -- simply negate X and Z.
400 void CalcAmbiCoeffs(const ALfloat y, const ALfloat z, const ALfloat x, const ALfloat spread,
401 ALfloat (&coeffs)[MAX_AMBI_CHANNELS]);
404 * CalcDirectionCoeffs
406 * Calculates ambisonic coefficients based on an OpenAL direction vector. The
407 * vector must be normalized (unit length), and the spread is the angular width
408 * of the sound (0...tau).
410 inline void CalcDirectionCoeffs(const ALfloat (&dir)[3], ALfloat spread, ALfloat (&coeffs)[MAX_AMBI_CHANNELS])
412 /* Convert from OpenAL coords to Ambisonics. */
413 CalcAmbiCoeffs(-dir[0], dir[1], -dir[2], spread, coeffs);
417 * CalcAngleCoeffs
419 * Calculates ambisonic coefficients based on azimuth and elevation. The
420 * azimuth and elevation parameters are in radians, going right and up
421 * respectively.
423 inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat (&coeffs)[MAX_AMBI_CHANNELS])
425 ALfloat x = -std::sin(azimuth) * std::cos(elevation);
426 ALfloat y = std::sin(elevation);
427 ALfloat z = std::cos(azimuth) * std::cos(elevation);
429 CalcAmbiCoeffs(x, y, z, spread, coeffs);
434 * ComputePanGains
436 * Computes panning gains using the given channel decoder coefficients and the
437 * pre-calculated direction or angle coefficients. For B-Format sources, the
438 * coeffs are a 'slice' of a transform matrix for the input channel, used to
439 * scale and orient the sound samples.
441 void ComputePanGains(const MixParams *mix, const ALfloat*RESTRICT coeffs, ALfloat ingain, ALfloat (&gains)[MAX_OUTPUT_CHANNELS]);
444 inline std::array<ALfloat,MAX_AMBI_CHANNELS> GetAmbiIdentityRow(size_t i) noexcept
446 std::array<ALfloat,MAX_AMBI_CHANNELS> ret{};
447 ret[i] = 1.0f;
448 return ret;
452 void aluMixData(ALCdevice *device, ALvoid *OutBuffer, const ALuint NumSamples);
453 /* Caller must lock the device state, and the mixer must not be running. */
454 void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3);
456 extern MixerFunc MixSamples;
457 extern RowMixerFunc MixRowSamples;
459 extern const ALfloat ConeScale;
460 extern const ALfloat ZScale;
462 #endif