Last active
September 7, 2022 03:43
-
-
Save andybp85/20a73975aef10379bcf2a3451169d58b to your computer and use it in GitHub Desktop.
Supercollider: basic midi control for a simple two sawtooth oscillator synth with midi bend working and midi cc's 32 and 33 to tune the oscs
This file contains 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
( | |
// set up midi | |
MIDIClient.init; | |
MIDIIn.disconnectAll; | |
MIDIIn.connectAll; | |
) | |
( | |
// arrays to store pressed keys and cc messages | |
~keys = Array.newClear(128); | |
~ccs = Array.fill(128, { 0 }); | |
// watch for changes | |
MIDIdef.cc(\assignCCs, { arg val, num, chan, src; | |
~ccs.put(num, val); | |
}); | |
) | |
( | |
// vars for channels. not using mod wheel yet but want to remember it | |
~modwheel = 1; | |
~freq1cc = 32; | |
~freq2cc = 33; | |
) | |
( | |
// the synth, parameterized so we can control it | |
SynthDef(\moscs, { arg freq1 = 440, freq2 = 440, freq1tune = 0, freq2tune = 0, amp, gate = 1; | |
var osc1, osc2, out; | |
osc1 = Saw.ar(freq1 + freq1tune, amp); | |
osc2 = Saw.ar(freq2 + freq2tune, amp); | |
out = EnvGen.kr(Env.asr, gate, doneAction: 2) * (osc1 + osc2); | |
Out.ar(0, Pan2.ar(out)); | |
}).add; | |
) | |
( | |
// tuning controller | |
MIDIdef.cc(\tunemoscs, { arg val, num, chan, src; | |
// loop over the whole array and set the values for any synths we find | |
// TODO: make this musical (cents or whatever) - for now I'm just varying the feq by the midi value | |
~keys.do({ arg k; | |
if (k.notNil, { | |
switch(num, | |
~freq1cc, { k.set(\freq1tune, val) }, | |
~freq2cc, { k.set(\freq2tune, val) } | |
); | |
}); | |
}); | |
}); | |
) | |
( | |
MIDIdef.bend(\bendmoscs, { arg val, num, chan, src; | |
// hard coding a whole step for now. | |
var halfsteps = 2; | |
var diff = round((val - 8192) / (8192 / halfsteps), 0.01); | |
// same as in tuning | |
~keys.do({ arg k, i; | |
if (k.notNil, { | |
k.set(\freq1, i.midicps * pow(pow(2,12.reciprocal), diff)); | |
k.set(\freq2, i.midicps * pow(pow(2,12.reciprocal), diff)); | |
}) | |
}); | |
}); | |
) | |
( | |
// based on https://carlcolglazier.com/notes/acoustics/midi-instrument-control-supercollider/ | |
MIDIdef.noteOn(\on, {arg val, num, chan, src; | |
var node = ~keys.at(num); | |
if (node.notNil, { | |
node.release; | |
~keys.put(num, nil); | |
}); | |
node = Synth(\moscs, [ | |
\freq1, num.midicps, | |
\freq1tune, ~ccs.at(~freq1cc).value, | |
\freq2, num.midicps, | |
\freq2tune, ~ccs.at(~freq2cc).value, | |
\amp, val * 0.00315]); | |
~keys.put(num, node); | |
}); | |
MIDIdef.noteOff(\off, {arg val, num, chan, src; | |
var node = ~keys.at(num); | |
if (node.notNil, { | |
node.release; | |
~keys.put(num, nil); | |
}); | |
}); | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment