> 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