I went back and forth with the envelope type for quite a while. At first I tried to stick with a sustaining envelope, but I kept having Synths overlap. Eventually I switched over to a retriggerable env, instantiating the Synth just once, and triggering the envelope during the sequence.
I still wasn’t quite abIe to get the combo of how the envelope modulates the cutoff, along with the monosynth env retriggering, and portamento effect. And the overall timbre doesn’t quite have that same …lush squiggle for lack of a better word, but so it goes!
// bassline [midi note, length]
(
~loop = [
// bar 1
[42, 1.75],
[49, 0.25],
[54, 0.25],
[49, 0.25],
[47, 0.50],
[42, 1.00],
// bar 2
[45, 1.50],
[52, 0.50],
[38, 2.00],
// bar 3
[45, 1.50],
[47, 0.25],
[45, 0.75],
[52, 1.50],
// bar 4
[47, 4.00],
// bar 5
[42, 1.75],
[47, 0.25],
[49, 0.25],
[54, 0.25],
[42, 1.50],
// bar 6
[45, 1.75],
[52, 0.25],
[38, 1.50],
[52, 0.50],
// bar 7
[45, 1.50],
[52, 0.50],
[50, 1.50],
[52, 0.50],
// bar 8
[37, 4.00]
]
)
// based on SH-101 architecture + delay and reverb
(
SynthDef(\roygbiv, { |freq, pw = 0.55, spw = 0.5, co = 650, res = 1, gate = 1, atk = 0.01, sus = 1, rel = 0.1, out = 0, portamento = 0, envScale = 1, delScale = 0.01|
var pulse, saw, subOsc, noise, lfo, env;
var glide, pitchCtrl, coCtrl;
var mix, lpf, delay, reverb, sig;
glide = VarLag.kr(0, 0.6, 0, -2, start: portamento);
lfo = LFTri.kr(0.5);
pitchCtrl = freq + lfo.range(-0.8, 0.8) + glide;
pulse = Pulse.ar(pitchCtrl, pw + lfo.range(-0.07, 0.07));
saw = LFSaw.ar(pitchCtrl);
subOsc = Pulse.ar(pitchCtrl + Rand(-0.06, 0.06) / 2, spw);
noise = WhiteNoise.ar;
env = EnvGen.ar(Env.linen(atk, sus, rel, 0.5, 4), \trig.tr(1), timeScale: envScale, doneAction: 2);
mix = Mix([pulse * 0.7, saw * 0.5, subOsc * 0.5, noise * 0.25]) * env;
mix = Mix([mix.distort * 0.4, mix * 0.7]);
coCtrl = (co + (env * 500));
lpf = LPF.ar(LPF.ar((mix.softclip * 0.1) + (mix * 0.9), coCtrl), coCtrl) * 1.5;
delay = DelayC.ar(lpf, 1, delScale);
reverb = FreeVerb.ar(Mix([delay.softclip * 0.1, delay * 0.6, lpf * 0.8]) ! 2, 0.3, 0.45, 0.5);
sig = (delay * 0.1) + (reverb * 0.25) + (lpf * 0.85);
Out.ar(out, sig)
}).add
)
// play sequence
(
var bpm = 84;
var t = TempoClock(bpm / 60);
var tt = t.tempo;
var i = 0;
var prevPitch = 0;
var synth;
{
4.do{
synth = Synth(\roygbiv, [
\atk, 0.01,
\delScale, tt * 0.2,
\freq, (~loop[i][0]).midicps,
]);
~loop.size.do{
synth.set(
\freq, (~loop[i][0]).midicps,
\portamento, (~loop[i][0]).midicps - prevPitch.midicps,
\envScale, ~loop[i][1],
\sus, 3,
\trig, 1,
);
if (i > 0){ synth.set(\atk, 0.2) };
~loop[i][1].wait;
prevPitch = ~loop[i][0];
i = i + 1;
if (i >= ~loop.size) { i = 0 };
};
synth.set(\envScale, 1, \atk, 0.01, \sus, 0.01, \rel, 0.5, \trig, 1);
}
}.fork(t)
)