-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to get more time resolution #13
Comments
Hi @jllodra, Great to hear that you are tinkering with adding new features, do make a pull request if you end up with something awesome. Looking into the rtmidi code, this is what I found with regards to how the // Calculate time stamp.
if ( data->firstMessage == true ) {
apiData->message.timeStamp = 0.0;
data->firstMessage = false;
}
else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; But it depends on the specific platform, as The So I don't know if it might be some inaccuracy in the Another route to go, could be that we calculate our own timestamp internally in The callbcak function is invoked shortly after the code which determines the timestamp, meaning our .net handled callback function ought to be invoked shortly after, so we might be able to produce a precise enough timestamp just when we receive it. Could do a quick experiment using a |
Here's the specific data structure as defined for Windows MM: https://docs.microsoft.com/da-dk/windows/desktop/Multimedia/mim-data
|
But I guess if the time resolution available is only down to the millisecond, then we cannot rely on that for high enough precision for this kind of time-keeping? With 120BPM we would receive a clock every 20833 microsecond, or 20.833 millisecond, so rounding that to nearest millisecond would become 20 or 21 milliseconds, depending on rounding strategy, and thus a quite significant loss of precision, no? Seems we need to keep track of time ourselves using something with higher than millisecond precision. |
I guess something along these lines in private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
private long _lastTicks = 0;
...
private void RtMidiInputDevice_Message(object sender, byte[] message)
{
// Calculate timestamp
var ticks = _stopwatch.ElapsedTicks;
var timestamp = ((double) (ticks - _lastTicks)) / Stopwatch.Frequency;
_lastTicks = ticks;
...
} |
Hi @micdah, Thank you for your follow-up. Indeed, using a Stopwatch (QueryPerformanceCounter) should work and we should be able to get steady times, I haven't tested it myself yet but I will. To give you some background about the topic, I am working on a Unity application that needs to read MIDI events (note & CC messages that RtMidi.Core provide plus MIDI Clock). Unity uses mono as scripting backend, I liked how RtMidi.Core is written so I decided to try it, and I got to integrate RtMidi.Core into my Unity project in an afternoon. The only issue I had to deal with was that RtMidi.Core seems to be written in C#7, and the mono runtime in Unity supports up to C#6 (and they don't have plans to upgrade to 7, they are moving to Roslyn but not at the moment). So, I had to "downgrade" it to C#6. I did it but I am unaware of the consequences or performance penalties. |
I also have the need for MIDI Clock, and did a test using Stopwatch. The result jitters about the same, if not more than the MIDI timestamp itself. Here's an excerpt of a 120bpm MIDI clock via
However, I have good news. By utilizing a ring buffer, I was able to smoothen out things. 24 clocks (= one beat)
96 clocks (= one bar)
384 clocks (= 4 bars)
In my (brief) tests, I've found 96 clocks to be the best compromise between accuracy and (potential) tempo change delays. I'll put up a PR very soon, including a (potential) deal breaker since I've added timestamp support for each callback. |
Oh another info: I just tried to sync Guess what - they are also interpolating. Even worse - the BPM cycles between 119 and 121 BPM over a period of a few seconds. No wonder they implemented Ableton Link ;) |
@Drachenkaetzchen You still have this issue and related PR, I guess you have stopped developing on the PR. Can I close this issue and related PR? |
I closed the PR but I cannot close this issue. |
Hi,
First of all, thanks for writing and sharing this software.
Today I forked it and tried to add MIDI Clock support (which I need to calculate BPM).
But what I found was a lack of precision for the timestamp (in
private void HandleRtMidiCallback(double timestamp, IntPtr messagePtr, UIntPtr messageSize, IntPtr userData)
.With values like 0,021 and 0,02 I can't get the original 120 bpm value, what I get is 119 and 121.
Do you know if that is the max resolution rtmidi can provide?
Thank you for reading this!
The text was updated successfully, but these errors were encountered: