Hello Sonic Pi community,
Here’s a little experiment with generative music. It’s rather monotonus, but I couldn’t figure out a way off reusing generated sections. It is also very resource intensive.
Greetings
Loop
# Melody Maker
# Coded by Loopiloop
#---options---
#set random seed. play around with this value
use_random_seed 93847
#root of the key
key_root = rrand_i(48, 60)
#quality of the key
key_qual = :major
#chord progression
chordprog = (ring :i, :v, :vi, :iv)
#---setup---
#pattern of accents for every beat
accent = (ring 1, 0, 0, 0)
#the melody is created randomly out of the first four notes of each chord
c = (ring 0, 1, 2, 3)
#generating melodies
melody_1 = c.pick(16) #square lead
melody_2 = c.pick(16) #square base
melody_3 = c.pick(16) #wave lead
#this variable is used to create random lists of boleans and for on-off patterns
ft = (ring 0, 1)
#generating rythms
onoff_1 = ft.pick(16) #square lead
onoff_2 = ft.pick(16) #square base
onoff_3 = ft.pick(16) #wave lead
onoff_4 = ft.pick(16) #drums
#define how much score a pattern gets for a note in each position
importance = (ring 4, 0, 1 ,0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0)
#add samples to list for automated sample choice and load them
drum = [:drum_bass_soft, :drum_bass_hard]
load_samples drum
#current position within the song in bars
cprogpos = 0
#current position within the song in sixteenth notes
sixteenth = 0
#offset of currently evaluated variation in relation to original pattern
evaluate_n = 0
#position in evaluated variation
evaluate_i = 0
#square lead evaluation variables
evaluate_s_1 = 0 #score of current variation
evaluate_t_1 = 0 #score of best variation
evaluate_r_1= 0 #offset of best variation
#square base evaluation variables
evaluate_s_2 = 0 #score of current variation
evaluate_t_2 = 0 #score of best variation
evaluate_r_2 = 0 #offset of best variation
#wave lead evaluation variables
evaluate_s_3 = 0 #score of current variation
evaluate_t_3 = 0 #score of best variation
evaluate_r_3 = 0 #offset of best variation
#drums evaluation variables
evaluate_s_4 = 0 #score of current variation
evaluate_t_4 = 0 #score of best variation
evaluate_r_4 = 0 #offset of best variation
#---pattern optimization---
#iterate through pattern variations
16.times do
#return to first position
evaluate_i = 0
#reset scores
evaluate_s_1 = 0 #square lead
evaluate_s_2 = 0 #square base
evaluate_s_3 = 0 #wave lead
evaluate_s_4 = 0 #drums
#iterate through positions
16.times do
#square lead
#if theres a note at the current position
if 1 == onoff_1[evaluate_n + evaluate_i]
#add importance of the current position to the score
evaluate_s_1 = evaluate_s_1 + importance[evaluate_i]
end
#square base
#if theres a note at the current position
if 1 == onoff_2[evaluate_n + evaluate_i]
#add importance of the current position to the score
evaluate_s_2 = evaluate_s_2 + importance[evaluate_i]
end
#wave lead
#if theres a note at the current position
if 1 == onoff_3[evaluate_n + evaluate_i]
#add importance of the current position to the score
evaluate_s_3 = evaluate_s_3 + importance[evaluate_i]
end
#drums
#if theres a note at the current position
if 1 == onoff_4[evaluate_n + evaluate_i]
#add importance of the current position to the score
evaluate_s_4 = evaluate_s_4 + importance[evaluate_i]
end
#move to next position
evaluate_i = evaluate_i +1
end
#square lead
#if current variant was better then the so far best variant
if evaluate_s_1 > evaluate_t_1
#set variant high score to score of current one
evaluate_t_1 = evaluate_s_1
#set offset of best variant to offset of current one
evaluate_r_1 = evaluate_n
end
#square base
#if current variant was better then the so far best variant
if evaluate_s_2 > evaluate_t_2
#set variant high score to score of current one
evaluate_t_2 = evaluate_s_2
#set offset of best variant to offset of current one
evaluate_r_2 = evaluate_n
end
#wave lead
#if current variant was better then the so far best variant
if evaluate_s_3 > evaluate_t_3
#set variant high score to score of current one
evaluate_t_3 = evaluate_s_3
#set offset of best variant to offset of current one
evaluate_r_3 = evaluate_n
end
#drums
#if current variant was better then the so far best variant
if evaluate_s_4 > evaluate_t_4
#set variant high score to score of current one
evaluate_t_4 = evaluate_s_4
#set offset of best variant to offset of current one
evaluate_r_4 = evaluate_n
end
#move to next variant
evaluate_n = evaluate_n + 1
end
#---playing the music---
#do forever
live_loop :main do
#iterate through four bars
4.times do
#iterate through sixteen sixteenth notes
16.times do
#synth for the square instuments
use_synth :chiplead
#square lead
play (chord_degree chordprog[cprogpos], key_root, key_qual)[melody_1[sixteenth]],on: onoff_1[sixteenth+evaluate_r_1], release: 0.25, amp: 0.25
#square lead base an octave lower
play (chord_degree chordprog[cprogpos], key_root, key_qual)[melody_2[sixteenth]]-12,on: onoff_2[sixteenth+evaluate_r_2], release: 0.25, amp: 0.25
#only on eighth notes
if ft[sixteenth+1]
#synth for wave lead
use_synth :chipbass
#wave lead
play (chord_degree chordprog[cprogpos], key_root, key_qual)[melody_3[sixteenth]],on: onoff_3[sixteenth+evaluate_r_3], release: 0.25, amp: 0.5
end
#drums according to accent pattern
sample drum[accent[sixteenth]],amp: 1
#move to next sixteenth
sixteenth = sixteenth + 1
#wait for current sixteenth to end
sleep 0.125
end
#move to next chord
cprogpos = cprogpos + 1
end
end