Sketch for a supercollider based cloud generator
/* | |
Sketch for a cloud generator | |
By Mads Kjeldgaard, 2020 | |
*/ | |
( | |
~numChannels = 2; | |
s.options.numOutputBusChannels_(~numChannels); | |
~filePath = "~/lee.flac"; | |
s.waitForBoot{ | |
fork{ | |
// b = Buffer.read(s, "~/testsound/harmonica1.wav".asAbsolutePath).normalize; | |
b = Buffer.read(s, ~filePath.asAbsolutePath).normalize; | |
s.sync; "Done loading buffer".postln; | |
} | |
} | |
) | |
( | |
Ndef(\cloud, {|gdur=0.1, buffer, density=1.0, rate=0.95, shape=0.5, ratespread=0.0, pos=0.25, posspread=0.0, rand=1.0, overlap=0.0, amp=0.5| | |
var cloud; | |
var numGrains=4; | |
var numBufChans=2; | |
// Normalize params | |
density = density.linexp(0.0,1.0,0.0001,100.0); | |
rate = rate.linexp(0.0,1.0,0.01,10.0); | |
cloud = Array.fill(numGrains, {|gNum| | |
var coef=gNum+1/numGrains; | |
// Add tiny difference to each grain generator | |
var weight = Rand(0.9999,1.0); | |
var finalgdur = gdur * weight * overlap.linlin(0.0,1.0,1.0,4.0); | |
// Deterministic | |
var imp = Impulse.ar(density, phase: coef); | |
// Random impulses | |
var dust = Dust2.ar(density); | |
// Crossfade between them | |
var trig = XFade2.ar(imp, dust, rand.linlin(0.0,1.0,-1.0,1.0)); | |
// Grain envelope | |
// Soft envelope | |
var sineenv = EnvGen.ar( | |
Env.sine, | |
trig, | |
timeScale: finalgdur | |
); | |
// Hard envelope | |
var clickenv = EnvGen.ar( | |
Env([0,1,1,0], [0,1,0]), | |
trig, | |
timeScale: finalgdur | |
); | |
// Faded | |
var env = XFade2.ar(sineenv, clickenv, shape.linlin(0.0,1.0,-1.0,1.0)); | |
// Calculate position in buffer | |
var position = (weight * pos + (posspread * coef)).wrap(0.0,1.0) * BufFrames.ir(buffer); | |
// Calculate playback rate | |
var playbackrate = weight * rate * BufRateScale.ir(buffer); | |
var sig = PlayBuf.ar( | |
numBufChans, | |
buffer, | |
ratespread * (gNum + 1) + 1 * playbackrate, | |
trig, | |
position, | |
loop: 0.0, | |
doneAction: 0 | |
); | |
LeakDC.ar(env * sig) | |
}); | |
// Normalize sound levels a bit | |
cloud = cloud / numGrains; | |
cloud = cloud * amp; | |
Splay.ar(cloud.flatten) | |
}).set(\buffer, b, \wet1, 0.35).play; | |
Ndef(\cloud)[1] = \filter -> {|in, verbtime=10, room=5| | |
JPverb.ar(in, verbtime, 0, room); | |
}; | |
) | |
// Gui | |
( | |
Spec.add(\pos, ControlSpec( minVal: 0.0, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.5)); | |
Spec.add(\density, ControlSpec( minVal: 0.0, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.5)); | |
Spec.add(\rate, ControlSpec( minVal: 0.0, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.5)); | |
Spec.add(\shape, ControlSpec( minVal: 0.0, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.5)); | |
Spec.add(\ratespread, ControlSpec( minVal: 0.0, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.5)); | |
Spec.add(\posspread, ControlSpec( minVal: 0.0, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.5)); | |
Spec.add(\rand, ControlSpec( minVal: 0.0, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.5)); | |
Spec.add(\overlap, ControlSpec( minVal: 0.0, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.5)); | |
Spec.add(\gdur, ControlSpec( minVal: 0.001, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.1)); | |
Spec.add(\wet1, ControlSpec( minVal: 0.0, maxVal: 1.0, warp: \lin, step: 0.0, default: 0.5)); | |
Ndef(\cloud).gui; | |
) | |
// Add some modulation | |
( | |
Ndef(\saw, {|f=0.001| LFSaw.kr(f).unipolar}).copy(\saw2).set(\f, 0.001); | |
Ndef(\sine, {|f=0.0151| SinOsc.kr(f).unipolar}).copy(\sine2).set(\f, 0.093211); | |
Ndef(\cloud).map(\posspread, Ndef(\saw), \stochastic, Ndef(\saw2), \rand, Ndef(\sine), \density, Ndef(\sine2)); | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment