Spaces:
Running
on
Zero
Running
on
Zero
Upload TMIDIX.py
Browse files
TMIDIX.py
CHANGED
@@ -5,9 +5,8 @@ r'''############################################################################
|
|
5 |
#
|
6 |
#
|
7 |
# Tegridy MIDI X Module (TMIDI X / tee-midi eks)
|
8 |
-
# Version 1.0
|
9 |
#
|
10 |
-
# NOTE: TMIDI X Module starts after the partial MIDI.py module @ line
|
11 |
#
|
12 |
# Based upon MIDI.py module v.6.7. by Peter Billam / pjb.com.au
|
13 |
#
|
@@ -26,7 +25,7 @@ r'''############################################################################
|
|
26 |
# you may not use this file except in compliance with the License.
|
27 |
# You may obtain a copy of the License at
|
28 |
#
|
29 |
-
#
|
30 |
#
|
31 |
# Unless required by applicable law or agreed to in writing, software
|
32 |
# distributed under the License is distributed on an "AS IS" BASIS,
|
@@ -47,9 +46,23 @@ r'''############################################################################
|
|
47 |
# Copyright 2020 Peter Billam
|
48 |
#
|
49 |
###################################################################################
|
50 |
-
###################################################################################
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
import sys, struct, copy
|
|
|
53 |
Version = '6.7'
|
54 |
VersionDate = '20201120'
|
55 |
|
@@ -1439,7 +1452,6 @@ def _encode(events_lol, unknown_callback=None, never_add_eot=False,
|
|
1439 |
###################################################################################
|
1440 |
#
|
1441 |
# Tegridy MIDI X Module (TMIDI X / tee-midi eks)
|
1442 |
-
# Version 1.0
|
1443 |
#
|
1444 |
# Based upon and includes the amazing MIDI.py module v.6.7. by Peter Billam
|
1445 |
# pjb.com.au
|
@@ -1476,6 +1488,7 @@ from itertools import groupby
|
|
1476 |
|
1477 |
from collections import Counter
|
1478 |
from collections import defaultdict
|
|
|
1479 |
|
1480 |
from operator import itemgetter
|
1481 |
|
@@ -1492,6 +1505,14 @@ import psutil
|
|
1492 |
|
1493 |
import json
|
1494 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1495 |
###################################################################################
|
1496 |
#
|
1497 |
# Original TMIDI Tegridy helper functions
|
@@ -3844,7 +3865,10 @@ def chordify_score(score,
|
|
3844 |
else:
|
3845 |
return None
|
3846 |
|
3847 |
-
def fix_monophonic_score_durations(monophonic_score
|
|
|
|
|
|
|
3848 |
|
3849 |
fixed_score = []
|
3850 |
|
@@ -3856,15 +3880,17 @@ def fix_monophonic_score_durations(monophonic_score):
|
|
3856 |
nmt = monophonic_score[i+1][1]
|
3857 |
|
3858 |
if note[1]+note[2] >= nmt:
|
3859 |
-
note_dur = nmt-note[1]-
|
3860 |
else:
|
3861 |
note_dur = note[2]
|
3862 |
|
3863 |
new_note = [note[0], note[1], note_dur] + note[3:]
|
3864 |
-
|
3865 |
-
|
3866 |
-
|
3867 |
-
|
|
|
|
|
3868 |
|
3869 |
elif type(monophonic_score[0][0]) == int:
|
3870 |
|
@@ -3874,15 +3900,17 @@ def fix_monophonic_score_durations(monophonic_score):
|
|
3874 |
nmt = monophonic_score[i+1][0]
|
3875 |
|
3876 |
if note[0]+note[1] >= nmt:
|
3877 |
-
note_dur = nmt-note[0]-
|
3878 |
else:
|
3879 |
note_dur = note[1]
|
3880 |
-
|
3881 |
new_note = [note[0], note_dur] + note[2:]
|
3882 |
-
|
3883 |
-
|
3884 |
-
|
3885 |
-
|
|
|
|
|
3886 |
|
3887 |
return fixed_score
|
3888 |
|
@@ -4144,15 +4172,16 @@ def tones_chord_to_pitches(tones_chord, base_pitch=60):
|
|
4144 |
###################################################################################
|
4145 |
|
4146 |
def advanced_score_processor(raw_score,
|
4147 |
-
|
4148 |
-
|
4149 |
-
|
4150 |
-
|
4151 |
-
|
4152 |
-
|
4153 |
-
|
4154 |
-
|
4155 |
-
|
|
|
4156 |
):
|
4157 |
|
4158 |
'''TMIDIX Advanced Score Processor'''
|
@@ -4192,6 +4221,9 @@ def advanced_score_processor(raw_score,
|
|
4192 |
e[2] = e[2] % 16
|
4193 |
e[3] = e[3] % 128
|
4194 |
|
|
|
|
|
|
|
4195 |
basic_single_track_score.sort(key=lambda x: x[4] if x[0] == 'note' else 128, reverse=True)
|
4196 |
basic_single_track_score.sort(key=lambda x: x[1])
|
4197 |
|
@@ -4706,7 +4738,8 @@ def augment_enhanced_score_notes(enhanced_score_notes,
|
|
4706 |
ceil_timings=False,
|
4707 |
round_timings=False,
|
4708 |
legacy_timings=True,
|
4709 |
-
sort_drums_last=False
|
|
|
4710 |
):
|
4711 |
|
4712 |
esn = copy.deepcopy(enhanced_score_notes)
|
@@ -4749,6 +4782,16 @@ def augment_enhanced_score_notes(enhanced_score_notes,
|
|
4749 |
e[4] = max(1, min(127, e[4] + pitch_shift))
|
4750 |
|
4751 |
pe = enhanced_score_notes[i]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4752 |
|
4753 |
if full_sorting:
|
4754 |
|
@@ -6689,12 +6732,23 @@ def find_next_bar(escore_notes, bar_time, start_note_idx, cur_bar):
|
|
6689 |
def align_escore_notes_to_bars(escore_notes,
|
6690 |
bar_time=4000,
|
6691 |
trim_durations=False,
|
6692 |
-
split_durations=False
|
|
|
6693 |
):
|
6694 |
|
6695 |
#=============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6696 |
|
6697 |
-
aligned_escore_notes = copy.deepcopy(
|
6698 |
|
6699 |
abs_time = 0
|
6700 |
nidx = 0
|
@@ -6706,13 +6760,13 @@ def align_escore_notes_to_bars(escore_notes,
|
|
6706 |
|
6707 |
while next_bar:
|
6708 |
|
6709 |
-
next_bar = find_next_bar(
|
6710 |
|
6711 |
if next_bar:
|
6712 |
-
|
6713 |
-
|
6714 |
else:
|
6715 |
-
gescore_notes =
|
6716 |
|
6717 |
original_timings = [delta] + [(b[1]-a[1]) for a, b in zip(gescore_notes[:-1], gescore_notes[1:])]
|
6718 |
adj_timings = adjust_numbers_to_sum(original_timings, bar_time)
|
@@ -6727,7 +6781,8 @@ def align_escore_notes_to_bars(escore_notes,
|
|
6727 |
nidx += 1
|
6728 |
|
6729 |
if next_bar:
|
6730 |
-
delta =
|
|
|
6731 |
bcount += 1
|
6732 |
|
6733 |
#=============================================================================
|
@@ -11138,13 +11193,17 @@ def escore_notes_core(escore_notes, core_len=128):
|
|
11138 |
|
11139 |
###################################################################################
|
11140 |
|
11141 |
-
def multiprocessing_wrapper(function, data_list):
|
11142 |
|
11143 |
with multiprocessing.Pool() as pool:
|
11144 |
|
11145 |
results = []
|
11146 |
|
11147 |
-
for result in tqdm.tqdm(pool.imap_unordered(function, data_list),
|
|
|
|
|
|
|
|
|
11148 |
results.append(result)
|
11149 |
|
11150 |
return results
|
@@ -11293,28 +11352,83 @@ def system_memory_utilization(return_dict=False):
|
|
11293 |
|
11294 |
###################################################################################
|
11295 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11296 |
def create_files_list(datasets_paths=['./'],
|
11297 |
files_exts=['.mid', '.midi', '.kar', '.MID', '.MIDI', '.KAR'],
|
|
|
|
|
|
|
11298 |
randomize_files_list=True,
|
|
|
|
|
|
|
11299 |
verbose=True
|
11300 |
):
|
|
|
11301 |
if verbose:
|
11302 |
print('=' * 70)
|
11303 |
print('Searching for files...')
|
11304 |
print('This may take a while on a large dataset in particular...')
|
11305 |
print('=' * 70)
|
11306 |
|
11307 |
-
filez_set = defaultdict(None)
|
11308 |
-
|
11309 |
files_exts = tuple(files_exts)
|
11310 |
|
11311 |
-
|
11312 |
-
|
11313 |
-
|
11314 |
-
|
11315 |
-
|
11316 |
-
|
11317 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11318 |
|
11319 |
if verbose:
|
11320 |
print('Done!')
|
@@ -11334,6 +11448,7 @@ def create_files_list(datasets_paths=['./'],
|
|
11334 |
|
11335 |
if verbose:
|
11336 |
print('Found', len(filez), 'files.')
|
|
|
11337 |
print('=' * 70)
|
11338 |
|
11339 |
else:
|
@@ -11341,8 +11456,20 @@ def create_files_list(datasets_paths=['./'],
|
|
11341 |
print('Could not find any files...')
|
11342 |
print('Please check dataset dirs and files extensions...')
|
11343 |
print('=' * 70)
|
|
|
|
|
|
|
|
|
11344 |
|
11345 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11346 |
|
11347 |
###################################################################################
|
11348 |
|
@@ -12163,8 +12290,16 @@ def escore_notes_pitches_chords_signature(escore_notes,
|
|
12163 |
sort_by_counts=False,
|
12164 |
use_full_chords=False
|
12165 |
):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12166 |
|
12167 |
-
escore_notes = [e for e in escore_notes if e[6] <= max_patch
|
12168 |
|
12169 |
if escore_notes:
|
12170 |
|
@@ -12173,7 +12308,7 @@ def escore_notes_pitches_chords_signature(escore_notes,
|
|
12173 |
sig = []
|
12174 |
dsig = []
|
12175 |
|
12176 |
-
drums_offset =
|
12177 |
|
12178 |
bad_chords_counter = 0
|
12179 |
|
@@ -12190,10 +12325,10 @@ def escore_notes_pitches_chords_signature(escore_notes,
|
|
12190 |
tones_chord = sorted(set([p % 12 for p in pitches]))
|
12191 |
|
12192 |
try:
|
12193 |
-
sig_token =
|
12194 |
except:
|
12195 |
checked_tones_chord = check_and_fix_tones_chord(tones_chord, use_full_chords=use_full_chords)
|
12196 |
-
sig_token =
|
12197 |
bad_chords_counter += 1
|
12198 |
|
12199 |
elif len(pitches) == 1:
|
@@ -12226,6 +12361,792 @@ def escore_notes_pitches_chords_signature(escore_notes,
|
|
12226 |
else:
|
12227 |
return []
|
12228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12229 |
###################################################################################
|
12230 |
# This is the end of the TMIDI X Python module
|
12231 |
###################################################################################
|
|
|
5 |
#
|
6 |
#
|
7 |
# Tegridy MIDI X Module (TMIDI X / tee-midi eks)
|
|
|
8 |
#
|
9 |
+
# NOTE: TMIDI X Module starts after the partial MIDI.py module @ line 1450
|
10 |
#
|
11 |
# Based upon MIDI.py module v.6.7. by Peter Billam / pjb.com.au
|
12 |
#
|
|
|
25 |
# you may not use this file except in compliance with the License.
|
26 |
# You may obtain a copy of the License at
|
27 |
#
|
28 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
29 |
#
|
30 |
# Unless required by applicable law or agreed to in writing, software
|
31 |
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
46 |
# Copyright 2020 Peter Billam
|
47 |
#
|
48 |
###################################################################################
|
49 |
+
###################################################################################
|
50 |
+
'''
|
51 |
+
|
52 |
+
###################################################################################
|
53 |
+
|
54 |
+
__version__ = "25.5.6"
|
55 |
+
|
56 |
+
print('=' * 70)
|
57 |
+
print('TMIDIX Python module')
|
58 |
+
print('Version:', __version__)
|
59 |
+
print('=' * 70)
|
60 |
+
print('Loading module...')
|
61 |
+
|
62 |
+
###################################################################################
|
63 |
|
64 |
import sys, struct, copy
|
65 |
+
|
66 |
Version = '6.7'
|
67 |
VersionDate = '20201120'
|
68 |
|
|
|
1452 |
###################################################################################
|
1453 |
#
|
1454 |
# Tegridy MIDI X Module (TMIDI X / tee-midi eks)
|
|
|
1455 |
#
|
1456 |
# Based upon and includes the amazing MIDI.py module v.6.7. by Peter Billam
|
1457 |
# pjb.com.au
|
|
|
1488 |
|
1489 |
from collections import Counter
|
1490 |
from collections import defaultdict
|
1491 |
+
from collections import OrderedDict
|
1492 |
|
1493 |
from operator import itemgetter
|
1494 |
|
|
|
1505 |
|
1506 |
import json
|
1507 |
|
1508 |
+
from pathlib import Path
|
1509 |
+
|
1510 |
+
import shutil
|
1511 |
+
|
1512 |
+
import hashlib
|
1513 |
+
|
1514 |
+
from array import array
|
1515 |
+
|
1516 |
###################################################################################
|
1517 |
#
|
1518 |
# Original TMIDI Tegridy helper functions
|
|
|
3865 |
else:
|
3866 |
return None
|
3867 |
|
3868 |
+
def fix_monophonic_score_durations(monophonic_score,
|
3869 |
+
min_notes_gap=1,
|
3870 |
+
min_notes_dur=1
|
3871 |
+
):
|
3872 |
|
3873 |
fixed_score = []
|
3874 |
|
|
|
3880 |
nmt = monophonic_score[i+1][1]
|
3881 |
|
3882 |
if note[1]+note[2] >= nmt:
|
3883 |
+
note_dur = max(1, nmt-note[1]-min_notes_gap)
|
3884 |
else:
|
3885 |
note_dur = note[2]
|
3886 |
|
3887 |
new_note = [note[0], note[1], note_dur] + note[3:]
|
3888 |
+
|
3889 |
+
if new_note[2] >= min_notes_dur:
|
3890 |
+
fixed_score.append(new_note)
|
3891 |
+
|
3892 |
+
if monophonic_score[-1][2] >= min_notes_dur:
|
3893 |
+
fixed_score.append(monophonic_score[-1])
|
3894 |
|
3895 |
elif type(monophonic_score[0][0]) == int:
|
3896 |
|
|
|
3900 |
nmt = monophonic_score[i+1][0]
|
3901 |
|
3902 |
if note[0]+note[1] >= nmt:
|
3903 |
+
note_dur = max(1, nmt-note[0]-min_notes_gap)
|
3904 |
else:
|
3905 |
note_dur = note[1]
|
3906 |
+
|
3907 |
new_note = [note[0], note_dur] + note[2:]
|
3908 |
+
|
3909 |
+
if new_note[1] >= min_notes_dur:
|
3910 |
+
fixed_score.append(new_note)
|
3911 |
+
|
3912 |
+
if monophonic_score[-1][1] >= min_notes_dur:
|
3913 |
+
fixed_score.append(monophonic_score[-1])
|
3914 |
|
3915 |
return fixed_score
|
3916 |
|
|
|
4172 |
###################################################################################
|
4173 |
|
4174 |
def advanced_score_processor(raw_score,
|
4175 |
+
patches_to_analyze=list(range(129)),
|
4176 |
+
return_score_analysis=False,
|
4177 |
+
return_enhanced_score=False,
|
4178 |
+
return_enhanced_score_notes=False,
|
4179 |
+
return_enhanced_monophonic_melody=False,
|
4180 |
+
return_chordified_enhanced_score=False,
|
4181 |
+
return_chordified_enhanced_score_with_lyrics=False,
|
4182 |
+
return_score_tones_chords=False,
|
4183 |
+
return_text_and_lyric_events=False,
|
4184 |
+
apply_sustain=False
|
4185 |
):
|
4186 |
|
4187 |
'''TMIDIX Advanced Score Processor'''
|
|
|
4221 |
e[2] = e[2] % 16
|
4222 |
e[3] = e[3] % 128
|
4223 |
|
4224 |
+
if apply_sustain:
|
4225 |
+
apply_sustain_to_ms_score([1000, basic_single_track_score])
|
4226 |
+
|
4227 |
basic_single_track_score.sort(key=lambda x: x[4] if x[0] == 'note' else 128, reverse=True)
|
4228 |
basic_single_track_score.sort(key=lambda x: x[1])
|
4229 |
|
|
|
4738 |
ceil_timings=False,
|
4739 |
round_timings=False,
|
4740 |
legacy_timings=True,
|
4741 |
+
sort_drums_last=False,
|
4742 |
+
even_timings=False
|
4743 |
):
|
4744 |
|
4745 |
esn = copy.deepcopy(enhanced_score_notes)
|
|
|
4782 |
e[4] = max(1, min(127, e[4] + pitch_shift))
|
4783 |
|
4784 |
pe = enhanced_score_notes[i]
|
4785 |
+
|
4786 |
+
|
4787 |
+
if even_timings:
|
4788 |
+
|
4789 |
+
for e in esn:
|
4790 |
+
if e[1] % 2 != 0:
|
4791 |
+
e[1] += 1
|
4792 |
+
|
4793 |
+
if e[2] % 2 != 0:
|
4794 |
+
e[2] += 1
|
4795 |
|
4796 |
if full_sorting:
|
4797 |
|
|
|
6732 |
def align_escore_notes_to_bars(escore_notes,
|
6733 |
bar_time=4000,
|
6734 |
trim_durations=False,
|
6735 |
+
split_durations=False,
|
6736 |
+
even_timings=False
|
6737 |
):
|
6738 |
|
6739 |
#=============================================================================
|
6740 |
+
|
6741 |
+
escore = copy.deepcopy(escore_notes)
|
6742 |
+
|
6743 |
+
if even_timings:
|
6744 |
+
for e in escore:
|
6745 |
+
if e[1] % 2 != 0:
|
6746 |
+
e[1] += 1
|
6747 |
+
|
6748 |
+
if e[2] % 2 != 0:
|
6749 |
+
e[2] += 1
|
6750 |
|
6751 |
+
aligned_escore_notes = copy.deepcopy(escore)
|
6752 |
|
6753 |
abs_time = 0
|
6754 |
nidx = 0
|
|
|
6760 |
|
6761 |
while next_bar:
|
6762 |
|
6763 |
+
next_bar = find_next_bar(escore, bar_time, nidx, bcount)
|
6764 |
|
6765 |
if next_bar:
|
6766 |
+
gescore_notes = escore[nidx:next_bar[1]]
|
6767 |
+
|
6768 |
else:
|
6769 |
+
gescore_notes = escore[nidx:]
|
6770 |
|
6771 |
original_timings = [delta] + [(b[1]-a[1]) for a, b in zip(gescore_notes[:-1], gescore_notes[1:])]
|
6772 |
adj_timings = adjust_numbers_to_sum(original_timings, bar_time)
|
|
|
6781 |
nidx += 1
|
6782 |
|
6783 |
if next_bar:
|
6784 |
+
delta = escore[next_bar[1]][1]-escore[next_bar[1]-1][1]
|
6785 |
+
|
6786 |
bcount += 1
|
6787 |
|
6788 |
#=============================================================================
|
|
|
11193 |
|
11194 |
###################################################################################
|
11195 |
|
11196 |
+
def multiprocessing_wrapper(function, data_list, verbose=True):
|
11197 |
|
11198 |
with multiprocessing.Pool() as pool:
|
11199 |
|
11200 |
results = []
|
11201 |
|
11202 |
+
for result in tqdm.tqdm(pool.imap_unordered(function, data_list),
|
11203 |
+
total=len(data_list),
|
11204 |
+
disable=not verbose
|
11205 |
+
):
|
11206 |
+
|
11207 |
results.append(result)
|
11208 |
|
11209 |
return results
|
|
|
11352 |
|
11353 |
###################################################################################
|
11354 |
|
11355 |
+
def system_cpus_utilization(return_dict=False):
|
11356 |
+
|
11357 |
+
if return_dict:
|
11358 |
+
return {'num_cpus': psutil.cpu_count(),
|
11359 |
+
'cpus_util': psutil.cpu_percent()
|
11360 |
+
}
|
11361 |
+
|
11362 |
+
else:
|
11363 |
+
print('Number of CPUs:', psutil.cpu_count())
|
11364 |
+
print('CPUs utilization:', psutil.cpu_percent())
|
11365 |
+
|
11366 |
+
###################################################################################
|
11367 |
+
|
11368 |
def create_files_list(datasets_paths=['./'],
|
11369 |
files_exts=['.mid', '.midi', '.kar', '.MID', '.MIDI', '.KAR'],
|
11370 |
+
max_num_files_per_dir=-1,
|
11371 |
+
randomize_dir_files=False,
|
11372 |
+
max_total_files=-1,
|
11373 |
randomize_files_list=True,
|
11374 |
+
check_for_dupes=False,
|
11375 |
+
use_md5_hashes=False,
|
11376 |
+
return_dupes=False,
|
11377 |
verbose=True
|
11378 |
):
|
11379 |
+
|
11380 |
if verbose:
|
11381 |
print('=' * 70)
|
11382 |
print('Searching for files...')
|
11383 |
print('This may take a while on a large dataset in particular...')
|
11384 |
print('=' * 70)
|
11385 |
|
|
|
|
|
11386 |
files_exts = tuple(files_exts)
|
11387 |
|
11388 |
+
filez_set = defaultdict(None)
|
11389 |
+
dupes_list = []
|
11390 |
+
|
11391 |
+
for dataset_addr in datasets_paths:
|
11392 |
+
|
11393 |
+
print('=' * 70)
|
11394 |
+
print('Processing', dataset_addr)
|
11395 |
+
print('=' * 70)
|
11396 |
+
|
11397 |
+
for dirpath, dirnames, filenames in tqdm.tqdm(os.walk(dataset_addr), disable=not verbose):
|
11398 |
+
|
11399 |
+
if randomize_dir_files:
|
11400 |
+
random.shuffle(filenames)
|
11401 |
+
|
11402 |
+
if max_num_files_per_dir > 0:
|
11403 |
+
max_num_files = max_num_files_per_dir
|
11404 |
+
|
11405 |
+
else:
|
11406 |
+
max_num_files = len(filenames)
|
11407 |
+
|
11408 |
+
for file in filenames[:max_num_files]:
|
11409 |
+
if file.endswith(files_exts):
|
11410 |
+
if check_for_dupes:
|
11411 |
+
|
11412 |
+
if use_md5_hashes:
|
11413 |
+
md5_hash = hashlib.md5(open(os.path.join(dirpath, file), 'rb').read()).hexdigest()
|
11414 |
+
|
11415 |
+
if md5_hash not in filez_set:
|
11416 |
+
filez_set[md5_hash] = os.path.join(dirpath, file)
|
11417 |
+
|
11418 |
+
else:
|
11419 |
+
dupes_list.append(os.path.join(dirpath, file))
|
11420 |
+
|
11421 |
+
else:
|
11422 |
+
if file not in filez_set:
|
11423 |
+
filez_set[file] = os.path.join(dirpath, file)
|
11424 |
+
|
11425 |
+
else:
|
11426 |
+
dupes_list.append(os.path.join(dirpath, file))
|
11427 |
+
else:
|
11428 |
+
fpath = os.path.join(dirpath, file)
|
11429 |
+
filez_set[fpath] = fpath
|
11430 |
+
|
11431 |
+
filez = list(filez_set.values())
|
11432 |
|
11433 |
if verbose:
|
11434 |
print('Done!')
|
|
|
11448 |
|
11449 |
if verbose:
|
11450 |
print('Found', len(filez), 'files.')
|
11451 |
+
print('Skipped', len(dupes_list), 'duplicate files.')
|
11452 |
print('=' * 70)
|
11453 |
|
11454 |
else:
|
|
|
11456 |
print('Could not find any files...')
|
11457 |
print('Please check dataset dirs and files extensions...')
|
11458 |
print('=' * 70)
|
11459 |
+
|
11460 |
+
if max_total_files > 0:
|
11461 |
+
if return_dupes:
|
11462 |
+
return filez[:max_total_files], dupes_list
|
11463 |
|
11464 |
+
else:
|
11465 |
+
return filez[:max_total_files]
|
11466 |
+
|
11467 |
+
else:
|
11468 |
+
if return_dupes:
|
11469 |
+
return filez, dupes_list
|
11470 |
+
|
11471 |
+
else:
|
11472 |
+
return filez
|
11473 |
|
11474 |
###################################################################################
|
11475 |
|
|
|
12290 |
sort_by_counts=False,
|
12291 |
use_full_chords=False
|
12292 |
):
|
12293 |
+
|
12294 |
+
if use_full_chords:
|
12295 |
+
CHORDS = ALL_CHORDS_FULL
|
12296 |
+
|
12297 |
+
else:
|
12298 |
+
CHORDS = ALL_CHORDS_SORTED
|
12299 |
+
|
12300 |
+
max_patch = max(0, min(128, max_patch))
|
12301 |
|
12302 |
+
escore_notes = [e for e in escore_notes if e[6] <= max_patch]
|
12303 |
|
12304 |
if escore_notes:
|
12305 |
|
|
|
12308 |
sig = []
|
12309 |
dsig = []
|
12310 |
|
12311 |
+
drums_offset = len(CHORDS) + 128
|
12312 |
|
12313 |
bad_chords_counter = 0
|
12314 |
|
|
|
12325 |
tones_chord = sorted(set([p % 12 for p in pitches]))
|
12326 |
|
12327 |
try:
|
12328 |
+
sig_token = CHORDS.index(tones_chord) + 128
|
12329 |
except:
|
12330 |
checked_tones_chord = check_and_fix_tones_chord(tones_chord, use_full_chords=use_full_chords)
|
12331 |
+
sig_token = CHORDS.index(checked_tones_chord) + 128
|
12332 |
bad_chords_counter += 1
|
12333 |
|
12334 |
elif len(pitches) == 1:
|
|
|
12361 |
else:
|
12362 |
return []
|
12363 |
|
12364 |
+
###################################################################################
|
12365 |
+
|
12366 |
+
def compute_sustain_intervals(events):
|
12367 |
+
|
12368 |
+
intervals = []
|
12369 |
+
pedal_on = False
|
12370 |
+
current_start = None
|
12371 |
+
|
12372 |
+
for t, cc in events:
|
12373 |
+
if not pedal_on and cc >= 64:
|
12374 |
+
|
12375 |
+
pedal_on = True
|
12376 |
+
current_start = t
|
12377 |
+
elif pedal_on and cc < 64:
|
12378 |
+
|
12379 |
+
pedal_on = False
|
12380 |
+
intervals.append((current_start, t))
|
12381 |
+
current_start = None
|
12382 |
+
|
12383 |
+
if pedal_on:
|
12384 |
+
intervals.append((current_start, float('inf')))
|
12385 |
+
|
12386 |
+
merged = []
|
12387 |
+
|
12388 |
+
for interval in intervals:
|
12389 |
+
if merged and interval[0] <= merged[-1][1]:
|
12390 |
+
merged[-1] = (merged[-1][0], max(merged[-1][1], interval[1]))
|
12391 |
+
else:
|
12392 |
+
merged.append(interval)
|
12393 |
+
return merged
|
12394 |
+
|
12395 |
+
###################################################################################
|
12396 |
+
|
12397 |
+
def apply_sustain_to_ms_score(score):
|
12398 |
+
|
12399 |
+
sustain_by_channel = {}
|
12400 |
+
|
12401 |
+
for track in score[1:]:
|
12402 |
+
for event in track:
|
12403 |
+
if event[0] == 'control_change' and event[3] == 64:
|
12404 |
+
channel = event[2]
|
12405 |
+
sustain_by_channel.setdefault(channel, []).append((event[1], event[4]))
|
12406 |
+
|
12407 |
+
sustain_intervals_by_channel = {}
|
12408 |
+
|
12409 |
+
for channel, events in sustain_by_channel.items():
|
12410 |
+
events.sort(key=lambda x: x[0])
|
12411 |
+
sustain_intervals_by_channel[channel] = compute_sustain_intervals(events)
|
12412 |
+
|
12413 |
+
global_max_off = 0
|
12414 |
+
|
12415 |
+
for track in score[1:]:
|
12416 |
+
for event in track:
|
12417 |
+
if event[0] == 'note':
|
12418 |
+
global_max_off = max(global_max_off, event[1] + event[2])
|
12419 |
+
|
12420 |
+
for channel, intervals in sustain_intervals_by_channel.items():
|
12421 |
+
updated_intervals = []
|
12422 |
+
for start, end in intervals:
|
12423 |
+
if end == float('inf'):
|
12424 |
+
end = global_max_off
|
12425 |
+
updated_intervals.append((start, end))
|
12426 |
+
sustain_intervals_by_channel[channel] = updated_intervals
|
12427 |
+
|
12428 |
+
if sustain_intervals_by_channel:
|
12429 |
+
|
12430 |
+
for track in score[1:]:
|
12431 |
+
for event in track:
|
12432 |
+
if event[0] == 'note':
|
12433 |
+
start = event[1]
|
12434 |
+
nominal_dur = event[2]
|
12435 |
+
nominal_off = start + nominal_dur
|
12436 |
+
channel = event[3]
|
12437 |
+
|
12438 |
+
intervals = sustain_intervals_by_channel.get(channel, [])
|
12439 |
+
effective_off = nominal_off
|
12440 |
+
|
12441 |
+
for intv_start, intv_end in intervals:
|
12442 |
+
if intv_start < nominal_off < intv_end:
|
12443 |
+
effective_off = intv_end
|
12444 |
+
break
|
12445 |
+
|
12446 |
+
effective_dur = effective_off - start
|
12447 |
+
|
12448 |
+
event[2] = effective_dur
|
12449 |
+
|
12450 |
+
return score
|
12451 |
+
|
12452 |
+
###################################################################################
|
12453 |
+
|
12454 |
+
def copy_file(src_file: str, trg_dir: str, add_subdir: bool = False, verbose: bool = False):
|
12455 |
+
|
12456 |
+
src_path = Path(src_file)
|
12457 |
+
target_directory = Path(trg_dir)
|
12458 |
+
|
12459 |
+
if not src_path.is_file():
|
12460 |
+
if verbose:
|
12461 |
+
print("Source file does not exist or is not a file.")
|
12462 |
+
|
12463 |
+
return None
|
12464 |
+
|
12465 |
+
target_directory.mkdir(parents=True, exist_ok=True)
|
12466 |
+
|
12467 |
+
if add_subdir:
|
12468 |
+
first_letter = src_path.name[0]
|
12469 |
+
target_directory = target_directory / first_letter
|
12470 |
+
target_directory.mkdir(parents=True, exist_ok=True)
|
12471 |
+
|
12472 |
+
destination = target_directory / src_path.name
|
12473 |
+
|
12474 |
+
try:
|
12475 |
+
shutil.copy2(src_path, destination)
|
12476 |
+
|
12477 |
+
except:
|
12478 |
+
if verbose:
|
12479 |
+
print('File could not be copied!')
|
12480 |
+
|
12481 |
+
return None
|
12482 |
+
|
12483 |
+
if verbose:
|
12484 |
+
print('File copied!')
|
12485 |
+
|
12486 |
+
return None
|
12487 |
+
|
12488 |
+
###################################################################################
|
12489 |
+
|
12490 |
+
def escore_notes_even_timings(escore_notes, in_place=True):
|
12491 |
+
|
12492 |
+
if in_place:
|
12493 |
+
for e in escore_notes:
|
12494 |
+
if e[1] % 2 != 0:
|
12495 |
+
e[1] += 1
|
12496 |
+
|
12497 |
+
if e[2] % 2 != 0:
|
12498 |
+
e[2] += 1
|
12499 |
+
|
12500 |
+
return []
|
12501 |
+
|
12502 |
+
else:
|
12503 |
+
escore = copy.deepcopy(escore_notes)
|
12504 |
+
|
12505 |
+
for e in escore:
|
12506 |
+
if e[1] % 2 != 0:
|
12507 |
+
e[1] += 1
|
12508 |
+
|
12509 |
+
if e[2] % 2 != 0:
|
12510 |
+
e[2] += 1
|
12511 |
+
|
12512 |
+
return escore
|
12513 |
+
|
12514 |
+
###################################################################################
|
12515 |
+
|
12516 |
+
def both_chords(chord1, chord2, merge_threshold=2):
|
12517 |
+
|
12518 |
+
if len(chord1) > 1 and len(chord2) > 0 and chord2[0][1]-chord1[0][1] <= merge_threshold:
|
12519 |
+
return True
|
12520 |
+
|
12521 |
+
elif len(chord1) > 0 and len(chord2) > 1 and chord2[0][1]-chord1[0][1] <= merge_threshold:
|
12522 |
+
return True
|
12523 |
+
|
12524 |
+
else:
|
12525 |
+
return False
|
12526 |
+
|
12527 |
+
def merge_chords(chord1, chord2, sort_drums_last=False):
|
12528 |
+
|
12529 |
+
mchord = chord1
|
12530 |
+
|
12531 |
+
seen = []
|
12532 |
+
|
12533 |
+
for e in chord2:
|
12534 |
+
if tuple([e[4], e[6]]) not in seen:
|
12535 |
+
mchord.append(e)
|
12536 |
+
seen.append(tuple([e[4], e[6]]))
|
12537 |
+
|
12538 |
+
for e in mchord[1:]:
|
12539 |
+
e[1] = mchord[0][1]
|
12540 |
+
|
12541 |
+
if sort_drums_last:
|
12542 |
+
mchord.sort(key=lambda x: (-x[4], x[6]) if x[6] != 128 else (x[6], -x[4]))
|
12543 |
+
|
12544 |
+
else:
|
12545 |
+
mchord.sort(key=lambda x: (-x[4], x[6]))
|
12546 |
+
|
12547 |
+
return mchord
|
12548 |
+
|
12549 |
+
def merge_escore_notes(escore_notes, merge_threshold=2, sort_drums_last=False):
|
12550 |
+
|
12551 |
+
cscore = chordify_score([1000, escore_notes])
|
12552 |
+
|
12553 |
+
merged_chords = []
|
12554 |
+
merged_chord = cscore[0]
|
12555 |
+
|
12556 |
+
for i in range(1, len(cscore)):
|
12557 |
+
|
12558 |
+
cchord = cscore[i]
|
12559 |
+
|
12560 |
+
if both_chords(merged_chord, cchord, merge_threshold=merge_threshold):
|
12561 |
+
merged_chord = merge_chords(merged_chord, cchord, sort_drums_last=sort_drums_last)
|
12562 |
+
|
12563 |
+
else:
|
12564 |
+
merged_chords.append(merged_chord)
|
12565 |
+
merged_chord = cchord
|
12566 |
+
|
12567 |
+
return flatten(merged_chords)
|
12568 |
+
|
12569 |
+
###################################################################################
|
12570 |
+
|
12571 |
+
def solo_piano_escore_notes_tokenized(escore_notes,
|
12572 |
+
compress_start_times=True,
|
12573 |
+
encode_velocities=False,
|
12574 |
+
verbose=False
|
12575 |
+
):
|
12576 |
+
|
12577 |
+
if verbose:
|
12578 |
+
print('=' * 70)
|
12579 |
+
print('Encoding MIDI...')
|
12580 |
+
|
12581 |
+
sp_escore_notes = solo_piano_escore_notes(escore_notes)
|
12582 |
+
zscore = recalculate_score_timings(sp_escore_notes)
|
12583 |
+
dscore = delta_score_notes(zscore, timings_clip_value=127)
|
12584 |
+
|
12585 |
+
score = []
|
12586 |
+
|
12587 |
+
notes_counter = 0
|
12588 |
+
chords_counter = 1
|
12589 |
+
|
12590 |
+
for i, e in enumerate(dscore):
|
12591 |
+
|
12592 |
+
dtime = e[1]
|
12593 |
+
dur = e[2]
|
12594 |
+
ptc = e[4]
|
12595 |
+
vel = e[5]
|
12596 |
+
|
12597 |
+
if compress_start_times:
|
12598 |
+
|
12599 |
+
if i == 0:
|
12600 |
+
score.extend([0, dur+128, ptc+256])
|
12601 |
+
|
12602 |
+
if encode_velocities:
|
12603 |
+
score.append(vel+384)
|
12604 |
+
|
12605 |
+
else:
|
12606 |
+
if dtime == 0:
|
12607 |
+
score.extend([dur+128, ptc+256])
|
12608 |
+
|
12609 |
+
else:
|
12610 |
+
score.extend([dtime, dur+128, ptc+256])
|
12611 |
+
|
12612 |
+
if encode_velocities:
|
12613 |
+
score.append(vel+384)
|
12614 |
+
|
12615 |
+
if dtime != 0:
|
12616 |
+
chords_counter += 1
|
12617 |
+
|
12618 |
+
else:
|
12619 |
+
score.extend([dtime, dur+128, ptc+256])
|
12620 |
+
|
12621 |
+
if encode_velocities:
|
12622 |
+
score.append(vel+384)
|
12623 |
+
|
12624 |
+
if dtime != 0:
|
12625 |
+
chords_counter += 1
|
12626 |
+
|
12627 |
+
notes_counter += 1
|
12628 |
+
|
12629 |
+
if verbose:
|
12630 |
+
print('Done!')
|
12631 |
+
print('=' * 70)
|
12632 |
+
|
12633 |
+
print('Source MIDI composition has', len(zscore), 'notes')
|
12634 |
+
print('Source MIDI composition has', len([d[1] for d in dscore if d[1] !=0 ])+1, 'chords')
|
12635 |
+
print('-' * 70)
|
12636 |
+
print('Encoded sequence has', notes_counter, 'pitches')
|
12637 |
+
print('Encoded sequence has', chords_counter, 'chords')
|
12638 |
+
print('-' * 70)
|
12639 |
+
print('Final encoded sequence has', len(score), 'tokens')
|
12640 |
+
print('=' * 70)
|
12641 |
+
|
12642 |
+
return score
|
12643 |
+
|
12644 |
+
###################################################################################
|
12645 |
+
|
12646 |
+
def equalize_closest_elements_dynamic(seq,
|
12647 |
+
min_val=128,
|
12648 |
+
max_val=256,
|
12649 |
+
splitting_factor=1.5,
|
12650 |
+
tightness_threshold=0.15
|
12651 |
+
):
|
12652 |
+
|
12653 |
+
candidates = [(i, x) for i, x in enumerate(seq) if min_val <= x <= max_val]
|
12654 |
+
|
12655 |
+
if len(candidates) < 2:
|
12656 |
+
return seq.copy()
|
12657 |
+
|
12658 |
+
sorted_candidates = sorted(candidates, key=lambda pair: pair[1])
|
12659 |
+
candidate_values = [val for _, val in sorted_candidates]
|
12660 |
+
|
12661 |
+
differences = [candidate_values[i+1] - candidate_values[i] for i in range(len(candidate_values)-1)]
|
12662 |
+
|
12663 |
+
def median(lst):
|
12664 |
+
|
12665 |
+
n = len(lst)
|
12666 |
+
sorted_lst = sorted(lst)
|
12667 |
+
mid = n // 2
|
12668 |
+
|
12669 |
+
if n % 2 == 0:
|
12670 |
+
return (sorted_lst[mid - 1] + sorted_lst[mid]) / 2.0
|
12671 |
+
|
12672 |
+
else:
|
12673 |
+
return sorted_lst[mid]
|
12674 |
+
|
12675 |
+
med_diff = median(differences)
|
12676 |
+
|
12677 |
+
split_indices = [i for i, diff in enumerate(differences) if diff > splitting_factor * med_diff]
|
12678 |
+
|
12679 |
+
clusters = []
|
12680 |
+
|
12681 |
+
if split_indices:
|
12682 |
+
start = 0
|
12683 |
+
for split_index in split_indices:
|
12684 |
+
clusters.append(sorted_candidates[start:split_index+1])
|
12685 |
+
start = split_index + 1
|
12686 |
+
clusters.append(sorted_candidates[start:])
|
12687 |
+
|
12688 |
+
else:
|
12689 |
+
clusters = [sorted_candidates]
|
12690 |
+
|
12691 |
+
|
12692 |
+
valid_clusters = [cluster for cluster in clusters if len(cluster) >= 2]
|
12693 |
+
if not valid_clusters:
|
12694 |
+
return seq.copy()
|
12695 |
+
|
12696 |
+
def cluster_spread(cluster):
|
12697 |
+
values = [val for (_, val) in cluster]
|
12698 |
+
return max(values) - min(values)
|
12699 |
+
|
12700 |
+
valid_clusters.sort(key=lambda cluster: (len(cluster), -cluster_spread(cluster)), reverse=True)
|
12701 |
+
selected_cluster = valid_clusters[0]
|
12702 |
+
|
12703 |
+
allowed_range_width = max_val - min_val
|
12704 |
+
spread = cluster_spread(selected_cluster)
|
12705 |
+
ratio = spread / allowed_range_width
|
12706 |
+
|
12707 |
+
if ratio > tightness_threshold:
|
12708 |
+
return seq.copy()
|
12709 |
+
|
12710 |
+
cluster_values = [val for (_, val) in selected_cluster]
|
12711 |
+
equal_value = sum(cluster_values) // len(cluster_values)
|
12712 |
+
|
12713 |
+
|
12714 |
+
result = list(seq)
|
12715 |
+
for idx, _ in selected_cluster:
|
12716 |
+
result[idx] = equal_value
|
12717 |
+
|
12718 |
+
return result
|
12719 |
+
|
12720 |
+
###################################################################################
|
12721 |
+
|
12722 |
+
def chunk_list(lst, chunk_size):
|
12723 |
+
return [lst[i:i + chunk_size] for i in range(0, len(lst), chunk_size)]
|
12724 |
+
|
12725 |
+
###################################################################################
|
12726 |
+
|
12727 |
+
def compress_tokens_sequence(seq,
|
12728 |
+
min_val=128,
|
12729 |
+
max_val=256,
|
12730 |
+
group_size=2,
|
12731 |
+
splitting_factor=1.5,
|
12732 |
+
tightness_threshold=0.15
|
12733 |
+
):
|
12734 |
+
|
12735 |
+
comp_seq = equalize_closest_elements_dynamic(seq,
|
12736 |
+
min_val,
|
12737 |
+
max_val,
|
12738 |
+
splitting_factor=splitting_factor,
|
12739 |
+
tightness_threshold=tightness_threshold
|
12740 |
+
)
|
12741 |
+
|
12742 |
+
seq_split = sorted(chunk_list(comp_seq, group_size), key=lambda x: (-x[0], -x[1]))
|
12743 |
+
|
12744 |
+
seq_grouped = [[[k]] + [vv[1:] for vv in v] for k, v in groupby(seq_split, key=lambda x: x[0])]
|
12745 |
+
|
12746 |
+
return flatten(flatten(sorted(seq_grouped, key=lambda x: -x[1][0])))
|
12747 |
+
|
12748 |
+
###################################################################################
|
12749 |
+
|
12750 |
+
def merge_adjacent_pairs(values_counts):
|
12751 |
+
|
12752 |
+
merged = []
|
12753 |
+
i = 0
|
12754 |
+
|
12755 |
+
while i < len(values_counts):
|
12756 |
+
|
12757 |
+
if i < len(values_counts) - 1:
|
12758 |
+
value1, count1 = values_counts[i]
|
12759 |
+
value2, count2 = values_counts[i + 1]
|
12760 |
+
|
12761 |
+
if value2 - value1 == 1:
|
12762 |
+
if count2 > count1:
|
12763 |
+
merged_value = value2
|
12764 |
+
|
12765 |
+
else:
|
12766 |
+
merged_value = value1
|
12767 |
+
|
12768 |
+
merged_count = count1 + count2
|
12769 |
+
merged.append((merged_value, merged_count))
|
12770 |
+
|
12771 |
+
i += 2
|
12772 |
+
|
12773 |
+
continue
|
12774 |
+
|
12775 |
+
merged.append(values_counts[i])
|
12776 |
+
|
12777 |
+
i += 1
|
12778 |
+
|
12779 |
+
return merged
|
12780 |
+
|
12781 |
+
###################################################################################
|
12782 |
+
|
12783 |
+
def merge_escore_notes_start_times(escore_notes, num_merges=1):
|
12784 |
+
|
12785 |
+
new_dscore = delta_score_notes(escore_notes)
|
12786 |
+
|
12787 |
+
times = [e[1] for e in new_dscore if e[1] != 0]
|
12788 |
+
times_counts = sorted(Counter(times).most_common())
|
12789 |
+
|
12790 |
+
prev_counts = []
|
12791 |
+
new_times_counts = times_counts
|
12792 |
+
|
12793 |
+
mcount = 0
|
12794 |
+
|
12795 |
+
while prev_counts != new_times_counts:
|
12796 |
+
prev_counts = new_times_counts
|
12797 |
+
new_times_counts = merge_adjacent_pairs(new_times_counts)
|
12798 |
+
|
12799 |
+
mcount += 1
|
12800 |
+
|
12801 |
+
if mcount == num_merges:
|
12802 |
+
break
|
12803 |
+
|
12804 |
+
gtimes = [r[0] for r in new_times_counts]
|
12805 |
+
|
12806 |
+
for e in new_dscore:
|
12807 |
+
if e[1] > 0:
|
12808 |
+
e[1] = find_closest_value(gtimes, e[1])[0]
|
12809 |
+
e[2] -= num_merges
|
12810 |
+
|
12811 |
+
return delta_score_to_abs_score(new_dscore)
|
12812 |
+
|
12813 |
+
###################################################################################
|
12814 |
+
|
12815 |
+
def multi_instrumental_escore_notes_tokenized(escore_notes, compress_seq=False):
|
12816 |
+
|
12817 |
+
melody_chords = []
|
12818 |
+
|
12819 |
+
pe = escore_notes[0]
|
12820 |
+
|
12821 |
+
for i, e in enumerate(escore_notes):
|
12822 |
+
|
12823 |
+
dtime = max(0, min(255, e[1]-pe[1]))
|
12824 |
+
|
12825 |
+
dur = max(0, min(255, e[2]))
|
12826 |
+
|
12827 |
+
cha = max(0, min(15, e[3]))
|
12828 |
+
|
12829 |
+
if cha == 9:
|
12830 |
+
pat = 128
|
12831 |
+
|
12832 |
+
else:
|
12833 |
+
pat = max(0, min(127, e[6]))
|
12834 |
+
|
12835 |
+
ptc = max(0, min(127, e[4]))
|
12836 |
+
|
12837 |
+
vel = max(8, min(127, e[5]))
|
12838 |
+
velocity = round(vel / 15)-1
|
12839 |
+
|
12840 |
+
dur_vel = (8 * dur) + velocity
|
12841 |
+
pat_ptc = (129 * pat) + ptc
|
12842 |
+
|
12843 |
+
if compress_seq:
|
12844 |
+
if dtime != 0 or i == 0:
|
12845 |
+
melody_chords.extend([dtime, dur_vel+256, pat_ptc+2304])
|
12846 |
+
|
12847 |
+
else:
|
12848 |
+
melody_chords.extend([dur_vel+256, pat_ptc+2304])
|
12849 |
+
|
12850 |
+
else:
|
12851 |
+
melody_chords.extend([dtime, dur_vel+256, pat_ptc+2304])
|
12852 |
+
|
12853 |
+
pe = e
|
12854 |
+
|
12855 |
+
return melody_chords
|
12856 |
+
|
12857 |
+
###################################################################################
|
12858 |
+
|
12859 |
+
def merge_counts(data, return_lists=True):
|
12860 |
+
|
12861 |
+
merged = defaultdict(int)
|
12862 |
+
|
12863 |
+
for value, count in data:
|
12864 |
+
merged[value] += count
|
12865 |
+
|
12866 |
+
if return_lists:
|
12867 |
+
return [[k, v] for k, v in merged.items()]
|
12868 |
+
|
12869 |
+
else:
|
12870 |
+
return list(merged.items())
|
12871 |
+
|
12872 |
+
###################################################################################
|
12873 |
+
|
12874 |
+
def convert_escore_notes_pitches_chords_signature(signature, convert_to_full_chords=True):
|
12875 |
+
|
12876 |
+
if convert_to_full_chords:
|
12877 |
+
SRC_CHORDS = ALL_CHORDS_SORTED
|
12878 |
+
TRG_CHORDS = ALL_CHORDS_FULL
|
12879 |
+
|
12880 |
+
else:
|
12881 |
+
SRC_CHORDS = ALL_CHORDS_FULL
|
12882 |
+
TRG_CHORDS = ALL_CHORDS_SORTED
|
12883 |
+
|
12884 |
+
cdiff = len(TRG_CHORDS) - len(SRC_CHORDS)
|
12885 |
+
|
12886 |
+
pitches_counts = [c for c in signature if -1 < c[0] < 128]
|
12887 |
+
chords_counts = [c for c in signature if 127 < c[0] < len(SRC_CHORDS)+128]
|
12888 |
+
drums_counts = [[c[0]+cdiff, c[1]] for c in signature if len(SRC_CHORDS)+127 < c[0] < len(SRC_CHORDS)+256]
|
12889 |
+
bad_chords_count = [c for c in signature if c[0] == -1]
|
12890 |
+
|
12891 |
+
new_chords_counts = []
|
12892 |
+
|
12893 |
+
for c in chords_counts:
|
12894 |
+
tones_chord = SRC_CHORDS[c[0]-128]
|
12895 |
+
|
12896 |
+
if tones_chord not in TRG_CHORDS:
|
12897 |
+
tones_chord = check_and_fix_tones_chord(tones_chord, use_full_chords=convert_to_full_chords)
|
12898 |
+
bad_chords_count[0][1] += 1
|
12899 |
+
|
12900 |
+
new_chords_counts.append([TRG_CHORDS.index(tones_chord)+128, c[1]])
|
12901 |
+
|
12902 |
+
return pitches_counts + merge_counts(new_chords_counts) + drums_counts + bad_chords_count
|
12903 |
+
|
12904 |
+
###################################################################################
|
12905 |
+
|
12906 |
+
def convert_bytes_in_nested_list(lst, encoding='utf-8', errors='ignore'):
|
12907 |
+
|
12908 |
+
new_list = []
|
12909 |
+
|
12910 |
+
for item in lst:
|
12911 |
+
if isinstance(item, list):
|
12912 |
+
new_list.append(convert_bytes_in_nested_list(item))
|
12913 |
+
|
12914 |
+
elif isinstance(item, bytes):
|
12915 |
+
new_list.append(item.decode(encoding, errors=errors))
|
12916 |
+
|
12917 |
+
else:
|
12918 |
+
new_list.append(item)
|
12919 |
+
|
12920 |
+
return new_list
|
12921 |
+
|
12922 |
+
###################################################################################
|
12923 |
+
|
12924 |
+
def mult_pitches(pitches, min_oct=4, max_oct=6):
|
12925 |
+
|
12926 |
+
tones_chord = sorted(set([p % 12 for p in pitches]))
|
12927 |
+
|
12928 |
+
mult_ptcs = []
|
12929 |
+
|
12930 |
+
for t in tones_chord:
|
12931 |
+
for i in range(min_oct, max_oct):
|
12932 |
+
mult_ptcs.append((i*12)+t)
|
12933 |
+
|
12934 |
+
return mult_ptcs
|
12935 |
+
|
12936 |
+
###################################################################################
|
12937 |
+
|
12938 |
+
def find_next(pitches, cur_ptc):
|
12939 |
+
|
12940 |
+
i = 0
|
12941 |
+
|
12942 |
+
for i, p in enumerate(pitches):
|
12943 |
+
if p != cur_ptc:
|
12944 |
+
break
|
12945 |
+
|
12946 |
+
return i
|
12947 |
+
|
12948 |
+
###################################################################################
|
12949 |
+
|
12950 |
+
def ordered_groups_unsorted(data, key_index):
|
12951 |
+
|
12952 |
+
def keyfunc(sublist):
|
12953 |
+
return sublist[key_index]
|
12954 |
+
|
12955 |
+
groups = []
|
12956 |
+
|
12957 |
+
for key, group in groupby(data, key=keyfunc):
|
12958 |
+
groups.append((key, list(group)))
|
12959 |
+
|
12960 |
+
return groups
|
12961 |
+
|
12962 |
+
###################################################################################
|
12963 |
+
|
12964 |
+
def ordered_groups(data, key_index):
|
12965 |
+
|
12966 |
+
groups = OrderedDict()
|
12967 |
+
|
12968 |
+
for sublist in data:
|
12969 |
+
key = sublist[key_index]
|
12970 |
+
|
12971 |
+
if key not in groups:
|
12972 |
+
groups[key] = []
|
12973 |
+
|
12974 |
+
groups[key].append(sublist)
|
12975 |
+
|
12976 |
+
return list(groups.items())
|
12977 |
+
|
12978 |
+
###################################################################################
|
12979 |
+
|
12980 |
+
def merge_melody_notes(escore_notes, pitches_idx=4, max_dur=255, last_dur=128):
|
12981 |
+
|
12982 |
+
groups = ordered_groups_unsorted(escore_notes, pitches_idx)
|
12983 |
+
|
12984 |
+
merged_melody_notes = []
|
12985 |
+
|
12986 |
+
for i, (k, g) in enumerate(groups[:-1]):
|
12987 |
+
|
12988 |
+
if len(g) == 1:
|
12989 |
+
merged_melody_notes.extend(g)
|
12990 |
+
|
12991 |
+
else:
|
12992 |
+
dur = min(max_dur, groups[i+1][1][0][1] - g[0][1])
|
12993 |
+
|
12994 |
+
merged_melody_notes.append(['note',
|
12995 |
+
g[0][1],
|
12996 |
+
dur,
|
12997 |
+
g[0][3],
|
12998 |
+
g[0][4],
|
12999 |
+
g[0][5],
|
13000 |
+
g[0][6]
|
13001 |
+
])
|
13002 |
+
|
13003 |
+
merged_melody_notes.append(['note',
|
13004 |
+
groups[-1][1][0][1],
|
13005 |
+
last_dur,
|
13006 |
+
groups[-1][1][0][3],
|
13007 |
+
groups[-1][1][0][4],
|
13008 |
+
groups[-1][1][0][5],
|
13009 |
+
groups[-1][1][0][6]
|
13010 |
+
])
|
13011 |
+
|
13012 |
+
return merged_melody_notes
|
13013 |
+
|
13014 |
+
###################################################################################
|
13015 |
+
|
13016 |
+
def add_expressive_melody_to_enhanced_score_notes(escore_notes,
|
13017 |
+
melody_start_chord=0,
|
13018 |
+
melody_prime_pitch=60,
|
13019 |
+
melody_step=1,
|
13020 |
+
melody_channel=3,
|
13021 |
+
melody_patch=40,
|
13022 |
+
melody_notes_max_duration=255,
|
13023 |
+
melody_last_note_dur=128,
|
13024 |
+
melody_clip_max_min_durs=[],
|
13025 |
+
melody_max_velocity=120,
|
13026 |
+
acc_max_velocity=90,
|
13027 |
+
return_melody=False
|
13028 |
+
):
|
13029 |
+
|
13030 |
+
|
13031 |
+
score = copy.deepcopy(escore_notes)
|
13032 |
+
|
13033 |
+
adjust_score_velocities(score, acc_max_velocity)
|
13034 |
+
|
13035 |
+
cscore = chordify_score([1000, score])
|
13036 |
+
|
13037 |
+
melody_pitches = [melody_prime_pitch]
|
13038 |
+
|
13039 |
+
for i, c in enumerate(cscore[melody_start_chord:]):
|
13040 |
+
|
13041 |
+
if i % melody_step == 0:
|
13042 |
+
|
13043 |
+
pitches = [e[4] for e in c if e[3] != 9]
|
13044 |
+
|
13045 |
+
if pitches:
|
13046 |
+
cptc = find_closest_value(mult_pitches(pitches), melody_pitches[-1])[0]
|
13047 |
+
melody_pitches.append(cptc)
|
13048 |
+
|
13049 |
+
song_f = []
|
13050 |
+
mel_f = []
|
13051 |
+
|
13052 |
+
idx = 1
|
13053 |
+
|
13054 |
+
for i, c in enumerate(cscore[:-melody_step]):
|
13055 |
+
pitches = [e[4] for e in c if e[3] != 9]
|
13056 |
+
|
13057 |
+
if pitches and i >= melody_start_chord and i % melody_step == 0:
|
13058 |
+
dur = min(cscore[i+melody_step][0][1] - c[0][1], melody_notes_max_duration)
|
13059 |
+
|
13060 |
+
mel_f.append(['note',
|
13061 |
+
c[0][1],
|
13062 |
+
dur,
|
13063 |
+
melody_channel,
|
13064 |
+
60+(melody_pitches[idx] % 24),
|
13065 |
+
100 + ((melody_pitches[idx] % 12) * 2),
|
13066 |
+
melody_patch
|
13067 |
+
])
|
13068 |
+
idx += 1
|
13069 |
+
|
13070 |
+
song_f.extend(c)
|
13071 |
+
|
13072 |
+
song_f.extend(flatten(cscore[-melody_step:]))
|
13073 |
+
|
13074 |
+
if len(melody_clip_max_min_durs) == 2:
|
13075 |
+
for e in mel_f:
|
13076 |
+
if e[2] >= melody_clip_max_min_durs[0]:
|
13077 |
+
e[2] = melody_clip_max_min_durs[1]
|
13078 |
+
|
13079 |
+
adjust_score_velocities(mel_f, melody_max_velocity)
|
13080 |
+
|
13081 |
+
merged_melody_notes = merge_melody_notes(mel_f,
|
13082 |
+
max_dur=melody_notes_max_duration,
|
13083 |
+
last_dur=melody_last_note_dur
|
13084 |
+
)
|
13085 |
+
|
13086 |
+
song_f = sorted(merged_melody_notes + song_f,
|
13087 |
+
key=lambda x: x[1]
|
13088 |
+
)
|
13089 |
+
|
13090 |
+
if return_melody:
|
13091 |
+
return mel_f
|
13092 |
+
|
13093 |
+
else:
|
13094 |
+
return song_f
|
13095 |
+
|
13096 |
+
###################################################################################
|
13097 |
+
|
13098 |
+
def list_md5_hash(ints_list):
|
13099 |
+
|
13100 |
+
arr = array('H', ints_list)
|
13101 |
+
binary_data = arr.tobytes()
|
13102 |
+
|
13103 |
+
return hashlib.md5(binary_data).hexdigest()
|
13104 |
+
|
13105 |
+
###################################################################################
|
13106 |
+
|
13107 |
+
def fix_escore_notes_durations(escore_notes,
|
13108 |
+
min_notes_gap=1,
|
13109 |
+
min_notes_dur=1,
|
13110 |
+
times_idx=1,
|
13111 |
+
durs_idx=2,
|
13112 |
+
channels_idx = 3,
|
13113 |
+
pitches_idx=4
|
13114 |
+
):
|
13115 |
+
|
13116 |
+
notes = [e for e in escore_notes if e[channels_idx] != 9]
|
13117 |
+
drums = [e for e in escore_notes if e[channels_idx] == 9]
|
13118 |
+
|
13119 |
+
escore_groups = ordered_groups(notes, pitches_idx)
|
13120 |
+
|
13121 |
+
merged_score = []
|
13122 |
+
|
13123 |
+
for k, g in escore_groups:
|
13124 |
+
if len(g) > 2:
|
13125 |
+
fg = fix_monophonic_score_durations(g,
|
13126 |
+
min_notes_gap=min_notes_gap,
|
13127 |
+
min_notes_dur=min_notes_dur
|
13128 |
+
)
|
13129 |
+
merged_score.extend(fg)
|
13130 |
+
|
13131 |
+
elif len(g) == 2:
|
13132 |
+
|
13133 |
+
if g[0][times_idx]+g[0][durs_idx] >= g[1][times_idx]:
|
13134 |
+
g[0][durs_idx] = max(1, g[1][times_idx] - g[0][times_idx] - 1)
|
13135 |
+
|
13136 |
+
merged_score.extend(g)
|
13137 |
+
|
13138 |
+
else:
|
13139 |
+
merged_score.extend(g)
|
13140 |
+
|
13141 |
+
return sorted(merged_score + drums, key=lambda x: x[times_idx])
|
13142 |
+
|
13143 |
+
###################################################################################
|
13144 |
+
|
13145 |
+
print('Module loaded!')
|
13146 |
+
print('=' * 70)
|
13147 |
+
print('Enjoy! :)')
|
13148 |
+
print('=' * 70)
|
13149 |
+
|
13150 |
###################################################################################
|
13151 |
# This is the end of the TMIDI X Python module
|
13152 |
###################################################################################
|