Skip to content

Instantly share code, notes, and snippets.

@andybp85
Last active September 7, 2022 03:43
Show Gist options
  • Save andybp85/20a73975aef10379bcf2a3451169d58b to your computer and use it in GitHub Desktop.
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
(
// 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