Music by Charles Céleste HUTCHINS
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)
])
])
])
]),
Pbind(
\dur, dur,
\freq, Prout({
\rest.yield;
//s.stopRecording;
})
)
]).play;
});