7#ifndef WIN32_LEAN_AND_MEAN
8#define WIN32_LEAN_AND_MEAN
14#include <audioclient.h>
16#include <mmdeviceapi.h>
30class WasapiBackend :
public IAudioBackend {
33 ~WasapiBackend()
override;
35 std::unique_ptr<AudioDevice> create_device_manager()
override;
37 std::unique_ptr<AudioStream> create_stream(
38 unsigned int output_device_id,
39 unsigned int input_device_id,
40 GlobalStreamInfo& stream_info,
41 void* user_data)
override;
43 [[nodiscard]] std::string get_version_string()
const override;
45 void cleanup()
override;
47 [[nodiscard]] IMMDeviceEnumerator* enumerator()
const {
return m_enumerator; }
50 IMMDeviceEnumerator* m_enumerator =
nullptr;
62class WasapiDevice :
public AudioDevice {
64 explicit WasapiDevice(IMMDeviceEnumerator* enumerator);
65 ~WasapiDevice()
override;
67 [[nodiscard]] std::vector<DeviceInfo> get_output_devices()
const override;
68 [[nodiscard]] std::vector<DeviceInfo> get_input_devices()
const override;
69 [[nodiscard]]
unsigned int get_default_output_device()
const override;
70 [[nodiscard]]
unsigned int get_default_input_device()
const override;
78 [[nodiscard]] IMMDevice* resolve_device(
unsigned int id, EDataFlow flow)
const;
81 struct EndpointEntry {
83 std::wstring endpoint_id;
86 void enumerate(IMMDeviceEnumerator* enumerator, EDataFlow flow,
87 std::vector<EndpointEntry>& out,
unsigned int& default_idx);
89 IMMDeviceEnumerator* m_enumerator =
nullptr;
91 std::vector<EndpointEntry> m_outputs;
92 std::vector<EndpointEntry> m_inputs;
94 unsigned int m_default_output = 0;
95 unsigned int m_default_input = 0;
116class WasapiStream :
public AudioStream {
119 IMMDevice* output_device,
120 IMMDevice* input_device,
121 GlobalStreamInfo& stream_info,
124 ~WasapiStream()
override;
126 void open()
override;
127 void start()
override;
128 void stop()
override;
129 void pause()
override;
130 void resume()
override;
131 void close()
override;
133 [[nodiscard]]
bool is_running()
const override;
134 [[nodiscard]]
bool is_open()
const override;
136 void set_process_callback(
137 std::function<
int(
void*,
void*,
unsigned int)> cb)
override;
140 static DWORD WINAPI render_thread_proc(LPVOID param);
151 bool negotiate_format(
152 IAudioClient* client,
154 uint32_t sample_rate,
155 WAVEFORMATEX** out_fmt);
157 IMMDevice* m_output_device =
nullptr;
158 IMMDevice* m_input_device =
nullptr;
160 IAudioClient* m_render_client =
nullptr;
161 IAudioRenderClient* m_render_sink =
nullptr;
162 IAudioClient* m_capture_client =
nullptr;
163 IAudioCaptureClient* m_capture_src =
nullptr;
165 HANDLE m_render_event =
nullptr;
166 HANDLE m_capture_event =
nullptr;
167 HANDLE m_stop_event =
nullptr;
169 HANDLE m_render_thread =
nullptr;
171 uint32_t m_render_buffer_frames = 0;
172 uint32_t m_capture_buffer_frames = 0;
174 uint32_t m_negotiated_output_rate = 0;
175 uint32_t m_negotiated_input_rate = 0;
176 uint32_t m_negotiated_output_channels = 0;
177 uint32_t m_negotiated_input_channels = 0;
179 std::vector<float> m_render_staging;
180 std::vector<double> m_output_staging;
181 std::vector<float> m_capture_staging;
182 std::vector<double> m_input_staging;
183 std::atomic<bool> m_input_ready {
false };
185 std::vector<double> m_render_ring;
186 uint32_t m_ring_write_pos { 0 };
187 uint32_t m_ring_read_pos { 0 };
188 uint32_t m_ring_frames { 0 };
189 std::vector<double> m_capture_ring;
190 uint32_t m_cap_ring_write_pos { 0 };
191 uint32_t m_cap_ring_read_pos { 0 };
192 uint32_t m_cap_ring_frames { 0 };
194 GlobalStreamInfo& m_stream_info;
195 void* m_user_data =
nullptr;
197 std::function<int(
void*,
void*,
unsigned int)> m_process_callback;
199 std::atomic<bool> m_is_open {
false };
200 std::atomic<bool> m_is_running {
false };
201 std::atomic<bool> m_is_paused {
false };
void stop()
Stop all Portal::Graphics operations.