Skip to content

Commit

Permalink
First Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaeleidus committed Feb 27, 2012
0 parents commit f6763b8
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
Empty file added README
Empty file.
126 changes: 126 additions & 0 deletions geneticMusic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import copy
import pprint
import random
import string
import pickle
import sys
from urllib.request import urlopen
from types import *

base = 41 #note value of middle A
octave = 12 #there are 12 potential notes in each octave
generationSize = 20 #how many songs should be generated in each generation

noteList = ['A-1','A-1#','B-1','C-1','C-1#','D-1','D-1#','E-1','F-1','F-1#','G-1','G-1#',
'A','A#','B','C','C#','D','D#','E','F','F#','G','G#',
'A2','A2#','B2','C2','C2#','D2','D2#','E2','F2','F2#','G2','G2#',
'A3','A3#','B3','C3','C3#','D3','D3#','E3','F3','F3#','G3','G3#']

keys = range(base, base+octave)
notes = {}
for i in range(len(noteList)): #build dictionary of notes to lookup the name of the note later
notes[i+base-octave] = noteList[i]

class Mode:
def __init__(self, name, notes):
self.name = name
self.notes = notes

modes = [
Mode("Ionian", [0,2,4,5,7,9,11]),
Mode("Dorian", [0,2,3,5,7,9,10]),
Mode("Phrygian", [0,1,3,5,7,8,10]),
Mode("Freygish", [0,1,4,5,7,9,11]),
Mode("Lydian", [0,2,4,6,7,9,11]),
Mode("Mixolydian", [0,2,4,5,7,9,10]),
Mode("Aeolian", [0,2,3,5,7,8,10]),
Mode("Locrian", [0,1,3,5,6,8,10])
]

class Scale:
def __init__(self, key, mode):
self.start = key
self.key = notes[key]
self.mode = mode
self.scaleNotes = []
for note in self.mode.notes:
self.scaleNotes.append(note+self.start-octave)
for note in self.mode.notes:
self.scaleNotes.append(note+self.start)
for note in self.mode.notes:
self.scaleNotes.append(note+self.start+octave)
self.scaleNotes.append(self.start+(2*octave)) #repeat the first scale degree 2 octaves up
def mainOctave(self):
return self.scaleNotes[8-1:(2*8)]

def randomWord(wordType):
urls = ["http://api.wordnik.com/v4/words.json/randomWord?hasDictionaryDef=true&includePartOfSpeech=adverb,adjective&api_key=1a726d79d51b76f7664090f16750cc75292f05d3df6083875",
"http://api.wordnik.com/v4/words.json/randomWord?hasDictionaryDef=true&includePartOfSpeech=noun,adjective,verb&api_key=1a726d79d51b76f7664090f16750cc75292f05d3df6083875"]
words = str(urlopen(urls[wordType]).read()).replace('"', '')
return dict(item.split(":") for item in words[3:-2].split(','))['word']

class Song:
def __init__(self):
self.mutationPoints = 10
self.generation = 0
self.songnum = 0
self.name = randomWord(0) + " " + randomWord(1)
self.bpm = random.randint(100, 200)
self.key = random.randint(base,base+octave-1)
self.mode = random.choice(modes)
self.scale = Scale(self.key, self.mode)
self.score = -1

def getKey(self):
return notes[self.key]

def prompt(prompt, options = [], required = False):
if len(options) > 0:
prompt = prompt + '[' + '|'.join(options) + ']'
prompt = prompt + ': '
resp = input(prompt)
while (required and resp == "") or (len(options)> 0 and resp not in options and not (not required and resp == "")):
print ("Please enter a valid option")
resp = input(prompt)
return resp

def main(argv=None):
if argv is None:
argv = sys.argv
data = {"Generation": 0, "Songs": []}
songs = data["Songs"]
print ("Would you like to:\n\t[1]Load a previous saved generation\n\t[2]Generate a new random generation\n\t[3]Exit")
choice = prompt("Please select an option", ["1", "2", "3"], True)
if choice == "1":
print ("Loading last generation")
data = pickle.load(open("GeneticMusic.pkl", "rb"))
songs = data["Songs"]
for song in songs:
print ("%d.%d: %s - %d bpm" % (song.generation, song.songnum, song.name, song.bpm))
print ("%s %s Scale" %(song.getKey(), song.mode.name))
print ([notes[note] for note in song.scale.mainOctave()])
if song.score == -1:
while True:
try:
score = float(prompt("Song score"))
song.score = score
pickle.dump(data, open("GeneticMusic.pkl", "wb"))
break
except ValueError:
print("Please enter a valid number")
else:
print ("Score: %s" % (song.score))
print ()

elif choice == "2":
for i in range(generationSize):
songs.append(Song())
s = songs[-1]
s.songnum = i
pickle.dump(data, open("GeneticMusic.pkl", "wb"))
print("Generation 0 generated and saved to file")
else:
print("goodbye")

if __name__ == "__main__":
main()

0 comments on commit f6763b8

Please sign in to comment.