12 #include "devformat.h"
13 #include "filters/biquad.h"
14 #include "filters/nfc.h"
15 #include "filters/splitter.h"
18 enum class DistanceModel
;
22 SpatializeOff
= AL_FALSE
,
23 SpatializeOn
= AL_TRUE
,
24 SpatializeAuto
= AL_AUTO_SOFT
27 enum class DirectMode
: unsigned char {
29 DropMismatch
= AL_DROP_UNMATCHED_SOFT
,
30 RemixMismatch
= AL_REMIX_UNMATCHED_SOFT
33 enum class Resampler
{
44 extern Resampler ResamplerDefault
;
46 /* The number of distinct scale and phase intervals within the bsinc filter
49 #define BSINC_SCALE_BITS 4
50 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
51 #define BSINC_PHASE_BITS 5
52 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
54 /* Interpolator state. Kind of a misnomer since the interpolator itself is
55 * stateless. This just keeps it from having to recompute scale-related
56 * mappings for every sample.
59 float sf
; /* Scale interpolation factor. */
60 ALuint m
; /* Coefficient count. */
61 ALuint l
; /* Left coefficient offset. */
62 /* Filter coefficients, followed by the phase, scale, and scale-phase
63 * delta coefficients. Starting at phase index 0, each subsequent phase
64 * index follows contiguously.
73 using ResamplerFunc
= const float*(*)(const InterpState
*state
, const float *RESTRICT src
,
74 ALuint frac
, ALuint increment
, const al::span
<float> dst
);
76 ResamplerFunc
PrepareResampler(Resampler resampler
, ALuint increment
, InterpState
*state
);
83 AF_BandPass
= AF_LowPass
| AF_HighPass
87 struct MixHrtfFilter
{
88 const HrirArray
*Coeffs
;
97 BiquadFilter HighPass
;
99 NfcFilter NFCtrlFilter
;
104 alignas(16) std::array
<float,HRTF_HISTORY_LENGTH
> History
;
108 std::array
<float,MAX_OUTPUT_CHANNELS
> Current
;
109 std::array
<float,MAX_OUTPUT_CHANNELS
> Target
;
114 BiquadFilter LowPass
;
115 BiquadFilter HighPass
;
118 std::array
<float,MAX_OUTPUT_CHANNELS
> Current
;
119 std::array
<float,MAX_OUTPUT_CHANNELS
> Target
;
124 struct ALvoicePropsBase
{
135 std::array
<float,3> Position
;
136 std::array
<float,3> Velocity
;
137 std::array
<float,3> Direction
;
138 std::array
<float,3> OrientAt
;
139 std::array
<float,3> OrientUp
;
141 DistanceModel mDistanceModel
;
142 Resampler mResampler
;
143 DirectMode DirectChannels
;
144 SpatializeMode mSpatializeMode
;
151 float AirAbsorptionFactor
;
152 float RoomRolloffFactor
;
155 std::array
<float,2> StereoPan
;
159 /** Direct filter and auxiliary send info. */
177 struct ALvoiceProps
: public ALvoicePropsBase
{
178 std::atomic
<ALvoiceProps
*> next
{nullptr};
180 DEF_NEWDEL(ALvoiceProps
)
183 #define VOICE_IS_STATIC (1u<<0)
184 #define VOICE_IS_FADING (1u<<1) /* Fading sources use gain stepping for smooth transitions. */
185 #define VOICE_IS_AMBISONIC (1u<<2) /* Voice needs HF scaling for ambisonic upsampling. */
186 #define VOICE_HAS_HRTF (1u<<3)
187 #define VOICE_HAS_NFC (1u<<4)
196 std::atomic
<ALvoiceProps
*> mUpdate
{nullptr};
198 std::atomic
<ALuint
> mSourceID
{0u};
199 std::atomic
<State
> mPlayState
{Stopped
};
201 ALvoicePropsBase mProps
;
204 * Source offset in samples, relative to the currently playing buffer, NOT
207 std::atomic
<ALuint
> mPosition
;
208 /** Fractional (fixed-point) offset to the next sample. */
209 std::atomic
<ALuint
> mPositionFrac
;
211 /* Current buffer queue item being played. */
212 std::atomic
<ALbufferlistitem
*> mCurrentBuffer
;
214 /* Buffer queue item to loop to at end of queue (will be NULL for non-
217 std::atomic
<ALbufferlistitem
*> mLoopBuffer
;
219 /* Properties for the attached buffer(s). */
220 FmtChannels mFmtChannels
;
224 AmbiLayout mAmbiLayout
;
225 AmbiNorm mAmbiScaling
;
228 /** Current target parameters used for mixing. */
231 ResamplerFunc mResampler
;
233 InterpState mResampleState
;
239 al::span
<FloatBufferLine
> Buffer
;
242 std::array
<TargetData
,MAX_SENDS
> mSend
;
245 alignas(16) std::array
<float,MAX_RESAMPLER_PADDING
> mPrevSamples
;
248 BandSplitter mAmbiSplitter
;
250 DirectParams mDryParams
;
251 std::array
<SendParams
,MAX_SENDS
> mWetParams
;
253 std::array
<ChannelData
,MAX_INPUT_CHANNELS
> mChans
;
256 ALvoice(const ALvoice
&) = delete;
257 ALvoice(ALvoice
&& rhs
) noexcept
{ *this = std::move(rhs
); }
258 ~ALvoice() { delete mUpdate
.exchange(nullptr, std::memory_order_acq_rel
); }
259 ALvoice
& operator=(const ALvoice
&) = delete;
260 ALvoice
& operator=(ALvoice
&& rhs
) noexcept
262 ALvoiceProps
*old_update
{mUpdate
.load(std::memory_order_relaxed
)};
263 mUpdate
.store(rhs
.mUpdate
.exchange(old_update
, std::memory_order_relaxed
),
264 std::memory_order_relaxed
);
266 mSourceID
.store(rhs
.mSourceID
.load(std::memory_order_relaxed
), std::memory_order_relaxed
);
267 mPlayState
.store(rhs
.mPlayState
.load(std::memory_order_relaxed
),
268 std::memory_order_relaxed
);
272 mPosition
.store(rhs
.mPosition
.load(std::memory_order_relaxed
), std::memory_order_relaxed
);
273 mPositionFrac
.store(rhs
.mPositionFrac
.load(std::memory_order_relaxed
),
274 std::memory_order_relaxed
);
276 mCurrentBuffer
.store(rhs
.mCurrentBuffer
.load(std::memory_order_relaxed
),
277 std::memory_order_relaxed
);
278 mLoopBuffer
.store(rhs
.mLoopBuffer
.load(std::memory_order_relaxed
),
279 std::memory_order_relaxed
);
281 mFmtChannels
= rhs
.mFmtChannels
;
282 mFrequency
= rhs
.mFrequency
;
283 mNumChannels
= rhs
.mNumChannels
;
284 mSampleSize
= rhs
.mSampleSize
;
285 mAmbiLayout
= rhs
.mAmbiLayout
;
286 mAmbiScaling
= rhs
.mAmbiScaling
;
287 mAmbiOrder
= rhs
.mAmbiOrder
;
290 mResampler
= rhs
.mResampler
;
292 mResampleState
= rhs
.mResampleState
;
296 mDirect
= rhs
.mDirect
;
303 void mix(const State vstate
, ALCcontext
*Context
, const ALuint SamplesToDo
);