Spaces:
Running
on
Zero
Running
on
Zero
asigalov61
commited on
Commit
•
44d8f4c
1
Parent(s):
0ba1e11
Upload 2 files
Browse files
TMIDIX.py
CHANGED
@@ -1484,6 +1484,7 @@ from abc import ABC, abstractmethod
|
|
1484 |
from difflib import SequenceMatcher as SM
|
1485 |
|
1486 |
import statistics
|
|
|
1487 |
|
1488 |
import matplotlib.pyplot as plt
|
1489 |
|
@@ -1762,7 +1763,10 @@ def plot_ms_SONG(ms_song,
|
|
1762 |
note_height = 0.75,
|
1763 |
show_grid_lines=False,
|
1764 |
return_plt = False,
|
1765 |
-
timings_multiplier=1
|
|
|
|
|
|
|
1766 |
):
|
1767 |
|
1768 |
'''Tegridy ms SONG plotter/vizualizer'''
|
@@ -1816,10 +1820,22 @@ def plot_ms_SONG(ms_song,
|
|
1816 |
|
1817 |
plt.title(plot_title)
|
1818 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1819 |
if return_plt:
|
1820 |
return fig
|
1821 |
|
1822 |
plt.show()
|
|
|
1823 |
|
1824 |
###################################################################################
|
1825 |
|
@@ -1932,7 +1948,7 @@ def Tegridy_Any_Pickle_File_Reader(input_file_name='TMIDI_Pickle_File', ext='.pi
|
|
1932 |
|
1933 |
'''Tegridy Pickle File Loader
|
1934 |
|
1935 |
-
Input: Full path and file name without extention
|
1936 |
File extension if different from default .pickle
|
1937 |
|
1938 |
Output: Standard Python 3 unpickled data object
|
@@ -1944,7 +1960,13 @@ def Tegridy_Any_Pickle_File_Reader(input_file_name='TMIDI_Pickle_File', ext='.pi
|
|
1944 |
print('Tegridy Pickle File Loader')
|
1945 |
print('Loading the pickle file. Please wait...')
|
1946 |
|
1947 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1948 |
content = pickle.load(pickle_file)
|
1949 |
|
1950 |
if verbose:
|
@@ -3519,12 +3541,19 @@ def Tegridy_Split_List(list_to_split, split_value=0):
|
|
3519 |
|
3520 |
# Binary chords functions
|
3521 |
|
3522 |
-
def tones_chord_to_bits(chord):
|
|
|
3523 |
bits = [0] * 12
|
|
|
3524 |
for num in chord:
|
3525 |
bits[num] = 1
|
3526 |
|
3527 |
-
|
|
|
|
|
|
|
|
|
|
|
3528 |
|
3529 |
def bits_to_tones_chord(bits):
|
3530 |
return [i for i, bit in enumerate(bits) if bit == 1]
|
@@ -4687,23 +4716,53 @@ def create_similarity_matrix(list_of_values, matrix_length=0):
|
|
4687 |
|
4688 |
###################################################################################
|
4689 |
|
|
|
|
|
|
|
|
|
|
|
|
|
4690 |
def augment_enhanced_score_notes(enhanced_score_notes,
|
4691 |
timings_divider=16,
|
4692 |
full_sorting=True,
|
4693 |
timings_shift=0,
|
4694 |
-
pitch_shift=0
|
|
|
4695 |
):
|
4696 |
|
4697 |
esn = copy.deepcopy(enhanced_score_notes)
|
4698 |
|
4699 |
-
|
4700 |
-
|
4701 |
-
|
4702 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4703 |
|
4704 |
if full_sorting:
|
4705 |
|
4706 |
-
# Sorting by patch, pitch
|
4707 |
esn.sort(key=lambda x: x[6])
|
4708 |
esn.sort(key=lambda x: x[4], reverse=True)
|
4709 |
esn.sort(key=lambda x: x[1])
|
@@ -4894,25 +4953,26 @@ def patch_list_from_enhanced_score_notes(enhanced_score_notes,
|
|
4894 |
patches = [-1] * 16
|
4895 |
|
4896 |
for idx, e in enumerate(enhanced_score_notes):
|
4897 |
-
if e[
|
4898 |
-
|
4899 |
-
|
4900 |
-
|
4901 |
-
|
4902 |
-
if e[
|
4903 |
-
e[
|
4904 |
-
|
4905 |
-
if -1 in patches:
|
4906 |
-
patches[patches.index(-1)] = e[6]
|
4907 |
else:
|
4908 |
-
|
|
|
|
|
|
|
4909 |
|
4910 |
-
|
4911 |
-
|
4912 |
-
|
4913 |
-
|
4914 |
-
|
4915 |
-
|
4916 |
|
4917 |
patches = [p if p != -1 else default_patch for p in patches]
|
4918 |
|
@@ -4945,19 +5005,20 @@ def patch_enhanced_score_notes(enhanced_score_notes,
|
|
4945 |
overflow_idx = -1
|
4946 |
|
4947 |
for idx, e in enumerate(enhanced_score_notes):
|
4948 |
-
if e[
|
4949 |
-
|
4950 |
-
|
4951 |
-
|
4952 |
-
|
4953 |
-
if e[
|
4954 |
-
e[
|
4955 |
-
|
4956 |
-
if -1 in patches:
|
4957 |
-
patches[patches.index(-1)] = e[6]
|
4958 |
else:
|
4959 |
-
|
4960 |
-
|
|
|
|
|
|
|
4961 |
|
4962 |
enhanced_score_notes_with_patch_changes.append(e)
|
4963 |
|
@@ -4967,15 +5028,16 @@ def patch_enhanced_score_notes(enhanced_score_notes,
|
|
4967 |
|
4968 |
if overflow_idx != -1:
|
4969 |
for idx, e in enumerate(enhanced_score_notes[overflow_idx:]):
|
4970 |
-
if e[
|
4971 |
-
if e[
|
4972 |
-
if e[6] not in
|
4973 |
-
|
4974 |
-
|
4975 |
-
|
4976 |
-
|
|
|
4977 |
|
4978 |
-
|
4979 |
|
4980 |
#===========================================================================
|
4981 |
|
@@ -5258,7 +5320,8 @@ def add_melody_to_enhanced_score_notes(enhanced_score_notes,
|
|
5258 |
melody_patch=40,
|
5259 |
melody_max_velocity=110,
|
5260 |
acc_max_velocity=90,
|
5261 |
-
pass_drums=True
|
|
|
5262 |
):
|
5263 |
|
5264 |
if pass_drums:
|
@@ -5336,7 +5399,11 @@ def add_melody_to_enhanced_score_notes(enhanced_score_notes,
|
|
5336 |
|
5337 |
adjust_score_velocities(smoothed_melody, melody_max_velocity)
|
5338 |
|
5339 |
-
|
|
|
|
|
|
|
|
|
5340 |
|
5341 |
return final_score
|
5342 |
|
@@ -5349,7 +5416,10 @@ def find_paths(list_of_lists, path=[]):
|
|
5349 |
|
5350 |
###################################################################################
|
5351 |
|
5352 |
-
def recalculate_score_timings(score,
|
|
|
|
|
|
|
5353 |
|
5354 |
rscore = copy.deepcopy(score)
|
5355 |
|
@@ -5359,10 +5429,10 @@ def recalculate_score_timings(score, start_time=0):
|
|
5359 |
|
5360 |
for e in rscore:
|
5361 |
|
5362 |
-
dtime = e[
|
5363 |
pe = copy.deepcopy(e)
|
5364 |
abs_time += dtime
|
5365 |
-
e[
|
5366 |
|
5367 |
return rscore
|
5368 |
|
@@ -6359,38 +6429,2002 @@ def transpose_pitches(pitches, transpose_value=0):
|
|
6359 |
|
6360 |
###################################################################################
|
6361 |
|
6362 |
-
def reverse_enhanced_score_notes(
|
|
|
|
|
|
|
|
|
|
|
6363 |
|
6364 |
-
|
6365 |
|
6366 |
-
|
6367 |
|
6368 |
-
|
6369 |
|
6370 |
-
|
6371 |
-
|
6372 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6373 |
|
6374 |
-
|
6375 |
-
pt = abs_dtimes[-1]
|
6376 |
|
6377 |
-
|
6378 |
-
new_dtimes.append(abs(pt-t))
|
6379 |
-
pt = t
|
6380 |
|
6381 |
-
|
6382 |
|
6383 |
-
|
6384 |
|
6385 |
-
|
6386 |
-
time += new_dtimes[i]
|
6387 |
-
for tt in t:
|
6388 |
-
tt[1] = time
|
6389 |
|
6390 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6391 |
|
6392 |
###################################################################################
|
6393 |
|
6394 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6395 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6396 |
###################################################################################
|
|
|
1484 |
from difflib import SequenceMatcher as SM
|
1485 |
|
1486 |
import statistics
|
1487 |
+
import math
|
1488 |
|
1489 |
import matplotlib.pyplot as plt
|
1490 |
|
|
|
1763 |
note_height = 0.75,
|
1764 |
show_grid_lines=False,
|
1765 |
return_plt = False,
|
1766 |
+
timings_multiplier=1,
|
1767 |
+
save_plt='',
|
1768 |
+
save_only_plt_image=True,
|
1769 |
+
save_transparent=False
|
1770 |
):
|
1771 |
|
1772 |
'''Tegridy ms SONG plotter/vizualizer'''
|
|
|
1820 |
|
1821 |
plt.title(plot_title)
|
1822 |
|
1823 |
+
if save_plt != '':
|
1824 |
+
if save_only_plt_image:
|
1825 |
+
plt.axis('off')
|
1826 |
+
plt.title('')
|
1827 |
+
plt.savefig(save_plt, transparent=save_transparent, bbox_inches='tight', pad_inches=0, facecolor='black')
|
1828 |
+
plt.close()
|
1829 |
+
|
1830 |
+
else:
|
1831 |
+
plt.savefig(save_plt)
|
1832 |
+
plt.close()
|
1833 |
+
|
1834 |
if return_plt:
|
1835 |
return fig
|
1836 |
|
1837 |
plt.show()
|
1838 |
+
plt.close()
|
1839 |
|
1840 |
###################################################################################
|
1841 |
|
|
|
1948 |
|
1949 |
'''Tegridy Pickle File Loader
|
1950 |
|
1951 |
+
Input: Full path and file name with or without extention
|
1952 |
File extension if different from default .pickle
|
1953 |
|
1954 |
Output: Standard Python 3 unpickled data object
|
|
|
1960 |
print('Tegridy Pickle File Loader')
|
1961 |
print('Loading the pickle file. Please wait...')
|
1962 |
|
1963 |
+
if os.path.basename(input_file_name).endswith(ext):
|
1964 |
+
fname = input_file_name
|
1965 |
+
|
1966 |
+
else:
|
1967 |
+
fname = input_file_name + ext
|
1968 |
+
|
1969 |
+
with open(fname, 'rb') as pickle_file:
|
1970 |
content = pickle.load(pickle_file)
|
1971 |
|
1972 |
if verbose:
|
|
|
3541 |
|
3542 |
# Binary chords functions
|
3543 |
|
3544 |
+
def tones_chord_to_bits(chord, reverse=True):
|
3545 |
+
|
3546 |
bits = [0] * 12
|
3547 |
+
|
3548 |
for num in chord:
|
3549 |
bits[num] = 1
|
3550 |
|
3551 |
+
if reverse:
|
3552 |
+
bits.reverse()
|
3553 |
+
return bits
|
3554 |
+
|
3555 |
+
else:
|
3556 |
+
return bits
|
3557 |
|
3558 |
def bits_to_tones_chord(bits):
|
3559 |
return [i for i, bit in enumerate(bits) if bit == 1]
|
|
|
4716 |
|
4717 |
###################################################################################
|
4718 |
|
4719 |
+
def ceil_with_precision(value, decimal_places):
|
4720 |
+
factor = 10 ** decimal_places
|
4721 |
+
return math.ceil(value * factor) / factor
|
4722 |
+
|
4723 |
+
###################################################################################
|
4724 |
+
|
4725 |
def augment_enhanced_score_notes(enhanced_score_notes,
|
4726 |
timings_divider=16,
|
4727 |
full_sorting=True,
|
4728 |
timings_shift=0,
|
4729 |
+
pitch_shift=0,
|
4730 |
+
legacy_timings=False
|
4731 |
):
|
4732 |
|
4733 |
esn = copy.deepcopy(enhanced_score_notes)
|
4734 |
|
4735 |
+
pe = enhanced_score_notes[0]
|
4736 |
+
|
4737 |
+
abs_time = max(0, int(enhanced_score_notes[0][1] / timings_divider))
|
4738 |
+
|
4739 |
+
for i, e in enumerate(esn):
|
4740 |
+
|
4741 |
+
dtime = (e[1] / timings_divider) - (pe[1] / timings_divider)
|
4742 |
+
|
4743 |
+
if 0.5 < dtime < 1:
|
4744 |
+
dtime = 1
|
4745 |
+
|
4746 |
+
else:
|
4747 |
+
dtime = int(dtime)
|
4748 |
+
|
4749 |
+
if legacy_timings:
|
4750 |
+
abs_time = int(e[1] / timings_divider) + timings_shift
|
4751 |
+
|
4752 |
+
else:
|
4753 |
+
abs_time += dtime
|
4754 |
+
|
4755 |
+
e[1] = max(0, abs_time + timings_shift)
|
4756 |
+
|
4757 |
+
e[2] = max(1, int(e[2] / timings_divider)) + timings_shift
|
4758 |
+
|
4759 |
+
e[4] = max(1, min(127, e[4] + pitch_shift))
|
4760 |
+
|
4761 |
+
pe = enhanced_score_notes[i]
|
4762 |
|
4763 |
if full_sorting:
|
4764 |
|
4765 |
+
# Sorting by patch, reverse pitch and start-time
|
4766 |
esn.sort(key=lambda x: x[6])
|
4767 |
esn.sort(key=lambda x: x[4], reverse=True)
|
4768 |
esn.sort(key=lambda x: x[1])
|
|
|
4953 |
patches = [-1] * 16
|
4954 |
|
4955 |
for idx, e in enumerate(enhanced_score_notes):
|
4956 |
+
if e[0] == 'note':
|
4957 |
+
if e[3] != 9:
|
4958 |
+
if patches[e[3]] == -1:
|
4959 |
+
patches[e[3]] = e[6]
|
4960 |
+
else:
|
4961 |
+
if patches[e[3]] != e[6]:
|
4962 |
+
if e[6] in patches:
|
4963 |
+
e[3] = patches.index(e[6])
|
|
|
|
|
4964 |
else:
|
4965 |
+
if -1 in patches:
|
4966 |
+
patches[patches.index(-1)] = e[6]
|
4967 |
+
else:
|
4968 |
+
patches[-1] = e[6]
|
4969 |
|
4970 |
+
if verbose:
|
4971 |
+
print('=' * 70)
|
4972 |
+
print('WARNING! Composition has more than 15 patches!')
|
4973 |
+
print('Conflict note number:', idx)
|
4974 |
+
print('Conflict channel number:', e[3])
|
4975 |
+
print('Conflict patch number:', e[6])
|
4976 |
|
4977 |
patches = [p if p != -1 else default_patch for p in patches]
|
4978 |
|
|
|
5005 |
overflow_idx = -1
|
5006 |
|
5007 |
for idx, e in enumerate(enhanced_score_notes):
|
5008 |
+
if e[0] == 'note':
|
5009 |
+
if e[3] != 9:
|
5010 |
+
if patches[e[3]] == -1:
|
5011 |
+
patches[e[3]] = e[6]
|
5012 |
+
else:
|
5013 |
+
if patches[e[3]] != e[6]:
|
5014 |
+
if e[6] in patches:
|
5015 |
+
e[3] = patches.index(e[6])
|
|
|
|
|
5016 |
else:
|
5017 |
+
if -1 in patches:
|
5018 |
+
patches[patches.index(-1)] = e[6]
|
5019 |
+
else:
|
5020 |
+
overflow_idx = idx
|
5021 |
+
break
|
5022 |
|
5023 |
enhanced_score_notes_with_patch_changes.append(e)
|
5024 |
|
|
|
5028 |
|
5029 |
if overflow_idx != -1:
|
5030 |
for idx, e in enumerate(enhanced_score_notes[overflow_idx:]):
|
5031 |
+
if e[0] == 'note':
|
5032 |
+
if e[3] != 9:
|
5033 |
+
if e[6] not in patches:
|
5034 |
+
if e[6] not in overflow_patches:
|
5035 |
+
overflow_patches.append(e[6])
|
5036 |
+
enhanced_score_notes_with_patch_changes.append(['patch_change', e[1], e[3], e[6]])
|
5037 |
+
else:
|
5038 |
+
e[3] = patches.index(e[6])
|
5039 |
|
5040 |
+
enhanced_score_notes_with_patch_changes.append(e)
|
5041 |
|
5042 |
#===========================================================================
|
5043 |
|
|
|
5320 |
melody_patch=40,
|
5321 |
melody_max_velocity=110,
|
5322 |
acc_max_velocity=90,
|
5323 |
+
pass_drums=True,
|
5324 |
+
return_melody=False
|
5325 |
):
|
5326 |
|
5327 |
if pass_drums:
|
|
|
5399 |
|
5400 |
adjust_score_velocities(smoothed_melody, melody_max_velocity)
|
5401 |
|
5402 |
+
if return_melody:
|
5403 |
+
final_score = sorted(smoothed_melody, key=lambda x: (x[1], -x[4]))
|
5404 |
+
|
5405 |
+
else:
|
5406 |
+
final_score = sorted(smoothed_melody + acc_score, key=lambda x: (x[1], -x[4]))
|
5407 |
|
5408 |
return final_score
|
5409 |
|
|
|
5416 |
|
5417 |
###################################################################################
|
5418 |
|
5419 |
+
def recalculate_score_timings(score,
|
5420 |
+
start_time=0,
|
5421 |
+
timings_index=1
|
5422 |
+
):
|
5423 |
|
5424 |
rscore = copy.deepcopy(score)
|
5425 |
|
|
|
5429 |
|
5430 |
for e in rscore:
|
5431 |
|
5432 |
+
dtime = e[timings_index] - pe[timings_index]
|
5433 |
pe = copy.deepcopy(e)
|
5434 |
abs_time += dtime
|
5435 |
+
e[timings_index] = abs_time
|
5436 |
|
5437 |
return rscore
|
5438 |
|
|
|
6429 |
|
6430 |
###################################################################################
|
6431 |
|
6432 |
+
def reverse_enhanced_score_notes(escore_notes):
|
6433 |
+
|
6434 |
+
score = recalculate_score_timings(escore_notes)
|
6435 |
+
|
6436 |
+
ematrix = escore_notes_to_escore_matrix(score, reverse_matrix=True)
|
6437 |
+
e_score = escore_matrix_to_original_escore_notes(ematrix)
|
6438 |
|
6439 |
+
reversed_score = recalculate_score_timings(e_score)
|
6440 |
|
6441 |
+
return reversed_score
|
6442 |
|
6443 |
+
###################################################################################
|
6444 |
|
6445 |
+
def count_patterns(lst, sublist):
|
6446 |
+
count = 0
|
6447 |
+
idx = 0
|
6448 |
+
for i in range(len(lst) - len(sublist) + 1):
|
6449 |
+
if lst[idx:idx + len(sublist)] == sublist:
|
6450 |
+
count += 1
|
6451 |
+
idx += len(sublist)
|
6452 |
+
else:
|
6453 |
+
idx += 1
|
6454 |
+
return count
|
6455 |
|
6456 |
+
###################################################################################
|
|
|
6457 |
|
6458 |
+
def find_lrno_patterns(seq):
|
|
|
|
|
6459 |
|
6460 |
+
all_seqs = Counter()
|
6461 |
|
6462 |
+
max_pat_len = math.ceil(len(seq) / 2)
|
6463 |
|
6464 |
+
num_iter = 0
|
|
|
|
|
|
|
6465 |
|
6466 |
+
for i in range(len(seq)):
|
6467 |
+
for j in range(i+1, len(seq)+1):
|
6468 |
+
if j-i <= max_pat_len:
|
6469 |
+
all_seqs[tuple(seq[i:j])] += 1
|
6470 |
+
num_iter += 1
|
6471 |
+
|
6472 |
+
max_count = 0
|
6473 |
+
max_len = 0
|
6474 |
+
|
6475 |
+
for val, count in all_seqs.items():
|
6476 |
+
|
6477 |
+
if max_len < len(val):
|
6478 |
+
max_count = max(2, count)
|
6479 |
+
|
6480 |
+
if count > 1:
|
6481 |
+
max_len = max(max_len, len(val))
|
6482 |
+
pval = val
|
6483 |
+
|
6484 |
+
max_pats = []
|
6485 |
+
|
6486 |
+
for val, count in all_seqs.items():
|
6487 |
+
if count == max_count and len(val) == max_len:
|
6488 |
+
max_pats.append(val)
|
6489 |
+
|
6490 |
+
found_patterns = []
|
6491 |
+
|
6492 |
+
for pat in max_pats:
|
6493 |
+
count = count_patterns(seq, list(pat))
|
6494 |
+
if count > 1:
|
6495 |
+
found_patterns.append([count, len(pat), pat])
|
6496 |
+
|
6497 |
+
return found_patterns
|
6498 |
|
6499 |
###################################################################################
|
6500 |
|
6501 |
+
def delta_pitches(escore_notes, pitches_index=4):
|
6502 |
+
|
6503 |
+
pitches = [p[pitches_index] for p in escore_notes]
|
6504 |
+
|
6505 |
+
return [a-b for a, b in zip(pitches[:-1], pitches[1:])]
|
6506 |
+
|
6507 |
+
###################################################################################
|
6508 |
+
|
6509 |
+
def split_list(lst, val):
|
6510 |
+
return [lst[i:j] for i, j in zip([0] + [k + 1 for k, x in enumerate(lst) if x == val], [k for k, x in enumerate(lst) if x == val] + [len(lst)]) if j > i]
|
6511 |
+
|
6512 |
+
###################################################################################
|
6513 |
+
|
6514 |
+
def even_timings(escore_notes,
|
6515 |
+
times_idx=1,
|
6516 |
+
durs_idx=2
|
6517 |
+
):
|
6518 |
+
|
6519 |
+
esn = copy.deepcopy(escore_notes)
|
6520 |
+
|
6521 |
+
for e in esn:
|
6522 |
+
|
6523 |
+
if e[times_idx] != 0:
|
6524 |
+
if e[times_idx] % 2 != 0:
|
6525 |
+
e[times_idx] += 1
|
6526 |
+
|
6527 |
+
if e[durs_idx] % 2 != 0:
|
6528 |
+
e[durs_idx] += 1
|
6529 |
+
|
6530 |
+
return esn
|
6531 |
+
|
6532 |
+
###################################################################################
|
6533 |
+
|
6534 |
+
def delta_score_to_abs_score(delta_score_notes,
|
6535 |
+
times_idx=1
|
6536 |
+
):
|
6537 |
+
|
6538 |
+
abs_score = copy.deepcopy(delta_score_notes)
|
6539 |
+
|
6540 |
+
abs_time = 0
|
6541 |
+
|
6542 |
+
for i, e in enumerate(delta_score_notes):
|
6543 |
+
|
6544 |
+
dtime = e[times_idx]
|
6545 |
+
|
6546 |
+
abs_time += dtime
|
6547 |
+
|
6548 |
+
abs_score[i][times_idx] = abs_time
|
6549 |
+
|
6550 |
+
return abs_score
|
6551 |
+
|
6552 |
+
###################################################################################
|
6553 |
+
|
6554 |
+
|
6555 |
+
def adjust_numbers_to_sum(numbers, target_sum):
|
6556 |
+
|
6557 |
+
current_sum = sum(numbers)
|
6558 |
+
difference = target_sum - current_sum
|
6559 |
+
|
6560 |
+
non_zero_elements = [(i, num) for i, num in enumerate(numbers) if num != 0]
|
6561 |
+
|
6562 |
+
total_non_zero = sum(num for _, num in non_zero_elements)
|
6563 |
+
|
6564 |
+
increments = []
|
6565 |
+
for i, num in non_zero_elements:
|
6566 |
+
proportion = num / total_non_zero
|
6567 |
+
increment = proportion * difference
|
6568 |
+
increments.append(increment)
|
6569 |
+
|
6570 |
+
for idx, (i, num) in enumerate(non_zero_elements):
|
6571 |
+
numbers[i] += int(round(increments[idx]))
|
6572 |
+
|
6573 |
+
current_sum = sum(numbers)
|
6574 |
+
difference = target_sum - current_sum
|
6575 |
+
non_zero_indices = [i for i, num in enumerate(numbers) if num != 0]
|
6576 |
+
|
6577 |
+
for i in range(abs(difference)):
|
6578 |
+
numbers[non_zero_indices[i % len(non_zero_indices)]] += 1 if difference > 0 else -1
|
6579 |
+
|
6580 |
+
return numbers
|
6581 |
+
|
6582 |
+
###################################################################################
|
6583 |
+
|
6584 |
+
def find_next_bar(escore_notes, bar_time, start_note_idx, cur_bar):
|
6585 |
+
for e in escore_notes[start_note_idx:]:
|
6586 |
+
if e[1] // bar_time > cur_bar:
|
6587 |
+
return e, escore_notes.index(e)
|
6588 |
+
|
6589 |
+
###################################################################################
|
6590 |
+
|
6591 |
+
def align_escore_notes_to_bars(escore_notes,
|
6592 |
+
bar_time=4000,
|
6593 |
+
trim_durations=False,
|
6594 |
+
split_durations=False
|
6595 |
+
):
|
6596 |
+
|
6597 |
+
#=============================================================================
|
6598 |
+
|
6599 |
+
aligned_escore_notes = copy.deepcopy(escore_notes)
|
6600 |
+
|
6601 |
+
abs_time = 0
|
6602 |
+
nidx = 0
|
6603 |
+
delta = 0
|
6604 |
+
bcount = 0
|
6605 |
+
next_bar = [0]
|
6606 |
+
|
6607 |
+
#=============================================================================
|
6608 |
+
|
6609 |
+
while next_bar:
|
6610 |
+
|
6611 |
+
next_bar = find_next_bar(escore_notes, bar_time, nidx, bcount)
|
6612 |
+
|
6613 |
+
if next_bar:
|
6614 |
+
|
6615 |
+
gescore_notes = escore_notes[nidx:next_bar[1]]
|
6616 |
+
else:
|
6617 |
+
gescore_notes = escore_notes[nidx:]
|
6618 |
+
|
6619 |
+
original_timings = [delta] + [(b[1]-a[1]) for a, b in zip(gescore_notes[:-1], gescore_notes[1:])]
|
6620 |
+
adj_timings = adjust_numbers_to_sum(original_timings, bar_time)
|
6621 |
+
|
6622 |
+
for t in adj_timings:
|
6623 |
+
|
6624 |
+
abs_time += t
|
6625 |
+
|
6626 |
+
aligned_escore_notes[nidx][1] = abs_time
|
6627 |
+
aligned_escore_notes[nidx][2] -= int(bar_time // 200)
|
6628 |
+
|
6629 |
+
nidx += 1
|
6630 |
+
|
6631 |
+
if next_bar:
|
6632 |
+
delta = escore_notes[next_bar[1]][1]-escore_notes[next_bar[1]-1][1]
|
6633 |
+
bcount += 1
|
6634 |
+
|
6635 |
+
#=============================================================================
|
6636 |
+
|
6637 |
+
aligned_adjusted_escore_notes = []
|
6638 |
+
bcount = 0
|
6639 |
+
|
6640 |
+
for a in aligned_escore_notes:
|
6641 |
+
bcount = a[1] // bar_time
|
6642 |
+
nbtime = bar_time * (bcount+1)
|
6643 |
+
|
6644 |
+
if a[1]+a[2] > nbtime and a[3] != 9:
|
6645 |
+
if trim_durations or split_durations:
|
6646 |
+
ddiff = ((a[1]+a[2])-nbtime)
|
6647 |
+
aa = copy.deepcopy(a)
|
6648 |
+
aa[2] = a[2] - ddiff
|
6649 |
+
aligned_adjusted_escore_notes.append(aa)
|
6650 |
+
|
6651 |
+
if split_durations:
|
6652 |
+
aaa = copy.deepcopy(a)
|
6653 |
+
aaa[1] = a[1]+aa[2]
|
6654 |
+
aaa[2] = ddiff
|
6655 |
+
|
6656 |
+
aligned_adjusted_escore_notes.append(aaa)
|
6657 |
+
|
6658 |
+
else:
|
6659 |
+
aligned_adjusted_escore_notes.append(a)
|
6660 |
+
|
6661 |
+
else:
|
6662 |
+
aligned_adjusted_escore_notes.append(a)
|
6663 |
+
|
6664 |
+
#=============================================================================
|
6665 |
+
|
6666 |
+
return aligned_adjusted_escore_notes
|
6667 |
+
|
6668 |
+
###################################################################################
|
6669 |
+
|
6670 |
+
def normalize_chord_durations(chord,
|
6671 |
+
dur_idx=2,
|
6672 |
+
norm_factor=100
|
6673 |
+
):
|
6674 |
+
|
6675 |
+
nchord = copy.deepcopy(chord)
|
6676 |
+
|
6677 |
+
for c in nchord:
|
6678 |
+
c[dur_idx] = int(round(max(1 / norm_factor, c[dur_idx] // norm_factor) * norm_factor))
|
6679 |
+
|
6680 |
+
return nchord
|
6681 |
+
|
6682 |
+
###################################################################################
|
6683 |
+
|
6684 |
+
def normalize_chordified_score_durations(chordified_score,
|
6685 |
+
dur_idx=2,
|
6686 |
+
norm_factor=100
|
6687 |
+
):
|
6688 |
+
|
6689 |
+
ncscore = copy.deepcopy(chordified_score)
|
6690 |
+
|
6691 |
+
for cc in ncscore:
|
6692 |
+
for c in cc:
|
6693 |
+
c[dur_idx] = int(round(max(1 / norm_factor, c[dur_idx] // norm_factor) * norm_factor))
|
6694 |
+
|
6695 |
+
return ncscore
|
6696 |
+
|
6697 |
+
###################################################################################
|
6698 |
+
|
6699 |
+
def horizontal_ordered_list_search(list_of_lists,
|
6700 |
+
query_list,
|
6701 |
+
start_idx=0,
|
6702 |
+
end_idx=-1
|
6703 |
+
):
|
6704 |
+
|
6705 |
+
lol = list_of_lists
|
6706 |
+
|
6707 |
+
results = []
|
6708 |
+
|
6709 |
+
if start_idx > 0:
|
6710 |
+
lol = list_of_lists[start_idx:]
|
6711 |
+
|
6712 |
+
if start_idx == -1:
|
6713 |
+
idx = -1
|
6714 |
+
for i, l in enumerate(list_of_lists):
|
6715 |
+
try:
|
6716 |
+
idx = l.index(query_list[0])
|
6717 |
+
lol = list_of_lists[i:]
|
6718 |
+
break
|
6719 |
+
except:
|
6720 |
+
continue
|
6721 |
+
|
6722 |
+
if idx == -1:
|
6723 |
+
results.append(-1)
|
6724 |
+
return results
|
6725 |
+
else:
|
6726 |
+
results.append(i)
|
6727 |
+
|
6728 |
+
if end_idx != -1:
|
6729 |
+
lol = list_of_lists[start_idx:start_idx+max(end_idx, len(query_list))]
|
6730 |
+
|
6731 |
+
for i, q in enumerate(query_list):
|
6732 |
+
try:
|
6733 |
+
idx = lol[i].index(q)
|
6734 |
+
results.append(idx)
|
6735 |
+
except:
|
6736 |
+
results.append(-1)
|
6737 |
+
return results
|
6738 |
+
|
6739 |
+
return results
|
6740 |
+
|
6741 |
+
###################################################################################
|
6742 |
+
|
6743 |
+
def escore_notes_to_escore_matrix(escore_notes,
|
6744 |
+
alt_velocities=False,
|
6745 |
+
flip_matrix=False,
|
6746 |
+
reverse_matrix=False
|
6747 |
+
):
|
6748 |
+
|
6749 |
+
last_time = escore_notes[-1][1]
|
6750 |
+
last_notes = [e for e in escore_notes if e[1] == last_time]
|
6751 |
+
max_last_dur = max([e[2] for e in last_notes])
|
6752 |
+
|
6753 |
+
time_range = last_time+max_last_dur
|
6754 |
+
|
6755 |
+
channels_list = sorted(set([e[3] for e in escore_notes]))
|
6756 |
+
|
6757 |
+
escore_matrixes = []
|
6758 |
+
|
6759 |
+
for cha in channels_list:
|
6760 |
+
|
6761 |
+
escore_matrix = [[[-1, -1]] * 128 for _ in range(time_range)]
|
6762 |
+
|
6763 |
+
pe = escore_notes[0]
|
6764 |
+
|
6765 |
+
for i, note in enumerate(escore_notes):
|
6766 |
+
|
6767 |
+
etype, time, duration, channel, pitch, velocity, patch = note
|
6768 |
+
|
6769 |
+
time = max(0, time)
|
6770 |
+
duration = max(1, duration)
|
6771 |
+
channel = max(0, min(15, channel))
|
6772 |
+
pitch = max(0, min(127, pitch))
|
6773 |
+
velocity = max(0, min(127, velocity))
|
6774 |
+
patch = max(0, min(128, patch))
|
6775 |
+
|
6776 |
+
if alt_velocities:
|
6777 |
+
velocity -= (i % 2)
|
6778 |
+
|
6779 |
+
if channel == cha:
|
6780 |
+
|
6781 |
+
for t in range(time, min(time + duration, time_range)):
|
6782 |
+
|
6783 |
+
escore_matrix[t][pitch] = [velocity, patch]
|
6784 |
+
|
6785 |
+
pe = note
|
6786 |
+
|
6787 |
+
if flip_matrix:
|
6788 |
+
|
6789 |
+
temp_matrix = []
|
6790 |
+
|
6791 |
+
for m in escore_matrix:
|
6792 |
+
temp_matrix.append(m[::-1])
|
6793 |
+
|
6794 |
+
escore_matrix = temp_matrix
|
6795 |
+
|
6796 |
+
if reverse_matrix:
|
6797 |
+
escore_matrix = escore_matrix[::-1]
|
6798 |
+
|
6799 |
+
escore_matrixes.append(escore_matrix)
|
6800 |
+
|
6801 |
+
return [channels_list, escore_matrixes]
|
6802 |
+
|
6803 |
+
###################################################################################
|
6804 |
+
|
6805 |
+
def escore_matrix_to_merged_escore_notes(full_escore_matrix,
|
6806 |
+
max_note_duration=4000
|
6807 |
+
):
|
6808 |
+
|
6809 |
+
merged_escore_notes = []
|
6810 |
+
|
6811 |
+
mat_channels_list = full_escore_matrix[0]
|
6812 |
+
|
6813 |
+
for m, cha in enumerate(mat_channels_list):
|
6814 |
+
|
6815 |
+
escore_matrix = full_escore_matrix[1][m]
|
6816 |
+
|
6817 |
+
result = []
|
6818 |
+
|
6819 |
+
for j in range(len(escore_matrix[0])):
|
6820 |
+
|
6821 |
+
count = 1
|
6822 |
+
|
6823 |
+
for i in range(1, len(escore_matrix)):
|
6824 |
+
|
6825 |
+
if escore_matrix[i][j] != [-1, -1] and escore_matrix[i][j][1] == escore_matrix[i-1][j][1] and count < max_note_duration:
|
6826 |
+
count += 1
|
6827 |
+
|
6828 |
+
else:
|
6829 |
+
if count > 1:
|
6830 |
+
result.append([i-count, count, j, escore_matrix[i-1][j]])
|
6831 |
+
|
6832 |
+
count = 1
|
6833 |
+
|
6834 |
+
if count > 1:
|
6835 |
+
result.append([len(escore_matrix)-count, count, j, escore_matrix[-1][j]])
|
6836 |
+
|
6837 |
+
result.sort(key=lambda x: (x[0], -x[2]))
|
6838 |
+
|
6839 |
+
for r in result:
|
6840 |
+
merged_escore_notes.append(['note', r[0], r[1], cha, r[2], r[3][0], r[3][1]])
|
6841 |
+
|
6842 |
+
return sorted(merged_escore_notes, key=lambda x: (x[1], -x[4], x[6]))
|
6843 |
+
|
6844 |
+
###################################################################################
|
6845 |
+
|
6846 |
+
def escore_matrix_to_original_escore_notes(full_escore_matrix):
|
6847 |
+
|
6848 |
+
merged_escore_notes = []
|
6849 |
+
|
6850 |
+
mat_channels_list = full_escore_matrix[0]
|
6851 |
+
|
6852 |
+
for m, cha in enumerate(mat_channels_list):
|
6853 |
+
|
6854 |
+
escore_matrix = full_escore_matrix[1][m]
|
6855 |
+
|
6856 |
+
result = []
|
6857 |
+
|
6858 |
+
for j in range(len(escore_matrix[0])):
|
6859 |
+
|
6860 |
+
count = 1
|
6861 |
+
|
6862 |
+
for i in range(1, len(escore_matrix)):
|
6863 |
+
|
6864 |
+
if escore_matrix[i][j] != [-1, -1] and escore_matrix[i][j] == escore_matrix[i-1][j]:
|
6865 |
+
count += 1
|
6866 |
+
|
6867 |
+
else:
|
6868 |
+
if count > 1:
|
6869 |
+
result.append([i-count, count, j, escore_matrix[i-1][j]])
|
6870 |
+
|
6871 |
+
count = 1
|
6872 |
+
|
6873 |
+
if count > 1:
|
6874 |
+
result.append([len(escore_matrix)-count, count, j, escore_matrix[-1][j]])
|
6875 |
+
|
6876 |
+
result.sort(key=lambda x: (x[0], -x[2]))
|
6877 |
+
|
6878 |
+
for r in result:
|
6879 |
+
merged_escore_notes.append(['note', r[0], r[1], cha, r[2], r[3][0], r[3][1]])
|
6880 |
+
|
6881 |
+
return sorted(merged_escore_notes, key=lambda x: (x[1], -x[4], x[6]))
|
6882 |
+
|
6883 |
+
###################################################################################
|
6884 |
+
|
6885 |
+
def escore_notes_to_binary_matrix(escore_notes,
|
6886 |
+
channel=0,
|
6887 |
+
patch=0,
|
6888 |
+
flip_matrix=False,
|
6889 |
+
reverse_matrix=False
|
6890 |
+
):
|
6891 |
+
|
6892 |
+
escore = [e for e in escore_notes if e[3] == channel and e[6] == patch]
|
6893 |
+
|
6894 |
+
if escore:
|
6895 |
+
last_time = escore[-1][1]
|
6896 |
+
last_notes = [e for e in escore if e[1] == last_time]
|
6897 |
+
max_last_dur = max([e[2] for e in last_notes])
|
6898 |
+
|
6899 |
+
time_range = last_time+max_last_dur
|
6900 |
+
|
6901 |
+
escore_matrix = []
|
6902 |
+
|
6903 |
+
escore_matrix = [[0] * 128 for _ in range(time_range)]
|
6904 |
+
|
6905 |
+
for note in escore:
|
6906 |
+
|
6907 |
+
etype, time, duration, chan, pitch, velocity, pat = note
|
6908 |
+
|
6909 |
+
time = max(0, time)
|
6910 |
+
duration = max(1, duration)
|
6911 |
+
chan = max(0, min(15, chan))
|
6912 |
+
pitch = max(0, min(127, pitch))
|
6913 |
+
velocity = max(0, min(127, velocity))
|
6914 |
+
pat = max(0, min(128, pat))
|
6915 |
+
|
6916 |
+
if channel == chan and patch == pat:
|
6917 |
+
|
6918 |
+
for t in range(time, min(time + duration, time_range)):
|
6919 |
+
|
6920 |
+
escore_matrix[t][pitch] = 1
|
6921 |
|
6922 |
+
if flip_matrix:
|
6923 |
+
|
6924 |
+
temp_matrix = []
|
6925 |
+
|
6926 |
+
for m in escore_matrix:
|
6927 |
+
temp_matrix.append(m[::-1])
|
6928 |
+
|
6929 |
+
escore_matrix = temp_matrix
|
6930 |
+
|
6931 |
+
if reverse_matrix:
|
6932 |
+
escore_matrix = escore_matrix[::-1]
|
6933 |
+
|
6934 |
+
return escore_matrix
|
6935 |
+
|
6936 |
+
else:
|
6937 |
+
return None
|
6938 |
+
|
6939 |
+
###################################################################################
|
6940 |
+
|
6941 |
+
def binary_matrix_to_original_escore_notes(binary_matrix,
|
6942 |
+
channel=0,
|
6943 |
+
patch=0,
|
6944 |
+
velocity=-1
|
6945 |
+
):
|
6946 |
+
|
6947 |
+
result = []
|
6948 |
+
|
6949 |
+
for j in range(len(binary_matrix[0])):
|
6950 |
+
|
6951 |
+
count = 1
|
6952 |
+
|
6953 |
+
for i in range(1, len(binary_matrix)):
|
6954 |
+
|
6955 |
+
if binary_matrix[i][j] != 0 and binary_matrix[i][j] == binary_matrix[i-1][j]:
|
6956 |
+
count += 1
|
6957 |
+
|
6958 |
+
else:
|
6959 |
+
if count > 1:
|
6960 |
+
result.append([i-count, count, j, binary_matrix[i-1][j]])
|
6961 |
+
|
6962 |
+
else:
|
6963 |
+
if binary_matrix[i-1][j] != 0:
|
6964 |
+
result.append([i-count, count, j, binary_matrix[i-1][j]])
|
6965 |
+
|
6966 |
+
count = 1
|
6967 |
+
|
6968 |
+
if count > 1:
|
6969 |
+
result.append([len(binary_matrix)-count, count, j, binary_matrix[-1][j]])
|
6970 |
+
|
6971 |
+
else:
|
6972 |
+
if binary_matrix[i-1][j] != 0:
|
6973 |
+
result.append([i-count, count, j, binary_matrix[i-1][j]])
|
6974 |
+
|
6975 |
+
result.sort(key=lambda x: (x[0], -x[2]))
|
6976 |
+
|
6977 |
+
original_escore_notes = []
|
6978 |
+
|
6979 |
+
vel = velocity
|
6980 |
+
|
6981 |
+
for r in result:
|
6982 |
+
|
6983 |
+
if velocity == -1:
|
6984 |
+
vel = max(40, r[2])
|
6985 |
+
|
6986 |
+
original_escore_notes.append(['note', r[0], r[1], channel, r[2], vel, patch])
|
6987 |
+
|
6988 |
+
return sorted(original_escore_notes, key=lambda x: (x[1], -x[4], x[6]))
|
6989 |
+
|
6990 |
+
###################################################################################
|
6991 |
+
|
6992 |
+
def escore_notes_averages(escore_notes,
|
6993 |
+
times_index=1,
|
6994 |
+
durs_index=2,
|
6995 |
+
chans_index=3,
|
6996 |
+
ptcs_index=4,
|
6997 |
+
vels_index=5,
|
6998 |
+
average_drums=False,
|
6999 |
+
score_is_delta=False,
|
7000 |
+
return_ptcs_and_vels=False
|
7001 |
+
):
|
7002 |
+
|
7003 |
+
if score_is_delta:
|
7004 |
+
if average_drums:
|
7005 |
+
times = [e[times_index] for e in escore_notes if e[times_index] != 0]
|
7006 |
+
else:
|
7007 |
+
times = [e[times_index] for e in escore_notes if e[times_index] != 0 and e[chans_index] != 9]
|
7008 |
+
|
7009 |
+
else:
|
7010 |
+
descore_notes = delta_score_notes(escore_notes)
|
7011 |
+
if average_drums:
|
7012 |
+
times = [e[times_index] for e in descore_notes if e[times_index] != 0]
|
7013 |
+
else:
|
7014 |
+
times = [e[times_index] for e in descore_notes if e[times_index] != 0 and e[chans_index] != 9]
|
7015 |
+
|
7016 |
+
if average_drums:
|
7017 |
+
durs = [e[durs_index] for e in escore_notes]
|
7018 |
+
else:
|
7019 |
+
durs = [e[durs_index] for e in escore_notes if e[chans_index] != 9]
|
7020 |
+
|
7021 |
+
if return_ptcs_and_vels:
|
7022 |
+
if average_drums:
|
7023 |
+
ptcs = [e[ptcs_index] for e in escore_notes]
|
7024 |
+
vels = [e[vels_index] for e in escore_notes]
|
7025 |
+
else:
|
7026 |
+
ptcs = [e[ptcs_index] for e in escore_notes if e[chans_index] != 9]
|
7027 |
+
vels = [e[vels_index] for e in escore_notes if e[chans_index] != 9]
|
7028 |
+
|
7029 |
+
return [sum(times) / len(times), sum(durs) / len(durs), sum(ptcs) / len(ptcs), sum(vels) / len(vels)]
|
7030 |
+
|
7031 |
+
else:
|
7032 |
+
return [sum(times) / len(times), sum(durs) / len(durs)]
|
7033 |
+
|
7034 |
+
###################################################################################
|
7035 |
+
|
7036 |
+
def adjust_escore_notes_timings(escore_notes,
|
7037 |
+
adj_k=1,
|
7038 |
+
times_index=1,
|
7039 |
+
durs_index=2,
|
7040 |
+
score_is_delta=False,
|
7041 |
+
return_delta_scpre=False
|
7042 |
+
):
|
7043 |
+
|
7044 |
+
if score_is_delta:
|
7045 |
+
adj_escore_notes = copy.deepcopy(escore_notes)
|
7046 |
+
else:
|
7047 |
+
adj_escore_notes = delta_score_notes(escore_notes)
|
7048 |
+
|
7049 |
+
for e in adj_escore_notes:
|
7050 |
+
|
7051 |
+
if e[times_index] != 0:
|
7052 |
+
e[times_index] = max(1, round(e[times_index] * adj_k))
|
7053 |
+
|
7054 |
+
e[durs_index] = max(1, round(e[durs_index] * adj_k))
|
7055 |
+
|
7056 |
+
if return_delta_scpre:
|
7057 |
+
return adj_escore_notes
|
7058 |
+
|
7059 |
+
else:
|
7060 |
+
return delta_score_to_abs_score(adj_escore_notes)
|
7061 |
+
|
7062 |
+
###################################################################################
|
7063 |
+
|
7064 |
+
def escore_notes_delta_times(escore_notes,
|
7065 |
+
times_index=1
|
7066 |
+
):
|
7067 |
+
|
7068 |
+
descore_notes = delta_score_notes(escore_notes)
|
7069 |
+
|
7070 |
+
return [e[times_index] for e in descore_notes]
|
7071 |
+
|
7072 |
+
###################################################################################
|
7073 |
+
|
7074 |
+
def escore_notes_durations(escore_notes,
|
7075 |
+
durs_index=1
|
7076 |
+
):
|
7077 |
+
|
7078 |
+
descore_notes = delta_score_notes(escore_notes)
|
7079 |
+
|
7080 |
+
return [e[durs_index] for e in descore_notes]
|
7081 |
+
|
7082 |
+
###################################################################################
|
7083 |
+
|
7084 |
+
def ordered_lists_match_ratio(src_list, trg_list):
|
7085 |
+
|
7086 |
+
zlist = list(zip(src_list, trg_list))
|
7087 |
+
|
7088 |
+
return sum([a == b for a, b in zlist]) / len(list(zlist))
|
7089 |
+
|
7090 |
+
###################################################################################
|
7091 |
+
|
7092 |
+
def lists_intersections(src_list, trg_list):
|
7093 |
+
return list(set(src_list) & set(trg_list))
|
7094 |
+
|
7095 |
+
###################################################################################
|
7096 |
+
|
7097 |
+
def transpose_escore_notes(escore_notes,
|
7098 |
+
transpose_value=0,
|
7099 |
+
channel_index=3,
|
7100 |
+
pitches_index=4
|
7101 |
+
):
|
7102 |
+
|
7103 |
+
tr_escore_notes = copy.deepcopy(escore_notes)
|
7104 |
+
|
7105 |
+
for e in tr_escore_notes:
|
7106 |
+
if e[channel_index] != 9:
|
7107 |
+
e[pitches_index] = max(1, min(127, e[pitches_index] + transpose_value))
|
7108 |
+
|
7109 |
+
return tr_escore_notes
|
7110 |
+
|
7111 |
+
###################################################################################
|
7112 |
+
|
7113 |
+
def transpose_escore_notes_to_pitch(escore_notes,
|
7114 |
+
target_pitch_value=60,
|
7115 |
+
channel_index=3,
|
7116 |
+
pitches_index=4
|
7117 |
+
):
|
7118 |
+
|
7119 |
+
tr_escore_notes = copy.deepcopy(escore_notes)
|
7120 |
+
|
7121 |
+
transpose_delta = int(round(target_pitch_value)) - int(round(escore_notes_averages(escore_notes, return_ptcs_and_vels=True)[2]))
|
7122 |
+
|
7123 |
+
for e in tr_escore_notes:
|
7124 |
+
if e[channel_index] != 9:
|
7125 |
+
e[pitches_index] = max(1, min(127, e[pitches_index] + transpose_delta))
|
7126 |
+
|
7127 |
+
return tr_escore_notes
|
7128 |
+
|
7129 |
+
###################################################################################
|
7130 |
+
|
7131 |
+
CHORDS_TYPES = ['WHITE', 'BLACK', 'UNKNOWN', 'MIXED WHITE', 'MIXED BLACK', 'MIXED GRAY']
|
7132 |
+
|
7133 |
+
###################################################################################
|
7134 |
+
|
7135 |
+
def tones_chord_type(tones_chord,
|
7136 |
+
return_chord_type_index=True,
|
7137 |
+
use_filtered_chords=True
|
7138 |
+
):
|
7139 |
+
|
7140 |
+
WN = WHITE_NOTES
|
7141 |
+
BN = BLACK_NOTES
|
7142 |
+
MX = WHITE_NOTES + BLACK_NOTES
|
7143 |
+
|
7144 |
+
if use_filtered_chords:
|
7145 |
+
CHORDS = ALL_CHORDS_FILTERED
|
7146 |
+
|
7147 |
+
else:
|
7148 |
+
CHORDS = ALL_CHORDS_SORTED
|
7149 |
+
|
7150 |
+
tones_chord = sorted(tones_chord)
|
7151 |
+
|
7152 |
+
ctype = 'UNKNOWN'
|
7153 |
+
|
7154 |
+
if tones_chord in CHORDS:
|
7155 |
+
|
7156 |
+
if sorted(set(tones_chord) & set(WN)) == tones_chord:
|
7157 |
+
ctype = 'WHITE'
|
7158 |
+
|
7159 |
+
elif sorted(set(tones_chord) & set(BN)) == tones_chord:
|
7160 |
+
ctype = 'BLACK'
|
7161 |
+
|
7162 |
+
if len(tones_chord) > 1 and sorted(set(tones_chord) & set(MX)) == tones_chord:
|
7163 |
+
|
7164 |
+
if len(sorted(set(tones_chord) & set(WN))) == len(sorted(set(tones_chord) & set(BN))):
|
7165 |
+
ctype = 'MIXED GRAY'
|
7166 |
+
|
7167 |
+
elif len(sorted(set(tones_chord) & set(WN))) > len(sorted(set(tones_chord) & set(BN))):
|
7168 |
+
ctype = 'MIXED WHITE'
|
7169 |
+
|
7170 |
+
elif len(sorted(set(tones_chord) & set(WN))) < len(sorted(set(tones_chord) & set(BN))):
|
7171 |
+
ctype = 'MIXED BLACK'
|
7172 |
+
|
7173 |
+
if return_chord_type_index:
|
7174 |
+
return CHORDS_TYPES.index(ctype)
|
7175 |
+
|
7176 |
+
else:
|
7177 |
+
return ctype
|
7178 |
+
|
7179 |
+
###################################################################################
|
7180 |
+
|
7181 |
+
def tone_type(tone,
|
7182 |
+
return_tone_type_index=True
|
7183 |
+
):
|
7184 |
+
|
7185 |
+
tone = tone % 12
|
7186 |
+
|
7187 |
+
if tone in BLACK_NOTES:
|
7188 |
+
if return_tone_type_index:
|
7189 |
+
return CHORDS_TYPES.index('BLACK')
|
7190 |
+
else:
|
7191 |
+
return "BLACK"
|
7192 |
+
|
7193 |
+
else:
|
7194 |
+
if return_tone_type_index:
|
7195 |
+
return CHORDS_TYPES.index('WHITE')
|
7196 |
+
else:
|
7197 |
+
return "WHITE"
|
7198 |
+
|
7199 |
+
###################################################################################
|
7200 |
+
|
7201 |
+
def lists_sym_differences(src_list, trg_list):
|
7202 |
+
return list(set(src_list) ^ set(trg_list))
|
7203 |
+
|
7204 |
+
###################################################################################
|
7205 |
+
|
7206 |
+
def lists_differences(long_list, short_list):
|
7207 |
+
return list(set(long_list) - set(short_list))
|
7208 |
+
|
7209 |
+
###################################################################################
|
7210 |
+
|
7211 |
+
def find_best_tones_chord(src_tones_chords,
|
7212 |
+
trg_tones_chords,
|
7213 |
+
find_longest=True
|
7214 |
+
):
|
7215 |
+
|
7216 |
+
not_seen_trg_chords = []
|
7217 |
+
|
7218 |
+
max_len = 0
|
7219 |
+
|
7220 |
+
for tc in trg_tones_chords:
|
7221 |
+
if sorted(tc) in src_tones_chords:
|
7222 |
+
not_seen_trg_chords.append(sorted(tc))
|
7223 |
+
max_len = max(max_len, len(tc))
|
7224 |
+
|
7225 |
+
if not not_seen_trg_chords:
|
7226 |
+
max_len = len(max(trg_tones_chords, key=len))
|
7227 |
+
not_seen_trg_chords = trg_tones_chords
|
7228 |
+
|
7229 |
+
if find_longest:
|
7230 |
+
return random.choice([c for c in not_seen_trg_chords if len(c) == max_len])
|
7231 |
+
|
7232 |
+
else:
|
7233 |
+
return random.choice(not_seen_trg_chords)
|
7234 |
+
|
7235 |
+
###################################################################################
|
7236 |
+
|
7237 |
+
def find_matching_tones_chords(tones_chord,
|
7238 |
+
matching_chord_length=-1,
|
7239 |
+
match_chord_type=True,
|
7240 |
+
use_filtered_chords=True
|
7241 |
+
):
|
7242 |
+
|
7243 |
+
if use_filtered_chords:
|
7244 |
+
CHORDS = ALL_CHORDS_FILTERED
|
7245 |
+
else:
|
7246 |
+
CHORDS = ALL_CHORDS_SORTED
|
7247 |
+
|
7248 |
+
tones_chord = sorted(tones_chord)
|
7249 |
+
|
7250 |
+
tclen = len(tones_chord)
|
7251 |
+
|
7252 |
+
tctype = tones_chord_type(tones_chord, use_filtered_chords=use_filtered_chords)
|
7253 |
+
|
7254 |
+
matches = []
|
7255 |
+
|
7256 |
+
for tc in CHORDS:
|
7257 |
+
|
7258 |
+
if matching_chord_length == -1:
|
7259 |
+
if len(tc) > tclen:
|
7260 |
+
if sorted(lists_intersections(tc, tones_chord)) == tones_chord:
|
7261 |
+
if match_chord_type:
|
7262 |
+
if tones_chord_type(tc, use_filtered_chords=use_filtered_chords) == tctype:
|
7263 |
+
tcdiffs = lists_differences(tc, tones_chord)
|
7264 |
+
if all(tone_type(d) == tctype % 3 for d in tcdiffs):
|
7265 |
+
matches.append(tc)
|
7266 |
+
else:
|
7267 |
+
matches.append(tc)
|
7268 |
+
|
7269 |
+
else:
|
7270 |
+
|
7271 |
+
if len(tc) == max(tclen, matching_chord_length):
|
7272 |
+
if sorted(lists_intersections(tc, tones_chord)) == tones_chord:
|
7273 |
+
if match_chord_type:
|
7274 |
+
if tones_chord_type(tc, use_filtered_chords=use_filtered_chords) == tctype:
|
7275 |
+
tcdiffs = lists_differences(tc, tones_chord)
|
7276 |
+
if all(tone_type(d) == tctype % 3 for d in tcdiffs):
|
7277 |
+
matches.append(tc)
|
7278 |
+
else:
|
7279 |
+
matches.append(tc)
|
7280 |
+
|
7281 |
+
return sorted(matches, key=len)
|
7282 |
+
|
7283 |
+
###################################################################################
|
7284 |
+
|
7285 |
+
def adjust_list_of_values_to_target_average(list_of_values,
|
7286 |
+
trg_avg,
|
7287 |
+
min_value,
|
7288 |
+
max_value
|
7289 |
+
):
|
7290 |
+
|
7291 |
+
filtered_values = [value for value in list_of_values if min_value <= value <= max_value]
|
7292 |
+
|
7293 |
+
if not filtered_values:
|
7294 |
+
return list_of_values
|
7295 |
+
|
7296 |
+
current_avg = sum(filtered_values) / len(filtered_values)
|
7297 |
+
scale_factor = trg_avg / current_avg
|
7298 |
+
|
7299 |
+
adjusted_values = [value * scale_factor for value in filtered_values]
|
7300 |
+
|
7301 |
+
total_difference = trg_avg * len(filtered_values) - sum(adjusted_values)
|
7302 |
+
adjustment_per_value = total_difference / len(filtered_values)
|
7303 |
+
|
7304 |
+
final_values = [value + adjustment_per_value for value in adjusted_values]
|
7305 |
+
|
7306 |
+
while abs(sum(final_values) / len(final_values) - trg_avg) > 1e-6:
|
7307 |
+
total_difference = trg_avg * len(final_values) - sum(final_values)
|
7308 |
+
adjustment_per_value = total_difference / len(final_values)
|
7309 |
+
final_values = [value + adjustment_per_value for value in final_values]
|
7310 |
+
|
7311 |
+
final_values = [round(value) for value in final_values]
|
7312 |
+
|
7313 |
+
adjusted_values = copy.deepcopy(list_of_values)
|
7314 |
+
|
7315 |
+
j = 0
|
7316 |
+
|
7317 |
+
for i in range(len(adjusted_values)):
|
7318 |
+
if min_value <= adjusted_values[i] <= max_value:
|
7319 |
+
adjusted_values[i] = final_values[j]
|
7320 |
+
j += 1
|
7321 |
+
|
7322 |
+
return adjusted_values
|
7323 |
+
|
7324 |
+
###################################################################################
|
7325 |
+
|
7326 |
+
def adjust_escore_notes_to_average(escore_notes,
|
7327 |
+
trg_avg,
|
7328 |
+
min_value=1,
|
7329 |
+
max_value=4000,
|
7330 |
+
times_index=1,
|
7331 |
+
durs_index=2,
|
7332 |
+
score_is_delta=False,
|
7333 |
+
return_delta_scpre=False
|
7334 |
+
):
|
7335 |
+
if score_is_delta:
|
7336 |
+
delta_escore_notes = copy.deepcopy(escore_notes)
|
7337 |
+
|
7338 |
+
else:
|
7339 |
+
delta_escore_notes = delta_score_notes(escore_notes)
|
7340 |
+
|
7341 |
+
times = [[e[times_index], e[durs_index]] for e in delta_escore_notes]
|
7342 |
+
|
7343 |
+
filtered_values = [value for value in times if min_value <= value[0] <= max_value]
|
7344 |
+
|
7345 |
+
if not filtered_values:
|
7346 |
+
return escore_notes
|
7347 |
+
|
7348 |
+
current_avg = sum([v[0] for v in filtered_values]) / len([v[0] for v in filtered_values])
|
7349 |
+
scale_factor = trg_avg / current_avg
|
7350 |
+
|
7351 |
+
adjusted_values = [[value[0] * scale_factor, value[1] * scale_factor] for value in filtered_values]
|
7352 |
+
|
7353 |
+
total_difference = trg_avg * len([v[0] for v in filtered_values]) - sum([v[0] for v in adjusted_values])
|
7354 |
+
adjustment_per_value = total_difference / len(filtered_values)
|
7355 |
+
|
7356 |
+
final_values = [[value[0] + adjustment_per_value, value[1] + adjustment_per_value] for value in adjusted_values]
|
7357 |
+
|
7358 |
+
while abs(sum([v[0] for v in final_values]) / len(final_values) - trg_avg) > 1e-6:
|
7359 |
+
total_difference = trg_avg * len(final_values) - sum([v[0] for v in final_values])
|
7360 |
+
adjustment_per_value = total_difference / len(final_values)
|
7361 |
+
final_values = [[value[0] + adjustment_per_value, value[1] + adjustment_per_value] for value in final_values]
|
7362 |
+
|
7363 |
+
final_values = [[round(value[0]), round(value[1])] for value in final_values]
|
7364 |
+
|
7365 |
+
adjusted_delta_score = copy.deepcopy(delta_escore_notes)
|
7366 |
+
|
7367 |
+
j = 0
|
7368 |
+
|
7369 |
+
for i in range(len(adjusted_delta_score)):
|
7370 |
+
if min_value <= adjusted_delta_score[i][1] <= max_value:
|
7371 |
+
adjusted_delta_score[i][times_index] = final_values[j][0]
|
7372 |
+
adjusted_delta_score[i][durs_index] = final_values[j][1]
|
7373 |
+
j += 1
|
7374 |
+
|
7375 |
+
adjusted_escore_notes = delta_score_to_abs_score(adjusted_delta_score)
|
7376 |
+
|
7377 |
+
if return_delta_scpre:
|
7378 |
+
return adjusted_delta_score
|
7379 |
+
|
7380 |
+
else:
|
7381 |
+
return adjusted_escore_notes
|
7382 |
+
|
7383 |
+
###################################################################################
|
7384 |
+
|
7385 |
+
def harmonize_enhanced_melody_score_notes_to_ms_SONG(escore_notes,
|
7386 |
+
melody_velocity=-1,
|
7387 |
+
melody_channel=3,
|
7388 |
+
melody_patch=40,
|
7389 |
+
melody_base_octave=4,
|
7390 |
+
harmonized_tones_chords_velocity=-1,
|
7391 |
+
harmonized_tones_chords_channel=0,
|
7392 |
+
harmonized_tones_chords_patch=0
|
7393 |
+
):
|
7394 |
+
|
7395 |
+
harmonized_tones_chords = harmonize_enhanced_melody_score_notes(escore_notes)
|
7396 |
+
|
7397 |
+
harm_escore_notes = []
|
7398 |
+
|
7399 |
+
time = 0
|
7400 |
+
|
7401 |
+
for i, note in enumerate(escore_notes):
|
7402 |
+
|
7403 |
+
time = note[1]
|
7404 |
+
dur = note[2]
|
7405 |
+
ptc = note[4]
|
7406 |
+
|
7407 |
+
if melody_velocity == -1:
|
7408 |
+
vel = int(110 + ((ptc % 12) * 1.5))
|
7409 |
+
else:
|
7410 |
+
vel = melody_velocity
|
7411 |
+
|
7412 |
+
harm_escore_notes.append(['note', time, dur, melody_channel, ptc, vel, melody_patch])
|
7413 |
+
|
7414 |
+
for t in harmonized_tones_chords[i]:
|
7415 |
+
|
7416 |
+
ptc = (melody_base_octave * 12) + t
|
7417 |
+
|
7418 |
+
if harmonized_tones_chords_velocity == -1:
|
7419 |
+
vel = int(80 + ((ptc % 12) * 1.5))
|
7420 |
+
else:
|
7421 |
+
vel = harmonized_tones_chords_velocity
|
7422 |
+
|
7423 |
+
harm_escore_notes.append(['note', time, dur, harmonized_tones_chords_channel, ptc, vel, harmonized_tones_chords_patch])
|
7424 |
+
|
7425 |
+
return sorted(harm_escore_notes, key=lambda x: (x[1], -x[4], x[6]))
|
7426 |
+
|
7427 |
+
###################################################################################
|
7428 |
+
|
7429 |
+
def check_and_fix_pitches_chord(pitches_chord,
|
7430 |
+
use_filtered_chords=True
|
7431 |
+
):
|
7432 |
+
|
7433 |
+
pitches_chord = sorted(pitches_chord, reverse=True)
|
7434 |
+
|
7435 |
+
if use_filtered_chords:
|
7436 |
+
CHORDS = ALL_CHORDS_FILTERED
|
7437 |
+
else:
|
7438 |
+
CHORDS = ALL_CHORDS_SORTED
|
7439 |
+
|
7440 |
+
tones_chord = sorted(set([p % 12 for p in pitches_chord]))
|
7441 |
+
|
7442 |
+
if tones_chord not in CHORDS:
|
7443 |
+
|
7444 |
+
if len(tones_chord) == 2:
|
7445 |
+
|
7446 |
+
tones_counts = Counter([p % 12 for p in pitches_chord]).most_common()
|
7447 |
+
|
7448 |
+
if tones_counts[0][1] > 1:
|
7449 |
+
tones_chord = [tones_counts[0][0]]
|
7450 |
+
elif tones_counts[1][1] > 1:
|
7451 |
+
tones_chord = [tones_counts[1][0]]
|
7452 |
+
else:
|
7453 |
+
tones_chord = [pitches_chord[0] % 12]
|
7454 |
+
|
7455 |
+
if len(tones_chord) > 2:
|
7456 |
+
|
7457 |
+
tones_chord_combs = [list(comb) for i in range(len(tones_chord)-2, 0, -1) for comb in combinations(tones_chord, i+1)]
|
7458 |
+
|
7459 |
+
for co in tones_chord_combs:
|
7460 |
+
if co in CHORDS:
|
7461 |
+
tones_chord = co
|
7462 |
+
break
|
7463 |
+
|
7464 |
+
new_pitches_chord = []
|
7465 |
+
|
7466 |
+
for p in pitches_chord:
|
7467 |
+
|
7468 |
+
if p % 12 in tones_chord:
|
7469 |
+
new_pitches_chord.append(p)
|
7470 |
+
|
7471 |
+
return sorted(new_pitches_chord, reverse=True)
|
7472 |
+
|
7473 |
+
###################################################################################
|
7474 |
+
|
7475 |
+
ALL_CHORDS_TRANS = [[0], [0, 4], [0, 4, 7], [0, 4, 8], [0, 5], [0, 6], [0, 7], [0, 8], [1], [1, 5],
|
7476 |
+
[1, 5, 9], [1, 6], [1, 7], [1, 8], [1, 9], [2], [2, 6], [2, 6, 10], [2, 7],
|
7477 |
+
[2, 8], [2, 9], [2, 10], [3], [3, 7], [3, 7, 11], [3, 8], [3, 9], [3, 10],
|
7478 |
+
[3, 11], [4], [4, 7], [4, 7, 11], [4, 8], [4, 9], [4, 10], [4, 11], [5],
|
7479 |
+
[5, 9], [5, 10], [5, 11], [6], [6, 10], [6, 11], [7], [7, 11], [8], [9], [10],
|
7480 |
+
[11]]
|
7481 |
+
|
7482 |
+
###################################################################################
|
7483 |
+
|
7484 |
+
def minkowski_distance(x, y, p=3, pad_value=float('inf')):
|
7485 |
+
|
7486 |
+
if len(x) != len(y):
|
7487 |
+
return -1
|
7488 |
+
|
7489 |
+
distance = 0
|
7490 |
+
|
7491 |
+
for i in range(len(x)):
|
7492 |
+
|
7493 |
+
if x[i] == pad_value or y[i] == pad_value:
|
7494 |
+
continue
|
7495 |
+
|
7496 |
+
distance += abs(x[i] - y[i]) ** p
|
7497 |
+
|
7498 |
+
return distance ** (1 / p)
|
7499 |
+
|
7500 |
+
###################################################################################
|
7501 |
+
|
7502 |
+
def dot_product(x, y, pad_value=None):
|
7503 |
+
return sum(xi * yi for xi, yi in zip(x, y) if xi != pad_value and yi != pad_value)
|
7504 |
+
|
7505 |
+
def norm(vector, pad_value=None):
|
7506 |
+
return sum(xi ** 2 for xi in vector if xi != pad_value) ** 0.5
|
7507 |
+
|
7508 |
+
def cosine_similarity(x, y, pad_value=None):
|
7509 |
+
if len(x) != len(y):
|
7510 |
+
return -1
|
7511 |
+
|
7512 |
+
dot_prod = dot_product(x, y, pad_value)
|
7513 |
+
norm_x = norm(x, pad_value)
|
7514 |
+
norm_y = norm(y, pad_value)
|
7515 |
+
|
7516 |
+
if norm_x == 0 or norm_y == 0:
|
7517 |
+
return 0.0
|
7518 |
+
|
7519 |
+
return dot_prod / (norm_x * norm_y)
|
7520 |
+
|
7521 |
+
###################################################################################
|
7522 |
+
|
7523 |
+
def hamming_distance(arr1, arr2, pad_value):
|
7524 |
+
return sum(el1 != el2 for el1, el2 in zip(arr1, arr2) if el1 != pad_value and el2 != pad_value)
|
7525 |
+
|
7526 |
+
###################################################################################
|
7527 |
+
|
7528 |
+
def jaccard_similarity(arr1, arr2, pad_value):
|
7529 |
+
intersection = sum(el1 and el2 for el1, el2 in zip(arr1, arr2) if el1 != pad_value and el2 != pad_value)
|
7530 |
+
union = sum((el1 or el2) for el1, el2 in zip(arr1, arr2) if el1 != pad_value or el2 != pad_value)
|
7531 |
+
return intersection / union if union != 0 else 0
|
7532 |
+
|
7533 |
+
###################################################################################
|
7534 |
+
|
7535 |
+
def pearson_correlation(arr1, arr2, pad_value):
|
7536 |
+
filtered_pairs = [(el1, el2) for el1, el2 in zip(arr1, arr2) if el1 != pad_value and el2 != pad_value]
|
7537 |
+
if not filtered_pairs:
|
7538 |
+
return 0
|
7539 |
+
n = len(filtered_pairs)
|
7540 |
+
sum1 = sum(el1 for el1, el2 in filtered_pairs)
|
7541 |
+
sum2 = sum(el2 for el1, el2 in filtered_pairs)
|
7542 |
+
sum1_sq = sum(el1 ** 2 for el1, el2 in filtered_pairs)
|
7543 |
+
sum2_sq = sum(el2 ** 2 for el1, el2 in filtered_pairs)
|
7544 |
+
p_sum = sum(el1 * el2 for el1, el2 in filtered_pairs)
|
7545 |
+
num = p_sum - (sum1 * sum2 / n)
|
7546 |
+
den = ((sum1_sq - sum1 ** 2 / n) * (sum2_sq - sum2 ** 2 / n)) ** 0.5
|
7547 |
+
if den == 0:
|
7548 |
+
return 0
|
7549 |
+
return num / den
|
7550 |
+
|
7551 |
+
###################################################################################
|
7552 |
+
|
7553 |
+
def calculate_combined_distances(array_of_arrays,
|
7554 |
+
combine_hamming_distance=True,
|
7555 |
+
combine_jaccard_similarity=True,
|
7556 |
+
combine_pearson_correlation=True,
|
7557 |
+
pad_value=None
|
7558 |
+
):
|
7559 |
+
|
7560 |
+
binary_arrays = array_of_arrays
|
7561 |
+
binary_array_len = len(binary_arrays)
|
7562 |
+
|
7563 |
+
hamming_distances = [[0] * binary_array_len for _ in range(binary_array_len)]
|
7564 |
+
jaccard_similarities = [[0] * binary_array_len for _ in range(binary_array_len)]
|
7565 |
+
pearson_correlations = [[0] * binary_array_len for _ in range(binary_array_len)]
|
7566 |
+
|
7567 |
+
for i in range(binary_array_len):
|
7568 |
+
for j in range(i + 1, binary_array_len):
|
7569 |
+
hamming_distances[i][j] = hamming_distance(binary_arrays[i], binary_arrays[j], pad_value)
|
7570 |
+
hamming_distances[j][i] = hamming_distances[i][j]
|
7571 |
+
|
7572 |
+
jaccard_similarities[i][j] = jaccard_similarity(binary_arrays[i], binary_arrays[j], pad_value)
|
7573 |
+
jaccard_similarities[j][i] = jaccard_similarities[i][j]
|
7574 |
+
|
7575 |
+
pearson_correlations[i][j] = pearson_correlation(binary_arrays[i], binary_arrays[j], pad_value)
|
7576 |
+
pearson_correlations[j][i] = pearson_correlations[i][j]
|
7577 |
+
|
7578 |
+
max_hamming = max(max(row) for row in hamming_distances)
|
7579 |
+
min_hamming = min(min(row) for row in hamming_distances)
|
7580 |
+
normalized_hamming = [[(val - min_hamming) / (max_hamming - min_hamming) for val in row] for row in hamming_distances]
|
7581 |
+
|
7582 |
+
max_jaccard = max(max(row) for row in jaccard_similarities)
|
7583 |
+
min_jaccard = min(min(row) for row in jaccard_similarities)
|
7584 |
+
normalized_jaccard = [[(val - min_jaccard) / (max_jaccard - min_jaccard) for val in row] for row in jaccard_similarities]
|
7585 |
+
|
7586 |
+
max_pearson = max(max(row) for row in pearson_correlations)
|
7587 |
+
min_pearson = min(min(row) for row in pearson_correlations)
|
7588 |
+
normalized_pearson = [[(val - min_pearson) / (max_pearson - min_pearson) for val in row] for row in pearson_correlations]
|
7589 |
+
|
7590 |
+
selected_metrics = 0
|
7591 |
+
|
7592 |
+
if combine_hamming_distance:
|
7593 |
+
selected_metrics += normalized_hamming[i][j]
|
7594 |
+
|
7595 |
+
if combine_jaccard_similarity:
|
7596 |
+
selected_metrics += (1 - normalized_jaccard[i][j])
|
7597 |
+
|
7598 |
+
if combine_pearson_correlation:
|
7599 |
+
selected_metrics += (1 - normalized_pearson[i][j])
|
7600 |
+
|
7601 |
+
combined_metric = [[selected_metrics for i in range(binary_array_len)] for j in range(binary_array_len)]
|
7602 |
+
|
7603 |
+
return combined_metric
|
7604 |
+
|
7605 |
+
###################################################################################
|
7606 |
+
|
7607 |
+
def tones_chords_to_bits(tones_chords):
|
7608 |
+
|
7609 |
+
bits_tones_chords = []
|
7610 |
+
|
7611 |
+
for c in tones_chords:
|
7612 |
+
|
7613 |
+
c.sort()
|
7614 |
+
|
7615 |
+
bits = tones_chord_to_bits(c)
|
7616 |
+
|
7617 |
+
bits_tones_chords.append(bits)
|
7618 |
+
|
7619 |
+
return bits_tones_chords
|
7620 |
+
|
7621 |
+
###################################################################################
|
7622 |
+
|
7623 |
+
def tones_chords_to_ints(tones_chords):
|
7624 |
+
|
7625 |
+
ints_tones_chords = []
|
7626 |
+
|
7627 |
+
for c in tones_chords:
|
7628 |
+
|
7629 |
+
c.sort()
|
7630 |
+
|
7631 |
+
bits = tones_chord_to_bits(c)
|
7632 |
+
|
7633 |
+
number = bits_to_int(bits)
|
7634 |
+
|
7635 |
+
ints_tones_chords.append(number)
|
7636 |
+
|
7637 |
+
return ints_tones_chords
|
7638 |
+
|
7639 |
+
###################################################################################
|
7640 |
+
|
7641 |
+
def tones_chords_to_types(tones_chords,
|
7642 |
+
return_chord_type_index=False
|
7643 |
+
):
|
7644 |
+
|
7645 |
+
types_tones_chords = []
|
7646 |
+
|
7647 |
+
for c in tones_chords:
|
7648 |
+
|
7649 |
+
c.sort()
|
7650 |
+
|
7651 |
+
ctype = tones_chord_type(c, return_chord_type_index=return_chord_type_index)
|
7652 |
+
|
7653 |
+
types_tones_chords.append(ctype)
|
7654 |
+
|
7655 |
+
return types_tones_chords
|
7656 |
+
|
7657 |
+
###################################################################################
|
7658 |
+
|
7659 |
+
def morph_tones_chord(tones_chord,
|
7660 |
+
trg_tone,
|
7661 |
+
use_filtered_chords=True
|
7662 |
+
):
|
7663 |
+
|
7664 |
+
src_tones_chord = sorted(sorted(set(tones_chord)) + [trg_tone])
|
7665 |
+
|
7666 |
+
combs = [list(comb) for i in range(len(src_tones_chord), 0, -1) for comb in combinations(src_tones_chord, i) if trg_tone in list(comb)]
|
7667 |
+
|
7668 |
+
matches = []
|
7669 |
+
|
7670 |
+
if use_filtered_chords:
|
7671 |
+
CHORDS = ALL_CHORDS_FILTERED
|
7672 |
+
|
7673 |
+
else:
|
7674 |
+
CHORDS = ALL_CHORDS_SORTED
|
7675 |
+
|
7676 |
+
for c in combs:
|
7677 |
+
if sorted(set(c)) in CHORDS:
|
7678 |
+
matches.append(sorted(set(c)))
|
7679 |
+
|
7680 |
+
max_len = len(max(matches, key=len))
|
7681 |
+
|
7682 |
+
return random.choice([m for m in matches if len(m) == max_len])
|
7683 |
+
|
7684 |
+
###################################################################################
|
7685 |
+
|
7686 |
+
def compress_binary_matrix(binary_matrix,
|
7687 |
+
only_compress_zeros=False,
|
7688 |
+
return_compression_ratio=False
|
7689 |
+
):
|
7690 |
+
|
7691 |
+
compressed_bmatrix = []
|
7692 |
+
|
7693 |
+
zm = [0] * len(binary_matrix[0])
|
7694 |
+
pm = [0] * len(binary_matrix[0])
|
7695 |
+
|
7696 |
+
mcount = 0
|
7697 |
+
|
7698 |
+
for m in binary_matrix:
|
7699 |
+
|
7700 |
+
if only_compress_zeros:
|
7701 |
+
if m != zm:
|
7702 |
+
compressed_bmatrix.append(m)
|
7703 |
+
mcount += 1
|
7704 |
+
|
7705 |
+
else:
|
7706 |
+
if m != pm:
|
7707 |
+
compressed_bmatrix.append(m)
|
7708 |
+
mcount += 1
|
7709 |
+
|
7710 |
+
pm = m
|
7711 |
+
|
7712 |
+
if return_compression_ratio:
|
7713 |
+
return [compressed_bmatrix, mcount / len(binary_matrix)]
|
7714 |
+
|
7715 |
+
else:
|
7716 |
+
return compressed_bmatrix
|
7717 |
+
|
7718 |
+
###################################################################################
|
7719 |
+
|
7720 |
+
def solo_piano_escore_notes(escore_notes,
|
7721 |
+
channels_index=3,
|
7722 |
+
pitches_index=4,
|
7723 |
+
patches_index=6,
|
7724 |
+
keep_drums=False,
|
7725 |
+
):
|
7726 |
+
|
7727 |
+
cscore = chordify_score([1000, escore_notes])
|
7728 |
+
|
7729 |
+
sp_escore_notes = []
|
7730 |
+
|
7731 |
+
for c in cscore:
|
7732 |
+
|
7733 |
+
seen = []
|
7734 |
+
chord = []
|
7735 |
+
|
7736 |
+
for cc in c:
|
7737 |
+
if cc[pitches_index] not in seen:
|
7738 |
+
|
7739 |
+
if cc[channels_index] != 9:
|
7740 |
+
cc[channels_index] = 0
|
7741 |
+
cc[patches_index] = 0
|
7742 |
+
|
7743 |
+
chord.append(cc)
|
7744 |
+
seen.append(cc[pitches_index])
|
7745 |
+
|
7746 |
+
else:
|
7747 |
+
if keep_drums:
|
7748 |
+
chord.append(cc)
|
7749 |
+
seen.append(cc[pitches_index])
|
7750 |
+
|
7751 |
+
sp_escore_notes.append(chord)
|
7752 |
+
|
7753 |
+
return flatten(sp_escore_notes)
|
7754 |
+
|
7755 |
+
###################################################################################
|
7756 |
+
|
7757 |
+
def strip_drums_from_escore_notes(escore_notes,
|
7758 |
+
channels_index=3
|
7759 |
+
):
|
7760 |
+
|
7761 |
+
return [e for e in escore_notes if e[channels_index] != 9]
|
7762 |
+
|
7763 |
+
###################################################################################
|
7764 |
+
|
7765 |
+
def fixed_escore_notes_timings(escore_notes,
|
7766 |
+
fixed_durations=False,
|
7767 |
+
fixed_timings_multiplier=1,
|
7768 |
+
custom_fixed_time=-1,
|
7769 |
+
custom_fixed_dur=-1
|
7770 |
+
):
|
7771 |
+
|
7772 |
+
fixed_timings_escore_notes = delta_score_notes(escore_notes, even_timings=True)
|
7773 |
+
|
7774 |
+
mode_time = round(Counter([e[1] for e in fixed_timings_escore_notes if e[1] != 0]).most_common()[0][0] * fixed_timings_multiplier)
|
7775 |
+
|
7776 |
+
if mode_time % 2 != 0:
|
7777 |
+
mode_time += 1
|
7778 |
+
|
7779 |
+
mode_dur = round(Counter([e[2] for e in fixed_timings_escore_notes if e[2] != 0]).most_common()[0][0] * fixed_timings_multiplier)
|
7780 |
+
|
7781 |
+
if mode_dur % 2 != 0:
|
7782 |
+
mode_dur += 1
|
7783 |
+
|
7784 |
+
for e in fixed_timings_escore_notes:
|
7785 |
+
if e[1] != 0:
|
7786 |
+
|
7787 |
+
if custom_fixed_time > 0:
|
7788 |
+
e[1] = custom_fixed_time
|
7789 |
+
|
7790 |
+
else:
|
7791 |
+
e[1] = mode_time
|
7792 |
+
|
7793 |
+
if fixed_durations:
|
7794 |
+
|
7795 |
+
if custom_fixed_dur > 0:
|
7796 |
+
e[2] = custom_fixed_dur
|
7797 |
+
|
7798 |
+
else:
|
7799 |
+
e[2] = mode_dur
|
7800 |
+
|
7801 |
+
return delta_score_to_abs_score(fixed_timings_escore_notes)
|
7802 |
+
|
7803 |
+
###################################################################################
|
7804 |
+
|
7805 |
+
def cubic_kernel(x):
|
7806 |
+
abs_x = abs(x)
|
7807 |
+
if abs_x <= 1:
|
7808 |
+
return 1.5 * abs_x**3 - 2.5 * abs_x**2 + 1
|
7809 |
+
elif abs_x <= 2:
|
7810 |
+
return -0.5 * abs_x**3 + 2.5 * abs_x**2 - 4 * abs_x + 2
|
7811 |
+
else:
|
7812 |
+
return 0
|
7813 |
+
|
7814 |
+
###################################################################################
|
7815 |
+
|
7816 |
+
def resize_matrix(matrix, new_height, new_width):
|
7817 |
+
old_height = len(matrix)
|
7818 |
+
old_width = len(matrix[0])
|
7819 |
+
resized_matrix = [[0] * new_width for _ in range(new_height)]
|
7820 |
+
|
7821 |
+
for i in range(new_height):
|
7822 |
+
for j in range(new_width):
|
7823 |
+
old_i = i * old_height / new_height
|
7824 |
+
old_j = j * old_width / new_width
|
7825 |
+
|
7826 |
+
value = 0
|
7827 |
+
total_weight = 0
|
7828 |
+
for m in range(-1, 3):
|
7829 |
+
for n in range(-1, 3):
|
7830 |
+
i_m = min(max(int(old_i) + m, 0), old_height - 1)
|
7831 |
+
j_n = min(max(int(old_j) + n, 0), old_width - 1)
|
7832 |
+
|
7833 |
+
if matrix[i_m][j_n] == 0:
|
7834 |
+
continue
|
7835 |
+
|
7836 |
+
weight = cubic_kernel(old_i - i_m) * cubic_kernel(old_j - j_n)
|
7837 |
+
value += matrix[i_m][j_n] * weight
|
7838 |
+
total_weight += weight
|
7839 |
+
|
7840 |
+
if total_weight > 0:
|
7841 |
+
value /= total_weight
|
7842 |
+
|
7843 |
+
resized_matrix[i][j] = int(value > 0.5)
|
7844 |
+
|
7845 |
+
return resized_matrix
|
7846 |
+
|
7847 |
+
###################################################################################
|
7848 |
+
|
7849 |
+
def square_binary_matrix(binary_matrix,
|
7850 |
+
matrix_size=128,
|
7851 |
+
use_fast_squaring=False,
|
7852 |
+
return_plot_points=False
|
7853 |
+
):
|
7854 |
+
|
7855 |
+
if use_fast_squaring:
|
7856 |
+
|
7857 |
+
step = round(len(binary_matrix) / matrix_size)
|
7858 |
+
|
7859 |
+
samples = []
|
7860 |
+
|
7861 |
+
for i in range(0, len(binary_matrix), step):
|
7862 |
+
samples.append(tuple([tuple(d) for d in binary_matrix[i:i+step]]))
|
7863 |
+
|
7864 |
+
resized_matrix = []
|
7865 |
+
|
7866 |
+
zmatrix = [[0] * matrix_size]
|
7867 |
+
|
7868 |
+
for s in samples:
|
7869 |
+
|
7870 |
+
samples_counts = Counter(s).most_common()
|
7871 |
+
|
7872 |
+
best_sample = tuple([0] * matrix_size)
|
7873 |
+
pm = tuple(zmatrix[0])
|
7874 |
+
|
7875 |
+
for sc in samples_counts:
|
7876 |
+
if sc[0] != tuple(zmatrix[0]) and sc[0] != pm:
|
7877 |
+
best_sample = sc[0]
|
7878 |
+
pm = sc[0]
|
7879 |
+
break
|
7880 |
+
|
7881 |
+
pm = sc[0]
|
7882 |
+
|
7883 |
+
resized_matrix.append(list(best_sample))
|
7884 |
+
|
7885 |
+
resized_matrix = resized_matrix[:matrix_size]
|
7886 |
+
resized_matrix += zmatrix * (matrix_size - len(resized_matrix))
|
7887 |
+
|
7888 |
+
else:
|
7889 |
+
resized_matrix = resize_matrix(binary_matrix, matrix_size, matrix_size)
|
7890 |
+
|
7891 |
+
points = [(i, j) for i in range(matrix_size) for j in range(matrix_size) if resized_matrix[i][j] == 1]
|
7892 |
+
|
7893 |
+
if return_plot_points:
|
7894 |
+
return [resized_matrix, points]
|
7895 |
+
|
7896 |
+
else:
|
7897 |
+
return resized_matrix
|
7898 |
+
|
7899 |
+
###################################################################################
|
7900 |
+
|
7901 |
+
def mean(matrix):
|
7902 |
+
return sum(sum(row) for row in matrix) / (len(matrix) * len(matrix[0]))
|
7903 |
+
|
7904 |
+
###################################################################################
|
7905 |
+
|
7906 |
+
def variance(matrix, mean_value):
|
7907 |
+
return sum(sum((element - mean_value) ** 2 for element in row) for row in matrix) / (len(matrix) * len(matrix[0]))
|
7908 |
+
|
7909 |
+
###################################################################################
|
7910 |
+
|
7911 |
+
def covariance(matrix1, matrix2, mean1, mean2):
|
7912 |
+
return sum(sum((matrix1[i][j] - mean1) * (matrix2[i][j] - mean2) for j in range(len(matrix1[0]))) for i in range(len(matrix1))) / (len(matrix1) * len(matrix1[0]))
|
7913 |
+
|
7914 |
+
###################################################################################
|
7915 |
+
|
7916 |
+
def ssim_index(matrix1, matrix2, bit_depth=1):
|
7917 |
+
|
7918 |
+
if len(matrix1) != len(matrix2) and len(matrix1[0]) != len(matrix2[0]):
|
7919 |
+
return -1
|
7920 |
+
|
7921 |
+
K1, K2 = 0.01, 0.03
|
7922 |
+
L = bit_depth
|
7923 |
+
C1 = (K1 * L) ** 2
|
7924 |
+
C2 = (K2 * L) ** 2
|
7925 |
+
|
7926 |
+
mu1 = mean(matrix1)
|
7927 |
+
mu2 = mean(matrix2)
|
7928 |
+
|
7929 |
+
sigma1_sq = variance(matrix1, mu1)
|
7930 |
+
sigma2_sq = variance(matrix2, mu2)
|
7931 |
+
|
7932 |
+
sigma12 = covariance(matrix1, matrix2, mu1, mu2)
|
7933 |
+
|
7934 |
+
ssim = ((2 * mu1 * mu2 + C1) * (2 * sigma12 + C2)) / ((mu1 ** 2 + mu2 ** 2 + C1) * (sigma1_sq + sigma2_sq + C2))
|
7935 |
+
|
7936 |
+
return ssim
|
7937 |
+
|
7938 |
+
###################################################################################
|
7939 |
+
|
7940 |
+
def find_most_similar_matrix(array_of_matrices,
|
7941 |
+
trg_matrix,
|
7942 |
+
matrices_bit_depth=1,
|
7943 |
+
return_most_similar_index=False
|
7944 |
+
):
|
7945 |
+
|
7946 |
+
max_ssim = -float('inf')
|
7947 |
+
most_similar_index = -1
|
7948 |
+
|
7949 |
+
for i, matrix in enumerate(array_of_matrices):
|
7950 |
+
|
7951 |
+
ssim = ssim_index(matrix, trg_matrix, bit_depth=matrices_bit_depth)
|
7952 |
+
|
7953 |
+
if ssim > max_ssim:
|
7954 |
+
max_ssim = ssim
|
7955 |
+
most_similar_index = i
|
7956 |
+
|
7957 |
+
if return_most_similar_index:
|
7958 |
+
return most_similar_index
|
7959 |
+
|
7960 |
+
else:
|
7961 |
+
return array_of_matrices[most_similar_index]
|
7962 |
+
|
7963 |
+
###################################################################################
|
7964 |
+
|
7965 |
+
def chord_to_pchord(chord):
|
7966 |
+
|
7967 |
+
pchord = []
|
7968 |
+
|
7969 |
+
for cc in chord:
|
7970 |
+
if cc[3] != 9:
|
7971 |
+
pchord.append(cc[4])
|
7972 |
+
|
7973 |
+
return pchord
|
7974 |
+
|
7975 |
+
###################################################################################
|
7976 |
+
|
7977 |
+
def summarize_escore_notes(escore_notes,
|
7978 |
+
summary_length_in_chords=128,
|
7979 |
+
preserve_timings=True,
|
7980 |
+
preserve_durations=False,
|
7981 |
+
time_threshold=12,
|
7982 |
+
min_sum_chord_len=2,
|
7983 |
+
use_tones_chords=True
|
7984 |
+
):
|
7985 |
+
|
7986 |
+
cscore = chordify_score([d[1:] for d in delta_score_notes(escore_notes)])
|
7987 |
+
|
7988 |
+
summary_length_in_chords = min(len(cscore), summary_length_in_chords)
|
7989 |
+
|
7990 |
+
ltthresh = time_threshold // 2
|
7991 |
+
uttresh = time_threshold * 2
|
7992 |
+
|
7993 |
+
mc_time = Counter([c[0][0] for c in cscore if c[0][2] != 9 and ltthresh < c[0][0] < uttresh]).most_common()[0][0]
|
7994 |
+
|
7995 |
+
pchords = []
|
7996 |
+
|
7997 |
+
for c in cscore:
|
7998 |
+
if use_tones_chords:
|
7999 |
+
pchords.append([c[0][0]] + pitches_to_tones_chord(chord_to_pchord(c)))
|
8000 |
+
|
8001 |
+
else:
|
8002 |
+
pchords.append([c[0][0]] + chord_to_pchord(c))
|
8003 |
+
|
8004 |
+
step = round(len(pchords) / summary_length_in_chords)
|
8005 |
+
|
8006 |
+
samples = []
|
8007 |
+
|
8008 |
+
for i in range(0, len(pchords), step):
|
8009 |
+
samples.append(tuple([tuple(d) for d in pchords[i:i+step]]))
|
8010 |
+
|
8011 |
+
summarized_escore_notes = []
|
8012 |
+
|
8013 |
+
for i, s in enumerate(samples):
|
8014 |
+
|
8015 |
+
best_chord = list([v[0] for v in Counter(s).most_common() if v[0][0] == mc_time and len(v[0]) > min_sum_chord_len])
|
8016 |
+
|
8017 |
+
if not best_chord:
|
8018 |
+
best_chord = list([v[0] for v in Counter(s).most_common() if len(v[0]) > min_sum_chord_len])
|
8019 |
+
|
8020 |
+
if not best_chord:
|
8021 |
+
best_chord = list([Counter(s).most_common()[0][0]])
|
8022 |
+
|
8023 |
+
chord = copy.deepcopy(cscore[[ss for ss in s].index(best_chord[0])+(i*step)])
|
8024 |
+
|
8025 |
+
if preserve_timings:
|
8026 |
+
|
8027 |
+
if not preserve_durations:
|
8028 |
+
|
8029 |
+
if i > 0:
|
8030 |
+
|
8031 |
+
pchord = summarized_escore_notes[-1]
|
8032 |
+
|
8033 |
+
for pc in pchord:
|
8034 |
+
pc[1] = min(pc[1], chord[0][0])
|
8035 |
+
|
8036 |
+
else:
|
8037 |
+
|
8038 |
+
chord[0][0] = 1
|
8039 |
+
|
8040 |
+
for c in chord:
|
8041 |
+
c[1] = 1
|
8042 |
+
|
8043 |
+
summarized_escore_notes.append(chord)
|
8044 |
+
|
8045 |
+
summarized_escore_notes = summarized_escore_notes[:summary_length_in_chords]
|
8046 |
+
|
8047 |
+
return [['note'] + d for d in delta_score_to_abs_score(flatten(summarized_escore_notes), times_idx=0)]
|
8048 |
+
|
8049 |
+
###################################################################################
|
8050 |
+
|
8051 |
+
def compress_patches_in_escore_notes(escore_notes,
|
8052 |
+
num_patches=4,
|
8053 |
+
group_patches=False
|
8054 |
+
):
|
8055 |
+
|
8056 |
+
if num_patches > 4:
|
8057 |
+
n_patches = 4
|
8058 |
+
elif num_patches < 1:
|
8059 |
+
n_patches = 1
|
8060 |
+
else:
|
8061 |
+
n_patches = num_patches
|
8062 |
+
|
8063 |
+
if group_patches:
|
8064 |
+
patches_set = sorted(set([e[6] for e in c]))
|
8065 |
+
trg_patch_list = []
|
8066 |
+
seen = []
|
8067 |
+
for p in patches_set:
|
8068 |
+
if p // 8 not in seen:
|
8069 |
+
trg_patch_list.append(p)
|
8070 |
+
seen.append(p // 8)
|
8071 |
+
|
8072 |
+
trg_patch_list = sorted(trg_patch_list)
|
8073 |
+
|
8074 |
+
else:
|
8075 |
+
trg_patch_list = sorted(set([e[6] for e in c]))
|
8076 |
+
|
8077 |
+
if 128 in trg_patch_list and n_patches > 1:
|
8078 |
+
trg_patch_list = trg_patch_list[:n_patches-1] + [128]
|
8079 |
+
else:
|
8080 |
+
trg_patch_list = trg_patch_list[:n_patches]
|
8081 |
+
|
8082 |
+
new_escore_notes = []
|
8083 |
+
|
8084 |
+
for e in escore_notes:
|
8085 |
+
if e[6] in trg_patch_list:
|
8086 |
+
new_escore_notes.append(e)
|
8087 |
+
|
8088 |
+
return new_escore_notes
|
8089 |
+
|
8090 |
+
###################################################################################
|
8091 |
+
|
8092 |
+
def compress_patches_in_escore_notes_chords(escore_notes,
|
8093 |
+
max_num_patches_per_chord=4,
|
8094 |
+
group_patches=True,
|
8095 |
+
root_grouped_patches=False
|
8096 |
+
):
|
8097 |
+
|
8098 |
+
if max_num_patches_per_chord > 4:
|
8099 |
+
n_patches = 4
|
8100 |
+
elif max_num_patches_per_chord < 1:
|
8101 |
+
n_patches = 1
|
8102 |
+
else:
|
8103 |
+
n_patches = max_num_patches_per_chord
|
8104 |
+
|
8105 |
+
cscore = chordify_score([1000, sorted(escore_notes, key=lambda x: (x[1], x[6]))])
|
8106 |
+
|
8107 |
+
new_escore_notes = []
|
8108 |
+
|
8109 |
+
for c in cscore:
|
8110 |
+
|
8111 |
+
if group_patches:
|
8112 |
+
patches_set = sorted(set([e[6] for e in c]))
|
8113 |
+
trg_patch_list = []
|
8114 |
+
seen = []
|
8115 |
+
for p in patches_set:
|
8116 |
+
if p // 8 not in seen:
|
8117 |
+
trg_patch_list.append(p)
|
8118 |
+
seen.append(p // 8)
|
8119 |
+
|
8120 |
+
trg_patch_list = sorted(trg_patch_list)
|
8121 |
+
|
8122 |
+
else:
|
8123 |
+
trg_patch_list = sorted(set([e[6] for e in c]))
|
8124 |
+
|
8125 |
+
if 128 in trg_patch_list and n_patches > 1:
|
8126 |
+
trg_patch_list = trg_patch_list[:n_patches-1] + [128]
|
8127 |
+
else:
|
8128 |
+
trg_patch_list = trg_patch_list[:n_patches]
|
8129 |
+
|
8130 |
+
for ccc in c:
|
8131 |
+
|
8132 |
+
cc = copy.deepcopy(ccc)
|
8133 |
+
|
8134 |
+
if group_patches:
|
8135 |
+
if cc[6] // 8 in [t // 8 for t in trg_patch_list]:
|
8136 |
+
if root_grouped_patches:
|
8137 |
+
cc[6] = (cc[6] // 8) * 8
|
8138 |
+
new_escore_notes.append(cc)
|
8139 |
+
|
8140 |
+
else:
|
8141 |
+
if cc[6] in trg_patch_list:
|
8142 |
+
new_escore_notes.append(cc)
|
8143 |
+
|
8144 |
+
return new_escore_notes
|
8145 |
+
|
8146 |
+
###################################################################################
|
8147 |
+
|
8148 |
+
def escore_notes_to_image_matrix(escore_notes,
|
8149 |
+
num_img_channels=3,
|
8150 |
+
filter_out_zero_rows=False,
|
8151 |
+
filter_out_duplicate_rows=False,
|
8152 |
+
flip_matrix=False,
|
8153 |
+
reverse_matrix=False
|
8154 |
+
):
|
8155 |
+
|
8156 |
+
escore_notes = sorted(escore_notes, key=lambda x: (x[1], x[6]))
|
8157 |
+
|
8158 |
+
if num_img_channels > 1:
|
8159 |
+
n_mat_channels = 3
|
8160 |
+
else:
|
8161 |
+
n_mat_channels = 1
|
8162 |
+
|
8163 |
+
if escore_notes:
|
8164 |
+
last_time = escore_notes[-1][1]
|
8165 |
+
last_notes = [e for e in escore_notes if e[1] == last_time]
|
8166 |
+
max_last_dur = max([e[2] for e in last_notes])
|
8167 |
+
|
8168 |
+
time_range = last_time+max_last_dur
|
8169 |
+
|
8170 |
+
escore_matrix = []
|
8171 |
+
|
8172 |
+
escore_matrix = [[0] * 128 for _ in range(time_range)]
|
8173 |
+
|
8174 |
+
for note in escore_notes:
|
8175 |
+
|
8176 |
+
etype, time, duration, chan, pitch, velocity, pat = note
|
8177 |
+
|
8178 |
+
time = max(0, time)
|
8179 |
+
duration = max(2, duration)
|
8180 |
+
chan = max(0, min(15, chan))
|
8181 |
+
pitch = max(0, min(127, pitch))
|
8182 |
+
velocity = max(0, min(127, velocity))
|
8183 |
+
patch = max(0, min(128, pat))
|
8184 |
+
|
8185 |
+
if chan != 9:
|
8186 |
+
pat = patch + 128
|
8187 |
+
else:
|
8188 |
+
pat = 127
|
8189 |
+
|
8190 |
+
seen_pats = []
|
8191 |
+
|
8192 |
+
for t in range(time, min(time + duration, time_range)):
|
8193 |
+
|
8194 |
+
mat_value = escore_matrix[t][pitch]
|
8195 |
+
|
8196 |
+
mat_value_0 = (mat_value // (256 * 256)) % 256
|
8197 |
+
mat_value_1 = (mat_value // 256) % 256
|
8198 |
+
|
8199 |
+
cur_num_chans = 0
|
8200 |
+
|
8201 |
+
if 0 < mat_value < 256 and pat not in seen_pats:
|
8202 |
+
cur_num_chans = 1
|
8203 |
+
elif 256 < mat_value < (256 * 256) and pat not in seen_pats:
|
8204 |
+
cur_num_chans = 2
|
8205 |
+
|
8206 |
+
if cur_num_chans < n_mat_channels:
|
8207 |
+
|
8208 |
+
if n_mat_channels == 1:
|
8209 |
+
|
8210 |
+
escore_matrix[t][pitch] = pat
|
8211 |
+
seen_pats.append(pat)
|
8212 |
+
|
8213 |
+
elif n_mat_channels == 3:
|
8214 |
+
|
8215 |
+
if cur_num_chans == 0:
|
8216 |
+
escore_matrix[t][pitch] = pat
|
8217 |
+
seen_pats.append(pat)
|
8218 |
+
elif cur_num_chans == 1:
|
8219 |
+
escore_matrix[t][pitch] = (256 * 256 * mat_value_0) + (256 * pat)
|
8220 |
+
seen_pats.append(pat)
|
8221 |
+
elif cur_num_chans == 2:
|
8222 |
+
escore_matrix[t][pitch] = (256 * 256 * mat_value_0) + (256 * mat_value_1) + pat
|
8223 |
+
seen_pats.append(pat)
|
8224 |
+
|
8225 |
+
if filter_out_zero_rows:
|
8226 |
+
escore_matrix = [e for e in escore_matrix if sum(e) != 0]
|
8227 |
+
|
8228 |
+
if filter_out_duplicate_rows:
|
8229 |
+
|
8230 |
+
dd_escore_matrix = []
|
8231 |
+
|
8232 |
+
pr = [-1] * 128
|
8233 |
+
for e in escore_matrix:
|
8234 |
+
if e != pr:
|
8235 |
+
dd_escore_matrix.append(e)
|
8236 |
+
pr = e
|
8237 |
+
|
8238 |
+
escore_matrix = dd_escore_matrix
|
8239 |
+
|
8240 |
+
if flip_matrix:
|
8241 |
+
|
8242 |
+
temp_matrix = []
|
8243 |
+
|
8244 |
+
for m in escore_matrix:
|
8245 |
+
temp_matrix.append(m[::-1])
|
8246 |
+
|
8247 |
+
escore_matrix = temp_matrix
|
8248 |
+
|
8249 |
+
if reverse_matrix:
|
8250 |
+
escore_matrix = escore_matrix[::-1]
|
8251 |
+
|
8252 |
+
return escore_matrix
|
8253 |
+
|
8254 |
+
else:
|
8255 |
+
return None
|
8256 |
+
|
8257 |
+
###################################################################################
|
8258 |
+
|
8259 |
+
def find_value_power(value, number):
|
8260 |
+
return math.floor(math.log(value, number))
|
8261 |
+
|
8262 |
+
###################################################################################
|
8263 |
+
|
8264 |
+
def image_matrix_to_original_escore_notes(image_matrix,
|
8265 |
+
velocity=-1
|
8266 |
+
):
|
8267 |
+
|
8268 |
+
result = []
|
8269 |
+
|
8270 |
+
for j in range(len(image_matrix[0])):
|
8271 |
+
|
8272 |
+
count = 1
|
8273 |
+
|
8274 |
+
for i in range(1, len(image_matrix)):
|
8275 |
+
|
8276 |
+
if image_matrix[i][j] != 0 and image_matrix[i][j] == image_matrix[i-1][j]:
|
8277 |
+
count += 1
|
8278 |
+
|
8279 |
+
else:
|
8280 |
+
if count > 1:
|
8281 |
+
result.append([i-count, count, j, image_matrix[i-1][j]])
|
8282 |
+
|
8283 |
+
else:
|
8284 |
+
if image_matrix[i-1][j] != 0:
|
8285 |
+
result.append([i-count, count, j, image_matrix[i-1][j]])
|
8286 |
+
|
8287 |
+
count = 1
|
8288 |
+
|
8289 |
+
if count > 1:
|
8290 |
+
result.append([len(image_matrix)-count, count, j, image_matrix[-1][j]])
|
8291 |
+
|
8292 |
+
else:
|
8293 |
+
if image_matrix[i-1][j] != 0:
|
8294 |
+
result.append([i-count, count, j, image_matrix[i-1][j]])
|
8295 |
+
|
8296 |
+
result.sort(key=lambda x: (x[0], -x[2]))
|
8297 |
+
|
8298 |
+
original_escore_notes = []
|
8299 |
+
|
8300 |
+
vel = velocity
|
8301 |
+
|
8302 |
+
for r in result:
|
8303 |
+
|
8304 |
+
if velocity == -1:
|
8305 |
+
vel = max(40, r[2])
|
8306 |
+
|
8307 |
+
ptc0 = 0
|
8308 |
+
ptc1 = 0
|
8309 |
+
ptc2 = 0
|
8310 |
+
|
8311 |
+
if find_value_power(r[3], 256) == 0:
|
8312 |
+
ptc0 = r[3] % 256
|
8313 |
+
|
8314 |
+
elif find_value_power(r[3], 256) == 1:
|
8315 |
+
ptc0 = r[3] // 256
|
8316 |
+
ptc1 = (r[3] // 256) % 256
|
8317 |
+
|
8318 |
+
elif find_value_power(r[3], 256) == 2:
|
8319 |
+
ptc0 = (r[3] // 256) // 256
|
8320 |
+
ptc1 = (r[3] // 256) % 256
|
8321 |
+
ptc2 = r[3] % 256
|
8322 |
+
|
8323 |
+
ptcs = [ptc0, ptc1, ptc2]
|
8324 |
+
patches = [p for p in ptcs if p != 0]
|
8325 |
+
|
8326 |
+
for i, p in enumerate(patches):
|
8327 |
+
|
8328 |
+
if p < 128:
|
8329 |
+
patch = 128
|
8330 |
+
channel = 9
|
8331 |
+
|
8332 |
+
else:
|
8333 |
+
patch = p % 128
|
8334 |
+
chan = p // 8
|
8335 |
+
|
8336 |
+
if chan == 9:
|
8337 |
+
chan += 1
|
8338 |
+
|
8339 |
+
channel = min(15, chan)
|
8340 |
+
|
8341 |
+
original_escore_notes.append(['note', r[0], r[1], channel, r[2], vel, patch])
|
8342 |
+
|
8343 |
+
output_score = sorted(original_escore_notes, key=lambda x: (x[1], -x[4], x[6]))
|
8344 |
+
|
8345 |
+
adjust_score_velocities(output_score, 127)
|
8346 |
+
|
8347 |
+
return output_score
|
8348 |
+
|
8349 |
+
###################################################################################
|
8350 |
+
|
8351 |
+
def escore_notes_delta_times(escore_notes,
|
8352 |
+
timings_index=1,
|
8353 |
+
channels_index=3,
|
8354 |
+
omit_zeros=False,
|
8355 |
+
omit_drums=False
|
8356 |
+
):
|
8357 |
+
|
8358 |
+
if omit_drums:
|
8359 |
+
|
8360 |
+
score = [e for e in escore_notes if e[channels_index] != 9]
|
8361 |
+
dtimes = [score[0][timings_index]] + [b[timings_index]-a[timings_index] for a, b in zip(score[:-1], score[1:])]
|
8362 |
+
|
8363 |
+
else:
|
8364 |
+
dtimes = [escore_notes[0][timings_index]] + [b[timings_index]-a[timings_index] for a, b in zip(escore_notes[:-1], escore_notes[1:])]
|
8365 |
+
|
8366 |
+
if omit_zeros:
|
8367 |
+
dtimes = [d for d in dtimes if d != 0]
|
8368 |
+
|
8369 |
+
return dtimes
|
8370 |
+
|
8371 |
+
###################################################################################
|
8372 |
+
|
8373 |
+
def monophonic_check(escore_notes, times_index=1):
|
8374 |
+
return len(escore_notes) == len(set([e[times_index] for e in escore_notes]))
|
8375 |
+
|
8376 |
+
###################################################################################
|
8377 |
+
|
8378 |
+
def count_escore_notes_patches(escore_notes, patches_index=6):
|
8379 |
+
return [list(c) for c in Counter([e[patches_index] for e in escore_notes]).most_common()]
|
8380 |
+
|
8381 |
+
###################################################################################
|
8382 |
+
|
8383 |
+
def escore_notes_medley(list_of_escore_notes,
|
8384 |
+
list_of_labels=None,
|
8385 |
+
pause_time_value=255
|
8386 |
+
):
|
8387 |
+
|
8388 |
+
if list_of_labels is not None:
|
8389 |
+
labels = [str(l) for l in list_of_labels] + ['No label'] * (len(list_of_escore_notes)-len(list_of_labels))
|
8390 |
+
|
8391 |
+
medley = []
|
8392 |
+
|
8393 |
+
time = 0
|
8394 |
+
|
8395 |
+
for i, m in enumerate(list_of_escore_notes):
|
8396 |
+
|
8397 |
+
if list_of_labels is not None:
|
8398 |
+
medley.append(['text_event', time, labels[i]])
|
8399 |
+
|
8400 |
+
pe = m[0]
|
8401 |
+
|
8402 |
+
for mm in m:
|
8403 |
+
|
8404 |
+
time += mm[1] - pe[1]
|
8405 |
+
|
8406 |
+
mmm = copy.deepcopy(mm)
|
8407 |
+
mmm[1] = time
|
8408 |
+
|
8409 |
+
medley.append(mmm)
|
8410 |
+
|
8411 |
+
pe = mm
|
8412 |
+
|
8413 |
+
time += pause_time_value
|
8414 |
+
|
8415 |
+
return medley
|
8416 |
+
|
8417 |
+
###################################################################################
|
8418 |
+
|
8419 |
+
def proportions_counter(list_of_values):
|
8420 |
+
|
8421 |
+
counts = Counter(list_of_values).most_common()
|
8422 |
+
clen = sum([c[1] for c in counts])
|
8423 |
+
|
8424 |
+
return [[c[0], c[1], c[1] / clen] for c in counts]
|
8425 |
+
|
8426 |
+
###################################################################################
|
8427 |
+
#
|
8428 |
+
# This is the end of the TMIDI X Python module
|
8429 |
+
#
|
8430 |
###################################################################################
|
TPLOTS.py
ADDED
@@ -0,0 +1,1245 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#! /usr/bin/python3
|
2 |
+
|
3 |
+
r'''############################################################################
|
4 |
+
################################################################################
|
5 |
+
#
|
6 |
+
#
|
7 |
+
# Tegridy Plots Python Module (TPLOTS)
|
8 |
+
# Version 1.0
|
9 |
+
#
|
10 |
+
# Project Los Angeles
|
11 |
+
#
|
12 |
+
# Tegridy Code 2024
|
13 |
+
#
|
14 |
+
# https://github.com/asigalov61/tegridy-tools
|
15 |
+
#
|
16 |
+
#
|
17 |
+
################################################################################
|
18 |
+
#
|
19 |
+
# Copyright 2024 Project Los Angeles / Tegridy Code
|
20 |
+
#
|
21 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
22 |
+
# you may not use this file except in compliance with the License.
|
23 |
+
# You may obtain a copy of the License at
|
24 |
+
#
|
25 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
26 |
+
#
|
27 |
+
# Unless required by applicable law or agreed to in writing, software
|
28 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
29 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
30 |
+
# See the License for the specific language governing permissions and
|
31 |
+
# limitations under the License.
|
32 |
+
#
|
33 |
+
################################################################################
|
34 |
+
################################################################################
|
35 |
+
#
|
36 |
+
# Critical dependencies
|
37 |
+
#
|
38 |
+
# !pip install numpy
|
39 |
+
# !pip install scipy
|
40 |
+
# !pip install matplotlib
|
41 |
+
# !pip install networkx
|
42 |
+
# !pip3 install scikit-learn
|
43 |
+
#
|
44 |
+
################################################################################
|
45 |
+
#
|
46 |
+
# Future critical dependencies
|
47 |
+
#
|
48 |
+
# !pip install umap-learn
|
49 |
+
# !pip install alphashape
|
50 |
+
#
|
51 |
+
################################################################################
|
52 |
+
'''
|
53 |
+
|
54 |
+
################################################################################
|
55 |
+
# Modules imports
|
56 |
+
################################################################################
|
57 |
+
|
58 |
+
import os
|
59 |
+
from collections import Counter
|
60 |
+
from itertools import groupby
|
61 |
+
|
62 |
+
import numpy as np
|
63 |
+
|
64 |
+
import networkx as nx
|
65 |
+
|
66 |
+
from sklearn.manifold import TSNE
|
67 |
+
from sklearn import metrics
|
68 |
+
from sklearn.preprocessing import MinMaxScaler
|
69 |
+
from sklearn.decomposition import PCA
|
70 |
+
|
71 |
+
from scipy.ndimage import zoom
|
72 |
+
from scipy.spatial import distance_matrix
|
73 |
+
from scipy.sparse.csgraph import minimum_spanning_tree
|
74 |
+
from scipy.stats import zscore
|
75 |
+
|
76 |
+
import matplotlib.pyplot as plt
|
77 |
+
from PIL import Image
|
78 |
+
|
79 |
+
################################################################################
|
80 |
+
# Constants
|
81 |
+
################################################################################
|
82 |
+
|
83 |
+
ALL_CHORDS_FILTERED = [[0], [0, 3], [0, 3, 5], [0, 3, 5, 8], [0, 3, 5, 9], [0, 3, 5, 10], [0, 3, 7],
|
84 |
+
[0, 3, 7, 10], [0, 3, 8], [0, 3, 9], [0, 3, 10], [0, 4], [0, 4, 6],
|
85 |
+
[0, 4, 6, 9], [0, 4, 6, 10], [0, 4, 7], [0, 4, 7, 10], [0, 4, 8], [0, 4, 9],
|
86 |
+
[0, 4, 10], [0, 5], [0, 5, 8], [0, 5, 9], [0, 5, 10], [0, 6], [0, 6, 9],
|
87 |
+
[0, 6, 10], [0, 7], [0, 7, 10], [0, 8], [0, 9], [0, 10], [1], [1, 4],
|
88 |
+
[1, 4, 6], [1, 4, 6, 9], [1, 4, 6, 10], [1, 4, 6, 11], [1, 4, 7],
|
89 |
+
[1, 4, 7, 10], [1, 4, 7, 11], [1, 4, 8], [1, 4, 8, 11], [1, 4, 9], [1, 4, 10],
|
90 |
+
[1, 4, 11], [1, 5], [1, 5, 8], [1, 5, 8, 11], [1, 5, 9], [1, 5, 10],
|
91 |
+
[1, 5, 11], [1, 6], [1, 6, 9], [1, 6, 10], [1, 6, 11], [1, 7], [1, 7, 10],
|
92 |
+
[1, 7, 11], [1, 8], [1, 8, 11], [1, 9], [1, 10], [1, 11], [2], [2, 5],
|
93 |
+
[2, 5, 8], [2, 5, 8, 11], [2, 5, 9], [2, 5, 10], [2, 5, 11], [2, 6], [2, 6, 9],
|
94 |
+
[2, 6, 10], [2, 6, 11], [2, 7], [2, 7, 10], [2, 7, 11], [2, 8], [2, 8, 11],
|
95 |
+
[2, 9], [2, 10], [2, 11], [3], [3, 5], [3, 5, 8], [3, 5, 8, 11], [3, 5, 9],
|
96 |
+
[3, 5, 10], [3, 5, 11], [3, 7], [3, 7, 10], [3, 7, 11], [3, 8], [3, 8, 11],
|
97 |
+
[3, 9], [3, 10], [3, 11], [4], [4, 6], [4, 6, 9], [4, 6, 10], [4, 6, 11],
|
98 |
+
[4, 7], [4, 7, 10], [4, 7, 11], [4, 8], [4, 8, 11], [4, 9], [4, 10], [4, 11],
|
99 |
+
[5], [5, 8], [5, 8, 11], [5, 9], [5, 10], [5, 11], [6], [6, 9], [6, 10],
|
100 |
+
[6, 11], [7], [7, 10], [7, 11], [8], [8, 11], [9], [10], [11]]
|
101 |
+
|
102 |
+
################################################################################
|
103 |
+
|
104 |
+
CHORDS_TYPES = ['WHITE', 'BLACK', 'UNKNOWN', 'MIXED WHITE', 'MIXED BLACK', 'MIXED GRAY']
|
105 |
+
|
106 |
+
################################################################################
|
107 |
+
|
108 |
+
WHITE_NOTES = [0, 2, 4, 5, 7, 9, 11]
|
109 |
+
|
110 |
+
################################################################################
|
111 |
+
|
112 |
+
BLACK_NOTES = [1, 3, 6, 8, 10]
|
113 |
+
|
114 |
+
################################################################################
|
115 |
+
# Helper functions
|
116 |
+
################################################################################
|
117 |
+
|
118 |
+
def tones_chord_type(tones_chord,
|
119 |
+
return_chord_type_index=True,
|
120 |
+
):
|
121 |
+
|
122 |
+
"""
|
123 |
+
Returns tones chord type
|
124 |
+
"""
|
125 |
+
|
126 |
+
WN = WHITE_NOTES
|
127 |
+
BN = BLACK_NOTES
|
128 |
+
MX = WHITE_NOTES + BLACK_NOTES
|
129 |
+
|
130 |
+
|
131 |
+
CHORDS = ALL_CHORDS_FILTERED
|
132 |
+
|
133 |
+
tones_chord = sorted(tones_chord)
|
134 |
+
|
135 |
+
ctype = 'UNKNOWN'
|
136 |
+
|
137 |
+
if tones_chord in CHORDS:
|
138 |
+
|
139 |
+
if sorted(set(tones_chord) & set(WN)) == tones_chord:
|
140 |
+
ctype = 'WHITE'
|
141 |
+
|
142 |
+
elif sorted(set(tones_chord) & set(BN)) == tones_chord:
|
143 |
+
ctype = 'BLACK'
|
144 |
+
|
145 |
+
if len(tones_chord) > 1 and sorted(set(tones_chord) & set(MX)) == tones_chord:
|
146 |
+
|
147 |
+
if len(sorted(set(tones_chord) & set(WN))) == len(sorted(set(tones_chord) & set(BN))):
|
148 |
+
ctype = 'MIXED GRAY'
|
149 |
+
|
150 |
+
elif len(sorted(set(tones_chord) & set(WN))) > len(sorted(set(tones_chord) & set(BN))):
|
151 |
+
ctype = 'MIXED WHITE'
|
152 |
+
|
153 |
+
elif len(sorted(set(tones_chord) & set(WN))) < len(sorted(set(tones_chord) & set(BN))):
|
154 |
+
ctype = 'MIXED BLACK'
|
155 |
+
|
156 |
+
if return_chord_type_index:
|
157 |
+
return CHORDS_TYPES.index(ctype)
|
158 |
+
|
159 |
+
else:
|
160 |
+
return ctype
|
161 |
+
|
162 |
+
###################################################################################
|
163 |
+
|
164 |
+
def tone_type(tone,
|
165 |
+
return_tone_type_index=True
|
166 |
+
):
|
167 |
+
|
168 |
+
"""
|
169 |
+
Returns tone type
|
170 |
+
"""
|
171 |
+
|
172 |
+
tone = tone % 12
|
173 |
+
|
174 |
+
if tone in BLACK_NOTES:
|
175 |
+
if return_tone_type_index:
|
176 |
+
return CHORDS_TYPES.index('BLACK')
|
177 |
+
else:
|
178 |
+
return "BLACK"
|
179 |
+
|
180 |
+
else:
|
181 |
+
if return_tone_type_index:
|
182 |
+
return CHORDS_TYPES.index('WHITE')
|
183 |
+
else:
|
184 |
+
return "WHITE"
|
185 |
+
|
186 |
+
###################################################################################
|
187 |
+
|
188 |
+
def find_closest_points(points, return_points=True):
|
189 |
+
|
190 |
+
"""
|
191 |
+
Find closest 2D points
|
192 |
+
"""
|
193 |
+
|
194 |
+
coords = np.array(points)
|
195 |
+
|
196 |
+
num_points = coords.shape[0]
|
197 |
+
closest_matches = np.zeros(num_points, dtype=int)
|
198 |
+
distances = np.zeros((num_points, num_points))
|
199 |
+
|
200 |
+
for i in range(num_points):
|
201 |
+
for j in range(num_points):
|
202 |
+
if i != j:
|
203 |
+
distances[i, j] = np.linalg.norm(coords[i] - coords[j])
|
204 |
+
else:
|
205 |
+
distances[i, j] = np.inf
|
206 |
+
|
207 |
+
closest_matches = np.argmin(distances, axis=1)
|
208 |
+
|
209 |
+
if return_points:
|
210 |
+
points_matches = coords[closest_matches].tolist()
|
211 |
+
return points_matches
|
212 |
+
|
213 |
+
else:
|
214 |
+
return closest_matches.tolist()
|
215 |
+
|
216 |
+
################################################################################
|
217 |
+
|
218 |
+
def reduce_dimensionality_tsne(list_of_valies,
|
219 |
+
n_comp=2,
|
220 |
+
n_iter=5000,
|
221 |
+
verbose=True
|
222 |
+
):
|
223 |
+
|
224 |
+
"""
|
225 |
+
Reduces the dimensionality of the values using t-SNE.
|
226 |
+
"""
|
227 |
+
|
228 |
+
vals = np.array(list_of_valies)
|
229 |
+
|
230 |
+
tsne = TSNE(n_components=n_comp,
|
231 |
+
n_iter=n_iter,
|
232 |
+
verbose=verbose)
|
233 |
+
|
234 |
+
reduced_vals = tsne.fit_transform(vals)
|
235 |
+
|
236 |
+
return reduced_vals.tolist()
|
237 |
+
|
238 |
+
################################################################################
|
239 |
+
|
240 |
+
def compute_mst_edges(similarity_scores_list):
|
241 |
+
|
242 |
+
"""
|
243 |
+
Computes the Minimum Spanning Tree (MST) edges based on the similarity scores.
|
244 |
+
"""
|
245 |
+
|
246 |
+
num_tokens = len(similarity_scores_list[0])
|
247 |
+
|
248 |
+
graph = nx.Graph()
|
249 |
+
|
250 |
+
for i in range(num_tokens):
|
251 |
+
for j in range(i + 1, num_tokens):
|
252 |
+
weight = 1 - similarity_scores_list[i][j]
|
253 |
+
graph.add_edge(i, j, weight=weight)
|
254 |
+
|
255 |
+
mst = nx.minimum_spanning_tree(graph)
|
256 |
+
|
257 |
+
mst_edges = list(mst.edges(data=False))
|
258 |
+
|
259 |
+
return mst_edges
|
260 |
+
|
261 |
+
################################################################################
|
262 |
+
|
263 |
+
def square_binary_matrix(binary_matrix,
|
264 |
+
matrix_size=128,
|
265 |
+
interpolation_order=5,
|
266 |
+
return_square_matrix_points=False
|
267 |
+
):
|
268 |
+
|
269 |
+
"""
|
270 |
+
Reduces an arbitrary binary matrix to a square binary matrix
|
271 |
+
"""
|
272 |
+
|
273 |
+
zoom_factors = (matrix_size / len(binary_matrix), 1)
|
274 |
+
|
275 |
+
resized_matrix = zoom(binary_matrix, zoom_factors, order=interpolation_order)
|
276 |
+
|
277 |
+
resized_matrix = (resized_matrix > 0.5).astype(int)
|
278 |
+
|
279 |
+
final_matrix = np.zeros((matrix_size, matrix_size), dtype=int)
|
280 |
+
final_matrix[:, :resized_matrix.shape[1]] = resized_matrix
|
281 |
+
|
282 |
+
points = np.column_stack(np.where(final_matrix == 1)).tolist()
|
283 |
+
|
284 |
+
if return_square_matrix_points:
|
285 |
+
return points
|
286 |
+
|
287 |
+
else:
|
288 |
+
return resized_matrix
|
289 |
+
|
290 |
+
################################################################################
|
291 |
+
|
292 |
+
def square_matrix_points_colors(square_matrix_points):
|
293 |
+
|
294 |
+
"""
|
295 |
+
Returns colors for square matrix points
|
296 |
+
"""
|
297 |
+
|
298 |
+
cmap = generate_colors(12)
|
299 |
+
|
300 |
+
chords = []
|
301 |
+
chords_dict = set()
|
302 |
+
counts = []
|
303 |
+
|
304 |
+
for k, v in groupby(square_matrix_points, key=lambda x: x[0]):
|
305 |
+
pgroup = [vv[1] for vv in v]
|
306 |
+
chord = sorted(set(pgroup))
|
307 |
+
tchord = sorted(set([p % 12 for p in chord]))
|
308 |
+
chords_dict.add(tuple(tchord))
|
309 |
+
chords.append(tuple(tchord))
|
310 |
+
counts.append(len(pgroup))
|
311 |
+
|
312 |
+
chords_dict = sorted(chords_dict)
|
313 |
+
|
314 |
+
colors = []
|
315 |
+
|
316 |
+
for i, c in enumerate(chords):
|
317 |
+
colors.extend([cmap[round(sum(c) / len(c))]] * counts[i])
|
318 |
+
|
319 |
+
return colors
|
320 |
+
|
321 |
+
################################################################################
|
322 |
+
|
323 |
+
def hsv_to_rgb(h, s, v):
|
324 |
+
|
325 |
+
if s == 0.0:
|
326 |
+
return v, v, v
|
327 |
+
|
328 |
+
i = int(h*6.0)
|
329 |
+
f = (h*6.0) - i
|
330 |
+
p = v*(1.0 - s)
|
331 |
+
q = v*(1.0 - s*f)
|
332 |
+
t = v*(1.0 - s*(1.0-f))
|
333 |
+
i = i%6
|
334 |
+
|
335 |
+
return [(v, t, p), (q, v, p), (p, v, t), (p, q, v), (t, p, v), (v, p, q)][i]
|
336 |
+
|
337 |
+
################################################################################
|
338 |
+
|
339 |
+
def generate_colors(n):
|
340 |
+
return [hsv_to_rgb(i/n, 1, 1) for i in range(n)]
|
341 |
+
|
342 |
+
################################################################################
|
343 |
+
|
344 |
+
def add_arrays(a, b):
|
345 |
+
return [sum(pair) for pair in zip(a, b)]
|
346 |
+
|
347 |
+
################################################################################
|
348 |
+
|
349 |
+
def calculate_similarities(lists_of_values, metric='cosine'):
|
350 |
+
return metrics.pairwise_distances(lists_of_values, metric=metric).tolist()
|
351 |
+
|
352 |
+
################################################################################
|
353 |
+
|
354 |
+
def get_tokens_embeddings(x_transformer_model):
|
355 |
+
return x_transformer_model.net.token_emb.emb.weight.detach().cpu().tolist()
|
356 |
+
|
357 |
+
################################################################################
|
358 |
+
|
359 |
+
def minkowski_distance_matrix(X, p=3):
|
360 |
+
|
361 |
+
X = np.array(X)
|
362 |
+
|
363 |
+
n = X.shape[0]
|
364 |
+
dist_matrix = np.zeros((n, n))
|
365 |
+
|
366 |
+
for i in range(n):
|
367 |
+
for j in range(n):
|
368 |
+
dist_matrix[i, j] = np.sum(np.abs(X[i] - X[j])**p)**(1/p)
|
369 |
+
|
370 |
+
return dist_matrix.tolist()
|
371 |
+
|
372 |
+
################################################################################
|
373 |
+
|
374 |
+
def robust_normalize(values):
|
375 |
+
|
376 |
+
values = np.array(values)
|
377 |
+
q1 = np.percentile(values, 25)
|
378 |
+
q3 = np.percentile(values, 75)
|
379 |
+
iqr = q3 - q1
|
380 |
+
|
381 |
+
filtered_values = values[(values >= q1 - 1.5 * iqr) & (values <= q3 + 1.5 * iqr)]
|
382 |
+
|
383 |
+
min_val = np.min(filtered_values)
|
384 |
+
max_val = np.max(filtered_values)
|
385 |
+
normalized_values = (values - min_val) / (max_val - min_val)
|
386 |
+
|
387 |
+
normalized_values = np.clip(normalized_values, 0, 1)
|
388 |
+
|
389 |
+
return normalized_values.tolist()
|
390 |
+
|
391 |
+
################################################################################
|
392 |
+
|
393 |
+
def min_max_normalize(values):
|
394 |
+
|
395 |
+
scaler = MinMaxScaler()
|
396 |
+
|
397 |
+
return scaler.fit_transform(values).tolist()
|
398 |
+
|
399 |
+
################################################################################
|
400 |
+
|
401 |
+
def remove_points_outliers(points, z_score_threshold=3):
|
402 |
+
|
403 |
+
points = np.array(points)
|
404 |
+
|
405 |
+
z_scores = np.abs(zscore(points, axis=0))
|
406 |
+
|
407 |
+
return points[(z_scores < z_score_threshold).all(axis=1)].tolist()
|
408 |
+
|
409 |
+
################################################################################
|
410 |
+
|
411 |
+
def generate_labels(lists_of_values,
|
412 |
+
return_indices_labels=False
|
413 |
+
):
|
414 |
+
|
415 |
+
ordered_indices = list(range(len(lists_of_values)))
|
416 |
+
ordered_indices_labels = [str(i) for i in ordered_indices]
|
417 |
+
ordered_values_labels = [str(lists_of_values[i]) for i in ordered_indices]
|
418 |
+
|
419 |
+
if return_indices_labels:
|
420 |
+
return ordered_indices_labels
|
421 |
+
|
422 |
+
else:
|
423 |
+
return ordered_values_labels
|
424 |
+
|
425 |
+
################################################################################
|
426 |
+
|
427 |
+
def reduce_dimensionality_pca(list_of_values, n_components=2):
|
428 |
+
|
429 |
+
"""
|
430 |
+
Reduces the dimensionality of the values using PCA.
|
431 |
+
"""
|
432 |
+
|
433 |
+
pca = PCA(n_components=n_components)
|
434 |
+
pca_data = pca.fit_transform(list_of_values)
|
435 |
+
|
436 |
+
return pca_data.tolist()
|
437 |
+
|
438 |
+
def reduce_dimensionality_simple(list_of_values,
|
439 |
+
return_means=True,
|
440 |
+
return_std_devs=True,
|
441 |
+
return_medians=False,
|
442 |
+
return_vars=False
|
443 |
+
):
|
444 |
+
|
445 |
+
'''
|
446 |
+
Reduces dimensionality of the values in a simple way
|
447 |
+
'''
|
448 |
+
|
449 |
+
array = np.array(list_of_values)
|
450 |
+
results = []
|
451 |
+
|
452 |
+
if return_means:
|
453 |
+
means = np.mean(array, axis=1)
|
454 |
+
results.append(means)
|
455 |
+
|
456 |
+
if return_std_devs:
|
457 |
+
std_devs = np.std(array, axis=1)
|
458 |
+
results.append(std_devs)
|
459 |
+
|
460 |
+
if return_medians:
|
461 |
+
medians = np.median(array, axis=1)
|
462 |
+
results.append(medians)
|
463 |
+
|
464 |
+
if return_vars:
|
465 |
+
vars = np.var(array, axis=1)
|
466 |
+
results.append(vars)
|
467 |
+
|
468 |
+
merged_results = np.column_stack(results)
|
469 |
+
|
470 |
+
return merged_results.tolist()
|
471 |
+
|
472 |
+
################################################################################
|
473 |
+
|
474 |
+
def reduce_dimensionality_2d_distance(list_of_values, p=5):
|
475 |
+
|
476 |
+
'''
|
477 |
+
Reduces the dimensionality of the values using 2d distance
|
478 |
+
'''
|
479 |
+
|
480 |
+
values = np.array(list_of_values)
|
481 |
+
|
482 |
+
dist_matrix = distance_matrix(values, values, p=p)
|
483 |
+
|
484 |
+
mst = minimum_spanning_tree(dist_matrix).toarray()
|
485 |
+
|
486 |
+
points = []
|
487 |
+
|
488 |
+
for i in range(len(values)):
|
489 |
+
for j in range(len(values)):
|
490 |
+
if mst[i, j] > 0:
|
491 |
+
points.append([i, j])
|
492 |
+
|
493 |
+
return points
|
494 |
+
|
495 |
+
################################################################################
|
496 |
+
|
497 |
+
def normalize_to_range(values, n):
|
498 |
+
|
499 |
+
min_val = min(values)
|
500 |
+
max_val = max(values)
|
501 |
+
|
502 |
+
range_val = max_val - min_val
|
503 |
+
|
504 |
+
normalized_values = [((value - min_val) / range_val * 2 * n) - n for value in values]
|
505 |
+
|
506 |
+
return normalized_values
|
507 |
+
|
508 |
+
################################################################################
|
509 |
+
|
510 |
+
def reduce_dimensionality_simple_pca(list_of_values, n_components=2):
|
511 |
+
|
512 |
+
'''
|
513 |
+
Reduces the dimensionality of the values using simple PCA
|
514 |
+
'''
|
515 |
+
|
516 |
+
reduced_values = []
|
517 |
+
|
518 |
+
for l in list_of_values:
|
519 |
+
|
520 |
+
norm_values = [round(v * len(l)) for v in normalize_to_range(l, (n_components+1) // 2)]
|
521 |
+
|
522 |
+
pca_values = Counter(norm_values).most_common()
|
523 |
+
pca_values = [vv[0] / len(l) for vv in pca_values]
|
524 |
+
pca_values = pca_values[:n_components]
|
525 |
+
pca_values = pca_values + [0] * (n_components - len(pca_values))
|
526 |
+
|
527 |
+
reduced_values.append(pca_values)
|
528 |
+
|
529 |
+
return reduced_values
|
530 |
+
|
531 |
+
################################################################################
|
532 |
+
|
533 |
+
def filter_and_replace_values(list_of_values,
|
534 |
+
threshold,
|
535 |
+
replace_value,
|
536 |
+
replace_above_threshold=False
|
537 |
+
):
|
538 |
+
|
539 |
+
array = np.array(list_of_values)
|
540 |
+
|
541 |
+
modified_array = np.copy(array)
|
542 |
+
|
543 |
+
if replace_above_threshold:
|
544 |
+
modified_array[modified_array > threshold] = replace_value
|
545 |
+
|
546 |
+
else:
|
547 |
+
modified_array[modified_array < threshold] = replace_value
|
548 |
+
|
549 |
+
return modified_array.tolist()
|
550 |
+
|
551 |
+
################################################################################
|
552 |
+
|
553 |
+
def find_shortest_constellation_path(points,
|
554 |
+
start_point_idx,
|
555 |
+
end_point_idx,
|
556 |
+
p=5,
|
557 |
+
return_path_length=False,
|
558 |
+
return_path_points=False,
|
559 |
+
):
|
560 |
+
|
561 |
+
"""
|
562 |
+
Finds the shortest path between two points of the points constellation
|
563 |
+
"""
|
564 |
+
|
565 |
+
points = np.array(points)
|
566 |
+
|
567 |
+
dist_matrix = distance_matrix(points, points, p=p)
|
568 |
+
|
569 |
+
mst = minimum_spanning_tree(dist_matrix).toarray()
|
570 |
+
|
571 |
+
G = nx.Graph()
|
572 |
+
|
573 |
+
for i in range(len(points)):
|
574 |
+
for j in range(len(points)):
|
575 |
+
if mst[i, j] > 0:
|
576 |
+
G.add_edge(i, j, weight=mst[i, j])
|
577 |
+
|
578 |
+
path = nx.shortest_path(G,
|
579 |
+
source=start_point_idx,
|
580 |
+
target=end_point_idx,
|
581 |
+
weight='weight'
|
582 |
+
)
|
583 |
+
|
584 |
+
path_length = nx.shortest_path_length(G,
|
585 |
+
source=start_point_idx,
|
586 |
+
target=end_point_idx,
|
587 |
+
weight='weight')
|
588 |
+
|
589 |
+
path_points = points[np.array(path)].tolist()
|
590 |
+
|
591 |
+
|
592 |
+
if return_path_points:
|
593 |
+
return path_points
|
594 |
+
|
595 |
+
if return_path_length:
|
596 |
+
return path_length
|
597 |
+
|
598 |
+
return path
|
599 |
+
|
600 |
+
################################################################################
|
601 |
+
# Core functions
|
602 |
+
################################################################################
|
603 |
+
|
604 |
+
def plot_ms_SONG(ms_song,
|
605 |
+
preview_length_in_notes=0,
|
606 |
+
block_lines_times_list = None,
|
607 |
+
plot_title='ms Song',
|
608 |
+
max_num_colors=129,
|
609 |
+
drums_color_num=128,
|
610 |
+
plot_size=(11,4),
|
611 |
+
note_height = 0.75,
|
612 |
+
show_grid_lines=False,
|
613 |
+
return_plt = False,
|
614 |
+
timings_multiplier=1,
|
615 |
+
save_plt='',
|
616 |
+
save_only_plt_image=True,
|
617 |
+
save_transparent=False
|
618 |
+
):
|
619 |
+
|
620 |
+
'''ms SONG plot'''
|
621 |
+
|
622 |
+
notes = [s for s in ms_song if s[0] == 'note']
|
623 |
+
|
624 |
+
if (len(max(notes, key=len)) != 7) and (len(min(notes, key=len)) != 7):
|
625 |
+
print('The song notes do not have patches information')
|
626 |
+
print('Ploease add patches to the notes in the song')
|
627 |
+
|
628 |
+
else:
|
629 |
+
|
630 |
+
start_times = [(s[1] * timings_multiplier) / 1000 for s in notes]
|
631 |
+
durations = [(s[2] * timings_multiplier) / 1000 for s in notes]
|
632 |
+
pitches = [s[4] for s in notes]
|
633 |
+
patches = [s[6] for s in notes]
|
634 |
+
|
635 |
+
colors = generate_colors(max_num_colors)
|
636 |
+
colors[drums_color_num] = (1, 1, 1)
|
637 |
+
|
638 |
+
pbl = (notes[preview_length_in_notes][1] * timings_multiplier) / 1000
|
639 |
+
|
640 |
+
fig, ax = plt.subplots(figsize=plot_size)
|
641 |
+
|
642 |
+
for start, duration, pitch, patch in zip(start_times, durations, pitches, patches):
|
643 |
+
rect = plt.Rectangle((start, pitch), duration, note_height, facecolor=colors[patch])
|
644 |
+
ax.add_patch(rect)
|
645 |
+
|
646 |
+
ax.set_xlim([min(start_times), max(add_arrays(start_times, durations))])
|
647 |
+
ax.set_ylim([min(pitches)-1, max(pitches)+1])
|
648 |
+
|
649 |
+
ax.set_facecolor('black')
|
650 |
+
fig.patch.set_facecolor('white')
|
651 |
+
|
652 |
+
if preview_length_in_notes > 0:
|
653 |
+
ax.axvline(x=pbl, c='white')
|
654 |
+
|
655 |
+
if block_lines_times_list:
|
656 |
+
for bl in block_lines_times_list:
|
657 |
+
ax.axvline(x=bl, c='white')
|
658 |
+
|
659 |
+
if show_grid_lines:
|
660 |
+
ax.grid(color='white')
|
661 |
+
|
662 |
+
plt.xlabel('Time (s)', c='black')
|
663 |
+
plt.ylabel('MIDI Pitch', c='black')
|
664 |
+
|
665 |
+
plt.title(plot_title)
|
666 |
+
|
667 |
+
if save_plt != '':
|
668 |
+
if save_only_plt_image:
|
669 |
+
plt.axis('off')
|
670 |
+
plt.title('')
|
671 |
+
plt.savefig(save_plt,
|
672 |
+
transparent=save_transparent,
|
673 |
+
bbox_inches='tight',
|
674 |
+
pad_inches=0,
|
675 |
+
facecolor='black'
|
676 |
+
)
|
677 |
+
plt.close()
|
678 |
+
|
679 |
+
else:
|
680 |
+
plt.savefig(save_plt)
|
681 |
+
plt.close()
|
682 |
+
|
683 |
+
if return_plt:
|
684 |
+
return fig
|
685 |
+
|
686 |
+
plt.show()
|
687 |
+
plt.close()
|
688 |
+
|
689 |
+
################################################################################
|
690 |
+
|
691 |
+
def plot_square_matrix_points(list_of_points,
|
692 |
+
list_of_points_colors,
|
693 |
+
plot_size=(7, 7),
|
694 |
+
point_size = 10,
|
695 |
+
show_grid_lines=False,
|
696 |
+
plot_title = 'Square Matrix Points Plot',
|
697 |
+
return_plt=False,
|
698 |
+
save_plt='',
|
699 |
+
save_only_plt_image=True,
|
700 |
+
save_transparent=False
|
701 |
+
):
|
702 |
+
|
703 |
+
'''Square matrix points plot'''
|
704 |
+
|
705 |
+
fig, ax = plt.subplots(figsize=plot_size)
|
706 |
+
|
707 |
+
ax.set_facecolor('black')
|
708 |
+
|
709 |
+
if show_grid_lines:
|
710 |
+
ax.grid(color='white')
|
711 |
+
|
712 |
+
plt.xlabel('Time Step', c='black')
|
713 |
+
plt.ylabel('MIDI Pitch', c='black')
|
714 |
+
|
715 |
+
plt.title(plot_title)
|
716 |
+
|
717 |
+
plt.scatter([p[0] for p in list_of_points],
|
718 |
+
[p[1] for p in list_of_points],
|
719 |
+
c=list_of_points_colors,
|
720 |
+
s=point_size
|
721 |
+
)
|
722 |
+
|
723 |
+
if save_plt != '':
|
724 |
+
if save_only_plt_image:
|
725 |
+
plt.axis('off')
|
726 |
+
plt.title('')
|
727 |
+
plt.savefig(save_plt,
|
728 |
+
transparent=save_transparent,
|
729 |
+
bbox_inches='tight',
|
730 |
+
pad_inches=0,
|
731 |
+
facecolor='black'
|
732 |
+
)
|
733 |
+
plt.close()
|
734 |
+
|
735 |
+
else:
|
736 |
+
plt.savefig(save_plt)
|
737 |
+
plt.close()
|
738 |
+
|
739 |
+
if return_plt:
|
740 |
+
return fig
|
741 |
+
|
742 |
+
plt.show()
|
743 |
+
plt.close()
|
744 |
+
|
745 |
+
################################################################################
|
746 |
+
|
747 |
+
def plot_cosine_similarities(lists_of_values,
|
748 |
+
plot_size=(7, 7),
|
749 |
+
save_plot=''
|
750 |
+
):
|
751 |
+
|
752 |
+
"""
|
753 |
+
Cosine similarities plot
|
754 |
+
"""
|
755 |
+
|
756 |
+
cos_sim = metrics.pairwise_distances(lists_of_values, metric='cosine')
|
757 |
+
|
758 |
+
plt.figure(figsize=plot_size)
|
759 |
+
|
760 |
+
plt.imshow(cos_sim, cmap="inferno", interpolation="nearest")
|
761 |
+
|
762 |
+
im_ratio = cos_sim.shape[0] / cos_sim.shape[1]
|
763 |
+
|
764 |
+
plt.colorbar(fraction=0.046 * im_ratio, pad=0.04)
|
765 |
+
|
766 |
+
plt.xlabel("Index")
|
767 |
+
plt.ylabel("Index")
|
768 |
+
|
769 |
+
plt.tight_layout()
|
770 |
+
|
771 |
+
if save_plot != '':
|
772 |
+
plt.savefig(save_plot, bbox_inches="tight")
|
773 |
+
plt.close()
|
774 |
+
|
775 |
+
plt.show()
|
776 |
+
plt.close()
|
777 |
+
|
778 |
+
################################################################################
|
779 |
+
|
780 |
+
def plot_points_with_mst_lines(points,
|
781 |
+
points_labels,
|
782 |
+
points_mst_edges,
|
783 |
+
plot_size=(20, 20),
|
784 |
+
labels_size=24,
|
785 |
+
save_plot=''
|
786 |
+
):
|
787 |
+
|
788 |
+
"""
|
789 |
+
Plots 2D points with labels and MST lines.
|
790 |
+
"""
|
791 |
+
|
792 |
+
plt.figure(figsize=plot_size)
|
793 |
+
|
794 |
+
for i, label in enumerate(points_labels):
|
795 |
+
plt.scatter(points[i][0], points[i][1])
|
796 |
+
plt.annotate(label, (points[i][0], points[i][1]), fontsize=labels_size)
|
797 |
+
|
798 |
+
for edge in points_mst_edges:
|
799 |
+
i, j = edge
|
800 |
+
plt.plot([points[i][0], points[j][0]], [points[i][1], points[j][1]], 'k-', alpha=0.5)
|
801 |
+
|
802 |
+
plt.title('Points Map with MST Lines', fontsize=labels_size)
|
803 |
+
plt.xlabel('X-axis', fontsize=labels_size)
|
804 |
+
plt.ylabel('Y-axis', fontsize=labels_size)
|
805 |
+
|
806 |
+
if save_plot != '':
|
807 |
+
plt.savefig(save_plot, bbox_inches="tight")
|
808 |
+
plt.close()
|
809 |
+
|
810 |
+
plt.show()
|
811 |
+
|
812 |
+
plt.close()
|
813 |
+
|
814 |
+
################################################################################
|
815 |
+
|
816 |
+
def plot_points_constellation(points,
|
817 |
+
points_labels,
|
818 |
+
p=5,
|
819 |
+
plot_size=(15, 15),
|
820 |
+
labels_size=12,
|
821 |
+
show_grid=False,
|
822 |
+
save_plot=''
|
823 |
+
):
|
824 |
+
|
825 |
+
"""
|
826 |
+
Plots 2D points constellation
|
827 |
+
"""
|
828 |
+
|
829 |
+
points = np.array(points)
|
830 |
+
|
831 |
+
dist_matrix = distance_matrix(points, points, p=p)
|
832 |
+
|
833 |
+
mst = minimum_spanning_tree(dist_matrix).toarray()
|
834 |
+
|
835 |
+
plt.figure(figsize=plot_size)
|
836 |
+
|
837 |
+
plt.scatter(points[:, 0], points[:, 1], color='blue')
|
838 |
+
|
839 |
+
for i, label in enumerate(points_labels):
|
840 |
+
plt.annotate(label, (points[i, 0], points[i, 1]),
|
841 |
+
textcoords="offset points",
|
842 |
+
xytext=(0, 10),
|
843 |
+
ha='center',
|
844 |
+
fontsize=labels_size
|
845 |
+
)
|
846 |
+
|
847 |
+
for i in range(len(points)):
|
848 |
+
for j in range(len(points)):
|
849 |
+
if mst[i, j] > 0:
|
850 |
+
plt.plot([points[i, 0], points[j, 0]], [points[i, 1], points[j, 1]], 'k--')
|
851 |
+
|
852 |
+
plt.xlabel('X-axis', fontsize=labels_size)
|
853 |
+
plt.ylabel('Y-axis', fontsize=labels_size)
|
854 |
+
plt.title('2D Coordinates with Minimum Spanning Tree', fontsize=labels_size)
|
855 |
+
|
856 |
+
plt.grid(show_grid)
|
857 |
+
|
858 |
+
if save_plot != '':
|
859 |
+
plt.savefig(save_plot, bbox_inches="tight")
|
860 |
+
plt.close()
|
861 |
+
|
862 |
+
plt.show()
|
863 |
+
|
864 |
+
plt.close()
|
865 |
+
|
866 |
+
################################################################################
|
867 |
+
|
868 |
+
def binary_matrix_to_images(matrix,
|
869 |
+
step,
|
870 |
+
overlap,
|
871 |
+
output_folder='./Dataset/',
|
872 |
+
output_img_prefix='image',
|
873 |
+
output_img_ext='.png',
|
874 |
+
save_to_array=False,
|
875 |
+
verbose=True
|
876 |
+
):
|
877 |
+
|
878 |
+
if not save_to_array:
|
879 |
+
|
880 |
+
if verbose:
|
881 |
+
print('=' * 70)
|
882 |
+
print('Checking output folder dir...')
|
883 |
+
|
884 |
+
os.makedirs(os.path.dirname(output_folder), exist_ok=True)
|
885 |
+
|
886 |
+
if verbose:
|
887 |
+
print('Done!')
|
888 |
+
|
889 |
+
if verbose:
|
890 |
+
print('=' * 70)
|
891 |
+
print('Writing images...')
|
892 |
+
|
893 |
+
matrix = np.array(matrix, dtype=np.uint8)
|
894 |
+
|
895 |
+
image_array = []
|
896 |
+
|
897 |
+
for i in range(0, max(1, matrix.shape[0]), overlap):
|
898 |
+
|
899 |
+
submatrix = matrix[i:i+step, :]
|
900 |
+
|
901 |
+
if submatrix.shape[0] < 128:
|
902 |
+
zeros_array = np.zeros((128-submatrix.shape[0], 128))
|
903 |
+
submatrix = np.vstack((submatrix, zeros_array))
|
904 |
+
|
905 |
+
img = Image.fromarray(submatrix * 255).convert('1')
|
906 |
+
|
907 |
+
if save_to_array:
|
908 |
+
image_array.append(np.array(img))
|
909 |
+
|
910 |
+
else:
|
911 |
+
img.save(output_folder + output_img_prefix + '_' + str(matrix.shape[1]) + '_' + str(i).zfill(7) + output_img_ext)
|
912 |
+
|
913 |
+
if verbose:
|
914 |
+
print('Done!')
|
915 |
+
print('=' * 70)
|
916 |
+
print('Saved', (matrix.shape[0] // min(step, overlap))+1, 'imges!')
|
917 |
+
print('=' * 70)
|
918 |
+
|
919 |
+
if save_to_array:
|
920 |
+
return np.array(image_array).tolist()
|
921 |
+
|
922 |
+
################################################################################
|
923 |
+
|
924 |
+
def images_to_binary_matrix(list_of_images):
|
925 |
+
|
926 |
+
image_array = np.array(list_of_images)
|
927 |
+
|
928 |
+
original_matrix = []
|
929 |
+
|
930 |
+
for img in image_array:
|
931 |
+
|
932 |
+
submatrix = np.array(img)
|
933 |
+
original_matrix.extend(submatrix.tolist())
|
934 |
+
|
935 |
+
return original_matrix
|
936 |
+
|
937 |
+
################################################################################
|
938 |
+
|
939 |
+
def square_image_matrix(image_matrix,
|
940 |
+
matrix_size=128,
|
941 |
+
num_pca_components=5,
|
942 |
+
filter_out_zero_rows=False,
|
943 |
+
return_square_matrix_points=False
|
944 |
+
):
|
945 |
+
|
946 |
+
"""
|
947 |
+
Reduces an arbitrary image matrix to a square image matrix
|
948 |
+
"""
|
949 |
+
|
950 |
+
matrix = np.array(image_matrix)
|
951 |
+
|
952 |
+
if filter_out_zero_rows:
|
953 |
+
matrix = matrix[~np.all(matrix == 0, axis=1)]
|
954 |
+
|
955 |
+
target_rows = matrix_size
|
956 |
+
|
957 |
+
rows_per_group = matrix.shape[0] // target_rows
|
958 |
+
|
959 |
+
compressed_matrix = np.zeros((target_rows, matrix.shape[1]), dtype=np.int32)
|
960 |
+
|
961 |
+
for i in range(target_rows):
|
962 |
+
start_row = i * rows_per_group
|
963 |
+
end_row = (i + 1) * rows_per_group
|
964 |
+
group = matrix[start_row:end_row, :]
|
965 |
+
|
966 |
+
pca = PCA(n_components=num_pca_components)
|
967 |
+
pca.fit(group)
|
968 |
+
|
969 |
+
principal_component = np.mean(pca.components_, axis=0)
|
970 |
+
contributions = np.dot(group, principal_component)
|
971 |
+
selected_row_index = np.argmax(contributions)
|
972 |
+
|
973 |
+
compressed_matrix[i, :] = group[selected_row_index, :]
|
974 |
+
|
975 |
+
if return_square_matrix_points:
|
976 |
+
filtered_matrix = compressed_matrix[~np.all(compressed_matrix == 0, axis=1)]
|
977 |
+
|
978 |
+
row_indexes, col_indexes = np.where(filtered_matrix != 0)
|
979 |
+
points = np.column_stack((row_indexes, filtered_matrix[row_indexes, col_indexes])).tolist()
|
980 |
+
|
981 |
+
return points
|
982 |
+
|
983 |
+
else:
|
984 |
+
return compressed_matrix.tolist()
|
985 |
+
|
986 |
+
################################################################################
|
987 |
+
|
988 |
+
def image_matrix_to_images(image_matrix,
|
989 |
+
step,
|
990 |
+
overlap,
|
991 |
+
num_img_channels=3,
|
992 |
+
output_folder='./Dataset/',
|
993 |
+
output_img_prefix='image',
|
994 |
+
output_img_ext='.png',
|
995 |
+
save_to_array=False,
|
996 |
+
verbose=True
|
997 |
+
):
|
998 |
+
|
999 |
+
if num_img_channels > 1:
|
1000 |
+
n_mat_channels = 3
|
1001 |
+
|
1002 |
+
else:
|
1003 |
+
n_mat_channels = 1
|
1004 |
+
|
1005 |
+
if not save_to_array:
|
1006 |
+
|
1007 |
+
if verbose:
|
1008 |
+
print('=' * 70)
|
1009 |
+
print('Checking output folder dir...')
|
1010 |
+
|
1011 |
+
os.makedirs(os.path.dirname(output_folder), exist_ok=True)
|
1012 |
+
|
1013 |
+
if verbose:
|
1014 |
+
print('Done!')
|
1015 |
+
|
1016 |
+
if verbose:
|
1017 |
+
print('=' * 70)
|
1018 |
+
print('Writing images...')
|
1019 |
+
|
1020 |
+
matrix = np.array(image_matrix)
|
1021 |
+
|
1022 |
+
image_array = []
|
1023 |
+
|
1024 |
+
for i in range(0, max(1, matrix.shape[0]), overlap):
|
1025 |
+
|
1026 |
+
submatrix = matrix[i:i+step, :]
|
1027 |
+
|
1028 |
+
if submatrix.shape[0] < 128:
|
1029 |
+
zeros_array = np.zeros((128-submatrix.shape[0], 128))
|
1030 |
+
submatrix = np.vstack((submatrix, zeros_array))
|
1031 |
+
|
1032 |
+
if n_mat_channels == 3:
|
1033 |
+
|
1034 |
+
r = (submatrix // (256*256)) % 256
|
1035 |
+
g = (submatrix // 256) % 256
|
1036 |
+
b = submatrix % 256
|
1037 |
+
|
1038 |
+
rgb_image = np.stack((r, g, b), axis=-1).astype(np.uint8)
|
1039 |
+
img = Image.fromarray(rgb_image, 'RGB')
|
1040 |
+
|
1041 |
+
else:
|
1042 |
+
grayscale_image = submatrix.astype(np.uint8)
|
1043 |
+
img = Image.fromarray(grayscale_image, 'L')
|
1044 |
+
|
1045 |
+
if save_to_array:
|
1046 |
+
image_array.append(np.array(img))
|
1047 |
+
|
1048 |
+
else:
|
1049 |
+
img.save(output_folder + output_img_prefix + '_' + str(matrix.shape[1]) + '_' + str(i).zfill(7) + output_img_ext)
|
1050 |
+
|
1051 |
+
if verbose:
|
1052 |
+
print('Done!')
|
1053 |
+
print('=' * 70)
|
1054 |
+
print('Saved', (matrix.shape[0] // min(step, overlap))+1, 'imges!')
|
1055 |
+
print('=' * 70)
|
1056 |
+
|
1057 |
+
if save_to_array:
|
1058 |
+
return np.array(image_array).tolist()
|
1059 |
+
|
1060 |
+
################################################################################
|
1061 |
+
|
1062 |
+
def images_to_image_matrix(list_of_images,
|
1063 |
+
num_img_channels=3
|
1064 |
+
):
|
1065 |
+
|
1066 |
+
if num_img_channels > 1:
|
1067 |
+
n_mat_channels = 3
|
1068 |
+
|
1069 |
+
else:
|
1070 |
+
n_mat_channels = 1
|
1071 |
+
|
1072 |
+
image_array = np.array(list_of_images)
|
1073 |
+
|
1074 |
+
original_matrix = []
|
1075 |
+
|
1076 |
+
for img in image_array:
|
1077 |
+
|
1078 |
+
if num_img_channels == 3:
|
1079 |
+
|
1080 |
+
rgb_array = np.array(img)
|
1081 |
+
|
1082 |
+
matrix = (rgb_array[..., 0].astype(np.int64) * 256*256 +
|
1083 |
+
rgb_array[..., 1].astype(np.int64) * 256 +
|
1084 |
+
rgb_array[..., 2].astype(np.int64))
|
1085 |
+
|
1086 |
+
else:
|
1087 |
+
matrix = np.array(img)
|
1088 |
+
|
1089 |
+
original_matrix.extend(matrix)
|
1090 |
+
|
1091 |
+
return original_matrix
|
1092 |
+
|
1093 |
+
################################################################################
|
1094 |
+
|
1095 |
+
def square_matrix_to_RGB_matrix(square_matrix):
|
1096 |
+
|
1097 |
+
smatrix = np.array(square_matrix)
|
1098 |
+
sq_matrix = smatrix[:smatrix.shape[1]]
|
1099 |
+
|
1100 |
+
r = (sq_matrix // (256 ** 2)) % 256
|
1101 |
+
g = (sq_matrix // 256) % 256
|
1102 |
+
b = sq_matrix % 256
|
1103 |
+
|
1104 |
+
rgb_array = np.stack((r, g, b), axis=-1)
|
1105 |
+
|
1106 |
+
return rgb_array.tolist()
|
1107 |
+
|
1108 |
+
################################################################################
|
1109 |
+
|
1110 |
+
def upsample_square_matrix(square_matrix, upsampling_factor=4):
|
1111 |
+
|
1112 |
+
smatrix = np.array(square_matrix)
|
1113 |
+
sq_matrix = smatrix[:smatrix.shape[1]]
|
1114 |
+
|
1115 |
+
scaling_array = np.ones((upsampling_factor, upsampling_factor))
|
1116 |
+
scaled_array = np.kron(sq_matrix, scaling_array)
|
1117 |
+
scaled_array = scaled_array.astype('int')
|
1118 |
+
|
1119 |
+
return scaled_array.tolist()
|
1120 |
+
|
1121 |
+
################################################################################
|
1122 |
+
|
1123 |
+
def downsample_square_matrix(square_matrix, downsampling_factor=4):
|
1124 |
+
|
1125 |
+
smatrix = np.array(square_matrix)
|
1126 |
+
sq_matrix = smatrix[:smatrix.shape[1]]
|
1127 |
+
|
1128 |
+
dmatrix = sq_matrix[::downsampling_factor, ::downsampling_factor]
|
1129 |
+
dmatrix = dmatrix.astype('int')
|
1130 |
+
|
1131 |
+
return dmatrix.tolist()
|
1132 |
+
|
1133 |
+
################################################################################
|
1134 |
+
# [WIP] Future dev functions
|
1135 |
+
################################################################################
|
1136 |
+
|
1137 |
+
'''
|
1138 |
+
import umap
|
1139 |
+
|
1140 |
+
def reduce_dimensionality_umap(list_of_values,
|
1141 |
+
n_comp=2,
|
1142 |
+
n_neighbors=15,
|
1143 |
+
):
|
1144 |
+
|
1145 |
+
"""
|
1146 |
+
Reduces the dimensionality of the values using UMAP.
|
1147 |
+
"""
|
1148 |
+
|
1149 |
+
vals = np.array(list_of_values)
|
1150 |
+
|
1151 |
+
umap_reducer = umap.UMAP(n_components=n_comp,
|
1152 |
+
n_neighbors=n_neighbors,
|
1153 |
+
n_epochs=5000,
|
1154 |
+
verbose=True
|
1155 |
+
)
|
1156 |
+
|
1157 |
+
reduced_vals = umap_reducer.fit_transform(vals)
|
1158 |
+
|
1159 |
+
return reduced_vals.tolist()
|
1160 |
+
'''
|
1161 |
+
|
1162 |
+
################################################################################
|
1163 |
+
|
1164 |
+
'''
|
1165 |
+
import alphashape
|
1166 |
+
from shapely.geometry import Point
|
1167 |
+
from matplotlib.tri import Triangulation, LinearTriInterpolator
|
1168 |
+
from scipy.stats import zscore
|
1169 |
+
|
1170 |
+
#===============================================================================
|
1171 |
+
|
1172 |
+
coordinates = points
|
1173 |
+
|
1174 |
+
dist_matrix = minkowski_distance_matrix(coordinates, p=3) # You can change the value of p as needed
|
1175 |
+
|
1176 |
+
# Centering matrix
|
1177 |
+
n = dist_matrix.shape[0]
|
1178 |
+
H = np.eye(n) - np.ones((n, n)) / n
|
1179 |
+
|
1180 |
+
# Apply double centering
|
1181 |
+
B = -0.5 * H @ dist_matrix**2 @ H
|
1182 |
+
|
1183 |
+
# Eigen decomposition
|
1184 |
+
eigvals, eigvecs = np.linalg.eigh(B)
|
1185 |
+
|
1186 |
+
# Sort eigenvalues and eigenvectors
|
1187 |
+
idx = np.argsort(eigvals)[::-1]
|
1188 |
+
eigvals = eigvals[idx]
|
1189 |
+
eigvecs = eigvecs[:, idx]
|
1190 |
+
|
1191 |
+
# Select the top 2 eigenvectors
|
1192 |
+
X_transformed = eigvecs[:, :2] * np.sqrt(eigvals[:2])
|
1193 |
+
|
1194 |
+
#===============================================================================
|
1195 |
+
|
1196 |
+
src_points = X_transformed
|
1197 |
+
src_values = np.array([[p[1]] for p in points]) #np.random.rand(X_transformed.shape[0])
|
1198 |
+
|
1199 |
+
#===============================================================================
|
1200 |
+
|
1201 |
+
# Normalize the points to the range [0, 1]
|
1202 |
+
scaler = MinMaxScaler()
|
1203 |
+
points_normalized = scaler.fit_transform(src_points)
|
1204 |
+
|
1205 |
+
values_normalized = custom_normalize(src_values)
|
1206 |
+
|
1207 |
+
# Remove outliers based on z-score
|
1208 |
+
z_scores = np.abs(zscore(points_normalized, axis=0))
|
1209 |
+
filtered_points = points_normalized[(z_scores < 3).all(axis=1)]
|
1210 |
+
filtered_values = values_normalized[(z_scores < 3).all(axis=1)]
|
1211 |
+
|
1212 |
+
# Compute the concave hull (alpha shape)
|
1213 |
+
alpha = 8 # Adjust alpha as needed
|
1214 |
+
hull = alphashape.alphashape(filtered_points, alpha)
|
1215 |
+
|
1216 |
+
# Create a triangulation
|
1217 |
+
tri = Triangulation(filtered_points[:, 0], filtered_points[:, 1])
|
1218 |
+
|
1219 |
+
# Interpolate the values on the triangulation
|
1220 |
+
interpolator = LinearTriInterpolator(tri, filtered_values[:, 0])
|
1221 |
+
xi, yi = np.meshgrid(np.linspace(0, 1, 100), np.linspace(0, 1, 100))
|
1222 |
+
zi = interpolator(xi, yi)
|
1223 |
+
|
1224 |
+
# Mask out points outside the concave hull
|
1225 |
+
mask = np.array([hull.contains(Point(x, y)) for x, y in zip(xi.flatten(), yi.flatten())])
|
1226 |
+
zi = np.ma.array(zi, mask=~mask.reshape(zi.shape))
|
1227 |
+
|
1228 |
+
# Plot the filled contour based on the interpolated values
|
1229 |
+
plt.contourf(xi, yi, zi, levels=50, cmap='viridis')
|
1230 |
+
|
1231 |
+
# Plot the original points
|
1232 |
+
#plt.scatter(filtered_points[:, 0], filtered_points[:, 1], c=filtered_values, edgecolors='k')
|
1233 |
+
|
1234 |
+
plt.title('Filled Contour Plot with Original Values')
|
1235 |
+
plt.xlabel('X-axis')
|
1236 |
+
plt.ylabel('Y-axis')
|
1237 |
+
plt.colorbar(label='Value')
|
1238 |
+
plt.show()
|
1239 |
+
'''
|
1240 |
+
|
1241 |
+
################################################################################
|
1242 |
+
#
|
1243 |
+
# This is the end of TPLOTS Python modules
|
1244 |
+
#
|
1245 |
+
################################################################################
|