Skip to content

Instantly share code, notes, and snippets.

@catfact
Created March 2, 2020 02:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save catfact/66d23dd48c0b1a3cace3c671c9755a42 to your computer and use it in GitHub Desktop.
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