🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
8.2 KiB

  1. #ifndef CORE_DEVICE_H
  2. #define CORE_DEVICE_H
  3. #include <stddef.h>
  4. #include <array>
  5. #include <atomic>
  6. #include <bitset>
  7. #include <chrono>
  8. #include <memory>
  9. #include <mutex>
  10. #include <string>
  11. #include "almalloc.h"
  12. #include "alspan.h"
  13. #include "ambidefs.h"
  14. #include "atomic.h"
  15. #include "bufferline.h"
  16. #include "devformat.h"
  17. #include "filters/nfc.h"
  18. #include "intrusive_ptr.h"
  19. #include "mixer/hrtfdefs.h"
  20. #include "opthelpers.h"
  21. #include "resampler_limits.h"
  22. #include "uhjfilter.h"
  23. #include "vector.h"
  24. class BFormatDec;
  25. struct bs2b;
  26. struct Compressor;
  27. struct ContextBase;
  28. struct DirectHrtfState;
  29. struct HrtfStore;
  30. using uint = unsigned int;
  31. #define MIN_OUTPUT_RATE 8000
  32. #define MAX_OUTPUT_RATE 192000
  33. #define DEFAULT_OUTPUT_RATE 44100
  34. #define DEFAULT_UPDATE_SIZE 882 /* 20ms */
  35. #define DEFAULT_NUM_UPDATES 3
  36. enum class DeviceType : unsigned char {
  37. Playback,
  38. Capture,
  39. Loopback
  40. };
  41. enum class RenderMode : unsigned char {
  42. Normal,
  43. Pairwise,
  44. Hrtf
  45. };
  46. enum class StereoEncoding : unsigned char {
  47. Basic,
  48. Uhj,
  49. Hrtf,
  50. Default = Basic
  51. };
  52. struct InputRemixMap {
  53. struct TargetMix { Channel channel; float mix; };
  54. Channel channel;
  55. std::array<TargetMix,2> targets;
  56. };
  57. /* Maximum delay in samples for speaker distance compensation. */
  58. #define MAX_DELAY_LENGTH 1024
  59. struct DistanceComp {
  60. struct ChanData {
  61. float Gain{1.0f};
  62. uint Length{0u}; /* Valid range is [0...MAX_DELAY_LENGTH). */
  63. float *Buffer{nullptr};
  64. };
  65. std::array<ChanData,MAX_OUTPUT_CHANNELS> mChannels;
  66. al::FlexArray<float,16> mSamples;
  67. DistanceComp(size_t count) : mSamples{count} { }
  68. static std::unique_ptr<DistanceComp> Create(size_t numsamples)
  69. { return std::unique_ptr<DistanceComp>{new(FamCount(numsamples)) DistanceComp{numsamples}}; }
  70. DEF_FAM_NEWDEL(DistanceComp, mSamples)
  71. };
  72. struct BFChannelConfig {
  73. float Scale;
  74. uint Index;
  75. };
  76. struct MixParams {
  77. /* Coefficient channel mapping for mixing to the buffer. */
  78. std::array<BFChannelConfig,MAX_OUTPUT_CHANNELS> AmbiMap{};
  79. al::span<FloatBufferLine> Buffer;
  80. };
  81. struct RealMixParams {
  82. al::span<const InputRemixMap> RemixMap;
  83. std::array<uint,MaxChannels> ChannelIndex{};
  84. al::span<FloatBufferLine> Buffer;
  85. };
  86. enum {
  87. // Frequency was requested by the app or config file
  88. FrequencyRequest,
  89. // Channel configuration was requested by the config file
  90. ChannelsRequest,
  91. // Sample type was requested by the config file
  92. SampleTypeRequest,
  93. // Specifies if the DSP is paused at user request
  94. DevicePaused,
  95. // Specifies if the device is currently running
  96. DeviceRunning,
  97. // Specifies if the output plays directly on/in ears (headphones, headset,
  98. // ear buds, etc).
  99. DirectEar,
  100. DeviceFlagsCount
  101. };
  102. struct DeviceBase {
  103. /* To avoid extraneous allocations, a 0-sized FlexArray<ContextBase*> is
  104. * defined globally as a sharable object.
  105. */
  106. static al::FlexArray<ContextBase*> sEmptyContextArray;
  107. std::atomic<bool> Connected{true};
  108. const DeviceType Type{};
  109. uint Frequency{};
  110. uint UpdateSize{};
  111. uint BufferSize{};
  112. DevFmtChannels FmtChans{};
  113. DevFmtType FmtType{};
  114. uint mAmbiOrder{0};
  115. float mXOverFreq{400.0f};
  116. /* For DevFmtAmbi* output only, specifies the channel order and
  117. * normalization.
  118. */
  119. DevAmbiLayout mAmbiLayout{DevAmbiLayout::Default};
  120. DevAmbiScaling mAmbiScale{DevAmbiScaling::Default};
  121. std::string DeviceName;
  122. // Device flags
  123. std::bitset<DeviceFlagsCount> Flags{};
  124. uint NumAuxSends{};
  125. /* Rendering mode. */
  126. RenderMode mRenderMode{RenderMode::Normal};
  127. /* The average speaker distance as determined by the ambdec configuration,
  128. * HRTF data set, or the NFC-HOA reference delay. Only used for NFC.
  129. */
  130. float AvgSpeakerDist{0.0f};
  131. /* The default NFC filter. Not used directly, but is pre-initialized with
  132. * the control distance from AvgSpeakerDist.
  133. */
  134. NfcFilter mNFCtrlFilter{};
  135. uint SamplesDone{0u};
  136. std::chrono::nanoseconds ClockBase{0};
  137. std::chrono::nanoseconds FixedLatency{0};
  138. /* Temp storage used for mixer processing. */
  139. static constexpr size_t MixerLineSize{BufferLineSize + MaxResamplerPadding +
  140. UhjDecoder::sFilterDelay};
  141. static constexpr size_t MixerChannelsMax{16};
  142. using MixerBufferLine = std::array<float,MixerLineSize>;
  143. alignas(16) std::array<MixerBufferLine,MixerChannelsMax> mSampleData;
  144. alignas(16) float ResampledData[BufferLineSize];
  145. alignas(16) float FilteredData[BufferLineSize];
  146. union {
  147. alignas(16) float HrtfSourceData[BufferLineSize + HrtfHistoryLength];
  148. alignas(16) float NfcSampleData[BufferLineSize];
  149. };
  150. /* Persistent storage for HRTF mixing. */
  151. alignas(16) float2 HrtfAccumData[BufferLineSize + HrirLength];
  152. /* Mixing buffer used by the Dry mix and Real output. */
  153. al::vector<FloatBufferLine, 16> MixBuffer;
  154. /* The "dry" path corresponds to the main output. */
  155. MixParams Dry;
  156. uint NumChannelsPerOrder[MaxAmbiOrder+1]{};
  157. /* "Real" output, which will be written to the device buffer. May alias the
  158. * dry buffer.
  159. */
  160. RealMixParams RealOut;
  161. /* HRTF state and info */
  162. std::unique_ptr<DirectHrtfState> mHrtfState;
  163. al::intrusive_ptr<HrtfStore> mHrtf;
  164. uint mIrSize{0};
  165. /* Ambisonic-to-UHJ encoder */
  166. std::unique_ptr<UhjEncoder> mUhjEncoder;
  167. /* Ambisonic decoder for speakers */
  168. std::unique_ptr<BFormatDec> AmbiDecoder;
  169. /* Stereo-to-binaural filter */
  170. std::unique_ptr<bs2b> Bs2b;
  171. using PostProc = void(DeviceBase::*)(const size_t SamplesToDo);
  172. PostProc PostProcess{nullptr};
  173. std::unique_ptr<Compressor> Limiter;
  174. /* Delay buffers used to compensate for speaker distances. */
  175. std::unique_ptr<DistanceComp> ChannelDelays;
  176. /* Dithering control. */
  177. float DitherDepth{0.0f};
  178. uint DitherSeed{0u};
  179. /* Running count of the mixer invocations, in 31.1 fixed point. This
  180. * actually increments *twice* when mixing, first at the start and then at
  181. * the end, so the bottom bit indicates if the device is currently mixing
  182. * and the upper bits indicates how many mixes have been done.
  183. */
  184. RefCount MixCount{0u};
  185. // Contexts created on this device
  186. std::atomic<al::FlexArray<ContextBase*>*> mContexts{nullptr};
  187. DeviceBase(DeviceType type);
  188. DeviceBase(const DeviceBase&) = delete;
  189. DeviceBase& operator=(const DeviceBase&) = delete;
  190. ~DeviceBase();
  191. uint bytesFromFmt() const noexcept { return BytesFromDevFmt(FmtType); }
  192. uint channelsFromFmt() const noexcept { return ChannelsFromDevFmt(FmtChans, mAmbiOrder); }
  193. uint frameSizeFromFmt() const noexcept { return bytesFromFmt() * channelsFromFmt(); }
  194. uint waitForMix() const noexcept
  195. {
  196. uint refcount;
  197. while((refcount=MixCount.load(std::memory_order_acquire))&1) {
  198. }
  199. return refcount;
  200. }
  201. void ProcessHrtf(const size_t SamplesToDo);
  202. void ProcessAmbiDec(const size_t SamplesToDo);
  203. void ProcessAmbiDecStablized(const size_t SamplesToDo);
  204. void ProcessUhj(const size_t SamplesToDo);
  205. void ProcessBs2b(const size_t SamplesToDo);
  206. inline void postProcess(const size_t SamplesToDo)
  207. { if LIKELY(PostProcess) (this->*PostProcess)(SamplesToDo); }
  208. void renderSamples(const al::span<float*> outBuffers, const uint numSamples);
  209. void renderSamples(void *outBuffer, const uint numSamples, const size_t frameStep);
  210. /* Caller must lock the device state, and the mixer must not be running. */
  211. #ifdef __USE_MINGW_ANSI_STDIO
  212. [[gnu::format(gnu_printf,2,3)]]
  213. #else
  214. [[gnu::format(printf,2,3)]]
  215. #endif
  216. void handleDisconnect(const char *msg, ...);
  217. DISABLE_ALLOC()
  218. private:
  219. uint renderSamples(const uint numSamples);
  220. };
  221. /* Must be less than 15 characters (16 including terminating null) for
  222. * compatibility with pthread_setname_np limitations. */
  223. #define MIXER_THREAD_NAME "alsoft-mixer"
  224. #define RECORD_THREAD_NAME "alsoft-record"
  225. /**
  226. * Returns the index for the given channel name (e.g. FrontCenter), or
  227. * INVALID_CHANNEL_INDEX if it doesn't exist.
  228. */
  229. inline uint GetChannelIdxByName(const RealMixParams &real, Channel chan) noexcept
  230. { return real.ChannelIndex[chan]; }
  231. #define INVALID_CHANNEL_INDEX ~0u
  232. #endif /* CORE_DEVICE_H */