diff options
Diffstat (limited to 'Source/Core/AudioCommon/CubebStream.cpp')
| -rw-r--r-- | Source/Core/AudioCommon/CubebStream.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/Source/Core/AudioCommon/CubebStream.cpp b/Source/Core/AudioCommon/CubebStream.cpp index 0cdf7f3b99..47f334d537 100644 --- a/Source/Core/AudioCommon/CubebStream.cpp +++ b/Source/Core/AudioCommon/CubebStream.cpp @@ -49,6 +49,19 @@ void CubebStream::WiimoteStateCallback(cubeb_stream* stream, void* user_data, cu { } +long CubebStream::GBADataCallback(cubeb_stream* stream, void* user_data, + const void* /*input_buffer*/, void* output_buffer, + long num_frames) +{ + const auto* data = static_cast<const GBAStreamData*>(user_data); + data->self->m_mixer->MixGBA(data->gba_index, static_cast<short*>(output_buffer), num_frames); + return num_frames; +} + +void CubebStream::GBAStateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) +{ +} + CubebStream::CubebStream() #ifdef _WIN32 : m_work_queue("Cubeb Worker") @@ -145,6 +158,48 @@ bool CubebStream::Init() } } } + + // Create per-GBA streams for audio routing when enabled + if (return_value && Config::Get(Config::MAIN_GBA_AUDIO_ROUTING_ENABLED)) + { + static const char* const GBA_STREAM_NAMES[4] = { + "Dolphin GBA 1 Audio", "Dolphin GBA 2 Audio", "Dolphin GBA 3 Audio", + "Dolphin GBA 4 Audio"}; + + cubeb_stream_params gba_params{}; + gba_params.rate = m_mixer->GetSampleRate(); + gba_params.channels = 2; + gba_params.format = CUBEB_SAMPLE_S16NE; + gba_params.layout = CUBEB_LAYOUT_STEREO; + + for (std::size_t i = 0; i < m_gba_streams.size(); ++i) + { + if (!Config::Get(Config::MAIN_GBA_AUDIO_OUTPUT_ENABLED[i])) + continue; + + const std::string device_id_str = Config::Get(Config::MAIN_GBA_AUDIO_OUTPUT_DEVICE[i]); + const cubeb_devid output_devid = + device_id_str.empty() ? + nullptr : + static_cast<cubeb_devid>(CubebUtils::GetOutputDeviceById(device_id_str)); + + u32 gba_min_latency = 0; + cubeb_get_min_latency(m_ctx.get(), &gba_params, &gba_min_latency); + + m_gba_stream_data[i] = {this, i}; + + const int result = cubeb_stream_init( + m_ctx.get(), &m_gba_streams[i], GBA_STREAM_NAMES[i], nullptr, nullptr, output_devid, + &gba_params, std::max(BUFFER_SAMPLES, gba_min_latency), GBADataCallback, + GBAStateCallback, &m_gba_stream_data[i]); + + if (result != CUBEB_OK) + { + ERROR_LOG_FMT(AUDIO, "Failed to create Cubeb stream for GBA {} audio split", i + 1); + m_gba_streams[i] = nullptr; + } + } + } } #ifdef _WIN32 @@ -171,6 +226,11 @@ bool CubebStream::SetRunning(bool running) if (ws) cubeb_stream_start(ws); } + for (auto& gs : m_gba_streams) + { + if (gs) + cubeb_stream_start(gs); + } } else { @@ -180,6 +240,11 @@ bool CubebStream::SetRunning(bool running) if (ws) cubeb_stream_stop(ws); } + for (auto& gs : m_gba_streams) + { + if (gs) + cubeb_stream_stop(gs); + } } #ifdef _WIN32 }); @@ -204,6 +269,15 @@ CubebStream::~CubebStream() ws = nullptr; } } + for (auto& gs : m_gba_streams) + { + if (gs) + { + cubeb_stream_stop(gs); + cubeb_stream_destroy(gs); + gs = nullptr; + } + } #ifdef _WIN32 if (m_should_couninit) { |
