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