// title: Piano phase // author: jpdrecourt // description: // Early experimentation with patterns. Attempt at recreating Piano Phase by Steve Reich with random part lengths. // code: ( SynthDef(\mdapianoL, { |out=0, freq=440, gate=1, pan = 0, vel = 100, delaySigma = 0.01, release = 0.1, releaseSigma = 0.03, tune = 0.5| var son = MdaPiano.ar(freq, gate, vel, release: NRand(-3*releaseSigma, 3*releaseSigma, 50) + release, stereo: 0.1, tune: tune, sustain: 0); // son = Rotate2.ar(Select.ar(0, son), Select.ar(1, son), -0.4); son = BAllPass.ar(son, 1500, 10); son = DelayC.ar(son, delaySigma*6, NRand(0, delaySigma*6, 50)); son = Balance2.ar(Select.ar(0, son), Select.ar(1, son), pan); FreeSelf.kr(DetectSilence.ar(son.abs.sum + Impulse.ar(0))); Out.ar(out, son * 0.5); }).add; SynthDef(\mdapianoR, { |out=0, freq=440, gate=1, pan = 0, vel = 100, delaySigma = 0.01, release = 0.1, releaseSigma = 0.03, tune = 0.5| var son = MdaPiano.ar(freq, gate, vel, release: NRand(-3*releaseSigma, 3*releaseSigma, 50) + release, stereo: 0.11, tune: tune, sustain: 0); // son = Rotate2.ar(Select.ar(0, son), Select.ar(1, son), -1); son = DelayC.ar(son, delaySigma*6, NRand(0, delaySigma*6, 50)); son = Balance2.ar(Select.ar(0, son), Select.ar(1, son), pan); FreeSelf.kr(DetectSilence.ar(son.abs.sum + Impulse.ar(0))); Out.ar(out, son * 0.5); }).add; SynthDef(\reverb, {|out = 0, mix = 0.33, room = 0.5, damp = 0.5, predelay = 0.02| var in = In.ar(out, 2); in = FreeVerb2.ar(Select.ar(0, in), Select.ar(1, in), mix, room, damp); in = DelayC.ar(in, 0.1, predelay); ReplaceOut.ar(out, in); }).add; SynthDef(\lpf, {|out = 0, freq = 1200| var in = In.ar(out, 2); ReplaceOut.ar(out, LPF.ar(in, freq)); }).add; SynthDef(\delay, {|out = 0, wet = 0.5| var in = In.ar(out, 2); var delayed = in; 4.do({ delayed = AllpassN.ar(delayed, 0.14, [0.13888.rand, 0.13888.rand], 1) }); ReplaceOut.ar(out, ((1 - wet)*in) + (wet*delayed)); }).add; ) ( var midiPart1, velPart1, sPart1; var midiPart2L, midiPart2R, velPart2, sPart2; var midiPart3, velPart3, sPart3; var velPattern = [ Pwhite(90, 100,1), // LH Pwhite(85, 95, 1)]; // RH var pianoL, pianoR; var pan = 0.4; var verbMix, verbRoom, verbDamp; // Create a non-linear pattern series from almost zero to almost 1. var pCrescendo = { |steps = 100, isDec = false| var low = -15, high = 15; isDec.if( {Pseries(high, (low - high)/(steps - 1), steps).distort + 1 * 0.5;}, {Pseries(low, (high - low)/(steps - 1), steps).distort + 1 * 0.5;} ); }; // Create a pattern for a more realistic accelerando of one beat of the number of bars var pAccel = {|nBars = 10, beats = 6| var bar = Array.fill(beats, 1); var nBarsAccel = nBars.div(2); var accelDur = 1 - (1 / nBarsAccel / beats); var patternBars = Array.fill(nBarsAccel, Pseq(bar*accelDur)) ++ Array.fill(nBars - nBarsAccel, Pseq(bar)); Pshuf(patternBars); }; ~theEnd = false; ~nBars = 0; // Current part length ~phrase = 1; // Phrase number // Part 1 - 1 to 15 midiPart1 = [64, 66, 71, 73, 74, 66, 64, 73, 71, 66, 74, 73]; sPart1 = midiPart1.size; velPart1 = Pwhite(0.98, 1)*Pseq(velPattern, sPart1 / 2); // Part 2 - 16 to 26 midiPart2L = [64, 66, 71, 73, 74, 66, 71, 73]; midiPart2R = [64, 76, 69, 71, 74, 76, 69, 71]; sPart2 = midiPart2L.size; velPart2 = Pseq(velPattern, sPart2 / 2); // Part 3 - 26a to 32 midiPart3 = [69, 71, 74, 76]; sPart3 = midiPart3.size; velPart3 = Pseq(velPattern, sPart3 / 2); TempoClock.default.tempo = 72*6/60; // Left piano // Because of the accelerandos, left piano effectively plays one bar less per part pianoL = Pbind( \instrument, \mdapianoL, \midinote, Pseq([ // 1 - 15 Pseq([ Plazy({ Pseq(midiPart1, ~nBars); }) ], 26), Plazy({ Pseq(midiPart1, ~nBars - 1); }), // 16 - 24 Pseq([ Plazy({ Pseq(midiPart2L, ~nBars); }) ], 16), Plazy({ Pseq(midiPart2L, (~nBars - 1)); }), // 25 and 26 Pseq([ Plazy({ Pseq(midiPart2L, ~nBars); }) ], 2), // 26a Pseq([Rest(1)], 2), // 27 to 31 Pseq([ Plazy({ Pseq(midiPart3, ~nBars); }) ], 9), // 32 // First bar to decide how long Pseq(midiPart3, 1), Plazy({ Pseq(midiPart3, ~nBars -1) }), // Sending the nod from midi instead of vel // because the nod has to be sent at the last note (and velPart3 is a pattern) Pseq(midiPart3[0..(sPart3 - 2)]), Plazy({ ~theEnd = true; "*** Noding for end ***".postln; Pseq([midiPart3[sPart3 - 1]]); }), Pseq(midiPart3, 4), // And wait Rest(10) ]), \dur, 1, \vel, Pseq([ // 1 - 15 Pseq([ Plazy({ Pseq([velPart1], ~nBars); }) ], 26), Plazy({ Pseq([velPart1], (~nBars - 1)); }), // 16 to 24 Pseq([ Plazy({ Pseq([velPart2], ~nBars); }) ], 16), Plazy({ Pseq([velPart2], (~nBars - 1)); }), // 25 Plazy({ Pseq([velPart2], ~nBars) * pCrescendo.value(sPart2 * ~nBars, true); }), // 26 Plazy({ Pseq([velPart2]*0, ~nBars); }), // 26a Pseq([0], 2), // 27 Plazy({ Pseq([0], sPart3*(~nBars - 1)); }), // Left piano chooses crescendo in phrase 28 Plazy({ ~nBars = (24..48).choose; Pseq([0], sPart3); }), // 28.1 Plazy({ Pseq([velPart3], ~nBars)*pCrescendo.value(sPart3 * ~nBars); }), // 28.2 to 31 Pseq([ Plazy({ Pseq([velPart3], ~nBars); }) ], 7), // 32 // One bar to choose Plazy({ // Leaving two bars at beginning and 4 bars for ending at the end ~nBars = (18..42).choose; Pseq([velPart3], 1); }), Plazy({ Pseq([velPart3], ~nBars + 4); }), // And wait Rest(10) ]), \legato, 0.7, \release, 0.15, \releaseSigma, 0.02, \tune, 0.49, \pan, (0 - pan) ); // Right piano pianoR = Pbind( \instrument, \mdapianoR, \legato, 0.7, \release, 0.10, \releaseSigma, 0.03, \pan, (pan), \vel, Pseq([ // 1 Plazy({ ~nBars = (4..8).choose; "*** Part 1 ***".postln; ("" ++ ~phrase ++ ": " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart1]*0, ~nBars);}), // 2.1 Plazy({ ~nBars = (12..18).choose; ("" ++ ~phrase ++ ".1: " ++ ~nBars).postln; Pseq([velPart1], ~nBars)*pCrescendo.value(sPart1 * ~nBars); }), // 2.2 Plazy({ ~nBars = (4..16).choose; ("" ++ ~phrase ++ ".2: " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart1], ~nBars); }), // 3 to 8 Pseq([ Plazy({ ~nBars = (16..24).choose; ("" ++ ~phrase ++ ".1: " ++ ~nBars).postln; Pseq([velPart1], ~nBars); }), Plazy({ ~nBars = (4..16).choose; ("" ++ ~phrase ++ ".2: " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart1], ~nBars); }) ], 6), // 9 to 13 Pseq([ Plazy({ ~nBars = (12..24).choose; ("" ++ ~phrase ++ ".1: " ++ ~nBars).postln; Pseq([velPart1], ~nBars); }), Plazy({ ~nBars = (4..16).choose; ("" ++ ~phrase ++ ".2: " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart1], ~nBars); }) ], 5), // 14 Plazy({ ~nBars = (4..8).choose; ("" ++ ~phrase ++ ": " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart1], ~nBars)*pCrescendo.value(sPart1 * ~nBars, true); }), // 15 Plazy({ ~nBars = (4..8).choose; ("" ++ ~phrase ++ ": " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart1]*0, ~nBars); }), // 16 Plazy({ "*** Part 2 ***".postln; ~nBars = (6..8).choose; ("" ++ ~phrase ++ ": " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart2]*0, ~nBars); }), // 17.1 Plazy({ ~nBars = (16..32).choose; ("" ++ ~phrase ++ ".1: " ++ ~nBars).postln; Pseq([velPart2], ~nBars)*pCrescendo.value(sPart2 * ~nBars); }), // 17.2 Plazy({ ~nBars = (6..18).choose; ("" ++ ~phrase ++ ".2: " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart2], ~nBars); }), // 18 to 24 Pseq([ Plazy({ ~nBars = (16..32).choose; ("" ++ ~phrase ++ ".1: " ++ ~nBars).postln; Pseq([velPart2], ~nBars); }), Plazy({ ~nBars = (6..18).choose; ("" ++ ~phrase ++ ".2: " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart2], ~nBars); }) ], 7), // 25 Plazy({ ~nBars = (8..24).choose; ("" ++ ~phrase ++ ": " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart2], ~nBars); }), // 26 Plazy({ ~nBars = (8..16).choose; ("" ++ ~phrase ++ ": " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart2], ~nBars); }), // 26a Plazy({ "*** Part 3 ***".postln; Pseq(velPattern); // Just 2 notes }), // 27 Plazy({ ~nBars = (8..24).choose; ("" ++ ~phrase ++ ": " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart3], ~nBars); }), // 28.1 Plazy({ // Left piano chooses crescendo length ("" ++ ~phrase ++ ".1: " ++ ~nBars).postln; Pseq([velPart3], ~nBars); }), // 28.2 Plazy({ ~nBars = (16..32).choose; ("" ++ ~phrase ++ ".2: " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart3], ~nBars); }), // 29 to 31 Pseq([ Plazy({ ~nBars = (48..60).choose; ("" ++ ~phrase ++ ".1: " ++ ~nBars).postln; Pseq([velPart3], ~nBars); }), Plazy({ ~nBars = (16..32).choose; ("" ++ ~phrase ++ ".2: " ++ ~nBars).postln; ~phrase = ~phrase + 1; Pseq([velPart3], ~nBars); }), ], 3), // 32 // Catching up the missing bar and playing one extra to let left decide how long Plazy({ ("" ++ ~phrase ++ ": ?").postln; Pseq([velPart3], 2); }), Pif(Pfunc({~theEnd.not}), Pseq([ Plazy({ Pseq([velPart3]); }) ], inf) ), Plazy({ "*** Nod back ***".postln; Pseq([velPart3], 4); }), // And wait Rest(10) ]), \dur, Pseq([ // 1 & 2.1 Pseq([Plazy({ Pseq([1], sPart1*~nBars); }) ], 2), // 2.2 Plazy({ pAccel.value(~nBars, sPart1); }), // 3 to 13 Pseq([ Plazy({ Pseq([1], sPart1*~nBars); }), Plazy({ pAccel.value(~nBars, sPart1); }), ], 11), // 14 and 15 Pseq([Plazy({ Pseq([1], sPart1*~nBars); }) ], 2), // 16 and 17.1 Pseq([Plazy({ Pseq([1], sPart2*~nBars); }) ], 2), // 17.2 Plazy({ pAccel.value(~nBars, sPart2); }), // 18 to 24 Pseq([ Plazy({ Pseq([1], sPart2*~nBars); }), Plazy({ pAccel.value(~nBars, sPart2); }), ], 7), // 25 and 26 Pseq([ Plazy({ Pseq([1], sPart2*~nBars); }) ], 2), // 26a Pseq([1], 2), // 27 and 28.1 Pseq([ Plazy({ Pseq([1], sPart3*~nBars); }) ], 2), // 28.2 Plazy({ pAccel.value(~nBars, sPart3); }), // 29 to 31 Pseq([ Plazy({ Pseq([1], sPart3*~nBars); }), Plazy({ pAccel.value(~nBars, sPart3); }), ], 3), // 32 // Catching up and one extra Pseq([1], sPart3*2), Pif(Pfunc({~theEnd.not}), Pseq(Array.fill(sPart3, 1), inf) ), Plazy({ Pseq([1], sPart3*4) }), // And wait Rest(10) ]), \midinote, Pseq([ // 1 to 15 Pseq([ Plazy({ Pseq(midiPart1, ~nBars); }) ], 27), // 16 to 24 Pseq([ Plazy({ Pseq(midiPart2R, ~nBars); }) ], 17), // 25 and 26 (same as before but for debug reasons) Pseq([ Plazy({ Pseq(midiPart2R, ~nBars); }) ], 2), // 26a Pseq(midiPart2R[0..1]), // 27 to 31 Pseq([ Plazy({ Pseq(midiPart3, ~nBars); }) ], 9), // 32 // Catching up and one extra Pseq(midiPart3, 2), Pif(Pfunc({~theEnd.not}), Pseq(midiPart3, inf) ), Pseq(midiPart3, 4), // And wait Rest(10) ]) ); verbMix = 0.07; verbRoom = 0.8; verbDamp = 1; pianoL = Pfxb(pianoL, \lpf, \freq, 4000); pianoL = Pfxb(pianoL, \delay, \wet, 0.10); pianoL = Pfxb(pianoL, \reverb, \mix, verbMix, \room, verbRoom, \damp, verbDamp); pianoL.play(quant: 1); pianoR = Pfxb(pianoR, \lpf, \freq, 3800); pianoR = Pfxb(pianoR, \delay, \wet, 0.12); pianoR = Pfxb(pianoR, \reverb, \mix, verbMix, \room, verbRoom, \damp, verbDamp); pianoR.play(quant: #[1, 0, 0.1]); )