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,7 +46,20 @@ r'''############################################################################
|
|
| 47 |
# Copyright 2020 Peter Billam
|
| 48 |
#
|
| 49 |
###################################################################################
|
| 50 |
-
###################################################################################
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
import sys, struct, copy
|
| 53 |
|
|
@@ -1440,7 +1452,6 @@ def _encode(events_lol, unknown_callback=None, never_add_eot=False,
|
|
| 1440 |
###################################################################################
|
| 1441 |
#
|
| 1442 |
# Tegridy MIDI X Module (TMIDI X / tee-midi eks)
|
| 1443 |
-
# Version 1.0
|
| 1444 |
#
|
| 1445 |
# Based upon and includes the amazing MIDI.py module v.6.7. by Peter Billam
|
| 1446 |
# pjb.com.au
|
|
@@ -1497,6 +1508,8 @@ from pathlib import Path
|
|
| 1497 |
|
| 1498 |
import shutil
|
| 1499 |
|
|
|
|
|
|
|
| 1500 |
###################################################################################
|
| 1501 |
#
|
| 1502 |
# Original TMIDI Tegridy helper functions
|
|
@@ -4715,7 +4728,8 @@ def augment_enhanced_score_notes(enhanced_score_notes,
|
|
| 4715 |
ceil_timings=False,
|
| 4716 |
round_timings=False,
|
| 4717 |
legacy_timings=True,
|
| 4718 |
-
sort_drums_last=False
|
|
|
|
| 4719 |
):
|
| 4720 |
|
| 4721 |
esn = copy.deepcopy(enhanced_score_notes)
|
|
@@ -4758,6 +4772,16 @@ def augment_enhanced_score_notes(enhanced_score_notes,
|
|
| 4758 |
e[4] = max(1, min(127, e[4] + pitch_shift))
|
| 4759 |
|
| 4760 |
pe = enhanced_score_notes[i]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4761 |
|
| 4762 |
if full_sorting:
|
| 4763 |
|
|
@@ -6698,12 +6722,23 @@ def find_next_bar(escore_notes, bar_time, start_note_idx, cur_bar):
|
|
| 6698 |
def align_escore_notes_to_bars(escore_notes,
|
| 6699 |
bar_time=4000,
|
| 6700 |
trim_durations=False,
|
| 6701 |
-
split_durations=False
|
|
|
|
| 6702 |
):
|
| 6703 |
|
| 6704 |
#=============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6705 |
|
| 6706 |
-
aligned_escore_notes = copy.deepcopy(
|
| 6707 |
|
| 6708 |
abs_time = 0
|
| 6709 |
nidx = 0
|
|
@@ -6715,13 +6750,13 @@ def align_escore_notes_to_bars(escore_notes,
|
|
| 6715 |
|
| 6716 |
while next_bar:
|
| 6717 |
|
| 6718 |
-
next_bar = find_next_bar(
|
| 6719 |
|
| 6720 |
if next_bar:
|
| 6721 |
-
|
| 6722 |
-
|
| 6723 |
else:
|
| 6724 |
-
gescore_notes =
|
| 6725 |
|
| 6726 |
original_timings = [delta] + [(b[1]-a[1]) for a, b in zip(gescore_notes[:-1], gescore_notes[1:])]
|
| 6727 |
adj_timings = adjust_numbers_to_sum(original_timings, bar_time)
|
|
@@ -6736,7 +6771,8 @@ def align_escore_notes_to_bars(escore_notes,
|
|
| 6736 |
nidx += 1
|
| 6737 |
|
| 6738 |
if next_bar:
|
| 6739 |
-
delta =
|
|
|
|
| 6740 |
bcount += 1
|
| 6741 |
|
| 6742 |
#=============================================================================
|
|
@@ -11304,26 +11340,57 @@ def system_memory_utilization(return_dict=False):
|
|
| 11304 |
|
| 11305 |
def create_files_list(datasets_paths=['./'],
|
| 11306 |
files_exts=['.mid', '.midi', '.kar', '.MID', '.MIDI', '.KAR'],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11307 |
randomize_files_list=True,
|
|
|
|
| 11308 |
verbose=True
|
| 11309 |
):
|
|
|
|
| 11310 |
if verbose:
|
| 11311 |
print('=' * 70)
|
| 11312 |
print('Searching for files...')
|
| 11313 |
print('This may take a while on a large dataset in particular...')
|
| 11314 |
print('=' * 70)
|
| 11315 |
|
| 11316 |
-
filez_set = defaultdict(None)
|
| 11317 |
-
|
| 11318 |
files_exts = tuple(files_exts)
|
| 11319 |
|
|
|
|
|
|
|
|
|
|
| 11320 |
for dataset_addr in tqdm.tqdm(datasets_paths, disable=not verbose):
|
| 11321 |
for dirpath, dirnames, filenames in os.walk(dataset_addr):
|
| 11322 |
-
|
| 11323 |
-
|
| 11324 |
-
|
| 11325 |
-
|
| 11326 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11327 |
|
| 11328 |
if verbose:
|
| 11329 |
print('Done!')
|
|
@@ -11343,6 +11410,7 @@ def create_files_list(datasets_paths=['./'],
|
|
| 11343 |
|
| 11344 |
if verbose:
|
| 11345 |
print('Found', len(filez), 'files.')
|
|
|
|
| 11346 |
print('=' * 70)
|
| 11347 |
|
| 11348 |
else:
|
|
@@ -11350,8 +11418,20 @@ def create_files_list(datasets_paths=['./'],
|
|
| 11350 |
print('Could not find any files...')
|
| 11351 |
print('Please check dataset dirs and files extensions...')
|
| 11352 |
print('=' * 70)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11353 |
|
| 11354 |
-
|
|
|
|
| 11355 |
|
| 11356 |
###################################################################################
|
| 11357 |
|
|
@@ -12172,8 +12252,16 @@ def escore_notes_pitches_chords_signature(escore_notes,
|
|
| 12172 |
sort_by_counts=False,
|
| 12173 |
use_full_chords=False
|
| 12174 |
):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12175 |
|
| 12176 |
-
escore_notes = [e for e in escore_notes if e[6] <= max_patch
|
| 12177 |
|
| 12178 |
if escore_notes:
|
| 12179 |
|
|
@@ -12182,7 +12270,7 @@ def escore_notes_pitches_chords_signature(escore_notes,
|
|
| 12182 |
sig = []
|
| 12183 |
dsig = []
|
| 12184 |
|
| 12185 |
-
drums_offset =
|
| 12186 |
|
| 12187 |
bad_chords_counter = 0
|
| 12188 |
|
|
@@ -12199,10 +12287,10 @@ def escore_notes_pitches_chords_signature(escore_notes,
|
|
| 12199 |
tones_chord = sorted(set([p % 12 for p in pitches]))
|
| 12200 |
|
| 12201 |
try:
|
| 12202 |
-
sig_token =
|
| 12203 |
except:
|
| 12204 |
checked_tones_chord = check_and_fix_tones_chord(tones_chord, use_full_chords=use_full_chords)
|
| 12205 |
-
sig_token =
|
| 12206 |
bad_chords_counter += 1
|
| 12207 |
|
| 12208 |
elif len(pitches) == 1:
|
|
@@ -12359,6 +12447,429 @@ def copy_file(src_file: str, trg_dir: str, add_subdir: bool = False, verbose: bo
|
|
| 12359 |
|
| 12360 |
return None
|
| 12361 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12362 |
###################################################################################
|
| 12363 |
# This is the end of the TMIDI X Python module
|
| 12364 |
###################################################################################
|
|
|
|
| 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.4.11"
|
| 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 |
|
|
|
|
| 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
|
|
|
|
| 1508 |
|
| 1509 |
import shutil
|
| 1510 |
|
| 1511 |
+
import hashlib
|
| 1512 |
+
|
| 1513 |
###################################################################################
|
| 1514 |
#
|
| 1515 |
# Original TMIDI Tegridy helper functions
|
|
|
|
| 4728 |
ceil_timings=False,
|
| 4729 |
round_timings=False,
|
| 4730 |
legacy_timings=True,
|
| 4731 |
+
sort_drums_last=False,
|
| 4732 |
+
even_timings=False
|
| 4733 |
):
|
| 4734 |
|
| 4735 |
esn = copy.deepcopy(enhanced_score_notes)
|
|
|
|
| 4772 |
e[4] = max(1, min(127, e[4] + pitch_shift))
|
| 4773 |
|
| 4774 |
pe = enhanced_score_notes[i]
|
| 4775 |
+
|
| 4776 |
+
|
| 4777 |
+
if even_timings:
|
| 4778 |
+
|
| 4779 |
+
for e in esn:
|
| 4780 |
+
if e[1] % 2 != 0:
|
| 4781 |
+
e[1] += 1
|
| 4782 |
+
|
| 4783 |
+
if e[2] % 2 != 0:
|
| 4784 |
+
e[2] += 1
|
| 4785 |
|
| 4786 |
if full_sorting:
|
| 4787 |
|
|
|
|
| 6722 |
def align_escore_notes_to_bars(escore_notes,
|
| 6723 |
bar_time=4000,
|
| 6724 |
trim_durations=False,
|
| 6725 |
+
split_durations=False,
|
| 6726 |
+
even_timings=False
|
| 6727 |
):
|
| 6728 |
|
| 6729 |
#=============================================================================
|
| 6730 |
+
|
| 6731 |
+
escore = copy.deepcopy(escore_notes)
|
| 6732 |
+
|
| 6733 |
+
if even_timings:
|
| 6734 |
+
for e in escore:
|
| 6735 |
+
if e[1] % 2 != 0:
|
| 6736 |
+
e[1] += 1
|
| 6737 |
+
|
| 6738 |
+
if e[2] % 2 != 0:
|
| 6739 |
+
e[2] += 1
|
| 6740 |
|
| 6741 |
+
aligned_escore_notes = copy.deepcopy(escore)
|
| 6742 |
|
| 6743 |
abs_time = 0
|
| 6744 |
nidx = 0
|
|
|
|
| 6750 |
|
| 6751 |
while next_bar:
|
| 6752 |
|
| 6753 |
+
next_bar = find_next_bar(escore, bar_time, nidx, bcount)
|
| 6754 |
|
| 6755 |
if next_bar:
|
| 6756 |
+
gescore_notes = escore[nidx:next_bar[1]]
|
| 6757 |
+
|
| 6758 |
else:
|
| 6759 |
+
gescore_notes = escore[nidx:]
|
| 6760 |
|
| 6761 |
original_timings = [delta] + [(b[1]-a[1]) for a, b in zip(gescore_notes[:-1], gescore_notes[1:])]
|
| 6762 |
adj_timings = adjust_numbers_to_sum(original_timings, bar_time)
|
|
|
|
| 6771 |
nidx += 1
|
| 6772 |
|
| 6773 |
if next_bar:
|
| 6774 |
+
delta = escore[next_bar[1]][1]-escore[next_bar[1]-1][1]
|
| 6775 |
+
|
| 6776 |
bcount += 1
|
| 6777 |
|
| 6778 |
#=============================================================================
|
|
|
|
| 11340 |
|
| 11341 |
def create_files_list(datasets_paths=['./'],
|
| 11342 |
files_exts=['.mid', '.midi', '.kar', '.MID', '.MIDI', '.KAR'],
|
| 11343 |
+
use_md5_hashes=False,
|
| 11344 |
+
max_num_files_per_dir=-1,
|
| 11345 |
+
randomize_dir_files=False,
|
| 11346 |
+
max_total_files=-1,
|
| 11347 |
randomize_files_list=True,
|
| 11348 |
+
return_dupes=False,
|
| 11349 |
verbose=True
|
| 11350 |
):
|
| 11351 |
+
|
| 11352 |
if verbose:
|
| 11353 |
print('=' * 70)
|
| 11354 |
print('Searching for files...')
|
| 11355 |
print('This may take a while on a large dataset in particular...')
|
| 11356 |
print('=' * 70)
|
| 11357 |
|
|
|
|
|
|
|
| 11358 |
files_exts = tuple(files_exts)
|
| 11359 |
|
| 11360 |
+
filez_set = defaultdict(None)
|
| 11361 |
+
dupes_list = []
|
| 11362 |
+
|
| 11363 |
for dataset_addr in tqdm.tqdm(datasets_paths, disable=not verbose):
|
| 11364 |
for dirpath, dirnames, filenames in os.walk(dataset_addr):
|
| 11365 |
+
|
| 11366 |
+
if randomize_dir_files:
|
| 11367 |
+
random.shuffle(filenames)
|
| 11368 |
+
|
| 11369 |
+
if max_num_files_per_dir > 0:
|
| 11370 |
+
max_num_files = max_num_files_per_dir
|
| 11371 |
+
|
| 11372 |
+
else:
|
| 11373 |
+
max_num_files = len(filenames)
|
| 11374 |
+
|
| 11375 |
+
for file in filenames[:max_num_files]:
|
| 11376 |
+
if file.endswith(files_exts):
|
| 11377 |
+
if use_md5_hashes:
|
| 11378 |
+
md5_hash = hashlib.md5(open(os.path.join(dirpath, file), 'rb').read()).hexdigest()
|
| 11379 |
+
|
| 11380 |
+
if md5_hash not in filez_set:
|
| 11381 |
+
filez_set[md5_hash] = os.path.join(dirpath, file)
|
| 11382 |
+
|
| 11383 |
+
else:
|
| 11384 |
+
dupes_list.append(os.path.join(dirpath, file))
|
| 11385 |
+
|
| 11386 |
+
else:
|
| 11387 |
+
if file not in filez_set:
|
| 11388 |
+
filez_set[file] = os.path.join(dirpath, file)
|
| 11389 |
+
|
| 11390 |
+
else:
|
| 11391 |
+
dupes_list.append(os.path.join(dirpath, file))
|
| 11392 |
+
|
| 11393 |
+
filez = list(filez_set.values())
|
| 11394 |
|
| 11395 |
if verbose:
|
| 11396 |
print('Done!')
|
|
|
|
| 11410 |
|
| 11411 |
if verbose:
|
| 11412 |
print('Found', len(filez), 'files.')
|
| 11413 |
+
print('Skipped', len(dupes_list), 'duplicate files.')
|
| 11414 |
print('=' * 70)
|
| 11415 |
|
| 11416 |
else:
|
|
|
|
| 11418 |
print('Could not find any files...')
|
| 11419 |
print('Please check dataset dirs and files extensions...')
|
| 11420 |
print('=' * 70)
|
| 11421 |
+
|
| 11422 |
+
if max_total_files > 0:
|
| 11423 |
+
if return_dupes:
|
| 11424 |
+
return filez[:max_total_files], dupes_list
|
| 11425 |
+
|
| 11426 |
+
else:
|
| 11427 |
+
return filez[:max_total_files]
|
| 11428 |
+
|
| 11429 |
+
else:
|
| 11430 |
+
if return_dupes:
|
| 11431 |
+
return filez, dupes_list
|
| 11432 |
|
| 11433 |
+
else:
|
| 11434 |
+
return filez
|
| 11435 |
|
| 11436 |
###################################################################################
|
| 11437 |
|
|
|
|
| 12252 |
sort_by_counts=False,
|
| 12253 |
use_full_chords=False
|
| 12254 |
):
|
| 12255 |
+
|
| 12256 |
+
if use_full_chords:
|
| 12257 |
+
CHORDS = ALL_CHORDS_FULL
|
| 12258 |
+
|
| 12259 |
+
else:
|
| 12260 |
+
CHORDS = ALL_CHORDS_SORTED
|
| 12261 |
+
|
| 12262 |
+
max_patch = max(0, min(128, max_patch))
|
| 12263 |
|
| 12264 |
+
escore_notes = [e for e in escore_notes if e[6] <= max_patch]
|
| 12265 |
|
| 12266 |
if escore_notes:
|
| 12267 |
|
|
|
|
| 12270 |
sig = []
|
| 12271 |
dsig = []
|
| 12272 |
|
| 12273 |
+
drums_offset = len(CHORDS) + 128
|
| 12274 |
|
| 12275 |
bad_chords_counter = 0
|
| 12276 |
|
|
|
|
| 12287 |
tones_chord = sorted(set([p % 12 for p in pitches]))
|
| 12288 |
|
| 12289 |
try:
|
| 12290 |
+
sig_token = CHORDS.index(tones_chord) + 128
|
| 12291 |
except:
|
| 12292 |
checked_tones_chord = check_and_fix_tones_chord(tones_chord, use_full_chords=use_full_chords)
|
| 12293 |
+
sig_token = CHORDS.index(checked_tones_chord) + 128
|
| 12294 |
bad_chords_counter += 1
|
| 12295 |
|
| 12296 |
elif len(pitches) == 1:
|
|
|
|
| 12447 |
|
| 12448 |
return None
|
| 12449 |
|
| 12450 |
+
###################################################################################
|
| 12451 |
+
|
| 12452 |
+
def escore_notes_even_timings(escore_notes, in_place=True):
|
| 12453 |
+
|
| 12454 |
+
if in_place:
|
| 12455 |
+
for e in escore_notes:
|
| 12456 |
+
if e[1] % 2 != 0:
|
| 12457 |
+
e[1] += 1
|
| 12458 |
+
|
| 12459 |
+
if e[2] % 2 != 0:
|
| 12460 |
+
e[2] += 1
|
| 12461 |
+
|
| 12462 |
+
return []
|
| 12463 |
+
|
| 12464 |
+
else:
|
| 12465 |
+
escore = copy.deepcopy(escore_notes)
|
| 12466 |
+
|
| 12467 |
+
for e in escore:
|
| 12468 |
+
if e[1] % 2 != 0:
|
| 12469 |
+
e[1] += 1
|
| 12470 |
+
|
| 12471 |
+
if e[2] % 2 != 0:
|
| 12472 |
+
e[2] += 1
|
| 12473 |
+
|
| 12474 |
+
return escore
|
| 12475 |
+
|
| 12476 |
+
###################################################################################
|
| 12477 |
+
|
| 12478 |
+
def both_chords(chord1, chord2, merge_threshold=2):
|
| 12479 |
+
|
| 12480 |
+
if len(chord1) > 1 and len(chord2) > 0 and chord2[0][1]-chord1[0][1] <= merge_threshold:
|
| 12481 |
+
return True
|
| 12482 |
+
|
| 12483 |
+
elif len(chord1) > 0 and len(chord2) > 1 and chord2[0][1]-chord1[0][1] <= merge_threshold:
|
| 12484 |
+
return True
|
| 12485 |
+
|
| 12486 |
+
else:
|
| 12487 |
+
return False
|
| 12488 |
+
|
| 12489 |
+
def merge_chords(chord1, chord2, sort_drums_last=False):
|
| 12490 |
+
|
| 12491 |
+
mchord = chord1
|
| 12492 |
+
|
| 12493 |
+
seen = []
|
| 12494 |
+
|
| 12495 |
+
for e in chord2:
|
| 12496 |
+
if tuple([e[4], e[6]]) not in seen:
|
| 12497 |
+
mchord.append(e)
|
| 12498 |
+
seen.append(tuple([e[4], e[6]]))
|
| 12499 |
+
|
| 12500 |
+
for e in mchord[1:]:
|
| 12501 |
+
e[1] = mchord[0][1]
|
| 12502 |
+
|
| 12503 |
+
if sort_drums_last:
|
| 12504 |
+
mchord.sort(key=lambda x: (x[4], x[6]) if x[6] != 128 else (x[6], -x[4]))
|
| 12505 |
+
|
| 12506 |
+
else:
|
| 12507 |
+
mchord.sort(key=lambda x: (x[4], x[6]))
|
| 12508 |
+
|
| 12509 |
+
return mchord
|
| 12510 |
+
|
| 12511 |
+
def merge_escore_notes(escore_notes, merge_threshold=2, sort_drums_last=False):
|
| 12512 |
+
|
| 12513 |
+
cscore = chordify_score([1000, escore_notes])
|
| 12514 |
+
|
| 12515 |
+
merged_chords = []
|
| 12516 |
+
merged_chord = cscore[0]
|
| 12517 |
+
|
| 12518 |
+
for i in range(1, len(cscore)):
|
| 12519 |
+
|
| 12520 |
+
cchord = cscore[i]
|
| 12521 |
+
|
| 12522 |
+
if both_chords(merged_chord, cchord, merge_threshold=merge_threshold):
|
| 12523 |
+
merged_chord = merge_chords(merged_chord, cchord, sort_drums_last=sort_drums_last)
|
| 12524 |
+
|
| 12525 |
+
else:
|
| 12526 |
+
merged_chords.append(merged_chord)
|
| 12527 |
+
merged_chord = cchord
|
| 12528 |
+
|
| 12529 |
+
return flatten(merged_chords)
|
| 12530 |
+
|
| 12531 |
+
###################################################################################
|
| 12532 |
+
|
| 12533 |
+
def solo_piano_escore_notes_tokenized(escore_notes,
|
| 12534 |
+
compress_start_times=True,
|
| 12535 |
+
encode_velocities=False,
|
| 12536 |
+
verbose=False
|
| 12537 |
+
):
|
| 12538 |
+
|
| 12539 |
+
if verbose:
|
| 12540 |
+
print('=' * 70)
|
| 12541 |
+
print('Encoding MIDI...')
|
| 12542 |
+
|
| 12543 |
+
sp_escore_notes = solo_piano_escore_notes(escore_notes)
|
| 12544 |
+
zscore = recalculate_score_timings(sp_escore_notes)
|
| 12545 |
+
dscore = delta_score_notes(zscore, timings_clip_value=127)
|
| 12546 |
+
|
| 12547 |
+
score = []
|
| 12548 |
+
|
| 12549 |
+
notes_counter = 0
|
| 12550 |
+
chords_counter = 1
|
| 12551 |
+
|
| 12552 |
+
for i, e in enumerate(dscore):
|
| 12553 |
+
|
| 12554 |
+
dtime = e[1]
|
| 12555 |
+
dur = e[2]
|
| 12556 |
+
ptc = e[4]
|
| 12557 |
+
vel = e[5]
|
| 12558 |
+
|
| 12559 |
+
if compress_start_times:
|
| 12560 |
+
|
| 12561 |
+
if i == 0:
|
| 12562 |
+
score.extend([0, dur+128, ptc+256])
|
| 12563 |
+
|
| 12564 |
+
if encode_velocities:
|
| 12565 |
+
score.append(vel+384)
|
| 12566 |
+
|
| 12567 |
+
else:
|
| 12568 |
+
if dtime == 0:
|
| 12569 |
+
score.extend([dur+128, ptc+256])
|
| 12570 |
+
|
| 12571 |
+
else:
|
| 12572 |
+
score.extend([dtime, dur+128, ptc+256])
|
| 12573 |
+
|
| 12574 |
+
if encode_velocities:
|
| 12575 |
+
score.append(vel+384)
|
| 12576 |
+
|
| 12577 |
+
if dtime != 0:
|
| 12578 |
+
chords_counter += 1
|
| 12579 |
+
|
| 12580 |
+
else:
|
| 12581 |
+
score.extend([dtime, dur+128, ptc+256])
|
| 12582 |
+
|
| 12583 |
+
if encode_velocities:
|
| 12584 |
+
score.append(vel+384)
|
| 12585 |
+
|
| 12586 |
+
if dtime != 0:
|
| 12587 |
+
chords_counter += 1
|
| 12588 |
+
|
| 12589 |
+
notes_counter += 1
|
| 12590 |
+
|
| 12591 |
+
if verbose:
|
| 12592 |
+
print('Done!')
|
| 12593 |
+
print('=' * 70)
|
| 12594 |
+
|
| 12595 |
+
print('Source MIDI composition has', len(zscore), 'notes')
|
| 12596 |
+
print('Source MIDI composition has', len([d[1] for d in dscore if d[1] !=0 ])+1, 'chords')
|
| 12597 |
+
print('-' * 70)
|
| 12598 |
+
print('Encoded sequence has', notes_counter, 'pitches')
|
| 12599 |
+
print('Encoded sequence has', chords_counter, 'chords')
|
| 12600 |
+
print('-' * 70)
|
| 12601 |
+
print('Final encoded sequence has', len(score), 'tokens')
|
| 12602 |
+
print('=' * 70)
|
| 12603 |
+
|
| 12604 |
+
return score
|
| 12605 |
+
|
| 12606 |
+
###################################################################################
|
| 12607 |
+
|
| 12608 |
+
def equalize_closest_elements_dynamic(seq,
|
| 12609 |
+
min_val=128,
|
| 12610 |
+
max_val=256,
|
| 12611 |
+
splitting_factor=1.5,
|
| 12612 |
+
tightness_threshold=0.15
|
| 12613 |
+
):
|
| 12614 |
+
|
| 12615 |
+
candidates = [(i, x) for i, x in enumerate(seq) if min_val <= x <= max_val]
|
| 12616 |
+
|
| 12617 |
+
if len(candidates) < 2:
|
| 12618 |
+
return seq.copy()
|
| 12619 |
+
|
| 12620 |
+
sorted_candidates = sorted(candidates, key=lambda pair: pair[1])
|
| 12621 |
+
candidate_values = [val for _, val in sorted_candidates]
|
| 12622 |
+
|
| 12623 |
+
differences = [candidate_values[i+1] - candidate_values[i] for i in range(len(candidate_values)-1)]
|
| 12624 |
+
|
| 12625 |
+
def median(lst):
|
| 12626 |
+
|
| 12627 |
+
n = len(lst)
|
| 12628 |
+
sorted_lst = sorted(lst)
|
| 12629 |
+
mid = n // 2
|
| 12630 |
+
|
| 12631 |
+
if n % 2 == 0:
|
| 12632 |
+
return (sorted_lst[mid - 1] + sorted_lst[mid]) / 2.0
|
| 12633 |
+
|
| 12634 |
+
else:
|
| 12635 |
+
return sorted_lst[mid]
|
| 12636 |
+
|
| 12637 |
+
med_diff = median(differences)
|
| 12638 |
+
|
| 12639 |
+
split_indices = [i for i, diff in enumerate(differences) if diff > splitting_factor * med_diff]
|
| 12640 |
+
|
| 12641 |
+
clusters = []
|
| 12642 |
+
|
| 12643 |
+
if split_indices:
|
| 12644 |
+
start = 0
|
| 12645 |
+
for split_index in split_indices:
|
| 12646 |
+
clusters.append(sorted_candidates[start:split_index+1])
|
| 12647 |
+
start = split_index + 1
|
| 12648 |
+
clusters.append(sorted_candidates[start:])
|
| 12649 |
+
|
| 12650 |
+
else:
|
| 12651 |
+
clusters = [sorted_candidates]
|
| 12652 |
+
|
| 12653 |
+
|
| 12654 |
+
valid_clusters = [cluster for cluster in clusters if len(cluster) >= 2]
|
| 12655 |
+
if not valid_clusters:
|
| 12656 |
+
return seq.copy()
|
| 12657 |
+
|
| 12658 |
+
def cluster_spread(cluster):
|
| 12659 |
+
values = [val for (_, val) in cluster]
|
| 12660 |
+
return max(values) - min(values)
|
| 12661 |
+
|
| 12662 |
+
valid_clusters.sort(key=lambda cluster: (len(cluster), -cluster_spread(cluster)), reverse=True)
|
| 12663 |
+
selected_cluster = valid_clusters[0]
|
| 12664 |
+
|
| 12665 |
+
allowed_range_width = max_val - min_val
|
| 12666 |
+
spread = cluster_spread(selected_cluster)
|
| 12667 |
+
ratio = spread / allowed_range_width
|
| 12668 |
+
|
| 12669 |
+
if ratio > tightness_threshold:
|
| 12670 |
+
return seq.copy()
|
| 12671 |
+
|
| 12672 |
+
cluster_values = [val for (_, val) in selected_cluster]
|
| 12673 |
+
equal_value = sum(cluster_values) // len(cluster_values)
|
| 12674 |
+
|
| 12675 |
+
|
| 12676 |
+
result = list(seq)
|
| 12677 |
+
for idx, _ in selected_cluster:
|
| 12678 |
+
result[idx] = equal_value
|
| 12679 |
+
|
| 12680 |
+
return result
|
| 12681 |
+
|
| 12682 |
+
###################################################################################
|
| 12683 |
+
|
| 12684 |
+
def chunk_list(lst, chunk_size):
|
| 12685 |
+
return [lst[i:i + chunk_size] for i in range(0, len(lst), chunk_size)]
|
| 12686 |
+
|
| 12687 |
+
###################################################################################
|
| 12688 |
+
|
| 12689 |
+
def compress_tokens_sequence(seq,
|
| 12690 |
+
min_val=128,
|
| 12691 |
+
max_val=256,
|
| 12692 |
+
group_size=2,
|
| 12693 |
+
splitting_factor=1.5,
|
| 12694 |
+
tightness_threshold=0.15
|
| 12695 |
+
):
|
| 12696 |
+
|
| 12697 |
+
comp_seq = equalize_closest_elements_dynamic(seq,
|
| 12698 |
+
min_val,
|
| 12699 |
+
max_val,
|
| 12700 |
+
splitting_factor=splitting_factor,
|
| 12701 |
+
tightness_threshold=tightness_threshold
|
| 12702 |
+
)
|
| 12703 |
+
|
| 12704 |
+
seq_split = sorted(chunk_list(comp_seq, group_size), key=lambda x: (-x[0], -x[1]))
|
| 12705 |
+
|
| 12706 |
+
seq_grouped = [[[k]] + [vv[1:] for vv in v] for k, v in groupby(seq_split, key=lambda x: x[0])]
|
| 12707 |
+
|
| 12708 |
+
return flatten(flatten(sorted(seq_grouped, key=lambda x: -x[1][0])))
|
| 12709 |
+
|
| 12710 |
+
###################################################################################
|
| 12711 |
+
|
| 12712 |
+
def merge_adjacent_pairs(values_counts):
|
| 12713 |
+
|
| 12714 |
+
merged = []
|
| 12715 |
+
i = 0
|
| 12716 |
+
|
| 12717 |
+
while i < len(values_counts):
|
| 12718 |
+
|
| 12719 |
+
if i < len(values_counts) - 1:
|
| 12720 |
+
value1, count1 = values_counts[i]
|
| 12721 |
+
value2, count2 = values_counts[i + 1]
|
| 12722 |
+
|
| 12723 |
+
if value2 - value1 == 1:
|
| 12724 |
+
if count2 > count1:
|
| 12725 |
+
merged_value = value2
|
| 12726 |
+
|
| 12727 |
+
else:
|
| 12728 |
+
merged_value = value1
|
| 12729 |
+
|
| 12730 |
+
merged_count = count1 + count2
|
| 12731 |
+
merged.append((merged_value, merged_count))
|
| 12732 |
+
|
| 12733 |
+
i += 2
|
| 12734 |
+
|
| 12735 |
+
continue
|
| 12736 |
+
|
| 12737 |
+
merged.append(values_counts[i])
|
| 12738 |
+
|
| 12739 |
+
i += 1
|
| 12740 |
+
|
| 12741 |
+
return merged
|
| 12742 |
+
|
| 12743 |
+
###################################################################################
|
| 12744 |
+
|
| 12745 |
+
def merge_escore_notes_start_times(escore_notes, num_merges=1):
|
| 12746 |
+
|
| 12747 |
+
new_dscore = delta_score_notes(escore_notes)
|
| 12748 |
+
|
| 12749 |
+
times = [e[1] for e in new_dscore if e[1] != 0]
|
| 12750 |
+
times_counts = sorted(Counter(times).most_common())
|
| 12751 |
+
|
| 12752 |
+
prev_counts = []
|
| 12753 |
+
new_times_counts = times_counts
|
| 12754 |
+
|
| 12755 |
+
mcount = 0
|
| 12756 |
+
|
| 12757 |
+
while prev_counts != new_times_counts:
|
| 12758 |
+
prev_counts = new_times_counts
|
| 12759 |
+
new_times_counts = merge_adjacent_pairs(new_times_counts)
|
| 12760 |
+
|
| 12761 |
+
mcount += 1
|
| 12762 |
+
|
| 12763 |
+
if mcount == num_merges:
|
| 12764 |
+
break
|
| 12765 |
+
|
| 12766 |
+
gtimes = [r[0] for r in new_times_counts]
|
| 12767 |
+
|
| 12768 |
+
for e in new_dscore:
|
| 12769 |
+
if e[1] > 0:
|
| 12770 |
+
e[1] = find_closest_value(gtimes, e[1])[0]
|
| 12771 |
+
e[2] -= num_merges
|
| 12772 |
+
|
| 12773 |
+
return delta_score_to_abs_score(new_dscore)
|
| 12774 |
+
|
| 12775 |
+
###################################################################################
|
| 12776 |
+
|
| 12777 |
+
def multi_instrumental_escore_notes_tokenized(escore_notes, compress_seq=False):
|
| 12778 |
+
|
| 12779 |
+
melody_chords = []
|
| 12780 |
+
|
| 12781 |
+
pe = escore_notes[0]
|
| 12782 |
+
|
| 12783 |
+
for i, e in enumerate(escore_notes):
|
| 12784 |
+
|
| 12785 |
+
dtime = max(0, min(255, e[1]-pe[1]))
|
| 12786 |
+
|
| 12787 |
+
dur = max(0, min(255, e[2]))
|
| 12788 |
+
|
| 12789 |
+
cha = max(0, min(15, e[3]))
|
| 12790 |
+
|
| 12791 |
+
if cha == 9:
|
| 12792 |
+
pat = 128
|
| 12793 |
+
|
| 12794 |
+
else:
|
| 12795 |
+
pat = max(0, min(127, e[6]))
|
| 12796 |
+
|
| 12797 |
+
ptc = max(0, min(127, e[4]))
|
| 12798 |
+
|
| 12799 |
+
vel = max(8, min(127, e[5]))
|
| 12800 |
+
velocity = round(vel / 15)-1
|
| 12801 |
+
|
| 12802 |
+
dur_vel = (8 * dur) + velocity
|
| 12803 |
+
pat_ptc = (129 * pat) + ptc
|
| 12804 |
+
|
| 12805 |
+
if compress_seq:
|
| 12806 |
+
if dtime != 0 or i == 0:
|
| 12807 |
+
melody_chords.extend([dtime, dur_vel+256, pat_ptc+2304])
|
| 12808 |
+
|
| 12809 |
+
else:
|
| 12810 |
+
melody_chords.extend([dur_vel+256, pat_ptc+2304])
|
| 12811 |
+
|
| 12812 |
+
else:
|
| 12813 |
+
melody_chords.extend([dtime, dur_vel+256, pat_ptc+2304])
|
| 12814 |
+
|
| 12815 |
+
pe = e
|
| 12816 |
+
|
| 12817 |
+
return melody_chords
|
| 12818 |
+
|
| 12819 |
+
###################################################################################
|
| 12820 |
+
|
| 12821 |
+
def merge_counts(data, return_lists=True):
|
| 12822 |
+
|
| 12823 |
+
merged = defaultdict(int)
|
| 12824 |
+
|
| 12825 |
+
for value, count in data:
|
| 12826 |
+
merged[value] += count
|
| 12827 |
+
|
| 12828 |
+
if return_lists:
|
| 12829 |
+
return [[k, v] for k, v in merged.items()]
|
| 12830 |
+
|
| 12831 |
+
else:
|
| 12832 |
+
return list(merged.items())
|
| 12833 |
+
|
| 12834 |
+
###################################################################################
|
| 12835 |
+
|
| 12836 |
+
def convert_escore_notes_pitches_chords_signature(signature, convert_to_full_chords=True):
|
| 12837 |
+
|
| 12838 |
+
if convert_to_full_chords:
|
| 12839 |
+
SRC_CHORDS = ALL_CHORDS_SORTED
|
| 12840 |
+
TRG_CHORDS = ALL_CHORDS_FULL
|
| 12841 |
+
|
| 12842 |
+
else:
|
| 12843 |
+
SRC_CHORDS = ALL_CHORDS_FULL
|
| 12844 |
+
TRG_CHORDS = ALL_CHORDS_SORTED
|
| 12845 |
+
|
| 12846 |
+
cdiff = len(TRG_CHORDS) - len(SRC_CHORDS)
|
| 12847 |
+
|
| 12848 |
+
pitches_counts = [c for c in signature if -1 < c[0] < 128]
|
| 12849 |
+
chords_counts = [c for c in signature if 127 < c[0] < len(SRC_CHORDS)+128]
|
| 12850 |
+
drums_counts = [[c[0]-cdiff, c[1]] for c in signature if len(SRC_CHORDS)+127 < c[0] < len(SRC_CHORDS)+256]
|
| 12851 |
+
bad_chords_count = [c for c in signature if c[0] == -1]
|
| 12852 |
+
|
| 12853 |
+
new_chords_counts = []
|
| 12854 |
+
|
| 12855 |
+
for c in chords_counts:
|
| 12856 |
+
tones_chord = SRC_CHORDS[c[0]-128]
|
| 12857 |
+
|
| 12858 |
+
if tones_chord not in TRG_CHORDS:
|
| 12859 |
+
tones_chord = check_and_fix_tones_chord(tones_chord, use_full_chords=convert_to_full_chords)
|
| 12860 |
+
bad_chords_count[0][1] += 1
|
| 12861 |
+
|
| 12862 |
+
new_chords_counts.append([TRG_CHORDS.index(tones_chord)+128, c[1]])
|
| 12863 |
+
|
| 12864 |
+
return pitches_counts + merge_counts(new_chords_counts) + drums_counts + bad_chords_count
|
| 12865 |
+
|
| 12866 |
+
###################################################################################
|
| 12867 |
+
|
| 12868 |
+
print('Module loaded!')
|
| 12869 |
+
print('=' * 70)
|
| 12870 |
+
print('Enjoy! :)')
|
| 12871 |
+
print('=' * 70)
|
| 12872 |
+
|
| 12873 |
###################################################################################
|
| 12874 |
# This is the end of the TMIDI X Python module
|
| 12875 |
###################################################################################
|