# Patterns changing gradually

**URL:** <https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599>\
**Category:** \[P\] Patreon Support\
**Created:** [January 7, 2018, 6:16pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599 "2018-01-07T18:16:33Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [January 7, 2018, 6:16pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/1 "2018-01-07T18:16:33Z")

</div>

Being interested in Minimal Music and generative art, I am looking for ways to have musical patterns evolve slowly over time. Below I tried to solve this with making a list containing all possible 3-part-patterns and setting up rules of possible successions of these patterns. Patterns with all three elements in different positions are not allowed to follow one another.

```
use_random_seed 1100

#defining the six possible variations of a 3-note-pattern with set
set :u, (ring :a3,:b3,:c4)
set :v, (ring :a3,:c4,:b3)
set :w, (ring :b3,:a3,:c4)
set :x, (ring :b3,:c4,:a3)
set :y, (ring :c4,:a3,:b3)
set :z, (ring :c4,:b3,:a3)

#setting the release of the notes
set :rel, 0.1

#setting the rhythm
set :sl, 0.125

#defining the length of each pattern
in_thread(name: :length) do
  loop do
    set :n, ([4, 8].choose)
    sleep 4
  end
end

#Choosing the variation to begin with
cue [:ua, :va, :wa, :xa, :ya, :za].choose

in_thread(name: :container) do
  #six different threads, one for each variation, defining which variations may follow the respective variation
  in_thread(name: :ua) do
    loop do
      sync :ua
      get[:n].times do
        play_pattern_timed get[:u], get[:sl], release: get[:rel]
      end
      cue [:va,:wa,:za].choose
    end
  end
  
  
  in_thread(name: :va) do
    loop do
      sync :va
      get[:n].times do
        play_pattern_timed get[:v], get[:sl], release: get[:rel]
      end
      cue [:ya,:ua,:xa].choose
    end
  end
  
  in_thread(name: :wa) do
    loop do
      sync :wa
      get[:n].times do
        play_pattern_timed get[:w], get[:sl], release: get[:rel]
      end
      cue [:ya,:ua,:xa].choose
    end
  end
  
  in_thread(name: :za) do
    loop do
      sync :za
      get[:n].times do
        play_pattern_timed get[:z], get[:sl], release: get[:rel]
      end
      cue [:ya,:ua,:xa].choose
    end
  end
  
  in_thread(name: :ya) do
    loop do
      sync :ya
      get[:n].times do
        play_pattern_timed get[:y], get[:sl], release: get[:rel]
      end
      cue [:va,:za,:wa].choose
    end
  end
  
  in_thread(name: :xa) do
    loop do
      sync :xa
      get[:n].times do
        play_pattern_timed get[:x], get[:sl], release: get[:rel]
      end
      cue [:za,:wa,:va].choose
    end
  end
end

```

The code seems to work like I intended, but I have some questions:

- To actually hear sound, I have to execute “run” twice, why?

- When using patterns with more elements, or patterns with changing number of elements, this approach does not seem the best. I would prefer to be able to single out two elements and be able to change their positions within the pattern; or one element, and change it´s pitch. How to do that?

Cheers,

Gisbert

---

<div class="post-metadata">

**Author:** ![Martin](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/martin/32/157_2.png) [@Martin](https://in-thread.sonic-pi.net/u/Martin)\
**Post date:** [January 7, 2018, 6:22pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/2 "2018-01-07T18:22:03Z")

</div>

Hi Gisbert,

welcome to the Sonic Pi community!

This is not an answer but more of a hint. @scossar has done a lot of nice stuff with Sonic Pi which definitely points into the direction you seem to be interested in. You might want to have a look: [https://soundcloud.com/simoncossar](https://soundcloud.com/simoncossar)

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [January 7, 2018, 6:23pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/3 "2018-01-07T18:23:12Z")

</div>

Hi Martin,

thanks, I will check it out!

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [January 7, 2018, 11:25pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/4 "2018-01-07T23:25:03Z")

</div>

The very same basic concept in a musically more elaborate version, adding a specific rhythm and effects to the patterns and a drumbeat.

```
use_random_seed 109

#Adding effects to the bass sound
with_fx :ixi_techno do
  with_fx :distortion do
    with_fx :wobble do
      #bass sound
      use_synth :sine
      
      #defining the six possible variations of a 3-note-pattern with set
      set :u, (ring :a1,:b1,:c2)
      set :v, (ring :a1,:c2,:b1)
      set :w, (ring :b1,:a1,:c2)
      set :x, (ring :b1,:c2,:a1)
      set :y, (ring :c2,:a1,:b1)
      set :z, (ring :c2,:b1,:a1)
      
      #setting the release of the notes
      set :rel, 0.1
      
      #setting the rhythm of the bass patterns
      set :sl, [0.375, 0.375, 0.25]
      
      
      #defining the length of each pattern
      in_thread(name: :length) do
        loop do
          set :n, ([2, 4, 8].choose)
          sleep 4
        end
      end
      
      #Choosing the variation to begin with
      cue [:ua, :va, :wa, :xa, :ya, :za].choose
      
      
      in_thread(name: :container) do
        #six different threads, one for each variation, defining which variations may follow the respective variation
        in_thread(name: :ua) do
          loop do
            sync :ua
            get[:n].times do
              play_pattern_timed get[:u], get[:sl], release: get[:rel]
            end
            cue [:va,:wa,:za].choose
            cue :beat
          end
        end
        
        
        in_thread(name: :va) do
          loop do
            sync :va
            get[:n].times do
              play_pattern_timed get[:v], get[:sl], release: get[:rel]
            end
            cue [:ya,:ua,:xa].choose
            cue :beat
          end
        end
        
        in_thread(name: :wa) do
          loop do
            sync :wa
            get[:n].times do
              play_pattern_timed get[:w], get[:sl], release: get[:rel]
            end
            cue [:ya,:ua,:xa].choose
            cue :beat
          end
        end
        
        in_thread(name: :za) do
          loop do
            sync :za
            get[:n].times do
              play_pattern_timed get[:z], get[:sl], release: get[:rel]
            end
            cue [:ya,:ua,:xa].choose
            cue :beat
          end
        end
        
        in_thread(name: :ya) do
          loop do
            sync :ya
            get[:n].times do
              play_pattern_timed get[:y], get[:sl], release: get[:rel]
            end
            cue [:va,:za,:wa].choose
            cue :beat
          end
        end
        
        in_thread(name: :xa) do
          loop do
            sync :xa
            get[:n].times do
              play_pattern_timed get[:x], get[:sl], release: get[:rel]
            end
            cue [:za,:wa,:va].choose
            cue :beat
          end
        end
      end
    end
  end
end

#Accompanying beat
in_thread(name: :beat) do
  sync :beat
  loop do
    get[:n].times do
      sample :drum_heavy_kick
      sleep 0.25
      sample :drum_cymbal_pedal
      sleep 0.25
      sample :drum_bass_soft
      sample :drum_heavy_kick
      sleep 0.25
      sample :drum_cymbal_pedal
      sleep 0.125
      sample :drum_cymbal_closed
      sleep 0.125
    end
  end
end
```

---

<div class="post-metadata">

**Author:** ![robin.newman](https://avatars.discourse-cdn.com/v4/letter/r/76d3ee/32.png) [@robin.newman](https://in-thread.sonic-pi.net/u/robin.newman)\
**Post date:** [January 8, 2018, 3:26pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/5 "2018-01-08T15:26:52Z")

</div>

HI Gisbert and welcome.  
You have some nice ideas here. I think the reason you need to run twice is that the cue is sent b efore the sync is set up, and therefore missed the first time round. If you move the cue line to the end and put a small delay before calling it all will b e well on the first run.

```ruby
#moved to the end
sleep 0.01 #small delay to make sure that sync is waiting before the cues is issued.
#Choosing the variation to begin with
cue [:ua, :va, :wa, :xa, :ya, :za].choose

```

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [January 8, 2018, 3:49pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/6 "2018-01-08T15:49:32Z")

</div>

Hi Robin,  
thanks for the clarification! This way it works fine 🙂

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [January 11, 2018, 11:52pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/7 "2018-01-11T23:52:42Z")

</div>

This time I´m not actually seeking help, but want to post a new approach to the same question - generating patterns that slowly evolve over time. This version is partly inspired by the App Nodebeat and the concept of having one sender triggering multiple ‘sound satellites’.

Also, the whole topic is in context of my research on forms of ‘Minimal Improvisation’.  
[http://www.phyla.info/?portfolio=minimal-improvisation](http://www.phyla.info/?portfolio=minimal-improvisation)

Thanks to @Martin for bringing up an elegant solution to create indeterminism in this thread:

> [@More real randomization](http://in-thread.sonic-pi.net/t/more-real-randomization/608):
>
> Hi, I have opened an issue ticket in Github, and only later discovered this forum. My ticket is rather a question, so admins, please feel free to just close it on github if you will. Here I paste what I wrote there: I have read documentation and tutorials on random methods. I do understand that reproducible behavior is in the philosophy of Sonic pi. However I am trying to come up with a way to get random number on each run. It does not have to be random per se, I only want it appear random, i…

I like it so much when I do NOT know what pattern will come up when I press start.

I´m very happy with this code as is, but I´m also interested in your feedback.

```
#Evolving Patterns
t = Time.now.to_i
use_random_seed t
puts rand

use_synth :sine

in_thread do
  loop do
    set :teim, (ring 0.125, 0.25, 0.375).choose
    sleep rrand_i(64, 256)
  end
end

in_thread do
  loop do
    set :taim, (ring 0.5, 0.75, 1, 1.5, 2).choose
    sleep rrand_i(64, 256)
  end
end

#Sending out regular cues
in_thread do
  loop do
    cue :zakkk
    cue :pakkk
    cue :rakkk
    cue :rikkk
    sleep get[:taim]
  end
end

#Adding individual delay to be applied to each sound creates a rhythmic pattern
in_thread do
  loop do
    #Choosing the delay which is actually applied below
    set :wa, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
    #After some time, the delay is changed, thus the pattern changes
    sleep rrand_i(16, 256)
  end
end

in_thread do
  loop do
    set :wo, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
    sleep rrand_i(16, 256)
  end
end

in_thread do
  loop do
    set :wu, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
    sleep rrand_i(16, 256)
  end
end

in_thread do
  loop do
    set :wi, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
    sleep rrand_i(16, 256)
  end
end

in_thread do
  loop do
    sync :zakkk
    #The choosen amount of delay is applied
    wait get[:wa]
    #The sound is played
    play 66, amp: rrand(0.1, 1), release: rrand(0.1, 1)
  end
end

in_thread do
  loop do
    sync :pakkk
    wait get[:wo]
    play 68, amp: rrand(0.1, 1), release: rrand(0.1, 1)
  end
end

in_thread do
  loop do
    sync :rakkk
    wait get[:wu]
    play 59, amp: rrand(0.1, 1), release: rrand(0.1, 1)
  end
end

in_thread do
  loop do
    sync :rikkk
    wait get[:wi]
    play 61, amp: rrand(0.1, 1), release: rrand(0.1, 1)
  end
end

```

Some things I have in mind to add in the future:

- Change not only rhythm over time but also pitch
- Refine the variations of dynamics, these might also be subject to long-term changes or to patterns of accent
- Combine this way to create change with ways to create large scale form, that is mechanisms that cause repetion of certain developements
- Combine this with interactive mechanisms, for example have the tempo of movements influence the tempo of pattern changes

Also, instead of pitches, it is interesting to use drum samples or send midi to another device. I had some fun tweaking sounds in Ableton live while Sonic Pi served as the sequencer.

---

<div class="post-metadata">

**Author:** ![Martin](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/martin/32/157_2.png) [@Martin](https://in-thread.sonic-pi.net/u/Martin)\
**Post date:** [January 14, 2018, 1:09pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/8 "2018-01-14T13:09:31Z")

</div>

Hi Gisbert,

I see that you use `in_thread` and `loop do`. As I understand you could replace this with the `live_loop` because essentially it is a combination of both (even though it does a bit more namely not create a new thread when evaluating again but update the current running ones).

You can put the sync as an option into the `live_loop` line which means: synchronise once the referenced `live_loop` has started (see the Sonic Pi tutorial or e. g. [https://github.com/mbutz/sonic-pi-resources/blob/master/control\_rhythmic\_and\_melodic\_processes/synchronisation-of-live-loops.rb](https://github.com/mbutz/sonic-pi-resources/blob/master/control_rhythmic_and_melodic_processes/synchronisation-of-live-loops.rb)):

```ruby
live_loop :a do
  # make something
end

live_loop :b, sync: :a do
  # make something else in sync with :a
end
```

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [January 14, 2018, 3:23pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/9 "2018-01-14T15:23:07Z")

</div>

Hi Martin,  
supercool, thanks!

The sync & cue-examples did not use live\_loop so I hesitated to use it.  
But it´s really great to be able to change parameters while running live\_loops!

I did an updated version, also applying slow random change to the pitches:

```
#Evolving Patterns
t = Time.now.to_i
use_random_seed t
puts rand

use_synth :sine

#Setting the minimum rhythmic unit
live_loop :define_delay do
  set :teim, (ring 0.125, 0.25, 0.375).choose
  sleep rrand_i(64, 256)
end

#Setting the length of the repeated pattern
live_loop :define_phrase do
  set :taim, (ring 0.5, 0.75, 1, 1.5, 2).choose
  sleep rrand_i(64, 256)
end

#Setting the four different pitches
live_loop :setting_pitch_one do
  set :pitch_one, rrand(40, 85)
  sleep rrand_i(64, 512)
end

live_loop :setting_pitch_two do
  set :pitch_two, rrand(40, 85)
  sleep rrand_i(64, 512)
end

live_loop :setting_pitch_three do
  set :pitch_three, rrand(40, 85)
  sleep rrand_i(64, 512)
end

live_loop :setting_pitch_four do
  set :pitch_four, rrand(40, 85)
  sleep rrand_i(64, 512)
end

#Sending out regular cues
live_loop :cues do
  cue :zakkk
  cue :pakkk
  cue :rakkk
  cue :rikkk
  sleep get[:taim]
end

#Adding the individual delay defined above to be applied to each sound creates a rhythmic pattern
live_loop :chooser_one do
  #Choosing the delay which is actually applied below
  set :wa, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
  #After some time, the delay is changed, thus the pattern changes
  sleep rrand_i(16, 256)
end

live_loop :chooser_two do
  set :wo, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
  sleep rrand_i(16, 256)
end

live_loop :chooser_three do
  set :wu, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
  sleep rrand_i(16, 256)
end

live_loop :chooser_four do
  set :wi, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
  sleep rrand_i(16, 256)
end

live_loop :sound_one do
  sync :zakkk
  #The choosen amount of delay is applied
  wait get[:wa]
  #The sound is played
  play get[:pitch_one], amp: rrand(0.1, 1), release: rrand(0.1, 0.8)
end

live_loop :sound_two do
  sync :pakkk
  wait get[:wo]
  play get[:pitch_two], amp: rrand(0.1, 1), release: rrand(0.1, 0.8)
end

live_loop :sound_three do
  sync :rakkk
  wait get[:wu]
  play get[:pitch_three], amp: rrand(0.1, 1), release: rrand(0.1, 0.8)
end

live_loop :sound_four do
  sync :rikkk
  wait get[:wi]
  play get[:pitch_four], amp: rrand(0.1, 1), release: rrand(0.1, 0.8)
end
```

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [June 10, 2018, 8:43pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/10 "2018-06-10T20:43:32Z")

</div>

I kept working on this topic, so here is some context why this is so interesting to me:  
[http://www.phyla.info/?p=2845](http://www.phyla.info/?p=2845)

Some audio examples - drums:

[iframe][https://hearthis.at/embed/2078657/transparent\_black/?hcolor=&color=&style=2&block\_size=2&block\_space=1&background=1&waveform=0&cover=0&autoplay=0&css=[/iframe]](https://hearthis.at/embed/2078657/transparent_black/?hcolor=&color=&style=2&block_size=2&block_space=1&background=1&waveform=0&cover=0&autoplay=0&css=%5B/iframe%5D)

Sine sounds:

[iframe][https://hearthis.at/embed/2078393/transparent\_black/?hcolor=&color=&style=2&block\_size=2&block\_space=1&background=1&waveform=0&cover=0&autoplay=0&css=[/iframe]](https://hearthis.at/embed/2078393/transparent_black/?hcolor=&color=&style=2&block_size=2&block_space=1&background=1&waveform=0&cover=0&autoplay=0&css=%5B/iframe%5D)

Sines & Drums:

[iframe][https://hearthis.at/embed/2078659/transparent\_black/?hcolor=&color=&style=2&block\_size=2&block\_space=1&background=1&waveform=0&cover=0&autoplay=0&css=[/iframe]](https://hearthis.at/embed/2078659/transparent_black/?hcolor=&color=&style=2&block_size=2&block_space=1&background=1&waveform=0&cover=0&autoplay=0&css=%5B/iframe%5D)

[iframe][https://hearthis.at/embed/2078658/transparent\_black/?hcolor=&color=&style=2&block\_size=2&block\_space=1&background=1&waveform=0&cover=0&autoplay=0&css=[/iframe]](https://hearthis.at/embed/2078658/transparent_black/?hcolor=&color=&style=2&block_size=2&block_space=1&background=1&waveform=0&cover=0&autoplay=0&css=%5B/iframe%5D)

Code for sines & drums:

```
#Evolving synth and drums asymetrical pattern length 2
t = Time.now.to_i
use_random_seed t
puts rand

use_synth :sine

use_bpm 52

#Setting the minimum rhythmic unit
live_loop :define_delay do
  set :teim, (ring 0.1, 0.2, 0.3, 0.4).choose
  sleep rrand_i(1, 256)
end

#Setting the lengths of the repeated patterns
#Symetric patterns
live_loop :define_phrase1 do
  set :taim1, (ring 0.3, 0.4, 0.6, 1.2, 2.4).choose
  sleep rrand_i(1, 256)
end

live_loop :define_phrase2 do
  set :taim2, (ring 0.3, 0.4, 0.6, 1.2, 2.4).choose
  sleep rrand_i(1, 256)
end

#Asymetric pattern
live_loop :define_phrase3 do
  if rand < 0.5
  then
    if rand < 0.5
    then
      set :taim3a, 1
      set :taim3b, 1.4
    else
      set :taim3a, 1.4
      set :taim3b, 1
    end
  else
    if rand < 0.5
    then
      set :taim3a, 0.5
      set :taim3b, 0.7
    else
      set :taim3a, 0.7
      set :taim3b, 0.5
    end
  end
  sleep rrand_i(1, 256)
end

live_loop :define_phrase4 do
  if rand < 0.5
    if rand < 0.5
    then
      set :taim4a, 1
      set :taim4b, 1.4
    else
      set :taim4a, 1.4
      set :taim4b, 1
    end
  else
    if rand < 0.5
    then
      set :taim4a, 0.5
      set :taim4b, 0.7
    else
      set :taim4a, 0.7
      set :taim4b, 0.5
    end
  end
  sleep rrand_i(1, 256)
end

#Setting the different pitches
live_loop :setting_pitch_one do
  set :pitch_one, rrand(40, 85)
  sleep rrand_i(1, 512)
end

live_loop :setting_pitch_two do
  set :pitch_two, rrand(40, 85)
  sleep rrand_i(1, 512)
end

live_loop :setting_pitch_three do
  set :pitch_three, rrand(40, 85)
  sleep rrand_i(1, 512)
end

live_loop :setting_pitch_four do
  set :pitch_four, rrand(40, 85)
  sleep rrand_i(1, 512)
end

#Sending out regular cues
live_loop :cue1 do
  cue :zakkk
  sleep get[:taim1]
end

live_loop :cue2 do
  cue :pakkk
  sleep get[:taim2]
end

live_loop :cue3 do
  cue :rakkk
  sleep get[(ring :taim3a, :taim3b).tick]
end

live_loop :cue4 do
  cue :rikkk
  sleep get[(ring :taim4a, :taim4b).tick]
end

#Adding the individual delay defined above to be applied to each sound creates a rhythmic pattern
live_loop :chooser_one do
  #Choosing the delay which is actually applied below
  set :wa, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
  #After some time, the delay is changed, thus the pattern changes
  sleep rrand_i(16, 256)
end

live_loop :chooser_two do
  set :wo, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
  sleep rrand_i(16, 256)
end

live_loop :chooser_three do
  set :wu, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
  sleep rrand_i(16, 256)
end

live_loop :chooser_four do
  set :wi, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:teim]
  sleep rrand_i(16, 256)
end

live_loop :releaserange do
  set :relmin, 0.1
  set :relmax, 0.4
  sleep 4
end

with_fx :distortion, distort: 0.1 do
  live_loop :sound_one do
    sync :zakkk
    #The choosen amount of delay is applied
    wait get[:wa]
    #The sound is played
    play get[:pitch_one], amp: rrand(0.1, 1), release: rrand(get[:relmin], get[:relmax])
  end
  
  live_loop :sound_two do
    sync :pakkk
    #The choosen amount of delay is applied
    wait get[:wo]
    #The sound is played
    play get[:pitch_two], amp: rrand(0.1, 1), release: rrand(get[:relmin], get[:relmax])
  end
  
  live_loop :sound_three do
    sync :rakkk
    #The choosen amount of delay is applied
    wait get[:wu]
    #The sound is played
    play get[:pitch_three], amp: rrand(0.1, 1), release: rrand(get[:relmin], get[:relmax])
  end
  
  live_loop :sound_four do
    sync :rikkk
    #The choosen amount of delay is applied
    wait get[:wi]
    #The sound is played
    play get[:pitch_four], amp: rrand(0.1, 1), release: rrand(get[:relmin], get[:relmax])
  end
end

#Setting the minimum rhythmic unit
live_loop :define_drumdelay do
  set :drumteim, (ring 0.1, 0.2, 0.3, 0.4).choose
  sleep rrand_i(1, 256)
end

#Setting the lengths of the repeated patterns
#Symetric patterns
live_loop :define_drumphrase1 do
  set :drumtaim1, (ring 0.3, 0.4, 0.6, 1.2, 2.4).choose
  sleep rrand_i(1, 256)
end

live_loop :define_drumphrase2 do
  set :drumtaim2, (ring 0.3, 0.4, 0.6, 1.2, 2.4).choose
  sleep rrand_i(1, 256)
end

#Asymetric pattern
live_loop :define_drumphrase3 do
  if rand < 0.5
    if rand < 0.5
    then
      set :drumtaim3a, 1
      set :drumtaim3b, 1.4
    else
      set :drumtaim3a, 1.4
      set :drumtaim3b, 1
    end
  else
    if rand < 0.5
    then
      set :drumtaim3a, 0.5
      set :drumtaim3b, 0.7
    else
      set :drumtaim3a, 0.7
      set :drumtaim3b, 0.5
    end
  end
  sleep rrand_i(1, 256)
end

live_loop :define_drumphrase4 do
  if rand < 0.5
    if rand < 0.5
    then
      set :drumtaim4a, 1
      set :drumtaim4b, 1.4
    else
      set :drumtaim4a, 1.4
      set :drumtaim4b, 1
    end
  else
    if rand < 0.5
    then
      set :drumtaim4a, 0.5
      set :drumtaim4b, 0.7
    else
      set :drumtaim4a, 0.7
      set :drumtaim4b, 0.5
    end
  end
  sleep rrand_i(1, 256)
end

#Sending out regular cues
live_loop :drumcue1 do
  cue :drumzakkk
  sleep get[:drumtaim1]
end

live_loop :drumcue2 do
  cue :drumpakkk
  sleep get[:drumtaim2]
end

live_loop :drumcue3 do
  cue :drumrakkk
  sleep get[(ring :drumtaim3a, :drumtaim3b).tick]
end

live_loop :drumcue4 do
  cue :drumrikkk
  sleep get[(ring :drumtaim4a, :drumtaim4b).tick]
end

#Adding the individual delay defined above to be applied to each sound creates a rhythmic pattern
live_loop :drumchooser_one do
  #Choosing the delay which is actually applied below
  set :drumwa, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:drumteim]
  #After some time, the delay is changed, thus the pattern changes
  sleep rrand_i(16, 256)
end

live_loop :drumchooser_two do
  set :drumwo, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:drumteim]
  sleep rrand_i(16, 256)
end

live_loop :drumchooser_three do
  set :drumwu, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:drumteim]
  sleep rrand_i(16, 256)
end

live_loop :drumchooser_four do
  set :drumwi, (ring 0, 1, 2, 3, 4, 5, 6, 7).choose*get[:drumteim]
  sleep rrand_i(16, 256)
end

live_loop :drumreleaserange do
  set :drumrelmin, 0.1
  set :drumrelmax, 0.4
  sleep 4
end

live_loop :drumsound_one do
  sync :drumzakkk
  #The choosen amount of delay is applied
  wait get[:drumwa]
  #The sound is played
  sample :drum_bass_soft
end

live_loop :drumsound_two do
  sync :drumpakkk
  wait get[:drumwo]
  sample :drum_cymbal_pedal
end

live_loop :drumsound_three do
  sync :drumrakkk
  wait get[:drumwu]
  sample :drum_heavy_kick
end

live_loop :drumsound_four do
  sync :drumrikkk
  wait get[:drumwi]
  sample :drum_cymbal_closed
end

```

Enjoy!

---

<div class="post-metadata">

**Author:** ![nabisco](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/nabisco/32/616_2.png) [@nabisco](https://in-thread.sonic-pi.net/u/nabisco)\
**Post date:** [June 19, 2018, 2:35pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/11 "2018-06-19T14:35:06Z")

</div>

@Gisbert Thanks for sharing! I’ve been working on different approaches to generative music myself using state machines / `set` / `get`, which really open up quite a lot of possibilities. I like how you are using these SonicPi features as well in your music. Your approach here is quite novel.

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [June 19, 2018, 3:34pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/12 "2018-06-19T15:34:08Z")

</div>

@nabisco Thanks for your kind words! What are state machines?

---

<div class="post-metadata">

**Author:** ![nabisco](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/nabisco/32/616_2.png) [@nabisco](https://in-thread.sonic-pi.net/u/nabisco)\
**Post date:** [June 19, 2018, 5:01pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/13 "2018-06-19T17:01:51Z")

</div>

@Gisbert a state machine is a model of computation and is often illustrated like:

![](https://dub1.discourse-cdn.com/flex017/uploads/sonic_pi/original/1X/8c5653d02b7329707a0f72ff822306a1fa3911ab.jpg)

However, in code, it can be thought of as a set of rules that govern how one “state” changes into another. In SonicPi terms, you could think of something like this as a state machine:

```ruby
# Initial state
set :current_state, 0

NOTES = [:c4, :d4, :e4, :f4, :g4]

# State machine rules
RULES = {
  0 => 1,
  1 => 2,
  2 => 3,
  3 => 4,
  4 => 0
}

live_loop :update_state do
  # get current state value -- 0 on the first run
  s = get[:current_state]
  play NOTES[s]
  
  # update to next state
  set :current_state, RULES[s]
  
  sleep 1
end

```

This represents a “cycle” that plays each note in `NOTES` once in a sort of loop. Like this:

![49%20PM](https://europe1.discourse-cdn.com/flex017/uploads/sonic_pi/original/1X/80b8d94c6dcd15817a7c3458061a8a903dc51f22.png)

There are a lot of different types of state machines, though, and most are “branching” and often non-cyclical. Here is a “branching” state machine that can go 1 of 3 possible directions on each state change:

```ruby
# Initial state
set :current_state, 0

NOTES = [:c4, :d4, :e4, :f4, :g4]

# State machine rules
RULES = {
  0 => [1,2,3],
  1 => [2,3,4],
  2 => [3,4,0],
  3 => [4,0,1],
  4 => [0,1,2]
}

live_loop :update_state do
  # get current state value -- 0 on the first run
  s = get[:current_state]
  play NOTES[s]
  
  # update to next state
  set :current_state, RULES[s].choose
  
  sleep 1
end

```

That second one looks more like this:  
 ![28%20PM](https://europe1.discourse-cdn.com/flex017/uploads/sonic_pi/original/1X/459d5a492a73519fa7886cfc19daeaa472c4cc45.jpg)

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [June 20, 2018, 7:47am UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/14 "2018-06-20T07:47:42Z")

</div>

Cool! Thanks for elaborating!  
I will need some time to check this out.

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [June 20, 2018, 10:02pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/15 "2018-06-20T22:02:49Z")

</div>

Got it, very interesting!

Now heading to your blog entry on Markov Chain Rhythms, cool stuff, thanks for sharing 😄

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [June 20, 2018, 11:41pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/16 "2018-06-20T23:41:46Z")

</div>

Your second example is very inspiring.

I added rhythm, modified the scale and narrowed down the choices to get a more specific melodic character:

> # Initial state
> 
> use\_random\_seed 929
> 
> set :current\_state, 0
> 
> NOTES = [:c4, :eb4, :f4, :g4, :bb4]  
> INTERONSET = [0.25, 0.25, 0.25, 0.5, 0.5]
> 
> # State machine rules
> 
> RULES = {  
> 0 =\> [1,2],  
> 1 =\> [3,4],  
> 2 =\> [1,3,4],  
> 3 =\> [4,0],  
> 4 =\> [0,1,2]  
> }
> 
> live\_loop :update\_state do
> 
> # get current state value – 0 on the first run
> 
> s = get[:current\_state]  
> play NOTES[s], release: rrand(0.1, 0.5)  
> sleep INTERONSET[s]
> 
> # update to next state
> 
> set :current\_state, RULES[s].choose
> 
> end

---

<div class="post-metadata">

**Author:** ![nabisco](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/nabisco/32/616_2.png) [@nabisco](https://in-thread.sonic-pi.net/u/nabisco)\
**Post date:** [June 21, 2018, 1:50pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/17 "2018-06-21T13:50:33Z")

</div>

@Gisbert this sounds awesome! I like the randomization of the durations added in there too and the updates to the notes set. Def. gives it a lot more character. 😃

---

<div class="post-metadata">

**Author:** ![Gisbert](https://avatars.discourse-cdn.com/v4/letter/g/d6d6ee/32.png) [@Gisbert](https://in-thread.sonic-pi.net/u/Gisbert)\
**Post date:** [June 21, 2018, 10:53pm UTC](https://in-thread.sonic-pi.net/t/patterns-changing-gradually/599/18 "2018-06-21T22:53:36Z")

</div>

@nabisco Thanks, glad you like it!
