All This Static Under Clouded Skies

Trying to be less abstract, started by defining a chord progression with a set of ‘embellishment’ notes for each chord on guitar first.

#All This Static Under Clouded Skies
duration = 240.0
with_bpm 30 do
  with_fx :normaliser, level: 0.90 do
    chord1 = [:G2, :C3, :G3, :B4, :D4, :G5]
    embel1 = [:A5, :C4]
    
    chord2 = [:E3, :D4, :Fs4, :G4, :D5, :E5]
    embel2 = [:A5]
    
    
    chord3 = [:D3, :G3, :D4, :Fs4]
    embel3 = [:G4, :A4]
    
    chord4 = [:E2, :B3, :E4, :G4]
    embel4 = [:B4, :E4, :D4]
    
    chord5 = [:A3, :E3, :A4, :C4, :E4]
    embel5 = [:G4]
    
    pairs = [[chord1, embel1], [chord2, embel2], [chord3, embel3], [chord4, embel4], [chord5, embel5]]
    
    strumtimes = [4, 4, 2, 2, 4, 1, 1, 2]
    set :c, chord1
    set :e, embel1
    x=0
    live_loop :strum do
      if vt > duration * 0.95
        stop
      end
      if vt > duration * 0.01
        cue :arp
        c,e = pairs.tick(:strum)
        set :e, e
        set :c, c
        x=0.1
        l=0.1
        v=0.125
        vol = vt/duration*3
        c.each do |n|
          with_fx :distortion, amp:1, distort:0.9 do
            with_synth :dark_ambience do
              if one_in(3)
                play n, amp:vol, release: 4, ring: 1, room: 15, reverb_time: 25
              end
            end
            s = l +rand(0.02)
            sleep s
            x+=s
          end
        end
        with_fx :ixi_techno, res: vt/duration, cutoff_min: (1-vt/duration)*120 do
          if one_in(2)
            sample :loop_industrial
          end
        end
      end
      sleep strumtimes.tick(:strumtime)-x
    end
    
    arptimes = [0.25, 0.25, 0.25, 0.75]
    octaves = [0,0,0,0,0,12]
    
    live_loop :arpeggio do
      if vt > duration *0.8
        stop
      end
      if vt > duration * 0.3
        
        e = get[:e]
        c = get[:c]
        if one_in(4)
          notes = c
        else
          notes = e
        end
        with_fx :distortion, amp:1, distort:0.9 do
          with_synth :hollow do
            play notes.tick(:arpn)+octaves.tick(:oct), amp:0.5+0.5*(1-vt/duration), release: 4
            
          end
        end
      end
      sleep arptimes.tick(:arp)
    end
    
    
    emb_pitch = 0
    emb_times = [0.125, 0.125, 0.125,  1, 1]
    live_loop :embellish do
      if vt > duration*0.85
        stop
      end
      if vt > duration * 0.01
        e = get[:e]
        c = get[:c]
        if one_in(3)
          notes = e+c
        else
          notes = e
        end
        with_fx :ping_pong, mix:0.5 do
          with_synth :hollow do
            with_fx :flanger, phase: duration/20 do
              with_fx :ixi_techno, res: vt/duration, cutoff_min: (1-vt/duration)*120 do
                with_fx :reverb, room:0.7 do
                  with_fx :distortion, amp:3 do
                    play choose(notes)+emb_pitch*12, amp: 0.25+0.75*vt/duration, release: emb_times.look(:embtimes)*1.5
                  end
                end
              end
            end
          end
        end
        
        if one_in(12)
          emb_pitch += choose([-1,1,1])
          if emb_pitch < -1
            emb_pitch = 0
          end
          if emb_pitch > 2
            emb_pitch = 0
          end
        end
      end
      sleep emb_times.tick(:embtimes)+choose([0,0,0,0,1,0.25])
    end
    
    live_loop :bass do
      if vt > duration*0.9
        stop
      end
      e = get[:e]
      n=e[0]
      with_swing do
        with_synth :piano do
          play n-24, release:8, attack:1, amp: 30
        end
      end
      sleep 4
    end
    
    beepnotes = [0,1]
    live_loop :beep do
      if vt > duration * 0.2
        if vt > duration *0.9
          stop
        end
        c = get[:c]
        with_synth :beep do
          play c[beepnotes.tick(:beepnotes)]-12, amp:3
        end
      end
      sleep 0.25
    end
    
    
    beattimes = [0.25, 1, 0.25, 1, 0.25]
    live_loop :beat do
      if vt > duration * 0.3
        if vt > duration * 0.9
          stop
        end
        sample :drum_bass_hard
        with_fx :ping_pong do
        end
      end
      sleep beattimes.tick(:beat)
    end
    
    
    live_loop :b1 do
      if vt > duration * 0.9
        stop
      end
      with_fx :panslicer, phase:1, amp:0.5, mix:0.5 do
        sample :bass_thick_c, amp: (1-vt/duration)
        sleep 1
      end
    end
  end
end
3 Likes

Just had a listen. Definitely enjoyed that - nice! :slightly_smiling_face:

1 Like

Thank you for posting.
I had a listen. I did take the normaliser off as it felt a bit too overwhelming through my system,
There are some really great points here and I particularly liked the direction between 85sec - 110sec with its resolution into the major7th that felt really satisfying.

Pieces that deliberately use distortion in this way are interesting. It strikes me that there would be an interesting development for Sonic Pi to include an opt for internal feedback routing, which would allow distortion to used in an interesting way by a algorithmically controlled feedback network. Not everyone’s cup of tea but definitely interesting.

I think the aspects of your piece that confused me most were those to do with the drums. Not quite sure what they bring to the piece that it doesn’t already have. Perhaps it’s different for others?

Anyway, that aside, I enjoyed this. Thank you for sharing the code. As a new user of Sonic Pi, it helps me to see how others use it, especially the evaluation when to stop the piece. Hadn’t seen this in any other pieces, so an interesting solution.

1 Like

Thanks for your thoughtful comments.
About the drums, I agree, I’m still testing my way around the general feel i can achieve in Sonic Pi, and I’ve been playing with non-continuos drums, not sure if they worked this time. I also have issues with sound getting too saturated, hence the normalising.
Still a way to go with understanding this instrument.

I agree, I’d love to also be able to put an ‘effects loop’ in the echo, for example.

yes, I agree. When I do these sorts of things using Ableton I have limiters to catch anything that goes over a threshold, especially when using headphones.

Have you seen Bastl’s Dark Matter module? https://youtu.be/_yphwOZKev4

The drums are an interesting point to consider. Perhaps you could consider preparing a large-ish audio file of drum parts and then use onset:pick to randomly select slices? I’ve found some interesting effects using this approach:

live_loop :motionLoop do
  sample :loop_industrial, beat_stretch: [2,1,3,4,8,0.5,0.25, 0.125].choose, rate:rrand(0.25,4), onset: pick, amp: 0.7
  sleep 0.25
end

That’s an interesting way to trigger the beats. I usually try to have some sort of drum, but don’t really want it to be steady or predictable, but not too random either. The first piece I made (Dropbox - You Just Have To Pay Attention 10.mp3 - Simplify your life) is probably a better example.

Yes, I like finding interesting ways. Still looking but slowly getting there. One thing that could be done is to vary the sleep times so that the drums will be less continuous i.e. make the times longer and of uneven amounts.

I see what you mean with the drum figures. In your track example you could vary with delay with specific number of repeats. You can also look at pitch bending the sample, as this can bring in some new timbres, especially when caught by the delay.

With your tracks have you thought about making them a multistage process? Design code, render to audio; design new code using the track as the sample; render etc? So your track acts as raw material at each stage and then subject this to more coding transforms to generate new outputs and then rinse and repeat? Might produce interestingly, degraded results.