base.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #include "config.h"
  2. #include "base.h"
  3. #include <atomic>
  4. #include <thread>
  5. #ifdef _WIN32
  6. #define WIN32_LEAN_AND_MEAN
  7. #include <windows.h>
  8. #include <mmreg.h>
  9. #endif
  10. #include "albit.h"
  11. #include "alcmain.h"
  12. #include "alnumeric.h"
  13. #include "aloptional.h"
  14. #include "atomic.h"
  15. #include "core/logging.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 DevFmtX51Rear:
  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[BackLeft] = 4;
  72. mDevice->RealOut.ChannelIndex[BackRight] = 5;
  73. break;
  74. case DevFmtX61:
  75. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  76. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  77. mDevice->RealOut.ChannelIndex[FrontCenter] = 2;
  78. mDevice->RealOut.ChannelIndex[LFE] = 3;
  79. mDevice->RealOut.ChannelIndex[BackCenter] = 4;
  80. mDevice->RealOut.ChannelIndex[SideLeft] = 5;
  81. mDevice->RealOut.ChannelIndex[SideRight] = 6;
  82. break;
  83. case DevFmtX71:
  84. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  85. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  86. mDevice->RealOut.ChannelIndex[FrontCenter] = 2;
  87. mDevice->RealOut.ChannelIndex[LFE] = 3;
  88. mDevice->RealOut.ChannelIndex[BackLeft] = 4;
  89. mDevice->RealOut.ChannelIndex[BackRight] = 5;
  90. mDevice->RealOut.ChannelIndex[SideLeft] = 6;
  91. mDevice->RealOut.ChannelIndex[SideRight] = 7;
  92. break;
  93. case DevFmtAmbi3D:
  94. break;
  95. }
  96. }
  97. void BackendBase::setDefaultChannelOrder()
  98. {
  99. mDevice->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
  100. switch(mDevice->FmtChans)
  101. {
  102. case DevFmtX51Rear:
  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. return;
  110. case DevFmtX71:
  111. mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
  112. mDevice->RealOut.ChannelIndex[FrontRight] = 1;
  113. mDevice->RealOut.ChannelIndex[BackLeft] = 2;
  114. mDevice->RealOut.ChannelIndex[BackRight] = 3;
  115. mDevice->RealOut.ChannelIndex[FrontCenter] = 4;
  116. mDevice->RealOut.ChannelIndex[LFE] = 5;
  117. mDevice->RealOut.ChannelIndex[SideLeft] = 6;
  118. mDevice->RealOut.ChannelIndex[SideRight] = 7;
  119. return;
  120. /* Same as WFX order */
  121. case DevFmtMono:
  122. case DevFmtStereo:
  123. case DevFmtQuad:
  124. case DevFmtX51:
  125. case DevFmtX61:
  126. case DevFmtAmbi3D:
  127. setDefaultWFXChannelOrder();
  128. break;
  129. }
  130. }
  131. #ifdef _WIN32
  132. void BackendBase::setChannelOrderFromWFXMask(uint chanmask)
  133. {
  134. auto get_channel = [](const DWORD chanbit) noexcept -> al::optional<Channel>
  135. {
  136. switch(chanbit)
  137. {
  138. case SPEAKER_FRONT_LEFT: return al::make_optional(FrontLeft);
  139. case SPEAKER_FRONT_RIGHT: return al::make_optional(FrontRight);
  140. case SPEAKER_FRONT_CENTER: return al::make_optional(FrontCenter);
  141. case SPEAKER_LOW_FREQUENCY: return al::make_optional(LFE);
  142. case SPEAKER_BACK_LEFT: return al::make_optional(BackLeft);
  143. case SPEAKER_BACK_RIGHT: return al::make_optional(BackRight);
  144. case SPEAKER_FRONT_LEFT_OF_CENTER: break;
  145. case SPEAKER_FRONT_RIGHT_OF_CENTER: break;
  146. case SPEAKER_BACK_CENTER: return al::make_optional(BackCenter);
  147. case SPEAKER_SIDE_LEFT: return al::make_optional(SideLeft);
  148. case SPEAKER_SIDE_RIGHT: return al::make_optional(SideRight);
  149. case SPEAKER_TOP_CENTER: return al::make_optional(TopCenter);
  150. case SPEAKER_TOP_FRONT_LEFT: return al::make_optional(TopFrontLeft);
  151. case SPEAKER_TOP_FRONT_CENTER: return al::make_optional(TopFrontCenter);
  152. case SPEAKER_TOP_FRONT_RIGHT: return al::make_optional(TopFrontRight);
  153. case SPEAKER_TOP_BACK_LEFT: return al::make_optional(TopBackLeft);
  154. case SPEAKER_TOP_BACK_CENTER: return al::make_optional(TopBackCenter);
  155. case SPEAKER_TOP_BACK_RIGHT: return al::make_optional(TopBackRight);
  156. }
  157. WARN("Unhandled WFX channel bit 0x%lx\n", chanbit);
  158. return al::nullopt;
  159. };
  160. const uint numchans{mDevice->channelsFromFmt()};
  161. uint idx{0};
  162. while(chanmask)
  163. {
  164. const int bit{al::countr_zero(chanmask)};
  165. const uint mask{1u << bit};
  166. chanmask &= ~mask;
  167. if(auto label = get_channel(mask))
  168. {
  169. mDevice->RealOut.ChannelIndex[*label] = idx;
  170. if(++idx == numchans) break;
  171. }
  172. }
  173. }
  174. #endif