Upload TMIDIX.py
Browse files
TMIDIX.py
CHANGED
|
@@ -14,14 +14,14 @@ r'''############################################################################
|
|
| 14 |
#
|
| 15 |
# Project Los Angeles
|
| 16 |
#
|
| 17 |
-
# Tegridy Code
|
| 18 |
#
|
| 19 |
# https://github.com/Tegridy-Code/Project-Los-Angeles
|
| 20 |
#
|
| 21 |
#
|
| 22 |
###################################################################################
|
| 23 |
###################################################################################
|
| 24 |
-
# Copyright
|
| 25 |
#
|
| 26 |
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 27 |
# you may not use this file except in compliance with the License.
|
|
@@ -4690,7 +4690,8 @@ def augment_enhanced_score_notes(enhanced_score_notes,
|
|
| 4690 |
pitch_shift=0,
|
| 4691 |
ceil_timings=False,
|
| 4692 |
round_timings=False,
|
| 4693 |
-
legacy_timings=True
|
|
|
|
| 4694 |
):
|
| 4695 |
|
| 4696 |
esn = copy.deepcopy(enhanced_score_notes)
|
|
@@ -4740,6 +4741,9 @@ def augment_enhanced_score_notes(enhanced_score_notes,
|
|
| 4740 |
esn.sort(key=lambda x: x[6])
|
| 4741 |
esn.sort(key=lambda x: x[4], reverse=True)
|
| 4742 |
esn.sort(key=lambda x: x[1])
|
|
|
|
|
|
|
|
|
|
| 4743 |
|
| 4744 |
return esn
|
| 4745 |
|
|
@@ -7097,13 +7101,25 @@ def escore_notes_averages(escore_notes,
|
|
| 7097 |
else:
|
| 7098 |
durs = [e[durs_index] for e in escore_notes if e[chans_index] != 9]
|
| 7099 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7100 |
if return_ptcs_and_vels:
|
| 7101 |
if average_drums:
|
| 7102 |
ptcs = [e[ptcs_index] for e in escore_notes]
|
| 7103 |
vels = [e[vels_index] for e in escore_notes]
|
| 7104 |
else:
|
| 7105 |
ptcs = [e[ptcs_index] for e in escore_notes if e[chans_index] != 9]
|
| 7106 |
-
vels = [e[vels_index] for e in escore_notes if e[chans_index] != 9]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7107 |
|
| 7108 |
return [sum(times) / len(times), sum(durs) / len(durs), sum(ptcs) / len(ptcs), sum(vels) / len(vels)]
|
| 7109 |
|
|
@@ -7883,19 +7899,21 @@ def solo_piano_escore_notes(escore_notes,
|
|
| 7883 |
chord = []
|
| 7884 |
|
| 7885 |
for cc in c:
|
| 7886 |
-
if cc[pitches_index] not in seen:
|
| 7887 |
|
| 7888 |
-
|
|
|
|
|
|
|
| 7889 |
cc[channels_index] = 0
|
| 7890 |
cc[patches_index] = 0
|
| 7891 |
-
|
| 7892 |
chord.append(cc)
|
| 7893 |
seen.append(cc[pitches_index])
|
| 7894 |
-
|
| 7895 |
-
|
| 7896 |
-
|
|
|
|
| 7897 |
chord.append(cc)
|
| 7898 |
-
seen.append(cc[pitches_index])
|
| 7899 |
|
| 7900 |
sp_escore_notes.append(chord)
|
| 7901 |
|
|
@@ -9254,6 +9272,1032 @@ def find_highest_density_escore_notes_chunk(escore_notes, max_chunk_time=512):
|
|
| 9254 |
|
| 9255 |
return chunk_escore
|
| 9256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9257 |
###################################################################################
|
| 9258 |
#
|
| 9259 |
# This is the end of the TMIDI X Python module
|
|
|
|
| 14 |
#
|
| 15 |
# Project Los Angeles
|
| 16 |
#
|
| 17 |
+
# Tegridy Code 2024
|
| 18 |
#
|
| 19 |
# https://github.com/Tegridy-Code/Project-Los-Angeles
|
| 20 |
#
|
| 21 |
#
|
| 22 |
###################################################################################
|
| 23 |
###################################################################################
|
| 24 |
+
# Copyright 2024 Project Los Angeles / Tegridy Code
|
| 25 |
#
|
| 26 |
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 27 |
# you may not use this file except in compliance with the License.
|
|
|
|
| 4690 |
pitch_shift=0,
|
| 4691 |
ceil_timings=False,
|
| 4692 |
round_timings=False,
|
| 4693 |
+
legacy_timings=True,
|
| 4694 |
+
sort_drums_last=False
|
| 4695 |
):
|
| 4696 |
|
| 4697 |
esn = copy.deepcopy(enhanced_score_notes)
|
|
|
|
| 4741 |
esn.sort(key=lambda x: x[6])
|
| 4742 |
esn.sort(key=lambda x: x[4], reverse=True)
|
| 4743 |
esn.sort(key=lambda x: x[1])
|
| 4744 |
+
|
| 4745 |
+
if sort_drums_last:
|
| 4746 |
+
esn.sort(key=lambda x: (x[1], -x[4], x[6]) if x[6] != 128 else (x[1], x[6], -x[4]))
|
| 4747 |
|
| 4748 |
return esn
|
| 4749 |
|
|
|
|
| 7101 |
else:
|
| 7102 |
durs = [e[durs_index] for e in escore_notes if e[chans_index] != 9]
|
| 7103 |
|
| 7104 |
+
if len(times) == 0:
|
| 7105 |
+
times = [0]
|
| 7106 |
+
|
| 7107 |
+
if len(durs) == 0:
|
| 7108 |
+
durs = [0]
|
| 7109 |
+
|
| 7110 |
if return_ptcs_and_vels:
|
| 7111 |
if average_drums:
|
| 7112 |
ptcs = [e[ptcs_index] for e in escore_notes]
|
| 7113 |
vels = [e[vels_index] for e in escore_notes]
|
| 7114 |
else:
|
| 7115 |
ptcs = [e[ptcs_index] for e in escore_notes if e[chans_index] != 9]
|
| 7116 |
+
vels = [e[vels_index] for e in escore_notes if e[chans_index] != 9]
|
| 7117 |
+
|
| 7118 |
+
if len(ptcs) == 0:
|
| 7119 |
+
ptcs = [0]
|
| 7120 |
+
|
| 7121 |
+
if len(vels) == 0:
|
| 7122 |
+
vels = [0]
|
| 7123 |
|
| 7124 |
return [sum(times) / len(times), sum(durs) / len(durs), sum(ptcs) / len(ptcs), sum(vels) / len(vels)]
|
| 7125 |
|
|
|
|
| 7899 |
chord = []
|
| 7900 |
|
| 7901 |
for cc in c:
|
|
|
|
| 7902 |
|
| 7903 |
+
if cc[channels_index] != 9:
|
| 7904 |
+
if cc[pitches_index] not in seen:
|
| 7905 |
+
|
| 7906 |
cc[channels_index] = 0
|
| 7907 |
cc[patches_index] = 0
|
| 7908 |
+
|
| 7909 |
chord.append(cc)
|
| 7910 |
seen.append(cc[pitches_index])
|
| 7911 |
+
|
| 7912 |
+
else:
|
| 7913 |
+
if keep_drums:
|
| 7914 |
+
if cc[pitches_index]+128 not in seen:
|
| 7915 |
chord.append(cc)
|
| 7916 |
+
seen.append(cc[pitches_index]+128)
|
| 7917 |
|
| 7918 |
sp_escore_notes.append(chord)
|
| 7919 |
|
|
|
|
| 9272 |
|
| 9273 |
return chunk_escore
|
| 9274 |
|
| 9275 |
+
###################################################################################
|
| 9276 |
+
|
| 9277 |
+
def advanced_add_drums_to_escore_notes(escore_notes,
|
| 9278 |
+
main_beat_min_dtime=5,
|
| 9279 |
+
main_beat_dtime_thres=1,
|
| 9280 |
+
drums_durations_value=2,
|
| 9281 |
+
drums_pitches_velocities=[(36, 100),
|
| 9282 |
+
(38, 100),
|
| 9283 |
+
(41, 125)],
|
| 9284 |
+
recalculate_score_timings=True,
|
| 9285 |
+
intro_drums_count=4,
|
| 9286 |
+
intro_drums_time_k=4,
|
| 9287 |
+
intro_drums_pitch_velocity=[37, 110]
|
| 9288 |
+
):
|
| 9289 |
+
|
| 9290 |
+
#===========================================================
|
| 9291 |
+
|
| 9292 |
+
new_dscore = delta_score_notes(escore_notes)
|
| 9293 |
+
|
| 9294 |
+
times = [d[1] for d in new_dscore if d[1] != 0]
|
| 9295 |
+
|
| 9296 |
+
time = [c[0] for c in Counter(times).most_common() if c[0] >= main_beat_min_dtime][0]
|
| 9297 |
+
|
| 9298 |
+
#===========================================================
|
| 9299 |
+
|
| 9300 |
+
if intro_drums_count > 0:
|
| 9301 |
+
|
| 9302 |
+
drums_score = []
|
| 9303 |
+
|
| 9304 |
+
for i in range(intro_drums_count):
|
| 9305 |
+
|
| 9306 |
+
if i == 0:
|
| 9307 |
+
dtime = 0
|
| 9308 |
+
|
| 9309 |
+
else:
|
| 9310 |
+
dtime = time
|
| 9311 |
+
|
| 9312 |
+
drums_score.append(['note',
|
| 9313 |
+
dtime * intro_drums_time_k,
|
| 9314 |
+
drums_durations_value,
|
| 9315 |
+
9,
|
| 9316 |
+
intro_drums_pitch_velocity[0],
|
| 9317 |
+
intro_drums_pitch_velocity[1],
|
| 9318 |
+
128]
|
| 9319 |
+
)
|
| 9320 |
+
|
| 9321 |
+
new_dscore[0][1] = time * intro_drums_time_k
|
| 9322 |
+
|
| 9323 |
+
new_dscore = drums_score + new_dscore
|
| 9324 |
+
|
| 9325 |
+
#===========================================================
|
| 9326 |
+
|
| 9327 |
+
for e in new_dscore:
|
| 9328 |
+
|
| 9329 |
+
if abs(e[1] - time) == main_beat_dtime_thres:
|
| 9330 |
+
e[1] = time
|
| 9331 |
+
|
| 9332 |
+
if recalculate_score_timings:
|
| 9333 |
+
|
| 9334 |
+
if e[1] % time != 0 and e[1] > time:
|
| 9335 |
+
if e[1] % time < time // 2:
|
| 9336 |
+
e[1] -= e[1] % time
|
| 9337 |
+
|
| 9338 |
+
else:
|
| 9339 |
+
e[1] += time - (e[1] % time)
|
| 9340 |
+
|
| 9341 |
+
#===========================================================
|
| 9342 |
+
|
| 9343 |
+
drums_score = []
|
| 9344 |
+
|
| 9345 |
+
dtime = 0
|
| 9346 |
+
|
| 9347 |
+
idx = 0
|
| 9348 |
+
|
| 9349 |
+
for i, e in enumerate(new_dscore):
|
| 9350 |
+
|
| 9351 |
+
drums_score.append(e)
|
| 9352 |
+
|
| 9353 |
+
dtime += e[1]
|
| 9354 |
+
|
| 9355 |
+
if e[1] != 0:
|
| 9356 |
+
idx += 1
|
| 9357 |
+
|
| 9358 |
+
if i >= intro_drums_count:
|
| 9359 |
+
|
| 9360 |
+
if (e[1] % time == 0 and e[1] != 0) or i == 0:
|
| 9361 |
+
|
| 9362 |
+
if idx % 2 == 0 and e[1] != 0:
|
| 9363 |
+
drums_score.append(['note',
|
| 9364 |
+
0,
|
| 9365 |
+
drums_durations_value,
|
| 9366 |
+
9,
|
| 9367 |
+
drums_pitches_velocities[0][0],
|
| 9368 |
+
drums_pitches_velocities[0][1],
|
| 9369 |
+
128]
|
| 9370 |
+
)
|
| 9371 |
+
|
| 9372 |
+
if idx % 2 != 0 and e[1] != 0:
|
| 9373 |
+
drums_score.append(['note',
|
| 9374 |
+
0,
|
| 9375 |
+
drums_durations_value,
|
| 9376 |
+
9,
|
| 9377 |
+
drums_pitches_velocities[1][0],
|
| 9378 |
+
drums_pitches_velocities[1][1],
|
| 9379 |
+
128]
|
| 9380 |
+
)
|
| 9381 |
+
|
| 9382 |
+
if idx % 4 == 0 and e[1] != 0:
|
| 9383 |
+
drums_score.append(['note',
|
| 9384 |
+
0,
|
| 9385 |
+
drums_durations_value,
|
| 9386 |
+
9,
|
| 9387 |
+
drums_pitches_velocities[2][0],
|
| 9388 |
+
drums_pitches_velocities[2][1],
|
| 9389 |
+
128]
|
| 9390 |
+
)
|
| 9391 |
+
|
| 9392 |
+
#===========================================================
|
| 9393 |
+
|
| 9394 |
+
return delta_score_to_abs_score(drums_score)
|
| 9395 |
+
|
| 9396 |
+
###################################################################################
|
| 9397 |
+
|
| 9398 |
+
MIDI_TEXT_EVENTS = ['text_event',
|
| 9399 |
+
'copyright_text_event',
|
| 9400 |
+
'track_name',
|
| 9401 |
+
'instrument_name',
|
| 9402 |
+
'lyric',
|
| 9403 |
+
'marker',
|
| 9404 |
+
'cue_point',
|
| 9405 |
+
'text_event_08',
|
| 9406 |
+
'text_event_09',
|
| 9407 |
+
'text_event_0a',
|
| 9408 |
+
'text_event_0b',
|
| 9409 |
+
'text_event_0c',
|
| 9410 |
+
'text_event_0d',
|
| 9411 |
+
'text_event_0e',
|
| 9412 |
+
'text_event_0f'
|
| 9413 |
+
]
|
| 9414 |
+
|
| 9415 |
+
###################################################################################
|
| 9416 |
+
|
| 9417 |
+
import hashlib
|
| 9418 |
+
import re
|
| 9419 |
+
|
| 9420 |
+
###################################################################################
|
| 9421 |
+
|
| 9422 |
+
def get_md5_hash(data):
|
| 9423 |
+
return hashlib.md5(data).hexdigest()
|
| 9424 |
+
|
| 9425 |
+
###################################################################################
|
| 9426 |
+
|
| 9427 |
+
def is_valid_md5_hash(string):
|
| 9428 |
+
return bool(re.match(r'^[a-fA-F0-9]{32}$', string))
|
| 9429 |
+
|
| 9430 |
+
###################################################################################
|
| 9431 |
+
|
| 9432 |
+
def clean_string(original_string,
|
| 9433 |
+
regex=r'[^a-zA-Z0-9 ]',
|
| 9434 |
+
remove_duplicate_spaces=True,
|
| 9435 |
+
title=False
|
| 9436 |
+
):
|
| 9437 |
+
|
| 9438 |
+
cstr1 = re.sub(regex, '', original_string)
|
| 9439 |
+
|
| 9440 |
+
if title:
|
| 9441 |
+
cstr1 = cstr1.title()
|
| 9442 |
+
|
| 9443 |
+
if remove_duplicate_spaces:
|
| 9444 |
+
return re.sub(r'\s+', ' ', cstr1).strip()
|
| 9445 |
+
|
| 9446 |
+
else:
|
| 9447 |
+
return cstr1
|
| 9448 |
+
|
| 9449 |
+
###################################################################################
|
| 9450 |
+
|
| 9451 |
+
def encode_to_ord(text, chars_range=[], sub_char='', chars_shift=0):
|
| 9452 |
+
|
| 9453 |
+
if not chars_range:
|
| 9454 |
+
chars_range = [32] + list(range(65, 91)) + list(range(97, 123))
|
| 9455 |
+
|
| 9456 |
+
if sub_char:
|
| 9457 |
+
chars_range.append(ord(sub_char))
|
| 9458 |
+
|
| 9459 |
+
chars_range = sorted(set(chars_range))
|
| 9460 |
+
|
| 9461 |
+
encoded = []
|
| 9462 |
+
|
| 9463 |
+
for char in text:
|
| 9464 |
+
if ord(char) in chars_range:
|
| 9465 |
+
encoded.append(chars_range.index(ord(char)) + chars_shift)
|
| 9466 |
+
|
| 9467 |
+
else:
|
| 9468 |
+
if sub_char:
|
| 9469 |
+
encoded.append(chars_range.index(ord(sub_char)) + chars_shift)
|
| 9470 |
+
|
| 9471 |
+
|
| 9472 |
+
return [encoded, chars_range]
|
| 9473 |
+
|
| 9474 |
+
###################################################################################
|
| 9475 |
+
|
| 9476 |
+
def decode_from_ord(ord_list, chars_range=[], sub_char='', chars_shift=0):
|
| 9477 |
+
|
| 9478 |
+
if not chars_range:
|
| 9479 |
+
chars_range = [32] + list(range(65, 91)) + list(range(97, 123))
|
| 9480 |
+
|
| 9481 |
+
if sub_char:
|
| 9482 |
+
chars_range.append(ord(sub_char))
|
| 9483 |
+
|
| 9484 |
+
chars_range = sorted(set(chars_range))
|
| 9485 |
+
|
| 9486 |
+
return ''.join(chr(chars_range[num-chars_shift]) if 0 <= num-chars_shift < len(chars_range) else sub_char for num in ord_list)
|
| 9487 |
+
|
| 9488 |
+
###################################################################################
|
| 9489 |
+
|
| 9490 |
+
def lists_similarity(list1, list2, by_elements=True, by_sum=True):
|
| 9491 |
+
|
| 9492 |
+
if len(list1) != len(list2):
|
| 9493 |
+
return -1
|
| 9494 |
+
|
| 9495 |
+
element_ratios = []
|
| 9496 |
+
total_counts1 = sum(list1)
|
| 9497 |
+
total_counts2 = sum(list2)
|
| 9498 |
+
|
| 9499 |
+
for a, b in zip(list1, list2):
|
| 9500 |
+
if a == 0 and b == 0:
|
| 9501 |
+
element_ratios.append(1)
|
| 9502 |
+
elif a == 0 or b == 0:
|
| 9503 |
+
element_ratios.append(0)
|
| 9504 |
+
else:
|
| 9505 |
+
element_ratios.append(min(a, b) / max(a, b))
|
| 9506 |
+
|
| 9507 |
+
average_element_ratio = sum(element_ratios) / len(element_ratios)
|
| 9508 |
+
|
| 9509 |
+
total_counts_ratio = min(total_counts1, total_counts2) / max(total_counts1, total_counts2)
|
| 9510 |
+
|
| 9511 |
+
if by_elements and by_sum:
|
| 9512 |
+
return (average_element_ratio + total_counts_ratio) / 2
|
| 9513 |
+
|
| 9514 |
+
elif by_elements and not by_sum:
|
| 9515 |
+
return average_element_ratio
|
| 9516 |
+
|
| 9517 |
+
elif not by_elements and by_sum:
|
| 9518 |
+
return total_counts_ratio
|
| 9519 |
+
|
| 9520 |
+
else:
|
| 9521 |
+
return -1
|
| 9522 |
+
|
| 9523 |
+
###################################################################################
|
| 9524 |
+
|
| 9525 |
+
def find_indexes(lst, value, mode='equal', dual_mode=True):
|
| 9526 |
+
|
| 9527 |
+
indexes = []
|
| 9528 |
+
|
| 9529 |
+
if mode == 'equal' or dual_mode:
|
| 9530 |
+
indexes.extend([index for index, elem in enumerate(lst) if elem == value])
|
| 9531 |
+
|
| 9532 |
+
if mode == 'smaller':
|
| 9533 |
+
indexes.extend([index for index, elem in enumerate(lst) if elem < value])
|
| 9534 |
+
|
| 9535 |
+
if mode == 'larger':
|
| 9536 |
+
indexes.extend([index for index, elem in enumerate(lst) if elem > value])
|
| 9537 |
+
|
| 9538 |
+
return sorted(set(indexes))
|
| 9539 |
+
|
| 9540 |
+
###################################################################################
|
| 9541 |
+
|
| 9542 |
+
NUMERALS = ["one", "two", "three", "four",
|
| 9543 |
+
"five", "six", "seven", "eight",
|
| 9544 |
+
"nine", "ten", "eleven", "twelve",
|
| 9545 |
+
"thirteen", "fourteen", "fifteen", "sixteen"
|
| 9546 |
+
]
|
| 9547 |
+
|
| 9548 |
+
SEMITONES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
|
| 9549 |
+
|
| 9550 |
+
MOOD_SCALES = ['Major', 'Minor', 'Major Minor']
|
| 9551 |
+
|
| 9552 |
+
###################################################################################
|
| 9553 |
+
|
| 9554 |
+
def alpha_str(string):
|
| 9555 |
+
return re.sub(r'[^a-zA-Z ()]', '', string).strip()
|
| 9556 |
+
|
| 9557 |
+
###################################################################################
|
| 9558 |
+
|
| 9559 |
+
def escore_notes_to_text_description(escore_notes, song_name='', artist_name=''):
|
| 9560 |
+
|
| 9561 |
+
#==============================================================================
|
| 9562 |
+
|
| 9563 |
+
song_time_min = (escore_notes[-1][1] * 16) / 1000 / 60
|
| 9564 |
+
|
| 9565 |
+
if song_time_min < 1.5:
|
| 9566 |
+
song_length = 'short'
|
| 9567 |
+
|
| 9568 |
+
elif 1.5 <= song_time_min < 2.5:
|
| 9569 |
+
song_length = 'average'
|
| 9570 |
+
|
| 9571 |
+
elif song_time_min >= 2.5:
|
| 9572 |
+
song_length = 'long'
|
| 9573 |
+
|
| 9574 |
+
#==============================================================================
|
| 9575 |
+
|
| 9576 |
+
escore_times = [e[1] for e in escore_notes if e[3] != 9]
|
| 9577 |
+
|
| 9578 |
+
comp_type = ''
|
| 9579 |
+
|
| 9580 |
+
if len(escore_times) > 0:
|
| 9581 |
+
if len(escore_times) == len(set(escore_times)):
|
| 9582 |
+
comp_type = 'monophonic melody'
|
| 9583 |
+
|
| 9584 |
+
elif len(escore_times) >= len(set(escore_times)) and 1 in Counter(escore_times).values():
|
| 9585 |
+
comp_type = 'melody and accompaniment'
|
| 9586 |
+
|
| 9587 |
+
elif len(escore_times) >= len(set(escore_times)) and 1 not in Counter(escore_times).values():
|
| 9588 |
+
comp_type = 'accompaniment'
|
| 9589 |
+
|
| 9590 |
+
else:
|
| 9591 |
+
comp_type = 'drums only'
|
| 9592 |
+
|
| 9593 |
+
#==============================================================================
|
| 9594 |
+
|
| 9595 |
+
patches = sorted(set([e[6] for e in escore_notes]))
|
| 9596 |
+
|
| 9597 |
+
instruments = [alpha_str(Number2patch[p]) for p in patches if p < 128]
|
| 9598 |
+
|
| 9599 |
+
if 128 in patches:
|
| 9600 |
+
drums_present = True
|
| 9601 |
+
|
| 9602 |
+
else:
|
| 9603 |
+
drums_present = False
|
| 9604 |
+
|
| 9605 |
+
drums_pitches = [e[4] for e in escore_notes if e[3] == 9]
|
| 9606 |
+
|
| 9607 |
+
most_common_drums = [alpha_str(Notenum2percussion[p[0]]) for p in Counter(drums_pitches).most_common(3) if p[0] in Notenum2percussion]
|
| 9608 |
+
|
| 9609 |
+
#==============================================================================
|
| 9610 |
+
|
| 9611 |
+
pitches = [e[4] for e in escore_notes if e[3] != 9]
|
| 9612 |
+
|
| 9613 |
+
key = ''
|
| 9614 |
+
|
| 9615 |
+
if pitches:
|
| 9616 |
+
key = SEMITONES[statistics.mode(pitches) % 12]
|
| 9617 |
+
|
| 9618 |
+
#==============================================================================
|
| 9619 |
+
|
| 9620 |
+
mood = ''
|
| 9621 |
+
|
| 9622 |
+
if pitches:
|
| 9623 |
+
|
| 9624 |
+
cscore = chordify_score([1000, escore_notes])
|
| 9625 |
+
|
| 9626 |
+
tones_chords = Counter()
|
| 9627 |
+
|
| 9628 |
+
for c in cscore:
|
| 9629 |
+
if len([e for e in c if e[3] != 9]) > 0:
|
| 9630 |
+
tones_chords[tuple(sorted(set([e[4] % 12 for e in c if e[3] != 9])))] += 1
|
| 9631 |
+
|
| 9632 |
+
most_common_tones_chords = [check_and_fix_tones_chord(list(c[0])) for c in tones_chords.most_common(10)]
|
| 9633 |
+
|
| 9634 |
+
mood_scale = statistics.mode(tones_chords_to_types(most_common_tones_chords, return_chord_type_index=True)) % 3
|
| 9635 |
+
|
| 9636 |
+
mood = MOOD_SCALES[mood_scale]
|
| 9637 |
+
|
| 9638 |
+
#==============================================================================
|
| 9639 |
+
|
| 9640 |
+
if pitches:
|
| 9641 |
+
|
| 9642 |
+
escore_averages = escore_notes_averages(escore_notes, return_ptcs_and_vels=True)
|
| 9643 |
+
|
| 9644 |
+
if escore_averages[0] < 8:
|
| 9645 |
+
rythm = 'fast'
|
| 9646 |
+
|
| 9647 |
+
elif 8 <= escore_averages[0] <= 12:
|
| 9648 |
+
rythm = 'average'
|
| 9649 |
+
|
| 9650 |
+
elif escore_averages[0] > 12:
|
| 9651 |
+
rythm = 'slow'
|
| 9652 |
+
|
| 9653 |
+
if escore_averages[1] < 16:
|
| 9654 |
+
tempo = 'fast'
|
| 9655 |
+
|
| 9656 |
+
elif 16 <= escore_averages[1] <= 24:
|
| 9657 |
+
tempo = 'average'
|
| 9658 |
+
|
| 9659 |
+
elif escore_averages[1] > 24:
|
| 9660 |
+
tempo = 'slow'
|
| 9661 |
+
|
| 9662 |
+
if escore_averages[2] < 50:
|
| 9663 |
+
tone = 'bass'
|
| 9664 |
+
|
| 9665 |
+
elif 50 <= escore_averages[2] <= 70:
|
| 9666 |
+
tone = 'midrange'
|
| 9667 |
+
|
| 9668 |
+
elif escore_averages[2] > 70:
|
| 9669 |
+
tone = 'treble'
|
| 9670 |
+
|
| 9671 |
+
if escore_averages[3] < 80:
|
| 9672 |
+
dynamics = 'quiet'
|
| 9673 |
+
|
| 9674 |
+
elif 80 <= escore_averages[3] <= 100:
|
| 9675 |
+
dynamics = 'average'
|
| 9676 |
+
|
| 9677 |
+
elif escore_averages[3] > 100:
|
| 9678 |
+
dynamics = 'loud'
|
| 9679 |
+
|
| 9680 |
+
#==============================================================================
|
| 9681 |
+
|
| 9682 |
+
description = ''
|
| 9683 |
+
|
| 9684 |
+
if song_name != '':
|
| 9685 |
+
description = 'Song "' + song_name + '"'
|
| 9686 |
+
|
| 9687 |
+
if artist_name != '':
|
| 9688 |
+
description += ' by ' + artist_name
|
| 9689 |
+
|
| 9690 |
+
if song_name != '' or artist_name != '':
|
| 9691 |
+
description += '.'
|
| 9692 |
+
description += '\n'
|
| 9693 |
+
|
| 9694 |
+
description += 'The song is '
|
| 9695 |
+
|
| 9696 |
+
if song_length != 'average':
|
| 9697 |
+
description += 'a ' + song_length
|
| 9698 |
+
|
| 9699 |
+
else:
|
| 9700 |
+
description += 'an ' + song_length
|
| 9701 |
+
|
| 9702 |
+
description += ' duration '
|
| 9703 |
+
|
| 9704 |
+
description += comp_type + ' composition'
|
| 9705 |
+
|
| 9706 |
+
if comp_type != 'drum track':
|
| 9707 |
+
|
| 9708 |
+
if drums_present:
|
| 9709 |
+
description += ' with drums'
|
| 9710 |
+
|
| 9711 |
+
else:
|
| 9712 |
+
description += ' without drums'
|
| 9713 |
+
|
| 9714 |
+
if key and mood:
|
| 9715 |
+
description += ' in ' + key + ' ' + mood
|
| 9716 |
+
|
| 9717 |
+
description += '.'
|
| 9718 |
+
|
| 9719 |
+
description += '\n'
|
| 9720 |
+
|
| 9721 |
+
if pitches:
|
| 9722 |
+
|
| 9723 |
+
description += 'It has '
|
| 9724 |
+
|
| 9725 |
+
description += rythm + ' rythm, '
|
| 9726 |
+
description += tempo + ' tempo, '
|
| 9727 |
+
description += tone + ' tone and '
|
| 9728 |
+
description += dynamics + ' dynamics.'
|
| 9729 |
+
|
| 9730 |
+
description += '\n'
|
| 9731 |
+
|
| 9732 |
+
description += 'The song '
|
| 9733 |
+
|
| 9734 |
+
if len(instruments) == 1:
|
| 9735 |
+
description += 'is played on a solo ' + instruments[0] + '.'
|
| 9736 |
+
|
| 9737 |
+
else:
|
| 9738 |
+
description += 'features ' + NUMERALS[max(0, min(15, len(instruments)-1))] + ' instruments: '
|
| 9739 |
+
description += ', '.join(instruments[:-1]) + ' and ' + instruments[-1] + '.'
|
| 9740 |
+
|
| 9741 |
+
description += '\n'
|
| 9742 |
+
|
| 9743 |
+
if drums_present and most_common_drums:
|
| 9744 |
+
description += 'The drum track has predominant '
|
| 9745 |
+
description += ', '.join(most_common_drums[:-1]) + ' and ' + most_common_drums[-1] + '.'
|
| 9746 |
+
|
| 9747 |
+
#==============================================================================
|
| 9748 |
+
|
| 9749 |
+
return description
|
| 9750 |
+
|
| 9751 |
+
###################################################################################
|
| 9752 |
+
|
| 9753 |
+
#==================================================================================
|
| 9754 |
+
#
|
| 9755 |
+
# Below constants code is a courtesy of MidiTok
|
| 9756 |
+
#
|
| 9757 |
+
# Retrieved on 12/29/2024
|
| 9758 |
+
#
|
| 9759 |
+
# https://github.com/Natooz/MidiTok/blob/main/src/miditok/constants.py
|
| 9760 |
+
#
|
| 9761 |
+
#==================================================================================
|
| 9762 |
+
|
| 9763 |
+
MIDI_FILES_EXTENSIONS = [".mid", ".midi", ".kar", ".MID", ".MIDI", ".KAR"]
|
| 9764 |
+
|
| 9765 |
+
# The recommended pitches for piano in the GM2 specs are from 21 to 108
|
| 9766 |
+
PIANO_PITCH_RANGE = range(21, 109)
|
| 9767 |
+
|
| 9768 |
+
# Chord params
|
| 9769 |
+
# "chord_unknown" specifies the range of number of notes that can form "unknown" chords
|
| 9770 |
+
# (that do not fit in "chord_maps") to add in tokens.
|
| 9771 |
+
# Known chord maps, with 0 as root note
|
| 9772 |
+
BASIC_CHORDS_MAP = {
|
| 9773 |
+
"min": (0, 3, 7),
|
| 9774 |
+
"maj": (0, 4, 7),
|
| 9775 |
+
"dim": (0, 3, 6),
|
| 9776 |
+
"aug": (0, 4, 8),
|
| 9777 |
+
"sus2": (0, 2, 7),
|
| 9778 |
+
"sus4": (0, 5, 7),
|
| 9779 |
+
"7dom": (0, 4, 7, 10),
|
| 9780 |
+
"7min": (0, 3, 7, 10),
|
| 9781 |
+
"7maj": (0, 4, 7, 11),
|
| 9782 |
+
"7halfdim": (0, 3, 6, 10),
|
| 9783 |
+
"7dim": (0, 3, 6, 9),
|
| 9784 |
+
"7aug": (0, 4, 8, 11),
|
| 9785 |
+
"9maj": (0, 4, 7, 10, 14),
|
| 9786 |
+
"9min": (0, 4, 7, 10, 13),
|
| 9787 |
+
}
|
| 9788 |
+
|
| 9789 |
+
# Drums
|
| 9790 |
+
# Recommended range from the GM2 specs
|
| 9791 |
+
DRUMS_PITCH_RANGE = range(27, 90)
|
| 9792 |
+
|
| 9793 |
+
# Used with chords
|
| 9794 |
+
PITCH_CLASSES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
|
| 9795 |
+
|
| 9796 |
+
# http://newt.phys.unsw.edu.au/jw/notes.html
|
| 9797 |
+
# https://www.midi.org/specifications
|
| 9798 |
+
|
| 9799 |
+
# index i = program i+1 in the GM2 specs (7. Appendix A)
|
| 9800 |
+
# index i = program i as retrieved by packages
|
| 9801 |
+
MIDI_INSTRUMENTS = [
|
| 9802 |
+
# Piano
|
| 9803 |
+
{"name": "Acoustic Grand Piano", "pitch_range": range(21, 109)},
|
| 9804 |
+
{"name": "Bright Acoustic Piano", "pitch_range": range(21, 109)},
|
| 9805 |
+
{"name": "Electric Grand Piano", "pitch_range": range(21, 109)},
|
| 9806 |
+
{"name": "Honky-tonk Piano", "pitch_range": range(21, 109)},
|
| 9807 |
+
{"name": "Electric Piano 1", "pitch_range": range(28, 104)},
|
| 9808 |
+
{"name": "Electric Piano 2", "pitch_range": range(28, 104)},
|
| 9809 |
+
{"name": "Harpsichord", "pitch_range": range(41, 90)},
|
| 9810 |
+
{"name": "Clavi", "pitch_range": range(36, 97)},
|
| 9811 |
+
# Chromatic Percussion
|
| 9812 |
+
{"name": "Celesta", "pitch_range": range(60, 109)},
|
| 9813 |
+
{"name": "Glockenspiel", "pitch_range": range(72, 109)},
|
| 9814 |
+
{"name": "Music Box", "pitch_range": range(60, 85)},
|
| 9815 |
+
{"name": "Vibraphone", "pitch_range": range(53, 90)},
|
| 9816 |
+
{"name": "Marimba", "pitch_range": range(48, 85)},
|
| 9817 |
+
{"name": "Xylophone", "pitch_range": range(65, 97)},
|
| 9818 |
+
{"name": "Tubular Bells", "pitch_range": range(60, 78)},
|
| 9819 |
+
{"name": "Dulcimer", "pitch_range": range(60, 85)},
|
| 9820 |
+
# Organs
|
| 9821 |
+
{"name": "Drawbar Organ", "pitch_range": range(36, 97)},
|
| 9822 |
+
{"name": "Percussive Organ", "pitch_range": range(36, 97)},
|
| 9823 |
+
{"name": "Rock Organ", "pitch_range": range(36, 97)},
|
| 9824 |
+
{"name": "Church Organ", "pitch_range": range(21, 109)},
|
| 9825 |
+
{"name": "Reed Organ", "pitch_range": range(36, 97)},
|
| 9826 |
+
{"name": "Accordion", "pitch_range": range(53, 90)},
|
| 9827 |
+
{"name": "Harmonica", "pitch_range": range(60, 85)},
|
| 9828 |
+
{"name": "Tango Accordion", "pitch_range": range(53, 90)},
|
| 9829 |
+
# Guitars
|
| 9830 |
+
{"name": "Acoustic Guitar (nylon)", "pitch_range": range(40, 85)},
|
| 9831 |
+
{"name": "Acoustic Guitar (steel)", "pitch_range": range(40, 85)},
|
| 9832 |
+
{"name": "Electric Guitar (jazz)", "pitch_range": range(40, 87)},
|
| 9833 |
+
{"name": "Electric Guitar (clean)", "pitch_range": range(40, 87)},
|
| 9834 |
+
{"name": "Electric Guitar (muted)", "pitch_range": range(40, 87)},
|
| 9835 |
+
{"name": "Overdriven Guitar", "pitch_range": range(40, 87)},
|
| 9836 |
+
{"name": "Distortion Guitar", "pitch_range": range(40, 87)},
|
| 9837 |
+
{"name": "Guitar Harmonics", "pitch_range": range(40, 87)},
|
| 9838 |
+
# Bass
|
| 9839 |
+
{"name": "Acoustic Bass", "pitch_range": range(28, 56)},
|
| 9840 |
+
{"name": "Electric Bass (finger)", "pitch_range": range(28, 56)},
|
| 9841 |
+
{"name": "Electric Bass (pick)", "pitch_range": range(28, 56)},
|
| 9842 |
+
{"name": "Fretless Bass", "pitch_range": range(28, 56)},
|
| 9843 |
+
{"name": "Slap Bass 1", "pitch_range": range(28, 56)},
|
| 9844 |
+
{"name": "Slap Bass 2", "pitch_range": range(28, 56)},
|
| 9845 |
+
{"name": "Synth Bass 1", "pitch_range": range(28, 56)},
|
| 9846 |
+
{"name": "Synth Bass 2", "pitch_range": range(28, 56)},
|
| 9847 |
+
# Strings & Orchestral instruments
|
| 9848 |
+
{"name": "Violin", "pitch_range": range(55, 94)},
|
| 9849 |
+
{"name": "Viola", "pitch_range": range(48, 85)},
|
| 9850 |
+
{"name": "Cello", "pitch_range": range(36, 73)},
|
| 9851 |
+
{"name": "Contrabass", "pitch_range": range(28, 56)},
|
| 9852 |
+
{"name": "Tremolo Strings", "pitch_range": range(28, 94)},
|
| 9853 |
+
{"name": "Pizzicato Strings", "pitch_range": range(28, 94)},
|
| 9854 |
+
{"name": "Orchestral Harp", "pitch_range": range(23, 104)},
|
| 9855 |
+
{"name": "Timpani", "pitch_range": range(36, 58)},
|
| 9856 |
+
# Ensembles
|
| 9857 |
+
{"name": "String Ensembles 1", "pitch_range": range(28, 97)},
|
| 9858 |
+
{"name": "String Ensembles 2", "pitch_range": range(28, 97)},
|
| 9859 |
+
{"name": "SynthStrings 1", "pitch_range": range(36, 97)},
|
| 9860 |
+
{"name": "SynthStrings 2", "pitch_range": range(36, 97)},
|
| 9861 |
+
{"name": "Choir Aahs", "pitch_range": range(48, 80)},
|
| 9862 |
+
{"name": "Voice Oohs", "pitch_range": range(48, 80)},
|
| 9863 |
+
{"name": "Synth Voice", "pitch_range": range(48, 85)},
|
| 9864 |
+
{"name": "Orchestra Hit", "pitch_range": range(48, 73)},
|
| 9865 |
+
# Brass
|
| 9866 |
+
{"name": "Trumpet", "pitch_range": range(58, 95)},
|
| 9867 |
+
{"name": "Trombone", "pitch_range": range(34, 76)},
|
| 9868 |
+
{"name": "Tuba", "pitch_range": range(29, 56)},
|
| 9869 |
+
{"name": "Muted Trumpet", "pitch_range": range(58, 83)},
|
| 9870 |
+
{"name": "French Horn", "pitch_range": range(41, 78)},
|
| 9871 |
+
{"name": "Brass Section", "pitch_range": range(36, 97)},
|
| 9872 |
+
{"name": "Synth Brass 1", "pitch_range": range(36, 97)},
|
| 9873 |
+
{"name": "Synth Brass 2", "pitch_range": range(36, 97)},
|
| 9874 |
+
# Reed
|
| 9875 |
+
{"name": "Soprano Sax", "pitch_range": range(54, 88)},
|
| 9876 |
+
{"name": "Alto Sax", "pitch_range": range(49, 81)},
|
| 9877 |
+
{"name": "Tenor Sax", "pitch_range": range(42, 76)},
|
| 9878 |
+
{"name": "Baritone Sax", "pitch_range": range(37, 69)},
|
| 9879 |
+
{"name": "Oboe", "pitch_range": range(58, 92)},
|
| 9880 |
+
{"name": "English Horn", "pitch_range": range(52, 82)},
|
| 9881 |
+
{"name": "Bassoon", "pitch_range": range(34, 73)},
|
| 9882 |
+
{"name": "Clarinet", "pitch_range": range(50, 92)},
|
| 9883 |
+
# Pipe
|
| 9884 |
+
{"name": "Piccolo", "pitch_range": range(74, 109)},
|
| 9885 |
+
{"name": "Flute", "pitch_range": range(60, 97)},
|
| 9886 |
+
{"name": "Recorder", "pitch_range": range(60, 97)},
|
| 9887 |
+
{"name": "Pan Flute", "pitch_range": range(60, 97)},
|
| 9888 |
+
{"name": "Blown Bottle", "pitch_range": range(60, 97)},
|
| 9889 |
+
{"name": "Shakuhachi", "pitch_range": range(55, 85)},
|
| 9890 |
+
{"name": "Whistle", "pitch_range": range(60, 97)},
|
| 9891 |
+
{"name": "Ocarina", "pitch_range": range(60, 85)},
|
| 9892 |
+
# Synth Lead
|
| 9893 |
+
{"name": "Lead 1 (square)", "pitch_range": range(21, 109)},
|
| 9894 |
+
{"name": "Lead 2 (sawtooth)", "pitch_range": range(21, 109)},
|
| 9895 |
+
{"name": "Lead 3 (calliope)", "pitch_range": range(36, 97)},
|
| 9896 |
+
{"name": "Lead 4 (chiff)", "pitch_range": range(36, 97)},
|
| 9897 |
+
{"name": "Lead 5 (charang)", "pitch_range": range(36, 97)},
|
| 9898 |
+
{"name": "Lead 6 (voice)", "pitch_range": range(36, 97)},
|
| 9899 |
+
{"name": "Lead 7 (fifths)", "pitch_range": range(36, 97)},
|
| 9900 |
+
{"name": "Lead 8 (bass + lead)", "pitch_range": range(21, 109)},
|
| 9901 |
+
# Synth Pad
|
| 9902 |
+
{"name": "Pad 1 (new age)", "pitch_range": range(36, 97)},
|
| 9903 |
+
{"name": "Pad 2 (warm)", "pitch_range": range(36, 97)},
|
| 9904 |
+
{"name": "Pad 3 (polysynth)", "pitch_range": range(36, 97)},
|
| 9905 |
+
{"name": "Pad 4 (choir)", "pitch_range": range(36, 97)},
|
| 9906 |
+
{"name": "Pad 5 (bowed)", "pitch_range": range(36, 97)},
|
| 9907 |
+
{"name": "Pad 6 (metallic)", "pitch_range": range(36, 97)},
|
| 9908 |
+
{"name": "Pad 7 (halo)", "pitch_range": range(36, 97)},
|
| 9909 |
+
{"name": "Pad 8 (sweep)", "pitch_range": range(36, 97)},
|
| 9910 |
+
# Synth SFX
|
| 9911 |
+
{"name": "FX 1 (rain)", "pitch_range": range(36, 97)},
|
| 9912 |
+
{"name": "FX 2 (soundtrack)", "pitch_range": range(36, 97)},
|
| 9913 |
+
{"name": "FX 3 (crystal)", "pitch_range": range(36, 97)},
|
| 9914 |
+
{"name": "FX 4 (atmosphere)", "pitch_range": range(36, 97)},
|
| 9915 |
+
{"name": "FX 5 (brightness)", "pitch_range": range(36, 97)},
|
| 9916 |
+
{"name": "FX 6 (goblins)", "pitch_range": range(36, 97)},
|
| 9917 |
+
{"name": "FX 7 (echoes)", "pitch_range": range(36, 97)},
|
| 9918 |
+
{"name": "FX 8 (sci-fi)", "pitch_range": range(36, 97)},
|
| 9919 |
+
# Ethnic Misc.
|
| 9920 |
+
{"name": "Sitar", "pitch_range": range(48, 78)},
|
| 9921 |
+
{"name": "Banjo", "pitch_range": range(48, 85)},
|
| 9922 |
+
{"name": "Shamisen", "pitch_range": range(50, 80)},
|
| 9923 |
+
{"name": "Koto", "pitch_range": range(55, 85)},
|
| 9924 |
+
{"name": "Kalimba", "pitch_range": range(48, 80)},
|
| 9925 |
+
{"name": "Bag pipe", "pitch_range": range(36, 78)},
|
| 9926 |
+
{"name": "Fiddle", "pitch_range": range(55, 97)},
|
| 9927 |
+
{"name": "Shanai", "pitch_range": range(48, 73)},
|
| 9928 |
+
# Percussive
|
| 9929 |
+
{"name": "Tinkle Bell", "pitch_range": range(72, 85)},
|
| 9930 |
+
{"name": "Agogo", "pitch_range": range(60, 73)},
|
| 9931 |
+
{"name": "Steel Drums", "pitch_range": range(52, 77)},
|
| 9932 |
+
{"name": "Woodblock", "pitch_range": range(128)},
|
| 9933 |
+
{"name": "Taiko Drum", "pitch_range": range(128)},
|
| 9934 |
+
{"name": "Melodic Tom", "pitch_range": range(128)},
|
| 9935 |
+
{"name": "Synth Drum", "pitch_range": range(128)},
|
| 9936 |
+
{"name": "Reverse Cymbal", "pitch_range": range(128)},
|
| 9937 |
+
# SFX
|
| 9938 |
+
{"name": "Guitar Fret Noise, Guitar Cutting Noise", "pitch_range": range(128)},
|
| 9939 |
+
{"name": "Breath Noise, Flute Key Click", "pitch_range": range(128)},
|
| 9940 |
+
{
|
| 9941 |
+
"name": "Seashore, Rain, Thunder, Wind, Stream, Bubbles",
|
| 9942 |
+
"pitch_range": range(128),
|
| 9943 |
+
},
|
| 9944 |
+
{"name": "Bird Tweet, Dog, Horse Gallop", "pitch_range": range(128)},
|
| 9945 |
+
{
|
| 9946 |
+
"name": "Telephone Ring, Door Creaking, Door, Scratch, Wind Chime",
|
| 9947 |
+
"pitch_range": range(128),
|
| 9948 |
+
},
|
| 9949 |
+
{"name": "Helicopter, Car Sounds", "pitch_range": range(128)},
|
| 9950 |
+
{
|
| 9951 |
+
"name": "Applause, Laughing, Screaming, Punch, Heart Beat, Footstep",
|
| 9952 |
+
"pitch_range": range(128),
|
| 9953 |
+
},
|
| 9954 |
+
{"name": "Gunshot, Machine Gun, Lasergun, Explosion", "pitch_range": range(128)},
|
| 9955 |
+
]
|
| 9956 |
+
|
| 9957 |
+
INSTRUMENTS_CLASSES = [
|
| 9958 |
+
{"name": "Piano", "program_range": range(8)}, # 0
|
| 9959 |
+
{"name": "Chromatic Percussion", "program_range": range(8, 16)},
|
| 9960 |
+
{"name": "Organ", "program_range": range(16, 24)},
|
| 9961 |
+
{"name": "Guitar", "program_range": range(24, 32)},
|
| 9962 |
+
{"name": "Bass", "program_range": range(32, 40)},
|
| 9963 |
+
{"name": "Strings", "program_range": range(40, 48)}, # 5
|
| 9964 |
+
{"name": "Ensemble", "program_range": range(48, 56)},
|
| 9965 |
+
{"name": "Brass", "program_range": range(56, 64)},
|
| 9966 |
+
{"name": "Reed", "program_range": range(64, 72)},
|
| 9967 |
+
{"name": "Pipe", "program_range": range(72, 80)},
|
| 9968 |
+
{"name": "Synth Lead", "program_range": range(80, 88)}, # 10
|
| 9969 |
+
{"name": "Synth Pad", "program_range": range(88, 96)},
|
| 9970 |
+
{"name": "Synth Effects", "program_range": range(96, 104)},
|
| 9971 |
+
{"name": "Ethnic", "program_range": range(104, 112)},
|
| 9972 |
+
{"name": "Percussive", "program_range": range(112, 120)},
|
| 9973 |
+
{"name": "Sound Effects", "program_range": range(120, 128)}, # 15
|
| 9974 |
+
{"name": "Drums", "program_range": range(-1, 0)},
|
| 9975 |
+
]
|
| 9976 |
+
|
| 9977 |
+
# To easily get the class index of any instrument program
|
| 9978 |
+
CLASS_OF_INST = [
|
| 9979 |
+
i
|
| 9980 |
+
for i, inst_class in enumerate(INSTRUMENTS_CLASSES)
|
| 9981 |
+
for _ in inst_class["program_range"]
|
| 9982 |
+
]
|
| 9983 |
+
|
| 9984 |
+
# index i = program i+1 in the GM2 specs (8. Appendix B)
|
| 9985 |
+
# index i = program i retrieved by packages
|
| 9986 |
+
DRUMS_SETS = {
|
| 9987 |
+
0: "Standard",
|
| 9988 |
+
8: "Room",
|
| 9989 |
+
16: "Power",
|
| 9990 |
+
24: "Electronic",
|
| 9991 |
+
25: "Analog",
|
| 9992 |
+
32: "Jazz",
|
| 9993 |
+
40: "Brush",
|
| 9994 |
+
48: "Orchestra",
|
| 9995 |
+
56: "SFX",
|
| 9996 |
+
}
|
| 9997 |
+
|
| 9998 |
+
# Control changes list (without specifications):
|
| 9999 |
+
# https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2
|
| 10000 |
+
# Undefined and general control changes are not considered here
|
| 10001 |
+
# All these attributes can take values from 0 to 127, with some of them being on/off
|
| 10002 |
+
CONTROL_CHANGES = {
|
| 10003 |
+
# MSB
|
| 10004 |
+
0: "Bank Select",
|
| 10005 |
+
1: "Modulation Depth",
|
| 10006 |
+
2: "Breath Controller",
|
| 10007 |
+
4: "Foot Controller",
|
| 10008 |
+
5: "Portamento Time",
|
| 10009 |
+
6: "Data Entry",
|
| 10010 |
+
7: "Channel Volume",
|
| 10011 |
+
8: "Balance",
|
| 10012 |
+
10: "Pan",
|
| 10013 |
+
11: "Expression Controller",
|
| 10014 |
+
# LSB
|
| 10015 |
+
32: "Bank Select",
|
| 10016 |
+
33: "Modulation Depth",
|
| 10017 |
+
34: "Breath Controller",
|
| 10018 |
+
36: "Foot Controller",
|
| 10019 |
+
37: "Portamento Time",
|
| 10020 |
+
38: "Data Entry",
|
| 10021 |
+
39: "Channel Volume",
|
| 10022 |
+
40: "Balance",
|
| 10023 |
+
42: "Pan",
|
| 10024 |
+
43: "Expression Controller",
|
| 10025 |
+
# On / Off control changes, ≤63 off, ≥64 on
|
| 10026 |
+
64: "Damper Pedal",
|
| 10027 |
+
65: "Portamento",
|
| 10028 |
+
66: "Sostenuto",
|
| 10029 |
+
67: "Soft Pedal",
|
| 10030 |
+
68: "Legato Footswitch",
|
| 10031 |
+
69: "Hold 2",
|
| 10032 |
+
# Continuous controls
|
| 10033 |
+
70: "Sound Variation",
|
| 10034 |
+
71: "Timbre/Harmonic Intensity",
|
| 10035 |
+
72: "Release Time",
|
| 10036 |
+
73: "Attack Time",
|
| 10037 |
+
74: "Brightness",
|
| 10038 |
+
75: "Decay Time",
|
| 10039 |
+
76: "Vibrato Rate",
|
| 10040 |
+
77: "Vibrato Depth",
|
| 10041 |
+
78: "Vibrato Delay",
|
| 10042 |
+
84: "Portamento Control",
|
| 10043 |
+
88: "High Resolution Velocity Prefix",
|
| 10044 |
+
# Effects depths
|
| 10045 |
+
91: "Reverb Depth",
|
| 10046 |
+
92: "Tremolo Depth",
|
| 10047 |
+
93: "Chorus Depth",
|
| 10048 |
+
94: "Celeste Depth",
|
| 10049 |
+
95: "Phaser Depth",
|
| 10050 |
+
# Registered parameters numbers
|
| 10051 |
+
96: "Data Increment",
|
| 10052 |
+
97: "Data Decrement",
|
| 10053 |
+
# 98: 'Non-Registered Parameter Number (NRPN) - LSB',
|
| 10054 |
+
# 99: 'Non-Registered Parameter Number (NRPN) - MSB',
|
| 10055 |
+
100: "Registered Parameter Number (RPN) - LSB",
|
| 10056 |
+
101: "Registered Parameter Number (RPN) - MSB",
|
| 10057 |
+
# Channel mode controls
|
| 10058 |
+
120: "All Sound Off",
|
| 10059 |
+
121: "Reset All Controllers",
|
| 10060 |
+
122: "Local Control On/Off",
|
| 10061 |
+
123: "All Notes Off",
|
| 10062 |
+
124: "Omni Mode Off", # + all notes off
|
| 10063 |
+
125: "Omni Mode On", # + all notes off
|
| 10064 |
+
126: "Mono Mode On", # + poly off, + all notes off
|
| 10065 |
+
127: "Poly Mode On", # + mono off, +all notes off
|
| 10066 |
+
}
|
| 10067 |
+
|
| 10068 |
+
###################################################################################
|
| 10069 |
+
|
| 10070 |
+
def patches_onset_times(escore_notes, times_idx=1, patches_idx=6):
|
| 10071 |
+
|
| 10072 |
+
patches = [e[patches_idx] for e in escore_notes]
|
| 10073 |
+
|
| 10074 |
+
patches_oset = ordered_set(patches)
|
| 10075 |
+
|
| 10076 |
+
patches_onset_times = []
|
| 10077 |
+
|
| 10078 |
+
for p in patches_oset:
|
| 10079 |
+
for e in escore_notes:
|
| 10080 |
+
if e[patches_idx] == p:
|
| 10081 |
+
patches_onset_times.append([p, e[times_idx]])
|
| 10082 |
+
break
|
| 10083 |
+
|
| 10084 |
+
return patches_onset_times
|
| 10085 |
+
|
| 10086 |
+
###################################################################################
|
| 10087 |
+
|
| 10088 |
+
def count_escore_notes_patches(escore_notes, patches_idx=6):
|
| 10089 |
+
|
| 10090 |
+
patches = [e[patches_idx] for e in escore_notes]
|
| 10091 |
+
|
| 10092 |
+
return Counter(patches).most_common()
|
| 10093 |
+
|
| 10094 |
+
###################################################################################
|
| 10095 |
+
|
| 10096 |
+
def escore_notes_monoponic_melodies(escore_notes,
|
| 10097 |
+
bad_notes_ratio=0.0,
|
| 10098 |
+
times_idx=1,
|
| 10099 |
+
patches_idx=6
|
| 10100 |
+
):
|
| 10101 |
+
|
| 10102 |
+
patches = escore_notes_patches(escore_notes, patches_index=patches_idx)
|
| 10103 |
+
|
| 10104 |
+
monophonic_melodies = []
|
| 10105 |
+
|
| 10106 |
+
for p in patches:
|
| 10107 |
+
patch_score = [e for e in escore_notes if e[patches_idx] == p]
|
| 10108 |
+
|
| 10109 |
+
ps_times = [e[times_idx] for e in patch_score]
|
| 10110 |
+
|
| 10111 |
+
if len(ps_times) <= len(set(ps_times)) * (1+bad_notes_ratio):
|
| 10112 |
+
monophonic_melodies.append([p, len(patch_score)])
|
| 10113 |
+
|
| 10114 |
+
return monophonic_melodies
|
| 10115 |
+
|
| 10116 |
+
###################################################################################
|
| 10117 |
+
|
| 10118 |
+
from itertools import groupby
|
| 10119 |
+
from operator import itemgetter
|
| 10120 |
+
|
| 10121 |
+
def group_by_threshold(data, threshold, groupby_idx):
|
| 10122 |
+
|
| 10123 |
+
data.sort(key=itemgetter(groupby_idx))
|
| 10124 |
+
|
| 10125 |
+
grouped_data = []
|
| 10126 |
+
cluster = []
|
| 10127 |
+
|
| 10128 |
+
for i, item in enumerate(data):
|
| 10129 |
+
if not cluster:
|
| 10130 |
+
cluster.append(item)
|
| 10131 |
+
elif abs(item[groupby_idx] - cluster[-1][groupby_idx]) <= threshold:
|
| 10132 |
+
cluster.append(item)
|
| 10133 |
+
else:
|
| 10134 |
+
grouped_data.append(cluster)
|
| 10135 |
+
cluster = [item]
|
| 10136 |
+
|
| 10137 |
+
if cluster:
|
| 10138 |
+
grouped_data.append(cluster)
|
| 10139 |
+
|
| 10140 |
+
return grouped_data
|
| 10141 |
+
|
| 10142 |
+
###################################################################################
|
| 10143 |
+
|
| 10144 |
+
def split_escore_notes_by_time(escore_notes, time_threshold=256):
|
| 10145 |
+
|
| 10146 |
+
dscore = delta_score_notes(escore_notes, timings_clip_value=time_threshold-1)
|
| 10147 |
+
|
| 10148 |
+
score_chunks = []
|
| 10149 |
+
|
| 10150 |
+
ctime = 0
|
| 10151 |
+
pchunk_idx = 0
|
| 10152 |
+
|
| 10153 |
+
for i, e in enumerate(dscore):
|
| 10154 |
+
|
| 10155 |
+
ctime += e[1]
|
| 10156 |
+
|
| 10157 |
+
if ctime >= time_threshold:
|
| 10158 |
+
score_chunks.append(escore_notes[pchunk_idx:i])
|
| 10159 |
+
pchunk_idx = i
|
| 10160 |
+
ctime = 0
|
| 10161 |
+
|
| 10162 |
+
return score_chunks
|
| 10163 |
+
|
| 10164 |
+
###################################################################################
|
| 10165 |
+
|
| 10166 |
+
def escore_notes_grouped_patches(escore_notes, time_threshold=256):
|
| 10167 |
+
|
| 10168 |
+
split_score_chunks = split_escore_notes_by_time(escore_notes,
|
| 10169 |
+
time_threshold=time_threshold
|
| 10170 |
+
)
|
| 10171 |
+
|
| 10172 |
+
chunks_patches = []
|
| 10173 |
+
|
| 10174 |
+
for s in split_score_chunks:
|
| 10175 |
+
chunks_patches.append(escore_notes_patches(s))
|
| 10176 |
+
|
| 10177 |
+
return chunks_patches
|
| 10178 |
+
|
| 10179 |
+
###################################################################################
|
| 10180 |
+
|
| 10181 |
+
def computeLPSArray(pattern, M, lps):
|
| 10182 |
+
length = 0
|
| 10183 |
+
i = 1
|
| 10184 |
+
|
| 10185 |
+
lps[0] = 0
|
| 10186 |
+
|
| 10187 |
+
while i < M:
|
| 10188 |
+
if pattern[i] == pattern[length]:
|
| 10189 |
+
length += 1
|
| 10190 |
+
lps[i] = length
|
| 10191 |
+
i += 1
|
| 10192 |
+
else:
|
| 10193 |
+
if length != 0:
|
| 10194 |
+
length = lps[length-1]
|
| 10195 |
+
else:
|
| 10196 |
+
lps[i] = 0
|
| 10197 |
+
i += 1
|
| 10198 |
+
|
| 10199 |
+
###################################################################################
|
| 10200 |
+
|
| 10201 |
+
def find_pattern_idxs(sub_pattern, pattern):
|
| 10202 |
+
|
| 10203 |
+
lst = pattern
|
| 10204 |
+
pattern = sub_pattern
|
| 10205 |
+
|
| 10206 |
+
M = len(pattern)
|
| 10207 |
+
N = len(lst)
|
| 10208 |
+
|
| 10209 |
+
lps = [0] * M
|
| 10210 |
+
j = 0 # index for pattern[]
|
| 10211 |
+
|
| 10212 |
+
computeLPSArray(pattern, M, lps)
|
| 10213 |
+
|
| 10214 |
+
i = 0 # index for lst[]
|
| 10215 |
+
indexes = []
|
| 10216 |
+
|
| 10217 |
+
while i < N:
|
| 10218 |
+
if pattern[j] == lst[i]:
|
| 10219 |
+
i += 1
|
| 10220 |
+
j += 1
|
| 10221 |
+
|
| 10222 |
+
if j == M:
|
| 10223 |
+
end_index = i - 1
|
| 10224 |
+
start_index = end_index - M + 1
|
| 10225 |
+
indexes.append((start_index, end_index))
|
| 10226 |
+
j = lps[j-1]
|
| 10227 |
+
elif i < N and pattern[j] != lst[i]:
|
| 10228 |
+
if j != 0:
|
| 10229 |
+
j = lps[j-1]
|
| 10230 |
+
else:
|
| 10231 |
+
i += 1
|
| 10232 |
+
|
| 10233 |
+
return indexes
|
| 10234 |
+
|
| 10235 |
+
###################################################################################
|
| 10236 |
+
|
| 10237 |
+
def escore_notes_patch_lrno_patterns(escore_notes,
|
| 10238 |
+
patch=0,
|
| 10239 |
+
zero_score_timings=False,
|
| 10240 |
+
pitches_idx=4,
|
| 10241 |
+
patches_idx=6
|
| 10242 |
+
):
|
| 10243 |
+
|
| 10244 |
+
patch_escore = [e for e in escore_notes if e[patches_idx] == patch]
|
| 10245 |
+
|
| 10246 |
+
if patch_escore:
|
| 10247 |
+
|
| 10248 |
+
patch_cscore = chordify_score([1000, patch_escore])
|
| 10249 |
+
|
| 10250 |
+
patch_tscore = []
|
| 10251 |
+
|
| 10252 |
+
for c in patch_cscore:
|
| 10253 |
+
|
| 10254 |
+
tones_chord = sorted(set([p[pitches_idx] % 12 for p in c]))
|
| 10255 |
+
|
| 10256 |
+
if tones_chord not in ALL_CHORDS_SORTED:
|
| 10257 |
+
tnoes_chord = check_and_fix_tones_chord(tones_chord)
|
| 10258 |
+
|
| 10259 |
+
patch_tscore.append(ALL_CHORDS_SORTED.index(tones_chord))
|
| 10260 |
+
|
| 10261 |
+
pattern = find_lrno_pattern_fast(patch_tscore)
|
| 10262 |
+
|
| 10263 |
+
patterns_idxs = find_pattern_idxs(pattern, patch_tscore)
|
| 10264 |
+
|
| 10265 |
+
patch_lrno_scores = []
|
| 10266 |
+
|
| 10267 |
+
for idxs in patterns_idxs:
|
| 10268 |
+
|
| 10269 |
+
score = patch_escore[idxs[0]:idxs[1]]
|
| 10270 |
+
|
| 10271 |
+
if zero_score_timings:
|
| 10272 |
+
score = recalculate_score_timings(score)
|
| 10273 |
+
|
| 10274 |
+
patch_lrno_scores.append(score)
|
| 10275 |
+
|
| 10276 |
+
return patch_lrno_scores
|
| 10277 |
+
|
| 10278 |
+
else:
|
| 10279 |
+
return []
|
| 10280 |
+
|
| 10281 |
+
###################################################################################
|
| 10282 |
+
|
| 10283 |
+
ALL_BASE_CHORDS_SORTED = [[0], [0, 2], [0, 2, 4], [0, 2, 4, 6], [0, 2, 4, 6, 8], [0, 2, 4, 6, 8, 10],
|
| 10284 |
+
[0, 2, 4, 6, 9], [0, 2, 4, 6, 10], [0, 2, 4, 7], [0, 2, 4, 7, 9],
|
| 10285 |
+
[0, 2, 4, 7, 10], [0, 2, 4, 8], [0, 2, 4, 8, 10], [0, 2, 4, 9], [0, 2, 4, 10],
|
| 10286 |
+
[0, 2, 5], [0, 2, 5, 7], [0, 2, 5, 7, 9], [0, 2, 5, 7, 10], [0, 2, 5, 8],
|
| 10287 |
+
[0, 2, 5, 8, 10], [0, 2, 5, 9], [0, 2, 5, 10], [0, 2, 6], [0, 2, 6, 8],
|
| 10288 |
+
[0, 2, 6, 8, 10], [0, 2, 6, 9], [0, 2, 6, 10], [0, 2, 7], [0, 2, 7, 9],
|
| 10289 |
+
[0, 2, 7, 10], [0, 2, 8], [0, 2, 8, 10], [0, 2, 9], [0, 2, 10], [0, 3],
|
| 10290 |
+
[0, 3, 5], [0, 3, 5, 7], [0, 3, 5, 7, 9], [0, 3, 5, 7, 10], [0, 3, 5, 8],
|
| 10291 |
+
[0, 3, 5, 8, 10], [0, 3, 5, 9], [0, 3, 5, 10], [0, 3, 6], [0, 3, 6, 8],
|
| 10292 |
+
[0, 3, 6, 8, 10], [0, 3, 6, 9], [0, 3, 6, 10], [0, 3, 7], [0, 3, 7, 9],
|
| 10293 |
+
[0, 3, 7, 10], [0, 3, 8], [0, 3, 8, 10], [0, 3, 9], [0, 3, 10], [0, 4],
|
| 10294 |
+
[0, 4, 6], [0, 4, 6, 8], [0, 4, 6, 8, 10], [0, 4, 6, 9], [0, 4, 6, 10],
|
| 10295 |
+
[0, 4, 7], [0, 4, 7, 9], [0, 4, 7, 10], [0, 4, 8], [0, 4, 8, 10], [0, 4, 9],
|
| 10296 |
+
[0, 4, 10], [0, 5], [0, 5, 7], [0, 5, 7, 9], [0, 5, 7, 10], [0, 5, 8],
|
| 10297 |
+
[0, 5, 8, 10], [0, 5, 9], [0, 5, 10], [0, 6], [0, 6, 8], [0, 6, 8, 10],
|
| 10298 |
+
[0, 6, 9], [0, 6, 10], [0, 7], [0, 7, 9], [0, 7, 10], [0, 8], [0, 8, 10],
|
| 10299 |
+
[0, 9], [0, 10]]
|
| 10300 |
+
|
| 10301 |
###################################################################################
|
| 10302 |
#
|
| 10303 |
# This is the end of the TMIDI X Python module
|