I mostly use SuperCollider as a sequencer, using patterns to generate MIDI that I then send to various soft synths in my DAW. This works great, and I love it! Today I fired it up and told it to play, but I forgot to boot the server first. Everything worked perfectly, as far as I can tell.
So… what’s going on there? I had assumed the server was responsible for timing events, but apparently not. Does the client manage timing, and the server only handles audio processing and generation? Or… what exactly is the division of labor there? Why does that work at all?
The server doesn’t even ‘understand’ MIDI. It only ‘speaks’ OSC. Your client / programming environment is what deals with MIDI. Eli Fieldsteel explains it in one of his youtube (#9/18) videos, i.i.r.c.
I should add that the same time stamping mechanism is only established with OSC messaging. With MIDI event patterns, the timing is only done by SC language and the MIDI messages are fired immediately – with the consequence of imperfect accuracy. However, in practical applications this might not be relevant – though, I think, it was reported that MIDI timing accuracy is also platform-dependant.
Aha! Thank you. I had read that help file and a few others trying to figure out what was going on here, and didn’t find much that I could immediately apply to this problem. The concept that MIDI is all handled language-side escaped me. I was having a hard time figuring out how the client handled the timing if the server was processing audio; seemed like that was asking for all kinds of trouble. If I understand this correctly, MIDI is a carve-out from the general rule that the server handles timing, and as a result MIDI may suffer from accuracy problems. That makes perfect sense, and it has implications for some of the ideas I’ve been kicking around for MIDI and sample manipulation simultaneously.
I can’t tell if MIDI is inaccurate from a practical standpoint–it sounds great on my system, but I like loose timing, and many of the instruments I’m using don’t have sharp attacks anyway, such that a little slop is undetectable.
Ah, this appears to be a mistaken inference (which is ok – half of learning programming is to guess the principle behind the system, then find that something in the guess was wrong, and refine).
Backing up a little. .play-able patterns generate events. Events, when played, execute functions accessible in the event’s \play key. In the default event prototype, \play uses the \type key to dispatch to one of the event type functions.
All of this is language-side so far. Also, the EventStreamPlayer that runs the pattern is scheduled on a language-side clock, so it handles its own timing. (Note also that there’s no basis for calculating timestamps to send, if the player’s doesn’t do its own timing in the language.)
At this point, the event type function may send messages (with or without timestamps) to the server, or it might not.
It happens that the usual event types we use do send server messages, and most of them do bundle those messages with a timestamp – leading to an inference that patterns depend on the server in some fundamental way. But that isn’t the case. (It’s easy, for instance, to write a pattern that updates a GUI slider or UserView. There would be no need to send messages in that case.)
One big advantage is that MIDI messages are sent as OSC messages and can be scheduled like any other Server message, so the timing can be (almost) sample accurate! At the very least it is guaranteed that two or more MIDI notes scheduled for the same logical time will be really played simultaneously on the Server.