Try to make most audio configs dynamic

This commit is contained in:
Megamouse 2020-06-20 02:44:32 +02:00
parent 8ee953ef8e
commit 20d6664dc1
12 changed files with 228 additions and 109 deletions

View File

@ -12,8 +12,7 @@ LOG_CHANNEL(OpenAL);
#define checkForAlcError(sit) do { ALCenum g_last_alc_error = alcGetError(m_device); if(g_last_alc_error != ALC_NO_ERROR) { OpenAL.error("%s: OpenALC error 0x%04x", sit, g_last_alc_error); return; }} while(0)
OpenALBackend::OpenALBackend()
: m_sampling_rate(get_sampling_rate())
, m_sample_size(get_sample_size())
: AudioBackend()
{
ALCdevice* m_device = alcOpenDevice(nullptr);
checkForAlcError("alcOpenDevice");
@ -24,9 +23,7 @@ OpenALBackend::OpenALBackend()
alcMakeContextCurrent(m_context);
checkForAlcError("alcMakeContextCurrent");
const auto channels = get_channels();
switch (channels)
switch (m_channels)
{
case 2:
m_format = (m_sample_size == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32;

View File

@ -15,9 +15,6 @@ private:
u32 m_next_buffer = 0;
u32 m_num_unqueued = 0;
const u32 m_sampling_rate;
const u32 m_sample_size;
void unqueue_processed();
public:

View File

@ -1,4 +1,4 @@
#ifndef HAVE_ALSA
#ifndef HAVE_ALSA
#error "ALSA support disabled but still being built."
#endif
@ -26,6 +26,7 @@ static bool check(int err, const char* reason)
}
ALSABackend::ALSABackend()
: AudioBackend()
{
}
@ -51,14 +52,14 @@ void ALSABackend::Open(u32 num_buffers)
if (!check(snd_pcm_hw_params_set_access(tls_handle, tls_hw_params, SND_PCM_ACCESS_RW_INTERLEAVED), "snd_pcm_hw_params_set_access"))
return;
if (!check(snd_pcm_hw_params_set_format(tls_handle, tls_hw_params, g_cfg.audio.convert_to_u16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_FLOAT_LE), "snd_pcm_hw_params_set_format"))
if (!check(snd_pcm_hw_params_set_format(tls_handle, tls_hw_params, m_convert_to_u16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_FLOAT_LE), "snd_pcm_hw_params_set_format"))
return;
uint rate = get_sampling_rate();
uint rate = m_sampling_rate;
if (!check(snd_pcm_hw_params_set_rate_near(tls_handle, tls_hw_params, &rate, nullptr), "snd_pcm_hw_params_set_rate_near"))
return;
if (!check(snd_pcm_hw_params_set_channels(tls_handle, tls_hw_params, get_channels()), "snd_pcm_hw_params_set_channels"))
if (!check(snd_pcm_hw_params_set_channels(tls_handle, tls_hw_params, m_channels), "snd_pcm_hw_params_set_channels"))
return;
//uint period = 5333;
@ -92,7 +93,7 @@ void ALSABackend::Open(u32 num_buffers)
if (!check(snd_pcm_sw_params_current(tls_handle, tls_sw_params), "snd_pcm_sw_params_current"))
return;
period_frames *= g_cfg.audio.startt;
period_frames *= m_start_threshold;
if (!check(snd_pcm_sw_params_set_start_threshold(tls_handle, tls_sw_params, period_frames + 1), "snd_pcm_sw_params_set_start_threshold"))
return;
@ -132,7 +133,7 @@ void ALSABackend::Close()
bool ALSABackend::AddData(const void* src, u32 num_samples)
{
u32 num_frames = num_samples / get_channels();
u32 num_frames = num_samples / m_channels;
int res = snd_pcm_writei(tls_handle, src, num_frames);

View File

@ -2,45 +2,69 @@
#include "AudioBackend.h"
#include "Emu/system_config.h"
/*
* Helper methods
*/
u32 AudioBackend::get_sampling_rate()
AudioBackend::AudioBackend()
{
m_convert_to_u16 = static_cast<bool>(g_cfg.audio.convert_to_u16);
m_sample_size = m_convert_to_u16 ? sizeof(u16) : sizeof(float);
m_start_threshold = g_cfg.audio.start_threshold;
const u32 sampling_period_multiplier_u32 = g_cfg.audio.sampling_period_multiplier;
if (sampling_period_multiplier_u32 == 100)
return DEFAULT_AUDIO_SAMPLING_RATE;
{
m_sampling_rate = DEFAULT_AUDIO_SAMPLING_RATE;
}
else
{
const f32 sampling_period_multiplier = sampling_period_multiplier_u32 / 100.0f;
const f32 sampling_rate_multiplier = 1.0f / sampling_period_multiplier;
m_sampling_rate = static_cast<u32>(f32{ DEFAULT_AUDIO_SAMPLING_RATE } *sampling_rate_multiplier);
}
const f32 sampling_period_multiplier = sampling_period_multiplier_u32 / 100.0f;
const f32 sampling_rate_multiplier = 1.0f / sampling_period_multiplier;
return static_cast<u32>(f32{DEFAULT_AUDIO_SAMPLING_RATE} * sampling_rate_multiplier);
}
u32 AudioBackend::get_sample_size()
{
return g_cfg.audio.convert_to_u16 ? sizeof(u16) : sizeof(float);
}
u32 AudioBackend::get_channels()
{
const audio_channels channels = g_cfg.audio.audio_channel_downmix.get();
switch (channels)
{
case audio_channels::use_application_settings:
return 2; // TODO
m_channels = 2; // TODO
break;
case audio_channels::downmix_to_stereo:
return 2;
m_channels = 2;
break;
case audio_channels::downmix_to_5_1:
return 6;
m_channels = 6;
break;
case audio_channels::surround_7_1:
return 8;
m_channels = 8;
break;
default:
fmt::throw_exception("Unknown audio channel mode %s (%d)", channels, static_cast<int>(channels));
}
}
/*
* Helper methods
*/
u32 AudioBackend::get_sampling_rate() const
{
return m_sampling_rate;
}
u32 AudioBackend::get_sample_size() const
{
return m_sample_size;
}
u32 AudioBackend::get_channels() const
{
return m_channels;
}
bool AudioBackend::get_convert_to_u16() const
{
return m_convert_to_u16;
}
bool AudioBackend::has_capability(u32 cap) const
{
return (cap & GetCapabilities()) == cap;

View File

@ -20,6 +20,8 @@ public:
SET_FREQUENCY_RATIO = 0x8, // Implements SetFrequencyRatio
};
AudioBackend();
virtual ~AudioBackend() = default;
/*
@ -94,13 +96,22 @@ public:
/*
* Helper methods
*/
static u32 get_sampling_rate();
u32 get_sampling_rate() const;
static u32 get_sample_size();
u32 get_sample_size() const;
static u32 get_channels();
u32 get_channels() const;
bool get_convert_to_u16() const;
bool has_capability(u32 cap) const;
void dump_capabilities(std::string& out) const;
protected:
bool m_convert_to_u16 = false;
u32 m_sample_size = sizeof(float);
u32 m_sampling_rate = DEFAULT_AUDIO_SAMPLING_RATE;
u32 m_channels = 0;
u32 m_start_threshold = 1;
};

View File

@ -1,4 +1,4 @@
#ifndef HAVE_FAUDIO
#ifndef HAVE_FAUDIO
#error "FAudio support disabled but still being built."
#endif
@ -10,6 +10,7 @@
LOG_CHANNEL(FAudio_, "FAudio");
FAudioBackend::FAudioBackend()
: AudioBackend()
{
u32 res;
@ -20,7 +21,7 @@ FAudioBackend::FAudioBackend()
return;
}
res = FAudio_CreateMasteringVoice(m_instance, &m_master_voice, g_cfg.audio.downmix_to_2ch ? 2 : 8, 48000, 0, 0, nullptr);
res = FAudio_CreateMasteringVoice(m_instance, &m_master_voice, m_channels, 48000, 0, 0, nullptr);
if (res)
{
FAudio_.fatal("FAudio_CreateMasteringVoice() failed(0x%08x)", res);
@ -102,17 +103,13 @@ void FAudioBackend::Close()
void FAudioBackend::Open(u32 /* num_buffers */)
{
const u32 sample_size = AudioBackend::get_sample_size();
const u32 channels = AudioBackend::get_channels();
const u32 sampling_rate = AudioBackend::get_sampling_rate();
FAudioWaveFormatEx waveformatex;
waveformatex.wFormatTag = g_cfg.audio.convert_to_u16 ? FAUDIO_FORMAT_PCM : FAUDIO_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = channels;
waveformatex.nSamplesPerSec = sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<u32>(sampling_rate * channels * sample_size);
waveformatex.nBlockAlign = channels * sample_size;
waveformatex.wBitsPerSample = sample_size * 8;
waveformatex.wFormatTag = m_convert_to_u16 ? FAUDIO_FORMAT_PCM : FAUDIO_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = m_channels;
waveformatex.nSamplesPerSec = m_sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<u32>(m_sampling_rate * m_channels * m_sample_size);
waveformatex.nBlockAlign = m_channels * m_sample_size;
waveformatex.wBitsPerSample = m_sample_size * 8;
waveformatex.cbSize = 0;
u32 res = FAudio_CreateSourceVoice(m_instance, &m_source_voice, &waveformatex, 0, FAUDIO_DEFAULT_FREQ_RATIO, nullptr, nullptr, nullptr);
@ -140,7 +137,7 @@ bool FAudioBackend::AddData(const void* src, u32 num_samples)
}
FAudioBuffer buffer;
buffer.AudioBytes = num_samples * AudioBackend::get_sample_size();
buffer.AudioBytes = num_samples * m_sample_size;
buffer.Flags = 0;
buffer.LoopBegin = FAUDIO_NO_LOOP_REGION;
buffer.LoopCount = 0;

View File

@ -1,4 +1,4 @@
#ifndef HAVE_PULSE
#ifndef HAVE_PULSE
#error "PulseAudio support disabled but still being built."
#endif
@ -9,6 +9,7 @@
#include <pulse/error.h>
PulseBackend::PulseBackend()
: AudioBackend()
{
}
@ -19,7 +20,8 @@ PulseBackend::~PulseBackend()
void PulseBackend::Close()
{
if(this->connection) {
if (this->connection)
{
pa_simple_free(this->connection);
this->connection = nullptr;
}
@ -28,20 +30,30 @@ void PulseBackend::Close()
void PulseBackend::Open(u32 /* num_buffers */)
{
pa_sample_spec ss;
ss.format = (get_sample_size() == 2) ? PA_SAMPLE_S16LE : PA_SAMPLE_FLOAT32LE;
ss.rate = get_sampling_rate();
ss.format = (m_sample_size == 2) ? PA_SAMPLE_S16LE : PA_SAMPLE_FLOAT32LE;
ss.rate = m_sampling_rate;
pa_channel_map channel_map;
if (get_channels() == 2)
if (m_channels == 2)
{
channel_map.channels = 2;
channel_map.channels = 2;
channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
}
else if (m_channels == 6)
{
channel_map.channels = 6;
channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
channel_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
channel_map.map[3] = PA_CHANNEL_POSITION_LFE;
channel_map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
channel_map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
}
else
{
channel_map.channels = 8;
channel_map.channels = 8;
channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
channel_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
@ -55,7 +67,8 @@ void PulseBackend::Open(u32 /* num_buffers */)
int err;
this->connection = pa_simple_new(NULL, "RPCS3", PA_STREAM_PLAYBACK, NULL, "Game", &ss, &channel_map, NULL, &err);
if(!this->connection) {
if (!this->connection)
{
fprintf(stderr, "PulseAudio: Failed to initialize audio: %s\n", pa_strerror(err));
}
}
@ -65,10 +78,11 @@ bool PulseBackend::AddData(const void* src, u32 num_samples)
AUDIT(this->connection);
int err;
if(pa_simple_write(this->connection, src, num_samples * get_sample_size(), &err) < 0) {
if (pa_simple_write(this->connection, src, num_samples * m_sample_size, &err) < 0)
{
fprintf(stderr, "PulseAudio: Failed to write audio stream: %s\n", pa_strerror(err));
return false;
}
return true;
}

View File

@ -16,6 +16,7 @@
LOG_CHANNEL(XAudio);
XAudio2Backend::XAudio2Backend()
: AudioBackend()
{
Microsoft::WRL::ComPtr<IXAudio2> instance;
@ -30,7 +31,7 @@ XAudio2Backend::XAudio2Backend()
return;
}
hr = instance->CreateMasteringVoice(&m_master_voice, get_channels(), 48000);
hr = instance->CreateMasteringVoice(&m_master_voice, m_channels, 48000);
if (FAILED(hr))
{
XAudio.error("CreateMasteringVoice() failed: %s (0x%08x)", std::system_category().message(hr), static_cast<u32>(hr));
@ -94,17 +95,13 @@ void XAudio2Backend::Open(u32 /* num_buffers */)
{
HRESULT hr;
const u32 sample_size = AudioBackend::get_sample_size();
const u32 channels = AudioBackend::get_channels();
const u32 sampling_rate = AudioBackend::get_sampling_rate();
WAVEFORMATEX waveformatex;
waveformatex.wFormatTag = g_cfg.audio.convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = channels;
waveformatex.nSamplesPerSec = sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<DWORD>(sampling_rate * channels * sample_size);
waveformatex.nBlockAlign = channels * sample_size;
waveformatex.wBitsPerSample = sample_size * 8;
waveformatex.wFormatTag = m_convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = m_channels;
waveformatex.nSamplesPerSec = m_sampling_rate;
waveformatex.nAvgBytesPerSec = static_cast<DWORD>(m_sampling_rate * m_channels * m_sample_size);
waveformatex.nBlockAlign = m_channels * m_sample_size;
waveformatex.wBitsPerSample = m_sample_size * 8;
waveformatex.cbSize = 0;
hr = m_xaudio2_instance->CreateSourceVoice(&m_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
@ -144,7 +141,7 @@ bool XAudio2Backend::AddData(const void* src, u32 num_samples)
XAUDIO2_BUFFER buffer;
buffer.AudioBytes = num_samples * AudioBackend::get_sample_size();
buffer.AudioBytes = num_samples * m_sample_size;
buffer.Flags = 0;
buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION;
buffer.LoopCount = 0;

View File

@ -44,6 +44,43 @@ void fmt_class_string<CellAudioError>::format(std::string& out, u64 arg)
cell_audio_config::cell_audio_config()
{
reset();
}
void cell_audio_config::reset()
{
backend.reset();
backend = Emu.GetCallbacks().get_audio();
audio_channels = backend->get_channels();
audio_sampling_rate = backend->get_sampling_rate();
audio_block_period = AUDIO_BUFFER_SAMPLES * 1000000 / audio_sampling_rate;
audio_buffer_length = AUDIO_BUFFER_SAMPLES * audio_channels;
audio_buffer_size = audio_buffer_length * backend->get_sample_size();
desired_buffer_duration = g_cfg.audio.desired_buffer_duration * 1000llu;
const bool raw_buffering_enabled = static_cast<bool>(g_cfg.audio.enable_buffering);
buffering_enabled = raw_buffering_enabled && backend->has_capability(AudioBackend::PLAY_PAUSE_FLUSH | AudioBackend::IS_PLAYING);;
minimum_block_period = audio_block_period / 2;
maximum_block_period = (6 * audio_block_period) / 5;
desired_full_buffers = buffering_enabled ? static_cast<u32>(desired_buffer_duration / audio_block_period) + 3 : 2;
num_allocated_buffers = desired_full_buffers + EXTRA_AUDIO_BUFFERS;
fully_untouched_timeout = static_cast<u64>(audio_block_period) * 2;
partially_untouched_timeout = static_cast<u64>(audio_block_period) * 4;
const s64 raw_time_stretching_threshold = g_cfg.audio.time_stretching_threshold;
const bool raw_time_stretching_enabled = buffering_enabled && g_cfg.audio.enable_time_stretching && (raw_time_stretching_threshold > 0);
time_stretching_enabled = raw_time_stretching_enabled && backend->has_capability(AudioBackend::SET_FREQUENCY_RATIO);
time_stretching_threshold = raw_time_stretching_threshold / 100.0f;
// Warn if audio backend does not support all requested features
if (raw_buffering_enabled && !buffering_enabled)
{
@ -500,6 +537,31 @@ void cell_audio_thread::advance(u64 timestamp, bool reset)
}
}
namespace audio
{
void configure_audio()
{
if (const auto g_audio = g_fxo->get<cell_audio>())
{
g_audio->m_update_configuration = true;
}
}
}
void cell_audio_thread::update_config()
{
std::lock_guard lock(mutex);
// Clear ringbuffer
ringbuffer.reset();
// Reload config
cfg.reset();
// Allocate ringbuffer
ringbuffer.reset(new audio_ringbuffer(cfg));
}
void cell_audio_thread::operator()()
{
thread_ctrl::set_native_priority(1);
@ -519,6 +581,12 @@ void cell_audio_thread::operator()()
// Main cellAudio loop
while (thread_ctrl::state() != thread_state::aborting)
{
if (m_update_configuration)
{
update_config();
m_update_configuration = false;
}
const u64 timestamp = ringbuffer->update();
if (Emu.IsPaused())
@ -959,7 +1027,7 @@ void cell_audio_thread::mix(float *out_buffer, s32 offset)
{
std::memset(out_buffer, 0, out_buffer_sz * sizeof(float));
}
else if (g_cfg.audio.convert_to_u16)
else if (cfg.backend->get_convert_to_u16())
{
// convert the data from float to u16 with clipping:
// 2x MULPS

View File

@ -187,49 +187,46 @@ struct audio_port
struct cell_audio_config
{
const std::shared_ptr<AudioBackend> backend = Emu.GetCallbacks().get_audio();
std::shared_ptr<AudioBackend> backend = nullptr;
const u32 audio_channels = AudioBackend::get_channels();
const u32 audio_sampling_rate = AudioBackend::get_sampling_rate();
const u32 audio_block_period = AUDIO_BUFFER_SAMPLES * 1000000 / audio_sampling_rate;
u32 audio_channels = 0;
u32 audio_sampling_rate = 0;
u32 audio_block_period = 0;
const u32 audio_buffer_length = AUDIO_BUFFER_SAMPLES * audio_channels;
const u32 audio_buffer_size = audio_buffer_length * AudioBackend::get_sample_size();
u32 audio_buffer_length = 0;
u32 audio_buffer_size = 0;
/*
* Buffering
*/
const u64 desired_buffer_duration = g_cfg.audio.desired_buffer_duration * 1000llu;
private:
const bool raw_buffering_enabled = static_cast<bool>(g_cfg.audio.enable_buffering);
public:
u64 desired_buffer_duration = 0;
// We need a non-blocking backend (implementing play/pause/flush) to be able to do buffering correctly
// We also need to be able to query the current playing state
const bool buffering_enabled = raw_buffering_enabled && backend->has_capability(AudioBackend::PLAY_PAUSE_FLUSH | AudioBackend::IS_PLAYING);
bool buffering_enabled = false;
const u64 minimum_block_period = audio_block_period / 2; // the block period will not be dynamically lowered below this value (usecs)
const u64 maximum_block_period = (6 * audio_block_period) / 5; // the block period will not be dynamically increased above this value (usecs)
u64 minimum_block_period = 0; // the block period will not be dynamically lowered below this value (usecs)
u64 maximum_block_period = 0; // the block period will not be dynamically increased above this value (usecs)
const u32 desired_full_buffers = buffering_enabled ? static_cast<u32>(desired_buffer_duration / audio_block_period) + 3 : 2;
const u32 num_allocated_buffers = desired_full_buffers + EXTRA_AUDIO_BUFFERS; // number of ringbuffer buffers
u32 desired_full_buffers = 0;
u32 num_allocated_buffers = 0; // number of ringbuffer buffers
const f32 period_average_alpha = 0.02f; // alpha factor for the m_average_period rolling average
const s64 period_comparison_margin = 250; // when comparing the current period time with the desired period, if it is below this number of usecs we do not wait any longer
const u64 fully_untouched_timeout = 2 * audio_block_period; // timeout if the game has not touched any audio buffer yet
const u64 partially_untouched_timeout = 4 * audio_block_period; // timeout if the game has not touched all audio buffers yet
u64 fully_untouched_timeout = 0; // timeout if the game has not touched any audio buffer yet
u64 partially_untouched_timeout = 0; // timeout if the game has not touched all audio buffers yet
/*
* Time Stretching
*/
private:
const bool raw_time_stretching_enabled = buffering_enabled && g_cfg.audio.enable_time_stretching && (g_cfg.audio.time_stretching_threshold > 0);
public:
// We need to be able to set a dynamic frequency ratio to be able to do time stretching
const bool time_stretching_enabled = raw_time_stretching_enabled && backend->has_capability(AudioBackend::SET_FREQUENCY_RATIO);
const f32 time_stretching_threshold = g_cfg.audio.time_stretching_threshold / 100.0f; // we only apply time stretching below this buffer fill rate (adjusted for average period)
// We need to be able to set a dynamic frequency ratio to be able to do time stretching
bool time_stretching_enabled = false;
f32 time_stretching_threshold = 0.0f; // we only apply time stretching below this buffer fill rate (adjusted for average period)
const f32 time_stretching_step = 0.1f; // will only reduce/increase the frequency ratio in steps of at least this value
const f32 time_stretching_scale = 0.9f;
@ -237,6 +234,11 @@ public:
* Constructor
*/
cell_audio_config();
/*
* Config changes
*/
void reset();
};
class audio_ringbuffer
@ -337,6 +339,7 @@ public:
class cell_audio_thread
{
private:
std::unique_ptr<audio_ringbuffer> ringbuffer;
void reset_ports(s32 offset = 0);
@ -351,8 +354,11 @@ class cell_audio_thread
return (time_left > 350) ? time_left - 250 : 100;
}
void update_config();
public:
cell_audio_config cfg;
atomic_t<bool> m_update_configuration = false;
shared_mutex mutex;
atomic_t<u32> init = 0;
@ -375,7 +381,7 @@ public:
u64 m_counter = 0;
u64 m_start_time = 0;
u64 m_dynamic_period = 0;
f32 m_average_playtime;
f32 m_average_playtime = 0.0f;
void operator()();
@ -405,3 +411,8 @@ public:
};
using cell_audio = named_thread<cell_audio_thread>;
namespace audio
{
void configure_audio();
}

View File

@ -208,23 +208,23 @@ struct cfg_root : cfg::node
cfg::_enum<audio_renderer> renderer{ this, "Renderer",
#ifdef _WIN32
audio_renderer::xaudio };
audio_renderer::xaudio, true };
#elif HAVE_FAUDIO
audio_renderer::faudio };
audio_renderer::faudio, true };
#else
audio_renderer::openal };
audio_renderer::openal, true };
#endif
cfg::_bool dump_to_file{ this, "Dump to file" };
cfg::_bool convert_to_u16{ this, "Convert to 16 bit" };
cfg::_enum<audio_channels> audio_channel_downmix{ this, "Audio Channels", audio_channels::downmix_to_stereo };
cfg::_int<1, 128> startt{ this, "Start Threshold", 1 }; // TODO: used only by ALSA, should probably be removed once ALSA is upgraded
cfg::_bool convert_to_u16{ this, "Convert to 16 bit", false, true };
cfg::_enum<audio_channels> audio_channel_downmix{ this, "Audio Channels", audio_channels::downmix_to_stereo, true };
cfg::_int<1, 128> start_threshold{ this, "Start Threshold", 1, true }; // TODO: used only by ALSA, should probably be removed once ALSA is upgraded
cfg::_int<0, 200> volume{ this, "Master Volume", 100, true };
cfg::_bool enable_buffering{ this, "Enable Buffering", true };
cfg::_int <4, 250> desired_buffer_duration{ this, "Desired Audio Buffer Duration", 100 };
cfg::_int<1, 1000> sampling_period_multiplier{ this, "Sampling Period Multiplier", 100 };
cfg::_bool enable_time_stretching{ this, "Enable Time Stretching", false };
cfg::_int<0, 100> time_stretching_threshold{ this, "Time Stretching Threshold", 75 };
cfg::_bool enable_buffering{ this, "Enable Buffering", true, true };
cfg::_int <4, 250> desired_buffer_duration{ this, "Desired Audio Buffer Duration", 100, true };
cfg::_int<1, 1000> sampling_period_multiplier{ this, "Sampling Period Multiplier", 100, true };
cfg::_bool enable_time_stretching{ this, "Enable Time Stretching", false, true };
cfg::_int<0, 100> time_stretching_threshold{ this, "Time Stretching Threshold", 75, true };
cfg::_enum<microphone_handler> microphone_type{ this, "Microphone Type", microphone_handler::null };
cfg::string microphone_devices{ this, "Microphone Devices", ";;;;" };
} audio{ this };

View File

@ -14,6 +14,7 @@
#include "_discord_utils.h"
#endif
#include "Emu/Cell/Modules/cellAudio.h"
#include "Emu/RSX/Overlays/overlay_perf_metrics.h"
#include "trophy_notification_helper.h"
#include "save_data_dialog.h"
@ -474,6 +475,7 @@ void gui_application::OnEmuSettingsChange()
}
Emu.ConfigureLogs();
audio::configure_audio();
rsx::overlays::reset_performance_overlay();
}