Created
March 2, 2020 02:18
-
-
Save catfact/66d23dd48c0b1a3cace3c671c9755a42 to your computer and use it in GitHub Desktop.
supercollider synth to midi / control bus demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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)?