Sorry for the delay, this got stuck in my drafts for a while:
So, just to try it out I wound up writing a direct core midi interface. It's
only 270 lines, took a few hours to write, and has been working right off the
bat as a drop-in replacement. It's faster and simpler (no Pm_Read
polling!),so I think I'll stick with it for the moment. Since the
alsa model is not too
different from CoreMIDI, making an alsa port if the time comes should be pretty
easy too.
So the below is just academic at this point, but I'm still curious, so if you'd
care to humor me...
> My concern is not throughput but the worst case latency, e.g. how long does
> it take a thru message to go through the system? The normal case is going to
> be very fast, but it's the occasional case due to the application event loop
> doing other things (or the system doing other things) that causes problems.
...
> So I guess you are saying that your application is not realiably
> low-latency, but you are willing to put up with that in the case of midi
> thru, but not in the case of playing sequencer data.
The entire app is not reliably low latency, but I can put a special thru
handler into a separate thread that is reliable, which is what I have done. I
haven't even needed to set prio or turn off GC or anything, but I could do that
if it became necessary. I could even call it directly from the read callback
and eliminate the queue and context switch overhead (which is what the
apple examples do, implying that MIDISend is re-entrant though no docs
say so).
> I would suggest a different structure: the GUI can write single-word
> parameters atomically (because memory words are atomic) to be read by the
> thread generating MIDI data from the sequencer data structures. In the case
> of more complex updates, data can be sent via messages to the generating
> thread, which can process messages atomically between polling for incoming
> MIDI. There's' no need to constantly flush messages, back up in time, and
> regenerate them as the user moves a slider.
...
> I was arguing for *no buffer*.
I don't have any sliders (well, plenty of hardware sliders, but none
on the screen :), but if I did, they would send "now" msgs, just like
midi thru does, so they wouldn't participate in the midi rendering
process and its buffer (which is of course what the hardware sliders
already do).
I'm feeling dull now, because I still don't understand how to get by without a
buffer. Here's some pseudo code of how I would imagine it:
-- thread generating midi from sequencer data structures
while (now < stop time)
in_msgs = poll read ports
gui_events = get since last iteration until now
midi_msgs = convert_to_midi gui_events
write_all midi_msgs -- write immediately
sleep iteration time
So, aren't you in trouble if convert_to_midi takes > iteration time?
Wouldn't that force you to keep gui_events in a format that's very
quickly convertible
to midi and are stored in a sorted order in the same way? This would place
pretty strict constraints on how you store note data, right?
So if what you're saying is "writing your own scheduler allows you to make
changes to the model and have them be immediately reflected while playing, then
I claim "having a simple correspondence between gui elements and midi msgs
allows you to do that". Even with a buffer, if I can generate midi msgs faster
than they get played and I can start generating at an arbitrary time, I can
always toss the buffer and regenerate them if someone makes a change. Directly
playing off the gui might be easier, but they're theoretically the same. All
this is really doing is shrinking the buffer down to an iteration time's worth
of data, right?
And all this just to be able to change a note when the play head is almost on
top of it? Doesn't seem like a huge win... and when I do a mass change
operation in cubase while it's playing, I get a short dropout anyway.
> If thru processing were deterministic I could run it inline, but it's not so
> it's in a separate thread hanging off the input queue and feeding back into
> the
> output queue (which is what I did above).
>
> Keep in mind that PortMidi does not support access by multiple threads.
True, the actual calls down to C are serialized.
_______________________________________________
media_api mailing list
[email protected]
http://lists.create.ucsb.edu/mailman/listinfo/media_api