Qt/overlays: Add secondary audio output for emulation

This commit is contained in:
Megamouse
2026-03-20 00:33:45 +01:00
parent cd1d6282b4
commit 62b2ffd7ca
2 changed files with 58 additions and 40 deletions
+54 -39
View File
@@ -8,14 +8,23 @@
#include <QAudioOutput> #include <QAudioOutput>
#include <QFile> #include <QFile>
static video_source* s_audio_source = nullptr; struct qt_audio_instance
static std::unique_ptr<QMediaPlayer> s_audio_player = nullptr; {
static std::unique_ptr<QAudioOutput> s_audio_output = nullptr; static constexpr u32 gui_index = 0;
static std::unique_ptr<QBuffer> s_audio_buffer = nullptr; static constexpr u32 emu_index = 1;
static std::unique_ptr<QByteArray> s_audio_data = nullptr;
qt_video_source::qt_video_source() video_source* source = nullptr;
std::unique_ptr<QMediaPlayer> player;
std::unique_ptr<QAudioOutput> output;
std::unique_ptr<QBuffer> buffer;
std::unique_ptr<QByteArray> data;
};
static std::array<qt_audio_instance, 2> s_audio_instance = {};
qt_video_source::qt_video_source(bool is_emulation)
: video_source() : 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() 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<QAudioOutput>(); audio.output = std::make_unique<QAudioOutput>();
s_audio_player = std::make_unique<QMediaPlayer>(); audio.player = std::make_unique<QMediaPlayer>();
s_audio_player->setAudioOutput(s_audio_output.get()); audio.player->setAudioOutput(audio.output.get());
} }
if (m_iso_path.empty()) if (m_iso_path.empty())
{ {
s_audio_player->setSource(QUrl::fromLocalFile(m_audio_path)); audio.player->setSource(QUrl::fromLocalFile(m_audio_path));
} }
else else
{ {
@@ -236,18 +248,18 @@ void qt_video_source::start_audio()
const auto audio_size = audio_file.size(); const auto audio_size = audio_file.size();
if (audio_size == 0) return; if (audio_size == 0) return;
std::unique_ptr<QByteArray> old_audio_data = std::move(s_audio_data); std::unique_ptr<QByteArray> old_audio_data = std::move(audio.data);
s_audio_data = std::make_unique<QByteArray>(audio_size, 0); audio.data = std::make_unique<QByteArray>(audio_size, 0);
audio_file.read(s_audio_data->data(), audio_size); audio_file.read(audio.data->data(), audio_size);
if (!s_audio_buffer) if (!audio.buffer)
{ {
s_audio_buffer = std::make_unique<QBuffer>(); audio.buffer = std::make_unique<QBuffer>();
} }
s_audio_buffer->setBuffer(s_audio_data.get()); audio.buffer->setBuffer(audio.data.get());
s_audio_buffer->open(QIODevice::ReadOnly); audio.buffer->open(QIODevice::ReadOnly);
s_audio_player->setSourceDevice(s_audio_buffer.get()); audio.player->setSourceDevice(audio.buffer.get());
if (old_audio_data) 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); audio.output->setVolume(g_cfg.audio.volume.get() / 100.0f);
s_audio_player->play(); audio.player->play();
s_audio_source = this; audio.source = this;
} }
void qt_video_source::stop_audio() 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(); audio.player->stop();
s_audio_player.reset(); audio.player.reset();
} }
s_audio_output.reset(); audio.output.reset();
s_audio_buffer.reset(); audio.buffer.reset();
s_audio_data.reset(); audio.data.reset();
} }
QPixmap qt_video_source::get_movie_image(const QVideoFrame& frame) const 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<qt_video_source>(true);
}
}
void qt_video_source_wrapper::set_video_path(const std::string& video_path) void qt_video_source_wrapper::set_video_path(const std::string& video_path)
{ {
Emu.CallFromMainThread([this, path = video_path]() Emu.CallFromMainThread([this, path = video_path]()
{ {
if (!m_qt_video_source) init_video_source();
{
m_qt_video_source = std::make_unique<qt_video_source>();
}
m_qt_video_source->m_image_change_callback = [this](const QVideoFrame& frame) 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]() Emu.CallFromMainThread([this, path = audio_path]()
{ {
if (!m_qt_video_source) init_video_source();
{
m_qt_video_source = std::make_unique<qt_video_source>();
}
m_qt_video_source->set_audio_path(path); m_qt_video_source->set_audio_path(path);
}); });
+4 -1
View File
@@ -14,7 +14,7 @@
class qt_video_source : public video_source class qt_video_source : public video_source
{ {
public: public:
qt_video_source(); qt_video_source(bool is_emulation = false);
virtual ~qt_video_source(); virtual ~qt_video_source();
void set_iso_path(const std::string& iso_path); void set_iso_path(const std::string& iso_path);
@@ -50,6 +50,7 @@ protected:
QString m_video_path; QString m_video_path;
QString m_audio_path; QString m_audio_path;
u32 m_audio_instance_index = 0;
std::string m_iso_path; // path of the source archive std::string m_iso_path; // path of the source archive
QByteArray m_video_data{}; QByteArray m_video_data{};
QImage m_image{}; QImage m_image{};
@@ -80,5 +81,7 @@ public:
void get_image(std::vector<u8>& data, int& w, int& h, int& ch, int& bpp) override; void get_image(std::vector<u8>& data, int& w, int& h, int& ch, int& bpp) override;
private: private:
void init_video_source();
std::unique_ptr<qt_video_source> m_qt_video_source; std::unique_ptr<qt_video_source> m_qt_video_source;
}; };