From 3831c41b9aacae957faaca250eed28b33929fc6f Mon Sep 17 00:00:00 2001
From: EillesWan
Date: Sat, 24 Feb 2024 21:31:39 +0800
Subject: [PATCH] =?UTF-8?q?=E6=88=91=E8=A7=89=E5=BE=97=E8=83=BD=E7=94=A8?=
=?UTF-8?q?=E4=BA=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Musicreater/__init__.py | 7 +-
Musicreater/constants.py | 949 ++++++++++++++----------
Musicreater/exceptions.py | 14 +-
Musicreater/experiment.py | 39 +-
Musicreater/main.py | 397 +++++-----
Musicreater/plugin/addonpack/main.py | 70 +-
Musicreater/plugin/bdxfile/main.py | 10 +-
Musicreater/plugin/mcstructfile/main.py | 6 +-
Musicreater/subclass.py | 2 +-
Musicreater/types.py | 2 +-
Musicreater/utils.py | 61 +-
README.md | 3 +-
README_EN.md | 5 +-
clean_update.py | 4 +-
example.py | 8 +-
15 files changed, 930 insertions(+), 647 deletions(-)
diff --git a/Musicreater/__init__.py b/Musicreater/__init__.py
index 192c038..c0f6df2 100644
--- a/Musicreater/__init__.py
+++ b/Musicreater/__init__.py
@@ -17,8 +17,8 @@ Terms & Conditions: License.md in the root directory
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
-__version__ = "1.7.4"
-__vername__ = "部分音色更新"
+__version__ = "1.8"
+__vername__ = "音调总体偏移的处理支持"
__author__ = (
("金羿", "Eilles Wan"),
("诸葛亮与八卦阵", "bgArray"),
@@ -27,6 +27,7 @@ __author__ = (
)
__all__ = [
# 主要类
+ "MusicSequence",
"MidiConvert",
# 附加类
"SingleNote",
@@ -35,7 +36,7 @@ __all__ = [
# "TimeStamp", 未来功能
# 默认值
"DEFAULT_PROGRESSBAR_STYLE",
- "MM_INSTRUMENT_DEVIATION_TABLE",
+ "MM_INSTRUMENT_RANGE_TABLE",
"MM_CLASSIC_PITCHED_INSTRUMENT_TABLE",
"MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE",
"MM_TOUCH_PITCHED_INSTRUMENT_TABLE",
diff --git a/Musicreater/constants.py b/Musicreater/constants.py
index e66d000..31f3074 100644
--- a/Musicreater/constants.py
+++ b/Musicreater/constants.py
@@ -302,7 +302,7 @@ MIDI_PITCHED_NOTE_NAME_TABLE: Dict[int, Tuple[str, str]] = {
111: ("古提琴", "Fiddle"),
112: ("唢呐", "Shanai"),
113: ("铃铛", "Tinkle Bell"),
- 114: ("拉丁打铃", "Agogo"),
+ 114: ("阿哥铃", "Agogo"),
115: ("钢鼓", "Steel Drums"),
116: ("木块", "Woodblock"),
117: ("太鼓", "Taiko Drum"),
@@ -353,8 +353,8 @@ MIDI_PERCUSSION_NOTE_NAME_TABLE: Dict[int, Tuple[str, str]] = {
64: ("低音康加鼓", "Low Conga"),
65: ("高音天巴鼓", "High Timbale"),
66: ("低音天巴鼓", "Low Timbale"),
- 67: ("高音阿哥哥", "High Agogo"),
- 68: ("低音阿哥哥", "Low Agogo"),
+ 67: ("高音阿哥铃", "High Agogo"),
+ 68: ("低音阿哥铃", "Low Agogo"),
69: ("串珠", "Cabasa"),
70: ("沙槌", "Maracas"),
71: ("短口哨", "Short Whistle"),
@@ -414,402 +414,589 @@ MC_INSTRUMENT_BLOCKS_TABLE: Dict[str, Tuple[str, ...]] = {
# Midi对MC通用对照表
-MM_INSTRUMENT_DEVIATION_TABLE: Dict[str, int] = {
- "note.harp": 6,
- "note.pling": 6,
- "note.guitar": 7,
- "note.iron_xylophone": 6,
- "note.bell": 4,
- "note.xylophone": 4,
- "note.chime": 4,
- "note.banjo": 6,
- "note.flute": 5,
- "note.bass": 8,
- "note.snare": -1,
- "note.didgeridoo": 8,
- "mob.zombie.wood": -1,
- "note.bit": 6,
- "note.hat": -1,
- "note.bd": -1,
- "firework.blast": -1,
- "firework.twinkle": -1,
- "fire.ignite": -1,
- "note.share": -1,
- "note.cow_bell": 5,
+MM_INSTRUMENT_RANGE_TABLE: Dict[str, Tuple[int, int]] = {
+ "note.harp": (42, 66),
+ "note.pling": (42, 66),
+ "note.guitar": (30, 54),
+ "note.iron_xylophone": (42, 66),
+ "note.bell": (66, 90),
+ "note.xylophone": (66, 90),
+ "note.chime": (66, 90),
+ "note.banjo": (42, 66),
+ "note.flute": (54, 78),
+ "note.bass": (18, 42),
+ "note.snare": (-1, 128), # 实际上是 0~127
+ "note.didgeridoo": (18, 42),
+ "mob.zombie.wood": (-1, 128),
+ "note.bit": (42, 66),
+ "note.hat": (-1, 128),
+ "note.bd": (-1, 128),
+ "note.basedrum": (-1, 128),
+ "firework.blast": (-1, 128),
+ "firework.twinkle": (-1, 128),
+ "fire.ignite": (-1, 128),
+ "note.cow_bell": (54, 78),
}
-"""不同乐器的音调偏离对照表"""
+"""不同乐器的音域偏离对照表"""
# Midi乐器对MC乐器对照表
-MM_CLASSIC_PITCHED_INSTRUMENT_TABLE: Dict[int, Tuple[str, int]] = {
- 0: ("note.harp", 6),
- 1: ("note.harp", 6),
- 2: ("note.pling", 6),
- 3: ("note.harp", 6),
- 4: ("note.pling", 6),
- 5: ("note.pling", 6),
- 6: ("note.harp", 6),
- 7: ("note.harp", 6),
- 8: ("note.share", -1), # 打击乐器无音域
- 9: ("note.harp", 6),
- 10: ("note.didgeridoo", 8),
- 11: ("note.harp", 6),
- 12: ("note.xylophone", 4),
- 13: ("note.chime", 4),
- 14: ("note.harp", 6),
- 15: ("note.harp", 6),
- 16: ("note.bass", 8),
- 17: ("note.harp", 6),
- 18: ("note.harp", 6),
- 19: ("note.harp", 6),
- 20: ("note.harp", 6),
- 21: ("note.harp", 6),
- 22: ("note.harp", 6),
- 23: ("note.guitar", 7),
- 24: ("note.guitar", 7),
- 25: ("note.guitar", 7),
- 26: ("note.guitar", 7),
- 27: ("note.guitar", 7),
- 28: ("note.guitar", 7),
- 29: ("note.guitar", 7),
- 30: ("note.guitar", 7),
- 31: ("note.bass", 8),
- 32: ("note.bass", 8),
- 33: ("note.bass", 8),
- 34: ("note.bass", 8),
- 35: ("note.bass", 8),
- 36: ("note.bass", 8),
- 37: ("note.bass", 8),
- 38: ("note.bass", 8),
- 39: ("note.bass", 8),
- 40: ("note.harp", 6),
- 41: ("note.harp", 6),
- 42: ("note.harp", 6),
- 43: ("note.harp", 6),
- 44: ("note.iron_xylophone", 6),
- 45: ("note.guitar", 7),
- 46: ("note.harp", 6),
- 47: ("note.harp", 6),
- 48: ("note.guitar", 7),
- 49: ("note.guitar", 7),
- 50: ("note.bit", 6),
- 51: ("note.bit", 6),
- 52: ("note.harp", 6),
- 53: ("note.harp", 6),
- 54: ("note.bit", 6),
- 55: ("note.flute", 5),
- 56: ("note.flute", 5),
- 57: ("note.flute", 5),
- 58: ("note.flute", 5),
- 59: ("note.flute", 5),
- 60: ("note.flute", 5),
- 61: ("note.flute", 5),
- 62: ("note.flute", 5),
- 63: ("note.flute", 5),
- 64: ("note.bit", 6),
- 65: ("note.bit", 6),
- 66: ("note.bit", 6),
- 67: ("note.bit", 6),
- 68: ("note.flute", 5),
- 69: ("note.harp", 6),
- 70: ("note.harp", 6),
- 71: ("note.flute", 5),
- 72: ("note.flute", 5),
- 73: ("note.flute", 5),
- 74: ("note.harp", 6),
- 75: ("note.flute", 5),
- 76: ("note.harp", 6),
- 77: ("note.harp", 6),
- 78: ("note.harp", 6),
- 79: ("note.harp", 6),
- 80: ("note.bit", 6),
- 81: ("note.bit", 6),
- 82: ("note.bit", 6),
- 83: ("note.bit", 6),
- 84: ("note.bit", 6),
- 85: ("note.bit", 6),
- 86: ("note.bit", 6),
- 87: ("note.bit", 6),
- 88: ("note.bit", 6),
- 89: ("note.bit", 6),
- 90: ("note.bit", 6),
- 91: ("note.bit", 6),
- 92: ("note.bit", 6),
- 93: ("note.bit", 6),
- 94: ("note.bit", 6),
- 95: ("note.bit", 6),
- 96: ("note.bit", 6),
- 97: ("note.bit", 6),
- 98: ("note.bit", 6),
- 99: ("note.bit", 6),
- 100: ("note.bit", 6),
- 101: ("note.bit", 6),
- 102: ("note.bit", 6),
- 103: ("note.bit", 6),
- 104: ("note.harp", 6),
- 105: ("note.banjo", 6),
- 106: ("note.harp", 6),
- 107: ("note.harp", 6),
- 108: ("note.harp", 6),
- 109: ("note.harp", 6),
- 110: ("note.harp", 6),
- 111: ("note.guitar", 7),
- 112: ("note.harp", 6),
- 113: ("note.bell", 4),
- 114: ("note.harp", 6),
- 115: ("note.cow_bell", 5),
- 116: ("note.bd", -1), # 打击乐器无音域
- 117: ("note.bass", 8),
- 118: ("note.bit", 6),
- 119: ("note.bd", -1), # 打击乐器无音域
- 120: ("note.guitar", 7),
- 121: ("note.harp", 6),
- 122: ("note.harp", 6),
- 123: ("note.harp", 6),
- 124: ("note.harp", 6),
- 125: ("note.hat", -1), # 打击乐器无音域
- 126: ("note.bd", -1), # 打击乐器无音域
- 127: ("note.snare", -1), # 打击乐器无音域
+MM_CLASSIC_PITCHED_INSTRUMENT_TABLE: Dict[int, str] = {
+ 0: "note.harp",
+ 1: "note.harp",
+ 2: "note.pling",
+ 3: "note.harp",
+ 4: "note.pling",
+ 5: "note.pling",
+ 6: "note.harp",
+ 7: "note.harp",
+ 8: "note.snare",
+ 9: "note.harp",
+ 10: "note.didgeridoo",
+ 11: "note.harp",
+ 12: "note.xylophone",
+ 13: "note.chime",
+ 14: "note.harp",
+ 15: "note.harp",
+ 16: "note.bass",
+ 17: "note.harp",
+ 18: "note.harp",
+ 19: "note.harp",
+ 20: "note.harp",
+ 21: "note.harp",
+ 22: "note.harp",
+ 23: "note.guitar",
+ 24: "note.guitar",
+ 25: "note.guitar",
+ 26: "note.guitar",
+ 27: "note.guitar",
+ 28: "note.guitar",
+ 29: "note.guitar",
+ 30: "note.guitar",
+ 31: "note.bass",
+ 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.harp",
+ 42: "note.harp",
+ 43: "note.harp",
+ 44: "note.iron_xylophone",
+ 45: "note.guitar",
+ 46: "note.harp",
+ 47: "note.harp",
+ 48: "note.guitar",
+ 49: "note.guitar",
+ 50: "note.bit",
+ 51: "note.bit",
+ 52: "note.harp",
+ 53: "note.harp",
+ 54: "note.bit",
+ 55: "note.flute",
+ 56: "note.flute",
+ 57: "note.flute",
+ 58: "note.flute",
+ 59: "note.flute",
+ 60: "note.flute",
+ 61: "note.flute",
+ 62: "note.flute",
+ 63: "note.flute",
+ 64: "note.bit",
+ 65: "note.bit",
+ 66: "note.bit",
+ 67: "note.bit",
+ 68: "note.flute",
+ 69: "note.harp",
+ 70: "note.harp",
+ 71: "note.flute",
+ 72: "note.flute",
+ 73: "note.flute",
+ 74: "note.harp",
+ 75: "note.flute",
+ 76: "note.harp",
+ 77: "note.harp",
+ 78: "note.harp",
+ 79: "note.harp",
+ 80: "note.bit",
+ 81: "note.bit",
+ 82: "note.bit",
+ 83: "note.bit",
+ 84: "note.bit",
+ 85: "note.bit",
+ 86: "note.bit",
+ 87: "note.bit",
+ 88: "note.bit",
+ 89: "note.bit",
+ 90: "note.bit",
+ 91: "note.bit",
+ 92: "note.bit",
+ 93: "note.bit",
+ 94: "note.bit",
+ 95: "note.bit",
+ 96: "note.bit",
+ 97: "note.bit",
+ 98: "note.bit",
+ 99: "note.bit",
+ 100: "note.bit",
+ 101: "note.bit",
+ 102: "note.bit",
+ 103: "note.bit",
+ 104: "note.harp",
+ 105: "note.banjo",
+ 106: "note.harp",
+ 107: "note.harp",
+ 108: "note.harp",
+ 109: "note.harp",
+ 110: "note.harp",
+ 111: "note.guitar",
+ 112: "note.harp",
+ 113: "note.bell",
+ 114: "note.harp",
+ 115: "note.cow_bell",
+ 116: "note.bd",
+ 117: "note.bass",
+ 118: "note.bit",
+ 119: "note.bd",
+ 120: "note.guitar",
+ 121: "note.harp",
+ 122: "note.harp",
+ 123: "note.harp",
+ 124: "note.harp",
+ 125: "note.hat",
+ 126: "note.bd",
+ 127: "note.snare",
}
"""“经典”乐音乐器对照表"""
-MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE: Dict[int, Tuple[str, int]] = {
- 34: ("note.bd", -1),
- 35: ("note.bd", -1),
- 36: ("note.hat", -1),
- 37: ("note.snare", -1),
- 38: ("note.snare", -1),
- 39: ("note.snare", -1),
- 40: ("note.hat", -1),
- 41: ("note.snare", -1),
- 42: ("note.hat", -1),
- 43: ("note.snare", -1),
- 44: ("note.snare", -1),
- 45: ("note.bell", 4),
- 46: ("note.snare", -1),
- 47: ("note.snare", -1),
- 48: ("note.bell", 4),
- 49: ("note.hat", -1),
- 50: ("note.bell", 4),
- 51: ("note.bell", 4),
- 52: ("note.bell", 4),
- 53: ("note.bell", 4),
- 54: ("note.bell", 4),
- 55: ("note.bell", 4),
- 56: ("note.snare", -1),
- 57: ("note.hat", -1),
- 58: ("note.chime", 4),
- 59: ("note.iron_xylophone", 6),
- 60: ("note.bd", -1),
- 61: ("note.bd", -1),
- 62: ("note.xylophone", 4),
- 63: ("note.xylophone", 4),
- 64: ("note.xylophone", 4),
- 65: ("note.hat", -1),
- 66: ("note.bell", 4),
- 67: ("note.bell", 4),
- 68: ("note.hat", -1),
- 69: ("note.hat", -1),
- 70: ("note.snare", -1),
- 71: ("note.flute", 5),
- 72: ("note.hat", -1),
- 73: ("note.hat", -1),
- 74: ("note.xylophone", 4),
- 75: ("note.hat", -1),
- 76: ("note.hat", -1),
- 77: ("note.xylophone", 4),
- 78: ("note.xylophone", 4),
- 79: ("note.bell", 4),
- 80: ("note.bell", 4),
+MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE: Dict[int, str] = {
+ 34: "note.bd",
+ 35: "note.bd",
+ 36: "note.hat",
+ 37: "note.snare",
+ 38: "note.snare",
+ 39: "note.snare",
+ 40: "note.hat",
+ 41: "note.snare",
+ 42: "note.hat",
+ 43: "note.snare",
+ 44: "note.snare",
+ 45: "note.bell",
+ 46: "note.snare",
+ 47: "note.snare",
+ 48: "note.bell",
+ 49: "note.hat",
+ 50: "note.bell",
+ 51: "note.bell",
+ 52: "note.bell",
+ 53: "note.bell",
+ 54: "note.bell",
+ 55: "note.bell",
+ 56: "note.snare",
+ 57: "note.hat",
+ 58: "note.chime",
+ 59: "note.iron_xylophone",
+ 60: "note.bd",
+ 61: "note.bd",
+ 62: "note.xylophone",
+ 63: "note.xylophone",
+ 64: "note.xylophone",
+ 65: "note.hat",
+ 66: "note.bell",
+ 67: "note.bell",
+ 68: "note.hat",
+ 69: "note.hat",
+ 70: "note.snare",
+ 71: "note.flute",
+ 72: "note.hat",
+ 73: "note.hat",
+ 74: "note.xylophone",
+ 75: "note.hat",
+ 76: "note.hat",
+ 77: "note.xylophone",
+ 78: "note.xylophone",
+ 79: "note.bell",
+ 80: "note.bell",
}
"""“经典”打击乐器对照表"""
-# 以下是由 Touch “偷吃” 带来的高准确率音效对照表
+# 以下是由 Touch “偷吃” 带来的高准确率音色对照表
# 包括乐音乐器对照和打击乐器对照
-MM_TOUCH_PITCHED_INSTRUMENT_TABLE: Dict[int, Tuple[str, int]] = {
- 0: ("note.harp", 6),
- 1: ("note.harp", 6),
- 2: ("note.pling", 6),
- 3: ("note.harp", 6),
- 4: ("note.pling", 6),
- 5: ("note.pling", 6),
- 6: ("note.guitar", 7),
- 7: ("note.guitar", 7),
- 8: ("note.iron_xylophone", 8),
- 9: ("note.bell", 4), # 打击乐器无音域
- 10: ("note.iron_xylophone", 6),
- 11: ("note.iron_xylophone", 6),
- 12: ("note.iron_xylophone", 6),
- 13: ("note.xylophone", 4),
- 14: ("note.chime", 4),
- 15: ("note.banjo", 6),
- 16: ("note.xylophone", 6),
- 17: ("note.iron_xylophone", 6),
- 18: ("note.flute", 5),
- 19: ("note.flute", 5),
- 20: ("note.flute", 5),
- 21: ("note.flute", 5),
- 22: ("note.flute", 5),
- 23: ("note.flute", 5),
- 24: ("note.guitar", 7),
- 25: ("note.guitar", 7),
- 26: ("note.guitar", 7),
- 27: ("note.guitar", 7),
- 28: ("note.guitar", 7),
- 29: ("note.guitar", 7),
- 30: ("note.guitar", 7),
- 31: ("note.bass", 8),
- 32: ("note.bass", 8),
- 33: ("note.bass", 8),
- 34: ("note.bass", 8),
- 35: ("note.bass", 8),
- 36: ("note.bass", 8),
- 37: ("note.bass", 8),
- 38: ("note.bass", 8),
- 39: ("note.bass", 8),
- 40: ("note.flute", 5),
- 41: ("note.flute", 5),
- 42: ("note.flute", 5),
- 43: ("note.bass", 8),
- 44: ("note.flute", 5),
- 45: ("note.iron_xylophone", 6),
- 46: ("note.harp", 6),
- 47: ("note.snare", -1),
- 48: ("note.flute", 5),
- 49: ("note.flute", 5),
- 50: ("note.flute", 5),
- 51: ("note.flute", 5),
- 52: ("note.didgeridoo", 5),
- 53: ("note.flute", 5), # 合唱“啊”音
- 54: ("note.flute", 5), # 人声“嘟”音
- 55: ("mob.zombie.wood", -1), # 合成人声
- 56: ("note.flute", 5),
- 57: ("note.flute", 5),
- 58: ("note.flute", 5),
- 59: ("note.flute", 5),
- 60: ("note.flute", 5),
- 61: ("note.flute", 5),
- 62: ("note.flute", 5),
- 63: ("note.flute", 5),
- 64: ("note.bit", 6),
- 65: ("note.bit", 6),
- 66: ("note.bit", 6),
- 67: ("note.bit", 6),
- 68: ("note.flute", 5),
- 69: ("note.bit", 6),
- 70: ("note.banjo", 6),
- 71: ("note.flute", 5),
- 72: ("note.flute", 5),
- 73: ("note.flute", 5),
- 74: ("note.flute", 5),
- 75: ("note.flute", 5),
- 76: ("note.iron_xylophone", 6),
- 77: ("note.iron_xylophone", 6),
- 78: ("note.flute", 5),
- 79: ("note.flute", 5),
- 80: ("note.bit", 6),
- 81: ("note.bit", 6),
- 82: ("note.flute", 5),
- 83: ("note.flute", 5),
- 84: ("note.guitar", 7),
- 85: ("note.flute", 5),
- 86: ("note.bass", 8),
- 87: ("note.bass", 8),
- 88: ("note.bit", 6),
- 89: ("note.flute", 5),
- 90: ("note.bit", 6),
- 91: ("note.flute", 5),
- 92: ("note.bell", 4),
- 93: ("note.guitar", 7),
- 94: ("note.flute", 5),
- 95: ("note.bit", 6),
- 96: ("note.bit", 6), # 雨声
- 97: ("note.flute", 5),
- 98: ("note.bell", 4),
- 99: ("note.bit", 6), # 大气
- 100: ("note.bit", 6), # 明亮
- 101: ("note.bit", 6), # 鬼怪
- 102: ("note.bit", 6), # 回声
- 103: ("note.bit", 6), # 科幻
- 104: ("note.iron_xylophone", 6),
- 105: ("note.banjo", 6),
- 106: ("note.harp", 6),
- 107: ("note.harp", 6),
- 108: ("note.bell", 4),
- 109: ("note.flute", 5),
- 110: ("note.flute", 5),
- 111: ("note.flute", 5),
- 112: ("note.bell", 4),
- 113: ("note.xylophone", 4),
- 114: ("note.flute", 5),
- 115: ("note.hat", -1), # 打击乐器无音域
- 116: ("note.snare", -1), # 打击乐器无音域
- 117: ("note.snare", -1), # 打击乐器无音域
- 118: ("note.bd", -1), # 打击乐器无音域
- 119: ("firework.blast", -1), # 打击乐器无音域
- 120: ("note.guitar", 7), # 吉他还把杂音
- 121: ("note.harp", 6), # 呼吸声
- 122: ("note.harp", 6), # 海浪声
- 123: ("note.harp", 6), # 鸟鸣
- 124: ("note.bit", 6),
- 125: ("note.hat", -1), # 直升机
- 126: ("firework.twinkle", -1), # 打击乐器无音域
- 127: ("mob.zombie.wood", -1), # 打击乐器无音域
+MM_TOUCH_PITCHED_INSTRUMENT_TABLE: Dict[int, str] = {
+ 0: "note.harp",
+ 1: "note.harp",
+ 2: "note.pling",
+ 3: "note.harp",
+ 4: "note.pling",
+ 5: "note.pling",
+ 6: "note.guitar",
+ 7: "note.guitar",
+ 8: "note.iron_xylophone",
+ 9: "note.bell",
+ 10: "note.iron_xylophone",
+ 11: "note.iron_xylophone",
+ 12: "note.iron_xylophone",
+ 13: "note.xylophone",
+ 14: "note.chime",
+ 15: "note.banjo",
+ 16: "note.xylophone",
+ 17: "note.iron_xylophone",
+ 18: "note.flute",
+ 19: "note.flute",
+ 20: "note.flute",
+ 21: "note.flute",
+ 22: "note.flute",
+ 23: "note.flute",
+ 24: "note.guitar",
+ 25: "note.guitar",
+ 26: "note.guitar",
+ 27: "note.guitar",
+ 28: "note.guitar",
+ 29: "note.guitar",
+ 30: "note.guitar",
+ 31: "note.bass",
+ 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.flute",
+ 41: "note.flute",
+ 42: "note.flute",
+ 43: "note.bass",
+ 44: "note.flute",
+ 45: "note.iron_xylophone",
+ 46: "note.harp",
+ 47: "note.snare",
+ 48: "note.flute",
+ 49: "note.flute",
+ 50: "note.flute",
+ 51: "note.flute",
+ 52: "note.didgeridoo",
+ 53: "note.flute",
+ 54: "note.flute",
+ 55: "mob.zombie.wood",
+ 56: "note.flute",
+ 57: "note.flute",
+ 58: "note.flute",
+ 59: "note.flute",
+ 60: "note.flute",
+ 61: "note.flute",
+ 62: "note.flute",
+ 63: "note.flute",
+ 64: "note.bit",
+ 65: "note.bit",
+ 66: "note.bit",
+ 67: "note.bit",
+ 68: "note.flute",
+ 69: "note.bit",
+ 70: "note.banjo",
+ 71: "note.flute",
+ 72: "note.flute",
+ 73: "note.flute",
+ 74: "note.flute",
+ 75: "note.flute",
+ 76: "note.iron_xylophone",
+ 77: "note.iron_xylophone",
+ 78: "note.flute",
+ 79: "note.flute",
+ 80: "note.bit",
+ 81: "note.bit",
+ 82: "note.flute",
+ 83: "note.flute",
+ 84: "note.guitar",
+ 85: "note.flute",
+ 86: "note.bass",
+ 87: "note.bass",
+ 88: "note.bit",
+ 89: "note.flute",
+ 90: "note.bit",
+ 91: "note.flute",
+ 92: "note.bell",
+ 93: "note.guitar",
+ 94: "note.flute",
+ 95: "note.bit",
+ 96: "note.bit",
+ 97: "note.flute",
+ 98: "note.bell",
+ 99: "note.bit",
+ 100: "note.bit",
+ 101: "note.bit",
+ 102: "note.bit",
+ 103: "note.bit",
+ 104: "note.iron_xylophone",
+ 105: "note.banjo",
+ 106: "note.harp",
+ 107: "note.harp",
+ 108: "note.bell",
+ 109: "note.flute",
+ 110: "note.flute",
+ 111: "note.flute",
+ 112: "note.bell",
+ 113: "note.xylophone",
+ 114: "note.flute",
+ 115: "note.hat",
+ 116: "note.snare",
+ 117: "note.snare",
+ 118: "note.bd",
+ 119: "firework.blast",
+ 120: "note.guitar",
+ 121: "note.harp",
+ 122: "note.harp",
+ 123: "note.harp",
+ 124: "note.bit",
+ 125: "note.hat",
+ 126: "firework.twinkle",
+ 127: "mob.zombie.wood",
}
"""“偷吃”乐音乐器对照表"""
-MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE: Dict[int, Tuple[str, int]] = {
- 34: ("note.hat", -1),
- 35: ("note.bd", -1),
- 36: ("note.bd", -1),
- 37: ("note.snare", -1),
- 38: ("note.snare", -1),
- 39: ("fire.ignite", 7),
- 40: ("note.snare", -1),
- 41: ("note.hat", -1),
- 42: ("note.hat", -1),
- 43: ("firework.blast", -1),
- 44: ("note.hat", -1),
- 45: ("note.snare", -1),
- 46: ("note.snare", -1),
- 47: ("note.snare", -1),
- 48: ("note.bell", 4),
- 49: ("note.hat", -1),
- 50: ("note.bell", 4),
- 51: ("note.bell", 4),
- 52: ("note.bell", 4),
- 53: ("note.bell", 4),
- 54: ("note.bell", 4),
- 55: ("note.bell", 4),
- 56: ("note.snare", -1),
- 57: ("note.hat", -1),
- 58: ("note.chime", 4),
- 59: ("note.iron_xylophone", 6),
- 60: ("note.bd", -1),
- 61: ("note.bd", -1),
- 62: ("note.xylophone", 4),
- 63: ("note.xylophone", 4),
- 64: ("note.xylophone", 4),
- 65: ("note.hat", -1),
- 66: ("note.bell", 4),
- 67: ("note.bell", 4),
- 68: ("note.hat", -1),
- 69: ("note.hat", -1),
- 70: ("note.snare", -1),
- 71: ("note.flute", 5),
- 72: ("note.hat", -1),
- 73: ("note.hat", -1),
- 74: ("note.xylophone", 4),
- 75: ("note.hat", -1),
- 76: ("note.hat", -1),
- 77: ("note.xylophone", 4),
- 78: ("note.xylophone", 4),
- 79: ("note.bell", 4),
- 80: ("note.bell", 4),
+MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE: Dict[int, str] = {
+ 34: "note.hat",
+ 35: "note.bd",
+ 36: "note.bd",
+ 37: "note.snare",
+ 38: "note.snare",
+ 39: "fire.ignite",
+ 40: "note.snare",
+ 41: "note.hat",
+ 42: "note.hat",
+ 43: "firework.blast",
+ 44: "note.hat",
+ 45: "note.snare",
+ 46: "note.snare",
+ 47: "note.snare",
+ 48: "note.bell",
+ 49: "note.hat",
+ 50: "note.bell",
+ 51: "note.bell",
+ 52: "note.bell",
+ 53: "note.bell",
+ 54: "note.bell",
+ 55: "note.bell",
+ 56: "note.snare",
+ 57: "note.hat",
+ 58: "note.chime",
+ 59: "note.iron_xylophone",
+ 60: "note.bd",
+ 61: "note.bd",
+ 62: "note.xylophone",
+ 63: "note.xylophone",
+ 64: "note.xylophone",
+ 65: "note.hat",
+ 66: "note.bell",
+ 67: "note.bell",
+ 68: "note.hat",
+ 69: "note.hat",
+ 70: "note.snare",
+ 71: "note.flute",
+ 72: "note.hat",
+ 73: "note.hat",
+ 74: "note.xylophone",
+ 75: "note.hat",
+ 76: "note.hat",
+ 77: "note.xylophone",
+ 78: "note.xylophone",
+ 79: "note.bell",
+ 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 = {
# 0.5: 0,
diff --git a/Musicreater/exceptions.py b/Musicreater/exceptions.py
index 4318d04..cf39919 100644
--- a/Musicreater/exceptions.py
+++ b/Musicreater/exceptions.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
-存放一堆报错类型
+存放一些报错类型
"""
"""
@@ -50,13 +50,13 @@ class MidiDestroyedError(MSCTBaseException):
super().__init__("MIDI文件损坏:无法读取MIDI文件", *args)
-class MidiUnboundError(MSCTBaseException):
- """未定义Midi对象"""
-
- def __init__(self, *args):
- """未绑定Midi对象"""
- super().__init__("未定义MidiFile对象:你甚至没有对象就想要生孩子?", *args)
+# class MidiUnboundError(MSCTBaseException):
+# """未定义Midi对象(无用)"""
+# def __init__(self, *args):
+# """未绑定Midi对象"""
+# super().__init__("未定义MidiFile对象:你甚至没有对象就想要生孩子?", *args)
+# 此错误在本版本内已经不再使用
class CommandFormatError(RuntimeError):
"""指令格式与目标格式不匹配而引起的错误"""
diff --git a/Musicreater/experiment.py b/Musicreater/experiment.py
index 375a223..43ef3c5 100644
--- a/Musicreater/experiment.py
+++ b/Musicreater/experiment.py
@@ -24,6 +24,7 @@ from .main import (
MidiConvert,
MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE,
MM_CLASSIC_PITCHED_INSTRUMENT_TABLE,
+ mido,
)
from .types import Tuple, List, Dict, ChannelType
@@ -122,7 +123,7 @@ class FutureMidiConvertM4(MidiConvert):
notes_list: List[SingleNote] = []
# 此处 我们把通道视为音轨
- for channel in self.to_music_note_channels().values():
+ for channel in self.channels.values():
for note in channel:
note.set_info(
note_to_command_parameters(
@@ -132,8 +133,11 @@ class FutureMidiConvertM4(MidiConvert):
if note.percussive
else self.pitched_note_reference_table
),
- (max_volume) if note.track_no == 0 else (max_volume * 0.9),
- self.volume_processing_function,
+ deviation=0,
+ 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(
self,
+ midi: mido.MidiFile,
) -> ChannelType:
"""
使用金羿的转换思路,将midi解析并转换为频道信息字典
@@ -189,10 +194,11 @@ class FutureMidiConvertM5(MidiConvert):
以频道作为分割的Midi信息字典:
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(
- "你是否正在使用的是一个由 copy_important 生成的MidiConvert对象?这是不可复用的。"
- )
+
+ # if self.midi is None:
+ # raise MidiUnboundError(
+ # "你是否正在使用的是一个由 copy_important 生成的MidiConvert对象?这是不可复用的。"
+ # )
# 一个midi中仅有16个通道 我们通过通道来识别而不是音轨
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
if not track:
continue
@@ -209,7 +215,7 @@ class FutureMidiConvertM5(MidiConvert):
for msg in track:
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.type == "set_tempo":
@@ -257,6 +263,7 @@ class FutureMidiConvertM5(MidiConvert):
# 神奇的偏移音
def to_command_list_in_delay(
self,
+ midi: mido.MidiFile,
max_volume: float = 1.0,
speed: float = 1.0,
player_selector: str = "@a",
@@ -282,7 +289,9 @@ class FutureMidiConvertM5(MidiConvert):
raise ZeroSpeedError("播放速度仅可为正实数")
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 = {}
InstID = -1
@@ -304,12 +313,12 @@ class FutureMidiConvertM5(MidiConvert):
InstID = msg[1]
elif msg[0] == "NoteS":
- soundID, _X = (
- inst_to_sould_with_deviation(
+ soundID = (
+ midi_inst_to_mc_sould(
msg[1], MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE
)
if SpecialBits
- else inst_to_sould_with_deviation(
+ else midi_inst_to_mc_sould(
InstID, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE
)
)
@@ -324,7 +333,7 @@ class FutureMidiConvertM5(MidiConvert):
+ (
""
if SpecialBits
- else f"{2 ** ((msg[1] - 60 - _X) / 12)}"
+ else f"{2 ** ((msg[1] - 66) / 12)}"
)
)
except KeyError:
@@ -334,7 +343,7 @@ class FutureMidiConvertM5(MidiConvert):
+ (
""
if SpecialBits
- else f"{2 ** ((msg[1] - 60 - _X) / 12)}"
+ else f"{2 ** ((msg[1] - 66) / 12)}"
)
]
diff --git a/Musicreater/main.py b/Musicreater/main.py
index 7fc7b91..4fa6b74 100644
--- a/Musicreater/main.py
+++ b/Musicreater/main.py
@@ -70,21 +70,203 @@ tick * tempo / 1000000.0 / ticks_per_beat * 一秒多少游戏刻
"""
-VoidMido = Union[mido.MidiFile, None] # void mido
-"""
-空Midi类类型
-"""
+# VoidMido = Union[mido.MidiFile, None] # void mido
+# """
+# 空Midi类类型
+# """
+# 已经成为历史了
@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: VoidMido
- """MidiFile对象"""
-
pitched_note_reference_table: MidiInstrumentTableType
"""乐音乐器Midi-MC对照表"""
@@ -94,18 +276,12 @@ class MidiConvert:
volume_processing_function: FittingFunctionType
"""音量处理函数"""
- midi_music_name: str
- """Midi乐曲名"""
-
enable_old_exe_format: bool
"""是否启用旧版execute指令格式"""
execute_cmd_head: str
"""execute指令头部"""
- channels: Union[ChannelType, NoteChannelType]
- """频道信息字典"""
-
music_command_list: List[SingleCommand]
"""音乐指令列表"""
@@ -115,10 +291,15 @@ class MidiConvert:
progress_bar_command: List[SingleCommand]
"""进度条指令列表"""
+ music_deviation: int
+ """音乐音调总偏移"""
+
def __init__(
self,
- midi_obj: VoidMido,
+ midi_obj: mido.MidiFile,
midi_name: str,
+ deviation: Union[int, Literal[None]] = 0,
+ ignore_mismatch_error: bool = True,
enable_old_exe_format: bool = False,
pitched_note_rtable: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_rtable: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
@@ -141,9 +322,15 @@ class MidiConvert:
打击乐器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
@@ -165,6 +352,7 @@ class MidiConvert:
def from_midi_file(
cls,
midi_file_path: str,
+ ignore_mismatch_error: bool = True,
old_exe_format: bool = False,
pitched_note_table: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_table: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
@@ -192,9 +380,14 @@ class MidiConvert:
try:
return cls(
- mido.MidiFile(midi_file_path, clip=True),
+ mido.MidiFile(
+ midi_file_path,
+ clip=True,
+ ),
midi_music_name,
+ None,
old_exe_format,
+ ignore_mismatch_error,
pitched_note_table,
percussion_note_table,
vol_processing_func,
@@ -207,6 +400,11 @@ class MidiConvert:
# ……真的那么重要吗
# 我又几曾何时,知道祂真的会抛下我
+ def guess_deviation(self) -> int:
+
+ # 等我想想看
+ return 0
+
def form_progress_bar(
self,
max_score: int,
@@ -422,7 +620,7 @@ class MidiConvert:
npg_stl = (
pgs_style.replace("_", progressbar_style.played_style, i + 1)
.replace("_", progressbar_style.to_play_style)
- .replace(r"%%N", self.midi_music_name)
+ .replace(r"%%N", self.music_name)
.replace(
r"%%s",
'"},{"score":{"name":"*","objective":"'
@@ -482,145 +680,6 @@ class MidiConvert:
self.progress_bar_command = 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(
self,
scoreboard_name: str = "mscplay",
@@ -653,7 +712,7 @@ class MidiConvert:
max_score = 0
# 此处 我们把通道视为音轨
- for channel in self.to_music_note_channels().values():
+ for channel in self.channels.values():
# 如果当前通道为空 则跳过
if not channel:
continue
@@ -676,8 +735,11 @@ class MidiConvert:
if note.percussive
else self.pitched_note_reference_table
),
- (max_volume) if note.track_no == 0 else (max_volume * 0.9),
- self.volume_processing_function,
+ deviation=self.music_deviation,
+ volume_percentage=(
+ (max_volume) if note.track_no == 0 else (max_volume * 0.9)
+ ),
+ volume_processing_method=self.volume_processing_function,
)
this_channel.append(
@@ -756,7 +818,7 @@ class MidiConvert:
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.sort(key=lambda a: a.start_time)
@@ -785,8 +847,11 @@ class MidiConvert:
if note.percussive
else self.pitched_note_reference_table
),
- (max_volume) if note.track_no == 0 else (max_volume * 0.9),
- self.volume_processing_function,
+ deviation=self.music_deviation,
+ 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(
@@ -829,8 +894,8 @@ class MidiConvert:
def copy_important(self):
dst = MidiConvert(
- midi_obj=None,
- midi_name=self.midi_music_name,
+ midi_obj=mido.MidiFile(),
+ midi_name=self.music_name,
enable_old_exe_format=self.enable_old_exe_format,
)
dst.music_command_list = [i.copy() for i in self.music_command_list]
diff --git a/Musicreater/plugin/addonpack/main.py b/Musicreater/plugin/addonpack/main.py
index 75b2a04..f4655b6 100644
--- a/Musicreater/plugin/addonpack/main.py
+++ b/Musicreater/plugin/addonpack/main.py
@@ -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:
json.dump(
behavior_mcpack_manifest(
- pack_description=f"{midi_cvt.midi_music_name} 音乐播放包,MCFUNCTION(MCPACK) 计分播放器 - 由 音·创 生成",
- pack_name=midi_cvt.midi_music_name + "播放",
+ pack_description=f"{midi_cvt.music_name} 音乐播放包,MCFUNCTION(MCPACK) 计分播放器 - 由 音·创 生成",
+ pack_name=midi_cvt.music_name + "播放",
modules_description=f"无 - 由 音·创 生成",
),
fp=f,
@@ -136,11 +136,11 @@ def to_addon_pack_in_score(
index_file.close()
- if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack"):
- os.remove(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.music_name}.mcpack")
compress_zipfile(
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/")
@@ -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:
json.dump(
behavior_mcpack_manifest(
- pack_description=f"{midi_cvt.midi_music_name} 音乐播放包,MCSTRUCTURE(MCPACK) 延迟播放器 - 由 音·创 生成",
- pack_name=midi_cvt.midi_music_name + "播放",
+ pack_description=f"{midi_cvt.music_name} 音乐播放包,MCSTRUCTURE(MCPACK) 延迟播放器 - 由 音·创 生成",
+ pack_name=midi_cvt.music_name + "播放",
modules_description=f"无 - 由 音·创 生成",
),
fp=f,
@@ -229,7 +229,7 @@ def to_addon_pack_in_delay(
os.path.join(
data_cfg.dist_path,
"temp/structures/",
- f"{midi_cvt.midi_music_name}_main.mcstructure",
+ f"{midi_cvt.music_name}_main.mcstructure",
)
),
"wb+",
@@ -239,7 +239,7 @@ def to_addon_pack_in_delay(
del struct
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))
struct_a = Structure((1, 1, 1), compability_version=compability_ver)
@@ -261,14 +261,14 @@ def to_addon_pack_in_delay(
os.path.join(
data_cfg.dist_path,
"temp/structures/",
- f"{midi_cvt.midi_music_name}_start.mcstructure",
+ f"{midi_cvt.music_name}_start.mcstructure",
)
),
"wb+",
) as 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(
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(
data_cfg.dist_path,
"temp/structures/",
- f"{midi_cvt.midi_music_name}_pgb.mcstructure",
+ f"{midi_cvt.music_name}_pgb.mcstructure",
)
),
"wb+",
) as 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(
(1, 1, 1),
@@ -311,7 +311,7 @@ def to_addon_pack_in_delay(
os.path.join(
data_cfg.dist_path,
"temp/structures/",
- f"{midi_cvt.midi_music_name}_reset.mcstructure",
+ f"{midi_cvt.music_name}_reset.mcstructure",
)
),
"wb+",
@@ -321,23 +321,23 @@ def to_addon_pack_in_delay(
del struct_a, pgb_struct
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(
- 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:
- 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()
- if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack"):
- os.remove(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.music_name}.mcpack")
compress_zipfile(
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/")
@@ -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:
json.dump(
behavior_mcpack_manifest(
- pack_description=f"{midi_cvt.midi_music_name} 音乐播放包,MCSTRUCTURE(MCPACK) 中继器播放器 - 由 音·创 生成",
- pack_name=midi_cvt.midi_music_name + "播放",
+ pack_description=f"{midi_cvt.music_name} 音乐播放包,MCSTRUCTURE(MCPACK) 中继器播放器 - 由 音·创 生成",
+ pack_name=midi_cvt.music_name + "播放",
modules_description=f"无 - 由 音·创 生成",
),
fp=f,
@@ -427,7 +427,7 @@ def to_addon_pack_in_repeater(
os.path.join(
data_cfg.dist_path,
"temp/structures/",
- f"{midi_cvt.midi_music_name}_main.mcstructure",
+ f"{midi_cvt.music_name}_main.mcstructure",
)
),
"wb+",
@@ -437,7 +437,7 @@ def to_addon_pack_in_repeater(
del struct
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))
struct_a = Structure((1, 1, 1), compability_version=compability_ver)
@@ -459,14 +459,14 @@ def to_addon_pack_in_repeater(
os.path.join(
data_cfg.dist_path,
"temp/structures/",
- f"{midi_cvt.midi_music_name}_start.mcstructure",
+ f"{midi_cvt.music_name}_start.mcstructure",
)
),
"wb+",
) as 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(
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(
data_cfg.dist_path,
"temp/structures/",
- f"{midi_cvt.midi_music_name}_pgb.mcstructure",
+ f"{midi_cvt.music_name}_pgb.mcstructure",
)
),
"wb+",
) as 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(
(1, 1, 1),
@@ -509,7 +509,7 @@ def to_addon_pack_in_repeater(
os.path.join(
data_cfg.dist_path,
"temp/structures/",
- f"{midi_cvt.midi_music_name}_reset.mcstructure",
+ f"{midi_cvt.music_name}_reset.mcstructure",
)
),
"wb+",
@@ -519,23 +519,23 @@ def to_addon_pack_in_repeater(
del struct_a, pgb_struct
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(
- 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:
- 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()
- if os.path.exists(f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack"):
- os.remove(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.music_name}.mcpack")
compress_zipfile(
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/")
diff --git a/Musicreater/plugin/bdxfile/main.py b/Musicreater/plugin/bdxfile/main.py
index 41db20b..51c2e72 100644
--- a/Musicreater/plugin/bdxfile/main.py
+++ b/Musicreater/plugin/bdxfile/main.py
@@ -69,7 +69,7 @@ def to_BDX_file_in_score(
with open(
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+",
) as f:
@@ -119,7 +119,7 @@ def to_BDX_file_in_score(
with open(
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+",
) as f:
@@ -167,7 +167,7 @@ def to_BDX_file_in_delay(
with open(
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+",
) as f:
@@ -180,7 +180,7 @@ def to_BDX_file_in_delay(
cmdBytes, size, finalPos = commands_to_BDX_bytes(cmdlist, max_height - 1)
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(
r"scoreboard objectives add {} dummy {}计".replace(r"{}", scb_name),
1,
@@ -217,7 +217,7 @@ def to_BDX_file_in_delay(
with open(
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+",
) as f:
diff --git a/Musicreater/plugin/mcstructfile/main.py b/Musicreater/plugin/mcstructfile/main.py
index 9b8f29a..ad10ffb 100644
--- a/Musicreater/plugin/mcstructfile/main.py
+++ b/Musicreater/plugin/mcstructfile/main.py
@@ -72,7 +72,7 @@ def to_mcstructure_file_in_delay(
with open(
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+",
) as f:
@@ -144,7 +144,7 @@ def to_mcstructure_file_in_score(
with open(
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+",
) as f:
@@ -207,7 +207,7 @@ def to_mcstructure_file_in_repeater(
with open(
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+",
) as f:
diff --git a/Musicreater/subclass.py b/Musicreater/subclass.py
index f77790c..bdd3d59 100644
--- a/Musicreater/subclass.py
+++ b/Musicreater/subclass.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
-存储许多非主要的相关类
+存储音·创附属子类
"""
"""
diff --git a/Musicreater/types.py b/Musicreater/types.py
index c3670df..0e354d2 100644
--- a/Musicreater/types.py
+++ b/Musicreater/types.py
@@ -36,7 +36,7 @@ MidiNoteNameTableType = Mapping[int, Tuple[str, ...]]
Midi音符名称对照表类型
"""
-MidiInstrumentTableType = Mapping[int, Tuple[str, int]]
+MidiInstrumentTableType = Mapping[int, str]
"""
Midi乐器对照表类型
"""
diff --git a/Musicreater/utils.py b/Musicreater/utils.py
index cc1bbf7..7deacf3 100644
--- a/Musicreater/utils.py
+++ b/Musicreater/utils.py
@@ -18,7 +18,7 @@ Terms & Conditions: License.md in the root directory
import math
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 .types import (
@@ -58,18 +58,10 @@ def inst_to_sould_with_deviation(
instrumentID: int,
reference_table: MidiInstrumentTableType,
default_instrument: str = "note.flute",
- default_deviation: Optional[int] = 5,
) -> Tuple[str, int]:
"""
返回midi的乐器ID对应的我的世界乐器名,对于音域转换算法,如下:
- 2**( ( msg.note - 60 - X ) / 12 ) 即为MC的音高,其中
- X的取值随乐器不同而变化:
- 竖琴harp、电钢琴pling、班卓琴banjo、方波bit、颤音琴iron_xylophone 的时候为6
- 吉他的时候为7
- 贝斯bass、迪吉里杜管didgeridoo的时候为8
- 长笛flute、牛铃cou_bell的时候为5
- 钟琴bell、管钟chime、木琴xylophone的时候为4
- 而存在一些打击乐器bd(basedrum)、hat、snare,没有音域,则没有X,那么我们返回7即可
+ 2**( ( msg.note - 66 ) / 12 ) 即为MC的音高
Parameters
----------
@@ -84,20 +76,43 @@ def inst_to_sould_with_deviation(
"""
return reference_table.get(
instrumentID,
- (
- default_instrument,
- (
- default_deviation
- if default_deviation
- else MM_INSTRUMENT_DEVIATION_TABLE.get(default_instrument, -1)
- ),
- ),
+ default=default_instrument,
+ ), 6
+
+ # 明明已经走了
+ # 凭什么还要在我心里留下缠绵缱绻
+
+
+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(
vol: float,
) -> float:
@@ -145,6 +160,7 @@ def straight_line(vol: float) -> float:
def note_to_command_parameters(
note_: SingleNote,
reference_table: MidiInstrumentTableType,
+ deviation: int = 0,
volume_percentage: float = 1,
volume_processing_method: Callable[[float], float] = natural_curve,
) -> Tuple[
@@ -156,20 +172,21 @@ def note_to_command_parameters(
"""
将音符转为播放的指令
: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_proccessing_method:Callable[[float], float]: 音量处理函数
+ :param volume_proccessing_method:Callable[[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,
reference_table,
"note.bd" if note_.percussive else "note.flute",
)
# 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)
diff --git a/README.md b/README.md
index 4ff1ac2..0d3b7da 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
-一款免费开源的《我的世界》数字音频转换库。
+一款免费开源的《我的世界》数字音频库。
@@ -46,6 +46,7 @@
```
- 如果无法更新最新,可以尝试:
+
```bash
pip install --upgrade -i https://pypi.python.org/simple Musicreater
```
diff --git a/README_EN.md b/README_EN.md
index ebba876..4538424 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -7,7 +7,7 @@
-A free open-source library of converting digital music files into Minecraft formats.
+A free open-source library of Minecraft digital music.
@@ -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:
+
```bash
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.
-
## Documentation 📄
(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: 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
diff --git a/clean_update.py b/clean_update.py
index 410261a..ec1475d 100644
--- a/clean_update.py
+++ b/clean_update.py
@@ -13,7 +13,9 @@ def main():
if file.endswith(".egg-info"):
egg_info.append(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):
shutil.rmtree(file)
diff --git a/example.py b/example.py
index e78f567..f3c3cfc 100644
--- a/example.py
+++ b/example.py
@@ -189,10 +189,12 @@ print(
)
)
if fileFormat == 1
- else (" 结构大小:{},延迟总数:{},指令数量:{}".format(
+ else (
+ " 结构大小:{},延迟总数:{},指令数量:{}".format(
*(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
)
)