summaryrefslogtreecommitdiff
path: root/drivers/wasapi/audio_driver_wasapi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/wasapi/audio_driver_wasapi.cpp')
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp41
1 files changed, 35 insertions, 6 deletions
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index 0b5cfceadc..403feb149e 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -121,6 +121,12 @@ const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
static bool default_render_device_changed = false;
static bool default_capture_device_changed = false;
+// Silence warning due to a COM API weirdness (GH-35194).
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
+#endif
+
class CMMNotificationClient : public IMMNotificationClient {
LONG _cRef = 1;
IMMDeviceEnumerator *_pEnumerator = nullptr;
@@ -162,7 +168,7 @@ public:
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) {
return S_OK;
- };
+ }
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
return S_OK;
@@ -189,6 +195,10 @@ public:
}
};
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
static CMMNotificationClient notif_client;
Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool reinit) {
@@ -274,7 +284,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c
ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error");
}
- bool using_audio_client_3 = !p_capture; // IID_IAudioClient3 is only used for adjustable output latency (not input)
+ using_audio_client_3 = !p_capture; // IID_IAudioClient3 is only used for adjustable output latency (not input)
if (using_audio_client_3) {
hr = device->Activate(IID_IAudioClient3, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client);
if (hr != S_OK) {
@@ -301,7 +311,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c
}
if (using_audio_client_3) {
- AudioClientProperties audioProps;
+ AudioClientProperties audioProps{};
audioProps.cbSize = sizeof(AudioClientProperties);
audioProps.bIsOffload = FALSE;
audioProps.eCategory = AudioCategory_GameEffects;
@@ -373,11 +383,21 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c
hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_capture ? REFTIMES_PER_SEC : 0, 0, pwfex, nullptr);
ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + ".");
UINT32 max_frames;
- HRESULT hr = p_device->audio_client->GetBufferSize(&max_frames);
+ hr = p_device->audio_client->GetBufferSize(&max_frames);
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
// Due to WASAPI Shared Mode we have no control of the buffer size
- buffer_frames = max_frames;
+ if (!p_capture) {
+ buffer_frames = max_frames;
+
+ int64_t latency = 0;
+ audio_output.audio_client->GetStreamLatency(&latency);
+ // WASAPI REFERENCE_TIME units are 100 nanoseconds per unit
+ // https://docs.microsoft.com/en-us/windows/win32/directshow/reference-time
+ // Convert REFTIME to seconds as godot uses for latency
+ real_latency = (float)latency / (float)REFTIMES_PER_SEC;
+ }
+
} else {
IAudioClient3 *device_audio_client_3 = (IAudioClient3 *)p_device->audio_client;
@@ -411,6 +431,11 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c
hr = device_audio_client_3->InitializeSharedAudioStream(0, period_frames, pwfex, nullptr);
ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: InitializeSharedAudioStream failed with error 0x" + String::num_uint64(hr, 16) + ".");
+ uint32_t output_latency_in_frames;
+ WAVEFORMATEX *current_pwfex;
+ device_audio_client_3->GetCurrentSharedModeEnginePeriod(&current_pwfex, &output_latency_in_frames);
+ real_latency = (float)output_latency_in_frames / (float)current_pwfex->nSamplesPerSec;
+ CoTaskMemFree(current_pwfex);
}
if (p_capture) {
@@ -499,7 +524,7 @@ Error AudioDriverWASAPI::finish_capture_device() {
Error AudioDriverWASAPI::init() {
mix_rate = GLOBAL_GET("audio/driver/mix_rate");
- target_latency_ms = GLOBAL_GET("audio/output_latency");
+ target_latency_ms = GLOBAL_GET("audio/driver/output_latency");
Error err = init_render_device();
if (err != OK) {
@@ -518,6 +543,10 @@ int AudioDriverWASAPI::get_mix_rate() const {
return mix_rate;
}
+float AudioDriverWASAPI::get_latency() {
+ return real_latency;
+}
+
AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const {
return get_speaker_mode_by_total_channels(channels);
}