// title: sloth canons // author: eli.rosenkim // description: // routine that takes a seed and generates a self-similar sloth canon with it by adding each term to each term, better explained in this blog post: https://www.science20.com/robert_inventor039s_column/blog/self_similar_sloth_canon_number_sequences-113689 // code: // Inspired by: https://www.science20.com/robert_inventor039s_column/blog/self_similar_sloth_canon_number_sequences-113689 //self-similar sloth-canon routine, for some integer a, r(n) = r(a*n) ( r = Routine({ var seed = #[0,1,0], i=0, temp, temp2 = List[], out; temp = seed; loop { out = temp[((i/3).floor)%temp.size] + seed[i%seed.size]; if(i%9 == 0, {out.post}); //comment next line and uncomment this line to demonstrate that for seed [0,1,0], r(n) = r(3*n) for all n //out.post; 0.1.wait; i = i+1; temp2.add(out); if((i+1) > (temp.size**2), {temp = temp2}); } }); ) r.play; r.stop; //simple musical examples (//disperser taken from https://scsynth.org/t/phase-rotation-fos/5575 SynthDef(\simpleSaw, { arg root=150, oTone=1, uTone=1, amp=0.8, gate = 0.5, release = 1, k= 0.4, curve = 2, lag = 0.01; var sig, finalFreq, env, tempO, tempU, sigL, sigR, sigM, sigS, hornbostelwertheimerkonstante = 0.00063; tempO = oTone; tempU = uTone; oTone = oTone.max(1); uTone = uTone.max(1); finalFreq = (oTone/uTone) * root; finalFreq = finalFreq.lag2(lag); sig = Saw.ar(finalFreq, 0.5); sig =sig *(tempO.abs.min(1))*(tempU.abs.min(1));//mutes notes with oTone or uTone = to 0 sigL = DelayC.ar(sig, 1, LFNoise1.ar(1.11, finalFreq * hornbostelwertheimerkonstante * 0.005)); sigR = DelayC.ar(sig, 1, LFNoise1.ar(1.1, finalFreq * hornbostelwertheimerkonstante * 0.005)); sigM = sigL + sigR; sigS = sigL - sigR; 100.do {sigS = FOS.ar(sigS, k.neg, 1, k);}; //allpass disperser sigL = (sigM + sigS); sigR = (sigM - sigS); sig = [sigL, sigR]; env = EnvGen.kr(Env.adsr(0.01, 0, 1, release, 1, curve), gate, levelScale: 1, doneAction: Done.freeSelf); sig = sig*env; Out.ar(0, sig!2); }).add; ) //sequence, wait for it to develop, increasingly complex ratios will emerge ( ~oFunc = { var seed = #[0,1, 0], i=0, temp, temp2 = List[], out; temp = seed; loop { out = temp[((i/3).floor)%temp.size] + seed[i%seed.size]; out.yield; ("o: " ++ out).postln; i = i+1; temp2.add(out); if((i+1) > (temp.size**2), {temp = temp2}); } }; ~uFunc = { var seed = #[0,1, -1], i=0, temp, temp2 = List[], out; temp = seed; loop { out = temp[((i/3).floor)%temp.size] + seed[i%seed.size]; out.yield; ("u: " ++ out).postln; i = i+1; temp2.add(out); if((i+1) > (temp.size**2), {temp = temp2}); } }; PmonoArtic( \simpleSaw, \oTone, Prout(~oFunc), \uTone, Prout(~uFunc), \root, 198 * Pseq([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, (3/2), (3/2), (3/2), (3/2), (3/2)], inf), \release, 0.1, \curve, -2, \k, 0.4, \dur, 0.15, \lag, Pseq([0.06, 0.05, 0.05, 0.04], inf), \legato, Pseq([1, 0.5], inf), ).play; PmonoArtic( \simpleSaw, \oTone, Prout(~oFunc), \uTone, Prout(~uFunc), \root, 198, \release, 0.5, \curve, -1, \k, 0.8, \dur, 0.3, \lag, Pseq([0.06, 0.05, 0.05, 0.04], inf), \legato, Pseq([1, 0.5], inf), ).play; PmonoArtic( \simpleSaw, \oTone, Prout(~oFunc), \uTone, Prout(~uFunc), \root, 198, \release, 0.5, \curve, 1, \k, 1, \dur, 0.6, \lag, Pseq([0.04], inf), \legato, Pseq([1, 0.5], inf), ).play; ) //sequence 2 ( ~oFunc = { var seed = #[-3,0,3,1], i=0, temp, temp2 = List[], out; temp = seed; loop { out = temp[((i/3).floor)%temp.size] + seed[i%seed.size]; out.yield; ("o: " ++ out).postln; i = i+1; temp2.add(out); if((i+1) > (temp.size**2), {temp = temp2}); } }; ~uFunc = { var seed = #[-3,-2,3], i=0, temp, temp2 = List[], out; temp = seed; loop { out = temp[((i/3).floor)%temp.size] + seed[i%seed.size]; out.yield; ("u: " ++ out).postln; i = i+1; temp2.add(out); if((i+1) > (temp.size**2), {temp = temp2}); } }; PmonoArtic( \simpleSaw, \oTone, Prout(~oFunc), \uTone, Prout(~uFunc), \root, 198*0.5, \release, 0.05, \curve, -2, \k, 0.4, \dur, 0.1, \lag, Pseq([0.06, 0.05, 0.05, 0.04], inf), \legato, Pseq([1, 0.5], inf), ).play; PmonoArtic( \simpleSaw, \oTone, Prout(~oFunc), \uTone, Prout(~uFunc), \root, 198*0.5, \release, 0.2, \curve, -1, \k, 0.8, \dur, 0.2, \lag, Pseq([0.06, 0.05, 0.05, 0.04], inf), \legato, Pseq([1, 0.5], inf), ).play; PmonoArtic( \simpleSaw, \oTone, Prout(~oFunc), \uTone, Prout(~uFunc), \root, 198*0.5, \release, 0.1, \curve, 1, \k, 1, \dur, 0.4, \lag, Pseq([0.04], inf), \legato, Pseq([1, 0.5], inf), ).play; ) //sequence 3 ( ~oFunc = { var seed = #[-3,0,3], i=0, temp, temp2 = List[], out; temp = seed; loop { out = temp[((i/3).floor)%temp.size] + seed[i%seed.size]; out.yield; ("o: " ++ out).postln; i = i+1; temp2.add(out); if((i+1) > (temp.size**2), {temp = temp2}); } }; ~uFunc = { var seed = #[-3,-2,0,5,0], i=0, temp, temp2 = List[], out; temp = seed; loop { out = temp[((i/3).floor)%temp.size] + seed[i%seed.size]; out.yield; ("u: " ++ out).postln; i = i+1; temp2.add(out); if((i+1) > (temp.size**2), {temp = temp2}); } }; PmonoArtic( \simpleSaw, \oTone, Prout(~oFunc), \uTone, Prout(~uFunc), \root, 198*2, \release, 0.1, \curve, -2, \k, 0.1, \dur, 0.1, \lag, Pseq([0.06, 0.05, 0.05, 0.04], inf), \legato, Pseq([1, 0.5], inf), ).play; PmonoArtic( \simpleSaw, \oTone, Prout(~oFunc), \uTone, Prout(~uFunc), \root, 198*2, \release, 0.1, \curve, -4, \k, 0.8, \dur, 0.2, \lag, Pseq([0.06, 0.05, 0.05, 0.04], inf), \legato, Pseq([1, 0.5], inf), ).play; PmonoArtic( \simpleSaw, \oTone, Prout(~oFunc), \uTone, Prout(~uFunc), \root, 198*2, \release, 0.2, \curve, 1, \k, 0.99, \dur, 0.3, \lag, Pseq([0.04], inf), \legato, Pseq([1, 0.5], inf), ).play; )