nsyshid: Play Emulated Portal Audio via Mono Audio (#1478)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 42s

This commit is contained in:
Joshua de Reeper 2025-06-19 23:30:19 +02:00 committed by GitHub
parent 00ff5549d9
commit 4f4412b334
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 254 additions and 41 deletions

View file

@ -13,13 +13,14 @@
std::shared_mutex g_audioMutex;
AudioAPIPtr g_tvAudio;
AudioAPIPtr g_padAudio;
AudioAPIPtr g_portalAudio;
std::atomic_int32_t g_padVolume = 0;
uint32 IAudioAPI::s_audioDelay = 2;
std::array<bool, IAudioAPI::AudioAPIEnd> IAudioAPI::s_availableApis{};
IAudioAPI::IAudioAPI(uint32 samplerate, uint32 channels, uint32 samples_per_block, uint32 bits_per_sample)
: m_samplerate(samplerate), m_channels(channels), m_samplesPerBlock(samples_per_block), m_bitsPerSample(bits_per_sample)
: m_samplerate(samplerate), m_channels(channels), m_samplesPerBlock(samples_per_block), m_bitsPerSample(bits_per_sample)
{
m_bytesPerBlock = samples_per_block * channels * (bits_per_sample / 8);
InitWFX(m_samplerate, m_channels, m_bitsPerSample);
@ -80,7 +81,7 @@ void IAudioAPI::InitializeStatic()
#if BOOST_OS_WINDOWS
s_availableApis[DirectSound] = true;
s_availableApis[XAudio2] = XAudio2API::InitializeStatic();
if(!s_availableApis[XAudio2]) // don't try to initialize the older lib if the newer version is available
if (!s_availableApis[XAudio2]) // don't try to initialize the older lib if the newer version is available
s_availableApis[XAudio27] = XAudio27API::InitializeStatic();
#endif
#if HAS_CUBEB
@ -97,30 +98,29 @@ bool IAudioAPI::IsAudioAPIAvailable(AudioAPI api)
return false;
}
AudioAPIPtr IAudioAPI::CreateDeviceFromConfig(bool TV, sint32 rate, sint32 samples_per_block, sint32 bits_per_sample)
AudioAPIPtr IAudioAPI::CreateDeviceFromConfig(AudioType type, sint32 rate, sint32 samples_per_block, sint32 bits_per_sample)
{
auto& config = GetConfig();
sint32 channels = CemuConfig::AudioChannelsToNChannels(TV ? config.tv_channels : config.pad_channels);
return CreateDeviceFromConfig(TV, rate, channels, samples_per_block, bits_per_sample);
sint32 channels = CemuConfig::AudioChannelsToNChannels(AudioTypeToChannels(type));
return CreateDeviceFromConfig(type, rate, channels, samples_per_block, bits_per_sample);
}
AudioAPIPtr IAudioAPI::CreateDeviceFromConfig(bool TV, sint32 rate, sint32 channels, sint32 samples_per_block, sint32 bits_per_sample)
AudioAPIPtr IAudioAPI::CreateDeviceFromConfig(AudioType type, sint32 rate, sint32 channels, sint32 samples_per_block, sint32 bits_per_sample)
{
AudioAPIPtr audioAPIDev;
auto& config = GetConfig();
const auto audio_api = (IAudioAPI::AudioAPI)config.audio_api;
auto& selectedDevice = TV ? config.tv_device : config.pad_device;
auto selectedDevice = GetDeviceFromType(type);
if(selectedDevice.empty())
if (selectedDevice.empty())
return {};
IAudioAPI::DeviceDescriptionPtr device_description;
if (IAudioAPI::IsAudioAPIAvailable(audio_api))
{
auto devices = IAudioAPI::GetDevices(audio_api);
const auto it = std::find_if(devices.begin(), devices.end(), [&selectedDevice](const auto& d) {return d->GetIdentifier() == selectedDevice; });
const auto it = std::find_if(devices.begin(), devices.end(), [&selectedDevice](const auto& d) { return d->GetIdentifier() == selectedDevice; });
if (it != devices.end())
device_description = *it;
}
@ -128,7 +128,8 @@ AudioAPIPtr IAudioAPI::CreateDeviceFromConfig(bool TV, sint32 rate, sint32 chann
throw std::runtime_error("failed to find selected device while trying to create audio device");
audioAPIDev = CreateDevice(audio_api, device_description, rate, channels, samples_per_block, bits_per_sample);
audioAPIDev->SetVolume(TV ? config.tv_volume : config.pad_volume);
audioAPIDev->SetVolume(GetVolumeFromType(type));
return audioAPIDev;
}
@ -137,7 +138,7 @@ AudioAPIPtr IAudioAPI::CreateDevice(AudioAPI api, const DeviceDescriptionPtr& de
if (!IsAudioAPIAvailable(api))
return {};
switch(api)
switch (api)
{
#if BOOST_OS_WINDOWS
case DirectSound:
@ -157,11 +158,11 @@ AudioAPIPtr IAudioAPI::CreateDevice(AudioAPI api, const DeviceDescriptionPtr& de
}
#endif
#if HAS_CUBEB
case Cubeb:
{
const auto tmp = std::dynamic_pointer_cast<CubebAPI::CubebDeviceDescription>(device);
return std::make_unique<CubebAPI>(tmp->GetDeviceId(), samplerate, channels, samples_per_block, bits_per_sample);
}
case Cubeb:
{
const auto tmp = std::dynamic_pointer_cast<CubebAPI::CubebDeviceDescription>(device);
return std::make_unique<CubebAPI>(tmp->GetDeviceId(), samplerate, channels, samples_per_block, bits_per_sample);
}
#endif
default:
throw std::runtime_error(fmt::format("invalid audio api: {}", api));
@ -172,8 +173,8 @@ std::vector<IAudioAPI::DeviceDescriptionPtr> IAudioAPI::GetDevices(AudioAPI api)
{
if (!IsAudioAPIAvailable(api))
return {};
switch(api)
switch (api)
{
#if BOOST_OS_WINDOWS
case DirectSound:
@ -209,3 +210,51 @@ uint32 IAudioAPI::GetAudioDelay() const
{
return m_audioDelayOverride > 0 ? m_audioDelayOverride : s_audioDelay;
}
AudioChannels IAudioAPI::AudioTypeToChannels(AudioType type)
{
auto& config = GetConfig();
switch (type)
{
case TV:
return config.tv_channels;
case Gamepad:
return config.pad_channels;
case Portal:
return kMono;
default:
return kMono;
}
}
std::wstring IAudioAPI::GetDeviceFromType(AudioType type)
{
auto& config = GetConfig();
switch (type)
{
case TV:
return config.tv_device;
case Gamepad:
return config.pad_device;
case Portal:
return config.portal_device;
default:
return L"";
}
}
sint32 IAudioAPI::GetVolumeFromType(AudioType type)
{
auto& config = GetConfig();
switch (type)
{
case TV:
return config.tv_volume;
case Gamepad:
return config.pad_volume;
case Portal:
return config.portal_volume;
default:
return 0;
}
}

View file

@ -4,6 +4,8 @@
#include <mmreg.h>
#endif
#include "config/CemuConfig.h"
class IAudioAPI
{
friend class GeneralSettings2;
@ -30,6 +32,13 @@ public:
using DeviceDescriptionPtr = std::shared_ptr<DeviceDescription>;
enum AudioType
{
TV = 0,
Gamepad,
Portal
};
enum AudioAPI
{
DirectSound = 0,
@ -62,8 +71,8 @@ public:
static void InitializeStatic();
static bool IsAudioAPIAvailable(AudioAPI api);
static std::unique_ptr<IAudioAPI> CreateDeviceFromConfig(bool TV, sint32 rate, sint32 samples_per_block, sint32 bits_per_sample);
static std::unique_ptr<IAudioAPI> CreateDeviceFromConfig(bool TV, sint32 rate, sint32 channels, sint32 samples_per_block, sint32 bits_per_sample);
static std::unique_ptr<IAudioAPI> CreateDeviceFromConfig(AudioType type, sint32 rate, sint32 samples_per_block, sint32 bits_per_sample);
static std::unique_ptr<IAudioAPI> CreateDeviceFromConfig(AudioType type, sint32 rate, sint32 channels, sint32 samples_per_block, sint32 bits_per_sample);
static std::unique_ptr<IAudioAPI> CreateDevice(AudioAPI api, const DeviceDescriptionPtr& device, sint32 samplerate, sint32 channels, sint32 samples_per_block, sint32 bits_per_sample);
static std::vector<DeviceDescriptionPtr> GetDevices(AudioAPI api);
@ -84,6 +93,9 @@ protected:
private:
static uint32 s_audioDelay;
void InitWFX(sint32 samplerate, sint32 channels, sint32 bits_per_sample);
static AudioChannels AudioTypeToChannels(AudioType type);
static std::wstring GetDeviceFromType(AudioType type);
static sint32 GetVolumeFromType(AudioType type);
};
@ -93,3 +105,5 @@ extern AudioAPIPtr g_tvAudio;
extern AudioAPIPtr g_padAudio;
extern std::atomic_int32_t g_padVolume;
extern AudioAPIPtr g_portalAudio;