mirror of
https://github.com/azahar-emu/azahar
synced 2025-11-07 07:29:58 +01:00
Improved realtime audio implementation
This commit is contained in:
parent
5b87ee3397
commit
1ff0dd780f
@ -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);
|
||||||
|
|||||||
@ -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() {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user