我觉得能用了

This commit is contained in:
EillesWan 2024-02-24 21:31:39 +08:00
parent a4565b8529
commit 3831c41b9a
15 changed files with 930 additions and 647 deletions

View File

@ -17,8 +17,8 @@ Terms & Conditions: License.md in the root directory
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
__version__ = "1.7.4" __version__ = "1.8"
__vername__ = "部分音色更新" __vername__ = "音调总体偏移的处理支持"
__author__ = ( __author__ = (
("金羿", "Eilles Wan"), ("金羿", "Eilles Wan"),
("诸葛亮与八卦阵", "bgArray"), ("诸葛亮与八卦阵", "bgArray"),
@ -27,6 +27,7 @@ __author__ = (
) )
__all__ = [ __all__ = [
# 主要类 # 主要类
"MusicSequence",
"MidiConvert", "MidiConvert",
# 附加类 # 附加类
"SingleNote", "SingleNote",
@ -35,7 +36,7 @@ __all__ = [
# "TimeStamp", 未来功能 # "TimeStamp", 未来功能
# 默认值 # 默认值
"DEFAULT_PROGRESSBAR_STYLE", "DEFAULT_PROGRESSBAR_STYLE",
"MM_INSTRUMENT_DEVIATION_TABLE", "MM_INSTRUMENT_RANGE_TABLE",
"MM_CLASSIC_PITCHED_INSTRUMENT_TABLE", "MM_CLASSIC_PITCHED_INSTRUMENT_TABLE",
"MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE", "MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE",
"MM_TOUCH_PITCHED_INSTRUMENT_TABLE", "MM_TOUCH_PITCHED_INSTRUMENT_TABLE",

View File

@ -302,7 +302,7 @@ MIDI_PITCHED_NOTE_NAME_TABLE: Dict[int, Tuple[str, str]] = {
111: ("古提琴", "Fiddle"), 111: ("古提琴", "Fiddle"),
112: ("唢呐", "Shanai"), 112: ("唢呐", "Shanai"),
113: ("铃铛", "Tinkle Bell"), 113: ("铃铛", "Tinkle Bell"),
114: ("拉丁打", "Agogo"), 114: ("阿哥", "Agogo"),
115: ("钢鼓", "Steel Drums"), 115: ("钢鼓", "Steel Drums"),
116: ("木块", "Woodblock"), 116: ("木块", "Woodblock"),
117: ("太鼓", "Taiko Drum"), 117: ("太鼓", "Taiko Drum"),
@ -353,8 +353,8 @@ MIDI_PERCUSSION_NOTE_NAME_TABLE: Dict[int, Tuple[str, str]] = {
64: ("低音康加鼓", "Low Conga"), 64: ("低音康加鼓", "Low Conga"),
65: ("高音天巴鼓", "High Timbale"), 65: ("高音天巴鼓", "High Timbale"),
66: ("低音天巴鼓", "Low Timbale"), 66: ("低音天巴鼓", "Low Timbale"),
67: ("高音阿哥", "High Agogo"), 67: ("高音阿哥", "High Agogo"),
68: ("低音阿哥", "Low Agogo"), 68: ("低音阿哥", "Low Agogo"),
69: ("串珠", "Cabasa"), 69: ("串珠", "Cabasa"),
70: ("沙槌", "Maracas"), 70: ("沙槌", "Maracas"),
71: ("短口哨", "Short Whistle"), 71: ("短口哨", "Short Whistle"),
@ -414,402 +414,589 @@ MC_INSTRUMENT_BLOCKS_TABLE: Dict[str, Tuple[str, ...]] = {
# Midi对MC通用对照表 # Midi对MC通用对照表
MM_INSTRUMENT_DEVIATION_TABLE: Dict[str, int] = { MM_INSTRUMENT_RANGE_TABLE: Dict[str, Tuple[int, int]] = {
"note.harp": 6, "note.harp": (42, 66),
"note.pling": 6, "note.pling": (42, 66),
"note.guitar": 7, "note.guitar": (30, 54),
"note.iron_xylophone": 6, "note.iron_xylophone": (42, 66),
"note.bell": 4, "note.bell": (66, 90),
"note.xylophone": 4, "note.xylophone": (66, 90),
"note.chime": 4, "note.chime": (66, 90),
"note.banjo": 6, "note.banjo": (42, 66),
"note.flute": 5, "note.flute": (54, 78),
"note.bass": 8, "note.bass": (18, 42),
"note.snare": -1, "note.snare": (-1, 128), # 实际上是 0~127
"note.didgeridoo": 8, "note.didgeridoo": (18, 42),
"mob.zombie.wood": -1, "mob.zombie.wood": (-1, 128),
"note.bit": 6, "note.bit": (42, 66),
"note.hat": -1, "note.hat": (-1, 128),
"note.bd": -1, "note.bd": (-1, 128),
"firework.blast": -1, "note.basedrum": (-1, 128),
"firework.twinkle": -1, "firework.blast": (-1, 128),
"fire.ignite": -1, "firework.twinkle": (-1, 128),
"note.share": -1, "fire.ignite": (-1, 128),
"note.cow_bell": 5, "note.cow_bell": (54, 78),
} }
"""不同乐器的音偏离对照表""" """不同乐器的音偏离对照表"""
# Midi乐器对MC乐器对照表 # Midi乐器对MC乐器对照表
MM_CLASSIC_PITCHED_INSTRUMENT_TABLE: Dict[int, Tuple[str, int]] = { MM_CLASSIC_PITCHED_INSTRUMENT_TABLE: Dict[int, str] = {
0: ("note.harp", 6), 0: "note.harp",
1: ("note.harp", 6), 1: "note.harp",
2: ("note.pling", 6), 2: "note.pling",
3: ("note.harp", 6), 3: "note.harp",
4: ("note.pling", 6), 4: "note.pling",
5: ("note.pling", 6), 5: "note.pling",
6: ("note.harp", 6), 6: "note.harp",
7: ("note.harp", 6), 7: "note.harp",
8: ("note.share", -1), # 打击乐器无音域 8: "note.snare",
9: ("note.harp", 6), 9: "note.harp",
10: ("note.didgeridoo", 8), 10: "note.didgeridoo",
11: ("note.harp", 6), 11: "note.harp",
12: ("note.xylophone", 4), 12: "note.xylophone",
13: ("note.chime", 4), 13: "note.chime",
14: ("note.harp", 6), 14: "note.harp",
15: ("note.harp", 6), 15: "note.harp",
16: ("note.bass", 8), 16: "note.bass",
17: ("note.harp", 6), 17: "note.harp",
18: ("note.harp", 6), 18: "note.harp",
19: ("note.harp", 6), 19: "note.harp",
20: ("note.harp", 6), 20: "note.harp",
21: ("note.harp", 6), 21: "note.harp",
22: ("note.harp", 6), 22: "note.harp",
23: ("note.guitar", 7), 23: "note.guitar",
24: ("note.guitar", 7), 24: "note.guitar",
25: ("note.guitar", 7), 25: "note.guitar",
26: ("note.guitar", 7), 26: "note.guitar",
27: ("note.guitar", 7), 27: "note.guitar",
28: ("note.guitar", 7), 28: "note.guitar",
29: ("note.guitar", 7), 29: "note.guitar",
30: ("note.guitar", 7), 30: "note.guitar",
31: ("note.bass", 8), 31: "note.bass",
32: ("note.bass", 8), 32: "note.bass",
33: ("note.bass", 8), 33: "note.bass",
34: ("note.bass", 8), 34: "note.bass",
35: ("note.bass", 8), 35: "note.bass",
36: ("note.bass", 8), 36: "note.bass",
37: ("note.bass", 8), 37: "note.bass",
38: ("note.bass", 8), 38: "note.bass",
39: ("note.bass", 8), 39: "note.bass",
40: ("note.harp", 6), 40: "note.harp",
41: ("note.harp", 6), 41: "note.harp",
42: ("note.harp", 6), 42: "note.harp",
43: ("note.harp", 6), 43: "note.harp",
44: ("note.iron_xylophone", 6), 44: "note.iron_xylophone",
45: ("note.guitar", 7), 45: "note.guitar",
46: ("note.harp", 6), 46: "note.harp",
47: ("note.harp", 6), 47: "note.harp",
48: ("note.guitar", 7), 48: "note.guitar",
49: ("note.guitar", 7), 49: "note.guitar",
50: ("note.bit", 6), 50: "note.bit",
51: ("note.bit", 6), 51: "note.bit",
52: ("note.harp", 6), 52: "note.harp",
53: ("note.harp", 6), 53: "note.harp",
54: ("note.bit", 6), 54: "note.bit",
55: ("note.flute", 5), 55: "note.flute",
56: ("note.flute", 5), 56: "note.flute",
57: ("note.flute", 5), 57: "note.flute",
58: ("note.flute", 5), 58: "note.flute",
59: ("note.flute", 5), 59: "note.flute",
60: ("note.flute", 5), 60: "note.flute",
61: ("note.flute", 5), 61: "note.flute",
62: ("note.flute", 5), 62: "note.flute",
63: ("note.flute", 5), 63: "note.flute",
64: ("note.bit", 6), 64: "note.bit",
65: ("note.bit", 6), 65: "note.bit",
66: ("note.bit", 6), 66: "note.bit",
67: ("note.bit", 6), 67: "note.bit",
68: ("note.flute", 5), 68: "note.flute",
69: ("note.harp", 6), 69: "note.harp",
70: ("note.harp", 6), 70: "note.harp",
71: ("note.flute", 5), 71: "note.flute",
72: ("note.flute", 5), 72: "note.flute",
73: ("note.flute", 5), 73: "note.flute",
74: ("note.harp", 6), 74: "note.harp",
75: ("note.flute", 5), 75: "note.flute",
76: ("note.harp", 6), 76: "note.harp",
77: ("note.harp", 6), 77: "note.harp",
78: ("note.harp", 6), 78: "note.harp",
79: ("note.harp", 6), 79: "note.harp",
80: ("note.bit", 6), 80: "note.bit",
81: ("note.bit", 6), 81: "note.bit",
82: ("note.bit", 6), 82: "note.bit",
83: ("note.bit", 6), 83: "note.bit",
84: ("note.bit", 6), 84: "note.bit",
85: ("note.bit", 6), 85: "note.bit",
86: ("note.bit", 6), 86: "note.bit",
87: ("note.bit", 6), 87: "note.bit",
88: ("note.bit", 6), 88: "note.bit",
89: ("note.bit", 6), 89: "note.bit",
90: ("note.bit", 6), 90: "note.bit",
91: ("note.bit", 6), 91: "note.bit",
92: ("note.bit", 6), 92: "note.bit",
93: ("note.bit", 6), 93: "note.bit",
94: ("note.bit", 6), 94: "note.bit",
95: ("note.bit", 6), 95: "note.bit",
96: ("note.bit", 6), 96: "note.bit",
97: ("note.bit", 6), 97: "note.bit",
98: ("note.bit", 6), 98: "note.bit",
99: ("note.bit", 6), 99: "note.bit",
100: ("note.bit", 6), 100: "note.bit",
101: ("note.bit", 6), 101: "note.bit",
102: ("note.bit", 6), 102: "note.bit",
103: ("note.bit", 6), 103: "note.bit",
104: ("note.harp", 6), 104: "note.harp",
105: ("note.banjo", 6), 105: "note.banjo",
106: ("note.harp", 6), 106: "note.harp",
107: ("note.harp", 6), 107: "note.harp",
108: ("note.harp", 6), 108: "note.harp",
109: ("note.harp", 6), 109: "note.harp",
110: ("note.harp", 6), 110: "note.harp",
111: ("note.guitar", 7), 111: "note.guitar",
112: ("note.harp", 6), 112: "note.harp",
113: ("note.bell", 4), 113: "note.bell",
114: ("note.harp", 6), 114: "note.harp",
115: ("note.cow_bell", 5), 115: "note.cow_bell",
116: ("note.bd", -1), # 打击乐器无音域 116: "note.bd",
117: ("note.bass", 8), 117: "note.bass",
118: ("note.bit", 6), 118: "note.bit",
119: ("note.bd", -1), # 打击乐器无音域 119: "note.bd",
120: ("note.guitar", 7), 120: "note.guitar",
121: ("note.harp", 6), 121: "note.harp",
122: ("note.harp", 6), 122: "note.harp",
123: ("note.harp", 6), 123: "note.harp",
124: ("note.harp", 6), 124: "note.harp",
125: ("note.hat", -1), # 打击乐器无音域 125: "note.hat",
126: ("note.bd", -1), # 打击乐器无音域 126: "note.bd",
127: ("note.snare", -1), # 打击乐器无音域 127: "note.snare",
} }
"""“经典”乐音乐器对照表""" """“经典”乐音乐器对照表"""
MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE: Dict[int, Tuple[str, int]] = { MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE: Dict[int, str] = {
34: ("note.bd", -1), 34: "note.bd",
35: ("note.bd", -1), 35: "note.bd",
36: ("note.hat", -1), 36: "note.hat",
37: ("note.snare", -1), 37: "note.snare",
38: ("note.snare", -1), 38: "note.snare",
39: ("note.snare", -1), 39: "note.snare",
40: ("note.hat", -1), 40: "note.hat",
41: ("note.snare", -1), 41: "note.snare",
42: ("note.hat", -1), 42: "note.hat",
43: ("note.snare", -1), 43: "note.snare",
44: ("note.snare", -1), 44: "note.snare",
45: ("note.bell", 4), 45: "note.bell",
46: ("note.snare", -1), 46: "note.snare",
47: ("note.snare", -1), 47: "note.snare",
48: ("note.bell", 4), 48: "note.bell",
49: ("note.hat", -1), 49: "note.hat",
50: ("note.bell", 4), 50: "note.bell",
51: ("note.bell", 4), 51: "note.bell",
52: ("note.bell", 4), 52: "note.bell",
53: ("note.bell", 4), 53: "note.bell",
54: ("note.bell", 4), 54: "note.bell",
55: ("note.bell", 4), 55: "note.bell",
56: ("note.snare", -1), 56: "note.snare",
57: ("note.hat", -1), 57: "note.hat",
58: ("note.chime", 4), 58: "note.chime",
59: ("note.iron_xylophone", 6), 59: "note.iron_xylophone",
60: ("note.bd", -1), 60: "note.bd",
61: ("note.bd", -1), 61: "note.bd",
62: ("note.xylophone", 4), 62: "note.xylophone",
63: ("note.xylophone", 4), 63: "note.xylophone",
64: ("note.xylophone", 4), 64: "note.xylophone",
65: ("note.hat", -1), 65: "note.hat",
66: ("note.bell", 4), 66: "note.bell",
67: ("note.bell", 4), 67: "note.bell",
68: ("note.hat", -1), 68: "note.hat",
69: ("note.hat", -1), 69: "note.hat",
70: ("note.snare", -1), 70: "note.snare",
71: ("note.flute", 5), 71: "note.flute",
72: ("note.hat", -1), 72: "note.hat",
73: ("note.hat", -1), 73: "note.hat",
74: ("note.xylophone", 4), 74: "note.xylophone",
75: ("note.hat", -1), 75: "note.hat",
76: ("note.hat", -1), 76: "note.hat",
77: ("note.xylophone", 4), 77: "note.xylophone",
78: ("note.xylophone", 4), 78: "note.xylophone",
79: ("note.bell", 4), 79: "note.bell",
80: ("note.bell", 4), 80: "note.bell",
} }
"""“经典”打击乐器对照表""" """“经典”打击乐器对照表"""
# 以下是由 Touch “偷吃” 带来的高准确率音对照表 # 以下是由 Touch “偷吃” 带来的高准确率音对照表
# 包括乐音乐器对照和打击乐器对照 # 包括乐音乐器对照和打击乐器对照
MM_TOUCH_PITCHED_INSTRUMENT_TABLE: Dict[int, Tuple[str, int]] = { MM_TOUCH_PITCHED_INSTRUMENT_TABLE: Dict[int, str] = {
0: ("note.harp", 6), 0: "note.harp",
1: ("note.harp", 6), 1: "note.harp",
2: ("note.pling", 6), 2: "note.pling",
3: ("note.harp", 6), 3: "note.harp",
4: ("note.pling", 6), 4: "note.pling",
5: ("note.pling", 6), 5: "note.pling",
6: ("note.guitar", 7), 6: "note.guitar",
7: ("note.guitar", 7), 7: "note.guitar",
8: ("note.iron_xylophone", 8), 8: "note.iron_xylophone",
9: ("note.bell", 4), # 打击乐器无音域 9: "note.bell",
10: ("note.iron_xylophone", 6), 10: "note.iron_xylophone",
11: ("note.iron_xylophone", 6), 11: "note.iron_xylophone",
12: ("note.iron_xylophone", 6), 12: "note.iron_xylophone",
13: ("note.xylophone", 4), 13: "note.xylophone",
14: ("note.chime", 4), 14: "note.chime",
15: ("note.banjo", 6), 15: "note.banjo",
16: ("note.xylophone", 6), 16: "note.xylophone",
17: ("note.iron_xylophone", 6), 17: "note.iron_xylophone",
18: ("note.flute", 5), 18: "note.flute",
19: ("note.flute", 5), 19: "note.flute",
20: ("note.flute", 5), 20: "note.flute",
21: ("note.flute", 5), 21: "note.flute",
22: ("note.flute", 5), 22: "note.flute",
23: ("note.flute", 5), 23: "note.flute",
24: ("note.guitar", 7), 24: "note.guitar",
25: ("note.guitar", 7), 25: "note.guitar",
26: ("note.guitar", 7), 26: "note.guitar",
27: ("note.guitar", 7), 27: "note.guitar",
28: ("note.guitar", 7), 28: "note.guitar",
29: ("note.guitar", 7), 29: "note.guitar",
30: ("note.guitar", 7), 30: "note.guitar",
31: ("note.bass", 8), 31: "note.bass",
32: ("note.bass", 8), 32: "note.bass",
33: ("note.bass", 8), 33: "note.bass",
34: ("note.bass", 8), 34: "note.bass",
35: ("note.bass", 8), 35: "note.bass",
36: ("note.bass", 8), 36: "note.bass",
37: ("note.bass", 8), 37: "note.bass",
38: ("note.bass", 8), 38: "note.bass",
39: ("note.bass", 8), 39: "note.bass",
40: ("note.flute", 5), 40: "note.flute",
41: ("note.flute", 5), 41: "note.flute",
42: ("note.flute", 5), 42: "note.flute",
43: ("note.bass", 8), 43: "note.bass",
44: ("note.flute", 5), 44: "note.flute",
45: ("note.iron_xylophone", 6), 45: "note.iron_xylophone",
46: ("note.harp", 6), 46: "note.harp",
47: ("note.snare", -1), 47: "note.snare",
48: ("note.flute", 5), 48: "note.flute",
49: ("note.flute", 5), 49: "note.flute",
50: ("note.flute", 5), 50: "note.flute",
51: ("note.flute", 5), 51: "note.flute",
52: ("note.didgeridoo", 5), 52: "note.didgeridoo",
53: ("note.flute", 5), # 合唱“啊”音 53: "note.flute",
54: ("note.flute", 5), # 人声“嘟”音 54: "note.flute",
55: ("mob.zombie.wood", -1), # 合成人声 55: "mob.zombie.wood",
56: ("note.flute", 5), 56: "note.flute",
57: ("note.flute", 5), 57: "note.flute",
58: ("note.flute", 5), 58: "note.flute",
59: ("note.flute", 5), 59: "note.flute",
60: ("note.flute", 5), 60: "note.flute",
61: ("note.flute", 5), 61: "note.flute",
62: ("note.flute", 5), 62: "note.flute",
63: ("note.flute", 5), 63: "note.flute",
64: ("note.bit", 6), 64: "note.bit",
65: ("note.bit", 6), 65: "note.bit",
66: ("note.bit", 6), 66: "note.bit",
67: ("note.bit", 6), 67: "note.bit",
68: ("note.flute", 5), 68: "note.flute",
69: ("note.bit", 6), 69: "note.bit",
70: ("note.banjo", 6), 70: "note.banjo",
71: ("note.flute", 5), 71: "note.flute",
72: ("note.flute", 5), 72: "note.flute",
73: ("note.flute", 5), 73: "note.flute",
74: ("note.flute", 5), 74: "note.flute",
75: ("note.flute", 5), 75: "note.flute",
76: ("note.iron_xylophone", 6), 76: "note.iron_xylophone",
77: ("note.iron_xylophone", 6), 77: "note.iron_xylophone",
78: ("note.flute", 5), 78: "note.flute",
79: ("note.flute", 5), 79: "note.flute",
80: ("note.bit", 6), 80: "note.bit",
81: ("note.bit", 6), 81: "note.bit",
82: ("note.flute", 5), 82: "note.flute",
83: ("note.flute", 5), 83: "note.flute",
84: ("note.guitar", 7), 84: "note.guitar",
85: ("note.flute", 5), 85: "note.flute",
86: ("note.bass", 8), 86: "note.bass",
87: ("note.bass", 8), 87: "note.bass",
88: ("note.bit", 6), 88: "note.bit",
89: ("note.flute", 5), 89: "note.flute",
90: ("note.bit", 6), 90: "note.bit",
91: ("note.flute", 5), 91: "note.flute",
92: ("note.bell", 4), 92: "note.bell",
93: ("note.guitar", 7), 93: "note.guitar",
94: ("note.flute", 5), 94: "note.flute",
95: ("note.bit", 6), 95: "note.bit",
96: ("note.bit", 6), # 雨声 96: "note.bit",
97: ("note.flute", 5), 97: "note.flute",
98: ("note.bell", 4), 98: "note.bell",
99: ("note.bit", 6), # 大气 99: "note.bit",
100: ("note.bit", 6), # 明亮 100: "note.bit",
101: ("note.bit", 6), # 鬼怪 101: "note.bit",
102: ("note.bit", 6), # 回声 102: "note.bit",
103: ("note.bit", 6), # 科幻 103: "note.bit",
104: ("note.iron_xylophone", 6), 104: "note.iron_xylophone",
105: ("note.banjo", 6), 105: "note.banjo",
106: ("note.harp", 6), 106: "note.harp",
107: ("note.harp", 6), 107: "note.harp",
108: ("note.bell", 4), 108: "note.bell",
109: ("note.flute", 5), 109: "note.flute",
110: ("note.flute", 5), 110: "note.flute",
111: ("note.flute", 5), 111: "note.flute",
112: ("note.bell", 4), 112: "note.bell",
113: ("note.xylophone", 4), 113: "note.xylophone",
114: ("note.flute", 5), 114: "note.flute",
115: ("note.hat", -1), # 打击乐器无音域 115: "note.hat",
116: ("note.snare", -1), # 打击乐器无音域 116: "note.snare",
117: ("note.snare", -1), # 打击乐器无音域 117: "note.snare",
118: ("note.bd", -1), # 打击乐器无音域 118: "note.bd",
119: ("firework.blast", -1), # 打击乐器无音域 119: "firework.blast",
120: ("note.guitar", 7), # 吉他还把杂音 120: "note.guitar",
121: ("note.harp", 6), # 呼吸声 121: "note.harp",
122: ("note.harp", 6), # 海浪声 122: "note.harp",
123: ("note.harp", 6), # 鸟鸣 123: "note.harp",
124: ("note.bit", 6), 124: "note.bit",
125: ("note.hat", -1), # 直升机 125: "note.hat",
126: ("firework.twinkle", -1), # 打击乐器无音域 126: "firework.twinkle",
127: ("mob.zombie.wood", -1), # 打击乐器无音域 127: "mob.zombie.wood",
} }
"""“偷吃”乐音乐器对照表""" """“偷吃”乐音乐器对照表"""
MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE: Dict[int, Tuple[str, int]] = { MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE: Dict[int, str] = {
34: ("note.hat", -1), 34: "note.hat",
35: ("note.bd", -1), 35: "note.bd",
36: ("note.bd", -1), 36: "note.bd",
37: ("note.snare", -1), 37: "note.snare",
38: ("note.snare", -1), 38: "note.snare",
39: ("fire.ignite", 7), 39: "fire.ignite",
40: ("note.snare", -1), 40: "note.snare",
41: ("note.hat", -1), 41: "note.hat",
42: ("note.hat", -1), 42: "note.hat",
43: ("firework.blast", -1), 43: "firework.blast",
44: ("note.hat", -1), 44: "note.hat",
45: ("note.snare", -1), 45: "note.snare",
46: ("note.snare", -1), 46: "note.snare",
47: ("note.snare", -1), 47: "note.snare",
48: ("note.bell", 4), 48: "note.bell",
49: ("note.hat", -1), 49: "note.hat",
50: ("note.bell", 4), 50: "note.bell",
51: ("note.bell", 4), 51: "note.bell",
52: ("note.bell", 4), 52: "note.bell",
53: ("note.bell", 4), 53: "note.bell",
54: ("note.bell", 4), 54: "note.bell",
55: ("note.bell", 4), 55: "note.bell",
56: ("note.snare", -1), 56: "note.snare",
57: ("note.hat", -1), 57: "note.hat",
58: ("note.chime", 4), 58: "note.chime",
59: ("note.iron_xylophone", 6), 59: "note.iron_xylophone",
60: ("note.bd", -1), 60: "note.bd",
61: ("note.bd", -1), 61: "note.bd",
62: ("note.xylophone", 4), 62: "note.xylophone",
63: ("note.xylophone", 4), 63: "note.xylophone",
64: ("note.xylophone", 4), 64: "note.xylophone",
65: ("note.hat", -1), 65: "note.hat",
66: ("note.bell", 4), 66: "note.bell",
67: ("note.bell", 4), 67: "note.bell",
68: ("note.hat", -1), 68: "note.hat",
69: ("note.hat", -1), 69: "note.hat",
70: ("note.snare", -1), 70: "note.snare",
71: ("note.flute", 5), 71: "note.flute",
72: ("note.hat", -1), 72: "note.hat",
73: ("note.hat", -1), 73: "note.hat",
74: ("note.xylophone", 4), 74: "note.xylophone",
75: ("note.hat", -1), 75: "note.hat",
76: ("note.hat", -1), 76: "note.hat",
77: ("note.xylophone", 4), 77: "note.xylophone",
78: ("note.xylophone", 4), 78: "note.xylophone",
79: ("note.bell", 4), 79: "note.bell",
80: ("note.bell", 4), 80: "note.bell",
} }
"""“偷吃”打击乐器对照表""" """“偷吃”打击乐器对照表"""
# 以下是 Dislink “断联” 的音色对照表
# 包括乐音乐器对照和打击乐器对照
MM_DISLINK_PITCHED_INSTRUMENT_TABLE: Dict[int, str] = {
0: "note.harp",
1: "note.harp",
2: "note.pling",
3: "note.harp",
4: "note.harp",
5: "note.harp",
6: "note.harp",
7: "note.harp",
8: "note.iron_xylophone",
9: "note.bell",
10: "note.iron_xylophone",
11: "note.iron_xylophone",
12: "note.iron_xylophone",
13: "note.iron_xylophone",
14: "note.chime",
15: "note.iron_xylophone",
16: "note.harp",
17: "note.harp",
18: "note.harp",
19: "note.harp",
20: "note.harp",
21: "note.harp",
22: "note.harp",
23: "note.harp",
24: "note.guitar",
25: "note.guitar",
26: "note.guitar",
27: "note.guitar",
28: "note.guitar",
29: "note.guitar",
30: "note.guitar",
31: "note.guitar",
32: "note.bass",
33: "note.bass",
34: "note.bass",
35: "note.bass",
36: "note.bass",
37: "note.bass",
38: "note.bass",
39: "note.bass",
40: "note.harp",
41: "note.flute",
42: "note.flute",
43: "note.flute",
44: "note.flute",
45: "note.harp",
46: "note.harp",
47: "note.harp",
48: "note.harp",
49: "note.harp",
50: "note.harp",
51: "note.harp",
52: "note.harp",
53: "note.harp",
54: "note.harp",
55: "note.harp",
56: "note.harp",
57: "note.harp",
58: "note.harp",
59: "note.harp",
60: "note.harp",
61: "note.harp",
62: "note.harp",
63: "note.harp",
64: "note.harp",
65: "note.harp",
66: "note.harp",
67: "note.harp",
68: "note.harp",
69: "note.harp",
70: "note.harp",
71: "note.harp",
72: "note.flute",
73: "note.flute",
74: "note.flute",
75: "note.flute",
76: "note.flute",
77: "note.flute",
78: "note.flute",
79: "note.flute",
80: "note.bit",
81: "note.bit",
82: "note.harp",
83: "note.harp",
84: "note.harp",
85: "note.harp",
86: "note.harp",
87: "note.harp",
88: "note.harp",
89: "note.harp",
90: "note.harp",
91: "note.harp",
92: "note.harp",
93: "note.harp",
94: "note.harp",
95: "note.harp",
96: "note.harp",
97: "note.harp",
98: "note.harp",
99: "note.harp",
100: "note.harp",
101: "note.harp",
102: "note.harp",
103: "note.harp",
104: "note.harp",
105: "note.banjo",
106: "note.harp",
107: "note.harp",
108: "note.harp",
109: "note.harp",
110: "note.harp",
111: "note.harp",
112: "note.cow_bell",
113: "note.harp",
114: "note.harp",
115: "note.bd",
116: "note.bd",
117: "note.bd",
118: "note.bd",
119: "note.harp",
120: "note.harp",
121: "note.harp",
122: "note.harp",
123: "note.harp",
124: "note.harp",
125: "note.harp",
126: "note.harp",
127: "note.harp",
}
"""“断联”乐音乐器对照表"""
MM_DISLINK_PERCUSSION_INSTRUMENT_TABLE: Dict[int, str] = {
34: "note.bd",
35: "note.bd",
36: "note.snare",
37: "note.snare",
38: "note.bd",
39: "note.snare",
40: "note.bd",
41: "note.hat",
42: "note.bd",
43: "note.hat",
44: "note.bd",
45: "note.hat",
46: "note.bd",
47: "note.bd",
48: "note.bd",
49: "note.bd",
50: "note.bd",
51: "note.bd",
52: "note.bd",
53: "note.bd",
54: "note.bd",
55: "note.cow_bell",
56: "note.bd",
57: "note.bd",
58: "note.bd",
59: "note.bd",
60: "note.bd",
61: "note.bd",
62: "note.bd",
63: "note.bd",
64: "note.bd",
65: "note.bd",
66: "note.bd",
67: "note.bd",
68: "note.bd",
69: "note.bd",
70: "note.bd",
71: "note.bd",
72: "note.bd",
73: "note.bd",
74: "note.bd",
75: "note.bd",
76: "note.bd",
77: "note.bd",
78: "note.bd",
79: "note.bd",
80: "note.bd",
}
"""“断联”打击乐器对照表"""
# 即将启用 # 即将启用
# height2note = { # height2note = {
# 0.5: 0, # 0.5: 0,

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
存放一报错类型 存放一报错类型
""" """
""" """
@ -50,13 +50,13 @@ class MidiDestroyedError(MSCTBaseException):
super().__init__("MIDI文件损坏无法读取MIDI文件", *args) super().__init__("MIDI文件损坏无法读取MIDI文件", *args)
class MidiUnboundError(MSCTBaseException): # class MidiUnboundError(MSCTBaseException):
"""未定义Midi对象""" # """未定义Midi对象无用"""
def __init__(self, *args):
"""未绑定Midi对象"""
super().__init__("未定义MidiFile对象你甚至没有对象就想要生孩子", *args)
# def __init__(self, *args):
# """未绑定Midi对象"""
# super().__init__("未定义MidiFile对象你甚至没有对象就想要生孩子", *args)
# 此错误在本版本内已经不再使用
class CommandFormatError(RuntimeError): class CommandFormatError(RuntimeError):
"""指令格式与目标格式不匹配而引起的错误""" """指令格式与目标格式不匹配而引起的错误"""

View File

@ -24,6 +24,7 @@ from .main import (
MidiConvert, MidiConvert,
MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE, MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE,
MM_CLASSIC_PITCHED_INSTRUMENT_TABLE, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE,
mido,
) )
from .types import Tuple, List, Dict, ChannelType from .types import Tuple, List, Dict, ChannelType
@ -122,7 +123,7 @@ class FutureMidiConvertM4(MidiConvert):
notes_list: List[SingleNote] = [] notes_list: List[SingleNote] = []
# 此处 我们把通道视为音轨 # 此处 我们把通道视为音轨
for channel in self.to_music_note_channels().values(): for channel in self.channels.values():
for note in channel: for note in channel:
note.set_info( note.set_info(
note_to_command_parameters( note_to_command_parameters(
@ -132,8 +133,11 @@ class FutureMidiConvertM4(MidiConvert):
if note.percussive if note.percussive
else self.pitched_note_reference_table else self.pitched_note_reference_table
), ),
(max_volume) if note.track_no == 0 else (max_volume * 0.9), deviation=0,
self.volume_processing_function, volume_percentage=(
(max_volume) if note.track_no == 0 else (max_volume * 0.9)
),
volume_processing_method=self.volume_processing_function,
) )
) )
@ -180,6 +184,7 @@ class FutureMidiConvertM5(MidiConvert):
def to_music_channels( def to_music_channels(
self, self,
midi: mido.MidiFile,
) -> ChannelType: ) -> ChannelType:
""" """
使用金羿的转换思路将midi解析并转换为频道信息字典 使用金羿的转换思路将midi解析并转换为频道信息字典
@ -189,10 +194,11 @@ class FutureMidiConvertM5(MidiConvert):
以频道作为分割的Midi信息字典: 以频道作为分割的Midi信息字典:
Dict[int,Dict[int,List[Union[Tuple[Literal["PgmC"], int, int],Tuple[Literal["NoteS"], int, int, int],Tuple[Literal["NoteE"], int, int],]],],] Dict[int,Dict[int,List[Union[Tuple[Literal["PgmC"], int, int],Tuple[Literal["NoteS"], int, int, int],Tuple[Literal["NoteE"], int, int],]],],]
""" """
if self.midi is None:
raise MidiUnboundError( # if self.midi is None:
"你是否正在使用的是一个由 copy_important 生成的MidiConvert对象这是不可复用的。" # raise MidiUnboundError(
) # "你是否正在使用的是一个由 copy_important 生成的MidiConvert对象这是不可复用的。"
# )
# 一个midi中仅有16个通道 我们通过通道来识别而不是音轨 # 一个midi中仅有16个通道 我们通过通道来识别而不是音轨
midi_channels: ChannelType = empty_midi_channels() midi_channels: ChannelType = empty_midi_channels()
@ -200,7 +206,7 @@ class FutureMidiConvertM5(MidiConvert):
# 我们来用通道统计音乐信息 # 我们来用通道统计音乐信息
# 但是是用分轨的思路的 # 但是是用分轨的思路的
for track_no, track in enumerate(self.midi.tracks): for track_no, track in enumerate(midi.tracks):
microseconds = 0 microseconds = 0
if not track: if not track:
continue continue
@ -209,7 +215,7 @@ class FutureMidiConvertM5(MidiConvert):
for msg in track: for msg in track:
if msg.time != 0: if msg.time != 0:
microseconds += msg.time * tempo / self.midi.ticks_per_beat / 1000 microseconds += msg.time * tempo / midi.ticks_per_beat / 1000
if msg.is_meta: if msg.is_meta:
if msg.type == "set_tempo": if msg.type == "set_tempo":
@ -257,6 +263,7 @@ class FutureMidiConvertM5(MidiConvert):
# 神奇的偏移音 # 神奇的偏移音
def to_command_list_in_delay( def to_command_list_in_delay(
self, self,
midi: mido.MidiFile,
max_volume: float = 1.0, max_volume: float = 1.0,
speed: float = 1.0, speed: float = 1.0,
player_selector: str = "@a", player_selector: str = "@a",
@ -282,7 +289,9 @@ class FutureMidiConvertM5(MidiConvert):
raise ZeroSpeedError("播放速度仅可为正实数") raise ZeroSpeedError("播放速度仅可为正实数")
max_volume = 1 if max_volume > 1 else (0.001 if max_volume <= 0 else max_volume) max_volume = 1 if max_volume > 1 else (0.001 if max_volume <= 0 else max_volume)
self.to_music_channels() self.to_music_channels(
midi=midi,
)
tracks = {} tracks = {}
InstID = -1 InstID = -1
@ -304,12 +313,12 @@ class FutureMidiConvertM5(MidiConvert):
InstID = msg[1] InstID = msg[1]
elif msg[0] == "NoteS": elif msg[0] == "NoteS":
soundID, _X = ( soundID = (
inst_to_sould_with_deviation( midi_inst_to_mc_sould(
msg[1], MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE msg[1], MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE
) )
if SpecialBits if SpecialBits
else inst_to_sould_with_deviation( else midi_inst_to_mc_sould(
InstID, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE InstID, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE
) )
) )
@ -324,7 +333,7 @@ class FutureMidiConvertM5(MidiConvert):
+ ( + (
"" ""
if SpecialBits if SpecialBits
else f"{2 ** ((msg[1] - 60 - _X) / 12)}" else f"{2 ** ((msg[1] - 66) / 12)}"
) )
) )
except KeyError: except KeyError:
@ -334,7 +343,7 @@ class FutureMidiConvertM5(MidiConvert):
+ ( + (
"" ""
if SpecialBits if SpecialBits
else f"{2 ** ((msg[1] - 60 - _X) / 12)}" else f"{2 ** ((msg[1] - 66) / 12)}"
) )
] ]

View File

@ -70,21 +70,203 @@ tick * tempo / 1000000.0 / ticks_per_beat * 一秒多少游戏刻
""" """
VoidMido = Union[mido.MidiFile, None] # void mido # VoidMido = Union[mido.MidiFile, None] # void mido
""" # """
空Midi类类型 # 空Midi类类型
""" # """
# 已经成为历史了
@dataclass(init=False) @dataclass(init=False)
class MidiConvert: class MusicSequence:
"""
音乐曲谱序列存储类
"""
music_name: str
"""Midi乐曲名"""
channels: NoteChannelType
"""频道信息字典"""
def __init__(
self,
name_of_music: str,
channels_of_notes: NoteChannelType,
) -> None:
self.music_name = name_of_music
self.channels = channels_of_notes
@classmethod
def from_mido(
cls,
mido_file: mido.MidiFile,
midi_music_name,
default_tempo: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
mismatch_error_ignorance: bool = True,
):
return cls(
midi_music_name,
cls.to_music_note_channels(
midi=mido_file,
default_tempo_value=default_tempo,
ignore_mismatch_error=mismatch_error_ignorance,
),
)
def set_deviation(self, deviation_value: int):
self.music_deviation = deviation_value
def rename_music(self, new_name: str):
self.music_name = new_name
@staticmethod
def to_music_note_channels(
midi: mido.MidiFile,
default_tempo_value: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
ignore_mismatch_error: bool = True,
) -> NoteChannelType:
"""
将midi解析并转换为频道音符字典
Returns
-------
以频道作为分割的Midi音符列表字典:
Dict[int,List[SingleNote,]]
"""
# if midi is None:
# raise MidiUnboundError(
# "Midi参量为空。你是否正在使用的是一个由 copy_important 生成的MidiConvert对象这是不可复用的。"
# )
# 一个midi中仅有16个通道 我们通过通道来识别而不是音轨
midi_channels: NoteChannelType = empty_midi_channels(staff=[])
tempo = default_tempo_value
# 我们来用通道统计音乐信息
# 但是是用分轨的思路的
for track_no, track in enumerate(midi.tracks):
microseconds = 0
if not track:
continue
note_queue_A: Dict[
int,
List[
Tuple[
int,
int,
]
],
] = empty_midi_channels(staff=[])
note_queue_B: Dict[
int,
List[
Tuple[
int,
int,
]
],
] = empty_midi_channels(staff=[])
channel_program: Dict[int, int] = empty_midi_channels(staff=-1)
for msg in track:
if msg.time != 0:
microseconds += msg.time * tempo / midi.ticks_per_beat / 1000
if msg.is_meta:
if msg.type == "set_tempo":
tempo = msg.tempo
else:
if msg.type == "program_change":
channel_program[msg.channel] = msg.program
elif msg.type == "note_on" and msg.velocity != 0:
note_queue_A[msg.channel].append(
(msg.note, channel_program[msg.channel])
)
note_queue_B[msg.channel].append((msg.velocity, microseconds))
elif (msg.type == "note_off") or (
msg.type == "note_on" and msg.velocity == 0
):
if (msg.note, channel_program[msg.channel]) in note_queue_A[
msg.channel
]:
_velocity, _ms = note_queue_B[msg.channel][
note_queue_A[msg.channel].index(
(msg.note, channel_program[msg.channel])
)
]
note_queue_A[msg.channel].remove(
(msg.note, channel_program[msg.channel])
)
note_queue_B[msg.channel].remove((_velocity, _ms))
midi_channels[msg.channel].append(
SingleNote(
instrument=msg.note,
pitch=channel_program[msg.channel],
velocity=_velocity,
startime=_ms,
lastime=microseconds - _ms,
track_number=track_no,
is_percussion=True,
)
if msg.channel == 9
else SingleNote(
instrument=channel_program[msg.channel],
pitch=msg.note,
velocity=_velocity,
startime=_ms,
lastime=microseconds - _ms,
track_number=track_no,
is_percussion=False,
)
)
else:
if ignore_mismatch_error:
print(
"[WARRING] MIDI格式错误 音符不匹配 {} 无法在上文中找到与之匹配的音符开音消息".format(
msg
)
)
else:
raise NoteOnOffMismatchError(
"当前的MIDI很可能有损坏之嫌……",
msg,
"无法在上文中找到与之匹配的音符开音消息。",
)
"""整合后的音乐通道格式
每个通道包括若干消息元素其中逃不过这三种
1 切换乐器消息
("PgmC", 切换后的乐器ID: int, 距离演奏开始的毫秒)
2 音符开始消息
("NoteS", 开始的音符ID, 力度响度, 距离演奏开始的毫秒)
3 音符结束消息
("NoteE", 结束的音符ID, 距离演奏开始的毫秒)"""
del tempo
channels = dict(
[
(channel_no, sorted(channel_notes, key=lambda note: note.start_time))
for channel_no, channel_notes in midi_channels.items()
]
)
return channels
class MidiConvert(MusicSequence):
""" """
将Midi文件转换为我的世界内容 将Midi文件转换为我的世界内容
""" """
midi: VoidMido
"""MidiFile对象"""
pitched_note_reference_table: MidiInstrumentTableType pitched_note_reference_table: MidiInstrumentTableType
"""乐音乐器Midi-MC对照表""" """乐音乐器Midi-MC对照表"""
@ -94,18 +276,12 @@ class MidiConvert:
volume_processing_function: FittingFunctionType volume_processing_function: FittingFunctionType
"""音量处理函数""" """音量处理函数"""
midi_music_name: str
"""Midi乐曲名"""
enable_old_exe_format: bool enable_old_exe_format: bool
"""是否启用旧版execute指令格式""" """是否启用旧版execute指令格式"""
execute_cmd_head: str execute_cmd_head: str
"""execute指令头部""" """execute指令头部"""
channels: Union[ChannelType, NoteChannelType]
"""频道信息字典"""
music_command_list: List[SingleCommand] music_command_list: List[SingleCommand]
"""音乐指令列表""" """音乐指令列表"""
@ -115,10 +291,15 @@ class MidiConvert:
progress_bar_command: List[SingleCommand] progress_bar_command: List[SingleCommand]
"""进度条指令列表""" """进度条指令列表"""
music_deviation: int
"""音乐音调总偏移"""
def __init__( def __init__(
self, self,
midi_obj: VoidMido, midi_obj: mido.MidiFile,
midi_name: str, midi_name: str,
deviation: Union[int, Literal[None]] = 0,
ignore_mismatch_error: bool = True,
enable_old_exe_format: bool = False, enable_old_exe_format: bool = False,
pitched_note_rtable: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE, pitched_note_rtable: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_rtable: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE, percussion_note_rtable: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
@ -141,9 +322,15 @@ class MidiConvert:
打击乐器Midi-MC对照表 打击乐器Midi-MC对照表
""" """
self.midi: VoidMido = midi_obj super(MidiConvert, self).from_mido(
midi_obj,
midi_name,
mismatch_error_ignorance=ignore_mismatch_error,
)
self.midi_music_name: str = midi_name self.music_deviation = (
self.guess_deviation() if deviation is None else deviation
)
self.enable_old_exe_format: bool = enable_old_exe_format self.enable_old_exe_format: bool = enable_old_exe_format
@ -165,6 +352,7 @@ class MidiConvert:
def from_midi_file( def from_midi_file(
cls, cls,
midi_file_path: str, midi_file_path: str,
ignore_mismatch_error: bool = True,
old_exe_format: bool = False, old_exe_format: bool = False,
pitched_note_table: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE, pitched_note_table: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_table: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE, percussion_note_table: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
@ -192,9 +380,14 @@ class MidiConvert:
try: try:
return cls( return cls(
mido.MidiFile(midi_file_path, clip=True), mido.MidiFile(
midi_file_path,
clip=True,
),
midi_music_name, midi_music_name,
None,
old_exe_format, old_exe_format,
ignore_mismatch_error,
pitched_note_table, pitched_note_table,
percussion_note_table, percussion_note_table,
vol_processing_func, vol_processing_func,
@ -207,6 +400,11 @@ class MidiConvert:
# ……真的那么重要吗 # ……真的那么重要吗
# 我又几曾何时,知道祂真的会抛下我 # 我又几曾何时,知道祂真的会抛下我
def guess_deviation(self) -> int:
# 等我想想看
return 0
def form_progress_bar( def form_progress_bar(
self, self,
max_score: int, max_score: int,
@ -422,7 +620,7 @@ class MidiConvert:
npg_stl = ( npg_stl = (
pgs_style.replace("_", progressbar_style.played_style, i + 1) pgs_style.replace("_", progressbar_style.played_style, i + 1)
.replace("_", progressbar_style.to_play_style) .replace("_", progressbar_style.to_play_style)
.replace(r"%%N", self.midi_music_name) .replace(r"%%N", self.music_name)
.replace( .replace(
r"%%s", r"%%s",
'"},{"score":{"name":"*","objective":"' '"},{"score":{"name":"*","objective":"'
@ -482,145 +680,6 @@ class MidiConvert:
self.progress_bar_command = result self.progress_bar_command = result
return result return result
def to_music_note_channels(
self,
default_tempo_value: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
ignore_mismatch_error: bool = True,
) -> NoteChannelType:
"""
将midi解析并转换为频道音符字典
Returns
-------
以频道作为分割的Midi音符列表字典:
Dict[int,List[SingleNote,]]
"""
if self.midi is None:
raise MidiUnboundError(
"你是否正在使用的是一个由 copy_important 生成的MidiConvert对象这是不可复用的。"
)
# 一个midi中仅有16个通道 我们通过通道来识别而不是音轨
midi_channels: NoteChannelType = empty_midi_channels(staff=[])
tempo = default_tempo_value
# 我们来用通道统计音乐信息
# 但是是用分轨的思路的
for track_no, track in enumerate(self.midi.tracks):
microseconds = 0
if not track:
continue
note_queue_A: Dict[
int,
List[
Tuple[
int,
int,
]
],
] = empty_midi_channels(staff=[])
note_queue_B: Dict[
int,
List[
Tuple[
int,
int,
]
],
] = empty_midi_channels(staff=[])
channel_program: Dict[int, int] = empty_midi_channels(staff=-1)
for msg in track:
if msg.time != 0:
microseconds += msg.time * tempo / self.midi.ticks_per_beat / 1000
if msg.is_meta:
if msg.type == "set_tempo":
tempo = msg.tempo
else:
if msg.type == "program_change":
channel_program[msg.channel] = msg.program
elif msg.type == "note_on" and msg.velocity != 0:
note_queue_A[msg.channel].append(
(msg.note, channel_program[msg.channel])
)
note_queue_B[msg.channel].append((msg.velocity, microseconds))
elif (msg.type == "note_off") or (
msg.type == "note_on" and msg.velocity == 0
):
if (msg.note, channel_program[msg.channel]) in note_queue_A[
msg.channel
]:
_velocity, _ms = note_queue_B[msg.channel][
note_queue_A[msg.channel].index(
(msg.note, channel_program[msg.channel])
)
]
note_queue_A[msg.channel].remove(
(msg.note, channel_program[msg.channel])
)
note_queue_B[msg.channel].remove((_velocity, _ms))
midi_channels[msg.channel].append(
SingleNote(
instrument=msg.note,
pitch=channel_program[msg.channel],
velocity=_velocity,
startime=_ms,
lastime=microseconds - _ms,
track_number=track_no,
is_percussion=True,
)
if msg.channel == 9
else SingleNote(
instrument=channel_program[msg.channel],
pitch=msg.note,
velocity=_velocity,
startime=_ms,
lastime=microseconds - _ms,
track_number=track_no,
is_percussion=False,
)
)
else:
if ignore_mismatch_error:
print(
"[WARRING] MIDI格式错误 音符不匹配 {} 无法在上文中找到与之匹配的音符开音消息".format(
msg
)
)
else:
raise NoteOnOffMismatchError(
"当前的MIDI很可能有损坏之嫌……",
msg,
"无法在上文中找到与之匹配的音符开音消息。",
)
"""整合后的音乐通道格式
每个通道包括若干消息元素其中逃不过这三种
1 切换乐器消息
("PgmC", 切换后的乐器ID: int, 距离演奏开始的毫秒)
2 音符开始消息
("NoteS", 开始的音符ID, 力度响度, 距离演奏开始的毫秒)
3 音符结束消息
("NoteE", 结束的音符ID, 距离演奏开始的毫秒)"""
del tempo, self.channels
self.channels = dict(
[
(channel_no, sorted(channel_notes, key=lambda note: note.start_time))
for channel_no, channel_notes in midi_channels.items()
]
)
return self.channels
def to_command_list_in_score( def to_command_list_in_score(
self, self,
scoreboard_name: str = "mscplay", scoreboard_name: str = "mscplay",
@ -653,7 +712,7 @@ class MidiConvert:
max_score = 0 max_score = 0
# 此处 我们把通道视为音轨 # 此处 我们把通道视为音轨
for channel in self.to_music_note_channels().values(): for channel in self.channels.values():
# 如果当前通道为空 则跳过 # 如果当前通道为空 则跳过
if not channel: if not channel:
continue continue
@ -676,8 +735,11 @@ class MidiConvert:
if note.percussive if note.percussive
else self.pitched_note_reference_table else self.pitched_note_reference_table
), ),
(max_volume) if note.track_no == 0 else (max_volume * 0.9), deviation=self.music_deviation,
self.volume_processing_function, volume_percentage=(
(max_volume) if note.track_no == 0 else (max_volume * 0.9)
),
volume_processing_method=self.volume_processing_function,
) )
this_channel.append( this_channel.append(
@ -756,7 +818,7 @@ class MidiConvert:
notes_list: List[SingleNote] = [] notes_list: List[SingleNote] = []
# 此处 我们把通道视为音轨 # 此处 我们把通道视为音轨
for channel in self.to_music_note_channels().values(): for channel in self.channels.values():
notes_list.extend(channel) notes_list.extend(channel)
notes_list.sort(key=lambda a: a.start_time) notes_list.sort(key=lambda a: a.start_time)
@ -785,8 +847,11 @@ class MidiConvert:
if note.percussive if note.percussive
else self.pitched_note_reference_table else self.pitched_note_reference_table
), ),
(max_volume) if note.track_no == 0 else (max_volume * 0.9), deviation=self.music_deviation,
self.volume_processing_function, volume_percentage=(
(max_volume) if note.track_no == 0 else (max_volume * 0.9)
),
volume_processing_method=self.volume_processing_function,
) )
self.music_command_list.append( self.music_command_list.append(
@ -829,8 +894,8 @@ class MidiConvert:
def copy_important(self): def copy_important(self):
dst = MidiConvert( dst = MidiConvert(
midi_obj=None, midi_obj=mido.MidiFile(),
midi_name=self.midi_music_name, midi_name=self.music_name,
enable_old_exe_format=self.enable_old_exe_format, enable_old_exe_format=self.enable_old_exe_format,
) )
dst.music_command_list = [i.copy() for i in self.music_command_list] dst.music_command_list = [i.copy() for i in self.music_command_list]

View File

@ -68,8 +68,8 @@ def to_addon_pack_in_score(
with open(f"{data_cfg.dist_path}/temp/manifest.json", "w", encoding="utf-8") as f: with open(f"{data_cfg.dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
json.dump( json.dump(
behavior_mcpack_manifest( behavior_mcpack_manifest(
pack_description=f"{midi_cvt.midi_music_name} 音乐播放包MCFUNCTION(MCPACK) 计分播放器 - 由 音·创 生成", pack_description=f"{midi_cvt.music_name} 音乐播放包MCFUNCTION(MCPACK) 计分播放器 - 由 音·创 生成",
pack_name=midi_cvt.midi_music_name + "播放", pack_name=midi_cvt.music_name + "播放",
modules_description=f"无 - 由 音·创 生成", modules_description=f"无 - 由 音·创 生成",
), ),
fp=f, fp=f,
@ -136,11 +136,11 @@ def to_addon_pack_in_score(
index_file.close() index_file.close()
if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack"): if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack") os.remove(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack")
compress_zipfile( compress_zipfile(
f"{data_cfg.dist_path}/temp/", f"{data_cfg.dist_path}/temp/",
f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack", f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack",
) )
shutil.rmtree(f"{data_cfg.dist_path}/temp/") shutil.rmtree(f"{data_cfg.dist_path}/temp/")
@ -198,8 +198,8 @@ def to_addon_pack_in_delay(
with open(f"{data_cfg.dist_path}/temp/manifest.json", "w", encoding="utf-8") as f: with open(f"{data_cfg.dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
json.dump( json.dump(
behavior_mcpack_manifest( behavior_mcpack_manifest(
pack_description=f"{midi_cvt.midi_music_name} 音乐播放包MCSTRUCTURE(MCPACK) 延迟播放器 - 由 音·创 生成", pack_description=f"{midi_cvt.music_name} 音乐播放包MCSTRUCTURE(MCPACK) 延迟播放器 - 由 音·创 生成",
pack_name=midi_cvt.midi_music_name + "播放", pack_name=midi_cvt.music_name + "播放",
modules_description=f"无 - 由 音·创 生成", modules_description=f"无 - 由 音·创 生成",
), ),
fp=f, fp=f,
@ -229,7 +229,7 @@ def to_addon_pack_in_delay(
os.path.join( os.path.join(
data_cfg.dist_path, data_cfg.dist_path,
"temp/structures/", "temp/structures/",
f"{midi_cvt.midi_music_name}_main.mcstructure", f"{midi_cvt.music_name}_main.mcstructure",
) )
), ),
"wb+", "wb+",
@ -239,7 +239,7 @@ def to_addon_pack_in_delay(
del struct del struct
if data_cfg.progressbar_style: if data_cfg.progressbar_style:
scb_name = midi_cvt.midi_music_name[:3] + "Pgb" scb_name = midi_cvt.music_name[:3] + "Pgb"
index_file.write("scoreboard objectives add {0} dummy {0}\n".format(scb_name)) index_file.write("scoreboard objectives add {0} dummy {0}\n".format(scb_name))
struct_a = Structure((1, 1, 1), compability_version=compability_ver) struct_a = Structure((1, 1, 1), compability_version=compability_ver)
@ -261,14 +261,14 @@ def to_addon_pack_in_delay(
os.path.join( os.path.join(
data_cfg.dist_path, data_cfg.dist_path,
"temp/structures/", "temp/structures/",
f"{midi_cvt.midi_music_name}_start.mcstructure", f"{midi_cvt.music_name}_start.mcstructure",
) )
), ),
"wb+", "wb+",
) as f: ) as f:
struct_a.dump(f) struct_a.dump(f)
index_file.write(f"structure load {midi_cvt.midi_music_name}_start ~ ~ ~1\n") index_file.write(f"structure load {midi_cvt.music_name}_start ~ ~ ~1\n")
pgb_struct, pgbSize, pgbNowPos = commands_to_structure( pgb_struct, pgbSize, pgbNowPos = commands_to_structure(
midi_cvt.form_progress_bar(max_delay, scb_name, data_cfg.progressbar_style), midi_cvt.form_progress_bar(max_delay, scb_name, data_cfg.progressbar_style),
@ -281,14 +281,14 @@ def to_addon_pack_in_delay(
os.path.join( os.path.join(
data_cfg.dist_path, data_cfg.dist_path,
"temp/structures/", "temp/structures/",
f"{midi_cvt.midi_music_name}_pgb.mcstructure", f"{midi_cvt.music_name}_pgb.mcstructure",
) )
), ),
"wb+", "wb+",
) as f: ) as f:
pgb_struct.dump(f) pgb_struct.dump(f)
index_file.write(f"structure load {midi_cvt.midi_music_name}_pgb ~ ~1 ~1\n") index_file.write(f"structure load {midi_cvt.music_name}_pgb ~ ~1 ~1\n")
struct_a = Structure( struct_a = Structure(
(1, 1, 1), (1, 1, 1),
@ -311,7 +311,7 @@ def to_addon_pack_in_delay(
os.path.join( os.path.join(
data_cfg.dist_path, data_cfg.dist_path,
"temp/structures/", "temp/structures/",
f"{midi_cvt.midi_music_name}_reset.mcstructure", f"{midi_cvt.music_name}_reset.mcstructure",
) )
), ),
"wb+", "wb+",
@ -321,23 +321,23 @@ def to_addon_pack_in_delay(
del struct_a, pgb_struct del struct_a, pgb_struct
index_file.write( index_file.write(
f"structure load {midi_cvt.midi_music_name}_reset ~{pgbSize[0] + 2} ~ ~1\n" f"structure load {midi_cvt.music_name}_reset ~{pgbSize[0] + 2} ~ ~1\n"
) )
index_file.write( index_file.write(
f"structure load {midi_cvt.midi_music_name}_main ~{pgbSize[0] + 2} ~1 ~1\n" f"structure load {midi_cvt.music_name}_main ~{pgbSize[0] + 2} ~1 ~1\n"
) )
else: else:
index_file.write(f"structure load {midi_cvt.midi_music_name}_main ~ ~ ~1\n") index_file.write(f"structure load {midi_cvt.music_name}_main ~ ~ ~1\n")
index_file.close() index_file.close()
if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack"): if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack") os.remove(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack")
compress_zipfile( compress_zipfile(
f"{data_cfg.dist_path}/temp/", f"{data_cfg.dist_path}/temp/",
f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack", f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack",
) )
shutil.rmtree(f"{data_cfg.dist_path}/temp/") shutil.rmtree(f"{data_cfg.dist_path}/temp/")
@ -395,8 +395,8 @@ def to_addon_pack_in_repeater(
with open(f"{data_cfg.dist_path}/temp/manifest.json", "w", encoding="utf-8") as f: with open(f"{data_cfg.dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
json.dump( json.dump(
behavior_mcpack_manifest( behavior_mcpack_manifest(
pack_description=f"{midi_cvt.midi_music_name} 音乐播放包MCSTRUCTURE(MCPACK) 中继器播放器 - 由 音·创 生成", pack_description=f"{midi_cvt.music_name} 音乐播放包MCSTRUCTURE(MCPACK) 中继器播放器 - 由 音·创 生成",
pack_name=midi_cvt.midi_music_name + "播放", pack_name=midi_cvt.music_name + "播放",
modules_description=f"无 - 由 音·创 生成", modules_description=f"无 - 由 音·创 生成",
), ),
fp=f, fp=f,
@ -427,7 +427,7 @@ def to_addon_pack_in_repeater(
os.path.join( os.path.join(
data_cfg.dist_path, data_cfg.dist_path,
"temp/structures/", "temp/structures/",
f"{midi_cvt.midi_music_name}_main.mcstructure", f"{midi_cvt.music_name}_main.mcstructure",
) )
), ),
"wb+", "wb+",
@ -437,7 +437,7 @@ def to_addon_pack_in_repeater(
del struct del struct
if data_cfg.progressbar_style: if data_cfg.progressbar_style:
scb_name = midi_cvt.midi_music_name[:3] + "Pgb" scb_name = midi_cvt.music_name[:3] + "Pgb"
index_file.write("scoreboard objectives add {0} dummy {0}\n".format(scb_name)) index_file.write("scoreboard objectives add {0} dummy {0}\n".format(scb_name))
struct_a = Structure((1, 1, 1), compability_version=compability_ver) struct_a = Structure((1, 1, 1), compability_version=compability_ver)
@ -459,14 +459,14 @@ def to_addon_pack_in_repeater(
os.path.join( os.path.join(
data_cfg.dist_path, data_cfg.dist_path,
"temp/structures/", "temp/structures/",
f"{midi_cvt.midi_music_name}_start.mcstructure", f"{midi_cvt.music_name}_start.mcstructure",
) )
), ),
"wb+", "wb+",
) as f: ) as f:
struct_a.dump(f) struct_a.dump(f)
index_file.write(f"structure load {midi_cvt.midi_music_name}_start ~ ~ ~1\n") index_file.write(f"structure load {midi_cvt.music_name}_start ~ ~ ~1\n")
pgb_struct, pgbSize, pgbNowPos = commands_to_structure( pgb_struct, pgbSize, pgbNowPos = commands_to_structure(
midi_cvt.form_progress_bar(max_delay, scb_name, data_cfg.progressbar_style), midi_cvt.form_progress_bar(max_delay, scb_name, data_cfg.progressbar_style),
@ -479,14 +479,14 @@ def to_addon_pack_in_repeater(
os.path.join( os.path.join(
data_cfg.dist_path, data_cfg.dist_path,
"temp/structures/", "temp/structures/",
f"{midi_cvt.midi_music_name}_pgb.mcstructure", f"{midi_cvt.music_name}_pgb.mcstructure",
) )
), ),
"wb+", "wb+",
) as f: ) as f:
pgb_struct.dump(f) pgb_struct.dump(f)
index_file.write(f"structure load {midi_cvt.midi_music_name}_pgb ~ ~1 ~1\n") index_file.write(f"structure load {midi_cvt.music_name}_pgb ~ ~1 ~1\n")
struct_a = Structure( struct_a = Structure(
(1, 1, 1), (1, 1, 1),
@ -509,7 +509,7 @@ def to_addon_pack_in_repeater(
os.path.join( os.path.join(
data_cfg.dist_path, data_cfg.dist_path,
"temp/structures/", "temp/structures/",
f"{midi_cvt.midi_music_name}_reset.mcstructure", f"{midi_cvt.music_name}_reset.mcstructure",
) )
), ),
"wb+", "wb+",
@ -519,23 +519,23 @@ def to_addon_pack_in_repeater(
del struct_a, pgb_struct del struct_a, pgb_struct
index_file.write( index_file.write(
f"structure load {midi_cvt.midi_music_name}_reset ~{pgbSize[0] + 2} ~ ~1\n" f"structure load {midi_cvt.music_name}_reset ~{pgbSize[0] + 2} ~ ~1\n"
) )
index_file.write( index_file.write(
f"structure load {midi_cvt.midi_music_name}_main ~{pgbSize[0] + 2} ~1 ~1\n" f"structure load {midi_cvt.music_name}_main ~{pgbSize[0] + 2} ~1 ~1\n"
) )
else: else:
index_file.write(f"structure load {midi_cvt.midi_music_name}_main ~ ~ ~1\n") index_file.write(f"structure load {midi_cvt.music_name}_main ~ ~ ~1\n")
index_file.close() index_file.close()
if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack"): if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack"):
os.remove(f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack") os.remove(f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack")
compress_zipfile( compress_zipfile(
f"{data_cfg.dist_path}/temp/", f"{data_cfg.dist_path}/temp/",
f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack", f"{data_cfg.dist_path}/{midi_cvt.music_name}.mcpack",
) )
shutil.rmtree(f"{data_cfg.dist_path}/temp/") shutil.rmtree(f"{data_cfg.dist_path}/temp/")

View File

@ -69,7 +69,7 @@ def to_BDX_file_in_score(
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.midi_music_name}.bdx") os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.bdx")
), ),
"w+", "w+",
) as f: ) as f:
@ -119,7 +119,7 @@ def to_BDX_file_in_score(
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.midi_music_name}.bdx") os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.bdx")
), ),
"ab+", "ab+",
) as f: ) as f:
@ -167,7 +167,7 @@ def to_BDX_file_in_delay(
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.midi_music_name}.bdx") os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.bdx")
), ),
"w+", "w+",
) as f: ) as f:
@ -180,7 +180,7 @@ def to_BDX_file_in_delay(
cmdBytes, size, finalPos = commands_to_BDX_bytes(cmdlist, max_height - 1) cmdBytes, size, finalPos = commands_to_BDX_bytes(cmdlist, max_height - 1)
if data_cfg.progressbar_style: if data_cfg.progressbar_style:
scb_name = midi_cvt.midi_music_name[:3] + "Pgb" scb_name = midi_cvt.music_name[:3] + "Pgb"
_bytes += form_command_block_in_BDX_bytes( _bytes += form_command_block_in_BDX_bytes(
r"scoreboard objectives add {} dummy {}".replace(r"{}", scb_name), r"scoreboard objectives add {} dummy {}".replace(r"{}", scb_name),
1, 1,
@ -217,7 +217,7 @@ def to_BDX_file_in_delay(
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.midi_music_name}.bdx") os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.bdx")
), ),
"ab+", "ab+",
) as f: ) as f:

View File

@ -72,7 +72,7 @@ def to_mcstructure_file_in_delay(
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.midi_music_name}.mcstructure") os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.mcstructure")
), ),
"wb+", "wb+",
) as f: ) as f:
@ -144,7 +144,7 @@ def to_mcstructure_file_in_score(
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.midi_music_name}.mcstructure") os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.mcstructure")
), ),
"wb+", "wb+",
) as f: ) as f:
@ -207,7 +207,7 @@ def to_mcstructure_file_in_repeater(
with open( with open(
os.path.abspath( os.path.abspath(
os.path.join(data_cfg.dist_path, f"{midi_cvt.midi_music_name}.mcstructure") os.path.join(data_cfg.dist_path, f"{midi_cvt.music_name}.mcstructure")
), ),
"wb+", "wb+",
) as f: ) as f:

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
存储许多非主要的相关 存储·创附属子
""" """
""" """

View File

@ -36,7 +36,7 @@ MidiNoteNameTableType = Mapping[int, Tuple[str, ...]]
Midi音符名称对照表类型 Midi音符名称对照表类型
""" """
MidiInstrumentTableType = Mapping[int, Tuple[str, int]] MidiInstrumentTableType = Mapping[int, str]
""" """
Midi乐器对照表类型 Midi乐器对照表类型
""" """

View File

@ -18,7 +18,7 @@ Terms & Conditions: License.md in the root directory
import math import math
import random import random
from .constants import MM_INSTRUMENT_DEVIATION_TABLE, MC_INSTRUMENT_BLOCKS_TABLE from .constants import MM_INSTRUMENT_RANGE_TABLE, MC_INSTRUMENT_BLOCKS_TABLE
from .subclass import SingleNote from .subclass import SingleNote
from .types import ( from .types import (
@ -58,18 +58,10 @@ def inst_to_sould_with_deviation(
instrumentID: int, instrumentID: int,
reference_table: MidiInstrumentTableType, reference_table: MidiInstrumentTableType,
default_instrument: str = "note.flute", default_instrument: str = "note.flute",
default_deviation: Optional[int] = 5,
) -> Tuple[str, int]: ) -> Tuple[str, int]:
""" """
返回midi的乐器ID对应的我的世界乐器名对于音域转换算法如下 返回midi的乐器ID对应的我的世界乐器名对于音域转换算法如下
2**( ( msg.note - 60 - X ) / 12 ) 即为MC的音高其中 2**( ( msg.note - 66 ) / 12 ) 即为MC的音高
X的取值随乐器不同而变化
竖琴harp电钢琴pling班卓琴banjo方波bit颤音琴iron_xylophone 的时候为6
吉他的时候为7
贝斯bass迪吉里杜管didgeridoo的时候为8
长笛flute牛铃cou_bell的时候为5
钟琴bell管钟chime木琴xylophone的时候为4
而存在一些打击乐器bd(basedrum)hatsnare没有音域则没有X那么我们返回7即可
Parameters Parameters
---------- ----------
@ -84,20 +76,43 @@ def inst_to_sould_with_deviation(
""" """
return reference_table.get( return reference_table.get(
instrumentID, instrumentID,
( default=default_instrument,
default_instrument, ), 6
(
default_deviation # 明明已经走了
if default_deviation # 凭什么还要在我心里留下缠绵缱绻
else MM_INSTRUMENT_DEVIATION_TABLE.get(default_instrument, -1)
),
), def midi_inst_to_mc_sould(
instrumentID: int,
reference_table: MidiInstrumentTableType,
default_instrument: str = "note.flute",
) -> str:
"""
返回midi的乐器ID对应的我的世界乐器名对于音域转换算法如下
2**( ( msg.note - 66 ) / 12 ) 即为MC的音高
Parameters
----------
instrumentID: int
midi的乐器ID
reference_table: Dict[int, Tuple[str, int]]
转换乐器参照表
Returns
-------
tuple(str我的世界乐器名, int转换算法中的X)
"""
return reference_table.get(
instrumentID,
default=default_instrument,
) )
# 明明已经走了 # 明明已经走了
# 凭什么还要在我心里留下缠绵缱绻 # 凭什么还要在我心里留下缠绵缱绻
def natural_curve( def natural_curve(
vol: float, vol: float,
) -> float: ) -> float:
@ -145,6 +160,7 @@ def straight_line(vol: float) -> float:
def note_to_command_parameters( def note_to_command_parameters(
note_: SingleNote, note_: SingleNote,
reference_table: MidiInstrumentTableType, reference_table: MidiInstrumentTableType,
deviation: int = 0,
volume_percentage: float = 1, volume_percentage: float = 1,
volume_processing_method: Callable[[float], float] = natural_curve, volume_processing_method: Callable[[float], float] = natural_curve,
) -> Tuple[ ) -> Tuple[
@ -156,20 +172,21 @@ def note_to_command_parameters(
""" """
将音符转为播放的指令 将音符转为播放的指令
:param note_:int 音符对象 :param note_:int 音符对象
:param reference_table:Dict[int, Tuple[str, int]] 转换对照表 :param reference_table:Dict[int, str] 转换对照表
:param deviation:int 音调偏移量
:param volume_percentage:int 音量占比(0,1] :param volume_percentage:int 音量占比(0,1]
:param volume_proccessing_method:Callable[[float], float]: 音量处理函数 :param volume_proccessing_method:Callable[[float], float] 音量处理函数
:return str[我的世界音符ID], float[播放距离], float[指令音量参数], float[指令音调参数] :return str[我的世界音符ID], float[播放距离], float[指令音量参数], float[指令音调参数]
""" """
mc_sound_ID, deviation = inst_to_sould_with_deviation( mc_sound_ID = midi_inst_to_mc_sould(
note_.inst, note_.inst,
reference_table, reference_table,
"note.bd" if note_.percussive else "note.flute", "note.bd" if note_.percussive else "note.flute",
) )
# delaytime_now = round(self.start_time / float(speed) / 50) # delaytime_now = round(self.start_time / float(speed) / 50)
mc_pitch = None if note_.percussive else 2 ** ((note_.note - 60 - deviation) / 12) mc_pitch = None if note_.percussive else 2 ** ((note_.note - 66 + deviation) / 12)
mc_distance_volume = volume_processing_method(note_.velocity * volume_percentage) mc_distance_volume = volume_processing_method(note_.velocity * volume_percentage)

View File

@ -7,7 +7,7 @@
</img> </img>
</p> </p>
<h3 align="center">一款免费开源的我的世界数字音频转换</h3> <h3 align="center">一款免费开源的我的世界数字音频</h3>
<p align="center"> <p align="center">
<img src="https://img.shields.io/badge/BUILD%20WITH%20LOVE-FF3432?style=for-the-badge"> <img src="https://img.shields.io/badge/BUILD%20WITH%20LOVE-FF3432?style=for-the-badge">
@ -46,6 +46,7 @@
``` ```
- 如果无法更新最新可以尝试 - 如果无法更新最新可以尝试
```bash ```bash
pip install --upgrade -i https://pypi.python.org/simple Musicreater pip install --upgrade -i https://pypi.python.org/simple Musicreater
``` ```

View File

@ -7,7 +7,7 @@
</img> </img>
</p> </p>
<h3 align="center">A free open-source library of converting digital music files into <i>Minecraft</i> formats.</h3> <h3 align="center">A free open-source library of <i>Minecraft</i> digital music.</h3>
<p align="center"> <p align="center">
<img src="https://img.shields.io/badge/BUILD%20WITH%20LOVE-FF3432?style=for-the-badge"> <img src="https://img.shields.io/badge/BUILD%20WITH%20LOVE-FF3432?style=for-the-badge">
@ -45,6 +45,7 @@ Welcome to join our QQ group: [861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr
``` ```
- If above command cannot fetch latest version, try: - If above command cannot fetch latest version, try:
```bash ```bash
pip install -i https://pypi.python.org/simple Musicreater --upgrade pip install -i https://pypi.python.org/simple Musicreater --upgrade
``` ```
@ -58,7 +59,6 @@ Welcome to join our QQ group: [861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr
Commands such as `python``pip` could be changed to some like `python3` or `pip3` according to the difference of platforms. Commands such as `python``pip` could be changed to some like `python3` or `pip3` according to the difference of platforms.
## Documentation 📄 ## Documentation 📄
(Not in English yet) (Not in English yet)
@ -121,7 +121,6 @@ NOT APPROVED BY OR ASSOCIATED WITH NETEASE.
- 上文提及的 网易 公司指代的是在中国大陆运营我的世界中国版的上海网之易网络科技发展有限公司 - 上文提及的 网易 公司指代的是在中国大陆运营我的世界中国版的上海网之易网络科技发展有限公司
[Bilibili: Eilles]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge [Bilibili: Eilles]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge
[Bilibili: bgArray]: https://img.shields.io/badge/Bilibili-%E8%AF%B8%E8%91%9B%E4%BA%AE%E4%B8%8E%E5%85%AB%E5%8D%A6%E9%98%B5-00A1E7?style=for-the-badge [Bilibili: bgArray]: https://img.shields.io/badge/Bilibili-%E8%AF%B8%E8%91%9B%E4%BA%AE%E4%B8%8E%E5%85%AB%E5%8D%A6%E9%98%B5-00A1E7?style=for-the-badge
[CodeStyle: black]: https://img.shields.io/badge/code%20style-black-121110.svg?style=for-the-badge [CodeStyle: black]: https://img.shields.io/badge/code%20style-black-121110.svg?style=for-the-badge

View File

@ -13,7 +13,9 @@ def main():
if file.endswith(".egg-info"): if file.endswith(".egg-info"):
egg_info.append(file) egg_info.append(file)
console.print(file) console.print(file)
for file in track(["build", "dist", "logs", *egg_info], description="Deleting files"): for file in track(
["build", "dist", "logs", *egg_info], description="Deleting files"
):
if os.path.isdir(file) and os.access(file, os.W_OK): if os.path.isdir(file) and os.access(file, os.W_OK):
shutil.rmtree(file) shutil.rmtree(file)

View File

@ -189,10 +189,12 @@ print(
) )
) )
if fileFormat == 1 if fileFormat == 1
else (" 结构大小:{},延迟总数:{},指令数量:{}".format( else (
" 结构大小:{},延迟总数:{},指令数量:{}".format(
*(cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore *(cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore
) if playerFormat == 2 else )
" 结构大小:{},延迟总数:{}".format( if playerFormat == 2
else " 结构大小:{},延迟总数:{}".format(
*(cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore *(cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore
) )
) )