Sawtooth Minimalism My colleague, Jackie Walduck, was showing students how to create phase music by putting loops out of synch in a DAW. Then I went home from teaching and created a PD patch to play low-pass filtered sawtooth waves, as an example for a different class. I got curious how much easier it would be in SuperCollider and created a tiny program that did the same thing and set it going at the same time. Then I started it again. The phasing was fixed, but it called to mind the shifting relationships of earlier that day. This version is only SuperCollider, but it uses a non band limitted sawtooth to mimic phasor~ in PD. This version is 7 minutes long, but the proper version should be about 3 hours. I get lost in the phasing and feel relaxed. I’ve attached the code below. If you want to to last longer, look for the number 340 – that’s 5’40” in seconds. Make it as long as you’d like. s.waitForBoot({ var scale, dur, pb, steps=16, loops = 4, loop_calc, env_dur, db = -14, fade_in=40, decay = 20; loop_calc = {|note_dur, section_dur| var loop_dur, total_dur; loop_dur = note_dur * steps * loops; total_dur = loop_dur * (section_dur/loop_dur).ceil; }; SynthDef(\saw, {|out=0, freq, amp, dur, pan| var saw, env, lop, pan2; saw = LFSaw.ar(freq); lop = LPF.ar(saw, freq*4); env = EnvGen.kr(Env.triangle(dur), doneAction:2); pan2 = Pan2.ar(lop, pan, env); Out.ar(out, pan2 * amp); }).add; //s.prepareForRecord("/home/celesteh/Documents/Pieces/SawtoothMinimalism/take-" ++ Date.getDate.rawSeconds ++".wav" , 2); s.sync; //s.record; dur = 60 / 250; // 250 BPM env_dur = loop_calc.(dur, 340) - (fade_in+ decay); env_dur.postln; scale = Scale.minorPentatonic(Tuning.choose(5)); pb = {|limit = 7| Pbind( \instrument, \saw, \db, db, \dur, dur, \scale, scale, \degree, Prout({ var loop; inf.do({ loop = steps.collect({ /*scale.degrees[5.rand]*/ limit.rand }); loop = loop.scramble; loops.do({ loop.do({|step| step.yield; }) }) }) }), //\midinote, Pkey(\add) + offset, \out, 0 ); }; s.sync; Pseq([ Pbindf(pb.value, \octave, 4, \pan, 0, \continue, Pn(1,loops*steps)), Ptpar([ 0, Pseq([ Pbindf(pb.value, \octave, 4, \pan, -75, \continue, Pn(1, loops*steps*4)), Pbindf(pb.value(5), \octave, [4, 5], \pan, -1, \db, Penv([db, db-2, db, db], [fade_in,decay, env_dur])), Pbindf(pb.value, \octave, 4, \pan, -0.88, \db, Pn(db+1, 1), \degree, [0, 2], \dur, dur*8) ] ), 0.0008.rrand(dur/10), Pseq([ Pbindf(pb.value, \octave, 5, \pan, 75, \continue, Pn(1, loops*steps*4)), Ptpar([ 0, Pseq([Pbindf(pb.(5), \octave, [4,5], \pan, 1, \db, Penv([db, db-2, db, db], [fade_in,decay, env_dur])), Pbindf(pb.value, \octave, 4, \pan, 0.88, \db, Pn(db+1, 1), \degree, [1, 4], \dur, dur*8)]), (dur * 0.3).rrand(dur*0.7), Pseq([ Pbindf(pb.value, \octave, 5, \pan, Pwhite(-0.1, 0.1), \dur, Pwhite((dur / -700), (dur/700)) + dur, \db, Penv([-60, db+1, db, db], [fade_in, decay, env_dur])), Pbindf(pb.value, \octave, 5, \pan, 0, \db, Pn(db+1, 1), \degree, [0, 3, 5], \dur, dur*8) ]) ]) ]) ]),