Skip to content

Instantly share code, notes, and snippets.

@catfact
Last active August 10, 2020 00:04
Show Gist options
  • Select an option

  • Save catfact/81673286bcf36bc52e0c9e745fcf87be to your computer and use it in GitHub Desktop.

Select an option

Save catfact/81673286bcf36bc52e0c9e745fcf87be to your computer and use it in GitHub Desktop.
drones
// utility func to "wrap: a value to a range, by octave division
var geoWrap = { arg x, max=2, min=1;
var y = x;
while ({y>max}, {y=y/2});
while ({y<min}, {y=y*2});
y
};
var synthFunc = {
arg hz=110, amp=0.125, out=0,
basePeriod=47,
attackTime=4, releaseTime=4, ampCurve= -0.5,
panWidth=0.75;
var gatePattern;
var scalePattern;
var ratioValues;
var snd;
// these determine the basic tonality
ratioValues = [1, 12/5, 3/2, 8/3, 18/8, 5/3];
gatePattern = [
[ 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[ 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0],
[ 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0],
[ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0],
];
scalePattern = [
[ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0],
[ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1],
[ 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
[ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1]
];
// for each scale pattern, extend it for 1-3 periods with random (but fixed) harmonic shifts
scalePattern = scalePattern.collect({
arg arr;
var harmShift = Array.series(1 + 3.rand, 1, 1 + 2.rand).scramble;
harmShift.collect({
arg harm;
arr.collect({ arg degree;
// lookup the index, apply the harmonic shift,
// and perform "geometric wrap" to [< 4]
geoWrap.value(ratioValues[degree] * harm, 4)
})
}).flatten;
});
// __more__
basePeriod = [basePeriod, basePeriod*2.718];
snd = gatePattern.size.collect({ arg i;
var gate, env, ratio, filterRatio, pulse, snd, del, delNeg, pan, panRate;
pulse = LFPulse.kr(1/basePeriod + LFNoise2.kr(1/basePeriod, 1));
gate = Demand.kr(pulse, 0, Dseq(gatePattern[i], inf));
env = EnvGen.kr(Env.asr(attackTime, 1, releaseTime, ampCurve), gate);
ratio = Demand.kr(pulse, 0, Dseq(scalePattern[i], inf));
// add a tiny amount of drift chaos to each sine freq
snd = SinOsc.ar(hz * ratio * (1 + LFNoise2.ar(0.25/basePeriod[0], 0.07))) * env;
snd = snd.distort.distort.distort;
snd = RLPF.ar(snd,
hz*[0.25, 0.5, 1, 1.5, 2] * Lag.kr(ratio, basePeriod) + LFNoise2.kr(1/basePeriod, 0.1),
LFNoise2.kr(1/basePeriod, 0.1 + 0.2.rand, 0.5 + 0.5.rand));
del = CombC.ar(snd, 0.5, 16.0/hz * LFNoise2.ar(0.125/basePeriod, 0.01, 1), basePeriod * 8);
// comb with a negative decay time, emphasizing odd harmonics 8vb
delNeg = CombC.ar(snd, 0.5, 4.0/hz * LFNoise2.ar(0.125/basePeriod, 0.01, 1), basePeriod * -8);
panRate = 1/(basePeriod) * geoWrap.value((i+1)*4.33, 2.0, 0.5);
Mix.new([
Pan2.ar(snd, SinOsc.ar(panRate, ((i+1)*pi/4.33).wrap(pi, 8*pi), panWidth), 0.5),
Pan2.ar(del, SinOsc.ar(panRate, ((i+3)*pi/2.78).wrap(pi, 8*pi), panWidth), 0.25),
Pan2.ar(delNeg, SinOsc.ar(panRate, ((i+5)*pi/1.595).wrap(pi, 8*pi), panWidth), 0.5)
])
});
snd = Mix.new(snd.flatten.clump(2));
snd = snd + RLPF.ar(snd, hz * 0.5, 0.2);
snd = (snd + [Normalizer.ar(snd[0]), Normalizer.ar(snd[1])]/2) * amp;
Out.ar(out, snd);
};
synthFunc
{
arg out=0, hz=110, amp=0.1, hzRatio=2.0,
aMin=1.0, aMax=1.3,
bMin=0.1, bMax=0.3;
var snd;
var aArr, bArr;
// defines tonality:
var ratios = [0.5, 1, 2, 15/8, 6/5];
//
aArr = Array.fill(ratios.size, {LFNoise2.ar(1/19).linlin(-1, 1, aMin, aMax)});
bArr = Array.fill(ratios.size, {LFNoise2.ar(1/29).linlin(-1, 1, bMin, bMax)});
snd = ratios.size.collect({
arg i;
Pan2.ar(
HenonL.ar(
hz * hzRatio * ratios + LFNoise2.ar(1/14, 0.4),
aArr[i], bArr[i], 0, 0.1
),
SinOsc.ar(1/31, (i*14).wrap(0, pi))
)
});
snd = LeakDC.ar(snd);
snd = Mix.new(snd.flatten.clump(2));
snd = (RLPF.ar(snd, hz*6) + RLPF.ar(Normalizer.ar(snd.tanh), hz * 0.5, 0.2));
Out.ar(out, snd * amp / (snd.size));
}
{
arg hz=110, amp=0.125, dt=66, out=0, modScale=7;
var ratios = [1, 23/22, 17/16, 13/12];
var n = ratios.size;
var fb = LocalIn.ar(n);
var mod = Array.fill(n, { LFNoise2.ar(1/dt, modScale) });
var phase = Array.fill(n, { arg i;
DelayL.ar(fb.wrapAt(i+1), 0.2, LFNoise2.ar(1/dt, 0.05, 0.06)) * mod[i]
});
var sines = ratios.collect({ arg r, i;
SinOsc.ar(hz * r, phase.wrapAt(i+2));
});
var snd;
LocalOut.ar(sines);
snd = Array.fill(n, {arg i;
Pan2.ar(sines[i], SinOscFB.ar(1/dt, LFNoise2.ar(1/dt, 2, 2)))
});
snd = Mix.new(snd);
snd.postln;
snd = RLPF.ar(snd, (hz*16).min(SampleRate.ir/2), LFNoise2.ar(1/dt, 0.3, 0.31));
Out.ar(out, snd* amp);
}
{
arg out=0, hz=110, amp=0.007, decay=1.0,
dustDensity=17, dustLagUp=0.017, dustLagDown=0.07,
dustAmp=0.73, brownAmp=0.05, sineAmp=0.007, rlpfAmp=0.33,
sineHzRatio=0.25, decayRatio=256;
var f, dust, sine, excite, klank, snd;
dust = Array.fill(2, {LagUD.ar(Dust.ar(dustDensity, dustAmp), dustLagUp, dustLagDown) });
dust = dust.distort.distort;
sine = SinOsc.ar((sineHzRatio*hz) + LFNoise2.ar(1/52, 0.127), 0, sineAmp);
excite = dust + BrownNoise.ar(brownAmp) + sine;
hz = [hz+LFNoise2.kr(0.1), hz-LFNoise2.kr(0.1)];
f = [1, 3, 5, 7, 11];
f = (f ++ (f * 13) ++ (f * 23)).flatten;
f = f.collect({|x| var y=x; while({y>4}, {y = y / 2}); y});
klank = DynKlank.ar(`[
f,
Array.geom(f.size, 1.0, 0.94),
Array.rand(f.size, 0, pi)
], excite, hz, 0, 1/hz * decayRatio);
snd = Mix.new(klank.flatten.clump(2))*amp;
snd = snd + RLPF.ar(excite, Array.fill(2, {hz * 0.5 * LFNoise2.ar(1/23, 0.5, 1.25)}), rlpfAmp);
snd = Limiter.ar((snd + snd.tanh)* 0.5 * 0.86);
Out.ar(out, snd);
}
{
arg out=0, hz=220, amp=0.125;
var dt = 47;
var n = 6;
var blips, saws, ring, snd, gnar;
var sloth = {
arg dt=10, ddt=30, min=0, max=1, ddtscale=1.0;
var hzhz = 1/ddt;
var hz = (1/dt) * LFNoise2.kr(hzhz, ddtscale, ddtscale*0.5);
var c = (max-min)*0.5; // tmp
LFNoise2.kr(hz, c, c+min)
};
var stack = {
arg base, // center frequency
n, // number of voices
m, // number of sub-octaves
dhz=2,
dt=10, ddt=100;
var oct = Array.geom(m, 2, 0.5); // sub octaves
var hz = Array.fill(n, {
var f = oct * base;
Zebra_DroneSloth.kr(dt, ddt, f-dhz, f+dhz)
});
hz.flatten
};
var pair = {
arg hz,
mod=1.0, // modulation scale
hzMul=1.0, // hz multiplier for cancelling saw
delRatio=0.5; // inverse multiplier for phase offset
var car = Saw.ar(hz);
var inv = Saw.ar(hz * hzMul);
car - (mod * DelayC.ar(inv, 0.1, delRatio/hz))
};
blips = Mix.new(
Blip.ar(
freq:stack.value(hz, 8, 3),
numharm: sloth.value(dt, dt*10, 1, 10, 2.0),
).clump(2)
);
saws = Mix.new(
pair.value(
hz: stack.value(hz, 8, 3),
mod: Array.fill(n, { sloth.value(dt, dt*10, 0.51, 0.99)}),
delRatio: Array.fill(n, {sloth.value(dt, dt*10, 055, 0.7)})
).clump(2)
);
ring = Array.fill(blips.size, { |i|
blips[i].ring2(saws.wrapAt(i+1));
});
snd = (blips + saws/2 + (ring * LFNoise2.kr(1/dt)))/2;
snd = Mix.new((snd + RLPF.ar(snd, hz * [0.25, 0.5] + LFNoise2.ar(1/dt, 0.5), 0.2 + LFNoise2.ar(1/dt, 0.1))).clump(2));
gnar = Normalizer.ar(RLPF.ar(Pulse.ar(hz * 0.25).distort, hz, 0.7));
Out.ar(out, (snd*0.9+gnar*1.2) * amp);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment