🛠️🐜 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.

194 lines
6.7 KiB

  1. #include "config.h"
  2. #include "base.h"
  3. #include <algorithm>
  4. #include <array>
  5. #include <atomic>
  6. #ifdef _WIN32
  7. #define WIN32_LEAN_AND_MEAN
  8. #include <windows.h>
  9. #include <mmreg.h>
  10. #include "albit.h"
  11. #include "core/logging.h"
  12. #include "aloptional.h"
  13. #endif
  14. #include "atomic.h"
  15. #include "core/devformat.h"
  16. bool BackendBase::reset()
  17. { throw al::backend_exception{al::backend_error::DeviceError, "Invalid BackendBase call"}; }
  18. void BackendBase::captureSamples(al::byte*, uint)
  19. { }
  20. uint BackendBase::availableSamples()
  21. { return 0; }
  22. ClockLatency BackendBase::getClockLatency()
  23. {
  24. ClockLatency ret;
  25. uint refcount;
  26. do {
  27. refcount = mDevice->waitForMix();
  28. ret.ClockTime = GetDeviceClockTime(mDevice);
  29. std::atomic_thread_fence(std::memory_order_acquire);
  30. } while(refcount != ReadRef(mDevice->MixCount));
  31. /* NOTE: The device will generally have about all but one periods filled at
  32. * any given time during playback. Without a more accurate measurement from
  33. * the output, this is an okay approximation.
  34. */
  35. ret.Latency = std::max(std::chrono::seconds{mDevice->BufferSize-mDevice->UpdateSize},
  36. std::chrono::seconds::zero());
  37. ret.Latency /= mDevice->Frequency;
  38. return ret;
  39. }
  40. void BackendBase::setDefaultWFXChannelOrder()
  41. {
  42. mDevice->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
  43. switch(mDevice->FmtChans)
  44. {
  45. case DevFmtMono:
  46. mDevice->RealOut.ChannelIndex[FrontCenter] = 0;
  47. break;
  48. case DevFmtStereo:
  49. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  50. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  51. break;
  52. case DevFmtQuad:
  53. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  54. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  55. mDevice->RealOut.ChannelIndex[BackLeft] = 2;
  56. mDevice->RealOut.ChannelIndex[BackRight] = 3;
  57. break;
  58. case DevFmtX51:
  59. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  60. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  61. mDevice->RealOut.ChannelIndex[FrontCenter] = 2;
  62. mDevice->RealOut.ChannelIndex[LFE] = 3;
  63. mDevice->RealOut.ChannelIndex[SideLeft] = 4;
  64. mDevice->RealOut.ChannelIndex[SideRight] = 5;
  65. break;
  66. case DevFmtX61:
  67. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  68. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  69. mDevice->RealOut.ChannelIndex[FrontCenter] = 2;
  70. mDevice->RealOut.ChannelIndex[LFE] = 3;
  71. mDevice->RealOut.ChannelIndex[BackCenter] = 4;
  72. mDevice->RealOut.ChannelIndex[SideLeft] = 5;
  73. mDevice->RealOut.ChannelIndex[SideRight] = 6;
  74. break;
  75. case DevFmtX71:
  76. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  77. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  78. mDevice->RealOut.ChannelIndex[FrontCenter] = 2;
  79. mDevice->RealOut.ChannelIndex[LFE] = 3;
  80. mDevice->RealOut.ChannelIndex[BackLeft] = 4;
  81. mDevice->RealOut.ChannelIndex[BackRight] = 5;
  82. mDevice->RealOut.ChannelIndex[SideLeft] = 6;
  83. mDevice->RealOut.ChannelIndex[SideRight] = 7;
  84. break;
  85. case DevFmtAmbi3D:
  86. break;
  87. }
  88. }
  89. void BackendBase::setDefaultChannelOrder()
  90. {
  91. mDevice->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
  92. switch(mDevice->FmtChans)
  93. {
  94. case DevFmtX51:
  95. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  96. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  97. mDevice->RealOut.ChannelIndex[SideLeft] = 2;
  98. mDevice->RealOut.ChannelIndex[SideRight] = 3;
  99. mDevice->RealOut.ChannelIndex[FrontCenter] = 4;
  100. mDevice->RealOut.ChannelIndex[LFE] = 5;
  101. return;
  102. case DevFmtX71:
  103. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  104. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  105. mDevice->RealOut.ChannelIndex[BackLeft] = 2;
  106. mDevice->RealOut.ChannelIndex[BackRight] = 3;
  107. mDevice->RealOut.ChannelIndex[FrontCenter] = 4;
  108. mDevice->RealOut.ChannelIndex[LFE] = 5;
  109. mDevice->RealOut.ChannelIndex[SideLeft] = 6;
  110. mDevice->RealOut.ChannelIndex[SideRight] = 7;
  111. return;
  112. /* Same as WFX order */
  113. case DevFmtMono:
  114. case DevFmtStereo:
  115. case DevFmtQuad:
  116. case DevFmtX61:
  117. case DevFmtAmbi3D:
  118. setDefaultWFXChannelOrder();
  119. break;
  120. }
  121. }
  122. #ifdef _WIN32
  123. void BackendBase::setChannelOrderFromWFXMask(uint chanmask)
  124. {
  125. static constexpr uint x51{SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER
  126. | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT};
  127. static constexpr uint x51rear{SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER
  128. | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT};
  129. /* Swap a 5.1 mask using the back channels for one with the sides. */
  130. if(chanmask == x51rear) chanmask = x51;
  131. auto get_channel = [](const DWORD chanbit) noexcept -> al::optional<Channel>
  132. {
  133. switch(chanbit)
  134. {
  135. case SPEAKER_FRONT_LEFT: return al::make_optional(FrontLeft);
  136. case SPEAKER_FRONT_RIGHT: return al::make_optional(FrontRight);
  137. case SPEAKER_FRONT_CENTER: return al::make_optional(FrontCenter);
  138. case SPEAKER_LOW_FREQUENCY: return al::make_optional(LFE);
  139. case SPEAKER_BACK_LEFT: return al::make_optional(BackLeft);
  140. case SPEAKER_BACK_RIGHT: return al::make_optional(BackRight);
  141. case SPEAKER_FRONT_LEFT_OF_CENTER: break;
  142. case SPEAKER_FRONT_RIGHT_OF_CENTER: break;
  143. case SPEAKER_BACK_CENTER: return al::make_optional(BackCenter);
  144. case SPEAKER_SIDE_LEFT: return al::make_optional(SideLeft);
  145. case SPEAKER_SIDE_RIGHT: return al::make_optional(SideRight);
  146. case SPEAKER_TOP_CENTER: return al::make_optional(TopCenter);
  147. case SPEAKER_TOP_FRONT_LEFT: return al::make_optional(TopFrontLeft);
  148. case SPEAKER_TOP_FRONT_CENTER: return al::make_optional(TopFrontCenter);
  149. case SPEAKER_TOP_FRONT_RIGHT: return al::make_optional(TopFrontRight);
  150. case SPEAKER_TOP_BACK_LEFT: return al::make_optional(TopBackLeft);
  151. case SPEAKER_TOP_BACK_CENTER: return al::make_optional(TopBackCenter);
  152. case SPEAKER_TOP_BACK_RIGHT: return al::make_optional(TopBackRight);
  153. }
  154. WARN("Unhandled WFX channel bit 0x%lx\n", chanbit);
  155. return al::nullopt;
  156. };
  157. const uint numchans{mDevice->channelsFromFmt()};
  158. uint idx{0};
  159. while(chanmask)
  160. {
  161. const int bit{al::countr_zero(chanmask)};
  162. const uint mask{1u << bit};
  163. chanmask &= ~mask;
  164. if(auto label = get_channel(mask))
  165. {
  166. mDevice->RealOut.ChannelIndex[*label] = idx;
  167. if(++idx == numchans) break;
  168. }
  169. }
  170. }
  171. #endif