22 #include "alnumeric.h"
26 #include "bufferline.h"
27 #include "devformat.h"
28 #include "filters/splitter.h"
30 #include "inprogext.h"
31 #include "intrusive_ptr.h"
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
{
60 enum class RenderMode
{
67 struct InputRemixMap
{
68 struct TargetMix
{ Channel channel
; float mix
; };
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; }
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; }
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; }
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
128 ALuint Length
{0u}; /* Valid range is [0...MAX_DELAY_LENGTH). */
129 float *Buffer
{nullptr};
133 using FloatArray
= al::FlexArray
<float,16>;
134 std::array
<DistData
,MAX_OUTPUT_CHANNELS
> mChannels
;
135 std::unique_ptr
<FloatArray
> mSamples
;
138 void setSampleCount(size_t new_size
)
139 { mSamples
= FloatArray::Create(new_size
); }
140 void clear() noexcept
142 mChannels
.fill(DistData
{});
146 float *getSamples() noexcept
{ return mSamples
->data(); }
148 al::span
<DistData
,MAX_OUTPUT_CHANNELS
> as_span() { return mChannels
; }
151 struct BFChannelConfig
{
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
160 #define MAX_RESAMPLER_PADDING 48
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
;
178 // Frequency was requested by the app or config file
180 // Channel configuration was requested by the config file
182 // Sample type was requested by the config file
185 // Specifies if the DSP is paused at user request
187 // Specifies if the device is currently running
193 struct ALCdevice
: public al::intrusive_ref
<ALCdevice
> {
194 std::atomic
<bool> Connected
{true};
195 const DeviceType Type
{};
201 DevFmtChannels FmtChans
{};
202 DevFmtType FmtType
{};
203 bool IsHeadphones
{false};
204 ALuint mAmbiOrder
{0};
205 /* For DevFmtAmbi* output only, specifies the channel order and
208 DevAmbiLayout mAmbiLayout
{DevAmbiLayout::Default
};
209 DevAmbiScaling mAmbiScale
{DevAmbiScaling::Default
};
211 ALCenum LimiterState
{ALC_DONT_CARE_SOFT
};
213 std::string DeviceName
;
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
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
];
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. */
274 ALuint NumChannelsPerOrder
[MAX_AMBI_ORDER
+1]{};
276 /* "Real" output, which will be written to the device buffer. May alias the
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;
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
336 while((refcount
=MixCount
.load(std::memory_order_acquire
))&1) {
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
);