From 8b0ae502ffecc2d769a55f71c1b1b4a32dc46977 Mon Sep 17 00:00:00 2001 From: reuk Date: Mon, 3 Nov 2025 13:11:16 +0000 Subject: [PATCH] CoreMidi: Fix timestamps for incoming MIDI messages Previously, the elapsed time in nanoseconds was multiplied by 1e6 instead of 1e-6, leading to incorrect timestamps on incoming messages. This change also DRYs the code handling time conversions between the native/host time and JUCE timestamps (milliseconds in double format). --- .../native/juce_CoreMidi_mac.mm | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/modules/juce_audio_devices/native/juce_CoreMidi_mac.mm b/modules/juce_audio_devices/native/juce_CoreMidi_mac.mm index 7b4f8890d8..d64eb14fa6 100644 --- a/modules/juce_audio_devices/native/juce_CoreMidi_mac.mm +++ b/modules/juce_audio_devices/native/juce_CoreMidi_mac.mm @@ -1232,6 +1232,23 @@ struct CoreMidiHelpers Endpoints endpoints; }; + struct TimeConverter + { + CoreAudioTimeConversions timeConversions; + #if JUCE_IOS + const MIDITimeStamp startTimeNative = mach_absolute_time(); + #else + const MIDITimeStamp startTimeNative = AudioGetCurrentHostTime(); + #endif + uint32_t startTimeMillis = Time::getMillisecondCounter(); + + double convertToMillis (uint64_t packetTimeNative) const + { + const auto elapsedTime = packetTimeNative - startTimeNative; + return startTimeMillis + (1e-6 * (double) timeConversions.hostTimeToNanos (elapsedTime)); + } + }; + //============================================================================== template struct Receiver; @@ -1254,8 +1271,7 @@ struct CoreMidiHelpers for (uint32_t i = 0; i < list->numPackets; ++i) { - const auto elapsedTime = packet->timeStamp - startTimeNative; - const auto juceTimeMillis = startTimeMillis + (1e6 * (double) timeConversions.hostTimeToNanos (elapsedTime)); + const auto juceTimeMillis = converter.convertToMillis (packet->timeStamp); static_assert (sizeof (uint32_t) == sizeof (UInt32) && alignof (uint32_t) == alignof (UInt32), @@ -1271,14 +1287,7 @@ struct CoreMidiHelpers private: ump::Consumer& callback; - - #if JUCE_IOS - const MIDITimeStamp startTimeNative = mach_absolute_time(); - #else - const MIDITimeStamp startTimeNative = AudioGetCurrentHostTime(); - #endif - const uint32_t startTimeMillis = Time::getMillisecondCounter(); - CoreAudioTimeConversions timeConversions; + TimeConverter converter; }; template <> @@ -1347,9 +1356,7 @@ struct CoreMidiHelpers for (unsigned int i = 0; i < list->numPackets; ++i) { - const auto elapsedTime = packet->timeStamp - startTimeNative; - const auto juceTimeMillis = startTimeMillis + (1e6 * (double) timeConversions.hostTimeToNanos (elapsedTime)); - + const auto juceTimeMillis = converter.convertToMillis (packet->timeStamp); const auto* bytes = unalignedPointerCast (packet->data); const auto len = readUnalignedlength)> (&(packet->length)); @@ -1367,14 +1374,7 @@ struct CoreMidiHelpers private: ump::BytestreamToUMPDispatcher dispatcher; ump::Consumer& callback; - - #if JUCE_IOS - const MIDITimeStamp startTimeNative = mach_absolute_time(); - #else - const MIDITimeStamp startTimeNative = AudioGetCurrentHostTime(); - #endif - const uint32_t startTimeMillis = Time::getMillisecondCounter(); - CoreAudioTimeConversions timeConversions; + TimeConverter converter; }; template <>