Skip to content

Instantly share code, notes, and snippets.

@dehaenw
Created December 30, 2021 20:33
Show Gist options
  • Save dehaenw/ad1bb98816707ecfea4ee62d068373dd to your computer and use it in GitHub Desktop.
Save dehaenw/ad1bb98816707ecfea4ee62d068373dd to your computer and use it in GitHub Desktop.
import itertools as it
import numpy as np
import midiutil
from midiutil.MidiFile import MIDIFile
#generates about half an h of modal fingerpicking tunes using a simple markov model
#change the seed with increments of about 100K to get a new one.
#lots of parameters to play around with but you can figure it out yourself.
startseed=234567
def get_tm(seed):
#think of some better way to populate this matrix in the future lol
transition_matrix = np.tile(probs,(len(states),1))
for i in range(10000):
np.random.seed(i+seed)
x=np.random.randint(len(states))
np.random.seed(i+123456+seed)
y=np.random.randint(len(states))
transition_matrix[x,y]*=0.5
transition_matrix[y,x]*=0.5
transition_matrix[transition_matrix < np.sort(transition_matrix.flatten())[-150]]= 0
for i in range(len(states)):
transition_matrix[i,i]=0
row_sums = transition_matrix.sum(axis=1)
for i in range(len(row_sums)):
transition_matrix[i,i]=0
if row_sums[i]==0 or list(transition_matrix[i]).count(0)==1:
identity=np.zeros(len(row_sums))
identity[i]=0.25
identity[(i+1)%len(row_sums)]=0.25
identity[(i+2)%len(row_sums)]=0.25
identity[(i+3)%len(row_sums)]=0.25
transition_matrix[i]=identity
row_sums[i]=1
transition_matrix = transition_matrix / row_sums[:, np.newaxis]
return transition_matrix
def allowednotes(scale,root=60,maxnote=84,minnote=36):
start=root%12-12
allnotes =[]
beginscale=[note+start for note in scale]
for i in range(12): #max 12 octaves bc midi max is 127
for note in beginscale:
allnotes.append(note+12*i)
notes_list = [note for note in allnotes if note >= minnote and note <= maxnote]
return notes_list
scales= [[0,3,5,7,8,10],[0,2,3,5,7,8,10],[0,2,3,5,7,10],[0,2,3,5,7,9,10],[0,3,5,7,9,10],[0,1,3,5,7,9,10],[0,1,3,5,7,10],[0,1,3,5,7,8,10],[0,3,5,7,8,10]]
nls=[allowednotes(x,minnote=40,maxnote=82) for x in scales]
pitch_delta = [0,1,2,3,-1,-2,-3]
pitch_proba = [10.,0.1,0.1,0.1,0.1,0.1,0.1]
time_delta = [1,0.5,0.25,-64,.75,4,8]
time_proba = [10.,10.04,20.03,20.02,15.01,0.5,0.5]
states = list(it.product(pitch_delta,time_delta))
probs = list(tup[0]*tup[1] for tup in it.product(pitch_proba,time_proba))
curr_state=0
states_list=[]
for i in range(40):
notes=500
transition_matrix=get_tm(startseed+250*i)
for i in range(notes):
np.random.seed(i+startseed)
curr_state = np.random.choice(np.arange(len(states)),replace=True,p=transition_matrix[curr_state])
states_list.append(states[curr_state])
# parse states list into midi
mf = MIDIFile(1, adjust_origin = True)
mf.addTrackName(0, 0, "test")
mf.addTempo(0, 0, 140)
curr_pitch = 60
curr_time = 0
curr_time_delta = 1
t1=0.25
times=set([])
curr_scale=0
scene_len=1000
min_time=-500
for i,state in enumerate(states_list):
if i%2000==0:
nl=nls[curr_scale]
curr_scale=(curr_scale+1)%len(nls)
min_time+=500
times=set([])
try:
curr_pitch=nl[(nl.index(curr_pitch)+state[0])%len(nl)]
except:
curr_pitch=nl[0]
curr_time_delta=state[1]
curr_time=(curr_time+curr_time_delta)%scene_len
if curr_time not in times:
if 0>curr_time_delta>4:
t1=curr_time_delta
else:
t1=4
mf.addNote(0, 0, curr_pitch, min_time+curr_time, t1, 50+(i%10)*5)
times.add(curr_time)
with open("output_{}.mid".format(startseed), 'wb') as outf:
mf.writeFile(outf)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment