mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2025-01-12 09:49:08 +01:00
Improve playback consistency for realtime audio during inconsistent framerates
Implements and uses `GetStableFrameTimeScale` instead of `GetLastFrameTimeScale` for realtime audio playback
This commit is contained in:
parent
d91334be84
commit
8551c18777
@ -419,7 +419,7 @@ 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().GetLastFrameTimeScale(), 1.0, 3.0)
|
? std::clamp(Core::System::GetInstance().GetStableFrameTimeScale(), 1.0, 3.0)
|
||||||
: 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);
|
||||||
|
@ -392,8 +392,8 @@ PerfStats::Results System::GetLastPerfStats() {
|
|||||||
return perf_stats ? perf_stats->GetLastStats() : PerfStats::Results{};
|
return perf_stats ? perf_stats->GetLastStats() : PerfStats::Results{};
|
||||||
}
|
}
|
||||||
|
|
||||||
double System::GetLastFrameTimeScale() {
|
double System::GetStableFrameTimeScale() {
|
||||||
return perf_stats->GetLastFrameTimeScale();
|
return perf_stats->GetStableFrameTimeScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::Reschedule() {
|
void System::Reschedule() {
|
||||||
|
@ -193,7 +193,7 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] PerfStats::Results GetLastPerfStats();
|
[[nodiscard]] PerfStats::Results GetLastPerfStats();
|
||||||
|
|
||||||
double GetLastFrameTimeScale();
|
double GetStableFrameTimeScale();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a reference to the emulated CPU.
|
* Gets a reference to the emulated CPU.
|
||||||
|
@ -129,6 +129,17 @@ double PerfStats::GetLastFrameTimeScale() const {
|
|||||||
return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH;
|
return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double PerfStats::GetStableFrameTimeScale() const {
|
||||||
|
std::scoped_lock lock{object_mutex};
|
||||||
|
|
||||||
|
constexpr double FRAME_LENGTH_MILLIS = (1.0 / SCREEN_REFRESH_RATE) * 1000;
|
||||||
|
const short num_frames = std::min(50ul, current_index + 1);
|
||||||
|
const double sum = std::accumulate(perf_history.begin() + current_index - num_frames,
|
||||||
|
perf_history.begin() + current_index, 0.0);
|
||||||
|
const double stable_frame_length = sum / num_frames;
|
||||||
|
return stable_frame_length / FRAME_LENGTH_MILLIS;
|
||||||
|
}
|
||||||
|
|
||||||
void FrameLimiter::WaitOnce() {
|
void FrameLimiter::WaitOnce() {
|
||||||
if (frame_advancing_enabled) {
|
if (frame_advancing_enabled) {
|
||||||
// Frame advancing is enabled: wait on event instead of doing framelimiting
|
// Frame advancing is enabled: wait on event instead of doing framelimiting
|
||||||
|
@ -82,6 +82,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
double GetLastFrameTimeScale() const;
|
double GetLastFrameTimeScale() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
double GetStableFrameTimeScale() const;
|
||||||
|
|
||||||
void AddArticBaseTraffic(u32 bytes) {
|
void AddArticBaseTraffic(u32 bytes) {
|
||||||
artic_transmitted += bytes;
|
artic_transmitted += bytes;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user