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 | 
             
            ###################################################################################
         | 
