diff --git a/Musicreater/__init__.py b/Musicreater/__init__.py index d5c2663..df9b37a 100644 --- a/Musicreater/__init__.py +++ b/Musicreater/__init__.py @@ -22,8 +22,8 @@ The Licensor of Musicreater("this project") is Eilles, bgArray. # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md -__version__ = "2.3.1" -__vername__ = "新增部分新可指定的默认值" +__version__ = "2.3.2" +__vername__ = "支持神羽资源包" __author__ = ( ("金羿", "Eilles"), ("诸葛亮与八卦阵", "bgArray"), diff --git a/Musicreater/experiment.py b/Musicreater/experiment.py index 4d3983a..9f01202 100644 --- a/Musicreater/experiment.py +++ b/Musicreater/experiment.py @@ -33,6 +33,9 @@ from .utils import * class FutureMidiConvertKamiRES(MidiConvert): + """ + 神羽资源包之测试支持 + """ @staticmethod def to_music_note_channels( midi: mido.MidiFile, @@ -212,6 +215,154 @@ class FutureMidiConvertKamiRES(MidiConvert): ) + def to_command_list_in_score( + self, + scoreboard_name: str = "mscplay", + ) -> Tuple[List[List[MineCommand]], int, int]: + """ + 将midi转换为我的世界命令列表 + + Parameters + ---------- + scoreboard_name: str + 我的世界的计分板名称 + + Returns + ------- + tuple( list[list[MineCommand指令,... ],... ], int指令数量, int音乐时长游戏刻 ) + """ + + command_channels = [] + command_amount = 0 + max_score = 0 + + # 此处 我们把通道视为音轨 + for channel in self.channels.values(): + # 如果当前通道为空 则跳过 + if not channel: + continue + + this_channel = [] + + for note in channel: + max_score = max(max_score, note.start_tick) + + ( + mc_sound_ID, + relative_coordinates, + volume_percentage, + mc_pitch, + ) = minenote_to_command_paramaters( + note, + pitch_deviation=self.music_deviation, + ) + + this_channel.append( + MineCommand( + ( + self.execute_cmd_head.format( + "@a[scores=({}={})]".format( + scoreboard_name, note.start_tick + ) + .replace("(", r"{") + .replace(")", r"}") + ) + + r"playsound {} @s ^{} ^{} ^{} {} {} {}".format( + mc_sound_ID, + *relative_coordinates, + volume_percentage, + 1.0, + self.minimum_volume, + ) + ), + annotation=( + "在{}播放{}".format( + mctick2timestr(note.start_tick), + mc_sound_ID, + ) + ), + ), + ) + + command_amount += 1 + + if this_channel: + self.music_command_list.extend(this_channel) + command_channels.append(this_channel) + + return command_channels, command_amount, max_score + + def to_command_list_in_delay( + self, + player_selector: str = "@a", + ) -> Tuple[List[MineCommand], int, int]: + """ + 将midi转换为我的世界命令列表,并输出每个音符之后的延迟 + + Parameters + ---------- + player_selector: str + 玩家选择器,默认为`@a` + + Returns + ------- + tuple( list[MineCommand指令,...], int音乐时长游戏刻, int最大同时播放的指令数量 ) + """ + + notes_list: List[MineNote] = sorted( + [i for j in self.channels.values() for i in j], + key=lambda note: note.start_tick, + ) + + # 此处 我们把通道视为音轨 + self.music_command_list = [] + multi = max_multi = 0 + delaytime_previous = 0 + + for note in notes_list: + if (tickdelay := (note.start_tick - delaytime_previous)) == 0: + multi += 1 + else: + max_multi = max(max_multi, multi) + multi = 0 + + ( + mc_sound_ID, + relative_coordinates, + volume_percentage, + mc_pitch, + ) = minenote_to_command_paramaters( + note, + pitch_deviation=self.music_deviation, + ) + + self.music_command_list.append( + MineCommand( + command=( + self.execute_cmd_head.format(player_selector) + + r"playsound {} @s ^{} ^{} ^{} {} {} {}".format( + mc_sound_ID, + *relative_coordinates, + volume_percentage, + 1.0, + self.minimum_volume, + ) + ), + annotation=( + "在{}播放音{}".format( + mctick2timestr(note.start_tick), + mc_sound_ID, + ) + ), + tick_delay=tickdelay, + ), + ) + delaytime_previous = note.start_tick + + return self.music_command_list, notes_list[-1].start_tick, max_multi + 1 + + + class FutureMidiConvertJavaE(MidiConvert): def form_java_progress_bar( diff --git a/Musicreater/utils.py b/Musicreater/utils.py index 444773e..38edcef 100644 --- a/Musicreater/utils.py +++ b/Musicreater/utils.py @@ -326,7 +326,8 @@ def midi_msgs_to_minenote_using_kami_respack( using_original = False if not percussive_ and (0 <= inst_ <= 119): mc_sound_ID = "{}{}.{}".format( - inst_, "d" if duration_ < 500_000 else "c", note_ + # inst_, "d" if duration_ < 500_000 else "c", note_ + inst_, "d", note_ ) elif percussive_ and (27 <= inst_ <= 87): mc_sound_ID = "-1d.{}".format(inst_) diff --git a/Packer/MSCT_Packer.py b/Packer/MSCT_Packer.py index b8f02e2..4fea1c9 100644 --- a/Packer/MSCT_Packer.py +++ b/Packer/MSCT_Packer.py @@ -1,6 +1,7 @@ import Musicreater import Musicreater.experiment import Musicreater.plugin + # import Musicreater.previous from Musicreater.plugin.addonpack import ( to_addon_pack_in_delay, diff --git a/pyproject.toml b/pyproject.toml index 4fee649..217a217 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,6 +51,7 @@ dev = [ "TrimMCStruct <= 0.0.5.9", "brotli >= 1.0.0", + "dill", "rich", "pyinstaller", "twine", @@ -91,3 +92,4 @@ [tool.pdm.version] source = "file" path = "Musicreater/__init__.py" + diff --git a/setup.py b/setup.py deleted file mode 100644 index 6391f1b..0000000 --- a/setup.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -import setuptools -import os - -# from Musicreater import __version__ - -os.chdir(os.path.dirname(os.path.abspath(__file__))) - -with open("./requirements.txt", "r", encoding="utf-8") as fh: - dependences = fh.read().strip().split("\n") - -with open("./README_EN.md", "r", encoding="utf-8") as fh: - long_description = fh.read().replace( - "./docs/", "https://github.com/TriM-Organization/Musicreater/blob/master/docs/" - ) - -setuptools.setup( - name="Musicreater", - version="2.2.4", - author="金羿Eilles, bgArray, 鱼旧梦ElapsingDreams", - author_email="TriM-Organization@hotmail.com", - description="A free open source library used for dealing with **Minecraft** digital musics.\n一款开源《我的世界》数字音频支持库。", - long_description=long_description, - long_description_content_type="text/markdown", - url="https://github.com/TriM-Organization/Musicreater", - packages=setuptools.find_packages(), - classifiers=[ - "Intended Audience :: Developers", - "Natural Language :: Chinese (Simplified)", - # "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Topic :: Software Development :: Libraries", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Topic :: Multimedia", - "Topic :: Multimedia :: Sound/Audio :: MIDI", - ], - # 需要安装的依赖 - install_requires=dependences, - python_requires=">=3.8", - license=open("./LICENSE.md", "r", encoding="utf-8").read(), -) diff --git a/test_future_kamires.py b/test_future_kamires.py index a317091..4857b38 100644 --- a/test_future_kamires.py +++ b/test_future_kamires.py @@ -1,2 +1,33 @@ +import Musicreater.experiment +import Musicreater.plugin +import Musicreater.plugin.mcstructfile -pass \ No newline at end of file +msct = Musicreater.experiment.FutureMidiConvertKamiRES.from_midi_file( + input("midi路径:"), old_exe_format=False +) + +opt = input("输出路径:") + +print( + "乐器使用情况", +) + +for name in set( + sorted( + [ + n.split(".")[0].replace("c", "").replace("d", "") + for n in msct.note_count_per_instrument.keys() + ] + ) +): + print("\t", name, flush=True) + +print( + "\n输出:", + Musicreater.plugin.mcstructfile.to_mcstructure_file_in_delay( + msct, + opt, + # Musicreater.plugin.ConvertConfig(input("输出路径:"),), + max_height=32, + ), +) diff --git a/uv.lock b/uv.lock index fb9341c..525af6d 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 1 +revision = 2 requires-python = ">=3.8, <4.0" resolution-markers = [ "python_full_version >= '3.10'", @@ -314,6 +314,15 @@ wheels = [ { url = "https://mirror.nju.edu.cn/pypi/web/packages/57/ff/f3b4b2d007c2a646b0f69440ab06224f9cf37a977a72cdb7b50632174e8a/cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390" }, ] +[[package]] +name = "dill" +version = "0.4.0" +source = { registry = "https://mirror.nju.edu.cn/pypi/web/simple" } +sdist = { url = "https://mirror.nju.edu.cn/pypi/web/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0" } +wheels = [ + { url = "https://mirror.nju.edu.cn/pypi/web/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049" }, +] + [[package]] name = "docutils" version = "0.20.1" @@ -575,6 +584,7 @@ dependencies = [ [package.optional-dependencies] dev = [ { name = "brotli" }, + { name = "dill" }, { name = "pyinstaller" }, { name = "rich" }, { name = "trimmcstruct" }, @@ -589,6 +599,7 @@ full = [ requires-dist = [ { name = "brotli", marker = "extra == 'dev'", specifier = ">=1.0.0" }, { name = "brotli", marker = "extra == 'full'", specifier = ">=1.0.0" }, + { name = "dill", marker = "extra == 'dev'" }, { name = "mido", specifier = ">=1.3" }, { name = "pyinstaller", marker = "extra == 'dev'" }, { name = "rich", marker = "extra == 'dev'" },