Here’s a SuperCollider recreation of Douglas Leedy’s “Entropical Paradise (with Bird Call)” for anyone who is interested. I probably missed a few things in my translating this from the score to code like some unit conversions, but the end result is pretty close. It doesn’t sound that close to the recording but I wasn’t necessarily expecting it to…
Read about it here:
My SC version here:
(
//conversions
var ampVolt = {|x| x.linlin(0, 1, 0, 15)};
var voltAmp = {|x| x.linlin(0, 15, 0, 1)};
var ampFreq = {|x| x.linexp(0, 1, 5, 20000)};
var freqAmp = {|x| x.explin(5, 20000, 0, 1)};
var voltFreq = {|x| x.linexp(0, 15, 5, 20000)};
var freqVolt = {|x| x.explin(5, 20000, 0, 15)};
//sequencer voltages
var seq1a = [3, 5, 7, 7, 3, 2, 9, 5];
var seq1b = [15, 5, 0, 0, 3, 7, 15, 5];
var seq1c = [0, 7, 15, 0, 3, 7, 0, 8];
var seq2a = [9, 9, 10, 10, 9, 8, 8, 8, 7, 8, 9, 7, 8, 8.5, 8, 8.5];
//env detector
var envDetectSens = 0.6;
var envDetectDecay = 1.0;
//tpg
var ampTime = {|x| x.linexp(0, 1, 0.005, 20.0)};
var atk = 0.05, hold = 0.01, rel = 2.0;
{
var makeVCO = {|freq, dist|
LinSelectX.ar(dist, [
SinOsc.ar(freq),
LFSaw.ar(freq)
]);
};
var makeCVP = {|inA, inB, a, b, voltage, c, d|
var ext = LinSelectX.ar(c / (c + d), [inA, inB]);
var output = LinSelectX.ar(a / (a + b), [ext, DC.ar(voltAmp.(voltage))]);
output.linlin(-1, 1, 0, 1);
};
var periodIn = LocalIn.ar(2);
var noise = PinkNoise.ar();
var envFollow = Amplitude.ar(
(noise * envDetectSens).linlin(-1, 1, 0, 1), //scale and rectify
SampleDur.ir,
envDetectDecay
);
var tpg1 = TDuty.ar(
ampTime.(periodIn[1].linlin(-1, 1, 0, 1))
);
var tpg2 = TDuty.ar(
ampTime.(periodIn[0].linlin(-1, 1, 0, 1))
);
var rvsA = TRand.ar(0, 1, PulseDivider.ar(tpg1, 2));
var rvsB = TRand.ar(0, 1, tpg2);
var sg1a = Demand.ar(tpg1, 0, Dseq(voltAmp.(seq1a), inf));
var sg1b = Demand.ar(tpg1, 0, Dseq(voltAmp.(seq1b), inf));
var sg1c = Demand.ar(tpg1, 0, Dseq(voltAmp.(seq1c), inf));
var sg2a = Demand.ar(tpg2, 0, Dseq(voltAmp.(seq2a), inf));
var cvp1a = makeCVP.(sg1a, rvsB, 9, 10, 7.5, 1, 1);
var cvp1b = makeCVP.(DC.ar(-1), rvsB.neg, 4, 5, 5, 3, 2);
var cvp2a = makeCVP.(cvp1b, sg2a, 1, 2, 7, 3, 2);
var atgA = Env([0, 1, 1, 0], [atk, hold, rel], \lin).ar(0, tpg2);
var atgB = Env([0, 1, 1, 0], [atk, hold, rel], \lin).ar(0, tpg1);
var vco1 = makeVCO.(
ampFreq.(envFollow),
0
);
var vco2 = makeVCO.(
ampFreq.(cvp1a),
0.3
) * atgA;
var vco3 = makeVCO.(
ampFreq.(cvp2a),
0.3
) * atgB;
var split;
var sig;
vco2 = FreeVerb.ar(vco2, 0.5, 1.0);
vco3 = FreeVerb.ar(vco3, 0.5, 1.0);
split = [vco2, vco3];
sig = vco1 * sg1a * [sg1c, sg1b];
//Send feedback
LocalOut.ar([rvsB, cvp1b]);
sig = (sig + split) * -7.dbamp;
}.play;
)
Listen to the original here: