From 62b2ffd7cadc3e850e308fb8a5366e432e55a115 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Fri, 20 Mar 2026 00:33:45 +0100 Subject: [PATCH] Qt/overlays: Add secondary audio output for emulation --- rpcs3/rpcs3qt/qt_video_source.cpp | 93 ++++++++++++++++++------------- rpcs3/rpcs3qt/qt_video_source.h | 5 +- 2 files changed, 58 insertions(+), 40 deletions(-) diff --git a/rpcs3/rpcs3qt/qt_video_source.cpp b/rpcs3/rpcs3qt/qt_video_source.cpp index 8877e00c0c..b14db8a019 100644 --- a/rpcs3/rpcs3qt/qt_video_source.cpp +++ b/rpcs3/rpcs3qt/qt_video_source.cpp @@ -8,14 +8,23 @@ #include #include -static video_source* s_audio_source = nullptr; -static std::unique_ptr s_audio_player = nullptr; -static std::unique_ptr s_audio_output = nullptr; -static std::unique_ptr s_audio_buffer = nullptr; -static std::unique_ptr s_audio_data = nullptr; +struct qt_audio_instance +{ + static constexpr u32 gui_index = 0; + static constexpr u32 emu_index = 1; -qt_video_source::qt_video_source() + video_source* source = nullptr; + std::unique_ptr player; + std::unique_ptr output; + std::unique_ptr buffer; + std::unique_ptr data; +}; + +static std::array s_audio_instance = {}; + +qt_video_source::qt_video_source(bool is_emulation) : video_source() + , m_audio_instance_index(is_emulation ? qt_audio_instance::emu_index : qt_audio_instance::gui_index) { } @@ -216,18 +225,21 @@ void qt_video_source::stop_movie() void qt_video_source::start_audio() { - if (m_audio_path.isEmpty() || s_audio_source == this) return; + if (m_audio_path.isEmpty()) return; - if (!s_audio_player) + qt_audio_instance& audio = ::at32(s_audio_instance, m_audio_instance_index); + if (audio.source == this) return; + + if (!audio.player) { - s_audio_output = std::make_unique(); - s_audio_player = std::make_unique(); - s_audio_player->setAudioOutput(s_audio_output.get()); + audio.output = std::make_unique(); + audio.player = std::make_unique(); + audio.player->setAudioOutput(audio.output.get()); } if (m_iso_path.empty()) { - s_audio_player->setSource(QUrl::fromLocalFile(m_audio_path)); + audio.player->setSource(QUrl::fromLocalFile(m_audio_path)); } else { @@ -236,18 +248,18 @@ void qt_video_source::start_audio() const auto audio_size = audio_file.size(); if (audio_size == 0) return; - std::unique_ptr old_audio_data = std::move(s_audio_data); - s_audio_data = std::make_unique(audio_size, 0); - audio_file.read(s_audio_data->data(), audio_size); + std::unique_ptr old_audio_data = std::move(audio.data); + audio.data = std::make_unique(audio_size, 0); + audio_file.read(audio.data->data(), audio_size); - if (!s_audio_buffer) + if (!audio.buffer) { - s_audio_buffer = std::make_unique(); + audio.buffer = std::make_unique(); } - s_audio_buffer->setBuffer(s_audio_data.get()); - s_audio_buffer->open(QIODevice::ReadOnly); - s_audio_player->setSourceDevice(s_audio_buffer.get()); + audio.buffer->setBuffer(audio.data.get()); + audio.buffer->open(QIODevice::ReadOnly); + audio.player->setSourceDevice(audio.buffer.get()); if (old_audio_data) { @@ -255,26 +267,27 @@ void qt_video_source::start_audio() } } - s_audio_output->setVolume(g_cfg.audio.volume.get() / 100.0f); - s_audio_player->play(); - s_audio_source = this; + audio.output->setVolume(g_cfg.audio.volume.get() / 100.0f); + audio.player->play(); + audio.source = this; } void qt_video_source::stop_audio() { - if (s_audio_source != this) return; + qt_audio_instance& audio = ::at32(s_audio_instance, m_audio_instance_index); + if (audio.source != this) return; - s_audio_source = nullptr; + audio.source = nullptr; - if (s_audio_player) + if (audio.player) { - s_audio_player->stop(); - s_audio_player.reset(); + audio.player->stop(); + audio.player.reset(); } - s_audio_output.reset(); - s_audio_buffer.reset(); - s_audio_data.reset(); + audio.output.reset(); + audio.buffer.reset(); + audio.data.reset(); } QPixmap qt_video_source::get_movie_image(const QVideoFrame& frame) const @@ -331,14 +344,19 @@ qt_video_source_wrapper::~qt_video_source_wrapper() }); } +void qt_video_source_wrapper::init_video_source() +{ + if (!m_qt_video_source) + { + m_qt_video_source = std::make_unique(true); + } +} + void qt_video_source_wrapper::set_video_path(const std::string& video_path) { Emu.CallFromMainThread([this, path = video_path]() { - if (!m_qt_video_source) - { - m_qt_video_source = std::make_unique(); - } + init_video_source(); m_qt_video_source->m_image_change_callback = [this](const QVideoFrame& frame) { @@ -375,10 +393,7 @@ void qt_video_source_wrapper::set_audio_path(const std::string& audio_path) { Emu.CallFromMainThread([this, path = audio_path]() { - if (!m_qt_video_source) - { - m_qt_video_source = std::make_unique(); - } + init_video_source(); m_qt_video_source->set_audio_path(path); }); diff --git a/rpcs3/rpcs3qt/qt_video_source.h b/rpcs3/rpcs3qt/qt_video_source.h index cda92671a2..8afc46ceb3 100644 --- a/rpcs3/rpcs3qt/qt_video_source.h +++ b/rpcs3/rpcs3qt/qt_video_source.h @@ -14,7 +14,7 @@ class qt_video_source : public video_source { public: - qt_video_source(); + qt_video_source(bool is_emulation = false); virtual ~qt_video_source(); void set_iso_path(const std::string& iso_path); @@ -50,6 +50,7 @@ protected: QString m_video_path; QString m_audio_path; + u32 m_audio_instance_index = 0; std::string m_iso_path; // path of the source archive QByteArray m_video_data{}; QImage m_image{}; @@ -80,5 +81,7 @@ public: void get_image(std::vector& data, int& w, int& h, int& ch, int& bpp) override; private: + void init_video_source(); + std::unique_ptr m_qt_video_source; };