Hexadecimal/binary rhythmic scheme


#1

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

#2

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!


#3

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

#4

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

#5

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!


#6

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:


#7

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…


#8

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

#9

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

#10

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