I love this performance by Dan, so I have tried to see what I can learn from his code by recreating a part of it in Sonic Pi.
I had much fun just exploring the first part translating TidalCycles mask"[111 111 111 111]" to Sonic Pi “amp:” which is a smart way to turn on/off notes.
The rest of the code is me playing around.
My code is auto running different possibilities with knit()
I didnt focus on the buildup in the beginning, but would do that in a live performance.
I think Dans way of doing things a great - from simple to complex.
There are many places in the code where you can change the melody rythm or playorder by removing “#” from line 39-70 or change the original notes in line 49.
Dan Gorelick Longest Night TidalCycles performance – Piano Phase
# 221218 2308 Dan Gorelick Longest Night TidalCycles performance Piano Phase
# Saved 221218 2308
# Backup
# Exploration/recreated in Sonic Pi by https://linktr.ee/relaxnow
# https://in-thread.sonic-pi.net/t/jumping-off-point-dan-gorelick-longest-night-tidalcycles-performance-piano-phase/7351
# Jumping off point
# Dan Gorelick Longest Night TidalCycles performance – Piano Phase
# https://youtu.be/Hc-lcAajQxo
# What I learned doing this
# 1) TidalCycles "MASK[111 111 111 111]" to Sonic Pi "amp:" is a smart way to turn on/off notes
# 2) Hoping to learn how to send midi notes to Ableton/Hydra and use notes in Ableton as visuals like Dan (not done yet)
# 3) Hoping to learn how to send osc notes to Hydra and use Hydra to create interesting visuals with midi notes (not done yet)
# Idea: midimap to LaunchControl or Beatstep pro (since it has more buttoms. I need 12. Do i?)
set_volume! 2
use_bpm 144
live_loop :time, delay: 0.01 do
sleep 0.5*12
end
with_fx :reverb, room: 0.7 do
with_fx :ping_pong, phase: 0.5, feedback: 0.2 do
/ arp synth /
live_loop :synth, sync: :time do
tick
# 111 111 111 111
a = [1,1,1, 1,1,1, 1,1,1, 1,1,1]
#a = [0,0,1, 0,1,1, 0,0,1, 0,1,1] # 6 # nice
#a = [0,0,1, 0,1,0, 0,0,1, 0,1,1] # 5 # nice
#a = [0,0,1, 0,0,0, 0,0,1, 0,1,1] # 4
#a = [0,0,1, 0,0,0, 0,0,1, 0,1,0] # 3
#a = [0,0,1, 0,0,0, 0,0,1, 0,0,0] # 2
#a = [0,0,1, 0,0,0, 0,0,0, 0,0,0] # 1
#a = [1,0,0, 0,0,0, 0,0,0, 0,0,0] # FOR SYNC
#a = [1,0,0, 1,0,0, 1,0,0, 1,0,0] # FOR SYNC
n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2] #original
/ exploring chain methods /
# n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].reverse # nice
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].shuffle
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].shuffle.take(2)
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].shuffle.take(5)
# n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].take(2)
# n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].take(3)
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].take(5) # nice A1 !!
# n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].take(5).reverse # nice A2
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].take(5).shuffle
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].pick(2)
# n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].sort
# n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].sort.reverse #nice nice A3
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].pick
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].drop(3)
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].drop(7)
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].drop(7).shuffle # nice
#n = [-7,-5,0, 2,3,-5, -7,2,0, -5,3,2].drop(4).shuffle.sort
#https://sonic-pi.net/tutorial.html#section-8-5
#Here’s a list of the available chain methods for you to play with:
#.reverse - returns a reversed version of the ring
#.sort - creates a sorted version of the ring
#.shuffle - creates a shuffled version of the ring
#.pick(3) - returns a ring with the results of calling .choose 3 times
#.pick - similar to .pick(3) only the size defaults to the same as the original ring
#.take(5) - returns a new ring containing only the first 5 elements
#.drop(3) - returns a new ring with everything but the first 3 elements
## ## Doesn't work here?
##.butlast - returns a new ring with the last element missing
##.drop_last(3) - returns a new ring with the last 3 elements missing
##.take_last(6)- returns a new ring with only the last 6 elements
##.stretch(2) - repeats each element in the ring twice
##.repeat(3) - repeats the entire ring 3 times
##.mirror - adds the ring to a reversed version of itself
##.reflect - same as mirror but doesn’t duplicate middle value
##.scale(2) - returns a new ring with all elements multiplied by 2 (assumes ring contains numbers only)
arpr = 64
#puts arpsynth = knit(1,arpr, 2,arpr, 3,arpr, 4,arpr,5,arpr,6,arpr,7,arpr,8,arpr).look
puts arpsynth = knit(1,arpr, 3,arpr, 7,arpr/2, 8,arpr/2, 6,arpr).look
#arpsynth = 1 # 1 3 7
# 1 original calm
# 2 +12
# 3 original + +12
# 4 piano bright echolike
# 5 piano bright echolike +12
# 6 piano bright echolike + +12
# 7 3 voices soft (with cutoff)
# 8 3 voices hard (without cutoff)
case arpsynth
when 1 # original
use_synth :saw
use_synth_defaults release: [0.7].choose, amp: a.look, cutoff: [50,60,70,80].choose # soft
play :b3+n.look # original
when 2 # +12
use_synth :saw
use_synth_defaults release: [0.7].choose, amp: a.look, cutoff: [50,60,70,80].choose # soft
play :b3+n.look+12 # +12
when 3
use_synth :saw
use_synth_defaults release: [0.7].choose, amp: a.look, cutoff: [50,60,70,80].choose # soft
play :b3+n.look # original
play :b3+n.look+12 # +12
when 4
use_synth :piano
use_synth_defaults release: [1].choose, amp: a.look#, cutoff: [50,60,70,80].choose # piano
#play :b3+n.look # original
play :b3+n.look#+12 # +12
when 5
use_synth :piano
use_synth_defaults release: [1].choose, amp: a.look#, cutoff: [50,60,70,80].choose # piano
#play :b3+n.look # original
play :b3+n.look+12 # +12
when 6
use_synth :piano
use_synth_defaults release: [1].choose, amp: a.look#, cutoff: [50,60,70,80].choose # piano
play :b3+n.look # original
play :b3+n.look+12 # +12
when 7
/ chordlike /
use_synth :saw
use_synth_defaults release: [0.7].choose, amp: a.look, cutoff: [50,60,70,80].choose # soft
play :b3+n.look # original
play :b3+n.rotate(1).look+12, pan: rdist(-1)
play :b3+n.rotate(3).look+24, pan: rdist(1)
when 8
/ chordlike /
use_synth :saw
use_synth_defaults release: [0.8].choose, amp: a.look, cutoff: [90,100].choose # hard
play :b3+n.look # original
play :b3+n.rotate(1).look+12, pan: rdist(-1)
play :b3+n.rotate(3).look+24, pan: rdist(1)
end
/ midi notes to visuals (needs to go to loopmidi or focusrite_usb_midi_1) /
##puts midi :b3+n.look, channel: 3#, port: "foo"
sleep 0.5
end
live_loop :synthcue, sync: :time do # used to cue bass to arp. I have learnt cue yet
sleep 0.5*12*2
end
/ bass /
live_loop :bass, sync: :synthcue do
# stop
tick
use_synth :fm # :b2 nice warm
#use_synth :saw # :b1 hard
use_synth :sine # original :b1 soft
use_synth_defaults attack: 0.1, sustain: 8, release: 2, cutoff: 80 # cutoff if :saw
a = 1
bass = 6
case bass
when 0
when 1
/ manual change here /
use_synth :fm # :b2 nice warm
use_synth :saw # :b1 hard
#use_synth :sine # original :b1 soft
play :b1 # almost all notes work
/ calm intro /
when 2 # calm intro :saw
use_synth :saw
play knit(:e1,a, :e1,a, :b1,a, nil,a).look
when 3 # calm intro :fm
use_synth :fm
play knit(:e1,a, :e1,a, :b1,a, nil,a).look+12
/ calm longer progession with tension /
when 4 # calm longer progession with tension :saw
use_synth :saw
play knit(:b1,a, :e1,a, :gs1,a, :g1,a, :d1,a, :fs1,a, :b1,a).look
when 5 # calm longer progession with tension :fm
use_synth :fm
play knit(:b1,a, :e1,a, :gs1,a, :g1,a, :d1,a, :fs1,a, :b1,a).look+12
when 6 # auto 4+5 nice with rest2
use_synth knit(:fm,7*a, :saw,7*a).look
play knit(:e1,a, :g1,a, :gs1,a, :a1,a, :as1,a, :b1,a, :e1,a).look+ knit(12,7*a, 0,7*a).look
end
## more ideas not used above yet
# 0) :b1 :g1 :fs1 :e1 :b2 (sine)
# 1) :b1 :e1 :b1
# 2) :b2, :e2, :fs2
# 3) :g2 :fs2 :g2 :fs2
# 4) :b2 :fs2, :gs2 :g2 :g2 :e2 :d2 (:cs2 :c2 tension) :b2(fm)
# 5) :e2 :d2 :cs2 :c2 :b2 (fm)
# 7) #sine :b1 :e1 :b1
rest = 2 #1
rest1 = 0.5*12*2*2 # original
rest2 = 0.5*12*2 # nice - a bit faster
case rest
when 1
/original/
sleep rest1# with a break between note
when 2
sleep rest2 # with a small break between note
when 3
sleep [rest1, rest2].choose # random mix of long/short rest
when 4
# sleep 0.5*12 # no break between note # NOT Aligned properly - sustain?
end
end
end #end pingpong
end #end reverb
/ drums /
live_loop :drum, sync: :synthcue do
#stop
tick
/ kick /
drum = 6 # 6+hihat is nice
case drum
when 0
when 1
sample :bd_haus, amp: 4, cutoff: 70, pan: rdist(0.25) if bools(1,0,0,0).look
when 2
sample :bd_haus, amp: 2, cutoff: 85, pan: rdist(0.5) if bools(1,0,0).look
when 3
sample :bd_haus, amp: 4, cutoff: 70, pan: rdist(0.25) if bools(1,0,0,0).look
sample :bd_haus, amp: 2, cutoff: 90, pan: rdist(0.5) if bools(1,0,0).look
when 4
sample :bd_haus, amp: 2, cutoff: 70, pan: rdist(0.25) if bools(1,0,0,0).look
sample :bd_haus, amp: 4, cutoff: [90,95,100].choose, pan: rdist(0.5) if bools(1,0,0).look
when 5
sample :bd_haus, amp: 4, cutoff: 70, pan: rdist(0.5) if spread(3,10).look
when 6 # nice ostinat with :saw :e1 and hihat + a = 6
sample :bd_haus, amp: 4, cutoff: 70, pan: rdist(0.5) if spread(3,10).look
use_synth :gnoise #:bnoise :noise :gnoise :pnoise (:gnoise is nice)
play :c2, amp: 2, pan: rdist(0.25) if bools(0,0,0,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0).look
end
/ hihat /
use_synth [:noise,:gnoise,:cnoise].look
use_synth_defaults release: [0.01,0.03,0.07].choose, amp: [[2,1,1].choose,0.25,0.25,0.5,0.25,0.25,0.25].look, pan: rdist(0.75)
play :c5
sleep 0.5
end