summaryrefslogtreecommitdiff
path: root/Source/Core/AudioCommon/CubebStream.cpp
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2022-11-27 03:26:11 +0100
committerGitHub <noreply@github.com>2022-11-27 03:26:11 +0100
commit3cdc6e3d4a4f2362f5e2b5960821573a13663be2 (patch)
treec453f1a16e7251396f3b19a5bddd2ba76b7bb6e2 /Source/Core/AudioCommon/CubebStream.cpp
parent332d18725255ab6cf739d8ae2747178a06457dd4 (diff)
parent49252a021758e3135e078aec1e52305dea360287 (diff)
Merge pull request #10343 from AdmiralCurtiss/cubeb-2021
Update cubeb to mozilla/cubeb@27d2a102b0b75d9e49d43bc1ea516233fb87d778
Diffstat (limited to 'Source/Core/AudioCommon/CubebStream.cpp')
-rw-r--r--Source/Core/AudioCommon/CubebStream.cpp150
1 files changed, 115 insertions, 35 deletions
diff --git a/Source/Core/AudioCommon/CubebStream.cpp b/Source/Core/AudioCommon/CubebStream.cpp
index b8ccbbdaee..5d3d70d9cb 100644
--- a/Source/Core/AudioCommon/CubebStream.cpp
+++ b/Source/Core/AudioCommon/CubebStream.cpp
@@ -7,10 +7,16 @@
#include "AudioCommon/CubebUtils.h"
#include "Common/CommonTypes.h"
+#include "Common/Event.h"
#include "Common/Logging/Log.h"
+#include "Common/ScopeGuard.h"
#include "Common/Thread.h"
#include "Core/Config/MainSettings.h"
+#ifdef _WIN32
+#include <Objbase.h>
+#endif
+
// ~10 ms - needs to be at least 240 for surround
constexpr u32 BUFFER_SAMPLES = 512;
@@ -31,55 +37,129 @@ void CubebStream::StateCallback(cubeb_stream* stream, void* user_data, cubeb_sta
{
}
-bool CubebStream::Init()
+CubebStream::CubebStream()
+#ifdef _WIN32
+ : m_work_queue([](const std::function<void()>& func) { func(); })
{
- m_ctx = CubebUtils::GetContext();
- if (!m_ctx)
- return false;
+ Common::Event sync_event;
+ m_work_queue.EmplaceItem([this, &sync_event] {
+ Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
+ auto result = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
+ m_coinit_success = result == S_OK;
+ });
+ sync_event.Wait();
+}
+#else
+ = default;
+#endif
- m_stereo = !Config::ShouldUseDPL2Decoder();
+bool CubebStream::Init()
+{
+ bool return_value = false;
- cubeb_stream_params params;
- params.rate = m_mixer->GetSampleRate();
- if (m_stereo)
- {
- params.channels = 2;
- params.format = CUBEB_SAMPLE_S16NE;
- params.layout = CUBEB_LAYOUT_STEREO;
- }
- else
- {
- params.channels = 6;
- params.format = CUBEB_SAMPLE_FLOAT32NE;
- params.layout = CUBEB_LAYOUT_3F2_LFE;
- }
-
- u32 minimum_latency = 0;
- if (cubeb_get_min_latency(m_ctx.get(), &params, &minimum_latency) != CUBEB_OK)
- ERROR_LOG_FMT(AUDIO, "Error getting minimum latency");
- INFO_LOG_FMT(AUDIO, "Minimum latency: {} frames", minimum_latency);
-
- return cubeb_stream_init(m_ctx.get(), &m_stream, "Dolphin Audio Output", nullptr, nullptr,
- nullptr, &params, std::max(BUFFER_SAMPLES, minimum_latency),
- DataCallback, StateCallback, this) == CUBEB_OK;
+#ifdef _WIN32
+ if (!m_coinit_success)
+ return false;
+ Common::Event sync_event;
+ m_work_queue.EmplaceItem([this, &return_value, &sync_event] {
+ Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
+#endif
+
+ m_ctx = CubebUtils::GetContext();
+ if (m_ctx)
+ {
+ m_stereo = !Config::ShouldUseDPL2Decoder();
+
+ cubeb_stream_params params{};
+ params.rate = m_mixer->GetSampleRate();
+ if (m_stereo)
+ {
+ params.channels = 2;
+ params.format = CUBEB_SAMPLE_S16NE;
+ params.layout = CUBEB_LAYOUT_STEREO;
+ }
+ else
+ {
+ params.channels = 6;
+ params.format = CUBEB_SAMPLE_FLOAT32NE;
+ params.layout = CUBEB_LAYOUT_3F2_LFE;
+ }
+
+ u32 minimum_latency = 0;
+ if (cubeb_get_min_latency(m_ctx.get(), &params, &minimum_latency) != CUBEB_OK)
+ ERROR_LOG_FMT(AUDIO, "Error getting minimum latency");
+ INFO_LOG_FMT(AUDIO, "Minimum latency: {} frames", minimum_latency);
+
+ return_value =
+ cubeb_stream_init(m_ctx.get(), &m_stream, "Dolphin Audio Output", nullptr, nullptr,
+ nullptr, &params, std::max(BUFFER_SAMPLES, minimum_latency),
+ DataCallback, StateCallback, this) == CUBEB_OK;
+ }
+
+#ifdef _WIN32
+ });
+ sync_event.Wait();
+#endif
+
+ return return_value;
}
bool CubebStream::SetRunning(bool running)
{
- if (running)
- return cubeb_stream_start(m_stream) == CUBEB_OK;
- else
- return cubeb_stream_stop(m_stream) == CUBEB_OK;
+ bool return_value = false;
+
+#ifdef _WIN32
+ if (!m_coinit_success)
+ return false;
+ Common::Event sync_event;
+ m_work_queue.EmplaceItem([this, running, &return_value, &sync_event] {
+ Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
+#endif
+ if (running)
+ return_value = cubeb_stream_start(m_stream) == CUBEB_OK;
+ else
+ return_value = cubeb_stream_stop(m_stream) == CUBEB_OK;
+#ifdef _WIN32
+ });
+ sync_event.Wait();
+#endif
+
+ return return_value;
}
CubebStream::~CubebStream()
{
- SetRunning(false);
- cubeb_stream_destroy(m_stream);
+#ifdef _WIN32
+ Common::Event sync_event;
+ m_work_queue.EmplaceItem([this, &sync_event] {
+ Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
+#endif
+ cubeb_stream_stop(m_stream);
+ cubeb_stream_destroy(m_stream);
+#ifdef _WIN32
+ if (m_coinit_success)
+ {
+ m_coinit_success = false;
+ CoUninitialize();
+ }
+ });
+ sync_event.Wait();
+#endif
m_ctx.reset();
}
void CubebStream::SetVolume(int volume)
{
- cubeb_stream_set_volume(m_stream, volume / 100.0f);
+#ifdef _WIN32
+ if (!m_coinit_success)
+ return;
+ Common::Event sync_event;
+ m_work_queue.EmplaceItem([this, volume, &sync_event] {
+ Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
+#endif
+ cubeb_stream_set_volume(m_stream, volume / 100.0f);
+#ifdef _WIN32
+ });
+ sync_event.Wait();
+#endif
}