Skip to content

Instantly share code, notes, and snippets.

@catfact
Last active August 14, 2025 14:20
Show Gist options
  • Select an option

  • Save catfact/538d0c27d3e53c513aa833026f9bb75b to your computer and use it in GitHub Desktop.

Select an option

Save catfact/538d0c27d3e53c513aa833026f9bb75b to your computer and use it in GitHub Desktop.
// polyform lite - nb editon v.0.1 @sonoCircuit
// supercollider class based on the skilled labour study written by ezra buchla & dani derks for monome.org
NB_PolyForm {
// classvar <voiceKeys,
classvar <synthParams, <synthGroup, <synthVoices;
// do these all need to be classvars?
// [eb] it strikes me as a little weird to make everything classvars, which are global
// (so these Groups are always present in the background, forever)
// but i guess in the context it's fine
classvar numVoices = 6;
*initClass {
// six voices
// voiceKeys = [ \1, \2, \3, \4, \5, \6];
// [eb] not needed, i think using a dictionary is weirding things up
// global synth params
synthParams = Dictionary.newFrom([
\amp, 0.8,
\spread, 0,
\mix, -0.6,
\saw_tune, 0,
\pulse_tune, 0,
\saw_shape, 1,
\pulse_width, 0.5,
\cutoff_lpf, 1200,
\res_lpf, 0.2,
\env_lpf_depth, 0.24,
\attack, 0,
\decay, 2.2,
\sendA, 0,
\sendB, 0
]);
// evaluate after startup
StartUp.add {
var s = Server.default;
// make sure that the server has actually finished booting
s.waitForBoot {
// create a group
synthGroup = Group.new(s);
// // create a dictionary to hold the synth voices
// synthVoices = Dictionary.new;
// // iterate over voiceKeys and assign each synthvoice to a new group within synthGroup
// voiceKeys.do({ arg i;
// synthVoices[i] = Group.new(synthGroup); // <<< do these need to be initialized some other way?
// });
// [eb] don't need a dictionary here
synthVoices = Array.fill(numVoices, { Group.new(synthGroup) });
// define synthDef
SynthDef(\nb_polyForm,{
arg note = 60, amp = 1.0, spread = 0, mix = 0,
saw_tune = 0, pulse_tune = 0, saw_shape = 1, pulse_width = 0.5,
cutoff_lpf = 1200, res_lpf = 0.1, env_lpf_depth = 0.2,
gate = 1, attack = 0.001, decay = 10,
sendA = 0, sendB = 0,
out = 0, sendABus = 0, sendBBus = 0;
var env = EnvGen.kr(Env.perc(attack, decay), doneAction: 2);
var env_gate = EnvGate(gate:gate, doneAction:2);
var freq = note.midicps.clip(8, 12544);
var freq_saw = Lag.kr(freq * 2.pow(saw_tune / 12));
var freq_pulse = Lag.kr(freq * 2.pow(pulse_tune / 12));
var osc_saw = VarSaw.ar(freq_saw, 0.248, saw_shape);
var osc_pulse = Pulse.ar(freq_pulse, pulse_width);
var osc_mix = XFade2.ar(osc_saw, osc_pulse, mix, amp) * -6.dbamp;
var cut_lin_lpf = cutoff_lpf.explin(20, 18000, 0, 1);
var cut_lpf_mod = cut_lin_lpf + (env * env_lpf_depth);
var cutoff = cut_lpf_mod.linexp(0, 1, 20, 18000);
var rq_lpf = res_lpf.linlin(0, 1, 0, 4);
var osc_lpf = MoogFF.ar(osc_mix, cutoff, rq_lpf) * env * env_gate;
var snd = Pan2.ar(osc_lpf, spread * Rand(-0.7, 0.7));
Out.ar(out, snd);
Out.ar(sendABus, sendA * snd);
Out.ar(sendBBus, sendB * snd);
}).add;
// add OSC functions
OSCFunc.new({ |msg, time, addr, recvPort|
var i = msg[1].asInteger;
var note = msg[2].asInteger;
var vel = msg[3].asFloat;
synthVoices[i].set(\gate, -1.05);
// [eb] ^ wasn't working with Env.perc / dictionary
Synth.new(\nb_polyForm,
[
\note, note,
\vel, vel,
\sendABus, ~sendA ? Server.default.outputBus,
\sendBBus, ~sendB ? Server.default.outputBus,
] ++ synthParams.getPairs, target: synthVoices[i]
);
}, "/nb_polyform/note_on");
OSCFunc.new({ |msg, time, addr, recvPort|
var i = msg[1].asInteger;
synthVoices[i].set(\gate, 0);
}, "/nb_polyform/note_off");
OSCFunc.new({ |msg, time, addr, recvPort|
var key = msg[1].asSymbol;
var val = msg[2].asFloat;
//voiceKeys.do({ arg i;
numVoices.do({ arg i;
synthVoices[i].set(key, val);
// [eb] wasn't working with dictionary, not sure why
});
synthParams[key] = val;
}, "/nb_polyform/set_param");
OSCFunc.new({ |msg, time, addr, recvPort|
synthGroup.set(\gate, -1.05);
}, "/nb_polyform/panic");
OSCFunc.new({ |msg, time, addr, recvPort|
synthGroup.free;
}, "/nb_polyform/free");
}
}
}
}
@sonocircuit
Copy link

sonocircuit commented Aug 13, 2025

just looked over your comments and changes and everything make sense to me. thank you, very much appreciated!

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