> It even says "don't look for a download there"
Well, actually I just added that line in response to your first message, 
so maybe it wasn't so obvious the first time you looked.

Yes, having portmidi add latency to the timestamp may seem convoluted 
compared to having the app just send absolute timestamps for the 
delivery time, but consider that if portmidi sends messages at the 
timestamp (without adding latency), then it becomes the application's 
job to say "I want to play something at time T, but my maximum latency 
is 50ms, so I'll schedule myself at T-50. Then when I wake up and read 
the time, I'll add 50ms to figure out all the stuff I need to send now." 
That seems convoluted (to me).

The alternative is: "I want to play something at time T, so I'll 
schedule myself at T, and when I wake up I'll send whatever needs to be 
sent at time T" The actual output will be delayed to T+50ms, and that 
may actually be a problem, but consider that if you are outputing audio 
as well, and you set the midi latency to equal the audio buffer 
duration, then the audio and midi will be synchronized -- with audio, 
you have no timestamps, so audio is going to behave much like the 
portmidi model, and you really don't have a choice.

I can see the logic in both approaches, but either way you think about 
it, it's a small amount of adding or subtracting.

Note that with MIDI THRU, you are really limited by system latency so 
you really should have a high-priority thread doing both THRU and MIDI 
generation. If you buffer stuff ahead and then MIDI input arrives that 
you want to forward to the output, (with portmidi,) messages go out in 
order (no sorting by timestamps), so the forwarded messages may be 
delayed. It might be possible to open two output streams and use one for 
timestamped MIDI and one for THRU. This would then use the underlying 
OS-level MIDI system to do the merging. Portmidi isn't really intended 
to let you do this though, so I'm not sure if it will work (or on what 
systems).

Pm_Read does not block mainly for historical reasons: early Mac and 
Windows systems did not use real threads for low-latency processing, so 
they could not block or suspend. In most cases, a Midi processing thread 
will do work depending upon: MIDI input, timed events in a queue, and 
user actions. If you suspend waiting for input, you might not run when 
it's time to perform a timed event or respond to a user action, so 
generally you end up polling anyway. There are other approaches, and 
polling is generally frowned upon (I'm even teaching Intro to OS at 
Carnegie Mellon, and this is really heresy in most of the OS world) but 
it's interesting that polling (compared to being waked up by something 
like Unix select() waiting on many devices) is more and more efficient 
as load increases. In real-time systems, it's performance under load 
that really matters.

I agree with most of your comments about SysEx. Another issue is that 
SysEx messages are handled in different ways on different platforms. 
E.g. I think ALSA does actually buffer full sysex messages until they 
are complete to allow for merging. So if PortMidi tried to merge 
realtime data and sysex data, I think that would be undone by ALSA. 
Merging on other systems can really only be done by the lowest-level 
driver because it's not known to the application how many bytes are 
queued up in the driver. I agree that PortMidi passes some thorny 
problems to the application writer. I think it's better that these 
things be worked out there in the app, or in a separate library rather 
than hard-wiring more design decisions into the PortMidi API. In other 
words, I think we really don't know the "right" way to do this, and 
maybe there's not one "right" way.

I'll post a separate message about Nyquist.

-Roger





_______________________________________________
media_api mailing list
media_api@create.ucsb.edu
http://lists.create.ucsb.edu/mailman/listinfo/media_api

Reply via email to