Jumping off point: "Dan Gorelick Longest Night TidalCycles performance – Piano Phase"

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
3 Likes

@Relaxnow I also loved this performance by Dan. Thanks, I was testing the code in SP.

1 Like