From 306e454f0c1cd47ee3c0ea8b28241ad50eb30c3d Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Tue, 17 Dec 2019 18:18:13 -0500 Subject: [PATCH] Use higher resolution clock for system::getNanoseconds() on Windows. Ban `long` from codebase. Use int64_t instead. --- include/engine/Engine.hpp | 6 +++--- include/midi.hpp | 2 +- include/system.hpp | 6 +++--- src/core/MIDI_CC.cpp | 4 ++-- src/core/MIDI_CV.cpp | 4 ++-- src/core/MIDI_Gate.cpp | 4 ++-- src/core/MIDI_Map.cpp | 4 ++-- src/engine/Engine.cpp | 18 +++++++++--------- src/logger.cpp | 4 ++-- src/system.cpp | 15 +++++++++++++-- 10 files changed, 39 insertions(+), 28 deletions(-) diff --git a/include/engine/Engine.hpp b/include/engine/Engine.hpp index 5a7d5c1d..36a44dc2 100644 --- a/include/engine/Engine.hpp +++ b/include/engine/Engine.hpp @@ -37,11 +37,11 @@ struct Engine { void yieldWorkers(); /** Returns the number of audio samples since the Engine's first sample. */ - long getFrame(); + int64_t getFrame(); /** Returns the frame when step() was last called. */ - long getStepFrame(); + int64_t getStepFrame(); /** Returns the timestamp in nanoseconds when step() was last called. */ - long getStepTime(); + int64_t getStepTime(); /** Returns the total number of frames in the current step() call. */ int getStepFrames(); diff --git a/include/midi.hpp b/include/midi.hpp index 6b8e6f1c..14d2337b 100644 --- a/include/midi.hpp +++ b/include/midi.hpp @@ -18,7 +18,7 @@ struct Message { /** Initialized to 3 empty bytes. */ std::vector bytes; /** Timestamp of MIDI message in nanoseconds. Negative if not set. */ - long timestamp = -1; + int64_t timestamp = -1; Message() : bytes(3) {} diff --git a/include/system.hpp b/include/system.hpp index 54cc05a7..36fe7b08 100644 --- a/include/system.hpp +++ b/include/system.hpp @@ -36,10 +36,10 @@ int getLogicalCoreCount(); void setThreadName(const std::string& name); /** Returns the caller's human-readable stack trace with "\n"-separated lines. */ std::string getStackTrace(); -/** Returns the current number of nanoseconds since the epoch. -Currently uses std::chrono::high_resolution_clock. +/** Returns the current number of nanoseconds since the epoch with the highest precion available on the OS. +The epoch is undefined and could be the UNIX epoch, time since boot, time since launch, etc. */ -long getNanoseconds(); +int64_t getNanoseconds(); /** Opens a URL, also happens to work with PDFs and folders. Shell injection is possible, so make sure the URL is trusted or hard coded. May block, so open in a new thread. diff --git a/src/core/MIDI_CC.cpp b/src/core/MIDI_CC.cpp index 3de25fe0..184e0ba6 100644 --- a/src/core/MIDI_CC.cpp +++ b/src/core/MIDI_CC.cpp @@ -51,8 +51,8 @@ struct MIDI_CC : Module { // Process MIDI messages only if they arrived `stepFrames` frames ago. while (!midiInput.queue.empty()) { midi::Message& msg = midiInput.queue.front(); - long msgTime = msg.timestamp + long(APP->engine->getStepFrames() * APP->engine->getSampleTime() * 1e9); - long frameTime = APP->engine->getStepTime() + long((APP->engine->getFrame() - APP->engine->getStepFrame()) * APP->engine->getSampleTime() * 1e9); + int64_t msgTime = msg.timestamp + int64_t(APP->engine->getStepFrames() * APP->engine->getSampleTime() * 1e9); + int64_t frameTime = APP->engine->getStepTime() + int64_t((APP->engine->getFrame() - APP->engine->getStepFrame()) * APP->engine->getSampleTime() * 1e9); if (msgTime > frameTime) break; processMessage(msg); diff --git a/src/core/MIDI_CV.cpp b/src/core/MIDI_CV.cpp index 80f9f4ea..23da619b 100644 --- a/src/core/MIDI_CV.cpp +++ b/src/core/MIDI_CV.cpp @@ -122,8 +122,8 @@ struct MIDI_CV : Module { // Process MIDI messages only if they arrived `stepFrames` frames ago. while (!midiInput.queue.empty()) { midi::Message& msg = midiInput.queue.front(); - long msgTime = msg.timestamp + long(APP->engine->getStepFrames() * APP->engine->getSampleTime() * 1e9); - long frameTime = APP->engine->getStepTime() + long((APP->engine->getFrame() - APP->engine->getStepFrame()) * APP->engine->getSampleTime() * 1e9); + int64_t msgTime = msg.timestamp + int64_t(APP->engine->getStepFrames() * APP->engine->getSampleTime() * 1e9); + int64_t frameTime = APP->engine->getStepTime() + int64_t((APP->engine->getFrame() - APP->engine->getStepFrame()) * APP->engine->getSampleTime() * 1e9); if (msgTime > frameTime) break; processMessage(msg); diff --git a/src/core/MIDI_Gate.cpp b/src/core/MIDI_Gate.cpp index 17ee8d48..799f2c29 100644 --- a/src/core/MIDI_Gate.cpp +++ b/src/core/MIDI_Gate.cpp @@ -58,8 +58,8 @@ struct MIDI_Gate : Module { // Process MIDI messages only if they arrived `stepFrames` frames ago. while (!midiInput.queue.empty()) { midi::Message& msg = midiInput.queue.front(); - long msgTime = msg.timestamp + long(APP->engine->getStepFrames() * APP->engine->getSampleTime() * 1e9); - long frameTime = APP->engine->getStepTime() + long((APP->engine->getFrame() - APP->engine->getStepFrame()) * APP->engine->getSampleTime() * 1e9); + int64_t msgTime = msg.timestamp + int64_t(APP->engine->getStepFrames() * APP->engine->getSampleTime() * 1e9); + int64_t frameTime = APP->engine->getStepTime() + int64_t((APP->engine->getFrame() - APP->engine->getStepFrame()) * APP->engine->getSampleTime() * 1e9); if (msgTime > frameTime) break; processMessage(msg); diff --git a/src/core/MIDI_Map.cpp b/src/core/MIDI_Map.cpp index 500395e4..de4175df 100644 --- a/src/core/MIDI_Map.cpp +++ b/src/core/MIDI_Map.cpp @@ -81,8 +81,8 @@ struct MIDI_Map : Module { // Process MIDI messages only if they arrived `stepFrames` frames ago. while (!midiInput.queue.empty()) { midi::Message& msg = midiInput.queue.front(); - long msgTime = msg.timestamp + long(APP->engine->getStepFrames() * APP->engine->getSampleTime() * 1e9); - long frameTime = APP->engine->getStepTime() + long((APP->engine->getFrame() - APP->engine->getStepFrame()) * APP->engine->getSampleTime() * 1e9); + int64_t msgTime = msg.timestamp + int64_t(APP->engine->getStepFrames() * APP->engine->getSampleTime() * 1e9); + int64_t frameTime = APP->engine->getStepTime() + int64_t((APP->engine->getFrame() - APP->engine->getStepFrame()) * APP->engine->getSampleTime() * 1e9); if (msgTime > frameTime) break; processMessage(msg); diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index 896a7204..559d1200 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -151,9 +151,9 @@ struct Engine::Internal { float sampleRate = 0.f; float sampleTime = 0.f; - long frame = 0; - long stepFrame = 0; - long stepTime = 0; + int64_t frame = 0; + int64_t stepFrame = 0; + int64_t stepTime = 0; int stepFrames = 0; Module* primaryModule = NULL; @@ -224,7 +224,7 @@ static void Engine_stepModulesWorker(Engine* that, int threadId) { Module* module = internal->modules[i]; // Start CPU timer - long startTime; + int64_t startTime; if (cpuMeter) { startTime = system::getNanoseconds(); } @@ -237,8 +237,8 @@ static void Engine_stepModulesWorker(Engine* that, int threadId) { // Stop CPU timer if (cpuMeter) { - long endTime = system::getNanoseconds(); - float duration = (endTime - startTime) / 1e9; + int64_t endTime = system::getNanoseconds(); + float duration = (endTime - startTime) * 1e-9f; // Smooth CPU time const float cpuTau = 2.f /* seconds */; @@ -521,19 +521,19 @@ void Engine::yieldWorkers() { } -long Engine::getFrame() { +int64_t Engine::getFrame() { // No lock, for performance return internal->frame; } -long Engine::getStepFrame() { +int64_t Engine::getStepFrame() { // No lock, for performance return internal->stepFrame; } -long Engine::getStepTime() { +int64_t Engine::getStepTime() { // No lock, for performance return internal->stepTime; } diff --git a/src/logger.cpp b/src/logger.cpp index 2f5ca0f9..3ed88790 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -10,7 +10,7 @@ namespace logger { static FILE* outputFile = NULL; -static long startTime = 0; +static int64_t startTime = 0; static std::mutex logMutex; @@ -50,7 +50,7 @@ static const int levelColors[] = { static void logVa(Level level, const char* filename, int line, const char* format, va_list args) { std::lock_guard lock(logMutex); - long nowTime = system::getNanoseconds(); + int64_t nowTime = system::getNanoseconds(); double duration = (nowTime - startTime) / 1e9; if (outputFile == stderr) fprintf(outputFile, "\x1B[%dm", levelColors[level]); diff --git a/src/system.cpp b/src/system.cpp index f09e3868..b6aec55c 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -215,13 +215,24 @@ std::string getStackTrace() { } -long getNanoseconds() { +int64_t getNanoseconds() { +#if defined ARCH_WIN + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + // TODO Check if this is always an integer factor on all CPUs + int64_t nsPerTick = 1000000000LL / frequency.QuadPart; + int64_t time = counter.QuadPart * nsPerTick; + return time; +#else using clock = std::chrono::high_resolution_clock; using time_point = std::chrono::time_point; time_point now = clock::now(); - using duration = std::chrono::duration; + using duration = std::chrono::duration; duration d = now.time_since_epoch(); return d.count(); +#endif }