MIDI

Here are some short examples to work with MIDI in SuperCollider.

// quick way to connect all available devices to SC
MIDIIn.connectAll;
 
// quick way to see all incoming MIDI messages
MIDIFunc.trace(true);
MIDIFunc.trace(false); // stop it
 
// quick way to inspect all CC inputs
MIDIdef.cc(\someCC, {arg a, b; [a, b].postln});
 
// Get input only from cc 7, channel 0
MIDIdef.cc(\someSpecificControl, {arg a, b; [a, b].postln}, ccNum: 7, chan: 0);
 
 
// a SynthDef for quick tests
SynthDef(\quick, {arg freq, amp; Out.ar(0, SinOsc.ar(freq) * Env.perc(level: amp).kr(2))}).add;
// play from a keyboard or drum pad
(
MIDIdef.noteOn(\someKeyboard, {arg vel, note;
  Synth(\quick, [\freq, note + 70, \amp, vel.linlin(0, 127, 0, 1)]);
});
)
 
 
// create a pattern and play that from the keyboard
(
a = Pbind(
  \instrument, \quick,
  \degree, Pwhite(0, 10, 5),
  \amp, Pwhite(0.05, 0.2),
  \dur, 0.1
);
)
// test
a.play;
// trigger pattern from pad or keyboard
MIDIdef.noteOn(\quneo, {arg vel, note; a.play});

Handling note on/off messages for sustained envelopes

You can assign a Synth Voice to an Slot in an Array, since a array can hold any object you wish, it can also hold a Synth. Per default you set the gate value of you SynthDef to 1. When you receive a MIDI note on message, you create a instance of a Synth and assign it to the array, at the slot corresponding to the MIDI Note value. When you receive a Note Off message, you check the note value and set the gate of this Array slot to 0.

// a SynthDef with ADSR envelope
(
SynthDef(\quick2, {arg freq = 440, amp = 0.1, gate = 1;
  var snd, env;
  env = Env.adsr(0.01, 0.1, 0.3, 2, amp).kr(2, gate);
  snd = Saw.ar([freq, freq * 1.5], env);
  Out.ar(0, snd)
}).add;
)
// play it with a MIDI keyboard
(
var noteArray = Array.newClear(128); // array has one slot per possible MIDI note
 
MIDIdef.noteOn(\myKeyDown, {arg vel, note;
  noteArray[note] = Synth(\quick2, [\freq, note.midicps, \amp, vel.linlin(0, 127, 0, 1)]);
  ["NOTE ON", note].postln;
});
 
MIDIdef.noteOff(\myKeyUp, {arg vel, note;
  noteArray[note].set(\gate, 0);
  ["NOTE OFF", note].postln;
});
)