Spaces:
Running
Running
Upload TMIDIX.py
Browse files
TMIDIX.py
CHANGED
|
@@ -1656,13 +1656,15 @@ def Tegridy_SONG_to_MIDI_Converter(SONG,
|
|
| 1656 |
|
| 1657 |
###################################################################################
|
| 1658 |
|
| 1659 |
-
def Tegridy_ms_SONG_to_MIDI_Converter(
|
| 1660 |
output_signature = 'Tegridy TMIDI Module',
|
| 1661 |
track_name = 'Composition Track',
|
| 1662 |
list_of_MIDI_patches = [0, 24, 32, 40, 42, 46, 56, 71, 73, 0, 0, 0, 0, 0, 0, 0],
|
| 1663 |
output_file_name = 'TMIDI-Composition',
|
| 1664 |
text_encoding='ISO-8859-1',
|
| 1665 |
-
|
|
|
|
|
|
|
| 1666 |
|
| 1667 |
'''Tegridy milisecond SONG to MIDI Converter
|
| 1668 |
|
|
@@ -1672,12 +1674,14 @@ def Tegridy_ms_SONG_to_MIDI_Converter(SONG,
|
|
| 1672 |
List of 16 MIDI patch numbers for output MIDI. Def. is MuseNet compatible patches.
|
| 1673 |
Output file name w/o .mid extension.
|
| 1674 |
Optional text encoding if you are working with text_events/lyrics. This is especially useful for Karaoke. Please note that anything but ISO-8859-1 is a non-standard way of encoding text_events according to MIDI specs.
|
|
|
|
|
|
|
| 1675 |
|
| 1676 |
Output: MIDI File
|
| 1677 |
Detailed MIDI stats
|
| 1678 |
|
| 1679 |
Project Los Angeles
|
| 1680 |
-
Tegridy Code
|
| 1681 |
|
| 1682 |
if verbose:
|
| 1683 |
print('Converting to MIDI. Please stand-by...')
|
|
@@ -1705,6 +1709,14 @@ def Tegridy_ms_SONG_to_MIDI_Converter(SONG,
|
|
| 1705 |
['patch_change', 0, 15, list_of_MIDI_patches[15]],
|
| 1706 |
['track_name', 0, bytes(track_name, text_encoding)]]
|
| 1707 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1708 |
output = output_header + [patch_list + SONG]
|
| 1709 |
|
| 1710 |
midi_data = score2midi(output, text_encoding)
|
|
@@ -4710,8 +4722,8 @@ def extract_melody(chordified_enhanced_score,
|
|
| 4710 |
if e[4] < melody_range[0]:
|
| 4711 |
e[4] = (e[4] % 12) + melody_range[0]
|
| 4712 |
|
| 4713 |
-
if e[4]
|
| 4714 |
-
e[4] = (e[4] % 12) + melody_range[1]
|
| 4715 |
|
| 4716 |
return fix_monophonic_score_durations(melody_score)
|
| 4717 |
|
|
@@ -4793,6 +4805,161 @@ ALL_CHORDS_SORTED = [[0], [0, 2], [0, 3], [0, 4], [0, 2, 4], [0, 5], [0, 2, 5],
|
|
| 4793 |
|
| 4794 |
###################################################################################
|
| 4795 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4796 |
# This is the end of the TMIDI X Python module
|
| 4797 |
|
| 4798 |
###################################################################################
|
|
|
|
| 1656 |
|
| 1657 |
###################################################################################
|
| 1658 |
|
| 1659 |
+
def Tegridy_ms_SONG_to_MIDI_Converter(ms_SONG,
|
| 1660 |
output_signature = 'Tegridy TMIDI Module',
|
| 1661 |
track_name = 'Composition Track',
|
| 1662 |
list_of_MIDI_patches = [0, 24, 32, 40, 42, 46, 56, 71, 73, 0, 0, 0, 0, 0, 0, 0],
|
| 1663 |
output_file_name = 'TMIDI-Composition',
|
| 1664 |
text_encoding='ISO-8859-1',
|
| 1665 |
+
timings_multiplier=1,
|
| 1666 |
+
verbose=True
|
| 1667 |
+
):
|
| 1668 |
|
| 1669 |
'''Tegridy milisecond SONG to MIDI Converter
|
| 1670 |
|
|
|
|
| 1674 |
List of 16 MIDI patch numbers for output MIDI. Def. is MuseNet compatible patches.
|
| 1675 |
Output file name w/o .mid extension.
|
| 1676 |
Optional text encoding if you are working with text_events/lyrics. This is especially useful for Karaoke. Please note that anything but ISO-8859-1 is a non-standard way of encoding text_events according to MIDI specs.
|
| 1677 |
+
Optional timings multiplier
|
| 1678 |
+
Optional verbose output
|
| 1679 |
|
| 1680 |
Output: MIDI File
|
| 1681 |
Detailed MIDI stats
|
| 1682 |
|
| 1683 |
Project Los Angeles
|
| 1684 |
+
Tegridy Code 2024'''
|
| 1685 |
|
| 1686 |
if verbose:
|
| 1687 |
print('Converting to MIDI. Please stand-by...')
|
|
|
|
| 1709 |
['patch_change', 0, 15, list_of_MIDI_patches[15]],
|
| 1710 |
['track_name', 0, bytes(track_name, text_encoding)]]
|
| 1711 |
|
| 1712 |
+
SONG = copy.deepcopy(ms_SONG)
|
| 1713 |
+
|
| 1714 |
+
if timings_multiplier != 1:
|
| 1715 |
+
for S in SONG:
|
| 1716 |
+
S[1] = S[1] * timings_multiplier
|
| 1717 |
+
if S[0] == 'note':
|
| 1718 |
+
S[2] = S[2] * timings_multiplier
|
| 1719 |
+
|
| 1720 |
output = output_header + [patch_list + SONG]
|
| 1721 |
|
| 1722 |
midi_data = score2midi(output, text_encoding)
|
|
|
|
| 4722 |
if e[4] < melody_range[0]:
|
| 4723 |
e[4] = (e[4] % 12) + melody_range[0]
|
| 4724 |
|
| 4725 |
+
if e[4] >= melody_range[1]:
|
| 4726 |
+
e[4] = (e[4] % 12) + (melody_range[1]-12)
|
| 4727 |
|
| 4728 |
return fix_monophonic_score_durations(melody_score)
|
| 4729 |
|
|
|
|
| 4805 |
|
| 4806 |
###################################################################################
|
| 4807 |
|
| 4808 |
+
MIDI_Instruments_Families = {
|
| 4809 |
+
0: 'Piano Family',
|
| 4810 |
+
1: 'Chromatic Percussion Family',
|
| 4811 |
+
2: 'Organ Family',
|
| 4812 |
+
3: 'Guitar Family',
|
| 4813 |
+
4: 'Bass Family',
|
| 4814 |
+
5: 'Strings Family',
|
| 4815 |
+
6: 'Ensemble Family',
|
| 4816 |
+
7: 'Brass Family',
|
| 4817 |
+
8: 'Reed Family',
|
| 4818 |
+
9: 'Pipe Family',
|
| 4819 |
+
10: 'Synth Lead Family',
|
| 4820 |
+
11: 'Synth Pad Family',
|
| 4821 |
+
12: 'Synth Effects Family',
|
| 4822 |
+
13: 'Ethnic Family',
|
| 4823 |
+
14: 'Percussive Family',
|
| 4824 |
+
15: 'Sound Effects Family',
|
| 4825 |
+
16: 'Drums Family',
|
| 4826 |
+
-1: 'Unknown Family',
|
| 4827 |
+
}
|
| 4828 |
+
|
| 4829 |
+
###################################################################################
|
| 4830 |
+
|
| 4831 |
+
def patch_to_instrument_family(MIDI_patch, drums_patch=128):
|
| 4832 |
+
|
| 4833 |
+
if 0 <= MIDI_patch < 128:
|
| 4834 |
+
return MIDI_patch // 8, MIDI_Instruments_Families[MIDI_patch // 8]
|
| 4835 |
+
|
| 4836 |
+
elif MIDI_patch == drums_patch:
|
| 4837 |
+
return MIDI_patch // 8, MIDI_Instruments_Families[16]
|
| 4838 |
+
|
| 4839 |
+
else:
|
| 4840 |
+
return -1, MIDI_Instruments_Families[-1]
|
| 4841 |
+
|
| 4842 |
+
###################################################################################
|
| 4843 |
+
|
| 4844 |
+
def patch_list_from_enhanced_score_notes(enhanced_score_notes,
|
| 4845 |
+
default_patch=0,
|
| 4846 |
+
drums_patch=9,
|
| 4847 |
+
verbose=False
|
| 4848 |
+
):
|
| 4849 |
+
|
| 4850 |
+
patches = [-1] * 16
|
| 4851 |
+
|
| 4852 |
+
for idx, e in enumerate(enhanced_score_notes):
|
| 4853 |
+
if e[3] != 9:
|
| 4854 |
+
if patches[e[3]] == -1:
|
| 4855 |
+
patches[e[3]] = e[6]
|
| 4856 |
+
else:
|
| 4857 |
+
if patches[e[3]] != e[6]:
|
| 4858 |
+
if e[6] in patches:
|
| 4859 |
+
e[3] = patches.index(e[6])
|
| 4860 |
+
else:
|
| 4861 |
+
if -1 in patches:
|
| 4862 |
+
patches[patches.index(-1)] = e[6]
|
| 4863 |
+
else:
|
| 4864 |
+
patches[-1] = e[6]
|
| 4865 |
+
|
| 4866 |
+
if verbose:
|
| 4867 |
+
print('=' * 70)
|
| 4868 |
+
print('WARNING! Composition has more than 15 patches!')
|
| 4869 |
+
print('Conflict note number:', idx)
|
| 4870 |
+
print('Conflict channel number:', e[3])
|
| 4871 |
+
print('Conflict patch number:', e[6])
|
| 4872 |
+
|
| 4873 |
+
patches = [p if p != -1 else default_patch for p in patches]
|
| 4874 |
+
|
| 4875 |
+
patches[9] = drums_patch
|
| 4876 |
+
|
| 4877 |
+
if verbose:
|
| 4878 |
+
print('=' * 70)
|
| 4879 |
+
print('Composition patches')
|
| 4880 |
+
print('=' * 70)
|
| 4881 |
+
for c, p in enumerate(patches):
|
| 4882 |
+
print('Cha', str(c).zfill(2), '---', str(p).zfill(3), Number2patch[p])
|
| 4883 |
+
print('=' * 70)
|
| 4884 |
+
|
| 4885 |
+
return patches
|
| 4886 |
+
|
| 4887 |
+
###################################################################################
|
| 4888 |
+
|
| 4889 |
+
def patch_enhanced_score_notes(enhanced_score_notes,
|
| 4890 |
+
default_patch=0,
|
| 4891 |
+
drums_patch=9,
|
| 4892 |
+
verbose=False
|
| 4893 |
+
):
|
| 4894 |
+
|
| 4895 |
+
#===========================================================================
|
| 4896 |
+
|
| 4897 |
+
enhanced_score_notes_with_patch_changes = []
|
| 4898 |
+
|
| 4899 |
+
patches = [-1] * 16
|
| 4900 |
+
|
| 4901 |
+
overflow_idx = -1
|
| 4902 |
+
|
| 4903 |
+
for idx, e in enumerate(enhanced_score_notes):
|
| 4904 |
+
if e[3] != 9:
|
| 4905 |
+
if patches[e[3]] == -1:
|
| 4906 |
+
patches[e[3]] = e[6]
|
| 4907 |
+
else:
|
| 4908 |
+
if patches[e[3]] != e[6]:
|
| 4909 |
+
if e[6] in patches:
|
| 4910 |
+
e[3] = patches.index(e[6])
|
| 4911 |
+
else:
|
| 4912 |
+
if -1 in patches:
|
| 4913 |
+
patches[patches.index(-1)] = e[6]
|
| 4914 |
+
else:
|
| 4915 |
+
overflow_idx = idx
|
| 4916 |
+
break
|
| 4917 |
+
|
| 4918 |
+
enhanced_score_notes_with_patch_changes.append(e)
|
| 4919 |
+
|
| 4920 |
+
#===========================================================================
|
| 4921 |
+
|
| 4922 |
+
overflow_patches = []
|
| 4923 |
+
|
| 4924 |
+
if overflow_idx != -1:
|
| 4925 |
+
for idx, e in enumerate(enhanced_score_notes[overflow_idx:]):
|
| 4926 |
+
if e[3] != 9:
|
| 4927 |
+
if e[6] not in patches:
|
| 4928 |
+
if e[6] not in overflow_patches:
|
| 4929 |
+
overflow_patches.append(e[6])
|
| 4930 |
+
enhanced_score_notes_with_patch_changes.append(['patch_change', e[1], e[3], e[6]])
|
| 4931 |
+
else:
|
| 4932 |
+
e[3] = patches.index(e[6])
|
| 4933 |
+
|
| 4934 |
+
enhanced_score_notes_with_patch_changes.append(e)
|
| 4935 |
+
|
| 4936 |
+
#===========================================================================
|
| 4937 |
+
|
| 4938 |
+
patches = [p if p != -1 else default_patch for p in patches]
|
| 4939 |
+
|
| 4940 |
+
patches[9] = drums_patch
|
| 4941 |
+
|
| 4942 |
+
#===========================================================================
|
| 4943 |
+
|
| 4944 |
+
if verbose:
|
| 4945 |
+
print('=' * 70)
|
| 4946 |
+
print('Composition patches')
|
| 4947 |
+
print('=' * 70)
|
| 4948 |
+
for c, p in enumerate(patches):
|
| 4949 |
+
print('Cha', str(c).zfill(2), '---', str(p).zfill(3), Number2patch[p])
|
| 4950 |
+
print('=' * 70)
|
| 4951 |
+
|
| 4952 |
+
if overflow_patches:
|
| 4953 |
+
print('Extra composition patches')
|
| 4954 |
+
print('=' * 70)
|
| 4955 |
+
for c, p in enumerate(overflow_patches):
|
| 4956 |
+
print(str(p).zfill(3), Number2patch[p])
|
| 4957 |
+
print('=' * 70)
|
| 4958 |
+
|
| 4959 |
+
return enhanced_score_notes_with_patch_changes, patches, overflow_patches
|
| 4960 |
+
|
| 4961 |
+
###################################################################################
|
| 4962 |
+
|
| 4963 |
# This is the end of the TMIDI X Python module
|
| 4964 |
|
| 4965 |
###################################################################################
|