xaudio2.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #include "xaudio2.hpp"
  2. #undef interface
  3. struct AudioXAudio2 : AudioDriver, public IXAudio2VoiceCallback {
  4. enum : uint { Buffers = 32 };
  5. AudioXAudio2& self = *this;
  6. AudioXAudio2(Audio& super) : AudioDriver(super) { construct(); }
  7. ~AudioXAudio2() { destruct(); }
  8. auto create() -> bool override {
  9. super.setDevice(hasDevices().first());
  10. super.setChannels(2);
  11. super.setFrequency(48000);
  12. super.setLatency(40);
  13. return initialize();
  14. }
  15. auto driver() -> string override { return "XAudio 2.1"; }
  16. auto ready() -> bool override { return self.isReady; }
  17. auto hasBlocking() -> bool override { return true; }
  18. auto hasDynamic() -> bool override { return true; }
  19. auto hasDevices() -> vector<string> override {
  20. vector<string> devices;
  21. for(auto& device : self.devices) devices.append(device.name);
  22. return devices;
  23. }
  24. auto hasFrequencies() -> vector<uint> override {
  25. return {44100, 48000, 96000};
  26. }
  27. auto hasLatencies() -> vector<uint> override {
  28. return {20, 40, 60, 80, 100};
  29. }
  30. auto setDevice(string device) -> bool override { return initialize(); }
  31. auto setBlocking(bool blocking) -> bool override { return true; }
  32. auto setFrequency(uint frequency) -> bool override { return initialize(); }
  33. auto setLatency(uint latency) -> bool override { return initialize(); }
  34. auto clear() -> void override {
  35. self.sourceVoice->Stop(0);
  36. self.sourceVoice->FlushSourceBuffers(); //calls OnBufferEnd for all currently submitted buffers
  37. self.index = 0;
  38. self.queue = 0;
  39. for(uint n : range(Buffers)) self.buffers[n].fill();
  40. self.sourceVoice->Start(0);
  41. }
  42. auto level() -> double override {
  43. XAUDIO2_VOICE_STATE state{};
  44. self.sourceVoice->GetState(&state);
  45. uint level = state.BuffersQueued * self.period + buffers[self.index].size() - state.SamplesPlayed % self.period;
  46. uint limit = Buffers * self.period;
  47. return (double)level / limit;
  48. }
  49. auto output(const double samples[]) -> void override {
  50. uint32_t frame = 0;
  51. frame |= (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
  52. frame |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
  53. auto& buffer = self.buffers[self.index];
  54. buffer.write(frame);
  55. if(!buffer.full()) return;
  56. buffer.flush();
  57. if(self.queue == Buffers - 1) {
  58. if(self.blocking) {
  59. //wait until there is at least one other free buffer for the next sample
  60. while(self.queue == Buffers - 1);
  61. } else {
  62. //there is no free buffer for the next block, so ignore the current contents
  63. return;
  64. }
  65. }
  66. write(buffer.data(), buffer.capacity<uint8_t>());
  67. self.index = (self.index + 1) % Buffers;
  68. }
  69. private:
  70. struct Device {
  71. uint id = 0;
  72. uint channels = 0;
  73. uint frequency = 0;
  74. Format format = Format::none;
  75. string name;
  76. };
  77. vector<Device> devices;
  78. auto construct() -> void {
  79. XAudio2Create(&self.interface, 0 , XAUDIO2_DEFAULT_PROCESSOR);
  80. uint deviceCount = 0;
  81. self.interface->GetDeviceCount(&deviceCount);
  82. for(uint deviceIndex : range(deviceCount)) {
  83. XAUDIO2_DEVICE_DETAILS deviceDetails{};
  84. self.interface->GetDeviceDetails(deviceIndex, &deviceDetails);
  85. auto format = deviceDetails.OutputFormat.Format.wFormatTag;
  86. auto bits = deviceDetails.OutputFormat.Format.wBitsPerSample;
  87. Device device;
  88. device.id = deviceIndex;
  89. device.name = (const char*)utf8_t(deviceDetails.DisplayName);
  90. device.channels = deviceDetails.OutputFormat.Format.nChannels;
  91. device.frequency = deviceDetails.OutputFormat.Format.nSamplesPerSec;
  92. if(format == WAVE_FORMAT_PCM) {
  93. if(bits == 16) device.format = Format::int16;
  94. if(bits == 32) device.format = Format::int32;
  95. } else if(format == WAVE_FORMAT_IEEE_FLOAT) {
  96. if(bits == 32) device.format = Format::float32;
  97. }
  98. //ensure devices.first() is the default device
  99. if(deviceDetails.Role & DefaultGameDevice) {
  100. devices.prepend(device);
  101. } else {
  102. devices.append(device);
  103. }
  104. }
  105. }
  106. auto destruct() -> void {
  107. terminate();
  108. if(self.interface) {
  109. self.interface->Release();
  110. self.interface = nullptr;
  111. }
  112. }
  113. auto initialize() -> bool {
  114. terminate();
  115. if(!self.interface) return false;
  116. self.period = self.frequency * self.latency / Buffers / 1000.0 + 0.5;
  117. for(uint n : range(Buffers)) buffers[n].resize(self.period);
  118. self.index = 0;
  119. self.queue = 0;
  120. if(!hasDevices().find(self.device)) self.device = hasDevices().first();
  121. uint deviceID = devices[hasDevices().find(self.device)()].id;
  122. if(FAILED(self.interface->CreateMasteringVoice(&self.masterVoice, self.channels, self.frequency, 0, deviceID, nullptr))) return terminate(), false;
  123. WAVEFORMATEX waveFormat{};
  124. waveFormat.wFormatTag = WAVE_FORMAT_PCM;
  125. waveFormat.nChannels = self.channels;
  126. waveFormat.nSamplesPerSec = self.frequency;
  127. waveFormat.nBlockAlign = 4;
  128. waveFormat.wBitsPerSample = 16;
  129. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  130. waveFormat.cbSize = 0;
  131. if(FAILED(self.interface->CreateSourceVoice(&self.sourceVoice, (WAVEFORMATEX*)&waveFormat, XAUDIO2_VOICE_NOSRC, XAUDIO2_DEFAULT_FREQ_RATIO, this, nullptr, nullptr))) return terminate(), false;
  132. clear();
  133. return self.isReady = true;
  134. }
  135. auto terminate() -> void {
  136. self.isReady = false;
  137. if(self.sourceVoice) {
  138. self.sourceVoice->Stop(0);
  139. self.sourceVoice->DestroyVoice();
  140. self.sourceVoice = nullptr;
  141. }
  142. if(self.masterVoice) {
  143. self.masterVoice->DestroyVoice();
  144. self.masterVoice = nullptr;
  145. }
  146. }
  147. auto write(const uint32_t* audioData, uint bytes) -> void {
  148. XAUDIO2_BUFFER buffer{};
  149. buffer.AudioBytes = bytes;
  150. buffer.pAudioData = (const BYTE*)audioData;
  151. buffer.pContext = nullptr;
  152. InterlockedIncrement(&self.queue);
  153. self.sourceVoice->SubmitSourceBuffer(&buffer);
  154. }
  155. bool isReady = false;
  156. queue<uint32_t> buffers[Buffers];
  157. uint period = 0; //amount (in 32-bit frames) of samples per buffer
  158. uint index = 0; //current buffer for writing samples to
  159. volatile long queue = 0; //how many buffers are queued and ready for playback
  160. IXAudio2* interface = nullptr;
  161. IXAudio2MasteringVoice* masterVoice = nullptr;
  162. IXAudio2SourceVoice* sourceVoice = nullptr;
  163. //inherited from IXAudio2VoiceCallback
  164. STDMETHODIMP_(void) OnBufferStart(void* pBufferContext){}
  165. STDMETHODIMP_(void) OnLoopEnd(void* pBufferContext){}
  166. STDMETHODIMP_(void) OnStreamEnd() {}
  167. STDMETHODIMP_(void) OnVoiceError(void* pBufferContext, HRESULT Error) {}
  168. STDMETHODIMP_(void) OnVoiceProcessingPassEnd() {}
  169. STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {}
  170. STDMETHODIMP_(void) OnBufferEnd(void* pBufferContext) {
  171. InterlockedDecrement(&self.queue);
  172. }
  173. };