Midi input for SC?

Is there a standard way to input midi from a keyboard into a SC session or code editor?

I am thinking about the midi input from Frescobaldi/ Lilypond or Musescore where can play a midi keyboard and the notes appear in the editor or staff respectively .

I am also interested in some facility for midi looping where I play notes and they get assigned to a program change number for later running.

If I have to code what I want that’s ok, but shoulders of giants and all that.

Appreciate any thoughts!

I have some rather old code (over 12 years) that captures MIDI notes into a data structure. It probably doesn’t do everything that you want, but you could get some ideas from it.

This is all in the ddwMIDI quark.

To recheck it, I ran some MIDI notes out of Pure Data. Pd showed up as MIDIClient.sources[3].

ddwMIDI has its own way of addressing MIDI input devices (MIDIPort). When you init MIDIPort, you can pull some devices to the front – MIDIPort.init([3]) means that the third device in MIDIClient.sources becomes device 0 (default device) in MIDIPort.


r = MIDIRecSocket(0, TempoClock.default);

Now r is grabbing note on/off messages, until you stopRecord. This method returns the data.

b = r.stopRecord;
-> a MIDIRecBuf


0 : [ 53, 0.20010301800005, 0.30231231300002, 0.50393700787402 ]
1 : [ 60, 0.19940607499996, 0.302256296, 0.50393700787402 ]
2 : [ 51, 0.20091244800005, 0.30381891100001, 0.50393700787402 ]
3 : [ 61, 0.20090130400001, 0.30378040400001, 0.50393700787402 ]

Then, a quick and dirty template to play back:

p = Pbind(
	\noteObj, b.asPattern,  // "a Pseq"
	[\midinote, \dur, \sustain, \amp], Pfunc { |ev|
		var note = ev[\noteObj];
		// freq is really note number
		// "gate" = velocity scaled to 0.0 - 1.0
		[note.freq, note.dur, note.length, note.gate]

There are some other features in there, related to quantizing, and I also had a neat idea at that time about parsing chords and grace notes. But I ended up not going in that direction for my compositional work, so at this point, it’s abandon-ware.

Since it captures notes with timing, though, it may be useful for looping. (The problem I never solved with looping is that language-side processing is earlier than what you hear by s.latency seconds – so you’ll hit the MIDI button to stop recording and start looping based on the time you hear, but the bar line in the language has already passed. Loop playback, then, would have to skip over the first fraction of a beat and resync on the next note. It’s certainly a solvable problem; I just never finished it.)

(PS One error in the code: it’s using clock.elapsedBeats to measure time when it really should be clock.beats.)

I don’t recall that anyone has done this, no.


If you just want to react to midi messages, the standard way would be to use the MIDIdef class that allows you to set up handlers for noteOn, noteOff, cc, pitchbend, sysex, program change, etc
There’s currently nothing in the supercollider eco system - to the best of my knowledge - that tries to analyze recorded midi information into notation-like data structures (e.g. to analyze the timings into standard rhythms).

For a midi looper, last summer I made a proof of concept - no doubt it will not be perfect, but you could try it and see if it goes in the direction you want: GitHub - shimpe/sc-midi-recorder: experiment with midi recording. If I remember well, it records and plays back notes and control changes, program changes, pitch bend/touch, etc and it also has provisions for recording to multiple tracks which then can be selectively muted/unmuted during playback, it can do some quantization on the recording and it comes with a small user interface.

If you are interested in reacting to midi with faders, buttons or other ui elements in supercollider last year I also made a small library to do just that: GitHub - shimpe/sc-midi-controls: bidirectional learning midi controls for supercollider This library supports reacting to cc, nrpn, rpn, sysex and has a “learning” mode to quickly get started with whatever midi device you have lying around. Other people have also worked on similar goals (without the learning, if I’m not mistaken) in the “modality” toolkit ( Modality Toolkit [Supported Controllers] ).

Have fun with supercollider!

Thanks everyone for the information. It looks to me that I will have to write my own system, as I want something pretty specific, but looking at this code is super helpful. Probably a delightful way to start learning SuperCollider :wink:

(Basically: use a midi foot pedal like my Roland FC300 to send a cc that says “start recording”, record with the 88 keyboard, a cc to “stop recording”, assign the pattern to a program change control number, then fire off the pattern by sending the program change control number later. I want to do some fanciness using lower notes to “clock” the recording process and enable interesting polyphony.)