-
Notifications
You must be signed in to change notification settings - Fork 78
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
Send with timestamp #45
Comments
Windows only supports sending msgs "right now", not "at some point So this feature would have to be built on top of |
Yes, midir unfortunately doesn't support this, because it's not available for all underlying platform APIs ... |
Thanks for the answers, it seems it won't be a feature :-( |
@Boscop @Boddlnagg I am reopening to explore another possibility. Would you consider |
@chris-zen Yes, this is a possibility that I've also thought about (which is why I hadn't closed this already). Do I understand you correctly that what you need is a variation of |
Exactly that.
I guess that this is because you need to translate/sync timestamps between different clocks/frameworks. For example CoreMIDI requires a match_host_time, which might be different to the one used by Chromium for execution and JS timers.
On that point, I would just look at existing APIs/frameworks and follow their general contract, which would consist on buffering MIDI messages to be sent in the future in a Heap, keep comparing the head of the heap with the current time (according to some reference clock) in a thread, and sending them to the output port whenever they are due. Obviously, in practice, things are more complex than what I describe if you wish to be precise and efficient, but I would keep in mind that this is just a fallback for those cases where the native implementation doesn't support this feature.
And I can fully understand it, it is not a trivial amount of work. It is sad that the common denominator to all those systems has to be so low. I am wondering what kind of applications is It is curious that my main motivation to start the My knowledge on windows is low too (although I remember from some ages ago that there was a high resolution timer in the win32 api), so I am sorry not to be very helpful this time. |
@Boscop by the way, I just took a look to the Windows APIs and saw a set of functions for working with streams of MIDI data, which seemed to support the feature of sending MIDI data in the future. I don't know how difficult would be to use them, but worth taking a look. MIDIEVENT structure See the |
I wasn't aware of the stream functions and I'm not sure if they can be easily unified with the coremidi way, e.g.:
Is it the same in Btw, here is another tutorial. Anyway, even if midir ends up supporting scheduled message sending, I think the current sending functions should be kept, and should still call the direct winapi functions for minimum latency & cpu usage (e.g. my application needs the lowest latency and sends a lot of midi messages, multiple kb/s).
Hm, if you only need to support Mac, you could just use the coremidi crate directly for now.. |
@Boscop every backend will have a different MIDI clock system (with the main characteristics of being monotonic with high resolution), for example, in the case of CoreMIDI it is the |
@Boscop @Boddlnagg I saw that portmidi also supports to specify the timestamp when sending data, and they also support Windows. After taking a look into their implementation, it doesn't seem like it would be that difficult for https://sourceforge.net/p/portmedia/code/HEAD/tree/portmidi/trunk/pm_win/pmwinmm.c#l733 The key seems to be the use of the streaming API. |
Okay ... so the streaming API allows timestamp, or rather, enforces timestamps ... when PortMidi uses the streaming API and wants to send a message immediately (timestamp = 0) it manually computes the correct timestamp. This seems suboptimal, and it's probably also the reason why PortMidi uses both the non-streaming and streaming API, depending on how the user initializes the PortMidi context ( Furthermore, in the WinRT/UWP implementation, which Because of this, I don't think it's a good idea to use the streaming API, because we would still need a manual scheduler implementation for the WinRT API (except when building a scheduler with WinRT APIs itself would be a lot easier than using classic WinAPI, but I don't know that). |
Another option is to have an extension API for this functionality that's simply not available on Windows. This is already the case for our virtual ports support. Would that help anyone here? |
Well, I only use midir on Windows thus far.. |
Well, I don't know since I have never done any driver work (neither in Rust nor another language). But the benefit of such an effort seems questionable to me. A driver can't be made a part of the midir library directly, it always will need to be installed system-wide before any application could use it. At least that has been my understanding so far, and I don't know why it would be any different when the thing is written in Rust. |
@chris-zen Do you know what the advantage is of using the windows midi streaming API vs the normal midi out api? With both, I have to do the timing (there is no external clock that calls my callback that returns all midi msgs to be sent for that timeframe). The only difference seems to be that with streaming, you queue the midi events with a timestamp and then flush the queue[1]. So their relative timing will be more correct but the latency will be higher (because you're not sending them out immediately), right? |
@Boscop I think that the point of those APIs is to avoid callbacks and the user to have to deal with precise timing. The user just queues the events that need to be sent with their respective timestamps in the future, and the API will take care to delivering them accurately on time. That's all. At least that's how CoreMIDI works, and how the portmidi interface is built on top of the Windows Streaming API. Those OS libs have realtime threads that can deal with high precission timing, which a mortal app cannot. That's why it was so important for me that midir implemented that interface, because otherwise it is useless for serious applications like DAWs, MIDI players, and so on. |
@chris-zen Doesn't that queueing add latency though, compared to sending the msgs out instead of queueing them? Maybe this would be more accurate than a loop that sleeps for the remainder of the time each frame?: https://docs.rs/crossbeam-channel/0.4.0/crossbeam_channel/fn.tick.html |
That queuing will be done or not by the low level OS API (CoreMIDI, ALSA, Windows MIDI Stream) depending on the timestamp, so we as users don't need to bother about the details, and just expect that it will be done in the more efficient way. Even if you use a precise timer, your code is not running in a real-time thread, so you will get unexpected delays when waking the thread up. I am surprised that ASIO don't allow two processes to process audio at the same time. But assuming that ASIO has that limitation you still have other audio drivers or devices that you can use for the callbacks. And even if you didn't have any audio device remaining, depending on the OS there are services to have precise callbacks (I used one from Windows plenty of years ago, but I don't remember now), but you might need to reconfigure your scheduling thread for real-time. You might be interested in this. Honestly, if portmidi supports specifying the timestamp when sending MIDI for all major platforms (including Windows), I don't see why midir couldn't do it. And about the scheduling needed by applications to send MIDI events in chunks, you need to look into the native multimedia services (or a library that wraps them, for example cpal), or a OS service with precise callbacks with real-time priority threads. |
It could be implemented for only the platforms that supports it natively and ignoring Windows. By a |
@faern I already suggested this basically in #45 (comment), but I'm not sure if it would really help. I'd still like midir to be as portable as possible, and having virtual ports only on non-Windows is already kind of sad ... |
Sorry. I searched the history for "trait" only, so I missed it. Most of the thread was about how to implement the scheduling so I did not read every message. |
Hi,
I was about to use
midir
, but realised of a missing feature that it is very important, the ability to specify the timestamp in the future when the MIDI data has to be sent (see this). I think this is specially important when working with audio and MIDI in sync and need the maximum precision possible (having to implement the scheduling of MIDI events myself with a thread is not an option, as this would lead to sync problems for sure).I was wondering if you were considering to add this feature at some point (if it is really possible to find a common model for timestamps and synchronisation across platforms).
The text was updated successfully, but these errors were encountered: