# Sharing Code: Polyrhythm

**URL:** <https://in-thread.sonic-pi.net/t/sharing-code-polyrhythm/6838>\
**Category:** Creations & Ideas\
**Created:** [June 8, 2022, 9:17pm UTC](https://in-thread.sonic-pi.net/t/sharing-code-polyrhythm/6838 "2022-06-08T21:17:07Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![j0le](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/j0le/32/769_2.png) [@j0le](https://in-thread.sonic-pi.net/u/j0le)\
**Post date:** [June 8, 2022, 9:17pm UTC](https://in-thread.sonic-pi.net/t/sharing-code-polyrhythm/6838/1 "2022-06-08T21:17:07Z")

</div>

Hello everyone!

I’d like to share some code I wrote, and tell a little story.

Do you know polyrhythms? It’s really fun to play them with your hands on random sound-making things.

I wanted to practice them and watched some cool Videos by Adam Neely to get into it again:

- “7:11 Polyrhythms” [7:11 Polyrhythms - YouTube](https://www.youtube.com/watch?v=U9CgR2Y6XO4)
- “Polyrhythmic Juggling (with Paul Davids)” [Polyrhythmic Juggling (with Paul Davids) - YouTube](https://www.youtube.com/watch?v=wEPu8rEYQJY)

After some practicing of the three-against-four (3:4) rhythm I had an idea:  
Let’s say, we play the slower 1/3 notes with the left hand and the faster 1/4 notes with the right hand.  
Then we stop playing with the left had and just continue to play with the right hand.  
The right hand continues in the same tempo for some time and we forget everything we played so far.  
We just hear the steady beat. Now we interpret the movement of the right hand as 1/3 notes, but the tempo of the right hand is still the same. Then we play 1/4 notes with the left hand. The left hand is faster than the right hand, because 1/4 notes are faster than 1/3 notes.

Now we can repeat the whole process, but the roles of the right and left hand are switched.  
That way we get faster with every new cycle – faster and faster.  
To compensate that, we slowly get slower while playing with both hands.

I tried to put my idea into practice, but I failed. I thought: “I have to listen to this to practice it.” And the easiest method for doing this, was to implement it in Sonic-Pi. And that’s what I did.

The code can be found in this git repo on github: [polyrhythm/three-against-four.rb at main · j0le/polyrhythm · GitHub](https://github.com/j0le/polyrhythm/blob/main/three-against-four.rb)

via the perma-link of the current version: [polyrhythm/three-against-four.rb at 2187a2748134caf83456fdc2c42ce976350569ea · j0le/polyrhythm · GitHub](https://github.com/j0le/polyrhythm/blob/2187a2748134caf83456fdc2c42ce976350569ea/three-against-four.rb)

or here:

```ruby
define :my_play do |bpm, sample_sym, repeats|
  in_thread do
    with_bpm bpm do
      repeats.times do
        sample sample_sym
        sleep 1.0/repeats
      end
    end
  end
end

repeats_x = 3
repeats_y = 4

state = 1
start_bpm = 40.0
end_bpm = start_bpm*1.0*repeats_x/repeats_y
bpm = start_bpm

sound_a = :perc_snap
sound_b = :perc_snap2

live_loop :polyrythm do
  with_bpm bpm do
    
    if state == 1
      
      if bpm == start_bpm
        sample :perc_bell, amp: 0.5
      end
      
      my_play bpm, sound_a, repeats_x
      my_play bpm, sound_b, repeats_y
      
      getting_faster = start_bpm < end_bpm
      
      if (getting_faster && (bpm >= end_bpm)) || (!getting_faster && (bpm <= end_bpm))
        state = 2
        bpm = end_bpm
      else
        bpm += (end_bpm - start_bpm)/6.0
      end
      
    elsif state == 2
      sample :perc_bell, amp: 0.5
      sample sound_a
      my_play bpm, sound_b, repeats_y
      
      bpm = start_bpm
      state=3
      
    elsif state == 3
      sample :perc_bell, amp: 0.5
      my_play bpm, sound_b, repeats_x
      
      # swap sounds
      helper = sound_a
      sound_a = sound_b
      sound_b = helper
      
      state=1
    else
      # alarm
      my_play bpm*2, :perc_bell, 7
      
    end
    
    sleep 1
  end
end

```

It’s a state machine. What do you think of it?  
Maybe I can use some other techniques. For example rings.

Anyway – I have some plans: I want to add some more states and fade the sounds in and out.

And that’s it for now. Maybe I add some more thoughts later.

— Ole

---

<div class="post-metadata">

**Author:** ![hitsware](https://avatars.discourse-cdn.com/v4/letter/h/a9adbd/32.png) [@hitsware](https://in-thread.sonic-pi.net/u/hitsware)\
**Post date:** [June 10, 2022, 5:52am UTC](https://in-thread.sonic-pi.net/t/sharing-code-polyrhythm/6838/2 "2022-06-10T05:52:49Z")

</div>

The ’ use\_bpm ’ and ’ live\_loop ’ used together  
make SPi a natural for polyrhythms …  
i.e…

```ruby
use_bpm A
Live_loop :a do
blah

use_bpm B
Live_loop :b do
blah

```

---

<div class="post-metadata">

**Author:** ![shemp](https://avatars.discourse-cdn.com/v4/letter/s/ba8739/32.png) [@shemp](https://in-thread.sonic-pi.net/u/shemp)\
**Post date:** [June 11, 2022, 1:01am UTC](https://in-thread.sonic-pi.net/t/sharing-code-polyrhythm/6838/3 "2022-06-11T01:01:08Z")

</div>

Just for fun: 🙂

```ruby
speedy = (line Math::log(90), Math::log(900), steps: 128).map {|x| Math.exp(x)}
use_bpm :link
in_thread do
  loop do
    set_link_bpm! speedy.ring.reflect[tick]
    sleep 1
  end
end

CHORD = (
  [55, 58, 62]*4+
  [54, 60, 57, 62]*3+
  [55, 58, 62]*4+
  [53, 57, 60]*4+
  [53, 58, 62]*4+
  [53, 57, 60]*4+
  [55, 58, 62]*4+
  [60,54,57,62]*3
).ring
set :foo, 0

def gensym()
  "#{tick(:g)}"
end

define :launch do |n|
  live_loop gensym do
    t = 4.0
    synth :bass_foundation, amp: 0.6, note: CHORD[get(:foo)], sustain: 0.3, release: 0.1
    set :foo, get(:foo)+1
    sleep t/n
  end
end

with_fx :flanger do
  with_fx :reverb do
    with_fx :bitcrusher, cutoff: 100 do
      with_fx :pan, pan: -1 do
        launch(4.05)
      end
      with_fx :pan, pan: 1 do
        launch(3)
      end
    end
  end
end

```

---

<div class="post-metadata">

**Author:** ![shemp](https://avatars.discourse-cdn.com/v4/letter/s/ba8739/32.png) [@shemp](https://in-thread.sonic-pi.net/u/shemp)\
**Post date:** [June 11, 2022, 5:09am UTC](https://in-thread.sonic-pi.net/t/sharing-code-polyrhythm/6838/4 "2022-06-11T05:09:41Z")

</div>

You can get different rhythms by changing the parameters:

```ruby
use_bpm 300
CHORD = (
  [55, 58, 62]*4+
  [50,54,57,60]*3+
  [55, 58, 62]*4+
  [53, 57, 60]*4+
  [58, 53, 62]*4+
  [53, 57, 60]*4+
  [55, 58, 62]*4+
  [50,54,57,60]*3
).ring
set :foo, 0

def gensym()
  "#{tick(:g)}"
end

define :launch do |n|
  live_loop gensym do
    t = 4.0
    synth :bass_foundation, amp: 0.6, note: CHORD[get(:foo)], sustain: 0.3, release: 0.1
    set :foo, get(:foo)+1
    sleep t/n
  end
end

with_fx :flanger do
  with_fx :reverb do
    with_fx :bitcrusher, cutoff: 100 do
      launch(6)
      with_fx :pan, pan: -1 do
        launch(6.01)
      end
      with_fx :pan, pan: 1 do
        launch(3)
      end
    end
  end
end

```

```ruby
use_bpm 100
CHORD = (
  [55, 58, 62]*4+
  [50,54,57,60]*3+
  [55, 58, 62]*4+
  [53, 57, 60]*4+
  [58, 53, 62]*4+
  [53, 57, 60]*4+
  [55, 58, 62]*4+
  [50,54,57,60]*3
).ring
set :foo, 0

def gensym()
  "#{tick(:g)}"
end

define :launch do |n|
  live_loop gensym do
    t = 4.0
    synth :bass_foundation, amp: 0.6, note: CHORD[get(:foo)], sustain: 0.3, release: 0.1
    set :foo, get(:foo)+1
    sleep t/n
  end
end

with_fx :flanger do
  with_fx :reverb do
    with_fx :bitcrusher, cutoff: 100 do
      
      with_fx :pan, pan: -1 do
        launch(7.01)
      end
      with_fx :pan, pan: 1 do
        launch(11.01)
      end
    end
  end
end

```

---

<div class="post-metadata">

**Author:** ![nlb](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/nlb/32/997_2.png) [@nlb](https://in-thread.sonic-pi.net/u/nlb)\
**Post date:** [June 11, 2022, 7:37am UTC](https://in-thread.sonic-pi.net/t/sharing-code-polyrhythm/6838/5 "2022-06-11T07:37:41Z")

</div>

> [@shemp](#):
>
> ```ruby
> hi
> def gensym()
> "#{tick(:g)}"
> end
> 
> ```

would you mind explain this part of you code ?

---

<div class="post-metadata">

**Author:** ![shemp](https://avatars.discourse-cdn.com/v4/letter/s/ba8739/32.png) [@shemp](https://in-thread.sonic-pi.net/u/shemp)\
**Post date:** [June 11, 2022, 12:44pm UTC](https://in-thread.sonic-pi.net/t/sharing-code-polyrhythm/6838/6 "2022-06-11T12:44:56Z")

</div>

I just did not want to type out each `live_loop` separately, so repeatedly calling `gensym` (it’s just used as a kind of macro there) outputs `"0"`, `"1"`, etc. Therefore `launch(11)`, `launch(4)` creates `live_loop_0`, `live_loop_1` and so on, just a different name every time you run it. Since this is not really “live” code you are right, you do not necessarily need named `live_loops`.
