From 74e752ed9c07c8cc982f8c6a46a966d0cfd0a933 Mon Sep 17 00:00:00 2001 From: Sam Belliveau Date: Fri, 4 Apr 2025 00:49:03 -0400 Subject: [PATCH] Mixer: Use Doubles for Sample Rate Conversion. --- Source/Core/AudioCommon/Mixer.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp index 31c30e76af..b52371d994 100644 --- a/Source/Core/AudioCommon/Mixer.cpp +++ b/Source/Core/AudioCommon/Mixer.cpp @@ -65,14 +65,17 @@ void Mixer::MixerFifo::Mix(s16* samples, std::size_t num_samples) constexpr DT_s FADE_IN_RC = DT_s(0.008); constexpr DT_s FADE_OUT_RC = DT_s(0.064); - const u64 out_sample_rate = m_mixer->m_output_sample_rate; - u64 in_sample_rate = FIXED_SAMPLE_RATE_DIVIDEND / m_input_sample_rate_divisor; + // We need at least a double because the index jump has 24 bits of fractional precision. + const double out_sample_rate = m_mixer->m_output_sample_rate; + double in_sample_rate = + static_cast(FIXED_SAMPLE_RATE_DIVIDEND) / m_input_sample_rate_divisor; - const float emulation_speed = m_mixer->m_config_emulation_speed; + const double emulation_speed = m_mixer->m_config_emulation_speed; if (0 < emulation_speed && emulation_speed != 1.0) - in_sample_rate = static_cast(std::llround(in_sample_rate * emulation_speed)); + in_sample_rate *= emulation_speed; - const u32 index_jump = (in_sample_rate << GRANULE_FRAC_BITS) / (out_sample_rate); + const double base = static_cast(1 << GRANULE_FRAC_BITS); + const u32 index_jump = std::lround(base * in_sample_rate / out_sample_rate); // These fade in / out multiplier are tuned to match a constant // fade speed regardless of the input or the output sample rate. @@ -83,7 +86,7 @@ void Mixer::MixerFifo::Mix(s16* samples, std::size_t num_samples) // Calculate the ideal length of the granule queue. const std::size_t buffer_size_ms = m_mixer->m_config_audio_buffer_ms; - const std::size_t buffer_size_samples = buffer_size_ms * in_sample_rate / 1000; + const std::size_t buffer_size_samples = std::llround(buffer_size_ms * in_sample_rate / 1000.0); // Limit the possible queue sizes to any number between 4 and 64. const std::size_t buffer_size_granules =