-
-
Save ul/9725b5152747384f870c9f733eb13845 to your computer and use it in GitHub Desktop.
Sketch for a supercollider based cloud generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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