1 #ifndef VOICE_H
2 #define VOICE_H
3 
4 #include <array>
5 #include <atomic>
6 
7 #include "almalloc.h"
8 #include "alspan.h"
9 #include "alu.h"
10 #include "buffer_storage.h"
11 #include "core/bufferline.h"
12 #include "core/devformat.h"
13 #include "core/filters/biquad.h"
14 #include "core/filters/nfc.h"
15 #include "core/filters/splitter.h"
16 #include "core/mixer/defs.h"
17 #include "core/mixer/hrtfdefs.h"
18 #include "vector.h"
19 
20 struct ALCcontext;
21 struct EffectSlot;
22 enum class DistanceModel : unsigned char;
23 
24 using uint = unsigned int;
25 
26 
27 enum class SpatializeMode : unsigned char {
28     Off,
29     On,
30     Auto
31 };
32 
33 enum class DirectMode : unsigned char {
34     Off,
35     DropMismatch,
36     RemixMismatch
37 };
38 
39 
40 enum {
41     AF_None = 0,
42     AF_LowPass = 1,
43     AF_HighPass = 2,
44     AF_BandPass = AF_LowPass | AF_HighPass
45 };
46 
47 
48 struct DirectParams {
49     BiquadFilter LowPass;
50     BiquadFilter HighPass;
51 
52     NfcFilter NFCtrlFilter;
53 
54     struct {
55         HrtfFilter Old;
56         HrtfFilter Target;
57         alignas(16) std::array<float,HrtfHistoryLength> History;
58     } Hrtf;
59 
60     struct {
61         std::array<float,MAX_OUTPUT_CHANNELS> Current;
62         std::array<float,MAX_OUTPUT_CHANNELS> Target;
63     } Gains;
64 };
65 
66 struct SendParams {
67     BiquadFilter LowPass;
68     BiquadFilter HighPass;
69 
70     struct {
71         std::array<float,MAX_OUTPUT_CHANNELS> Current;
72         std::array<float,MAX_OUTPUT_CHANNELS> Target;
73     } Gains;
74 };
75 
76 
77 struct VoiceBufferItem {
78     std::atomic<VoiceBufferItem*> mNext{nullptr};
79 
80     CallbackType mCallback{nullptr};
81     void *mUserData{nullptr};
82 
83     uint mSampleLen{0u};
84     uint mLoopStart{0u};
85     uint mLoopEnd{0u};
86 
87     al::byte *mSamples{nullptr};
88 };
89 
90 
91 struct VoiceProps {
92     float Pitch;
93     float Gain;
94     float OuterGain;
95     float MinGain;
96     float MaxGain;
97     float InnerAngle;
98     float OuterAngle;
99     float RefDistance;
100     float MaxDistance;
101     float RolloffFactor;
102     std::array<float,3> Position;
103     std::array<float,3> Velocity;
104     std::array<float,3> Direction;
105     std::array<float,3> OrientAt;
106     std::array<float,3> OrientUp;
107     bool HeadRelative;
108     DistanceModel mDistanceModel;
109     Resampler mResampler;
110     DirectMode DirectChannels;
111     SpatializeMode mSpatializeMode;
112 
113     bool DryGainHFAuto;
114     bool WetGainAuto;
115     bool WetGainHFAuto;
116     float OuterGainHF;
117 
118     float AirAbsorptionFactor;
119     float RoomRolloffFactor;
120     float DopplerFactor;
121 
122     std::array<float,2> StereoPan;
123 
124     float Radius;
125 
126     /** Direct filter and auxiliary send info. */
127     struct {
128         float Gain;
129         float GainHF;
130         float HFReference;
131         float GainLF;
132         float LFReference;
133     } Direct;
134     struct SendData {
135         EffectSlot *Slot;
136         float Gain;
137         float GainHF;
138         float HFReference;
139         float GainLF;
140         float LFReference;
141     } Send[MAX_SENDS];
142 };
143 
144 struct VoicePropsItem : public VoiceProps {
145     std::atomic<VoicePropsItem*> next{nullptr};
146 
147     DEF_NEWDEL(VoicePropsItem)
148 };
149 
150 constexpr uint VoiceIsStatic{       1u<<0};
151 constexpr uint VoiceIsCallback{     1u<<1};
152 constexpr uint VoiceIsAmbisonic{    1u<<2}; /* Needs HF scaling for ambisonic upsampling. */
153 constexpr uint VoiceCallbackStopped{1u<<3};
154 constexpr uint VoiceIsFading{       1u<<4}; /* Use gain stepping for smooth transitions. */
155 constexpr uint VoiceHasHrtf{        1u<<5};
156 constexpr uint VoiceHasNfc{         1u<<6};
157 
158 struct Voice {
159     enum State {
160         Stopped,
161         Playing,
162         Stopping,
163         Pending
164     };
165 
166     std::atomic<VoicePropsItem*> mUpdate{nullptr};
167 
168     VoiceProps mProps;
169 
170     std::atomic<uint> mSourceID{0u};
171     std::atomic<State> mPlayState{Stopped};
172     std::atomic<bool> mPendingChange{false};
173 
174     /**
175      * Source offset in samples, relative to the currently playing buffer, NOT
176      * the whole queue.
177      */
178     std::atomic<uint> mPosition;
179     /** Fractional (fixed-point) offset to the next sample. */
180     std::atomic<uint> mPositionFrac;
181 
182     /* Current buffer queue item being played. */
183     std::atomic<VoiceBufferItem*> mCurrentBuffer;
184 
185     /* Buffer queue item to loop to at end of queue (will be NULL for non-
186      * looping voices).
187      */
188     std::atomic<VoiceBufferItem*> mLoopBuffer;
189 
190     /* Properties for the attached buffer(s). */
191     FmtChannels mFmtChannels;
192     FmtType mFmtType;
193     uint mFrequency;
194     uint mSampleSize;
195     AmbiLayout mAmbiLayout;
196     AmbiScaling mAmbiScaling;
197     uint mAmbiOrder;
198 
199     /** Current target parameters used for mixing. */
200     uint mStep{0};
201 
202     ResamplerFunc mResampler;
203 
204     InterpState mResampleState;
205 
206     uint mFlags{};
207     uint mNumCallbackSamples{0};
208 
209     struct TargetData {
210         int FilterType;
211         al::span<FloatBufferLine> Buffer;
212     };
213     TargetData mDirect;
214     std::array<TargetData,MAX_SENDS> mSend;
215 
216     struct ChannelData {
217         alignas(16) std::array<float,MaxResamplerPadding> mPrevSamples;
218 
219         float mAmbiScale;
220         BandSplitter mAmbiSplitter;
221 
222         DirectParams mDryParams;
223         std::array<SendParams,MAX_SENDS> mWetParams;
224     };
225     al::vector<ChannelData> mChans{2};
226 
227     Voice() = default;
~VoiceVoice228     ~Voice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
229 
230     Voice(const Voice&) = delete;
231     Voice& operator=(const Voice&) = delete;
232 
233     void mix(const State vstate, ALCcontext *Context, const uint SamplesToDo);
234 
235     DEF_NEWDEL(Voice)
236 };
237 
238 extern Resampler ResamplerDefault;
239 
240 #endif /* VOICE_H */
241