Simplify clearing an array
[openal-soft.git] / alc / alcmain.h
blob7a6c952fccb0afe63b99b00ff0b424d9aa12a111
1 #ifndef ALC_MAIN_H
2 #define ALC_MAIN_H
4 #include <algorithm>
5 #include <array>
6 #include <atomic>
7 #include <chrono>
8 #include <cstdint>
9 #include <cstddef>
10 #include <memory>
11 #include <mutex>
12 #include <string>
13 #include <thread>
14 #include <utility>
16 #include "AL/al.h"
17 #include "AL/alc.h"
18 #include "AL/alext.h"
20 #include "albyte.h"
21 #include "almalloc.h"
22 #include "alnumeric.h"
23 #include "alspan.h"
24 #include "ambidefs.h"
25 #include "atomic.h"
26 #include "bufferline.h"
27 #include "devformat.h"
28 #include "filters/splitter.h"
29 #include "hrtf.h"
30 #include "inprogext.h"
31 #include "intrusive_ptr.h"
32 #include "vector.h"
34 class BFormatDec;
35 struct ALbuffer;
36 struct ALeffect;
37 struct ALfilter;
38 struct BackendBase;
39 struct Compressor;
40 struct EffectState;
41 struct Uhj2Encoder;
42 struct bs2b;
45 #define MIN_OUTPUT_RATE 8000
46 #define MAX_OUTPUT_RATE 192000
47 #define DEFAULT_OUTPUT_RATE 44100
49 #define DEFAULT_UPDATE_SIZE 882 /* 20ms */
50 #define DEFAULT_NUM_UPDATES 3
53 enum class DeviceType {
54 Playback,
55 Capture,
56 Loopback
60 enum class RenderMode {
61 Normal,
62 Pairwise,
63 Hrtf
67 struct InputRemixMap {
68 struct TargetMix { Channel channel; float mix; };
70 Channel channel;
71 std::array<TargetMix,2> targets;
75 struct BufferSubList {
76 uint64_t FreeMask{~0_u64};
77 ALbuffer *Buffers{nullptr}; /* 64 */
79 BufferSubList() noexcept = default;
80 BufferSubList(const BufferSubList&) = delete;
81 BufferSubList(BufferSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Buffers{rhs.Buffers}
82 { rhs.FreeMask = ~0_u64; rhs.Buffers = nullptr; }
83 ~BufferSubList();
85 BufferSubList& operator=(const BufferSubList&) = delete;
86 BufferSubList& operator=(BufferSubList&& rhs) noexcept
87 { std::swap(FreeMask, rhs.FreeMask); std::swap(Buffers, rhs.Buffers); return *this; }
90 struct EffectSubList {
91 uint64_t FreeMask{~0_u64};
92 ALeffect *Effects{nullptr}; /* 64 */
94 EffectSubList() noexcept = default;
95 EffectSubList(const EffectSubList&) = delete;
96 EffectSubList(EffectSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Effects{rhs.Effects}
97 { rhs.FreeMask = ~0_u64; rhs.Effects = nullptr; }
98 ~EffectSubList();
100 EffectSubList& operator=(const EffectSubList&) = delete;
101 EffectSubList& operator=(EffectSubList&& rhs) noexcept
102 { std::swap(FreeMask, rhs.FreeMask); std::swap(Effects, rhs.Effects); return *this; }
105 struct FilterSubList {
106 uint64_t FreeMask{~0_u64};
107 ALfilter *Filters{nullptr}; /* 64 */
109 FilterSubList() noexcept = default;
110 FilterSubList(const FilterSubList&) = delete;
111 FilterSubList(FilterSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Filters{rhs.Filters}
112 { rhs.FreeMask = ~0_u64; rhs.Filters = nullptr; }
113 ~FilterSubList();
115 FilterSubList& operator=(const FilterSubList&) = delete;
116 FilterSubList& operator=(FilterSubList&& rhs) noexcept
117 { std::swap(FreeMask, rhs.FreeMask); std::swap(Filters, rhs.Filters); return *this; }
121 /* Maximum delay in samples for speaker distance compensation. */
122 #define MAX_DELAY_LENGTH 1024
124 class DistanceComp {
125 public:
126 struct DistData {
127 float Gain{1.0f};
128 ALuint Length{0u}; /* Valid range is [0...MAX_DELAY_LENGTH). */
129 float *Buffer{nullptr};
132 private:
133 using FloatArray = al::FlexArray<float,16>;
134 std::array<DistData,MAX_OUTPUT_CHANNELS> mChannels;
135 std::unique_ptr<FloatArray> mSamples;
137 public:
138 void setSampleCount(size_t new_size)
139 { mSamples = FloatArray::Create(new_size); }
140 void clear() noexcept
142 mChannels.fill(DistData{});
143 mSamples = nullptr;
146 float *getSamples() noexcept { return mSamples->data(); }
148 al::span<DistData,MAX_OUTPUT_CHANNELS> as_span() { return mChannels; }
151 struct BFChannelConfig {
152 float Scale;
153 ALuint Index;
156 /* Maximum number of samples to pad on the ends of a buffer for resampling.
157 * Note that the padding is symmetric (half at the beginning and half at the
158 * end)!
160 #define MAX_RESAMPLER_PADDING 48
163 struct MixParams {
164 /* Coefficient channel mapping for mixing to the buffer. */
165 std::array<BFChannelConfig,MAX_OUTPUT_CHANNELS> AmbiMap{};
167 al::span<FloatBufferLine> Buffer;
170 struct RealMixParams {
171 al::span<const InputRemixMap> RemixMap;
172 std::array<ALuint,MaxChannels> ChannelIndex{};
174 al::span<FloatBufferLine> Buffer;
177 enum {
178 // Frequency was requested by the app or config file
179 FrequencyRequest,
180 // Channel configuration was requested by the config file
181 ChannelsRequest,
182 // Sample type was requested by the config file
183 SampleTypeRequest,
185 // Specifies if the DSP is paused at user request
186 DevicePaused,
187 // Specifies if the device is currently running
188 DeviceRunning,
190 DeviceFlagsCount
193 struct ALCdevice : public al::intrusive_ref<ALCdevice> {
194 std::atomic<bool> Connected{true};
195 const DeviceType Type{};
197 ALuint Frequency{};
198 ALuint UpdateSize{};
199 ALuint BufferSize{};
201 DevFmtChannels FmtChans{};
202 DevFmtType FmtType{};
203 bool IsHeadphones{false};
204 ALuint mAmbiOrder{0};
205 /* For DevFmtAmbi* output only, specifies the channel order and
206 * normalization.
208 DevAmbiLayout mAmbiLayout{DevAmbiLayout::Default};
209 DevAmbiScaling mAmbiScale{DevAmbiScaling::Default};
211 ALCenum LimiterState{ALC_DONT_CARE_SOFT};
213 std::string DeviceName;
215 // Device flags
216 al::bitfield<DeviceFlagsCount> Flags{};
218 std::string HrtfName;
219 al::vector<std::string> HrtfList;
220 ALCenum HrtfStatus{ALC_FALSE};
222 std::atomic<ALCenum> LastError{ALC_NO_ERROR};
224 // Maximum number of sources that can be created
225 ALuint SourcesMax{};
226 // Maximum number of slots that can be created
227 ALuint AuxiliaryEffectSlotMax{};
229 ALCuint NumMonoSources{};
230 ALCuint NumStereoSources{};
231 ALCuint NumAuxSends{};
233 // Map of Buffers for this device
234 std::mutex BufferLock;
235 al::vector<BufferSubList> BufferList;
237 // Map of Effects for this device
238 std::mutex EffectLock;
239 al::vector<EffectSubList> EffectList;
241 // Map of Filters for this device
242 std::mutex FilterLock;
243 al::vector<FilterSubList> FilterList;
245 /* Rendering mode. */
246 RenderMode mRenderMode{RenderMode::Normal};
248 /* The average speaker distance as determined by the ambdec configuration,
249 * HRTF data set, or the NFC-HOA reference delay. Only used for NFC.
251 float AvgSpeakerDist{0.0f};
253 ALuint SamplesDone{0u};
254 std::chrono::nanoseconds ClockBase{0};
255 std::chrono::nanoseconds FixedLatency{0};
257 /* Temp storage used for mixer processing. */
258 alignas(16) float SourceData[BUFFERSIZE + MAX_RESAMPLER_PADDING];
259 alignas(16) float ResampledData[BUFFERSIZE];
260 alignas(16) float FilteredData[BUFFERSIZE];
261 union {
262 alignas(16) float HrtfSourceData[BUFFERSIZE + HRTF_HISTORY_LENGTH];
263 alignas(16) float NfcSampleData[BUFFERSIZE];
266 /* Persistent storage for HRTF mixing. */
267 alignas(16) float2 HrtfAccumData[BUFFERSIZE + HRIR_LENGTH + HRTF_DIRECT_DELAY];
269 /* Mixing buffer used by the Dry mix and Real output. */
270 al::vector<FloatBufferLine, 16> MixBuffer;
272 /* The "dry" path corresponds to the main output. */
273 MixParams Dry;
274 ALuint NumChannelsPerOrder[MAX_AMBI_ORDER+1]{};
276 /* "Real" output, which will be written to the device buffer. May alias the
277 * dry buffer.
279 RealMixParams RealOut;
281 /* HRTF state and info */
282 std::unique_ptr<DirectHrtfState> mHrtfState;
283 al::intrusive_ptr<HrtfStore> mHrtf;
285 /* Ambisonic-to-UHJ encoder */
286 std::unique_ptr<Uhj2Encoder> Uhj_Encoder;
288 /* Ambisonic decoder for speakers */
289 std::unique_ptr<BFormatDec> AmbiDecoder;
291 /* Stereo-to-binaural filter */
292 std::unique_ptr<bs2b> Bs2b;
294 using PostProc = void(ALCdevice::*)(const size_t SamplesToDo);
295 PostProc PostProcess{nullptr};
297 std::unique_ptr<Compressor> Limiter;
299 /* Delay buffers used to compensate for speaker distances. */
300 DistanceComp ChannelDelay;
302 /* Dithering control. */
303 float DitherDepth{0.0f};
304 ALuint DitherSeed{0u};
306 /* Running count of the mixer invocations, in 31.1 fixed point. This
307 * actually increments *twice* when mixing, first at the start and then at
308 * the end, so the bottom bit indicates if the device is currently mixing
309 * and the upper bits indicates how many mixes have been done.
311 RefCount MixCount{0u};
313 // Contexts created on this device
314 std::atomic<al::FlexArray<ALCcontext*>*> mContexts{nullptr};
316 /* This lock protects the device state (format, update size, etc) from
317 * being from being changed in multiple threads, or being accessed while
318 * being changed. It's also used to serialize calls to the backend.
320 std::mutex StateLock;
321 std::unique_ptr<BackendBase> Backend;
324 ALCdevice(DeviceType type);
325 ALCdevice(const ALCdevice&) = delete;
326 ALCdevice& operator=(const ALCdevice&) = delete;
327 ~ALCdevice();
329 ALuint bytesFromFmt() const noexcept { return BytesFromDevFmt(FmtType); }
330 ALuint channelsFromFmt() const noexcept { return ChannelsFromDevFmt(FmtChans, mAmbiOrder); }
331 ALuint frameSizeFromFmt() const noexcept { return bytesFromFmt() * channelsFromFmt(); }
333 ALuint waitForMix() const noexcept
335 ALuint refcount;
336 while((refcount=MixCount.load(std::memory_order_acquire))&1) {
338 return refcount;
341 void ProcessHrtf(const size_t SamplesToDo);
342 void ProcessAmbiDec(const size_t SamplesToDo);
343 void ProcessAmbiDecStablized(const size_t SamplesToDo);
344 void ProcessUhj(const size_t SamplesToDo);
345 void ProcessBs2b(const size_t SamplesToDo);
347 inline void postProcess(const size_t SamplesToDo)
348 { if LIKELY(PostProcess) (this->*PostProcess)(SamplesToDo); }
350 void renderSamples(void *outBuffer, const ALuint numSamples, const size_t frameStep);
352 /* Caller must lock the device state, and the mixer must not be running. */
353 [[gnu::format(printf,2,3)]] void handleDisconnect(const char *msg, ...);
355 DEF_NEWDEL(ALCdevice)
358 /* Must be less than 15 characters (16 including terminating null) for
359 * compatibility with pthread_setname_np limitations. */
360 #define MIXER_THREAD_NAME "alsoft-mixer"
362 #define RECORD_THREAD_NAME "alsoft-record"
365 extern int RTPrioLevel;
366 void SetRTPriority(void);
368 const ALCchar *DevFmtTypeString(DevFmtType type) noexcept;
369 const ALCchar *DevFmtChannelsString(DevFmtChannels chans) noexcept;
372 * Returns the index for the given channel name (e.g. FrontCenter), or
373 * INVALID_CHANNEL_INDEX if it doesn't exist.
375 inline ALuint GetChannelIdxByName(const RealMixParams &real, Channel chan) noexcept
376 { return real.ChannelIndex[chan]; }
377 #define INVALID_CHANNEL_INDEX ~0u
380 al::vector<std::string> SearchDataFiles(const char *match, const char *subdir);
382 #endif