Skip to content

Instantly share code, notes, and snippets.

@omardelarosa
Last active December 29, 2020 08:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save omardelarosa/168114215e9c182b9a4cc7b44300ac94 to your computer and use it in GitHub Desktop.
Save omardelarosa/168114215e9c182b9a4cc7b44300ac94 to your computer and use it in GitHub Desktop.
Markov-chain based generative Piano Music for SonicPi
set :root, 60
T = 4.0
# This hash simulates a markov chain.
# Each key is the state and the array
# value represents the next state.
H = {
60 => [58, 58, 58, 55, 60, 60, 60],
58 => [60, 56, 56, 58, 60, 60],
56 => [55, 58],
55 => [60, 56, 60, 58, 58, 58, 58],
}
define :markov do |a, h|
return h[a].sample # Chooses the next state at random from hash
end
define :g do
get[:root] # simplified root note getter
end
define :s do |n|
set :root, n # simplified root note setter
end
define :r do
(Math.cos(rand(180)) * 10).to_i # simplified random cosine index
end
s1 = scale(60, :aeolian) # working scale
p = [1,0,0,0,0,0,0,0].ring # hi-hat pattern 1
p2 = [0,0,0,1].ring # hi-hat pattern 2
live_loop :beat do
sample :bd_fat, amp: 4
sleep T / 8
end
live_loop :hats do
sleep T / 16
if p2.tick == 0
sample :drum_cymbal_closed, amp: 1
else
sample :drum_cymbal_open, attack: 0.01, sustain: 0, release: 0.25
end
sleep T / 16
end
live_loop :right do
sync :beat
with_fx :reverb, mix: 0.5, room: 0.8 do
use_synth :piano
n1 = s1[r] # choose random note in scale
n2 = s1[r - 5] # choose 4th of scale
n3 = s1[r - 7] # choose 2nd of scale
play n1, amp: 4, release: 5, sustain: 5
(play n2, amp: 3, release: 5, sustain: 5) if p.tick == 1 # randomly form chords on leading edge of measure
sleep (T / 8) + (T / 16)
play n2, amp: 3, release: 5
sleep (T / 16)
play n3, amp: 3, release: 5
sleep (T / 16)
sleep (T / 8)
end
end
live_loop :left do
sync :beat
with_fx :reverb, mix: 0.8, room: 0.8 do
with_fx :echo, mix: 0.5 do
use_synth :piano
s markov(g, H) # update the state using markov chaining
play (g - 12), release: 5, amp: 2, sustain: 5
sleep T / 4 + T / 8
play (g - 5), release: 3.5, amp: 2, sustain: 5
sleep (T / 4) - (T / 8)
sleep T / 4
end
end
end
sb = (20..150).ring.mirror # simulate fade-up -> fade-down
live_loop :subass do
with_fx :reverb, mix: 0.5 do
with_fx :distortion, distort: (sb.tick * 0.01) do
use_synth :sine
play g, release: 15, amp: (sb.tick * 0.01) # play subbass sine
sleep T / 1
end
end
end
@rbnpi
Copy link

rbnpi commented May 24, 2018

There is an end missing in line 69 to finish the live_loop :right
Otherwise some nice interesting code!

@omardelarosa
Copy link
Author

@rbnpi good catch! fixed.

@joesh1
Copy link

joesh1 commented May 25, 2018

Just tried running the code but I get an error immediately on line 1, the post window says 'set' is an undefined method!

Any ideas?

@rbnpi
Copy link

rbnpi commented May 25, 2018

joesh1: set and get were only added in version 3 of Sonic Pi. I expect you are trying it on an earlier version.

@omardelarosa
Copy link
Author

Ah yes, I should've noted that I'm running v3.1.0 @joesh1

@sharmer156
Copy link

very nice ,wonderful job

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment