Hexadecimal/binary rhythmic scheme

Hexadecimal/binary rhythmic scheme

Note that

“spread” example 3 in documentation

live_loop :euclid_beat do
    sample :elec_bong, amp: 1.5 if (spread 3, 8).tick
    sample :perc_snap, amp: 0.8 if (spread 7, 11).look
    sample :bd_haus, amp: 2 if (spread 1, 4).look
    sleep 0.125
  end

Binary rhythmic scheme

 # Binary rhythmic scheme
    def schr(num)
      num.split(//).collect  { |n| n == "1" }
    end
  
live_loop :euclid_beat do
    sample :elec_bong, amp: 1.5 if schr('10010010').ring.tick
    sample :perc_snap, amp: 0.8 if schr('10101101101').ring.look
    sample :bd_haus, amp: 2 if schr('1000').ring.look
    sleep 0.125
  end

Hexadecimal/binary rhythmic scheme

More efficient but less flexible because I made the choice to keep 4 bits for 1 hexadecimal.

0=0000, 1=0001, 2=0010, 3=0011
4=0100, 5=0101, 6=0110, 7=0111
8=1000, 9=1001, a=1010, b=1011
c=1100, d=1101, e=1110, f=1111

# Binary rhythmic scheme
def schr(num)
  num.split(//).collect  { |n| n == "1" }
 end

# hexadecimal/binary rhythmic scheme
# 0=0000, 1=0001, 2=0010, 3=0011 
# 4=0100, 5=0101, 6=0110, 7=0111
# 8=1000, 9=1001, a=1010, b=1011
# c=1100, d=1101, e=1110, f=1111
def schr2(num)
  num.hex.to_s(2).rjust(num.size*4, '0').split(//).collect  { |n| n == "1" }
end
    
  
live_loop :euclid_beat do
    sample :elec_bong, amp: 1.5 if schr2('92').ring.tick
    sample :perc_snap, amp: 0.8 if schr('10101101101').ring.look # 11 bits, not possible in hex because I made the choice to keep 4 bits for 1 hexadecimal
    sample :bd_haus, amp: 2 if schr2('8').ring.look
    sleep 0.125
  end
3 Likes

You may already be aware of it, but at least in regards to binary notation there’s also the built in alternative, bools - eg:

sample :elec_bong, amp: 1.5 if (bools 1, 0, 0, 1, 0, 0, 1, 0).look

Your function is definitely more compact to use though!

1 Like

No, I did not know that but hexadecimal is more efficient.

The binary was a necessary step (the “to_s (2)”) and so we understand better perhaps.

I put the “.ring” in the function, it’s better.

I also want to manage synth with different chord sequences.

Is my code correct?

use_bpm 50
# hexadecimal/binary rhythmic scheme
def schr2(num)
  num.hex.to_s(2).rjust(num.size*4, '0').split(//).collect  { |n| n == "1" }.ring
end
# 0=0000, 1=0001, 2=0010, 3=0011
# 4=0100, 5=0101, 6=0110, 7=0111
# 8=1000, 9=1001, a=1010, b=1011
# c=1100, d=1101, e=1110, f=1111

live_loop :foo do
  p1 = [chord(:a3,"major7"), chord(:fs3,"minor7"), chord(:b3,"minor7"), chord(:E3,"7")]
  p2 = [chord(:d4,"minor7"), chord(:e4,"7"), chord(:fs3,"minor7"), chord(:b3,"minor7")]
  6.times do |y| # sequences
    4.times do |x| # chords
      16.times do # samples/notes
        if y < 4
          abc=p1[x]
        else
          abc=p2[x]
        end
        sample :drum_snare_soft, amp: 1.5 if schr2('1210').tick ^ (one_in 24)   # drum
        sample :drum_cymbal_closed, amp: 0.8 if (spread 7, 11).look             # drum
        sample :bd_haus, amp: 1.5 if schr2('80').look ^ (one_in 32)             # drum
        play abc, amp: 1.5,release: 0.1 if schr2('2').look ^ (one_in 30)        # chord
        play abc.choose+12, amp: 0.7,release: 0.3 if (one_in 3)                 # solo
        play abc[0]-12, amp: 1.2,release: 0.4 if schr2('92').look ^ (one_in 12) # bass
        sleep 0.125
      end
    end
  end
end
6 Likes

That is absolutely brilliant, And with a little tweaking, it sounds
even more realistic…

Eli…

use_bpm 50
# hexadecimal/binary rhythmic scheme
def schr2(num)
  num.hex.to_s(2).rjust(num.size*4, '0').split(//).collect  { |n| n == "1" }.ring
end


live_loop :foo do
  p1 = [chord(:a3,"major7"), chord(:fs3,"minor7"), chord(:b3,"minor7"), chord(:E3,"7")]
  p2 = [chord(:d4,"minor7"), chord(:e4,"7"), chord(:fs3,"minor7"), chord(:b3,"minor7")]
  6.times do |y| # sequences
    4.times do |x| # chords
      16.times do # samples/notes
        if y < 4
          abc=p1[x]
        else
          abc=p2[x]
        end
        sample :drum_snare_soft, amp: 1.5 if schr2('1210').tick ^ (one_in 24)   # drum
        sample :drum_cymbal_closed, amp: 0.8 if (spread 7, 11).look             # drum
        sample :bd_haus, amp: 1.5 if schr2('80').look ^ (one_in 32)             # drum
        use_synth :pluck
        play abc, amp: 3,release: 0.3 if schr2('2').look ^ (one_in 30)        # chord
        use_synth :piano
        play abc.choose+12, amp: 0.7,release: 0.3 if (one_in 3)                 # solo
        use_synth :fm
        play abc[0]-12, amp: 1,release: 0.4 if schr2('92').look ^ (one_in 12) # bass
        sleep 0.125
      end
    end
  end
end
2 Likes

I agree with @Eli This is brilliant.

I have converted it for three channel midi output, and am playing it to a three manual virtual pipe organ which sounds great.
I used

define :mplay do |n,*args|
  n.to_a.each do |x|
    midi x,*args
  end
end

for the first play abc command i.e. mplay abc… and added channel: and port: settings. Otherwise the same. The other two play abc commands just play single notes so you can use straight midi here.

use_bpm 50
# hexadecimal/binary rhythmic scheme
def schr2(num)
  num.hex.to_s(2).rjust(num.size*4, '0').split(//).collect  { |n| n == "1" }.ring
end
# 0=0000, 1=0001, 2=0010, 3=0011
# 4=0100, 5=0101, 6=0110, 7=0111
# 8=1000, 9=1001, a=1010, b=1011
# c=1100, d=1101, e=1110, f=1111
use_midi_defaults port: "rbnphone bluetooth"
live_loop :foo do
  p1 = [chord(:a3,"major7"), chord(:fs3,"minor7"), chord(:b3,"minor7"), chord(:E3,"7")]
  p2 = [chord(:d4,"minor7"), chord(:e4,"7"), chord(:fs3,"minor7"), chord(:b3,"minor7")]
  6.times do |y| # sequences
    4.times do |x| # chords
      16.times do # samples/notes
        if y < 4
          abc=p1[x]
        else
          abc=p2[x]
        end
        puts abc
        
        sample :drum_snare_soft, amp: 1.5 if schr2('1210').tick ^ (one_in 24)   # drum
        sample :drum_cymbal_closed, amp: 0.8 if (spread 7, 11).look             # drum
        sample :bd_haus, amp: 1.5 if schr2('80').look ^ (one_in 32)             # drum
        mplay abc, channel: 2,sustain: 0.1 #if schr2('2').look ^ (one_in 30)        # chord
        midi abc.choose+12, channel: 1,sustain: 0.3 if (one_in 3)                 # solo
        midi abc[0]-12, channel: 3,sustain: 0.4 if schr2('92').look ^ (one_in 12) # bass
        sleep 0.125
      end
    end
  end
end

Eli’s mods for Sonic Pi also sound very very cool!

Thank you but the problem is that you have to wait for an entire cycle to see code changes.
It’s not live coding anymore :frowning:

Granted its not live coding, but then live coding is only one
aspect of using Sonic Pi. I like writing stuff that has a fixed
format. Songs that have a beginning middle and end. I
tend towards hip-hop and edm type music, and if I can
figure out the

schr2('xxxx')

required for that type of beat, this is very compact and
mutable code that will save me hours of writing live loops.

Eli…

I found a solution maybe.

Also, I tested something else in ternary, like 6/8 ^^.

use_bpm 47

# hexadecimal/binary rhythmic scheme
def schr2(num)
  num.hex.to_s(2).rjust(num.size*4, '0').split(//).collect  { |n| n == "1" }.ring
end
# 0=0000, 1=0001, 2=0010, 3=0011
# 4=0100, 5=0101, 6=0110, 7=0111
# 8=1000, 9=1001, a=1010, b=1011
# c=1100, d=1101, e=1110, f=1111

live_loop :a do #sequences
  6.times do
    X = tick; sleep 12
  end
  tick_reset
end

live_loop :b do #chords
  4.times do
    I = tick; sleep 3
  end
  tick_reset
end

live_loop :foo do #samples/notes
  chords = (ring 1, 2, 5, 1)
  if X<4
    abc=(chord_degree chords[I], :c3,:major,4)
  else
    abc=(chord_degree chords[I], :b2,:major,4)
  end
  sample :drum_snare_soft, amp: 1.5 if schr2('924').tick ^ (one_in 12)     # drum
  sample :drum_cymbal_closed, amp: 0.8 if schr2('b6d').look ^ (one_in 31)  # drum
  sample :bd_haus, amp: 1.5 if schr2('888').look ^ (one_in 32)             # drum
  use_synth :pluck
  play abc, amp: 2,release: 0.3 if schr2('8cb').look ^ (one_in 30)       # chord
  use_synth :piano
  play abc.choose+12, amp: 0.7,release: 0.3 if (one_in 3)                  # solo
  use_synth :fm
  play abc.butlast.reflect.look-12, amp: 1,release: 0.4 if schr2('924').look ^ (one_in 12) # bass
  sleep 0.125
end

I wanted to test the command “with_swing” (“heeey” ^^)

with_swing -0.1, pulse: 3 do

It’s fine but I have an error after more than 3 minutes :frowning:

Runtime Error:[buffer 7, line 35] - SonicPi::Lang::Core::TimeTravelError
Thread death +--> :live_loop_foo
Time travel error - a jump back of -0.1 is too far.
Sorry, although it would be amizing, you can't go back in time beyond the sched_ahead time of 0.5
use_bpm 65

# hexadecimal/binary rhythmic scheme
# 0=0000, 1=0001, 2=0010, 3=0011
# 4=0100, 5=0101, 6=0110, 7=0111
# 8=1000, 9=1001, a=1010, b=1011
# c=1100, d=1101, e=1110, f=1111
def schr2(num)
  num.hex.to_s(2).rjust(num.size*4, '0').split(//).collect  { |n| n == "1" }.ring
end

live_loop :a do #sequences
  6.times do
    X = tick; sleep 12
  end
  tick_reset
end

live_loop :b do #chords
  4.times do
    I = tick; sleep 3
  end
  tick_reset
end

live_loop :foo do #samples/notes
  chords = (ring 1, 2, 5, 1)
  if X<4
    abc=(chord_degree chords[I], :c3,:major,4)
  else
    abc=(chord_degree chords[I], :b2,:major,4)
  end
  puts X
  puts I
  with_swing -0.1, pulse: 3 do
    sample :drum_snare_soft, amp: 1.5 if schr2('924').tick ^ (one_in 12)     # drum
    sample :drum_cymbal_closed, amp: 1 if schr2('aaa').look ^ (one_in 24)  # drum
    sample :bd_haus, amp: 2 if schr2('888').look ^ (one_in 32)    # drum
    with_fx :bitcrusher do
      sample :bd_tek, amp: 3.5 if schr2('800').look ^ (one_in 31)    # drum
      sample :elec_hi_snare, amp: 1.5 if schr2('020').look ^ (one_in 30)    # drum
    end
    use_synth :chiplead
    play abc, amp: 1,release: 0.2 if schr2('8cb').look ^ (one_in 32)       # chord
    use_synth :dpulse
    play abc.choose+12, amp: 0.5,release: 0.3 if (one_in 3)                  # solo
    use_synth :fm
    play abc.butlast.reflect.look-12, amp: 1.2,release: 0.4 if schr2('924').look ^ (one_in 12) # bass
  end
  sleep 0.125
end

Apparently, to use “with_swing”, you have to increase the “sched_ahead_time” but after a while, it always ends up shifting and crashing anyway.

use_sched_ahead_time 2

See for yourself ^^

use_sched_ahead_time 2
use_random_seed 4
use_bpm 50

def schr2(num)
  num.hex.to_s(2).rjust(num.size*4, '0').split(//).collect  { |n| n == "1" }.ring
end

live_loop :a do #sequences
  
  6.times do; X = tick; sleep 15; end
  tick_reset
end

live_loop :b do #chords
  5.times do; I = tick; sleep 3; end
  tick_reset
end

live_loop :foo do #samples/notes
  if X<4
    chords = (ring 1, 7, 6, 2, 5)
    abc=(chord_degree chords[I], :a2,:major,4)
  else
    chords = (ring 4, 4, 5, 6, 2)
    abc=(chord_degree chords[I], :a2,:major,4)
  end
  puts I
  with_fx :slicer, phase: [0.5,0.25,0.75,0.125,0.25][I] do
    use_synth :blade
    play abc+12, amp: 1.7,attack: 0.2,release: 3 if schr2('800').look      # chord
  end
  use_synth :saw
  play abc+12, amp: 0.4,attack: 0.2,release: 3 if schr2('800').look      # chord
  with_fx :echo, phase: [0.5,0.25,0.75,0.25,0.5][I]  do
    use_synth :chiplead
    play abc, amp: 1.2 ,release: 0.2 if schr2('8cb').look ^ (one_in 32)       # chord
  end
  with_fx :reverb do
    use_synth :hollow
    play abc.reflect.look+36, amp: 2,release: 1, attack: 0, cutoff: rrand(90,110) if schr2('800').look ^ (one_in 9)                  # solo
    use_synth :pulse
    play abc[0]-12,attack: 0.05, amp: 0.7,release: 0.35, cutoff: rrand(110,120) if schr2('a22').look ^ (one_in 24) # bass
  end
  with_swing -0.125,pulse: 3 do
    sample :drum_snare_soft, amp: 1.5 if schr2('924').tick ^ (one_in 12)     # drum
    sample :drum_cymbal_closed, amp: 1 if schr2('aaa').look ^ (one_in 24)  # drum
    sample :bd_haus, amp: 2 if schr2('888').look ^ (one_in 32)    # drum
    with_fx :bitcrusher,amp: 1.3,cutoff: rrand(110,130) do
      sample :bd_tek, amp: 2 if schr2('800').look ^ (one_in 31)    # drum
      sample :elec_hi_snare, amp: 1 if schr2('020').look ^ (one_in 30)    # drum
    end
  end
  sleep 0.125
end

tuto-track

1 Like

S’funny… I played your code for about 30 mins straight, with no error…
(Win 10, 16G mem, early i7 processor, SP 3.1)

Try running it again, from a fresh start of SP. I’ve found in the past that
running other code beforehand can ‘influence’ how a track behaves.

Eli…

1 Like