1 /*************************************************************************/
2 /*  audio_driver_wasapi.cpp                                              */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #ifdef WASAPI_ENABLED
32 
33 #include "audio_driver_wasapi.h"
34 
35 #include "core/os/os.h"
36 #include "core/project_settings.h"
37 
38 #include <functiondiscoverykeys.h>
39 
40 #ifndef PKEY_Device_FriendlyName
41 
42 #undef DEFINE_PROPERTYKEY
43 /* clang-format off */
44 #define DEFINE_PROPERTYKEY(id, a, b, c, d, e, f, g, h, i, j, k, l) \
45 	const PROPERTYKEY id = { { a, b, c, { d, e, f, g, h, i, j, k, } }, l };
46 /* clang-format on */
47 
48 DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
49 #endif
50 
51 const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
52 const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
53 const IID IID_IAudioClient = __uuidof(IAudioClient);
54 const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
55 const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
56 
57 #define SAFE_RELEASE(memory) \
58 	if ((memory) != NULL) {  \
59 		(memory)->Release(); \
60 		(memory) = NULL;     \
61 	}
62 
63 #define REFTIMES_PER_SEC 10000000
64 #define REFTIMES_PER_MILLISEC 10000
65 
66 #define CAPTURE_BUFFER_CHANNELS 2
67 
68 static bool default_render_device_changed = false;
69 static bool default_capture_device_changed = false;
70 
71 class CMMNotificationClient : public IMMNotificationClient {
72 	LONG _cRef;
73 	IMMDeviceEnumerator *_pEnumerator;
74 
75 public:
CMMNotificationClient()76 	CMMNotificationClient() :
77 			_cRef(1),
78 			_pEnumerator(NULL) {}
~CMMNotificationClient()79 	virtual ~CMMNotificationClient() {
80 		if ((_pEnumerator) != NULL) {
81 			(_pEnumerator)->Release();
82 			(_pEnumerator) = NULL;
83 		}
84 	}
85 
AddRef()86 	ULONG STDMETHODCALLTYPE AddRef() {
87 		return InterlockedIncrement(&_cRef);
88 	}
89 
Release()90 	ULONG STDMETHODCALLTYPE Release() {
91 		ULONG ulRef = InterlockedDecrement(&_cRef);
92 		if (0 == ulRef) {
93 			delete this;
94 		}
95 		return ulRef;
96 	}
97 
QueryInterface(REFIID riid,VOID ** ppvInterface)98 	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) {
99 		if (IID_IUnknown == riid) {
100 			AddRef();
101 			*ppvInterface = (IUnknown *)this;
102 		} else if (__uuidof(IMMNotificationClient) == riid) {
103 			AddRef();
104 			*ppvInterface = (IMMNotificationClient *)this;
105 		} else {
106 			*ppvInterface = NULL;
107 			return E_NOINTERFACE;
108 		}
109 		return S_OK;
110 	}
111 
OnDeviceAdded(LPCWSTR pwstrDeviceId)112 	HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) {
113 		return S_OK;
114 	};
115 
OnDeviceRemoved(LPCWSTR pwstrDeviceId)116 	HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
117 		return S_OK;
118 	}
119 
OnDeviceStateChanged(LPCWSTR pwstrDeviceId,DWORD dwNewState)120 	HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) {
121 		return S_OK;
122 	}
123 
OnDefaultDeviceChanged(EDataFlow flow,ERole role,LPCWSTR pwstrDeviceId)124 	HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) {
125 		if (role == eConsole) {
126 			if (flow == eRender) {
127 				default_render_device_changed = true;
128 			} else if (flow == eCapture) {
129 				default_capture_device_changed = true;
130 			}
131 		}
132 
133 		return S_OK;
134 	}
135 
OnPropertyValueChanged(LPCWSTR pwstrDeviceId,const PROPERTYKEY key)136 	HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
137 		return S_OK;
138 	}
139 };
140 
141 static CMMNotificationClient notif_client;
142 
audio_device_init(AudioDeviceWASAPI * p_device,bool p_capture,bool reinit)143 Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool reinit) {
144 
145 	WAVEFORMATEX *pwfex;
146 	IMMDeviceEnumerator *enumerator = NULL;
147 	IMMDevice *device = NULL;
148 
149 	CoInitialize(NULL);
150 
151 	HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator);
152 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
153 
154 	if (p_device->device_name == "Default") {
155 		hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device);
156 	} else {
157 		IMMDeviceCollection *devices = NULL;
158 
159 		hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices);
160 		ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
161 
162 		LPWSTR strId = NULL;
163 		bool found = false;
164 
165 		UINT count = 0;
166 		hr = devices->GetCount(&count);
167 		ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
168 
169 		for (ULONG i = 0; i < count && !found; i++) {
170 			IMMDevice *tmp_device = NULL;
171 
172 			hr = devices->Item(i, &tmp_device);
173 			ERR_BREAK(hr != S_OK);
174 
175 			IPropertyStore *props = NULL;
176 			hr = tmp_device->OpenPropertyStore(STGM_READ, &props);
177 			ERR_BREAK(hr != S_OK);
178 
179 			PROPVARIANT propvar;
180 			PropVariantInit(&propvar);
181 
182 			hr = props->GetValue(PKEY_Device_FriendlyName, &propvar);
183 			ERR_BREAK(hr != S_OK);
184 
185 			if (p_device->device_name == String(propvar.pwszVal)) {
186 				hr = tmp_device->GetId(&strId);
187 				ERR_BREAK(hr != S_OK);
188 
189 				found = true;
190 			}
191 
192 			PropVariantClear(&propvar);
193 			props->Release();
194 			tmp_device->Release();
195 		}
196 
197 		if (found) {
198 			hr = enumerator->GetDevice(strId, &device);
199 		}
200 
201 		if (strId) {
202 			CoTaskMemFree(strId);
203 		}
204 
205 		if (device == NULL) {
206 			hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device);
207 		}
208 	}
209 
210 	if (reinit) {
211 		// In case we're trying to re-initialize the device prevent throwing this error on the console,
212 		// otherwise if there is currently no device available this will spam the console.
213 		if (hr != S_OK) {
214 			return ERR_CANT_OPEN;
215 		}
216 	} else {
217 		ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
218 	}
219 
220 	hr = enumerator->RegisterEndpointNotificationCallback(&notif_client);
221 	SAFE_RELEASE(enumerator)
222 
223 	if (hr != S_OK) {
224 		ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error");
225 	}
226 
227 	hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&p_device->audio_client);
228 	SAFE_RELEASE(device)
229 
230 	if (reinit) {
231 		if (hr != S_OK) {
232 			return ERR_CANT_OPEN;
233 		}
234 	} else {
235 		ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
236 	}
237 
238 	hr = p_device->audio_client->GetMixFormat(&pwfex);
239 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
240 
241 	print_verbose("WASAPI: wFormatTag = " + itos(pwfex->wFormatTag));
242 	print_verbose("WASAPI: nChannels = " + itos(pwfex->nChannels));
243 	print_verbose("WASAPI: nSamplesPerSec = " + itos(pwfex->nSamplesPerSec));
244 	print_verbose("WASAPI: nAvgBytesPerSec = " + itos(pwfex->nAvgBytesPerSec));
245 	print_verbose("WASAPI: nBlockAlign = " + itos(pwfex->nBlockAlign));
246 	print_verbose("WASAPI: wBitsPerSample = " + itos(pwfex->wBitsPerSample));
247 	print_verbose("WASAPI: cbSize = " + itos(pwfex->cbSize));
248 
249 	WAVEFORMATEX *closest = NULL;
250 	hr = p_device->audio_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, pwfex, &closest);
251 	if (hr == S_FALSE) {
252 		WARN_PRINT("WASAPI: Mix format is not supported by the Device");
253 		if (closest) {
254 			print_verbose("WASAPI: closest->wFormatTag = " + itos(closest->wFormatTag));
255 			print_verbose("WASAPI: closest->nChannels = " + itos(closest->nChannels));
256 			print_verbose("WASAPI: closest->nSamplesPerSec = " + itos(closest->nSamplesPerSec));
257 			print_verbose("WASAPI: closest->nAvgBytesPerSec = " + itos(closest->nAvgBytesPerSec));
258 			print_verbose("WASAPI: closest->nBlockAlign = " + itos(closest->nBlockAlign));
259 			print_verbose("WASAPI: closest->wBitsPerSample = " + itos(closest->wBitsPerSample));
260 			print_verbose("WASAPI: closest->cbSize = " + itos(closest->cbSize));
261 
262 			WARN_PRINT("WASAPI: Using closest match instead");
263 			pwfex = closest;
264 		}
265 	}
266 
267 	// Since we're using WASAPI Shared Mode we can't control any of these, we just tag along
268 	p_device->channels = pwfex->nChannels;
269 	p_device->format_tag = pwfex->wFormatTag;
270 	p_device->bits_per_sample = pwfex->wBitsPerSample;
271 	p_device->frame_size = (p_device->bits_per_sample / 8) * p_device->channels;
272 
273 	if (p_device->format_tag == WAVE_FORMAT_EXTENSIBLE) {
274 		WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE *)pwfex;
275 
276 		if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_PCM) {
277 			p_device->format_tag = WAVE_FORMAT_PCM;
278 		} else if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) {
279 			p_device->format_tag = WAVE_FORMAT_IEEE_FLOAT;
280 		} else {
281 			ERR_PRINT("WASAPI: Format not supported");
282 			ERR_FAIL_V(ERR_CANT_OPEN);
283 		}
284 	} else {
285 		if (p_device->format_tag != WAVE_FORMAT_PCM && p_device->format_tag != WAVE_FORMAT_IEEE_FLOAT) {
286 			ERR_PRINT("WASAPI: Format not supported");
287 			ERR_FAIL_V(ERR_CANT_OPEN);
288 		}
289 	}
290 
291 	DWORD streamflags = 0;
292 	if ((DWORD)mix_rate != pwfex->nSamplesPerSec) {
293 		streamflags |= AUDCLNT_STREAMFLAGS_RATEADJUST;
294 		pwfex->nSamplesPerSec = mix_rate;
295 		pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nChannels * (pwfex->wBitsPerSample / 8);
296 	}
297 
298 	hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_capture ? REFTIMES_PER_SEC : 0, 0, pwfex, NULL);
299 	ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + ".");
300 
301 	if (p_capture) {
302 		hr = p_device->audio_client->GetService(IID_IAudioCaptureClient, (void **)&p_device->capture_client);
303 	} else {
304 		hr = p_device->audio_client->GetService(IID_IAudioRenderClient, (void **)&p_device->render_client);
305 	}
306 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
307 
308 	// Free memory
309 	CoTaskMemFree(pwfex);
310 	SAFE_RELEASE(device)
311 
312 	return OK;
313 }
314 
init_render_device(bool reinit)315 Error AudioDriverWASAPI::init_render_device(bool reinit) {
316 
317 	Error err = audio_device_init(&audio_output, false, reinit);
318 	if (err != OK)
319 		return err;
320 
321 	switch (audio_output.channels) {
322 		case 2: // Stereo
323 		case 4: // Surround 3.1
324 		case 6: // Surround 5.1
325 		case 8: // Surround 7.1
326 			channels = audio_output.channels;
327 			break;
328 
329 		default:
330 			WARN_PRINTS("WASAPI: Unsupported number of channels: " + itos(audio_output.channels));
331 			channels = 2;
332 			break;
333 	}
334 
335 	UINT32 max_frames;
336 	HRESULT hr = audio_output.audio_client->GetBufferSize(&max_frames);
337 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
338 
339 	// Due to WASAPI Shared Mode we have no control of the buffer size
340 	buffer_frames = max_frames;
341 
342 	// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
343 	samples_in.resize(buffer_frames * channels);
344 
345 	input_position = 0;
346 	input_size = 0;
347 
348 	print_verbose("WASAPI: detected " + itos(channels) + " channels");
349 	print_verbose("WASAPI: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");
350 
351 	return OK;
352 }
353 
init_capture_device(bool reinit)354 Error AudioDriverWASAPI::init_capture_device(bool reinit) {
355 
356 	Error err = audio_device_init(&audio_input, true, reinit);
357 	if (err != OK)
358 		return err;
359 
360 	// Get the max frames
361 	UINT32 max_frames;
362 	HRESULT hr = audio_input.audio_client->GetBufferSize(&max_frames);
363 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
364 
365 	input_buffer_init(max_frames);
366 
367 	return OK;
368 }
369 
audio_device_finish(AudioDeviceWASAPI * p_device)370 Error AudioDriverWASAPI::audio_device_finish(AudioDeviceWASAPI *p_device) {
371 
372 	if (p_device->active) {
373 		if (p_device->audio_client) {
374 			p_device->audio_client->Stop();
375 		}
376 
377 		p_device->active = false;
378 	}
379 
380 	SAFE_RELEASE(p_device->audio_client)
381 	SAFE_RELEASE(p_device->render_client)
382 	SAFE_RELEASE(p_device->capture_client)
383 
384 	return OK;
385 }
386 
finish_render_device()387 Error AudioDriverWASAPI::finish_render_device() {
388 
389 	return audio_device_finish(&audio_output);
390 }
391 
finish_capture_device()392 Error AudioDriverWASAPI::finish_capture_device() {
393 
394 	return audio_device_finish(&audio_input);
395 }
396 
init()397 Error AudioDriverWASAPI::init() {
398 
399 	mix_rate = GLOBAL_GET("audio/mix_rate");
400 
401 	Error err = init_render_device();
402 	if (err != OK) {
403 		ERR_PRINT("WASAPI: init_render_device error");
404 	}
405 
406 	exit_thread = false;
407 	thread_exited = false;
408 
409 	mutex = Mutex::create(true);
410 	thread = Thread::create(thread_func, this);
411 
412 	return OK;
413 }
414 
get_mix_rate() const415 int AudioDriverWASAPI::get_mix_rate() const {
416 
417 	return mix_rate;
418 }
419 
get_speaker_mode() const420 AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const {
421 
422 	return get_speaker_mode_by_total_channels(channels);
423 }
424 
audio_device_get_list(bool p_capture)425 Array AudioDriverWASAPI::audio_device_get_list(bool p_capture) {
426 
427 	Array list;
428 	IMMDeviceCollection *devices = NULL;
429 	IMMDeviceEnumerator *enumerator = NULL;
430 
431 	list.push_back(String("Default"));
432 
433 	CoInitialize(NULL);
434 
435 	HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator);
436 	ERR_FAIL_COND_V(hr != S_OK, Array());
437 
438 	hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices);
439 	ERR_FAIL_COND_V(hr != S_OK, Array());
440 
441 	UINT count = 0;
442 	hr = devices->GetCount(&count);
443 	ERR_FAIL_COND_V(hr != S_OK, Array());
444 
445 	for (ULONG i = 0; i < count; i++) {
446 		IMMDevice *device = NULL;
447 
448 		hr = devices->Item(i, &device);
449 		ERR_BREAK(hr != S_OK);
450 
451 		IPropertyStore *props = NULL;
452 		hr = device->OpenPropertyStore(STGM_READ, &props);
453 		ERR_BREAK(hr != S_OK);
454 
455 		PROPVARIANT propvar;
456 		PropVariantInit(&propvar);
457 
458 		hr = props->GetValue(PKEY_Device_FriendlyName, &propvar);
459 		ERR_BREAK(hr != S_OK);
460 
461 		list.push_back(String(propvar.pwszVal));
462 
463 		PropVariantClear(&propvar);
464 		props->Release();
465 		device->Release();
466 	}
467 
468 	devices->Release();
469 	enumerator->Release();
470 	return list;
471 }
472 
get_device_list()473 Array AudioDriverWASAPI::get_device_list() {
474 
475 	return audio_device_get_list(false);
476 }
477 
get_device()478 String AudioDriverWASAPI::get_device() {
479 
480 	lock();
481 	String name = audio_output.device_name;
482 	unlock();
483 
484 	return name;
485 }
486 
set_device(String device)487 void AudioDriverWASAPI::set_device(String device) {
488 
489 	lock();
490 	audio_output.new_device = device;
491 	unlock();
492 }
493 
read_sample(WORD format_tag,int bits_per_sample,BYTE * buffer,int i)494 int32_t AudioDriverWASAPI::read_sample(WORD format_tag, int bits_per_sample, BYTE *buffer, int i) {
495 	if (format_tag == WAVE_FORMAT_PCM) {
496 		int32_t sample = 0;
497 		switch (bits_per_sample) {
498 			case 8:
499 				sample = int32_t(((int8_t *)buffer)[i]) << 24;
500 				break;
501 
502 			case 16:
503 				sample = int32_t(((int16_t *)buffer)[i]) << 16;
504 				break;
505 
506 			case 24:
507 				sample |= int32_t(((int8_t *)buffer)[i * 3 + 2]) << 24;
508 				sample |= int32_t(((int8_t *)buffer)[i * 3 + 1]) << 16;
509 				sample |= int32_t(((int8_t *)buffer)[i * 3 + 0]) << 8;
510 				break;
511 
512 			case 32:
513 				sample = ((int32_t *)buffer)[i];
514 				break;
515 		}
516 
517 		return sample;
518 	} else if (format_tag == WAVE_FORMAT_IEEE_FLOAT) {
519 		return int32_t(((float *)buffer)[i] * 32768.0) << 16;
520 	} else {
521 		ERR_PRINT("WASAPI: Unknown format tag");
522 	}
523 
524 	return 0;
525 }
526 
write_sample(WORD format_tag,int bits_per_sample,BYTE * buffer,int i,int32_t sample)527 void AudioDriverWASAPI::write_sample(WORD format_tag, int bits_per_sample, BYTE *buffer, int i, int32_t sample) {
528 	if (format_tag == WAVE_FORMAT_PCM) {
529 		switch (bits_per_sample) {
530 			case 8:
531 				((int8_t *)buffer)[i] = sample >> 24;
532 				break;
533 
534 			case 16:
535 				((int16_t *)buffer)[i] = sample >> 16;
536 				break;
537 
538 			case 24:
539 				((int8_t *)buffer)[i * 3 + 2] = sample >> 24;
540 				((int8_t *)buffer)[i * 3 + 1] = sample >> 16;
541 				((int8_t *)buffer)[i * 3 + 0] = sample >> 8;
542 				break;
543 
544 			case 32:
545 				((int32_t *)buffer)[i] = sample;
546 				break;
547 		}
548 	} else if (format_tag == WAVE_FORMAT_IEEE_FLOAT) {
549 		((float *)buffer)[i] = (sample >> 16) / 32768.f;
550 	} else {
551 		ERR_PRINT("WASAPI: Unknown format tag");
552 	}
553 }
554 
thread_func(void * p_udata)555 void AudioDriverWASAPI::thread_func(void *p_udata) {
556 
557 	AudioDriverWASAPI *ad = (AudioDriverWASAPI *)p_udata;
558 	uint32_t avail_frames = 0;
559 	uint32_t write_ofs = 0;
560 
561 	while (!ad->exit_thread) {
562 
563 		uint32_t read_frames = 0;
564 		uint32_t written_frames = 0;
565 
566 		if (avail_frames == 0) {
567 			ad->lock();
568 			ad->start_counting_ticks();
569 
570 			if (ad->audio_output.active) {
571 				ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw());
572 			} else {
573 				for (int i = 0; i < ad->samples_in.size(); i++) {
574 					ad->samples_in.write[i] = 0;
575 				}
576 			}
577 
578 			avail_frames = ad->buffer_frames;
579 			write_ofs = 0;
580 
581 			ad->stop_counting_ticks();
582 			ad->unlock();
583 		}
584 
585 		ad->lock();
586 		ad->start_counting_ticks();
587 
588 		if (avail_frames > 0 && ad->audio_output.audio_client) {
589 
590 			UINT32 cur_frames;
591 			bool invalidated = false;
592 			HRESULT hr = ad->audio_output.audio_client->GetCurrentPadding(&cur_frames);
593 			if (hr == S_OK) {
594 
595 				// Check how much frames are available on the WASAPI buffer
596 				UINT32 write_frames = MIN(ad->buffer_frames - cur_frames, avail_frames);
597 				if (write_frames > 0) {
598 					BYTE *buffer = NULL;
599 					hr = ad->audio_output.render_client->GetBuffer(write_frames, &buffer);
600 					if (hr == S_OK) {
601 
602 						// We're using WASAPI Shared Mode so we must convert the buffer
603 						if (ad->channels == ad->audio_output.channels) {
604 							for (unsigned int i = 0; i < write_frames * ad->channels; i++) {
605 								ad->write_sample(ad->audio_output.format_tag, ad->audio_output.bits_per_sample, buffer, i, ad->samples_in.write[write_ofs++]);
606 							}
607 						} else {
608 							for (unsigned int i = 0; i < write_frames; i++) {
609 								for (unsigned int j = 0; j < MIN(ad->channels, ad->audio_output.channels); j++) {
610 									ad->write_sample(ad->audio_output.format_tag, ad->audio_output.bits_per_sample, buffer, i * ad->audio_output.channels + j, ad->samples_in.write[write_ofs++]);
611 								}
612 								if (ad->audio_output.channels > ad->channels) {
613 									for (unsigned int j = ad->channels; j < ad->audio_output.channels; j++) {
614 										ad->write_sample(ad->audio_output.format_tag, ad->audio_output.bits_per_sample, buffer, i * ad->audio_output.channels + j, 0);
615 									}
616 								}
617 							}
618 						}
619 
620 						hr = ad->audio_output.render_client->ReleaseBuffer(write_frames, 0);
621 						if (hr != S_OK) {
622 							ERR_PRINT("WASAPI: Release buffer error");
623 						}
624 
625 						avail_frames -= write_frames;
626 						written_frames += write_frames;
627 					} else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) {
628 						// Device is not valid anymore, reopen it
629 
630 						Error err = ad->finish_render_device();
631 						if (err != OK) {
632 							ERR_PRINT("WASAPI: finish_render_device error");
633 						} else {
634 							// We reopened the device and samples_in may have resized, so invalidate the current avail_frames
635 							avail_frames = 0;
636 						}
637 					} else {
638 						ERR_PRINT("WASAPI: Get buffer error");
639 						ad->exit_thread = true;
640 					}
641 				}
642 			} else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) {
643 				invalidated = true;
644 			} else {
645 				ERR_PRINT("WASAPI: GetCurrentPadding error");
646 			}
647 
648 			if (invalidated) {
649 				// Device is not valid anymore
650 				WARN_PRINT("WASAPI: Current device invalidated, closing device");
651 
652 				Error err = ad->finish_render_device();
653 				if (err != OK) {
654 					ERR_PRINT("WASAPI: finish_render_device error");
655 				}
656 			}
657 		}
658 
659 		// If we're using the Default device and it changed finish it so we'll re-init the device
660 		if (ad->audio_output.device_name == "Default" && default_render_device_changed) {
661 			Error err = ad->finish_render_device();
662 			if (err != OK) {
663 				ERR_PRINT("WASAPI: finish_render_device error");
664 			}
665 
666 			default_render_device_changed = false;
667 		}
668 
669 		// User selected a new device, finish the current one so we'll init the new device
670 		if (ad->audio_output.device_name != ad->audio_output.new_device) {
671 			ad->audio_output.device_name = ad->audio_output.new_device;
672 			Error err = ad->finish_render_device();
673 			if (err != OK) {
674 				ERR_PRINT("WASAPI: finish_render_device error");
675 			}
676 		}
677 
678 		if (!ad->audio_output.audio_client) {
679 			Error err = ad->init_render_device(true);
680 			if (err == OK) {
681 				ad->start();
682 			}
683 
684 			avail_frames = 0;
685 			write_ofs = 0;
686 		}
687 
688 		if (ad->audio_input.active) {
689 			UINT32 packet_length = 0;
690 			BYTE *data;
691 			UINT32 num_frames_available;
692 			DWORD flags;
693 
694 			HRESULT hr = ad->audio_input.capture_client->GetNextPacketSize(&packet_length);
695 			if (hr == S_OK) {
696 				while (packet_length != 0) {
697 					hr = ad->audio_input.capture_client->GetBuffer(&data, &num_frames_available, &flags, NULL, NULL);
698 					ERR_BREAK(hr != S_OK);
699 
700 					// fixme: Only works for floating point atm
701 					for (UINT32 j = 0; j < num_frames_available; j++) {
702 						int32_t l, r;
703 
704 						if (flags & AUDCLNT_BUFFERFLAGS_SILENT) {
705 							l = r = 0;
706 						} else {
707 							if (ad->audio_input.channels == 2) {
708 								l = read_sample(ad->audio_input.format_tag, ad->audio_input.bits_per_sample, data, j * 2);
709 								r = read_sample(ad->audio_input.format_tag, ad->audio_input.bits_per_sample, data, j * 2 + 1);
710 							} else if (ad->audio_input.channels == 1) {
711 								l = r = read_sample(ad->audio_input.format_tag, ad->audio_input.bits_per_sample, data, j);
712 							} else {
713 								l = r = 0;
714 								ERR_PRINT("WASAPI: unsupported channel count in microphone!");
715 							}
716 						}
717 
718 						ad->input_buffer_write(l);
719 						ad->input_buffer_write(r);
720 					}
721 
722 					read_frames += num_frames_available;
723 
724 					hr = ad->audio_input.capture_client->ReleaseBuffer(num_frames_available);
725 					ERR_BREAK(hr != S_OK);
726 
727 					hr = ad->audio_input.capture_client->GetNextPacketSize(&packet_length);
728 					ERR_BREAK(hr != S_OK);
729 				}
730 			}
731 
732 			// If we're using the Default device and it changed finish it so we'll re-init the device
733 			if (ad->audio_input.device_name == "Default" && default_capture_device_changed) {
734 				Error err = ad->finish_capture_device();
735 				if (err != OK) {
736 					ERR_PRINT("WASAPI: finish_capture_device error");
737 				}
738 
739 				default_capture_device_changed = false;
740 			}
741 
742 			// User selected a new device, finish the current one so we'll init the new device
743 			if (ad->audio_input.device_name != ad->audio_input.new_device) {
744 				ad->audio_input.device_name = ad->audio_input.new_device;
745 				Error err = ad->finish_capture_device();
746 				if (err != OK) {
747 					ERR_PRINT("WASAPI: finish_capture_device error");
748 				}
749 			}
750 
751 			if (!ad->audio_input.audio_client) {
752 				Error err = ad->init_capture_device(true);
753 				if (err == OK) {
754 					ad->capture_start();
755 				}
756 			}
757 		}
758 
759 		ad->stop_counting_ticks();
760 		ad->unlock();
761 
762 		// Let the thread rest a while if we haven't read or write anything
763 		if (written_frames == 0 && read_frames == 0) {
764 			OS::get_singleton()->delay_usec(1000);
765 		}
766 	}
767 
768 	ad->thread_exited = true;
769 }
770 
start()771 void AudioDriverWASAPI::start() {
772 
773 	if (audio_output.audio_client) {
774 		HRESULT hr = audio_output.audio_client->Start();
775 		if (hr != S_OK) {
776 			ERR_PRINT("WASAPI: Start failed");
777 		} else {
778 			audio_output.active = true;
779 		}
780 	}
781 }
782 
lock()783 void AudioDriverWASAPI::lock() {
784 
785 	if (mutex)
786 		mutex->lock();
787 }
788 
unlock()789 void AudioDriverWASAPI::unlock() {
790 
791 	if (mutex)
792 		mutex->unlock();
793 }
794 
finish()795 void AudioDriverWASAPI::finish() {
796 
797 	if (thread) {
798 		exit_thread = true;
799 		Thread::wait_to_finish(thread);
800 
801 		memdelete(thread);
802 		thread = NULL;
803 	}
804 
805 	finish_capture_device();
806 	finish_render_device();
807 
808 	if (mutex) {
809 		memdelete(mutex);
810 		mutex = NULL;
811 	}
812 }
813 
capture_start()814 Error AudioDriverWASAPI::capture_start() {
815 
816 	Error err = init_capture_device();
817 	if (err != OK) {
818 		ERR_PRINT("WASAPI: init_capture_device error");
819 		return err;
820 	}
821 
822 	if (audio_input.active) {
823 		return FAILED;
824 	}
825 
826 	audio_input.audio_client->Start();
827 	audio_input.active = true;
828 	return OK;
829 }
830 
capture_stop()831 Error AudioDriverWASAPI::capture_stop() {
832 
833 	if (audio_input.active) {
834 		audio_input.audio_client->Stop();
835 		audio_input.active = false;
836 
837 		return OK;
838 	}
839 
840 	return FAILED;
841 }
842 
capture_set_device(const String & p_name)843 void AudioDriverWASAPI::capture_set_device(const String &p_name) {
844 
845 	lock();
846 	audio_input.new_device = p_name;
847 	unlock();
848 }
849 
capture_get_device_list()850 Array AudioDriverWASAPI::capture_get_device_list() {
851 
852 	return audio_device_get_list(true);
853 }
854 
capture_get_device()855 String AudioDriverWASAPI::capture_get_device() {
856 
857 	lock();
858 	String name = audio_input.device_name;
859 	unlock();
860 
861 	return name;
862 }
863 
AudioDriverWASAPI()864 AudioDriverWASAPI::AudioDriverWASAPI() {
865 
866 	mutex = NULL;
867 	thread = NULL;
868 
869 	samples_in.clear();
870 
871 	channels = 0;
872 	mix_rate = 0;
873 	buffer_frames = 0;
874 
875 	thread_exited = false;
876 	exit_thread = false;
877 }
878 
879 #endif
880