1 #ifndef ALC_MAIN_H
2 #define ALC_MAIN_H
3 
4 #include <algorithm>
5 #include <array>
6 #include <atomic>
7 #include <bitset>
8 #include <chrono>
9 #include <cstdint>
10 #include <cstddef>
11 #include <memory>
12 #include <mutex>
13 #include <string>
14 #include <thread>
15 #include <utility>
16 
17 #include "AL/al.h"
18 #include "AL/alc.h"
19 #include "AL/alext.h"
20 
21 #include "almalloc.h"
22 #include "alnumeric.h"
23 #include "alspan.h"
24 #include "atomic.h"
25 #include "core/ambidefs.h"
26 #include "core/bufferline.h"
27 #include "core/devformat.h"
28 #include "core/filters/splitter.h"
29 #include "core/mixer/defs.h"
30 #include "hrtf.h"
31 #include "inprogext.h"
32 #include "intrusive_ptr.h"
33 #include "vector.h"
34 
35 class BFormatDec;
36 struct ALbuffer;
37 struct ALeffect;
38 struct ALfilter;
39 struct BackendBase;
40 struct Compressor;
41 struct EffectState;
42 struct Uhj2Encoder;
43 struct bs2b;
44 
45 using uint = unsigned int;
46 
47 
48 #define MIN_OUTPUT_RATE      8000
49 #define MAX_OUTPUT_RATE      192000
50 #define DEFAULT_OUTPUT_RATE  44100
51 
52 #define DEFAULT_UPDATE_SIZE  882 /* 20ms */
53 #define DEFAULT_NUM_UPDATES  3
54 
55 
56 enum class DeviceType : unsigned char {
57     Playback,
58     Capture,
59     Loopback
60 };
61 
62 
63 enum class RenderMode : unsigned char {
64     Normal,
65     Pairwise,
66     Hrtf
67 };
68 
69 
70 struct InputRemixMap {
71     struct TargetMix { Channel channel; float mix; };
72 
73     Channel channel;
74     std::array<TargetMix,2> targets;
75 };
76 
77 
78 struct BufferSubList {
79     uint64_t FreeMask{~0_u64};
80     ALbuffer *Buffers{nullptr}; /* 64 */
81 
82     BufferSubList() noexcept = default;
83     BufferSubList(const BufferSubList&) = delete;
BufferSubListBufferSubList84     BufferSubList(BufferSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Buffers{rhs.Buffers}
85     { rhs.FreeMask = ~0_u64; rhs.Buffers = nullptr; }
86     ~BufferSubList();
87 
88     BufferSubList& operator=(const BufferSubList&) = delete;
89     BufferSubList& operator=(BufferSubList&& rhs) noexcept
90     { std::swap(FreeMask, rhs.FreeMask); std::swap(Buffers, rhs.Buffers); return *this; }
91 };
92 
93 struct EffectSubList {
94     uint64_t FreeMask{~0_u64};
95     ALeffect *Effects{nullptr}; /* 64 */
96 
97     EffectSubList() noexcept = default;
98     EffectSubList(const EffectSubList&) = delete;
EffectSubListEffectSubList99     EffectSubList(EffectSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Effects{rhs.Effects}
100     { rhs.FreeMask = ~0_u64; rhs.Effects = nullptr; }
101     ~EffectSubList();
102 
103     EffectSubList& operator=(const EffectSubList&) = delete;
104     EffectSubList& operator=(EffectSubList&& rhs) noexcept
105     { std::swap(FreeMask, rhs.FreeMask); std::swap(Effects, rhs.Effects); return *this; }
106 };
107 
108 struct FilterSubList {
109     uint64_t FreeMask{~0_u64};
110     ALfilter *Filters{nullptr}; /* 64 */
111 
112     FilterSubList() noexcept = default;
113     FilterSubList(const FilterSubList&) = delete;
FilterSubListFilterSubList114     FilterSubList(FilterSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Filters{rhs.Filters}
115     { rhs.FreeMask = ~0_u64; rhs.Filters = nullptr; }
116     ~FilterSubList();
117 
118     FilterSubList& operator=(const FilterSubList&) = delete;
119     FilterSubList& operator=(FilterSubList&& rhs) noexcept
120     { std::swap(FreeMask, rhs.FreeMask); std::swap(Filters, rhs.Filters); return *this; }
121 };
122 
123 
124 /* Maximum delay in samples for speaker distance compensation. */
125 #define MAX_DELAY_LENGTH 1024
126 
127 struct DistanceComp {
128     struct ChanData {
129         float Gain{1.0f};
130         uint Length{0u}; /* Valid range is [0...MAX_DELAY_LENGTH). */
131         float *Buffer{nullptr};
132     };
133 
134     std::array<ChanData,MAX_OUTPUT_CHANNELS> mChannels;
135     al::FlexArray<float,16> mSamples;
136 
DistanceCompDistanceComp137     DistanceComp(size_t count) : mSamples{count} { }
138 
CreateDistanceComp139     static std::unique_ptr<DistanceComp> Create(size_t numsamples)
140     { return std::unique_ptr<DistanceComp>{new(FamCount(numsamples)) DistanceComp{numsamples}}; }
141 
142     DEF_FAM_NEWDEL(DistanceComp, mSamples)
143 };
144 
145 
146 struct BFChannelConfig {
147     float Scale;
148     uint Index;
149 };
150 
151 
152 struct MixParams {
153     /* Coefficient channel mapping for mixing to the buffer. */
154     std::array<BFChannelConfig,MAX_OUTPUT_CHANNELS> AmbiMap{};
155 
156     al::span<FloatBufferLine> Buffer;
157 };
158 
159 struct RealMixParams {
160     al::span<const InputRemixMap> RemixMap;
161     std::array<uint,MaxChannels> ChannelIndex{};
162 
163     al::span<FloatBufferLine> Buffer;
164 };
165 
166 enum {
167     // Frequency was requested by the app or config file
168     FrequencyRequest,
169     // Channel configuration was requested by the config file
170     ChannelsRequest,
171     // Sample type was requested by the config file
172     SampleTypeRequest,
173 
174     // Specifies if the DSP is paused at user request
175     DevicePaused,
176     // Specifies if the device is currently running
177     DeviceRunning,
178 
179     DeviceFlagsCount
180 };
181 
182 struct ALCdevice : public al::intrusive_ref<ALCdevice> {
183     std::atomic<bool> Connected{true};
184     const DeviceType Type{};
185 
186     uint Frequency{};
187     uint UpdateSize{};
188     uint BufferSize{};
189 
190     DevFmtChannels FmtChans{};
191     DevFmtType FmtType{};
192     bool IsHeadphones{false};
193     uint mAmbiOrder{0};
194     float mXOverFreq{400.0f};
195     /* For DevFmtAmbi* output only, specifies the channel order and
196      * normalization.
197      */
198     DevAmbiLayout mAmbiLayout{DevAmbiLayout::Default};
199     DevAmbiScaling mAmbiScale{DevAmbiScaling::Default};
200 
201     std::string DeviceName;
202 
203     // Device flags
204     std::bitset<DeviceFlagsCount> Flags{};
205 
206     // Maximum number of sources that can be created
207     uint SourcesMax{};
208     // Maximum number of slots that can be created
209     uint AuxiliaryEffectSlotMax{};
210 
211     /* Rendering mode. */
212     RenderMode mRenderMode{RenderMode::Normal};
213 
214     /* The average speaker distance as determined by the ambdec configuration,
215      * HRTF data set, or the NFC-HOA reference delay. Only used for NFC.
216      */
217     float AvgSpeakerDist{0.0f};
218 
219     uint SamplesDone{0u};
220     std::chrono::nanoseconds ClockBase{0};
221     std::chrono::nanoseconds FixedLatency{0};
222 
223     /* Temp storage used for mixer processing. */
224     alignas(16) float SourceData[BufferLineSize + MaxResamplerPadding];
225     alignas(16) float ResampledData[BufferLineSize];
226     alignas(16) float FilteredData[BufferLineSize];
227     union {
228         alignas(16) float HrtfSourceData[BufferLineSize + HrtfHistoryLength];
229         alignas(16) float NfcSampleData[BufferLineSize];
230     };
231 
232     /* Persistent storage for HRTF mixing. */
233     alignas(16) float2 HrtfAccumData[BufferLineSize + HrirLength + HrtfDirectDelay];
234 
235     /* Mixing buffer used by the Dry mix and Real output. */
236     al::vector<FloatBufferLine, 16> MixBuffer;
237 
238     /* The "dry" path corresponds to the main output. */
239     MixParams Dry;
240     uint NumChannelsPerOrder[MaxAmbiOrder+1]{};
241 
242     /* "Real" output, which will be written to the device buffer. May alias the
243      * dry buffer.
244      */
245     RealMixParams RealOut;
246 
247     /* HRTF state and info */
248     std::unique_ptr<DirectHrtfState> mHrtfState;
249     al::intrusive_ptr<HrtfStore> mHrtf;
250     uint mIrSize{0};
251 
252     /* Ambisonic-to-UHJ encoder */
253     std::unique_ptr<Uhj2Encoder> Uhj_Encoder;
254 
255     /* Ambisonic decoder for speakers */
256     std::unique_ptr<BFormatDec> AmbiDecoder;
257 
258     /* Stereo-to-binaural filter */
259     std::unique_ptr<bs2b> Bs2b;
260 
261     using PostProc = void(ALCdevice::*)(const size_t SamplesToDo);
262     PostProc PostProcess{nullptr};
263 
264     std::unique_ptr<Compressor> Limiter;
265 
266     /* Delay buffers used to compensate for speaker distances. */
267     std::unique_ptr<DistanceComp> ChannelDelays;
268 
269     /* Dithering control. */
270     float DitherDepth{0.0f};
271     uint DitherSeed{0u};
272 
273     /* Running count of the mixer invocations, in 31.1 fixed point. This
274      * actually increments *twice* when mixing, first at the start and then at
275      * the end, so the bottom bit indicates if the device is currently mixing
276      * and the upper bits indicates how many mixes have been done.
277      */
278     RefCount MixCount{0u};
279 
280     // Contexts created on this device
281     std::atomic<al::FlexArray<ALCcontext*>*> mContexts{nullptr};
282 
283     /* This lock protects the device state (format, update size, etc) from
284      * being from being changed in multiple threads, or being accessed while
285      * being changed. It's also used to serialize calls to the backend.
286      */
287     std::mutex StateLock;
288     std::unique_ptr<BackendBase> Backend;
289 
290 
291     ALCuint NumMonoSources{};
292     ALCuint NumStereoSources{};
293     ALCuint NumAuxSends{};
294 
295     std::string HrtfName;
296     al::vector<std::string> HrtfList;
297     ALCenum HrtfStatus{ALC_FALSE};
298 
299     ALCenum LimiterState{ALC_DONT_CARE_SOFT};
300 
301     std::atomic<ALCenum> LastError{ALC_NO_ERROR};
302 
303     // Map of Buffers for this device
304     std::mutex BufferLock;
305     al::vector<BufferSubList> BufferList;
306 
307     // Map of Effects for this device
308     std::mutex EffectLock;
309     al::vector<EffectSubList> EffectList;
310 
311     // Map of Filters for this device
312     std::mutex FilterLock;
313     al::vector<FilterSubList> FilterList;
314 
315 
316     ALCdevice(DeviceType type);
317     ALCdevice(const ALCdevice&) = delete;
318     ALCdevice& operator=(const ALCdevice&) = delete;
319     ~ALCdevice();
320 
bytesFromFmtALCdevice321     uint bytesFromFmt() const noexcept { return BytesFromDevFmt(FmtType); }
channelsFromFmtALCdevice322     uint channelsFromFmt() const noexcept { return ChannelsFromDevFmt(FmtChans, mAmbiOrder); }
frameSizeFromFmtALCdevice323     uint frameSizeFromFmt() const noexcept { return bytesFromFmt() * channelsFromFmt(); }
324 
waitForMixALCdevice325     uint waitForMix() const noexcept
326     {
327         uint refcount;
328         while((refcount=MixCount.load(std::memory_order_acquire))&1) {
329         }
330         return refcount;
331     }
332 
333     void ProcessHrtf(const size_t SamplesToDo);
334     void ProcessAmbiDec(const size_t SamplesToDo);
335     void ProcessAmbiDecStablized(const size_t SamplesToDo);
336     void ProcessUhj(const size_t SamplesToDo);
337     void ProcessBs2b(const size_t SamplesToDo);
338 
postProcessALCdevice339     inline void postProcess(const size_t SamplesToDo)
340     { if LIKELY(PostProcess) (this->*PostProcess)(SamplesToDo); }
341 
342     void renderSamples(void *outBuffer, const uint numSamples, const size_t frameStep);
343 
344     /* Caller must lock the device state, and the mixer must not be running. */
345     [[gnu::format(printf,2,3)]] void handleDisconnect(const char *msg, ...);
346 
347     DEF_NEWDEL(ALCdevice)
348 };
349 
350 /* Must be less than 15 characters (16 including terminating null) for
351  * compatibility with pthread_setname_np limitations. */
352 #define MIXER_THREAD_NAME "alsoft-mixer"
353 
354 #define RECORD_THREAD_NAME "alsoft-record"
355 
356 
357 extern int RTPrioLevel;
358 void SetRTPriority(void);
359 
360 /**
361  * Returns the index for the given channel name (e.g. FrontCenter), or
362  * INVALID_CHANNEL_INDEX if it doesn't exist.
363  */
GetChannelIdxByName(const RealMixParams & real,Channel chan)364 inline uint GetChannelIdxByName(const RealMixParams &real, Channel chan) noexcept
365 { return real.ChannelIndex[chan]; }
366 #define INVALID_CHANNEL_INDEX ~0u
367 
368 
369 al::vector<std::string> SearchDataFiles(const char *match, const char *subdir);
370 
371 #endif
372