├── .gitignore └── src ├── pysynth.py ├── MarkovBuilder.py └── MarkovMusic.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.wav 2 | *.pyc 3 | .project 4 | .pydevproject 5 | .settings 6 | .DS_Store -------------------------------------------------------------------------------- /src/pysynth.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcbozonier/MarkovMusic/master/src/pysynth.py -------------------------------------------------------------------------------- /src/MarkovBuilder.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 14, 2009 3 | 4 | @author: darkxanthos 5 | ''' 6 | import random 7 | 8 | class MarkovBuilder: 9 | def __init__(self, value_list): 10 | self._values_added = 0 11 | self._reverse_value_lookup = value_list 12 | self._value_lookup = {} 13 | for i in range(0, len(value_list)): 14 | self._value_lookup[value_list[i]] = i 15 | #Initialize our adjacency matrix with the initial 16 | #probabilities for note transitions. 17 | self._matrix=[[0 for x in range(0,len(value_list))] for i in range(0,len(value_list))] 18 | 19 | def add(self, from_value, to_value): 20 | """Add a path from a note to another note. Re-adding a path between notes will increase the associated weight.""" 21 | value = self._value_lookup 22 | self._matrix[value[from_value]][value[to_value]] += 1 23 | self._values_added = self._values_added + 1 24 | 25 | def next_value(self, from_value): 26 | value = self._value_lookup[from_value] 27 | value_counts = self._matrix[value] 28 | value_index = self.randomly_choose(value_counts) 29 | if(value_index < 0): 30 | raise RuntimeError, "Non-existent value selected." 31 | else: 32 | return self._reverse_value_lookup[value_index] 33 | 34 | def randomly_choose(self, choice_counts): 35 | """Given an array of counts, returns the index that was randomly chosen""" 36 | counted_sum = 0 37 | count_sum = sum(choice_counts) 38 | selected_count = random.randrange(1, count_sum + 1) 39 | for index in range(0, len(choice_counts)): 40 | counted_sum += choice_counts[index] 41 | if(counted_sum >= selected_count): 42 | return index 43 | raise RuntimeError, "Impossible value selection made. BAD!" -------------------------------------------------------------------------------- /src/MarkovMusic.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 12, 2009 3 | 4 | @author: Justin Bozonier 5 | ''' 6 | import pysynth 7 | from MarkovBuilder import MarkovBuilder 8 | 9 | class MusicMatrix: 10 | def __init__(self): 11 | self._previous_note = None 12 | self._markov = MarkovBuilder(["a", "a#", "b", "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#"]) 13 | self._timings = MarkovBuilder([1, 2, 4, 8, 16]) 14 | 15 | def add(self, to_note): 16 | """Add a path from a note to another note. Re-adding a path between notes will increase the associated weight.""" 17 | if(self._previous_note is None): 18 | self._previous_note = to_note 19 | return 20 | from_note = self._previous_note 21 | self._markov.add(from_note[0], to_note[0]) 22 | self._timings.add(from_note[1], to_note[1]) 23 | self._previous_note = to_note 24 | 25 | def next_note(self, from_note): 26 | return [self._markov.next_value(from_note[0]), self._timings.next_value(from_note[1])] 27 | 28 | # Playing it comes next :) 29 | #test = [['c',4], ['e',4], ['g',4], ['c5',1]] 30 | #pysynth.make_wav(test, fn = "test.wav") 31 | 32 | musicLearner = MusicMatrix() 33 | 34 | # Input the melody of Row, Row, Row Your Boat 35 | # The MusicMatrix will automatically use this to 36 | # model our own song after it. 37 | musicLearner.add(["c", 4]) 38 | musicLearner.add(["c", 4]) 39 | musicLearner.add(["c", 4]) 40 | musicLearner.add(["d", 8]) 41 | musicLearner.add(["e", 4]) 42 | musicLearner.add(["e", 4]) 43 | musicLearner.add(["d", 8]) 44 | musicLearner.add(["e", 4]) 45 | musicLearner.add(["f", 8]) 46 | musicLearner.add(["g", 2]) 47 | 48 | musicLearner.add(["c", 8]) 49 | musicLearner.add(["c", 8]) 50 | musicLearner.add(["c", 8]) 51 | 52 | musicLearner.add(["g", 8]) 53 | musicLearner.add(["g", 8]) 54 | musicLearner.add(["g", 8]) 55 | 56 | musicLearner.add(["e", 8]) 57 | musicLearner.add(["e", 8]) 58 | musicLearner.add(["e", 8]) 59 | 60 | musicLearner.add(["c", 8]) 61 | musicLearner.add(["c", 8]) 62 | musicLearner.add(["c", 8]) 63 | 64 | musicLearner.add(["g", 4]) 65 | musicLearner.add(["f", 8]) 66 | musicLearner.add(["e", 4]) 67 | musicLearner.add(["d", 8]) 68 | musicLearner.add(["c", 2]) 69 | 70 | random_score = [] 71 | current_note = ["c", 4] 72 | for i in range(0,100): 73 | print current_note[0] + ", " + str(current_note[1]) 74 | current_note = musicLearner.next_note(current_note) 75 | random_score.append(current_note) 76 | 77 | pysynth.make_wav(random_score, fn = "first_score.wav") --------------------------------------------------------------------------------