Created
December 30, 2021 20:33
-
-
Save dehaenw/ad1bb98816707ecfea4ee62d068373dd to your computer and use it in GitHub Desktop.
This file contains hidden or 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
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