asigalov61 commited on
Commit
6df655f
1 Parent(s): 6e75fcb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +357 -2
app.py CHANGED
@@ -11,10 +11,19 @@ import json
11
  import MIDI
12
  from midi_synthesizer import synthesis
13
 
 
 
 
 
 
14
  import matplotlib.pyplot as plt
15
 
 
 
16
  in_space = os.getenv("SYSTEM") == "spaces"
17
 
 
 
18
  def run(midi, progress=gr.Progress()):
19
 
20
  mid_seq = MIDI.midi2score(midi)
@@ -53,6 +62,352 @@ def run(midi, progress=gr.Progress()):
53
  audio = synthesis(MIDI.score2opus([mid_seq_ticks, mid_seq]), soundfont_path)
54
  yield mdata, "output.mid", (44100, audio), plt
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  if __name__ == "__main__":
57
  parser = argparse.ArgumentParser()
58
  parser.add_argument("--share", action="store_true", default=False, help="share gradio app")
@@ -88,7 +443,7 @@ if __name__ == "__main__":
88
  output_midi_seq = gr.Textbox(label="output midi metadata")
89
  output_plot = gr.Plot(label="output midi plot")
90
 
91
- run_event = input_midi.upload(run, [input_midi],
92
- [output_midi_seq, output_midi, output_audio, output_plot])
93
 
94
  app.queue(1).launch(server_port=opt.port, share=opt.share, inbrowser=True)
 
11
  import MIDI
12
  from midi_synthesizer import synthesis
13
 
14
+ import copy
15
+ from collections import Counter
16
+ import random
17
+ import statistics
18
+
19
  import matplotlib.pyplot as plt
20
 
21
+ #==========================================================================================================
22
+
23
  in_space = os.getenv("SYSTEM") == "spaces"
24
 
25
+ #==========================================================================================================
26
+
27
  def run(midi, progress=gr.Progress()):
28
 
29
  mid_seq = MIDI.midi2score(midi)
 
62
  audio = synthesis(MIDI.score2opus([mid_seq_ticks, mid_seq]), soundfont_path)
63
  yield mdata, "output.mid", (44100, audio), plt
64
 
65
+ #==========================================================================================================
66
+
67
+ def match_midi(midi, progress=gr.Progress()):
68
+
69
+ print('=' * 70)
70
+ print('Loading MIDI file...')
71
+
72
+ #==================================================
73
+
74
+ score = MIDI.midi2score(midi)
75
+
76
+ events_matrix = []
77
+
78
+ track_count = 0
79
+
80
+ for s in score:
81
+
82
+ if track_count > 0:
83
+ track = s
84
+ track.sort(key=lambda x: x[1])
85
+ events_matrix.extend(track)
86
+ else:
87
+ midi_ticks = s
88
+
89
+ track_count += 1
90
+
91
+ events_matrix.sort(key=lambda x: x[1])
92
+
93
+ mult_pitches_counts = []
94
+
95
+ for i in range(-6, 6):
96
+
97
+ events_matrix1 = []
98
+
99
+ for e in events_matrix:
100
+
101
+ ev = copy.deepcopy(e)
102
+
103
+ if e[0] == 'note':
104
+ if e[3] == 9:
105
+ ev[4] = ((e[4] % 128) + 128)
106
+ else:
107
+ ev[4] = ((e[4] % 128) + i)
108
+
109
+ events_matrix1.append(ev)
110
+
111
+ pitches_counts = [[y[0],y[1]] for y in Counter([y[4] for y in events_matrix1 if y[0] == 'note']).most_common()]
112
+ pitches_counts.sort(key=lambda x: x[0], reverse=True)
113
+
114
+ mult_pitches_counts.append(pitches_counts)
115
+
116
+ patches_list = sorted(list(set([y[3] for y in events_matrix if y[0] == 'patch_change'])))
117
+
118
+
119
+ #==================================================
120
+
121
+ ms_score = MIDI.midi2ms_score(midi)
122
+
123
+ ms_events_matrix = []
124
+
125
+ itrack1 = 1
126
+
127
+ while itrack1 < len(ms_score):
128
+ for event in ms_score[itrack1]:
129
+ if event[0] == 'note':
130
+ ms_events_matrix.append(event)
131
+ itrack1 += 1
132
+
133
+ ms_events_matrix.sort(key=lambda x: x[1])
134
+
135
+
136
+ chords = []
137
+ pe = ms_events_matrix[0]
138
+ cho = []
139
+ for e in ms_events_matrix:
140
+ if (e[1] - pe[1]) == 0:
141
+ if e[3] != 9:
142
+ if (e[4] % 12) not in cho:
143
+ cho.append(e[4] % 12)
144
+ else:
145
+ if len(cho) > 0:
146
+ chords.append(sorted(cho))
147
+ cho = []
148
+ if e[3] != 9:
149
+ if (e[4] % 12) not in cho:
150
+ cho.append(e[4] % 12)
151
+
152
+ pe = e
153
+
154
+ if len(cho) > 0:
155
+ chords.append(sorted(cho))
156
+
157
+ ms_chords_counts = sorted([[list(key), val] for key,val in Counter([tuple(c) for c in chords if len(c) > 1]).most_common()], reverse=True, key = lambda x: x[1])
158
+
159
+ times = []
160
+ pt = ms_events_matrix[0][1]
161
+ start = True
162
+ for e in ms_events_matrix:
163
+ if (e[1]-pt) != 0 or start == True:
164
+ times.append((e[1]-pt))
165
+ start = False
166
+ pt = e[1]
167
+
168
+ durs = [e[2] for e in ms_events_matrix]
169
+ vels = [e[5] for e in ms_events_matrix]
170
+
171
+ avg_time = int(sum(times) / len(times))
172
+ avg_dur = int(sum(durs) / len(durs))
173
+
174
+ mode_time = statistics.mode(times)
175
+ mode_dur = statistics.mode(durs)
176
+
177
+ median_time = int(statistics.median(times))
178
+ median_dur = int(statistics.median(durs))
179
+
180
+ #==================================================
181
+
182
+ print('=' * 70)
183
+ print('Done!')
184
+ print('=' * 70)
185
+
186
+ #==========================================================================================================
187
+
188
+ #@title MIDI Pitches Search
189
+
190
+ #@markdown Match ratio control option
191
+
192
+ maximum_match_ratio_to_search_for = 1 #@param {type:"slider", min:0, max:1, step:0.01}
193
+
194
+ #@markdown MIDI pitches search options
195
+
196
+ pitches_counts_cutoff_threshold_ratio = 0 #@param {type:"slider", min:0, max:1, step:0.05}
197
+ search_transposed_pitches = False #@param {type:"boolean"}
198
+ skip_exact_matches = True #@param {type:"boolean"}
199
+
200
+ #@markdown Additional search options
201
+
202
+ add_pitches_counts_ratios = False #@param {type:"boolean"}
203
+ add_timings_ratios = False #@param {type:"boolean"}
204
+ add_durations_ratios = False #@param {type:"boolean"}
205
+
206
+ print('=' * 70)
207
+ print('MIDI Pitches Search')
208
+ print('=' * 70)
209
+
210
+ final_ratios = []
211
+
212
+ for d in progress.tqdm(meta_data):
213
+
214
+ try:
215
+ p_counts = d[1][10][1]
216
+ p_counts.sort(reverse = True, key = lambda x: x[1])
217
+ max_p_count = p_counts[0][1]
218
+ trimmed_p_counts = [y for y in p_counts if y[1] >= (max_p_count * pitches_counts_cutoff_threshold_ratio)]
219
+ total_p_counts = sum([y[1] for y in trimmed_p_counts])
220
+
221
+ if search_transposed_pitches:
222
+ search_pitches = mult_pitches_counts
223
+ else:
224
+ search_pitches = [mult_pitches_counts[6]]
225
+
226
+ #===================================================
227
+
228
+ ratios_list = []
229
+
230
+ #===================================================
231
+
232
+ atrat = [0]
233
+
234
+ if add_timings_ratios:
235
+
236
+ source_times = [avg_time,
237
+ median_time,
238
+ mode_time]
239
+
240
+ match_times = meta_data[0][1][3][1]
241
+
242
+ times_ratios = []
243
+
244
+ for i in range(len(source_times)):
245
+ maxtratio = max(source_times[i], match_times[i])
246
+ mintratio = min(source_times[i], match_times[i])
247
+ times_ratios.append(mintratio / maxtratio)
248
+
249
+ avg_times_ratio = sum(times_ratios) / len(times_ratios)
250
+
251
+ atrat[0] = avg_times_ratio
252
+
253
+ #===================================================
254
+
255
+ adrat = [0]
256
+
257
+ if add_durations_ratios:
258
+
259
+ source_durs = [avg_dur,
260
+ median_dur,
261
+ mode_dur]
262
+
263
+ match_durs = meta_data[0][1][4][1]
264
+
265
+ durs_ratios = []
266
+
267
+ for i in range(len(source_durs)):
268
+ maxtratio = max(source_durs[i], match_durs[i])
269
+ mintratio = min(source_durs[i], match_durs[i])
270
+ durs_ratios.append(mintratio / maxtratio)
271
+
272
+ avg_durs_ratio = sum(durs_ratios) / len(durs_ratios)
273
+
274
+ adrat[0] = avg_durs_ratio
275
+
276
+ #===================================================
277
+
278
+ for m in search_pitches:
279
+
280
+ sprat = []
281
+
282
+ m.sort(reverse = True, key = lambda x: x[1])
283
+ max_pitches_count = m[0][1]
284
+ trimmed_pitches_counts = [y for y in m if y[1] >= (max_pitches_count * pitches_counts_cutoff_threshold_ratio)]
285
+ total_pitches_counts = sum([y[1] for y in trimmed_pitches_counts])
286
+
287
+ same_pitches = set([T[0] for T in trimmed_p_counts]) & set([m[0] for m in trimmed_pitches_counts])
288
+ num_same_pitches = len(same_pitches)
289
+
290
+ if num_same_pitches == len(trimmed_pitches_counts):
291
+ same_pitches_ratio = (num_same_pitches / len(trimmed_p_counts))
292
+ else:
293
+ same_pitches_ratio = (num_same_pitches / max(len(trimmed_p_counts), len(trimmed_pitches_counts)))
294
+
295
+ if skip_exact_matches:
296
+ if same_pitches_ratio == 1:
297
+ same_pitches_ratio = 0
298
+
299
+ sprat.append(same_pitches_ratio)
300
+
301
+ #===================================================
302
+
303
+ spcrat = [0]
304
+
305
+ if add_pitches_counts_ratios:
306
+
307
+ same_trimmed_p_counts = sorted([T for T in trimmed_p_counts if T[0] in same_pitches], reverse = True)
308
+ same_trimmed_pitches_counts = sorted([T for T in trimmed_pitches_counts if T[0] in same_pitches], reverse = True)
309
+
310
+ same_trimmed_p_counts_ratios = [[s[0], s[1] / total_p_counts] for s in same_trimmed_p_counts]
311
+ same_trimmed_pitches_counts_ratios = [[s[0], s[1] / total_pitches_counts] for s in same_trimmed_pitches_counts]
312
+
313
+ same_pitches_counts_ratios = []
314
+
315
+ for i in range(len(same_trimmed_p_counts_ratios)):
316
+ mincratio = min(same_trimmed_p_counts_ratios[i][1], same_trimmed_pitches_counts_ratios[i][1])
317
+ maxcratio = max(same_trimmed_p_counts_ratios[i][1], same_trimmed_pitches_counts_ratios[i][1])
318
+ same_pitches_counts_ratios.append([same_trimmed_p_counts_ratios[i][0], mincratio / maxcratio])
319
+
320
+ same_counts_ratios = [s[1] for s in same_pitches_counts_ratios]
321
+
322
+ if len(same_counts_ratios) > 0:
323
+ avg_same_pitches_counts_ratio = sum(same_counts_ratios) / len(same_counts_ratios)
324
+ else:
325
+ avg_same_pitches_counts_ratio = 0
326
+
327
+ spcrat[0] = avg_same_pitches_counts_ratio
328
+
329
+ #===================================================
330
+
331
+ r_list = [sprat[0]]
332
+
333
+ if add_pitches_counts_ratios:
334
+ r_list.append(spcrat[0])
335
+
336
+ if add_timings_ratios:
337
+ r_list.append(atrat[0])
338
+
339
+ if add_durations_ratios:
340
+ r_list.append(adrat[0])
341
+
342
+ ratios_list.append(r_list)
343
+
344
+ #===================================================
345
+
346
+ avg_ratios_list = []
347
+
348
+ for r in ratios_list:
349
+ avg_ratios_list.append(sum(r) / len(r))
350
+
351
+ #===================================================
352
+
353
+ final_ratio = max(avg_ratios_list)
354
+
355
+ if final_ratio > maximum_match_ratio_to_search_for:
356
+ final_ratio = 0
357
+
358
+ final_ratios.append(final_ratio)
359
+
360
+ #===================================================
361
+
362
+ max_ratio = max(final_ratios)
363
+ max_ratio_index = final_ratios.index(max_ratio)
364
+
365
+ print('FOUND')
366
+ print('=' * 70)
367
+ print('Match ratio', max_ratio)
368
+ print('MIDI file name', meta_data[max_ratio_index][0])
369
+ print('=' * 70)
370
+
371
+ fn = meta_data[max_ratio_index][0]
372
+
373
+ #==========================================================================================================
374
+
375
+ md = meta_data[max_ratio_index]
376
+
377
+ mid_seq = md[1][17:-1]
378
+ mid_seq_ticks = md[1][16][1]
379
+ mdata = md[1][:16]
380
+
381
+ x = []
382
+ y = []
383
+ c = []
384
+
385
+ colors = ['red', 'yellow', 'green', 'cyan',
386
+ 'blue', 'pink', 'orange', 'purple',
387
+ 'gray', 'white', 'gold', 'silver',
388
+ 'lightgreen', 'indigo', 'maroon', 'turquoise']
389
+
390
+ for s in [m for m in mid_seq if m[0] == 'note']:
391
+ x.append(s[1])
392
+ y.append(s[4])
393
+ c.append(colors[s[3]])
394
+
395
+ plt.close()
396
+ plt.figure(figsize=(14,5))
397
+ ax=plt.axes(title='MIDI Search Plot')
398
+ ax.set_facecolor('black')
399
+
400
+ plt.scatter(x,y, c=c)
401
+ plt.xlabel("Time")
402
+ plt.ylabel("Pitch")
403
+
404
+ with open(f"output.mid", 'wb') as f:
405
+ f.write(MIDI.score2midi([mid_seq_ticks, mid_seq]))
406
+ audio = synthesis(MIDI.score2opus([mid_seq_ticks, mid_seq]), soundfont_path)
407
+ yield mdata, "output.mid", (44100, audio), plt
408
+
409
+ #==========================================================================================================
410
+
411
  if __name__ == "__main__":
412
  parser = argparse.ArgumentParser()
413
  parser.add_argument("--share", action="store_true", default=False, help="share gradio app")
 
443
  output_midi_seq = gr.Textbox(label="output midi metadata")
444
  output_plot = gr.Plot(label="output midi plot")
445
 
446
+ run_event = input_midi.upload(match_midi, [input_midi],
447
+ [output_midi_seq, output_midi, output_audio, output_plot])
448
 
449
  app.queue(1).launch(server_port=opt.port, share=opt.share, inbrowser=True)