Improved realtime audio implementation

This commit is contained in:
OpenSauce04 2024-11-27 20:48:04 +00:00
parent 5b87ee3397
commit 1ff0dd780f
3 changed files with 14 additions and 10 deletions

View File

@ -419,8 +419,8 @@ void DspHle::Impl::AudioTickCallback(s64 cycles_late) {
// Reschedule recurrent event // Reschedule recurrent event
const double time_scale = const double time_scale =
Settings::values.enable_realtime_audio Settings::values.enable_realtime_audio
? std::clamp(Core::System::GetInstance().GetStableFrameTimeScale(), ? std::max(0.01, // Arbitrary small value to prevent time_scale from approaching zero
100. / Settings::values.frame_limit.GetValue(), 3.0) Core::System::GetInstance().GetStableFrameTimeScale())
: 1.0; : 1.0;
s64 adjusted_ticks = static_cast<s64>(audio_frame_ticks / time_scale - cycles_late); s64 adjusted_ticks = static_cast<s64>(audio_frame_ticks / time_scale - cycles_late);
core_timing.ScheduleEvent(adjusted_ticks, tick_event); core_timing.ScheduleEvent(adjusted_ticks, tick_event);

View File

@ -22,6 +22,7 @@ using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>;
using std::chrono::duration_cast; using std::chrono::duration_cast;
using std::chrono::microseconds; using std::chrono::microseconds;
constexpr double FRAME_LENGTH = 1.0 / SCREEN_REFRESH_RATE;
// Purposefully ignore the first five frames, as there's a significant amount of overhead in // Purposefully ignore the first five frames, as there's a significant amount of overhead in
// booting that we shouldn't account for // booting that we shouldn't account for
constexpr std::size_t IgnoreFrames = 5; constexpr std::size_t IgnoreFrames = 5;
@ -65,6 +66,9 @@ void PerfStats::EndSystemFrame() {
accumulated_frametime += frame_time; accumulated_frametime += frame_time;
system_frames += 1; system_frames += 1;
// TODO: Track previous frame times in a less stupid way. -OS
previous_previous_frame_length = previous_frame_length;
previous_frame_length = frame_end - previous_frame_end; previous_frame_length = frame_end - previous_frame_end;
previous_frame_end = frame_end; previous_frame_end = frame_end;
} }
@ -125,19 +129,17 @@ PerfStats::Results PerfStats::GetLastStats() {
double PerfStats::GetLastFrameTimeScale() const { double PerfStats::GetLastFrameTimeScale() const {
std::scoped_lock lock{object_mutex}; std::scoped_lock lock{object_mutex};
constexpr double FRAME_LENGTH = 1.0 / SCREEN_REFRESH_RATE;
return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH; return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH;
} }
double PerfStats::GetStableFrameTimeScale() const { double PerfStats::GetStableFrameTimeScale() const {
std::scoped_lock lock{object_mutex}; std::scoped_lock lock{object_mutex};
constexpr double FRAME_LENGTH_MILLIS = (1.0 / SCREEN_REFRESH_RATE) * 1000; const double stable_previous_frame_length =
const size_t num_frames = std::min<size_t>(50UL, current_index + 1); (duration_cast<DoubleSecs>(previous_frame_length).count() +
const double sum = std::accumulate(perf_history.begin() + current_index - num_frames, duration_cast<DoubleSecs>(previous_previous_frame_length).count()) /
perf_history.begin() + current_index, 0.0); 2;
const double stable_frame_length = sum / num_frames; return stable_previous_frame_length / FRAME_LENGTH;
return stable_frame_length / FRAME_LENGTH_MILLIS;
} }
void FrameLimiter::WaitOnce() { void FrameLimiter::WaitOnce() {

View File

@ -85,7 +85,7 @@ public:
/** /**
* Has the same functionality as GetLastFrameTimeScale, but uses the mean frame time over the * Has the same functionality as GetLastFrameTimeScale, but uses the mean frame time over the
* last 50 frames rather than only the frame time of the previous frame. * last 2 frames rather than only the frame time of the previous frame.
*/ */
double GetStableFrameTimeScale() const; double GetStableFrameTimeScale() const;
@ -137,6 +137,8 @@ private:
Clock::time_point frame_begin = reset_point; Clock::time_point frame_begin = reset_point;
/// Total visible duration (including frame-limiting, etc.) of the previous system frame /// Total visible duration (including frame-limiting, etc.) of the previous system frame
Clock::duration previous_frame_length = Clock::duration::zero(); Clock::duration previous_frame_length = Clock::duration::zero();
/// Visible duration for the frame prior to previous_frame_length
Clock::duration previous_previous_frame_length = Clock::duration::zero();
/// Last recorded performance statistics. /// Last recorded performance statistics.
Results last_stats; Results last_stats;