aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2020-12-14 14:07:49 +0800
committerGravatar Chris Xiong <chirs241097@gmail.com> 2020-12-14 14:07:49 +0800
commit64fd118e1c5944befcf067a0e99d6d138c7559cb (patch)
tree71ff8b662c266dda6940b54fb45da642143532e0
parentfcd13f9b227d80e066775f75b09bc6ec9337bfc8 (diff)
downloadQMidiPlayer-64fd118e1c5944befcf067a0e99d6d138c7559cb.tar.xz
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.
-rw-r--r--core/qmpmidiplay.cpp32
1 files changed, 29 insertions, 3 deletions
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;