base.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #ifndef ALC_BACKENDS_BASE_H
  2. #define ALC_BACKENDS_BASE_H
  3. #include <chrono>
  4. #include <memory>
  5. #include <mutex>
  6. #include <string>
  7. #include "albyte.h"
  8. #include "alcmain.h"
  9. #include "core/except.h"
  10. using uint = unsigned int;
  11. struct ClockLatency {
  12. std::chrono::nanoseconds ClockTime;
  13. std::chrono::nanoseconds Latency;
  14. };
  15. struct BackendBase {
  16. virtual void open(const char *name) = 0;
  17. virtual bool reset();
  18. virtual void start() = 0;
  19. virtual void stop() = 0;
  20. virtual void captureSamples(al::byte *buffer, uint samples);
  21. virtual uint availableSamples();
  22. virtual ClockLatency getClockLatency();
  23. ALCdevice *const mDevice;
  24. BackendBase(ALCdevice *device) noexcept : mDevice{device} { }
  25. virtual ~BackendBase() = default;
  26. protected:
  27. /** Sets the default channel order used by most non-WaveFormatEx-based APIs. */
  28. void setDefaultChannelOrder();
  29. /** Sets the default channel order used by WaveFormatEx. */
  30. void setDefaultWFXChannelOrder();
  31. #ifdef _WIN32
  32. /** Sets the channel order given the WaveFormatEx mask. */
  33. void setChannelOrderFromWFXMask(uint chanmask);
  34. #endif
  35. };
  36. using BackendPtr = std::unique_ptr<BackendBase>;
  37. enum class BackendType {
  38. Playback,
  39. Capture
  40. };
  41. /* Helper to get the current clock time from the device's ClockBase, and
  42. * SamplesDone converted from the sample rate.
  43. */
  44. inline std::chrono::nanoseconds GetDeviceClockTime(ALCdevice *device)
  45. {
  46. using std::chrono::seconds;
  47. using std::chrono::nanoseconds;
  48. auto ns = nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
  49. return device->ClockBase + ns;
  50. }
  51. /* Helper to get the device latency from the backend, including any fixed
  52. * latency from post-processing.
  53. */
  54. inline ClockLatency GetClockLatency(ALCdevice *device)
  55. {
  56. BackendBase *backend{device->Backend.get()};
  57. ClockLatency ret{backend->getClockLatency()};
  58. ret.Latency += device->FixedLatency;
  59. return ret;
  60. }
  61. struct BackendFactory {
  62. virtual bool init() = 0;
  63. virtual bool querySupport(BackendType type) = 0;
  64. virtual std::string probe(BackendType type) = 0;
  65. virtual BackendPtr createBackend(ALCdevice *device, BackendType type) = 0;
  66. protected:
  67. virtual ~BackendFactory() = default;
  68. };
  69. namespace al {
  70. enum class backend_error {
  71. NoDevice,
  72. DeviceError,
  73. OutOfMemory
  74. };
  75. class backend_exception final : public base_exception {
  76. backend_error mErrorCode;
  77. public:
  78. [[gnu::format(printf, 3, 4)]]
  79. backend_exception(backend_error code, const char *msg, ...) : mErrorCode{code}
  80. {
  81. std::va_list args;
  82. va_start(args, msg);
  83. setMessage(msg, args);
  84. va_end(args);
  85. }
  86. backend_error errorCode() const noexcept { return mErrorCode; }
  87. };
  88. } // namespace al
  89. #endif /* ALC_BACKENDS_BASE_H */