asigalov61 commited on
Commit
42df0c2
·
verified ·
1 Parent(s): 2e2e44f

Upload TMIDIX.py

Browse files
Files changed (1) hide show
  1. TMIDIX.py +971 -50
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 1437
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
- # http://www.apache.org/licenses/LICENSE-2.0
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]-1
3860
  else:
3861
  note_dur = note[2]
3862
 
3863
  new_note = [note[0], note[1], note_dur] + note[3:]
3864
-
3865
- fixed_score.append(new_note)
3866
-
3867
- fixed_score.append(monophonic_score[-1])
 
 
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]-1
3878
  else:
3879
  note_dur = note[1]
3880
-
3881
  new_note = [note[0], note_dur] + note[2:]
3882
-
3883
- fixed_score.append(new_note)
3884
-
3885
- fixed_score.append(monophonic_score[-1])
 
 
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
- patches_to_analyze=list(range(129)),
4148
- return_score_analysis=False,
4149
- return_enhanced_score=False,
4150
- return_enhanced_score_notes=False,
4151
- return_enhanced_monophonic_melody=False,
4152
- return_chordified_enhanced_score=False,
4153
- return_chordified_enhanced_score_with_lyrics=False,
4154
- return_score_tones_chords=False,
4155
- return_text_and_lyric_events=False
 
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(escore_notes)
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(escore_notes, bar_time, nidx, bcount)
6710
 
6711
  if next_bar:
6712
-
6713
- gescore_notes = escore_notes[nidx:next_bar[1]]
6714
  else:
6715
- gescore_notes = escore_notes[nidx:]
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 = escore_notes[next_bar[1]][1]-escore_notes[next_bar[1]-1][1]
 
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), total=len(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
- for dataset_addr in tqdm.tqdm(datasets_paths, disable=not verbose):
11312
- for dirpath, dirnames, filenames in os.walk(dataset_addr):
11313
- for file in filenames:
11314
- if file not in filez_set and file.endswith(files_exts):
11315
- filez_set[os.path.join(dirpath, file)] = None
11316
-
11317
- filez = list(filez_set.keys())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- return filez
 
 
 
 
 
 
 
 
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 % 129]
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 = 321 + 128
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 = ALL_CHORDS_SORTED.index(tones_chord) + 128
12194
  except:
12195
  checked_tones_chord = check_and_fix_tones_chord(tones_chord, use_full_chords=use_full_chords)
12196
- sig_token = ALL_CHORDS_SORTED.index(checked_tones_chord) + 128
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
  ###################################################################################