Use an array of 2 instead of a pair
[openal-soft.git] / core / voice.h
bloba55367aaf655f5df8e1d78a4eedf14f594845aae
1 #ifndef CORE_VOICE_H
2 #define CORE_VOICE_H
4 #include <array>
5 #include <atomic>
6 #include <bitset>
7 #include <chrono>
8 #include <cstddef>
9 #include <memory>
10 #include <optional>
11 #include <string>
13 #include "alspan.h"
14 #include "bufferline.h"
15 #include "buffer_storage.h"
16 #include "devformat.h"
17 #include "filters/biquad.h"
18 #include "filters/nfc.h"
19 #include "filters/splitter.h"
20 #include "mixer/defs.h"
21 #include "mixer/hrtfdefs.h"
22 #include "opthelpers.h"
23 #include "resampler_limits.h"
24 #include "uhjfilter.h"
25 #include "vector.h"
27 struct ContextBase;
28 struct DeviceBase;
29 struct EffectSlot;
30 enum class DistanceModel : unsigned char;
32 using uint = unsigned int;
35 inline constexpr size_t MaxSendCount{6};
38 enum class SpatializeMode : unsigned char {
39 Off,
40 On,
41 Auto
44 enum class DirectMode : unsigned char {
45 Off,
46 DropMismatch,
47 RemixMismatch
51 inline constexpr uint MaxPitch{10};
54 enum {
55 AF_None = 0,
56 AF_LowPass = 1,
57 AF_HighPass = 2,
58 AF_BandPass = AF_LowPass | AF_HighPass
62 struct DirectParams {
63 BiquadFilter LowPass;
64 BiquadFilter HighPass;
66 NfcFilter NFCtrlFilter;
68 struct HrtfParams {
69 HrtfFilter Old{};
70 HrtfFilter Target{};
71 alignas(16) std::array<float,HrtfHistoryLength> History{};
73 HrtfParams Hrtf;
75 struct GainParams {
76 std::array<float,MaxOutputChannels> Current{};
77 std::array<float,MaxOutputChannels> Target{};
79 GainParams Gains;
82 struct SendParams {
83 BiquadFilter LowPass;
84 BiquadFilter HighPass;
86 struct GainParams {
87 std::array<float,MaxAmbiChannels> Current{};
88 std::array<float,MaxAmbiChannels> Target{};
90 GainParams Gains;
94 struct VoiceBufferItem {
95 std::atomic<VoiceBufferItem*> mNext{nullptr};
97 CallbackType mCallback{nullptr};
98 void *mUserData{nullptr};
100 uint mBlockAlign{0u};
101 uint mSampleLen{0u};
102 uint mLoopStart{0u};
103 uint mLoopEnd{0u};
105 al::span<std::byte> mSamples{};
109 struct VoiceProps {
110 float Pitch;
111 float Gain;
112 float OuterGain;
113 float MinGain;
114 float MaxGain;
115 float InnerAngle;
116 float OuterAngle;
117 float RefDistance;
118 float MaxDistance;
119 float RolloffFactor;
120 std::array<float,3> Position;
121 std::array<float,3> Velocity;
122 std::array<float,3> Direction;
123 std::array<float,3> OrientAt;
124 std::array<float,3> OrientUp;
125 bool HeadRelative;
126 DistanceModel mDistanceModel;
127 Resampler mResampler;
128 DirectMode DirectChannels;
129 SpatializeMode mSpatializeMode;
131 bool DryGainHFAuto;
132 bool WetGainAuto;
133 bool WetGainHFAuto;
134 float OuterGainHF;
136 float AirAbsorptionFactor;
137 float RoomRolloffFactor;
138 float DopplerFactor;
140 std::array<float,2> StereoPan;
142 float Radius;
143 float EnhWidth;
144 float Panning;
146 /** Direct filter and auxiliary send info. */
147 struct DirectData {
148 float Gain;
149 float GainHF;
150 float HFReference;
151 float GainLF;
152 float LFReference;
154 DirectData Direct;
156 struct SendData {
157 EffectSlot *Slot;
158 float Gain;
159 float GainHF;
160 float HFReference;
161 float GainLF;
162 float LFReference;
164 std::array<SendData,MaxSendCount> Send;
167 struct VoicePropsItem : public VoiceProps {
168 std::atomic<VoicePropsItem*> next{nullptr};
171 enum : uint {
172 VoiceIsStatic,
173 VoiceIsCallback,
174 VoiceIsAmbisonic,
175 VoiceCallbackStopped,
176 VoiceIsFading,
177 VoiceHasHrtf,
178 VoiceHasNfc,
180 VoiceFlagCount
183 struct SIMDALIGN Voice {
184 enum State {
185 Stopped,
186 Playing,
187 Stopping,
188 Pending
191 std::atomic<VoicePropsItem*> mUpdate{nullptr};
193 VoiceProps mProps{};
195 std::atomic<uint> mSourceID{0u};
196 std::atomic<State> mPlayState{Stopped};
197 std::atomic<bool> mPendingChange{false};
200 * Source offset in samples, relative to the currently playing buffer, NOT
201 * the whole queue.
203 std::atomic<int> mPosition{};
204 /** Fractional (fixed-point) offset to the next sample. */
205 std::atomic<uint> mPositionFrac{};
207 /* Current buffer queue item being played. */
208 std::atomic<VoiceBufferItem*> mCurrentBuffer{};
210 /* Buffer queue item to loop to at end of queue (will be NULL for non-
211 * looping voices).
213 std::atomic<VoiceBufferItem*> mLoopBuffer{};
215 std::chrono::nanoseconds mStartTime{};
217 /* Properties for the attached buffer(s). */
218 FmtChannels mFmtChannels{};
219 FmtType mFmtType{};
220 uint mFrequency{};
221 uint mFrameStep{}; /**< In steps of the sample type size. */
222 uint mBytesPerBlock{}; /**< Or for PCM formats, BytesPerFrame. */
223 uint mSamplesPerBlock{}; /**< Always 1 for PCM formats. */
224 AmbiLayout mAmbiLayout{};
225 AmbiScaling mAmbiScaling{};
226 uint mAmbiOrder{};
228 std::unique_ptr<DecoderBase> mDecoder;
229 uint mDecoderPadding{};
231 /** Current target parameters used for mixing. */
232 uint mStep{0};
234 ResamplerFunc mResampler{};
236 InterpState mResampleState{};
238 std::bitset<VoiceFlagCount> mFlags{};
239 uint mNumCallbackBlocks{0};
240 uint mCallbackBlockBase{0};
242 struct TargetData {
243 int FilterType{};
244 al::span<FloatBufferLine> Buffer;
246 TargetData mDirect;
247 std::array<TargetData,MaxSendCount> mSend;
249 /* The first MaxResamplerPadding/2 elements are the sample history from the
250 * previous mix, with an additional MaxResamplerPadding/2 elements that are
251 * now current (which may be overwritten if the buffer data is still
252 * available).
254 using HistoryLine = std::array<float,MaxResamplerPadding>;
255 al::vector<HistoryLine,16> mPrevSamples{2};
257 struct ChannelData {
258 float mAmbiHFScale{}, mAmbiLFScale{};
259 BandSplitter mAmbiSplitter;
261 DirectParams mDryParams;
262 std::array<SendParams,MaxSendCount> mWetParams;
264 al::vector<ChannelData> mChans{2};
266 Voice() = default;
267 ~Voice() = default;
269 Voice(const Voice&) = delete;
270 Voice& operator=(const Voice&) = delete;
272 void mix(const State vstate, ContextBase *Context, const std::chrono::nanoseconds deviceTime,
273 const uint SamplesToDo);
275 void prepare(DeviceBase *device);
277 static void InitMixer(std::optional<std::string> resopt);
280 inline Resampler ResamplerDefault{Resampler::Gaussian};
282 #endif /* CORE_VOICE_H */