-
Notifications
You must be signed in to change notification settings - Fork 0
/
testMusicProcessing.py
149 lines (103 loc) · 4.55 KB
/
testMusicProcessing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#Import Libraries ----------------------------------------
#import torch
#import torchvision
from music21 import *
import numpy as np
import os
import pickle
#Parameters-----------------------------------------------
path = '/Users/Hannah Kim/Desktop/ESE587/FinalProject/MidiFiles/'
sequence_length = 100
#Method for reading MIDI files with music21---------------
#writes notes and chords to an array
def readMIDIfile(filePath):
print("Reading MIDI files!")
notes=[]
#For every file in folder
for file in os.listdir(filePath):
if file.endswith(".mid"):
print("Parsing %s" % filePath+file)
#Open MIDI file
midiFile = converter.parse(filePath+file)
notes_to_parse = None
p = instrument.partitionByInstrument(midiFile)
for part in p.parts:
#Only extract Piano
notes_to_parse = part.recurse()
for element in notes_to_parse:
if isinstance(element, note.Note):
notes.append(str(element.pitch))
elif isinstance(element, chord.Chord):
notes.append('.'.join(str(n) for n in element.normalOrder))
elif isinstance(element, note.Rest):
notes.append(element.name)
with open('data/notes','wb') as filepath
pickle.dump(notes, filepath)
return notes
#copied from Skuldur:------------------------------------
#creates arrays for network input/output and maps notes to numbers
def prepareData(notes, length):
# get all pitch names
pitchnames = sorted(set(item for item in notes))
# create a dictionary to map pitches to integers
note_to_int = dict((note, number) for number, note in enumerate(pitchnames))
network_input = []
network_output = []
# create input sequences and the corresponding outputs
for i in range(0, len(notes) - sequence_length, 1):
sequence_in = notes[i:i + sequence_length]
sequence_out = notes[i + sequence_length]
network_input.append([note_to_int[char] for char in sequence_in])
network_output.append(note_to_int[sequence_out])
n_patterns = len(network_input)
# reshape the input into a format compatible with LSTM layers
network_input = np.reshape(network_input, (n_patterns, sequence_length, 1))
# normalize input??????
#network_input = network_input / float(length)
#one hot encode output???????? (Using keras)
#network_output = np_utils.to_categorical(network_output)
return (network_input, network_output)
notes = readMIDIfile(path)
notes_len = len(set(notes))
network_in, network_out = prepareData(notes, notes_len)
print("This is the input array: \n", network_in)
#print("input size:", network_in.shape)
#print("output size:", len(network_out))
print("\n\nThis is the output array: \n" , network_out)
#copied from Skuldur:-------------------------------------
#From "generate_notes" module
#Gets a random sequence from an input array and passes it
#thru the network to get the next expected note, which is
#then appended to the original input and fed back in (repeat this 500 tiems)
def generateMusic():
#copied from Skuldur:-------------------------------------
#From "create_midi" module
#Takes the string of notes output of makeMusic(), converts it
#to note and chord objects, and then written to midi file
def createMIDI(network_output):
offset = 0
output_notes = []
#Convert to notes
#Create MIDI file
for pattern in network_output:
# pattern is a chord
if ('.' in pattern) or pattern.isdigit():
notes_in_chord = pattern.split('.')
notes = []
for current_note in notes_in_chord:
new_note = note.Note(int(current_note))
new_note.storedInstrument = instrument.Piano()
notes.append(new_note)
new_chord = chord.Chord(notes)
new_chord.offset = offset
output_notes.append(new_chord)
# pattern is a note
else:
new_note = note.Note(pattern)
new_note.offset = offset
new_note.storedInstrument = instrument.Piano()
output_notes.append(new_note)
# increase offset each iteration so that notes do not stack
offset += 0.5
midi_stream = stream.Stream(output_notes)
midi_stream.write('midi', fp='test_output.mid')