asigalov61 commited on
Commit
2d9a4a0
·
verified ·
1 Parent(s): dc2151f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -199
app.py CHANGED
@@ -129,7 +129,48 @@ def kmp_search(main_list, sublist):
129
 
130
  #==================================================================================
131
 
132
- def Remix_MIDI(max_num_loops,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  comp_loops_mult,
134
  chords_chunks_len,
135
  loops_chords_set_len
@@ -142,8 +183,13 @@ def Remix_MIDI(max_num_loops,
142
  start_time = reqtime.time()
143
  print('=' * 70)
144
 
 
 
 
 
145
  print('Requested settings:')
146
  print('=' * 70)
 
147
  print('Max number of loops:', max_num_loops)
148
  print('Num of loops reps:', comp_loops_mult)
149
  print('Matches chords chunks len:', chords_chunks_len)
@@ -153,24 +199,20 @@ def Remix_MIDI(max_num_loops,
153
 
154
  #===============================================================================
155
 
156
- print('Prepping dataset...')
157
-
158
- chunk_len = chords_chunks_len
159
- chunk_chords_set = loops_chords_set_len
160
 
161
- all_chords_chunks = []
162
 
163
- midi_loops = [l for l in midi_loops_dataset if len(set(l[1])) >= chunk_chords_set]
 
 
164
 
165
- for loop in tqdm.tqdm(midi_loops):
166
-
167
- fn = loop[0]
168
- chords = loop[1]
169
- score = loop[2]
170
-
171
- all_chords_chunks.append(chords[:chunk_len])
172
 
173
- all_chords_chunks = np.array(all_chords_chunks)
 
 
 
174
 
175
  print('Done!')
176
  print('=' * 70)
@@ -179,106 +221,65 @@ def Remix_MIDI(max_num_loops,
179
 
180
  #==================================================================
181
 
182
- print('Mixing loops...')
183
  print('=' * 70)
184
 
185
- max_tries = 100
186
- loops_mult = 1
187
-
188
- song_loops_counter = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
- stries = 0
 
191
 
192
- while song_loops_counter < max_num_loops:
193
 
194
- if stries % 25 == 0:
195
- print('Mixing attempt #', stries)
196
-
197
- stries += 1
198
 
199
- midxs = []
200
- sidxs = [-1]
201
-
202
- while not midxs:
203
-
204
- song_names = []
205
- song_chords = []
206
- song_scores = []
207
- song_idxs = []
208
- sidx = -1
209
-
210
- while sidx in sidxs:
211
- sidx = random.randint(0, len(midi_loops)-1)
212
-
213
- song_idxs.append(sidx)
214
- sidxs.append(sidx)
215
-
216
- song_names.append(midi_loops[sidx][0])
217
- song_chords.append(midi_loops[sidx][1][-chunk_len:]) #tv
218
- song_scores.append(midi_loops[sidx][2])
219
-
220
- song_midxs = [(song_idxs[-1]*loops_mult)+3]
221
-
222
- midxs = [song_midxs[-1]]
223
-
224
- midxs = find_matches(np.array(song_chords[-1]), all_chords_chunks)
225
- midxs = [midx for midx in midxs if midx != song_midxs[-1]]
226
-
227
- song_loops_counter = 1
228
- rtries = 0
229
- end = False
230
-
231
- while song_loops_counter < max_num_loops and not end:
232
-
233
- midxs = [song_midxs[-1]]
234
- midxs = []
235
- rmidxs = [-1]
236
-
237
- midxs = find_matches(np.array(song_chords[-1]), all_chords_chunks)
238
- midxs = [midx for midx in midxs if midx != song_midxs[-1]]
239
-
240
- if midxs:
241
- midx = find_best_midx(midi_loops, midxs, song_midxs[-1])
242
-
243
- else:
244
- midx = rmidxs[-1]
245
-
246
- if midx not in rmidxs and midx not in song_midxs:
247
-
248
- song_midxs.append(midx)
249
 
250
- sidx = int(midx // loops_mult)
251
- song_idxs.append(sidx)
252
-
253
- song = midi_loops[sidx]
254
-
255
- song_names.append(song[0])
256
- song_chords.append(song[1][-chunk_len:]) # tv
257
- song_scores.append(song[2])
258
-
259
- song_loops_counter += 1
260
 
261
- else:
262
- if len(rmidxs) > 1 and rtries < max_tries:
263
- song_idxs.pop()
264
- song_midxs.pop()
265
- song_names.pop()
266
- song_chords.pop()
267
- song_scores.pop()
268
- song_loops_counter -= 1
269
- rtries += 1
270
- rmidxs.append(midx)
271
 
272
- else:
273
- end = True
274
- break
275
 
276
- if end:
277
- break
278
-
279
- if stries > 1000:
280
- break
281
-
 
 
 
 
282
  print('=' * 70)
283
  print('Done!')
284
  print('=' * 70)
@@ -287,105 +288,41 @@ def Remix_MIDI(max_num_loops,
287
 
288
  print('Creating final MIDI score...')
289
 
290
- loops_mult = comp_loops_mult
291
 
292
- final_song = []
293
-
294
- last_max_dur = 0
295
- last_dtime = 0
296
- mode_dtime = 0
297
- mode_dur = 0
298
 
299
- for i, src_score in enumerate(song_scores):
300
-
301
- final_song.append(['text_event', 0, song_names[i]])
302
-
303
- score = copy.deepcopy(src_score)
304
-
305
- for j in range(loops_mult):
306
-
307
- if j == loops_mult-1 and not (i == len(song_scores)-1 and j == loops_mult-1):
308
 
309
- if i > 0:
310
- last_chord = score[[e for e in range(len(score)) if score[e][0] > 0][-1]:]
311
- last_dtime = last_chord[0][0]
312
- last_max_dur = max([e[1] for e in last_chord])
313
-
314
- dtimes = [e[0] for e in score if e[0] != 0]
315
- durs = [e[1] for e in score]
316
-
317
- mode_dtime= statistics.mode(dtimes)
318
- mode_dur = statistics.mode(durs)
319
-
320
- score[0][0] = max(mode_dtime, mode_dur)
321
-
322
- rscore = list(reversed(score))
323
-
324
- ccount = 0
325
-
326
- for r in range(len(rscore)):
327
- if rscore[r][0] > 0:
328
- ccount += 1
329
-
330
- if ccount == chunk_len:
331
- break
332
-
333
- trimmed_score = score[:-(r+1)]
334
 
335
- extended_score = [['note'] + e for e in trimmed_score]
336
 
337
- final_song.extend(extended_score)
338
-
 
339
 
340
- else:
341
- if i > 0:
342
- last_chord = score[[e for e in range(len(score)) if score[e][0] > 0][-1]:]
343
- last_dtime = last_chord[0][0]
344
- last_max_dur = max([e[1] for e in last_chord])
345
-
346
- dtimes = [e[0] for e in score if e[0] != 0]
347
- durs = [e[1] for e in score]
348
-
349
- mode_dtime= statistics.mode(dtimes)
350
- mode_dur = statistics.mode(durs)
351
-
352
- score[0][0] = max(mode_dtime, mode_dur)
353
 
354
- extended_score = [['note'] + e for e in score]
355
-
356
- final_song.extend(extended_score)
357
-
358
- final_song_abs = TMIDIX.delta_score_to_abs_score(final_song)
359
 
360
  print('Done!')
361
  print('=' * 70)
362
 
363
- #===============================================================================
364
-
365
- print('Creating MIDI summary...')
366
-
367
- midi_summary = 'Number of source MIDI loops: ' + str(len(song_names) * loops_mult) + '\n'
368
- midi_summary += '-' * 40
369
- midi_summary += '\n'
370
-
371
- for i, song_name in enumerate(song_names):
372
-
373
- son_art = song_name.split('___')[:2]
374
-
375
- son = son_art[0]
376
- art = son_art[1]
377
-
378
- midi_summary += 'Loops # ' + str((i*loops_mult)+1) + '-' + str((i*loops_mult)+loops_mult) + ': "' + son + '" by ' + art + '\n'
379
-
380
- #===============================================================================
381
 
382
  print('Rendering results...')
383
 
384
  print('=' * 70)
385
- print('Sample MIDI events:', final_song_abs[:3])
386
  print('=' * 70)
387
 
388
- output_score, patches, overflow_patches = TMIDIX.patch_enhanced_score_notes(final_song_abs)
389
 
390
  fn1 = "MIDI-Remixer-Composition"
391
 
@@ -412,7 +349,6 @@ def Remix_MIDI(max_num_loops,
412
 
413
  #========================================================
414
 
415
- output_midi_summary = str(midi_summary)
416
  output_midi = str(new_fn)
417
  output_audio = (16000, audio)
418
 
@@ -424,10 +360,6 @@ def Remix_MIDI(max_num_loops,
424
 
425
  print('Output MIDI file name:', output_midi)
426
  print('=' * 70)
427
- print('Output MIDI summary:')
428
- print('-' * 70)
429
- print(output_midi_summary)
430
- print('=' * 70)
431
 
432
  #========================================================
433
 
@@ -436,7 +368,7 @@ def Remix_MIDI(max_num_loops,
436
  print('-' * 70)
437
  print('Req execution time:', (reqtime.time() - start_time), 'sec')
438
 
439
- return output_midi_summary, output_audio, output_plot, output_midi
440
 
441
  #==================================================================================
442
 
@@ -475,25 +407,22 @@ with gr.Blocks() as demo:
475
  chords_chunks_len = gr.Slider(6, 10, value=6, step=1, label="Number of loops chords to match")
476
  loops_chords_set_len = gr.Slider(16, 24, value=16, step=1, label="Minimum number of unique chords in each loop")
477
 
478
- mix_btn = gr.Button("Mix", variant="primary")
479
 
480
  gr.Markdown("## Mixing results")
481
 
482
- output_midi_summary = gr.Textbox(label="MIDI summary")
483
  output_audio = gr.Audio(label="MIDI audio", format="wav", elem_id="midi_audio")
484
  output_plot = gr.Plot(label="MIDI score plot")
485
  output_midi = gr.File(label="MIDI file", file_types=[".mid"])
486
 
487
  mix_btn.click(Remix_MIDI,
488
- [
489
  max_num_loops,
490
  comp_loops_mult,
491
  chords_chunks_len,
492
  loops_chords_set_len
493
  ],
494
- [
495
- output_midi_summary,
496
- output_audio,
497
  output_plot,
498
  output_midi
499
  ]
 
129
 
130
  #==================================================================================
131
 
132
+ def load_midi(midi_file):
133
+
134
+ print('Loading MIDI...')
135
+
136
+ raw_score = TMIDIX.midi2single_track_ms_score(midi_file)
137
+ escore_notes = TMIDIX.advanced_score_processor(raw_score, return_enhanced_score_notes=True)[0]
138
+ escore_notes = TMIDIX.augment_enhanced_score_notes(escore_notes, sort_drums_last=True)
139
+
140
+ zscore = TMIDIX.recalculate_score_timings(escore_notes)
141
+
142
+ cscore = TMIDIX.chordify_score([1000, zscore])
143
+
144
+ tones_chords = []
145
+ tones_chords_idxs = []
146
+
147
+ for i, c in enumerate(cscore):
148
+ pitches = [e[4] for e in c if e[3] != 9]
149
+
150
+ if pitches:
151
+ tones_chord = sorted(set([p % 12 for p in pitches]))
152
+
153
+ if tones_chord in TMIDIX.ALL_CHORDS_SORTED:
154
+ chord_token = TMIDIX.ALL_CHORDS_SORTED.index(tones_chord)
155
+
156
+ else:
157
+ tones_chord = TMIDIX.check_and_fix_tones_chord(tones_chord)
158
+ chord_token = TMIDIX.ALL_CHORDS_SORTED.index(tones_chord)
159
+
160
+ tones_chords.append(chord_token)
161
+ tones_chords_idxs.append(i)
162
+
163
+ print('Done!')
164
+ print('=' * 70)
165
+ print('MIDI has', len(tones_chords), 'chords')
166
+ print('=' * 70)
167
+
168
+ return tones_chords, tones_chords_idxs
169
+
170
+ #==================================================================================
171
+
172
+ def Remix_MIDI(input_midi,
173
+ max_num_loops,
174
  comp_loops_mult,
175
  chords_chunks_len,
176
  loops_chords_set_len
 
183
  start_time = reqtime.time()
184
  print('=' * 70)
185
 
186
+ fn = os.path.basename(input_midi)
187
+ fn1 = fn.split('.')[0]
188
+
189
+ print('=' * 70)
190
  print('Requested settings:')
191
  print('=' * 70)
192
+ print('Input MIDI file name:', fn)
193
  print('Max number of loops:', max_num_loops)
194
  print('Num of loops reps:', comp_loops_mult)
195
  print('Matches chords chunks len:', chords_chunks_len)
 
199
 
200
  #===============================================================================
201
 
202
+ tones_chords, tones_chords_idxs = load_midi(input_midi.name)
 
 
 
203
 
204
+ #===============================================================================
205
 
206
+ print('Prepping chords chunks...')
207
+
208
+ chunk_len = 4
209
 
210
+ all_chords_chunks = Counter()
 
 
 
 
 
 
211
 
212
+ for i in range(0, len(tones_chords)):
213
+ chunk = tones_chords[i:i+chunk_len]
214
+ if len(chunk) == chunk_len:
215
+ all_chords_chunks[tuple(chunk)] += 1
216
 
217
  print('Done!')
218
  print('=' * 70)
 
221
 
222
  #==================================================================
223
 
224
+ print('Remixing MIDI...')
225
  print('=' * 70)
226
 
227
+ other_chunks = [list(k) for k, v in all_chords_chunks.most_common(10)]
228
+
229
+ all_match_chunks = {}
230
+
231
+ for mc_chunk in other_chunks:
232
+ chunk_lens = fuzzy_find([len(l) for l in split_by_sublist(tones_chords, mc_chunk) if len(l) > chunk_len])
233
+ match_chunks = [l for l in split_by_sublist(tones_chords, mc_chunk) if len(l) in chunk_lens]
234
+ all_match_chunks[tuple(mc_chunk)] = match_chunks
235
+
236
+ chunks_map = random.choices(other_chunks, k=10)
237
+
238
+ #==================================================================
239
+
240
+ matched_chunks = []
241
+ start_chunk = []
242
+ res = -1
243
+ tries = 0
244
+ while res == -1 and len(start_chunk[:res]) < chunk_len and tries < 100:
245
 
246
+ start_chunk = random.choice(all_match_chunks[tuple(chunks_map[0])])
247
+ res = kmp_search(start_chunk, chunks_map[1])[0]
248
 
249
+ tries += 1
250
 
251
+ #print(res)
252
+ if tries < 100:
253
+ matched_chunks.append(start_chunk[:res])
 
254
 
255
+ else:
256
+ print('FAIL!')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
 
258
+ #==================================================================
259
+
260
+ mchunks = [-1]
261
+ tries = 0
262
+ while -1 in mchunks and tries < 100:
263
+
264
+ mchunks = []
 
 
 
265
 
266
+ for i, chunk in enumerate(chunks_map[1:-1]):
267
+ start_chunk = random.choice(all_match_chunks[tuple(chunk)])
268
+ res = kmp_search(start_chunk, chunks_map[i+2])[0]
 
 
 
 
 
 
 
269
 
270
+ #print(res)
271
+ mchunks.append(start_chunk[:res])
 
272
 
273
+ tries += 1
274
+
275
+ if tries < 100:
276
+ matched_chunks.extend(mchunks)
277
+
278
+ else:
279
+ print('FAIL!')
280
+
281
+ #==================================================================
282
+
283
  print('=' * 70)
284
  print('Done!')
285
  print('=' * 70)
 
288
 
289
  print('Creating final MIDI score...')
290
 
291
+ all_matches_dscores = []
292
 
293
+ for match in matched_chunks:
 
 
 
 
 
294
 
295
+ start, end = kmp_search(tones_chords, match)
296
+
297
+ sidx = tones_chords_idxs[start]
298
+ eidx = tones_chords_idxs[end]
 
 
 
 
 
299
 
300
+ all_matches_dscores.append(TMIDIX.delta_score_notes(TMIDIX.flatten(cscore[sidx:eidx+1])))
301
+
302
+ #===============================================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
 
304
+ new_dscore = all_matches_dscores[0]
305
 
306
+ for score in all_matches_dscores[1:]:
307
+ score[0][1] = statistics.mode([e[1] for e in new_dscore[-75:] if e[1] != 0 and e[3] != 9])
308
+ new_dscore.extend(score)
309
 
310
+ new_escore = TMIDIX.delta_score_to_abs_score(new_dscore)
 
 
 
 
 
 
 
 
 
 
 
 
311
 
312
+ #===============================================================================
 
 
 
 
313
 
314
  print('Done!')
315
  print('=' * 70)
316
 
317
+ #===============================================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
 
319
  print('Rendering results...')
320
 
321
  print('=' * 70)
322
+ print('Sample MIDI events:', new_escore[:3])
323
  print('=' * 70)
324
 
325
+ output_score, patches, overflow_patches = TMIDIX.patch_enhanced_score_notes(new_escore)
326
 
327
  fn1 = "MIDI-Remixer-Composition"
328
 
 
349
 
350
  #========================================================
351
 
 
352
  output_midi = str(new_fn)
353
  output_audio = (16000, audio)
354
 
 
360
 
361
  print('Output MIDI file name:', output_midi)
362
  print('=' * 70)
 
 
 
 
363
 
364
  #========================================================
365
 
 
368
  print('-' * 70)
369
  print('Req execution time:', (reqtime.time() - start_time), 'sec')
370
 
371
+ return output_audio, output_plot, output_midi
372
 
373
  #==================================================================================
374
 
 
407
  chords_chunks_len = gr.Slider(6, 10, value=6, step=1, label="Number of loops chords to match")
408
  loops_chords_set_len = gr.Slider(16, 24, value=16, step=1, label="Minimum number of unique chords in each loop")
409
 
410
+ mix_btn = gr.Button("Remix", variant="primary")
411
 
412
  gr.Markdown("## Mixing results")
413
 
 
414
  output_audio = gr.Audio(label="MIDI audio", format="wav", elem_id="midi_audio")
415
  output_plot = gr.Plot(label="MIDI score plot")
416
  output_midi = gr.File(label="MIDI file", file_types=[".mid"])
417
 
418
  mix_btn.click(Remix_MIDI,
419
+ [input_midi,
420
  max_num_loops,
421
  comp_loops_mult,
422
  chords_chunks_len,
423
  loops_chords_set_len
424
  ],
425
+ [output_audio,
 
 
426
  output_plot,
427
  output_midi
428
  ]