diff options
Diffstat (limited to 'Source/Core/AudioCommon/CubebStream.cpp')
| -rw-r--r-- | Source/Core/AudioCommon/CubebStream.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/Source/Core/AudioCommon/CubebStream.cpp b/Source/Core/AudioCommon/CubebStream.cpp index 2a04985e3b..adc947b426 100644 --- a/Source/Core/AudioCommon/CubebStream.cpp +++ b/Source/Core/AudioCommon/CubebStream.cpp @@ -9,6 +9,7 @@ #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" #include "Core/Config/MainSettings.h" +#include "Core/System.h" #ifdef _WIN32 #include <Objbase.h> @@ -34,6 +35,20 @@ void CubebStream::StateCallback(cubeb_stream* stream, void* user_data, cubeb_sta { } +long CubebStream::WiimoteDataCallback(cubeb_stream* stream, void* user_data, + const void* /*input_buffer*/, void* output_buffer, + long num_frames) +{ + const auto* data = static_cast<const WiimoteStreamData*>(user_data); + data->self->m_mixer->MixWiimoteSpeaker(data->wiimote_index, static_cast<short*>(output_buffer), + num_frames); + return num_frames; +} + +void CubebStream::WiimoteStateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) +{ +} + CubebStream::CubebStream() #ifdef _WIN32 : m_work_queue("Cubeb Worker") @@ -86,6 +101,50 @@ bool CubebStream::Init() cubeb_stream_init(m_ctx.get(), &m_stream, "Dolphin Audio Output", nullptr, nullptr, nullptr, ¶ms, std::max(BUFFER_SAMPLES, minimum_latency), DataCallback, StateCallback, this) == CUBEB_OK; + + // Create per-wiimote streams for audio routing (Wii games only, when enabled) + if (return_value && Core::System::GetInstance().IsWii() && + Config::Get(Config::MAIN_WIIMOTE_AUDIO_ROUTING_ENABLED)) + { + static const char* const WIIMOTE_STREAM_NAMES[4] = { + "Dolphin Wiimote 1 Audio", "Dolphin Wiimote 2 Audio", "Dolphin Wiimote 3 Audio", + "Dolphin Wiimote 4 Audio"}; + + cubeb_stream_params wiimote_params{}; + wiimote_params.rate = m_mixer->GetSampleRate(); + wiimote_params.channels = 2; + wiimote_params.format = CUBEB_SAMPLE_S16NE; + wiimote_params.layout = CUBEB_LAYOUT_STEREO; + + for (std::size_t i = 0; i < m_wiimote_streams.size(); ++i) + { + if (!Config::Get(Config::MAIN_WIIMOTE_AUDIO_OUTPUT_ENABLED[i])) + continue; + + const std::string device_id_str = + Config::Get(Config::MAIN_WIIMOTE_AUDIO_OUTPUT_DEVICE[i]); + const cubeb_devid output_devid = + device_id_str.empty() ? + nullptr : + static_cast<cubeb_devid>(CubebUtils::GetOutputDeviceById(device_id_str)); + + u32 wiimote_min_latency = 0; + cubeb_get_min_latency(m_ctx.get(), &wiimote_params, &wiimote_min_latency); + + m_wiimote_stream_data[i] = {this, i}; + const int result = cubeb_stream_init( + m_ctx.get(), &m_wiimote_streams[i], WIIMOTE_STREAM_NAMES[i], nullptr, nullptr, + output_devid, &wiimote_params, std::max(BUFFER_SAMPLES, wiimote_min_latency), + WiimoteDataCallback, WiimoteStateCallback, &m_wiimote_stream_data[i]); + + if (result != CUBEB_OK) + { + ERROR_LOG_FMT(AUDIO, "Failed to create Cubeb stream for Wiimote {} audio routing", + i + 1); + m_wiimote_streams[i] = nullptr; + } + } + } } #ifdef _WIN32 @@ -105,9 +164,23 @@ bool CubebStream::SetRunning(bool running) m_work_queue.PushBlocking([this, running, &return_value] { #endif if (running) + { return_value = cubeb_stream_start(m_stream) == CUBEB_OK; + for (auto& ws : m_wiimote_streams) + { + if (ws) + cubeb_stream_start(ws); + } + } else + { return_value = cubeb_stream_stop(m_stream) == CUBEB_OK; + for (auto& ws : m_wiimote_streams) + { + if (ws) + cubeb_stream_stop(ws); + } + } #ifdef _WIN32 }); #endif @@ -122,6 +195,15 @@ CubebStream::~CubebStream() #endif cubeb_stream_stop(m_stream); cubeb_stream_destroy(m_stream); + for (auto& ws : m_wiimote_streams) + { + if (ws) + { + cubeb_stream_stop(ws); + cubeb_stream_destroy(ws); + ws = nullptr; + } + } #ifdef _WIN32 if (m_should_couninit) { |
