Skip to content

Instantly share code, notes, and snippets.

@catfact
Created March 2, 2020 02:18
Show Gist options
  • Select an option

  • Save catfact/66d23dd48c0b1a3cace3c671c9755a42 to your computer and use it in GitHub Desktop.

Select an option

Save catfact/66d23dd48c0b1a3cace3c671c9755a42 to your computer and use it in GitHub Desktop.
supercollider synth to midi / control bus demo
MIDIClient.init; // initialize MIDI
m = MIDIOut(0); // get the first output device
Routine { // use a Routine (aka a thread) for synchronization with the server
s = Server.default;
s.boot;
s.sync; // wait for the server to be ready
// a control-rate bus which our synth will write to
~lfo_out_bus = Bus.control(s, 1);
// make a new synthdef (a control-rate sine)...
~lfo = SynthDef.new(\lfo, {
arg hz=1, out, mul=1, add=0;
Out.kr(out, SinOsc.kr(hz, mul:mul, add:add));
}).play(target:s, ///... and play it on the server...
args: [ //... with some arguments...
\out, ~lfo_out_bus.index // ... including the target bus
]
);
// now there are different things we could do to read the bus.
// here, we'll just explicitly read values from it in an endless loop.
inf.do {
~lfo_out_bus.get(
// getting a bus value is asnychronous, so the method takes a callback...
{
arg val; // ...whose argument is the bus value.
var scaled; // the value is in [-1, 1], so we want to rescale it
scaled = (val+1)/2 * 127;
postln(scaled);
m.control(1, 10, scaled); // send it out on CC 10, channel 1 (or 2 if your client is 1-based!)
}
);
0.1.wait; // initiate a read every 100 milliseconds
// (we could go faster but this is so we don't choke on the print statements)
}
}.play; // make everything go
/// if we want to, say, modulate the LFO speed with another lfo,
/// another control bus is the way to do it
// this is a bit hacky, but we'll just make another routine here...
Routine {
8.wait; // ... and use it to wait for some arbitrary time for the earlier stuff to happen
~lfo_hz_bus = Bus.control(s, 1); // make another bus
~lfo.map(\hz, ~lfo_hz_bus); // map it to the synth
~lfo_mod = Synth.new(\lfo, // we already sent this def to the server
args: [
\hz, 0.2, // slower
\add:1.1, // scaled up to [0.1, 2.1]
\out, ~lfo_hz_bus.index // and sending to the modulation bus
],
target: ~lfo, addAction:\addBefore // make sure the modulator executes before its destination
);
}.play; // make it go
@anwaldt
Copy link

anwaldt commented Jun 19, 2021

I am also using this solution but the outgoing MIDI control values have discontinuities and produce clicks. So there needs to be an interpolation - but how would that work (since it is not on the server)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment