Dmytro Lopushanskyy commited on
Commit
c12a65c
1 Parent(s): 7b9a464

upload base version

Browse files
.DS_Store ADDED
Binary file (6.15 kB). View file
 
.gitattributes CHANGED
@@ -1,4 +1,5 @@
1
  *.7z filter=lfs diff=lfs merge=lfs -text
 
2
  *.arrow filter=lfs diff=lfs merge=lfs -text
3
  *.bin filter=lfs diff=lfs merge=lfs -text
4
  *.bz2 filter=lfs diff=lfs merge=lfs -text
@@ -25,3 +26,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
25
  *.zip filter=lfs diff=lfs merge=lfs -text
26
  *.zstandard filter=lfs diff=lfs merge=lfs -text
27
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
1
  *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.pkl filter=lfs diff=lfs merge=lfs -text
3
  *.arrow filter=lfs diff=lfs merge=lfs -text
4
  *.bin filter=lfs diff=lfs merge=lfs -text
5
  *.bz2 filter=lfs diff=lfs merge=lfs -text
 
26
  *.zip filter=lfs diff=lfs merge=lfs -text
27
  *.zstandard filter=lfs diff=lfs merge=lfs -text
28
  *tfevents* filter=lfs diff=lfs merge=lfs -text
29
+ objects/*.pkl filter=lfs diff=lfs merge=lfs -text
.ipynb_checkpoints/main-checkpoint.ipynb ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 11,
6
+ "id": "61e10139",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "import pickle\n",
11
+ "from music21 import *"
12
+ ]
13
+ },
14
+ {
15
+ "cell_type": "code",
16
+ "execution_count": 3,
17
+ "id": "1a2b28be",
18
+ "metadata": {},
19
+ "outputs": [],
20
+ "source": [
21
+ "import torch\n",
22
+ "import torch.nn as nn\n",
23
+ "from torch.nn import functional as F\n",
24
+ "\n",
25
+ "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
26
+ "\n",
27
+ "class GenerationRNN(nn.Module):\n",
28
+ " def __init__(self, input_size, hidden_size, output_size, n_layers=1):\n",
29
+ " super(GenerationRNN, self).__init__()\n",
30
+ " self.input_size = input_size\n",
31
+ " self.hidden_size = hidden_size\n",
32
+ " self.output_size = output_size\n",
33
+ " self.n_layers = n_layers\n",
34
+ " \n",
35
+ " self.embedding = nn.Embedding(input_size, hidden_size)\n",
36
+ " self.gru = nn.GRU(hidden_size, hidden_size, n_layers)\n",
37
+ " self.decoder = nn.Linear(hidden_size * n_layers, output_size)\n",
38
+ " \n",
39
+ " def forward(self, input, hidden):\n",
40
+ " # Creates embedding of the input texts\n",
41
+ " #print('initial input', input.size())\n",
42
+ " input = self.embedding(input.view(1, -1))\n",
43
+ " #print('input after embedding', input.size())\n",
44
+ " output, hidden = self.gru(input, hidden)\n",
45
+ " #print('output after gru', output.size())\n",
46
+ " #print('hidden after gru', hidden.size())\n",
47
+ " output = self.decoder(hidden.view(1, -1))\n",
48
+ " #print('output after decoder', output.size())\n",
49
+ " return output, hidden\n",
50
+ "\n",
51
+ " def init_hidden(self):\n",
52
+ " return torch.zeros(self.n_layers, 1, self.hidden_size).to(device)"
53
+ ]
54
+ },
55
+ {
56
+ "cell_type": "code",
57
+ "execution_count": 4,
58
+ "id": "5b7120cf",
59
+ "metadata": {},
60
+ "outputs": [],
61
+ "source": [
62
+ "def predict_multimomial(net, prime_seq, predict_len, temperature=0.8):\n",
63
+ " '''\n",
64
+ " Arguments:\n",
65
+ " prime_seq - priming sequence (converted t)\n",
66
+ " predict_len - number of notes to predict for after prime sequence\n",
67
+ " '''\n",
68
+ " hidden = net.init_hidden()\n",
69
+ "\n",
70
+ " predicted = prime_seq.copy()\n",
71
+ " prime_seq = torch.tensor(prime_seq, dtype = torch.long).to(device)\n",
72
+ "\n",
73
+ "\n",
74
+ " # \"Building up\" the hidden state using the prime sequence\n",
75
+ " for p in range(len(prime_seq) - 1):\n",
76
+ " input = prime_seq[p]\n",
77
+ " _, hidden = net(input, hidden)\n",
78
+ " \n",
79
+ " # Last character of prime sequence\n",
80
+ " input = prime_seq[-1]\n",
81
+ " \n",
82
+ " # For every index to predict\n",
83
+ " for p in range(predict_len):\n",
84
+ "\n",
85
+ " # Pass the inputs to the model - output has dimension n_pitches - scores for each of the possible characters\n",
86
+ " output, hidden = net(input, hidden)\n",
87
+ " # Sample from the network output as a multinomial distribution\n",
88
+ " output = output.data.view(-1).div(temperature).exp()\n",
89
+ " predicted_id = torch.multinomial(output, 1)\n",
90
+ "\n",
91
+ " # Add predicted index to the list and use as next input\n",
92
+ " predicted.append(predicted_id.item()) \n",
93
+ " input = predicted_id\n",
94
+ "\n",
95
+ " return predicted"
96
+ ]
97
+ },
98
+ {
99
+ "cell_type": "code",
100
+ "execution_count": 5,
101
+ "id": "8ce30142",
102
+ "metadata": {},
103
+ "outputs": [],
104
+ "source": [
105
+ "file_path = '/home/dmytro/ucu/music-generation/model.pkl'\n",
106
+ "with open(file_path, 'rb') as f:\n",
107
+ " model = pickle.load(f)"
108
+ ]
109
+ },
110
+ {
111
+ "cell_type": "code",
112
+ "execution_count": 6,
113
+ "id": "84a2ea9b",
114
+ "metadata": {},
115
+ "outputs": [],
116
+ "source": [
117
+ "file_path = '/home/dmytro/ucu/music-generation/int_to_note.pkl'\n",
118
+ "with open(file_path, 'rb') as f:\n",
119
+ " int_to_note = pickle.load(f)"
120
+ ]
121
+ },
122
+ {
123
+ "cell_type": "code",
124
+ "execution_count": 12,
125
+ "id": "07815507",
126
+ "metadata": {},
127
+ "outputs": [],
128
+ "source": [
129
+ "def create_midi(prediction_output):\n",
130
+ " \"\"\" convert the output from the prediction to notes and create a midi file\n",
131
+ " from the notes \"\"\"\n",
132
+ " offset = 0\n",
133
+ " output_notes = []\n",
134
+ "\n",
135
+ " # create note and chord objects based on the values generated by the model\n",
136
+ " for pattern in prediction_output:\n",
137
+ " # pattern is a chord\n",
138
+ " if ('.' in pattern) or pattern.isdigit():\n",
139
+ " notes_in_chord = pattern.split('.')\n",
140
+ " notes = []\n",
141
+ " for current_note in notes_in_chord:\n",
142
+ " new_note = note.Note(int(current_note))\n",
143
+ " new_note.storedInstrument = instrument.Piano()\n",
144
+ " notes.append(new_note)\n",
145
+ " new_chord = chord.Chord(notes)\n",
146
+ " new_chord.offset = offset\n",
147
+ " output_notes.append(new_chord)\n",
148
+ " # pattern is a note\n",
149
+ " else:\n",
150
+ " new_note = note.Note(pattern)\n",
151
+ " new_note.offset = offset\n",
152
+ " new_note.storedInstrument = instrument.Piano()\n",
153
+ " output_notes.append(new_note)\n",
154
+ "\n",
155
+ " # increase offset each iteration so that notes do not stack\n",
156
+ " offset += 0.5\n",
157
+ "\n",
158
+ " midi_stream = stream.Stream(output_notes)\n",
159
+ "\n",
160
+ " return midi_stream"
161
+ ]
162
+ },
163
+ {
164
+ "cell_type": "code",
165
+ "execution_count": 30,
166
+ "id": "a70a41f1",
167
+ "metadata": {},
168
+ "outputs": [],
169
+ "source": [
170
+ "input_melody = [727,\n",
171
+ " 224,\n",
172
+ " 55,\n",
173
+ " 55,\n",
174
+ " 727,\n",
175
+ " 224,\n",
176
+ " 55]\n"
177
+ ]
178
+ },
179
+ {
180
+ "cell_type": "code",
181
+ "execution_count": 28,
182
+ "id": "c9afc0c0",
183
+ "metadata": {},
184
+ "outputs": [],
185
+ "source": [
186
+ "generated_seq_multinomial = predict_multimomial(model, input_melody, predict_len = 100, temperature = 2.2)\n",
187
+ "generated_seq_multinomial = [int_to_note[e] for e in generated_seq_multinomial]\n",
188
+ "pred_midi_multinomial = create_midi(generated_seq_multinomial)"
189
+ ]
190
+ },
191
+ {
192
+ "cell_type": "code",
193
+ "execution_count": 29,
194
+ "id": "99a1aabe",
195
+ "metadata": {},
196
+ "outputs": [
197
+ {
198
+ "data": {
199
+ "text/plain": [
200
+ "'/home/dmytro/ucu/music-generation/output/new_2.mid'"
201
+ ]
202
+ },
203
+ "execution_count": 29,
204
+ "metadata": {},
205
+ "output_type": "execute_result"
206
+ }
207
+ ],
208
+ "source": [
209
+ "pred_midi_multinomial.write('midi', fp='result.mid')"
210
+ ]
211
+ },
212
+ {
213
+ "cell_type": "code",
214
+ "execution_count": null,
215
+ "id": "ba84139a",
216
+ "metadata": {},
217
+ "outputs": [],
218
+ "source": [
219
+ "sound_font = \"/usr/share/sounds/sf2/FluidR3_GM.sf2\"\n",
220
+ "FluidSynth(sound_font).midi_to_audio('result.midi', 'result.wav')\n",
221
+ "return 'result.wav', 'result.midi'"
222
+ ]
223
+ },
224
+ {
225
+ "cell_type": "code",
226
+ "execution_count": null,
227
+ "id": "0f4481b8",
228
+ "metadata": {},
229
+ "outputs": [],
230
+ "source": [
231
+ "def process_input():\n",
232
+ " pass"
233
+ ]
234
+ },
235
+ {
236
+ "cell_type": "code",
237
+ "execution_count": null,
238
+ "id": "2f2e7a91",
239
+ "metadata": {},
240
+ "outputs": [],
241
+ "source": [
242
+ "midi_file_desc = \"\"\"Please entUpload your own MIDI file here (try to keep it small).\n",
243
+ "If you do not have a MIDI file, add some text and we will turn it into music!\n",
244
+ "\"\"\"\n",
245
+ "\n",
246
+ "article = \"\"\"# Pop Music Transformer\n",
247
+ "We are using a language model to create music by treating a musical standard MIDI a simple text, with tokens for note values, note duration, and separations to denote movement forward in time.\n",
248
+ "\n",
249
+ "This is all following the great work you can find [at this repo](https://github.com/bearpelican/musicautobot). Moreover check out [their full web app](http://musicautobot.com/). We use the pretrained model they created as well as the utilities for converting between MIDI, audio streams, numpy encodings, and WAV files.\n",
250
+ "\n",
251
+ "## Sonification\n",
252
+ "\n",
253
+ "This is the process of turning something not inherently musical into music. Here we do something pretty simple. We take your input text \"pretty cool\", get a sentiment score (hard coded right now, model TODO), and use a major progression if it's positive and a minor progression if it's negative, and then factor the score into the randomness of the generated music. We also take the text and extract a melody by taking any of the letters from A to G, which in the example is just \"E C\". With the simple \"E C\" melody and a major progression a musical idea is generated.\n",
254
+ "\"\"\"\n",
255
+ "\n",
256
+ "iface = gr.Interface(\n",
257
+ " fn=process_input, \n",
258
+ " inputs=[\n",
259
+ " gr.inputs.File(optional=True, label=midi_file_desc),\n",
260
+ " \"text\", \n",
261
+ " gr.inputs.Slider(0, 250, default=100, step=50),\n",
262
+ " gr.inputs.Radio([100, 200, 500], type=\"value\", default=100)\n",
263
+ " ], \n",
264
+ " outputs=[\"audio\", \"file\"],\n",
265
+ " article=article\n",
266
+ " # examples=['C major scale.midi']\n",
267
+ ")\n",
268
+ "\n",
269
+ "iface.launch()"
270
+ ]
271
+ }
272
+ ],
273
+ "metadata": {
274
+ "kernelspec": {
275
+ "display_name": "Python 3 (ipykernel)",
276
+ "language": "python",
277
+ "name": "python3"
278
+ },
279
+ "language_info": {
280
+ "codemirror_mode": {
281
+ "name": "ipython",
282
+ "version": 3
283
+ },
284
+ "file_extension": ".py",
285
+ "mimetype": "text/x-python",
286
+ "name": "python",
287
+ "nbconvert_exporter": "python",
288
+ "pygments_lexer": "ipython3",
289
+ "version": "3.9.12"
290
+ }
291
+ },
292
+ "nbformat": 4,
293
+ "nbformat_minor": 5
294
+ }
.ipynb_checkpoints/music_generation_with_Variational_AE-checkpoint.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
app.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pickle
2
+ import pretty_midi
3
+ from music21 import *
4
+ from midi2audio import FluidSynth
5
+
6
+ import torch
7
+ import torch.nn as nn
8
+ from torch.nn import functional as F
9
+
10
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
11
+
12
+ file_path = './objects/int_to_note.pkl'
13
+ with open(file_path, 'rb') as f:
14
+ int_to_note = pickle.load(f)
15
+
16
+ file_path = './objects/note_to_int.pkl'
17
+ with open(file_path, 'rb') as f:
18
+ note_to_int = pickle.load(f)
19
+
20
+
21
+ class GenerationRNN(nn.Module):
22
+ def __init__(self, input_size, hidden_size, output_size, n_layers=1):
23
+ super(GenerationRNN, self).__init__()
24
+ self.input_size = input_size
25
+ self.hidden_size = hidden_size
26
+ self.output_size = output_size
27
+ self.n_layers = n_layers
28
+
29
+ self.embedding = nn.Embedding(input_size, hidden_size)
30
+ self.gru = nn.GRU(hidden_size, hidden_size, n_layers)
31
+ self.decoder = nn.Linear(hidden_size * n_layers, output_size)
32
+
33
+ def forward(self, input, hidden):
34
+ # Creates embedding of the input texts
35
+ #print('initial input', input.size())
36
+ input = self.embedding(input.view(1, -1))
37
+ #print('input after embedding', input.size())
38
+ output, hidden = self.gru(input, hidden)
39
+ #print('output after gru', output.size())
40
+ #print('hidden after gru', hidden.size())
41
+ output = self.decoder(hidden.view(1, -1))
42
+ #print('output after decoder', output.size())
43
+ return output, hidden
44
+
45
+ def init_hidden(self):
46
+ return torch.zeros(self.n_layers, 1, self.hidden_size).to(device)
47
+
48
+
49
+ def predict_multimomial(net, prime_seq, predict_len, temperature=0.8):
50
+ '''
51
+ Arguments:
52
+ prime_seq - priming sequence (converted t)
53
+ predict_len - number of notes to predict for after prime sequence
54
+ '''
55
+ hidden = net.init_hidden()
56
+
57
+ predicted = prime_seq.copy()
58
+ prime_seq = torch.tensor(prime_seq, dtype = torch.long).to(device)
59
+
60
+
61
+ # "Building up" the hidden state using the prime sequence
62
+ for p in range(len(prime_seq) - 1):
63
+ input = prime_seq[p]
64
+ _, hidden = net(input, hidden)
65
+
66
+ # Last character of prime sequence
67
+ input = prime_seq[-1]
68
+
69
+ # For every index to predict
70
+ for p in range(predict_len):
71
+
72
+ # Pass the inputs to the model - output has dimension n_pitches - scores for each of the possible characters
73
+ output, hidden = net(input, hidden)
74
+ # Sample from the network output as a multinomial distribution
75
+ output = output.data.view(-1).div(temperature).exp()
76
+ predicted_id = torch.multinomial(output, 1)
77
+
78
+ # Add predicted index to the list and use as next input
79
+ predicted.append(predicted_id.item())
80
+ input = predicted_id
81
+
82
+ return predicted
83
+
84
+
85
+ def create_midi(prediction_output):
86
+ """ convert the output from the prediction to notes and create a midi file
87
+ from the notes """
88
+ offset = 0
89
+ output_notes = []
90
+
91
+ # create note and chord objects based on the values generated by the model
92
+ for pattern in prediction_output:
93
+ # pattern is a chord
94
+ if ('.' in pattern) or pattern.isdigit():
95
+ notes_in_chord = pattern.split('.')
96
+ notes = []
97
+ for current_note in notes_in_chord:
98
+ new_note = note.Note(int(current_note))
99
+ new_note.storedInstrument = instrument.Piano()
100
+ notes.append(new_note)
101
+ new_chord = chord.Chord(notes)
102
+ new_chord.offset = offset
103
+ output_notes.append(new_chord)
104
+ # pattern is a note
105
+ else:
106
+ new_note = note.Note(pattern)
107
+ new_note.offset = offset
108
+ new_note.storedInstrument = instrument.Piano()
109
+ output_notes.append(new_note)
110
+
111
+ # increase offset each iteration so that notes do not stack
112
+ offset += 0.5
113
+
114
+ midi_stream = stream.Stream(output_notes)
115
+
116
+ return midi_stream
117
+
118
+
119
+ def get_note_names(midi):
120
+ s2 = instrument.partitionByInstrument(midi)
121
+
122
+ piano_part = None
123
+ # Filter for only the piano part
124
+ instr = instrument.Piano
125
+ for part in s2:
126
+ if isinstance(part.getInstrument(), instr):
127
+ piano_part = part
128
+
129
+ notes_song = []
130
+ if not piano_part: # Some songs somehow have no piano parts
131
+ # Just take the first part
132
+ piano_part = s2[0]
133
+
134
+ for element in piano_part:
135
+ if isinstance(element, note.Note):
136
+ # Return the pitch of the single note
137
+ notes_song.append(str(element.pitch))
138
+ elif isinstance(element, chord.Chord):
139
+ # Returns the normal order of a Chord represented in a list of integers
140
+ notes_song.append('.'.join(str(n) for n in element.normalOrder))
141
+
142
+ return notes_song
143
+
144
+
145
+ def process_input(input_midi_file, input_randomness, input_duration):
146
+ midi = converter.parse(input_midi_file)
147
+ note_names = get_note_names(midi)
148
+ int_notes = [note_to_int[note_name] for note_name in note_names]
149
+
150
+ generated_seq_multinomial = predict_multimomial(model, int_notes, predict_len = 100, temperature = 2.2)
151
+ generated_seq_multinomial = [int_to_note[e] for e in generated_seq_multinomial]
152
+ pred_midi_multinomial = create_midi(generated_seq_multinomial)
153
+
154
+ pred_midi_multinomial.write('midi', fp='result.midi')
155
+
156
+ # sound_font = "/usr/share/sounds/sf2/FluidR3_GM.sf2"
157
+ FluidSynth().midi_to_audio('result.midi', 'result.wav')
158
+ return 'result.wav', 'result.midi'
159
+
160
+
161
+ file_path = './objects/model_cpu.pkl'
162
+ with open(file_path, 'rb') as f:
163
+ model = pickle.load(f)
164
+
165
+
166
+ midi_file_desc = """
167
+ This model allows to generate music based on your input.
168
+ Please upload a MIDI file below, choose music randomness and duration. Enjoy!
169
+ """
170
+
171
+ article = """# Music Generation
172
+ This project has been created by the students of Ukrainian Catholic University for our ML course.
173
+
174
+ We are using a GRU model to output new notes based on the given input. You can find more information at our Git repo: https://github.com/DmytroLopushanskyy/music-generation
175
+ We are using a language model to create music by treating a musical standard MIDI a simple text, with tokens for note values, note duration, and separations to denote movement forward in time.
176
+ """
177
+
178
+ iface = gr.Interface(
179
+ fn=process_input,
180
+ inputs=[
181
+ gr.inputs.File(label=midi_file_desc),
182
+ gr.inputs.Slider(0, 250, default=100, step=50),
183
+ gr.inputs.Radio([10, 20, 30], type="value", default=20)
184
+ ],
185
+ outputs=["audio", "file"],
186
+ article=article,
187
+ examples=['examples/mozart.midi']
188
+ )
189
+
190
+ iface.launch()
examples/.DS_Store ADDED
Binary file (6.15 kB). View file
 
examples/beethoven.midi ADDED
Binary file (759 Bytes). View file
 
examples/chopin.midi ADDED
Binary file (1.18 kB). View file
 
examples/mozart.midi ADDED
Binary file (761 Bytes). View file
 
main.ipynb ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 108,
6
+ "id": "61e10139",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "import pickle\n",
11
+ "import pretty_midi\n",
12
+ "from music21 import *\n",
13
+ "from midi2audio import FluidSynth"
14
+ ]
15
+ },
16
+ {
17
+ "cell_type": "code",
18
+ "execution_count": 48,
19
+ "id": "1a2b28be",
20
+ "metadata": {},
21
+ "outputs": [],
22
+ "source": [
23
+ "import torch\n",
24
+ "import torch.nn as nn\n",
25
+ "from torch.nn import functional as F\n",
26
+ "\n",
27
+ "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
28
+ "\n",
29
+ "class GenerationRNN(nn.Module):\n",
30
+ " def __init__(self, input_size, hidden_size, output_size, n_layers=1):\n",
31
+ " super(GenerationRNN, self).__init__()\n",
32
+ " self.input_size = input_size\n",
33
+ " self.hidden_size = hidden_size\n",
34
+ " self.output_size = output_size\n",
35
+ " self.n_layers = n_layers\n",
36
+ " \n",
37
+ " self.embedding = nn.Embedding(input_size, hidden_size)\n",
38
+ " self.gru = nn.GRU(hidden_size, hidden_size, n_layers)\n",
39
+ " self.decoder = nn.Linear(hidden_size * n_layers, output_size)\n",
40
+ " \n",
41
+ " def forward(self, input, hidden):\n",
42
+ " # Creates embedding of the input texts\n",
43
+ " #print('initial input', input.size())\n",
44
+ " input = self.embedding(input.view(1, -1))\n",
45
+ " #print('input after embedding', input.size())\n",
46
+ " output, hidden = self.gru(input, hidden)\n",
47
+ " #print('output after gru', output.size())\n",
48
+ " #print('hidden after gru', hidden.size())\n",
49
+ " output = self.decoder(hidden.view(1, -1))\n",
50
+ " #print('output after decoder', output.size())\n",
51
+ " return output, hidden\n",
52
+ "\n",
53
+ " def init_hidden(self):\n",
54
+ " return torch.zeros(self.n_layers, 1, self.hidden_size).to(device)"
55
+ ]
56
+ },
57
+ {
58
+ "cell_type": "code",
59
+ "execution_count": 49,
60
+ "id": "5b7120cf",
61
+ "metadata": {},
62
+ "outputs": [],
63
+ "source": [
64
+ "def predict_multimomial(net, prime_seq, predict_len, temperature=0.8):\n",
65
+ " '''\n",
66
+ " Arguments:\n",
67
+ " prime_seq - priming sequence (converted t)\n",
68
+ " predict_len - number of notes to predict for after prime sequence\n",
69
+ " '''\n",
70
+ " hidden = net.init_hidden()\n",
71
+ "\n",
72
+ " predicted = prime_seq.copy()\n",
73
+ " prime_seq = torch.tensor(prime_seq, dtype = torch.long).to(device)\n",
74
+ "\n",
75
+ "\n",
76
+ " # \"Building up\" the hidden state using the prime sequence\n",
77
+ " for p in range(len(prime_seq) - 1):\n",
78
+ " input = prime_seq[p]\n",
79
+ " _, hidden = net(input, hidden)\n",
80
+ " \n",
81
+ " # Last character of prime sequence\n",
82
+ " input = prime_seq[-1]\n",
83
+ " \n",
84
+ " # For every index to predict\n",
85
+ " for p in range(predict_len):\n",
86
+ "\n",
87
+ " # Pass the inputs to the model - output has dimension n_pitches - scores for each of the possible characters\n",
88
+ " output, hidden = net(input, hidden)\n",
89
+ " # Sample from the network output as a multinomial distribution\n",
90
+ " output = output.data.view(-1).div(temperature).exp()\n",
91
+ " predicted_id = torch.multinomial(output, 1)\n",
92
+ "\n",
93
+ " # Add predicted index to the list and use as next input\n",
94
+ " predicted.append(predicted_id.item()) \n",
95
+ " input = predicted_id\n",
96
+ "\n",
97
+ " return predicted"
98
+ ]
99
+ },
100
+ {
101
+ "cell_type": "code",
102
+ "execution_count": 63,
103
+ "id": "8ce30142",
104
+ "metadata": {},
105
+ "outputs": [],
106
+ "source": [
107
+ "file_path = './objects/model_cpu.pkl'\n",
108
+ "with open(file_path, 'rb') as f:\n",
109
+ " model = pickle.load(f)"
110
+ ]
111
+ },
112
+ {
113
+ "cell_type": "code",
114
+ "execution_count": 64,
115
+ "id": "84a2ea9b",
116
+ "metadata": {},
117
+ "outputs": [],
118
+ "source": [
119
+ "file_path = './objects/int_to_note.pkl'\n",
120
+ "with open(file_path, 'rb') as f:\n",
121
+ " int_to_note = pickle.load(f)"
122
+ ]
123
+ },
124
+ {
125
+ "cell_type": "code",
126
+ "execution_count": 65,
127
+ "id": "102cd217",
128
+ "metadata": {},
129
+ "outputs": [],
130
+ "source": [
131
+ "file_path = './objects/note_to_int.pkl'\n",
132
+ "with open(file_path, 'rb') as f:\n",
133
+ " note_to_int = pickle.load(f)"
134
+ ]
135
+ },
136
+ {
137
+ "cell_type": "code",
138
+ "execution_count": 66,
139
+ "id": "07815507",
140
+ "metadata": {},
141
+ "outputs": [],
142
+ "source": [
143
+ "def create_midi(prediction_output):\n",
144
+ " \"\"\" convert the output from the prediction to notes and create a midi file\n",
145
+ " from the notes \"\"\"\n",
146
+ " offset = 0\n",
147
+ " output_notes = []\n",
148
+ "\n",
149
+ " # create note and chord objects based on the values generated by the model\n",
150
+ " for pattern in prediction_output:\n",
151
+ " # pattern is a chord\n",
152
+ " if ('.' in pattern) or pattern.isdigit():\n",
153
+ " notes_in_chord = pattern.split('.')\n",
154
+ " notes = []\n",
155
+ " for current_note in notes_in_chord:\n",
156
+ " new_note = note.Note(int(current_note))\n",
157
+ " new_note.storedInstrument = instrument.Piano()\n",
158
+ " notes.append(new_note)\n",
159
+ " new_chord = chord.Chord(notes)\n",
160
+ " new_chord.offset = offset\n",
161
+ " output_notes.append(new_chord)\n",
162
+ " # pattern is a note\n",
163
+ " else:\n",
164
+ " new_note = note.Note(pattern)\n",
165
+ " new_note.offset = offset\n",
166
+ " new_note.storedInstrument = instrument.Piano()\n",
167
+ " output_notes.append(new_note)\n",
168
+ "\n",
169
+ " # increase offset each iteration so that notes do not stack\n",
170
+ " offset += 0.5\n",
171
+ "\n",
172
+ " midi_stream = stream.Stream(output_notes)\n",
173
+ "\n",
174
+ " return midi_stream"
175
+ ]
176
+ },
177
+ {
178
+ "cell_type": "code",
179
+ "execution_count": 113,
180
+ "id": "ad197703",
181
+ "metadata": {},
182
+ "outputs": [],
183
+ "source": [
184
+ "def get_note_names(midi):\n",
185
+ " s2 = instrument.partitionByInstrument(midi)\n",
186
+ "\n",
187
+ " piano_part = None\n",
188
+ " # Filter for only the piano part\n",
189
+ " instr = instrument.Piano\n",
190
+ " for part in s2:\n",
191
+ " if isinstance(part.getInstrument(), instr):\n",
192
+ " piano_part = part\n",
193
+ "\n",
194
+ " notes_song = []\n",
195
+ " if not piano_part: # Some songs somehow have no piano parts\n",
196
+ " # Just take the first part\n",
197
+ " piano_part = s2[0]\n",
198
+ " \n",
199
+ " for element in piano_part:\n",
200
+ " if isinstance(element, note.Note):\n",
201
+ " # Return the pitch of the single note\n",
202
+ " notes_song.append(str(element.pitch))\n",
203
+ " elif isinstance(element, chord.Chord):\n",
204
+ " # Returns the normal order of a Chord represented in a list of integers\n",
205
+ " notes_song.append('.'.join(str(n) for n in element.normalOrder))\n",
206
+ " \n",
207
+ " return notes_song"
208
+ ]
209
+ },
210
+ {
211
+ "cell_type": "code",
212
+ "execution_count": 114,
213
+ "id": "0d1140d7",
214
+ "metadata": {},
215
+ "outputs": [],
216
+ "source": [
217
+ "def process_input(input_midi_file, input_randomness, input_duration):\n",
218
+ " midi = converter.parse(input_midi_file)\n",
219
+ " note_names = get_note_names(midi)\n",
220
+ " int_notes = [note_to_int[note_name] for note_name in note_names]\n",
221
+ " \n",
222
+ " generated_seq_multinomial = predict_multimomial(model, int_notes, predict_len = 100, temperature = 2.2)\n",
223
+ " generated_seq_multinomial = [int_to_note[e] for e in generated_seq_multinomial]\n",
224
+ " pred_midi_multinomial = create_midi(generated_seq_multinomial)\n",
225
+ " \n",
226
+ " pred_midi_multinomial.write('midi', fp='result.midi')\n",
227
+ " \n",
228
+ " # sound_font = \"/usr/share/sounds/sf2/FluidR3_GM.sf2\"\n",
229
+ " FluidSynth().midi_to_audio('result.midi', 'result.wav')\n",
230
+ " return 'result.wav', 'result.midi'"
231
+ ]
232
+ },
233
+ {
234
+ "cell_type": "code",
235
+ "execution_count": 115,
236
+ "id": "7227d54b",
237
+ "metadata": {},
238
+ "outputs": [
239
+ {
240
+ "ename": "FileNotFoundError",
241
+ "evalue": "[Errno 2] No such file or directory: 'fluidsynth'",
242
+ "output_type": "error",
243
+ "traceback": [
244
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
245
+ "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)",
246
+ "Input \u001b[0;32mIn [115]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m example_path \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m/Users/dmytrolopushanskyy/Documents/ucu/music-generation/examples/mozart.midi\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mprocess_input\u001b[49m\u001b[43m(\u001b[49m\u001b[43mexample_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m2\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m3\u001b[39;49m\u001b[43m)\u001b[49m\n",
247
+ "Input \u001b[0;32mIn [114]\u001b[0m, in \u001b[0;36mprocess_input\u001b[0;34m(input_midi_file, input_randomness, input_duration)\u001b[0m\n\u001b[1;32m 10\u001b[0m pred_midi_multinomial\u001b[38;5;241m.\u001b[39mwrite(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmidi\u001b[39m\u001b[38;5;124m'\u001b[39m, fp\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mresult.midi\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 12\u001b[0m sound_font \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/usr/share/sounds/sf2/FluidR3_GM.sf2\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 13\u001b[0m \u001b[43mFluidSynth\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmidi_to_audio\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mresult.midi\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mresult.wav\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mresult.wav\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mresult.midi\u001b[39m\u001b[38;5;124m'\u001b[39m\n",
248
+ "File \u001b[0;32m~/miniconda3/envs/hugface-demo/lib/python3.9/site-packages/midi2audio.py:46\u001b[0m, in \u001b[0;36mFluidSynth.midi_to_audio\u001b[0;34m(self, midi_file, audio_file)\u001b[0m\n\u001b[1;32m 45\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmidi_to_audio\u001b[39m(\u001b[38;5;28mself\u001b[39m, midi_file, audio_file):\n\u001b[0;32m---> 46\u001b[0m \u001b[43msubprocess\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcall\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mfluidsynth\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m-ni\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msound_font\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmidi_file\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m-F\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maudio_file\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m-r\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msample_rate\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n",
249
+ "File \u001b[0;32m~/miniconda3/envs/hugface-demo/lib/python3.9/subprocess.py:349\u001b[0m, in \u001b[0;36mcall\u001b[0;34m(timeout, *popenargs, **kwargs)\u001b[0m\n\u001b[1;32m 341\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcall\u001b[39m(\u001b[38;5;241m*\u001b[39mpopenargs, timeout\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 342\u001b[0m \u001b[38;5;124;03m\"\"\"Run command with arguments. Wait for command to complete or\u001b[39;00m\n\u001b[1;32m 343\u001b[0m \u001b[38;5;124;03m timeout, then return the returncode attribute.\u001b[39;00m\n\u001b[1;32m 344\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 347\u001b[0m \u001b[38;5;124;03m retcode = call([\"ls\", \"-l\"])\u001b[39;00m\n\u001b[1;32m 348\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 349\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mPopen\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mpopenargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m p:\n\u001b[1;32m 350\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 351\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m p\u001b[38;5;241m.\u001b[39mwait(timeout\u001b[38;5;241m=\u001b[39mtimeout)\n",
250
+ "File \u001b[0;32m~/miniconda3/envs/hugface-demo/lib/python3.9/subprocess.py:951\u001b[0m, in \u001b[0;36mPopen.__init__\u001b[0;34m(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask)\u001b[0m\n\u001b[1;32m 947\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtext_mode:\n\u001b[1;32m 948\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstderr \u001b[38;5;241m=\u001b[39m io\u001b[38;5;241m.\u001b[39mTextIOWrapper(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstderr,\n\u001b[1;32m 949\u001b[0m encoding\u001b[38;5;241m=\u001b[39mencoding, errors\u001b[38;5;241m=\u001b[39merrors)\n\u001b[0;32m--> 951\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_execute_child\u001b[49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mexecutable\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpreexec_fn\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mclose_fds\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 952\u001b[0m \u001b[43m \u001b[49m\u001b[43mpass_fds\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcwd\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43menv\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 953\u001b[0m \u001b[43m \u001b[49m\u001b[43mstartupinfo\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcreationflags\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mshell\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 954\u001b[0m \u001b[43m \u001b[49m\u001b[43mp2cread\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mp2cwrite\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 955\u001b[0m \u001b[43m \u001b[49m\u001b[43mc2pread\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mc2pwrite\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 956\u001b[0m \u001b[43m \u001b[49m\u001b[43merrread\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43merrwrite\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 957\u001b[0m \u001b[43m \u001b[49m\u001b[43mrestore_signals\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 958\u001b[0m \u001b[43m \u001b[49m\u001b[43mgid\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgids\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43muid\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mumask\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 959\u001b[0m \u001b[43m \u001b[49m\u001b[43mstart_new_session\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 960\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m:\n\u001b[1;32m 961\u001b[0m \u001b[38;5;66;03m# Cleanup if the child failed starting.\u001b[39;00m\n\u001b[1;32m 962\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m f \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mfilter\u001b[39m(\u001b[38;5;28;01mNone\u001b[39;00m, (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstdin, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstdout, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstderr)):\n",
251
+ "File \u001b[0;32m~/miniconda3/envs/hugface-demo/lib/python3.9/subprocess.py:1821\u001b[0m, in \u001b[0;36mPopen._execute_child\u001b[0;34m(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)\u001b[0m\n\u001b[1;32m 1819\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m errno_num \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 1820\u001b[0m err_msg \u001b[38;5;241m=\u001b[39m os\u001b[38;5;241m.\u001b[39mstrerror(errno_num)\n\u001b[0;32m-> 1821\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m child_exception_type(errno_num, err_msg, err_filename)\n\u001b[1;32m 1822\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m child_exception_type(err_msg)\n",
252
+ "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'fluidsynth'"
253
+ ]
254
+ }
255
+ ],
256
+ "source": [
257
+ "example_path = '/Users/dmytrolopushanskyy/Documents/ucu/music-generation/examples/mozart.midi'\n",
258
+ "process_input(example_path, 2, 3)"
259
+ ]
260
+ },
261
+ {
262
+ "cell_type": "code",
263
+ "execution_count": null,
264
+ "id": "01491a9f",
265
+ "metadata": {},
266
+ "outputs": [],
267
+ "source": [
268
+ "midi_file_desc = \"\"\"\n",
269
+ "This model allows to generate music based on your input. \n",
270
+ "Please upload a MIDI file below, choose music randomness and duration. Enjoy!\n",
271
+ "\"\"\"\n",
272
+ "\n",
273
+ "article = \"\"\"# Music Generation\n",
274
+ "This project has been created by the students of Ukrainian Catholic University for our ML course.\n",
275
+ "\n",
276
+ "We are using a GRU model to output new notes based on the given input. You can find more information at our Git repo: https://github.com/DmytroLopushanskyy/music-generation\n",
277
+ "We are using a language model to create music by treating a musical standard MIDI a simple text, with tokens for note values, note duration, and separations to denote movement forward in time.\n",
278
+ "\"\"\"\n",
279
+ "\n",
280
+ "iface = gr.Interface(\n",
281
+ " fn=process_input, \n",
282
+ " inputs=[\n",
283
+ " gr.inputs.File(label=midi_file_desc),\n",
284
+ " gr.inputs.Slider(0, 250, default=100, step=50),\n",
285
+ " gr.inputs.Radio([10, 20, 30], type=\"value\", default=20)\n",
286
+ " ], \n",
287
+ " outputs=[\"audio\", \"file\"],\n",
288
+ " article=article,\n",
289
+ " examples=['examples/mozart.midi']\n",
290
+ ")\n",
291
+ "\n",
292
+ "iface.launch()"
293
+ ]
294
+ }
295
+ ],
296
+ "metadata": {
297
+ "kernelspec": {
298
+ "display_name": "Python 3 (ipykernel)",
299
+ "language": "python",
300
+ "name": "python3"
301
+ },
302
+ "language_info": {
303
+ "codemirror_mode": {
304
+ "name": "ipython",
305
+ "version": 3
306
+ },
307
+ "file_extension": ".py",
308
+ "mimetype": "text/x-python",
309
+ "name": "python",
310
+ "nbconvert_exporter": "python",
311
+ "pygments_lexer": "ipython3",
312
+ "version": "3.9.12"
313
+ }
314
+ },
315
+ "nbformat": 4,
316
+ "nbformat_minor": 5
317
+ }
objects/.DS_Store ADDED
Binary file (6.15 kB). View file
 
objects/int_to_note.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4fe1e610f0141d28688665699dece4874401b0ab34c567d976cf15e9005f4950
3
+ size 11141
objects/model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d7b7367ebab17c01d1d0127193a603335c432525431488c80a7073bc1c607e71
3
+ size 4615215
objects/model_cpu.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7b17bffabc953e0d18122c78e9ef6ba7924c536e54e742bd6ca398ecc72a1e1e
3
+ size 1486285
objects/note_to_int.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0221d1cb9e7fe0839a8a5c1342006618f917413102968d73b7bc4f0921aed346
3
+ size 11141
packages.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ fluidsynth
2
+ fluid-soundfont-gm
3
+ fluid-soundfont-gs
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ musicautobot
2
+ fastai==1.0.61
3
+ music21
4
+ pebble
5
+ midi2audio
6
+ spacy
7
+ transformers
8
+ gradio
9
+ pretty_midi
10
+ pypianoroll