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