asigalov61
commited on
Commit
•
77240fe
1
Parent(s):
4490a32
Upload TMIDIX.py
Browse files
TMIDIX.py
CHANGED
@@ -174,7 +174,7 @@ Translates a "score" into MIDI, using score2opus() then opus2midi()
|
|
174 |
|
175 |
#--------------------------- Decoding stuff ------------------------
|
176 |
|
177 |
-
def midi2opus(midi=b''):
|
178 |
r'''Translates MIDI into a "opus". For a description of the
|
179 |
"opus" format, see opus2midi()
|
180 |
'''
|
@@ -186,7 +186,8 @@ def midi2opus(midi=b''):
|
|
186 |
if id != b'MThd':
|
187 |
_warn("midi2opus: midi starts with "+str(id)+" instead of 'MThd'")
|
188 |
_clean_up_warnings()
|
189 |
-
|
|
|
190 |
[length, format, tracks_expected, ticks] = struct.unpack(
|
191 |
'>IHHH', bytes(my_midi[4:14]))
|
192 |
if length != 6:
|
@@ -266,27 +267,38 @@ see opus2midi() and score2opus().
|
|
266 |
_clean_up_warnings()
|
267 |
return score
|
268 |
|
269 |
-
def midi2score(midi=b''):
|
270 |
r'''
|
271 |
Translates MIDI into a "score", using midi2opus() then opus2score()
|
272 |
'''
|
273 |
-
return opus2score(midi2opus(midi))
|
274 |
|
275 |
-
def midi2ms_score(midi=b''):
|
276 |
r'''
|
277 |
Translates MIDI into a "score" with one beat per second and one
|
278 |
tick per millisecond, using midi2opus() then to_millisecs()
|
279 |
then opus2score()
|
280 |
'''
|
281 |
-
return opus2score(to_millisecs(midi2opus(midi)))
|
282 |
-
|
283 |
-
def midi2single_track_ms_score(
|
|
|
|
|
|
|
|
|
|
|
284 |
r'''
|
285 |
Translates MIDI into a single track "score" with 16 instruments and one beat per second and one
|
286 |
tick per millisecond
|
287 |
'''
|
288 |
|
289 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
|
291 |
if recalculate_channels:
|
292 |
|
@@ -1736,7 +1748,9 @@ def plot_ms_SONG(ms_song,
|
|
1736 |
drums_color_num=128,
|
1737 |
plot_size=(11,4),
|
1738 |
note_height = 0.75,
|
1739 |
-
show_grid_lines=False
|
|
|
|
|
1740 |
|
1741 |
'''Tegridy ms SONG plotter/vizualizer'''
|
1742 |
|
@@ -1784,15 +1798,16 @@ def plot_ms_SONG(ms_song,
|
|
1784 |
if show_grid_lines:
|
1785 |
ax.grid(color='white')
|
1786 |
|
1787 |
-
plt.xlabel('Time', c='black')
|
1788 |
plt.ylabel('Pitch', c='black')
|
1789 |
|
1790 |
plt.title(plot_title)
|
1791 |
|
1792 |
-
|
1793 |
-
|
1794 |
-
|
1795 |
-
|
|
|
1796 |
###################################################################################
|
1797 |
|
1798 |
def Tegridy_SONG_to_Full_MIDI_Converter(SONG,
|
@@ -3782,19 +3797,41 @@ def fix_monophonic_score_durations(monophonic_score):
|
|
3782 |
|
3783 |
fixed_score = []
|
3784 |
|
3785 |
-
|
3786 |
-
note = monophonic_score[i]
|
3787 |
|
3788 |
-
|
|
|
3789 |
|
3790 |
-
|
3791 |
-
|
3792 |
-
|
3793 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3794 |
|
3795 |
-
|
|
|
3796 |
|
3797 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3798 |
|
3799 |
return fixed_score
|
3800 |
|
@@ -4058,10 +4095,10 @@ def tones_chord_to_pitches(tones_chord, base_pitch=60):
|
|
4058 |
|
4059 |
def advanced_score_processor(raw_score,
|
4060 |
patches_to_analyze=list(range(129)),
|
4061 |
-
return_score_analysis=
|
4062 |
return_enhanced_score=False,
|
4063 |
return_enhanced_score_notes=False,
|
4064 |
-
return_enhanced_monophonic_melody=False,
|
4065 |
return_chordified_enhanced_score=False,
|
4066 |
return_chordified_enhanced_score_with_lyrics=False,
|
4067 |
return_score_tones_chords=False,
|
@@ -4329,30 +4366,42 @@ def replace_bad_tones_chord(bad_tones_chord):
|
|
4329 |
###################################################################################
|
4330 |
|
4331 |
def check_and_fix_chord(chord,
|
4332 |
-
channel_index=3,
|
4333 |
-
pitch_index=4
|
|
|
4334 |
|
4335 |
-
|
4336 |
-
chord_drums = [x for x in chord if x[channel_index] == 9]
|
4337 |
-
chord_pitches = [x[pitch_index] for x in chord_notes]
|
4338 |
-
tones_chord = sorted(set([x % 12 for x in chord_pitches]))
|
4339 |
-
good_tones_chord = replace_bad_tones_chord(tones_chord)[0]
|
4340 |
-
bad_tones = list(set(tones_chord) ^ set(good_tones_chord))
|
4341 |
|
4342 |
-
|
|
|
4343 |
|
4344 |
-
|
4345 |
|
4346 |
-
|
4347 |
-
if (c[pitch_index] % 12) not in bad_tones:
|
4348 |
-
fixed_chord.append(c)
|
4349 |
|
4350 |
-
|
|
|
|
|
4351 |
|
4352 |
-
|
4353 |
|
4354 |
-
|
4355 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4356 |
|
4357 |
###################################################################################
|
4358 |
|
@@ -4541,6 +4590,64 @@ def check_and_fix_tones_chord(tones_chord):
|
|
4541 |
|
4542 |
###################################################################################
|
4543 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4544 |
def create_similarity_matrix(list_of_values, matrix_length=0):
|
4545 |
|
4546 |
counts = Counter(list_of_values).items()
|
@@ -4564,6 +4671,31 @@ def create_similarity_matrix(list_of_values, matrix_length=0):
|
|
4564 |
|
4565 |
###################################################################################
|
4566 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4567 |
# This is the end of the TMIDI X Python module
|
4568 |
|
4569 |
###################################################################################
|
|
|
174 |
|
175 |
#--------------------------- Decoding stuff ------------------------
|
176 |
|
177 |
+
def midi2opus(midi=b'', do_not_check_MIDI_signature=False):
|
178 |
r'''Translates MIDI into a "opus". For a description of the
|
179 |
"opus" format, see opus2midi()
|
180 |
'''
|
|
|
186 |
if id != b'MThd':
|
187 |
_warn("midi2opus: midi starts with "+str(id)+" instead of 'MThd'")
|
188 |
_clean_up_warnings()
|
189 |
+
if do_not_check_MIDI_signature == False:
|
190 |
+
return [1000,[],]
|
191 |
[length, format, tracks_expected, ticks] = struct.unpack(
|
192 |
'>IHHH', bytes(my_midi[4:14]))
|
193 |
if length != 6:
|
|
|
267 |
_clean_up_warnings()
|
268 |
return score
|
269 |
|
270 |
+
def midi2score(midi=b'', do_not_check_MIDI_signature=False):
|
271 |
r'''
|
272 |
Translates MIDI into a "score", using midi2opus() then opus2score()
|
273 |
'''
|
274 |
+
return opus2score(midi2opus(midi, do_not_check_MIDI_signature))
|
275 |
|
276 |
+
def midi2ms_score(midi=b'', do_not_check_MIDI_signature=False):
|
277 |
r'''
|
278 |
Translates MIDI into a "score" with one beat per second and one
|
279 |
tick per millisecond, using midi2opus() then to_millisecs()
|
280 |
then opus2score()
|
281 |
'''
|
282 |
+
return opus2score(to_millisecs(midi2opus(midi, do_not_check_MIDI_signature)))
|
283 |
+
|
284 |
+
def midi2single_track_ms_score(midi_path_or_bytes,
|
285 |
+
recalculate_channels = False,
|
286 |
+
pass_old_timings_events= False,
|
287 |
+
verbose = False,
|
288 |
+
do_not_check_MIDI_signature=False
|
289 |
+
):
|
290 |
r'''
|
291 |
Translates MIDI into a single track "score" with 16 instruments and one beat per second and one
|
292 |
tick per millisecond
|
293 |
'''
|
294 |
|
295 |
+
if type(midi_path_or_bytes) == bytes:
|
296 |
+
midi_data = midi_path_or_bytes
|
297 |
+
|
298 |
+
elif type(midi_path_or_bytes) == str:
|
299 |
+
midi_data = open(midi_path_or_bytes, 'rb').read()
|
300 |
+
|
301 |
+
score = midi2score(midi_data, do_not_check_MIDI_signature)
|
302 |
|
303 |
if recalculate_channels:
|
304 |
|
|
|
1748 |
drums_color_num=128,
|
1749 |
plot_size=(11,4),
|
1750 |
note_height = 0.75,
|
1751 |
+
show_grid_lines=False,
|
1752 |
+
return_plt = False
|
1753 |
+
):
|
1754 |
|
1755 |
'''Tegridy ms SONG plotter/vizualizer'''
|
1756 |
|
|
|
1798 |
if show_grid_lines:
|
1799 |
ax.grid(color='white')
|
1800 |
|
1801 |
+
plt.xlabel('Time (ms)', c='black')
|
1802 |
plt.ylabel('Pitch', c='black')
|
1803 |
|
1804 |
plt.title(plot_title)
|
1805 |
|
1806 |
+
if return_plt:
|
1807 |
+
return plt
|
1808 |
+
|
1809 |
+
plt.show()
|
1810 |
+
|
1811 |
###################################################################################
|
1812 |
|
1813 |
def Tegridy_SONG_to_Full_MIDI_Converter(SONG,
|
|
|
3797 |
|
3798 |
fixed_score = []
|
3799 |
|
3800 |
+
if monophonic_score[0][0] == 'note':
|
|
|
3801 |
|
3802 |
+
for i in range(len(monophonic_score)-1):
|
3803 |
+
note = monophonic_score[i]
|
3804 |
|
3805 |
+
nmt = monophonic_score[i+1][1]
|
3806 |
+
|
3807 |
+
if note[1]+note[2] >= nmt:
|
3808 |
+
note_dur = nmt-note[1]-1
|
3809 |
+
else:
|
3810 |
+
note_dur = note[2]
|
3811 |
+
|
3812 |
+
new_note = [note[0], note[1], note_dur] + note[3:]
|
3813 |
+
|
3814 |
+
fixed_score.append(new_note)
|
3815 |
+
|
3816 |
+
fixed_score.append(monophonic_score[-1])
|
3817 |
+
|
3818 |
+
elif type(monophonic_score[0][0]) == int:
|
3819 |
|
3820 |
+
for i in range(len(monophonic_score)-1):
|
3821 |
+
note = monophonic_score[i]
|
3822 |
|
3823 |
+
nmt = monophonic_score[i+1][0]
|
3824 |
+
|
3825 |
+
if note[0]+note[1] >= nmt:
|
3826 |
+
note_dur = nmt-note[0]-1
|
3827 |
+
else:
|
3828 |
+
note_dur = note[1]
|
3829 |
+
|
3830 |
+
new_note = [note[0], note_dur] + note[2:]
|
3831 |
+
|
3832 |
+
fixed_score.append(new_note)
|
3833 |
+
|
3834 |
+
fixed_score.append(monophonic_score[-1])
|
3835 |
|
3836 |
return fixed_score
|
3837 |
|
|
|
4095 |
|
4096 |
def advanced_score_processor(raw_score,
|
4097 |
patches_to_analyze=list(range(129)),
|
4098 |
+
return_score_analysis=False,
|
4099 |
return_enhanced_score=False,
|
4100 |
return_enhanced_score_notes=False,
|
4101 |
+
return_enhanced_monophonic_melody=False,
|
4102 |
return_chordified_enhanced_score=False,
|
4103 |
return_chordified_enhanced_score_with_lyrics=False,
|
4104 |
return_score_tones_chords=False,
|
|
|
4366 |
###################################################################################
|
4367 |
|
4368 |
def check_and_fix_chord(chord,
|
4369 |
+
channel_index=3,
|
4370 |
+
pitch_index=4
|
4371 |
+
):
|
4372 |
|
4373 |
+
tones_chord = sorted(set([t[pitch_index] % 12 for t in chord if t[channel_index] != 9]))
|
|
|
|
|
|
|
|
|
|
|
4374 |
|
4375 |
+
notes_events = [t for t in chord if t[channel_index] != 9]
|
4376 |
+
notes_events.sort(key=lambda x: x[pitch_index], reverse=True)
|
4377 |
|
4378 |
+
drums_events = [t for t in chord if t[channel_index] == 9]
|
4379 |
|
4380 |
+
checked_and_fixed_chord = []
|
|
|
|
|
4381 |
|
4382 |
+
if tones_chord:
|
4383 |
+
|
4384 |
+
new_tones_chord = advanced_check_and_fix_tones_chord(tones_chord, high_pitch=notes_events[0][pitch_index])
|
4385 |
|
4386 |
+
if new_tones_chord != tones_chord:
|
4387 |
|
4388 |
+
if len(notes_events) > 1:
|
4389 |
+
checked_and_fixed_chord.extend([notes_events[0]])
|
4390 |
+
for cc in notes_events[1:]:
|
4391 |
+
if cc[channel_index] != 9:
|
4392 |
+
if (cc[pitch_index] % 12) in new_tones_chord:
|
4393 |
+
checked_and_fixed_chord.extend([cc])
|
4394 |
+
checked_and_fixed_chord.extend(drums_events)
|
4395 |
+
else:
|
4396 |
+
checked_and_fixed_chord.extend([notes_events[0]])
|
4397 |
+
else:
|
4398 |
+
checked_and_fixed_chord.extend(chord)
|
4399 |
+
else:
|
4400 |
+
checked_and_fixed_chord.extend(chord)
|
4401 |
+
|
4402 |
+
checked_and_fixed_chord.sort(key=lambda x: x[pitch_index], reverse=True)
|
4403 |
+
|
4404 |
+
return checked_and_fixed_chord
|
4405 |
|
4406 |
###################################################################################
|
4407 |
|
|
|
4590 |
|
4591 |
###################################################################################
|
4592 |
|
4593 |
+
def find_closest_tone(tones, tone):
|
4594 |
+
return min(tones, key=lambda x:abs(x-tone))
|
4595 |
+
|
4596 |
+
def advanced_check_and_fix_tones_chord(tones_chord, high_pitch=0):
|
4597 |
+
|
4598 |
+
lst = tones_chord
|
4599 |
+
|
4600 |
+
if 0 < high_pitch < 128:
|
4601 |
+
ht = high_pitch % 12
|
4602 |
+
else:
|
4603 |
+
ht = 12
|
4604 |
+
|
4605 |
+
cht = find_closest_tone(lst, ht)
|
4606 |
+
|
4607 |
+
if len(lst) == 2:
|
4608 |
+
if lst[1] - lst[0] == 1:
|
4609 |
+
return [cht]
|
4610 |
+
else:
|
4611 |
+
if 0 in lst and 11 in lst:
|
4612 |
+
if find_closest_tone([0, 11], cht) == 11:
|
4613 |
+
lst.remove(0)
|
4614 |
+
else:
|
4615 |
+
lst.remove(11)
|
4616 |
+
return lst
|
4617 |
+
|
4618 |
+
non_consecutive = []
|
4619 |
+
|
4620 |
+
if len(lst) > 2:
|
4621 |
+
for i in range(0, len(lst) - 1):
|
4622 |
+
if lst[i] + 1 != lst[i+1]:
|
4623 |
+
non_consecutive.append(lst[i])
|
4624 |
+
if lst[-1] - lst[-2] > 1:
|
4625 |
+
non_consecutive.append(lst[-1])
|
4626 |
+
|
4627 |
+
if cht not in non_consecutive:
|
4628 |
+
non_consecutive.append(cht)
|
4629 |
+
non_consecutive.sort()
|
4630 |
+
if any(abs(non_consecutive[i+1] - non_consecutive[i]) == 1 for i in range(len(non_consecutive) - 1)):
|
4631 |
+
final_list = [x for x in non_consecutive if x == cht or abs(x - cht) > 1]
|
4632 |
+
else:
|
4633 |
+
final_list = non_consecutive
|
4634 |
+
|
4635 |
+
else:
|
4636 |
+
final_list = non_consecutive
|
4637 |
+
|
4638 |
+
if 0 in final_list and 11 in final_list:
|
4639 |
+
if find_closest_tone([0, 11], cht) == 11:
|
4640 |
+
final_list.remove(0)
|
4641 |
+
else:
|
4642 |
+
final_list.remove(11)
|
4643 |
+
|
4644 |
+
if cht in final_list or ht in final_list:
|
4645 |
+
return final_list
|
4646 |
+
else:
|
4647 |
+
return ['Error']
|
4648 |
+
|
4649 |
+
###################################################################################
|
4650 |
+
|
4651 |
def create_similarity_matrix(list_of_values, matrix_length=0):
|
4652 |
|
4653 |
counts = Counter(list_of_values).items()
|
|
|
4671 |
|
4672 |
###################################################################################
|
4673 |
|
4674 |
+
def augment_enhanced_score_notes(enhanced_score_notes,
|
4675 |
+
timings_divider=16,
|
4676 |
+
full_sorting=True,
|
4677 |
+
timings_shift=0,
|
4678 |
+
pitch_shift=0
|
4679 |
+
):
|
4680 |
+
|
4681 |
+
esn = copy.deepcopy(enhanced_score_notes)
|
4682 |
+
|
4683 |
+
for e in esn:
|
4684 |
+
e[1] = int(e[1] / timings_divider) + timings_shift
|
4685 |
+
e[2] = int(e[2] / timings_divider) + timings_shift
|
4686 |
+
e[4] = e[4] + pitch_shift
|
4687 |
+
|
4688 |
+
if full_sorting:
|
4689 |
+
|
4690 |
+
# Sorting by patch, pitch, then by start-time
|
4691 |
+
esn.sort(key=lambda x: x[6])
|
4692 |
+
esn.sort(key=lambda x: x[4], reverse=True)
|
4693 |
+
esn.sort(key=lambda x: x[1])
|
4694 |
+
|
4695 |
+
return esn
|
4696 |
+
|
4697 |
+
###################################################################################
|
4698 |
+
|
4699 |
# This is the end of the TMIDI X Python module
|
4700 |
|
4701 |
###################################################################################
|