Last active
December 29, 2020 08:19
-
-
Save omardelarosa/168114215e9c182b9a4cc7b44300ac94 to your computer and use it in GitHub Desktop.
Markov-chain based generative Piano Music for SonicPi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 good catch! fixed.
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?
joesh1: set and get were only added in version 3 of Sonic Pi. I expect you are trying it on an earlier version.
Ah yes, I should've noted that I'm running v3.1.0
@joesh1
very nice ,wonderful job
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There is an
end
missing in line 69 to finish the live_loop :rightOtherwise some nice interesting code!