From 64fd118e1c5944befcf067a0e99d6d138c7559cb Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Mon, 14 Dec 2020 14:07:49 +0800 Subject: Before we have tick-based playback, we get this monstrosity. This should help fixing issues such as "welp my player freezes when I switch tracks" etc. Don't worry. Event-based playback is here to stay. TODOs: - Maybe switch to an implementation based on condition variables? Current implementation is just a mess and unnecessarily wastes CPU time. Also that will allow several new interfaces to be added (such as player.interrupt) - Fix seeking. Seeking is still weird if there's a long gap between events. --- core/qmpmidiplay.cpp | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/qmpmidiplay.cpp b/core/qmpmidiplay.cpp index c987e01..99db420 100644 --- a/core/qmpmidiplay.cpp +++ b/core/qmpmidiplay.cpp @@ -236,17 +236,43 @@ void CMidiPlayer::playEvents() break; high_resolution_clock::time_point a = high_resolution_clock::now(); auto sendtime = a - b; - if (sendtime.count() < (getEvent(tceptr)->time - ct)*dpt) + if (sendtime.count() < (getEvent(tceptr)->time - ct) * dpt) { double ns_sleep = (getEvent(tceptr)->time - ct) * dpt - sendtime.count(); double correction = (getTick() - ttick) * dpt - (b - ttime).count(); if (correction > 0) correction = 0; + if (ns_sleep + correction > 2e8) + { + high_resolution_clock::time_point t = high_resolution_clock::now(); + uint64_t tts = uint64_t(ns_sleep + correction); + while (tts > 2e8 && !tcstop && midiReaders) + { +#ifdef _WIN32 + w32usleep(2e5); +#else + std::this_thread::sleep_for(std::chrono::nanoseconds(uint64_t(2e8))); +#endif + tts -= uint64_t((high_resolution_clock::now() - t).count()); + t = high_resolution_clock::now(); + } + if (tts > 0 && !tcstop && midiReaders) + { #ifdef _WIN32 - w32usleep((uint64_t)(((getEvent(tceptr)->time - ct)*dpt - sendtime.count()) / 1000)); + w32usleep(tts / 1000); #else - std::this_thread::sleep_for(std::chrono::nanoseconds((uint64_t)(ns_sleep + correction))); + std::this_thread::sleep_for(std::chrono::nanoseconds(tts)); #endif + } + } + else + { +#ifdef _WIN32 + w32usleep(uint64_t((ns_sleep + correction) / 1000))); +#else + std::this_thread::sleep_for(std::chrono::nanoseconds(uint64_t(ns_sleep + correction))); +#endif + } } if (tcstop || !midiReaders) break; -- cgit v1.2.3