Use one PulseAudio mainloop per device
[openal-soft.git] / alc / voice.h
blob206e2e6b3d9a42eb9eb6b5860e9b8ad6beb326c0
1 #ifndef VOICE_H
2 #define VOICE_H
4 #include <array>
6 #include "AL/al.h"
7 #include "AL/alext.h"
9 #include "al/buffer.h"
10 #include "alspan.h"
11 #include "alu.h"
12 #include "filters/biquad.h"
13 #include "filters/nfc.h"
14 #include "filters/splitter.h"
15 #include "hrtf.h"
17 enum class DistanceModel;
20 enum SpatializeMode {
21 SpatializeOff = AL_FALSE,
22 SpatializeOn = AL_TRUE,
23 SpatializeAuto = AL_AUTO_SOFT
26 enum class Resampler {
27 Point,
28 Linear,
29 Cubic,
30 FastBSinc12,
31 BSinc12,
32 FastBSinc24,
33 BSinc24,
35 Max = BSinc24
37 extern Resampler ResamplerDefault;
39 /* The number of distinct scale and phase intervals within the bsinc filter
40 * table.
42 #define BSINC_SCALE_BITS 4
43 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
44 #define BSINC_PHASE_BITS 5
45 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
47 /* Interpolator state. Kind of a misnomer since the interpolator itself is
48 * stateless. This just keeps it from having to recompute scale-related
49 * mappings for every sample.
51 struct BsincState {
52 float sf; /* Scale interpolation factor. */
53 ALuint m; /* Coefficient count. */
54 ALuint l; /* Left coefficient offset. */
55 /* Filter coefficients, followed by the phase, scale, and scale-phase
56 * delta coefficients. Starting at phase index 0, each subsequent phase
57 * index follows contiguously.
59 const float *filter;
62 union InterpState {
63 BsincState bsinc;
66 using ResamplerFunc = const float*(*)(const InterpState *state, const float *RESTRICT src,
67 ALuint frac, ALuint increment, const al::span<float> dst);
69 ResamplerFunc PrepareResampler(Resampler resampler, ALuint increment, InterpState *state);
72 enum {
73 AF_None = 0,
74 AF_LowPass = 1,
75 AF_HighPass = 2,
76 AF_BandPass = AF_LowPass | AF_HighPass
80 struct MixHrtfFilter {
81 const HrirArray *Coeffs;
82 ALsizei Delay[2];
83 float Gain;
84 float GainStep;
88 struct DirectParams {
89 BiquadFilter LowPass;
90 BiquadFilter HighPass;
92 NfcFilter NFCtrlFilter;
94 struct {
95 HrtfFilter Old;
96 HrtfFilter Target;
97 HrtfState State;
98 } Hrtf;
100 struct {
101 std::array<float,MAX_OUTPUT_CHANNELS> Current;
102 std::array<float,MAX_OUTPUT_CHANNELS> Target;
103 } Gains;
106 struct SendParams {
107 BiquadFilter LowPass;
108 BiquadFilter HighPass;
110 struct {
111 std::array<float,MAX_OUTPUT_CHANNELS> Current;
112 std::array<float,MAX_OUTPUT_CHANNELS> Target;
113 } Gains;
117 struct ALvoicePropsBase {
118 float Pitch;
119 float Gain;
120 float OuterGain;
121 float MinGain;
122 float MaxGain;
123 float InnerAngle;
124 float OuterAngle;
125 float RefDistance;
126 float MaxDistance;
127 float RolloffFactor;
128 std::array<float,3> Position;
129 std::array<float,3> Velocity;
130 std::array<float,3> Direction;
131 std::array<float,3> OrientAt;
132 std::array<float,3> OrientUp;
133 bool HeadRelative;
134 DistanceModel mDistanceModel;
135 Resampler mResampler;
136 bool DirectChannels;
137 SpatializeMode mSpatializeMode;
139 bool DryGainHFAuto;
140 bool WetGainAuto;
141 bool WetGainHFAuto;
142 float OuterGainHF;
144 float AirAbsorptionFactor;
145 float RoomRolloffFactor;
146 float DopplerFactor;
148 std::array<float,2> StereoPan;
150 float Radius;
152 /** Direct filter and auxiliary send info. */
153 struct {
154 float Gain;
155 float GainHF;
156 float HFReference;
157 float GainLF;
158 float LFReference;
159 } Direct;
160 struct SendData {
161 ALeffectslot *Slot;
162 float Gain;
163 float GainHF;
164 float HFReference;
165 float GainLF;
166 float LFReference;
167 } Send[MAX_SENDS];
170 struct ALvoiceProps : public ALvoicePropsBase {
171 std::atomic<ALvoiceProps*> next{nullptr};
173 DEF_NEWDEL(ALvoiceProps)
176 #define VOICE_IS_STATIC (1u<<0)
177 #define VOICE_IS_FADING (1u<<1) /* Fading sources use gain stepping for smooth transitions. */
178 #define VOICE_IS_AMBISONIC (1u<<2) /* Voice needs HF scaling for ambisonic upsampling. */
179 #define VOICE_HAS_HRTF (1u<<3)
180 #define VOICE_HAS_NFC (1u<<4)
182 struct ALvoice {
183 enum State {
184 Stopped = 0,
185 Playing = 1,
186 Stopping = 2
189 std::atomic<ALvoiceProps*> mUpdate{nullptr};
191 std::atomic<ALuint> mSourceID{0u};
192 std::atomic<State> mPlayState{Stopped};
194 ALvoicePropsBase mProps;
197 * Source offset in samples, relative to the currently playing buffer, NOT
198 * the whole queue.
200 std::atomic<ALuint> mPosition;
201 /** Fractional (fixed-point) offset to the next sample. */
202 std::atomic<ALuint> mPositionFrac;
204 /* Current buffer queue item being played. */
205 std::atomic<ALbufferlistitem*> mCurrentBuffer;
207 /* Buffer queue item to loop to at end of queue (will be NULL for non-
208 * looping voices).
210 std::atomic<ALbufferlistitem*> mLoopBuffer;
212 /* Properties for the attached buffer(s). */
213 FmtChannels mFmtChannels;
214 ALuint mFrequency;
215 ALuint mNumChannels;
216 ALuint mSampleSize;
218 /** Current target parameters used for mixing. */
219 ALuint mStep;
221 ResamplerFunc mResampler;
223 InterpState mResampleState;
225 ALuint mFlags;
227 struct TargetData {
228 int FilterType;
229 al::span<FloatBufferLine> Buffer;
231 TargetData mDirect;
232 std::array<TargetData,MAX_SENDS> mSend;
234 struct ChannelData {
235 alignas(16) std::array<float,MAX_RESAMPLER_PADDING> mPrevSamples;
237 float mAmbiScale;
238 BandSplitter mAmbiSplitter;
240 DirectParams mDryParams;
241 std::array<SendParams,MAX_SENDS> mWetParams;
243 std::array<ChannelData,MAX_INPUT_CHANNELS> mChans;
245 ALvoice() = default;
246 ALvoice(const ALvoice&) = delete;
247 ALvoice(ALvoice&& rhs) noexcept { *this = std::move(rhs); }
248 ~ALvoice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
249 ALvoice& operator=(const ALvoice&) = delete;
250 ALvoice& operator=(ALvoice&& rhs) noexcept
252 ALvoiceProps *old_update{mUpdate.load(std::memory_order_relaxed)};
253 mUpdate.store(rhs.mUpdate.exchange(old_update, std::memory_order_relaxed),
254 std::memory_order_relaxed);
256 mSourceID.store(rhs.mSourceID.load(std::memory_order_relaxed), std::memory_order_relaxed);
257 mPlayState.store(rhs.mPlayState.load(std::memory_order_relaxed),
258 std::memory_order_relaxed);
260 mProps = rhs.mProps;
262 mPosition.store(rhs.mPosition.load(std::memory_order_relaxed), std::memory_order_relaxed);
263 mPositionFrac.store(rhs.mPositionFrac.load(std::memory_order_relaxed),
264 std::memory_order_relaxed);
266 mCurrentBuffer.store(rhs.mCurrentBuffer.load(std::memory_order_relaxed),
267 std::memory_order_relaxed);
268 mLoopBuffer.store(rhs.mLoopBuffer.load(std::memory_order_relaxed),
269 std::memory_order_relaxed);
271 mFmtChannels = rhs.mFmtChannels;
272 mFrequency = rhs.mFrequency;
273 mNumChannels = rhs.mNumChannels;
274 mSampleSize = rhs.mSampleSize;
276 mStep = rhs.mStep;
277 mResampler = rhs.mResampler;
279 mResampleState = rhs.mResampleState;
281 mFlags = rhs.mFlags;
283 mDirect = rhs.mDirect;
284 mSend = rhs.mSend;
285 mChans = rhs.mChans;
287 return *this;
290 void mix(State vstate, ALCcontext *Context, const ALuint SamplesToDo);
293 #endif /* VOICE_H */