Skip to content

Commit

Permalink
Use doubles to count m_ratio to improve accuracy
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam-Belliveau committed May 24, 2024
1 parent ce19d74 commit 2767c22
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 21 deletions.
6 changes: 3 additions & 3 deletions Source/Core/AudioCommon/AudioStretcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ void AudioStretcher::ProcessSamples(const short* in, unsigned int num_in, unsign
// We were given actual_samples number of samples, and num_samples were requested from us.
double current_ratio = static_cast<double>(num_in) / static_cast<double>(num_out);

const double max_latency = Config::Get(Config::MAIN_AUDIO_STRETCH_LATENCY);
const double max_backlog = m_sample_rate * max_latency / 1000.0 / m_stretch_ratio;
const double max_latency = Config::Get(Config::MAIN_AUDIO_STRETCH_LATENCY) / 1000.0;
const double max_backlog = m_sample_rate * max_latency / m_stretch_ratio;
const double backlog_fullness = m_sound_touch.numSamples() / max_backlog;
if (backlog_fullness > 5.0)
{
Expand All @@ -49,7 +49,7 @@ void AudioStretcher::ProcessSamples(const short* in, unsigned int num_in, unsign

// This low-pass filter smoothes out variance in the calculated stretch ratio.
// The time-scale determines how responsive this filter is.
constexpr double lpf_time_scale = 0.1; // seconds
const double lpf_time_scale = max_latency * tweak_time_scale; // seconds
const double lpf_gain = 1.0 - std::exp(-time_delta / lpf_time_scale);
m_stretch_ratio += lpf_gain * (current_ratio - m_stretch_ratio);

Expand Down
24 changes: 11 additions & 13 deletions Source/Core/AudioCommon/Mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ unsigned int Mixer::MixerFifo::Mix(s16* samples, unsigned int num_samples,

// Amount of time that has passed since the last frame. This is also used to calculate the low
// pass filter gain for smoothing out playback speed.
const float time_delta = num_samples / float(m_mixer->m_sampleRate);
const float lpf_gain = 1.0f - std::exp(-time_delta / (num_samples * SAMPLE_RATE_LPF));
const double time_delta = num_samples / float(m_mixer->m_sampleRate);
const double lpf_gain = 1.0f - std::exp(-time_delta / (num_samples * SAMPLE_RATE_LPF));

// This is the sample rate of the device this is resampling from
float aid_sample_rate = FIXED_SAMPLE_RATE_DIVIDEND / float(m_input_sample_rate_divisor);
double aid_sample_rate = FIXED_SAMPLE_RATE_DIVIDEND / double(m_input_sample_rate_divisor);

// If the frame limit is enabled, adjust the sample rate to sync audio with video.
if (consider_frame_limit)
Expand All @@ -110,17 +110,15 @@ unsigned int Mixer::MixerFifo::Mix(s16* samples, unsigned int num_samples,
(u64(m_input_sample_rate_divisor) * 1000)));

// Calculate the number of samples remaining after this frame
const float requested_samples = time_delta * aid_sample_rate;
const float numLeft = getRemainingSamples();
const double requested_samples = time_delta * aid_sample_rate;
const double numLeft = getRemainingSamples();

// Ideally, numLeft - low_watermark should be the number of samples requested which would make
// the multiplier here 1.0. However if the speed is different, we need to adjust the multiplier
// to match the requested samples.
float multiplier = (numLeft - low_watermark) / requested_samples;
if (0.0f < audio_speed)
multiplier =
std::clamp(multiplier, audio_speed * MIN_PITCH_SHIFT, audio_speed * MAX_PITCH_SHIFT);
aid_sample_rate *= multiplier;
double multiplier = (numLeft - low_watermark) / requested_samples;
multiplier = std::clamp(multiplier, MIN_PITCH_SHIFT, MAX_PITCH_SHIFT);
aid_sample_rate *= audio_speed * multiplier;
}

// This ratio is how many emulator samples are needed to produce one host sample. In the majority
Expand All @@ -129,8 +127,8 @@ unsigned int Mixer::MixerFifo::Mix(s16* samples, unsigned int num_samples,
// where this is > 1.0, i.e. the emulators is running faster than native speed, we will need to
// adjust the sinc window to be wider to avoid aliasing. We also need to define pi because windows
// doesn't define it in the global namespace >:(
const float ratio = float(aid_sample_rate) / float(m_mixer->m_sampleRate);
const float sinc_ratio = 1.0f / std::max(1.0f, ratio);
const double ratio = float(aid_sample_rate) / float(m_mixer->m_sampleRate);
const float sinc_ratio = 1.0f / std::max(1.0f, float(ratio));
const float pi = 3.14159265358979323846f;

unsigned int sample = 0;
Expand All @@ -146,7 +144,7 @@ unsigned int Mixer::MixerFifo::Mix(s16* samples, unsigned int num_samples,
for (int i = 1 - SINC_WINDOW_WIDTH; i <= SINC_WINDOW_WIDTH; ++i)
{
// Distance from the target sample
float x = i - m_frac;
float x = i - float(m_frac);

// Initialize weight with value of Hanning Window. When tested against Kaiser window, this was
// found to do better.
Expand Down
10 changes: 5 additions & 5 deletions Source/Core/AudioCommon/Mixer.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ class Mixer final
static constexpr u32 MAX_SAMPLES = 1024 * 4; // 128 ms
static constexpr u32 INDEX_MASK = MAX_SAMPLES * 2 - 1;
static constexpr int SINC_WINDOW_WIDTH = 48;
static constexpr float MAX_PITCH_SHIFT = 1.01454533f; // 2 ^ (+1/48) - Half Note Up
static constexpr float MIN_PITCH_SHIFT = 0.98566320f; // 2 ^ (-1/48) - Half Note Down
static constexpr float SAMPLE_RATE_LPF = 0.25f; // How much to smooth out the sample rate changes
static constexpr double MAX_PITCH_SHIFT = 1.01454533; // 2 ^ (+1/48) - Half Note Up
static constexpr double MIN_PITCH_SHIFT = 0.98566320; // 2 ^ (-1/48) - Half Note Down
static constexpr double SAMPLE_RATE_LPF = 0.125; // How much to smooth out sample rate

const unsigned int SURROUND_CHANNELS = 6;

Expand Down Expand Up @@ -93,8 +93,8 @@ class Mixer final
std::atomic<s32> m_LVolume{256};
std::atomic<s32> m_RVolume{256};

float m_ratio = 0.0f;
float m_frac = 0.0f;
double m_ratio = 0.0;
double m_frac = 0.0;
};

void RefreshConfig();
Expand Down

0 comments on commit 2767c22

Please sign in to comment.