mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-10-11 22:49:50 +00:00
Merge pull request #14880 from ICEREG1992/GBARouting
Integrated GBA Audio Routing
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <cubeb/cubeb.h>
|
||||
#endif
|
||||
|
||||
#include "Core/Config/MainSettings.h"
|
||||
|
||||
class CubebStream final : public SoundStream
|
||||
{
|
||||
#ifdef HAVE_CUBEB
|
||||
@@ -38,11 +40,19 @@ private:
|
||||
std::size_t wiimote_index;
|
||||
};
|
||||
|
||||
struct GBAStreamData
|
||||
{
|
||||
CubebStream* self;
|
||||
std::size_t gba_index;
|
||||
};
|
||||
|
||||
bool m_stereo = false;
|
||||
std::shared_ptr<cubeb> m_ctx;
|
||||
cubeb_stream* m_stream = nullptr;
|
||||
std::array<WiimoteStreamData, 4> m_wiimote_stream_data{};
|
||||
std::array<cubeb_stream*, 4> m_wiimote_streams{};
|
||||
std::array<GBAStreamData, Config::GBA_SPEAKER_COUNT> m_gba_stream_data{};
|
||||
std::array<cubeb_stream*, Config::GBA_SPEAKER_COUNT> m_gba_streams{};
|
||||
|
||||
std::vector<short> m_short_buffer;
|
||||
std::vector<float> m_floatstereo_buffer;
|
||||
@@ -60,5 +70,8 @@ private:
|
||||
const void* /*input_buffer*/, void* output_buffer,
|
||||
long num_frames);
|
||||
static void WiimoteStateCallback(cubeb_stream* stream, void* user_data, cubeb_state state);
|
||||
static long GBADataCallback(cubeb_stream* stream, void* user_data, const void* /*input_buffer*/,
|
||||
void* output_buffer, long num_frames);
|
||||
static void GBAStateCallback(cubeb_stream* stream, void* user_data, cubeb_state state);
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -176,8 +176,11 @@ std::size_t Mixer::Mix(s16* samples, std::size_t num_samples)
|
||||
m_wiimote_speaker_mixers[i].Mix(samples, num_samples);
|
||||
}
|
||||
m_skylander_portal_mixer.Mix(samples, num_samples);
|
||||
for (auto& mixer : m_gba_mixers)
|
||||
mixer.Mix(samples, num_samples);
|
||||
for (std::size_t i = 0; i < m_gba_mixers.size(); ++i)
|
||||
{
|
||||
if (!m_config_gba_routing_enabled || !m_config_gba_output_enabled[i])
|
||||
m_gba_mixers[i].Mix(samples, num_samples);
|
||||
}
|
||||
|
||||
return num_samples;
|
||||
}
|
||||
@@ -317,6 +320,15 @@ void Mixer::PushGBASamples(std::size_t device_number, const s16* samples, std::s
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t Mixer::MixGBA(std::size_t device_number, s16* samples, std::size_t num_samples)
|
||||
{
|
||||
if (!samples || device_number >= m_gba_mixers.size())
|
||||
return 0;
|
||||
memset(samples, 0, num_samples * 2 * sizeof(s16));
|
||||
m_gba_mixers[device_number].Mix(samples, num_samples);
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
void Mixer::SetDMAInputSampleRateDivisor(u32 rate_divisor)
|
||||
{
|
||||
m_dma_mixer.SetInputSampleRateDivisor(rate_divisor);
|
||||
@@ -433,6 +445,9 @@ void Mixer::RefreshConfig()
|
||||
m_config_wiimote_routing_enabled = Config::Get(Config::MAIN_WIIMOTE_AUDIO_ROUTING_ENABLED);
|
||||
for (std::size_t i = 0; i < m_config_wiimote_output_enabled.size(); ++i)
|
||||
m_config_wiimote_output_enabled[i] = Config::Get(Config::MAIN_WIIMOTE_AUDIO_OUTPUT_ENABLED[i]);
|
||||
m_config_gba_routing_enabled = Config::Get(Config::MAIN_GBA_AUDIO_ROUTING_ENABLED);
|
||||
for (std::size_t i = 0; i < m_config_gba_output_enabled.size(); ++i)
|
||||
m_config_gba_output_enabled[i] = Config::Get(Config::MAIN_GBA_AUDIO_OUTPUT_ENABLED[i]);
|
||||
}
|
||||
|
||||
void Mixer::MixerFifo::DoState(PointerWrap& p)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Config/Config.h"
|
||||
#include "Common/Inline.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
@@ -49,6 +50,7 @@ public:
|
||||
void SetWiimoteSpeakerVolume(std::size_t wiimote_index, u32 lvolume, u32 rvolume);
|
||||
std::size_t MixWiimoteSpeaker(std::size_t wiimote_index, s16* samples, std::size_t num_samples);
|
||||
void SetGBAVolume(std::size_t device_number, u32 lvolume, u32 rvolume);
|
||||
std::size_t MixGBA(std::size_t device_number, s16* samples, std::size_t num_samples);
|
||||
|
||||
void StartLogDTKAudio(const std::string& filename);
|
||||
void StopLogDTKAudio();
|
||||
@@ -178,7 +180,7 @@ private:
|
||||
// GBAs generally use a 65536 sample rate which is not a factor of our FIXED_SAMPLE_RATE_DIVIDEND.
|
||||
static constexpr u32 GBA_SAMPLE_RATE_DIVIDEND = 0x1000000;
|
||||
|
||||
std::array<MixerFifo, 4> m_gba_mixers{
|
||||
std::array<MixerFifo, Config::GBA_SPEAKER_COUNT> m_gba_mixers{
|
||||
MixerFifo{this, GBA_SAMPLE_RATE_DIVIDEND / 65536, GBA_SAMPLE_RATE_DIVIDEND},
|
||||
MixerFifo{this, GBA_SAMPLE_RATE_DIVIDEND / 65536, GBA_SAMPLE_RATE_DIVIDEND},
|
||||
MixerFifo{this, GBA_SAMPLE_RATE_DIVIDEND / 65536, GBA_SAMPLE_RATE_DIVIDEND},
|
||||
@@ -200,6 +202,8 @@ private:
|
||||
int m_config_audio_buffer_ms;
|
||||
bool m_config_wiimote_routing_enabled = false;
|
||||
std::array<bool, 4> m_config_wiimote_output_enabled{};
|
||||
bool m_config_gba_routing_enabled = false;
|
||||
std::array<bool, Config::GBA_SPEAKER_COUNT> m_config_gba_output_enabled{};
|
||||
|
||||
Config::ConfigChangedCallbackID m_config_changed_callback_id;
|
||||
};
|
||||
|
||||
@@ -716,6 +716,23 @@ const std::array<Info<std::string>, WIIMOTE_SPEAKER_COUNT> MAIN_WIIMOTE_AUDIO_OU
|
||||
Info<std::string>{{System::Main, "Core", "Wiimote3AudioOutputDevice"}, ""},
|
||||
Info<std::string>{{System::Main, "Core", "Wiimote4AudioOutputDevice"}, ""}};
|
||||
|
||||
// Main.GBAAudioRouting
|
||||
|
||||
const Info<bool> MAIN_GBA_AUDIO_ROUTING_ENABLED{{System::Main, "Core", "GBAAudioRoutingEnabled"},
|
||||
false};
|
||||
const std::array<Info<bool>, GBA_SPEAKER_COUNT> MAIN_GBA_AUDIO_OUTPUT_ENABLED = {
|
||||
Info<bool>{{System::Main, "Core", "GBA1AudioOutputEnabled"}, false},
|
||||
Info<bool>{{System::Main, "Core", "GBA2AudioOutputEnabled"}, false},
|
||||
Info<bool>{{System::Main, "Core", "GBA3AudioOutputEnabled"}, false},
|
||||
Info<bool>{{System::Main, "Core", "GBA4AudioOutputEnabled"}, false},
|
||||
};
|
||||
const std::array<Info<std::string>, GBA_SPEAKER_COUNT> MAIN_GBA_AUDIO_OUTPUT_DEVICE = {
|
||||
Info<std::string>{{System::Main, "Core", "GBA1AudioOutputDevice"}, ""},
|
||||
Info<std::string>{{System::Main, "Core", "GBA2AudioOutputDevice"}, ""},
|
||||
Info<std::string>{{System::Main, "Core", "GBA3AudioOutputDevice"}, ""},
|
||||
Info<std::string>{{System::Main, "Core", "GBA4AudioOutputDevice"}, ""},
|
||||
};
|
||||
|
||||
// The reason we need this function is because some memory card code
|
||||
// expects to get a non-NTSC-K region even if we're emulating an NTSC-K Wii.
|
||||
DiscIO::Region ToGameCubeRegion(DiscIO::Region region)
|
||||
|
||||
@@ -405,6 +405,14 @@ extern const Info<bool> MAIN_WIIMOTE_AUDIO_ROUTING_ENABLED;
|
||||
extern const std::array<Info<bool>, WIIMOTE_SPEAKER_COUNT> MAIN_WIIMOTE_AUDIO_OUTPUT_ENABLED;
|
||||
extern const std::array<Info<std::string>, WIIMOTE_SPEAKER_COUNT> MAIN_WIIMOTE_AUDIO_OUTPUT_DEVICE;
|
||||
|
||||
// Main.GBAAudioRouting
|
||||
|
||||
static constexpr std::size_t GBA_SPEAKER_COUNT = 4;
|
||||
|
||||
extern const Info<bool> MAIN_GBA_AUDIO_ROUTING_ENABLED;
|
||||
extern const std::array<Info<bool>, GBA_SPEAKER_COUNT> MAIN_GBA_AUDIO_OUTPUT_ENABLED;
|
||||
extern const std::array<Info<std::string>, GBA_SPEAKER_COUNT> MAIN_GBA_AUDIO_OUTPUT_DEVICE;
|
||||
|
||||
// GameCube path utility functions
|
||||
|
||||
// Replaces NTSC-K with some other region, and doesn't replace non-NTSC-K regions
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/Config/WiimoteSettings.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/SI/SI_Device.h"
|
||||
#include "Core/HW/Wiimote.h"
|
||||
#include "Core/System.h"
|
||||
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
|
||||
@@ -242,6 +243,34 @@ void AudioPane::CreateWidgets()
|
||||
}
|
||||
#endif
|
||||
|
||||
// GBA Audio Routing
|
||||
#ifdef HAVE_CUBEB
|
||||
m_gba_routing_box = new QGroupBox(tr("GBA Audio Routing"));
|
||||
auto* gba_routing_layout = new QVBoxLayout;
|
||||
m_gba_routing_box->setLayout(gba_routing_layout);
|
||||
|
||||
m_gba_routing_enable =
|
||||
new ConfigBool(tr("Enable GBA Audio Routing"), Config::MAIN_GBA_AUDIO_ROUTING_ENABLED);
|
||||
gba_routing_layout->addWidget(m_gba_routing_enable);
|
||||
|
||||
for (std::size_t i = 0; i < Config::GBA_SPEAKER_COUNT; ++i)
|
||||
{
|
||||
auto* row_widget = new QWidget;
|
||||
auto* row_layout = new QHBoxLayout(row_widget);
|
||||
row_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
m_gba_output_enable[i] =
|
||||
new ConfigBool(tr("GBA %1").arg(i + 1), Config::MAIN_GBA_AUDIO_OUTPUT_ENABLED[i]);
|
||||
m_gba_output_device[i] =
|
||||
new ConfigStringChoice(output_devices, Config::MAIN_GBA_AUDIO_OUTPUT_DEVICE[i]);
|
||||
|
||||
row_layout->addWidget(m_gba_output_enable[i]);
|
||||
row_layout->addWidget(m_gba_output_device[i], 1);
|
||||
|
||||
gba_routing_layout->addWidget(row_widget);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto* const main_vbox_layout = new QVBoxLayout;
|
||||
|
||||
main_vbox_layout->addWidget(dsp_box);
|
||||
@@ -249,6 +278,7 @@ void AudioPane::CreateWidgets()
|
||||
main_vbox_layout->addWidget(playback_box);
|
||||
#ifdef HAVE_CUBEB
|
||||
main_vbox_layout->addWidget(m_wiimote_routing_box);
|
||||
main_vbox_layout->addWidget(m_gba_routing_box);
|
||||
#endif
|
||||
|
||||
m_main_layout = new QHBoxLayout;
|
||||
@@ -276,15 +306,25 @@ void AudioPane::ConnectWidgets()
|
||||
#ifdef HAVE_CUBEB
|
||||
connect(m_wiimote_routing_enable, &ConfigBool::toggled, this,
|
||||
[this](bool) { UpdateWiimoteRoutingEnabled(); });
|
||||
connect(m_gba_routing_enable, &ConfigBool::toggled, this,
|
||||
[this](bool) { UpdateGBARoutingEnabled(); });
|
||||
for (std::size_t i = 0; i < 4; ++i)
|
||||
{
|
||||
connect(m_wiimote_output_enable[i], &ConfigBool::toggled, this,
|
||||
[this](bool) { UpdateWiimoteRoutingEnabled(); });
|
||||
}
|
||||
for (std::size_t i = 0; i < Config::GBA_SPEAKER_COUNT; ++i)
|
||||
{
|
||||
connect(m_gba_output_enable[i], &ConfigBool::toggled, this,
|
||||
[this](bool) { UpdateGBARoutingEnabled(); });
|
||||
}
|
||||
// Also react to external config changes: wiimote source type, speaker data, BT passthrough.
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
|
||||
&AudioPane::UpdateWiimoteRoutingEnabled);
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
|
||||
&AudioPane::UpdateGBARoutingEnabled);
|
||||
UpdateWiimoteRoutingEnabled();
|
||||
UpdateGBARoutingEnabled();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -321,6 +361,7 @@ void AudioPane::OnBackendChanged()
|
||||
|
||||
#ifdef HAVE_CUBEB
|
||||
UpdateWiimoteRoutingEnabled();
|
||||
UpdateGBARoutingEnabled();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -349,6 +390,7 @@ void AudioPane::OnEmulationStateChanged(bool running)
|
||||
|
||||
#ifdef HAVE_CUBEB
|
||||
UpdateWiimoteRoutingEnabled();
|
||||
UpdateGBARoutingEnabled();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -383,6 +425,33 @@ void AudioPane::UpdateWiimoteRoutingEnabled()
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioPane::UpdateGBARoutingEnabled()
|
||||
{
|
||||
#ifdef HAVE_CUBEB
|
||||
if (!m_gba_routing_box)
|
||||
return;
|
||||
|
||||
const bool running = Core::GetState(Core::System::GetInstance()) != Core::State::Uninitialized;
|
||||
const bool is_cubeb = Config::Get(Config::MAIN_AUDIO_BACKEND) == BACKEND_CUBEB;
|
||||
const bool group_usable = !running && is_cubeb;
|
||||
|
||||
m_gba_routing_enable->setEnabled(group_usable);
|
||||
|
||||
const bool routing_on = group_usable && m_gba_routing_enable->isChecked();
|
||||
|
||||
for (std::size_t i = 0; i < Config::GBA_SPEAKER_COUNT; ++i)
|
||||
{
|
||||
const u32 device_type = Config::Get(Config::GetInfoForSIDevice(static_cast<u32>(i)));
|
||||
const bool is_gba_connected = static_cast<SerialInterface::SIDevices>(device_type) ==
|
||||
SerialInterface::SIDEVICE_GC_GBA_EMULATED;
|
||||
|
||||
m_gba_output_enable[i]->setEnabled(routing_on && is_gba_connected);
|
||||
m_gba_output_device[i]->setEnabled(routing_on && is_gba_connected &&
|
||||
m_gba_output_enable[i]->isChecked());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioPane::CheckNeedForLatencyControl()
|
||||
{
|
||||
std::vector<std::string> backends = AudioCommon::GetSoundBackends();
|
||||
@@ -493,5 +562,30 @@ void AudioPane::AddDescriptions()
|
||||
m_wiimote_output_device[i]->SetDescription(tr(TR_WIIMOTE_OUTPUT_DEVICE_DESCRIPTION));
|
||||
}
|
||||
}
|
||||
|
||||
static const char TR_GBA_ROUTING_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Routes each GBA's speaker audio to a separate audio output device. "
|
||||
"This setting cannot be changed while emulation is active."
|
||||
"<br><br>This setting is disabled when an audio backend other than "
|
||||
"Cubeb is selected."
|
||||
"<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>");
|
||||
static const char TR_GBA_OUTPUT_ENABLE_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Enables routing this GBA's speaker audio to a separate output device.");
|
||||
static const char TR_GBA_OUTPUT_DEVICE_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Selects the audio output device for this GBA's speaker audio."
|
||||
"<br><br>This setting is disabled when this port is not set to GBA "
|
||||
"(Integrated).");
|
||||
|
||||
if (m_gba_routing_box)
|
||||
{
|
||||
m_gba_routing_enable->SetTitle(tr("Enable GBA Audio Routing"));
|
||||
m_gba_routing_enable->SetDescription(tr(TR_GBA_ROUTING_DESCRIPTION));
|
||||
for (std::size_t i = 0; i < Config::GBA_SPEAKER_COUNT; ++i)
|
||||
{
|
||||
m_gba_output_enable[i]->SetDescription(tr(TR_GBA_OUTPUT_ENABLE_DESCRIPTION));
|
||||
m_gba_output_device[i]->SetTitle(tr("GBA %1").arg(i + 1));
|
||||
m_gba_output_device[i]->SetDescription(tr(TR_GBA_OUTPUT_DEVICE_DESCRIPTION));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Core/Config/MainSettings.h"
|
||||
|
||||
namespace AudioCommon
|
||||
{
|
||||
enum class DPL2Quality;
|
||||
@@ -41,6 +43,7 @@ private:
|
||||
void OnDspChanged();
|
||||
|
||||
void UpdateWiimoteRoutingEnabled();
|
||||
void UpdateGBARoutingEnabled();
|
||||
|
||||
void CheckNeedForLatencyControl();
|
||||
bool m_latency_control_supported;
|
||||
@@ -79,4 +82,10 @@ private:
|
||||
ConfigBool* m_wiimote_routing_enable = nullptr;
|
||||
std::array<ConfigBool*, 4> m_wiimote_output_enable{};
|
||||
std::array<ConfigStringChoice*, 4> m_wiimote_output_device{};
|
||||
|
||||
// GBA Audio Routing
|
||||
QGroupBox* m_gba_routing_box = nullptr;
|
||||
ConfigBool* m_gba_routing_enable = nullptr;
|
||||
std::array<ConfigBool*, Config::GBA_SPEAKER_COUNT> m_gba_output_enable{};
|
||||
std::array<ConfigStringChoice*, Config::GBA_SPEAKER_COUNT> m_gba_output_device{};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user