文档全面升级,部分架构更新

This commit is contained in:
EillesWan 2023-09-24 00:38:31 +08:00
parent 7b60d3f9ea
commit 76eff25a1d
25 changed files with 517 additions and 515 deletions

View File

@ -17,8 +17,8 @@ Terms & Conditions: License.md in the root directory
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
__version__ = "1.4.2" __version__ = "1.5.0"
__vername__ = "优质的红石音乐生成&更好的线性插值算法" __vername__ = "修改附加包插件的调用方式,新增播放终止函数,文档内容增强"
__author__ = ( __author__ = (
("金羿", "Eilles Wan"), ("金羿", "Eilles Wan"),
("诸葛亮与八卦阵", "bgArray"), ("诸葛亮与八卦阵", "bgArray"),

View File

@ -171,7 +171,7 @@ class FutureMidiConvertM4(MidiConvert):
:return list[tuple(int开始时间毫秒, int乐器, int音符, int力度内置, float音量播放),]""" :return list[tuple(int开始时间毫秒, int乐器, int音符, int力度内置, float音量播放),]"""
totalCount = int(_note.duration / _apply_time_division) totalCount = int(_note.duration / _apply_time_division)
if totalCount == 0: if totalCount == 0:
return [ return [
(_note.start_time, _note.inst, _note.pitch, _note.velocity, 1), (_note.start_time, _note.inst, _note.pitch, _note.velocity, 1),
@ -411,9 +411,7 @@ class FutureMidiConvertM4(MidiConvert):
SpecialBits = True if no == 9 else False SpecialBits = True if no == 9 else False
for note in track: for note in track:
liner_list = self._linear_note( liner_list = self._linear_note(note, 100 if note.track_no == 0 else 500)
note, 100 if note.track_no == 0 else 500
)
for every_note in liner_list: for every_note in liner_list:
soundID, _X = ( soundID, _X = (
self.perc_inst_to_soundID_withX(note.pitch) self.perc_inst_to_soundID_withX(note.pitch)
@ -446,7 +444,7 @@ class FutureMidiConvertM4(MidiConvert):
all_ticks = list(tracks.keys()) all_ticks = list(tracks.keys())
all_ticks.sort() all_ticks.sort()
results:List[SingleCommand] = [] results: List[SingleCommand] = []
max_multi = 0 max_multi = 0
now_multi_delay = 0 now_multi_delay = 0
now_multi = 0 now_multi = 0

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
用以生成函数附加包的附加功能 用以生成附加包的附加功能
版权所有 © 2023 · 开发者 版权所有 © 2023 · 开发者
Copyright © 2023 all the developers of Musicreater Copyright © 2023 all the developers of Musicreater
@ -15,9 +15,14 @@ Terms & Conditions: License.md in the root directory
__all__ = [ __all__ = [
"to_function_addon_in_score" "to_addon_pack_in_delay",
"to_addon_pack_in_score",
"to_addon_pack_in_repeater",
] ]
__author__ = (("金羿", "Eilles Wan"),) __author__ = (("金羿", "Eilles Wan"),)
from .main import * from .main import (
to_addon_pack_in_delay,
to_addon_pack_in_repeater,
to_addon_pack_in_score,
)

View File

@ -14,10 +14,10 @@ Terms & Conditions: License.md in the root directory
import json import json
import os import os
import shutil import shutil
from typing import Tuple
from TrimMCStruct import Structure from TrimMCStruct import Structure
from ...exceptions import CommandFormatError
from ...main import MidiConvert from ...main import MidiConvert
from ..archive import behavior_mcpack_manifest, compress_zipfile from ..archive import behavior_mcpack_manifest, compress_zipfile
from ..main import ConvertConfig from ..main import ConvertConfig
@ -30,12 +30,128 @@ from ..mcstructure import (
) )
def to_mcstructure_addon_in_delay( def to_addon_pack_in_score(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
scoreboard_name: str = "mscplay",
auto_reset: bool = False,
) -> Tuple[int, int]:
"""
将midi以计分播放器形式转换为我的世界函数附加包
Parameters
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
scoreboard_name: str
我的世界的计分板名称
auto_reset: bool
是否自动重置计分板
Returns
-------
tuple[int指令数量, int音乐总延迟]
"""
cmdlist, maxlen, maxscore = midi_cvt.to_command_list_in_score(
scoreboard_name, data_cfg.volume_ratio, data_cfg.speed_multiplier
)
# 当文件f夹{self.outputPath}/temp/functions存在时清空其下所有项目然后创建
if os.path.exists(f"{data_cfg.dist_path}/temp/functions/"):
shutil.rmtree(f"{data_cfg.dist_path}/temp/functions/")
os.makedirs(f"{data_cfg.dist_path}/temp/functions/mscplay")
# 写入manifest.json
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 + "播放",
modules_description=f"无 - 由 音·创 生成",
),
fp=f,
indent=4,
)
# 写入stop.mcfunction
with open(
f"{data_cfg.dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
) as f:
f.write("scoreboard players reset @a {}".format(scoreboard_name))
# 将命令列表写入文件
index_file = open(
f"{data_cfg.dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
)
for i in range(len(cmdlist)):
index_file.write(f"function mscplay/track{i + 1}\n")
with open(
f"{data_cfg.dist_path}/temp/functions/mscplay/track{i + 1}.mcfunction",
"w",
encoding="utf-8",
) as f:
f.write("\n".join([single_cmd.cmd for single_cmd in cmdlist[i]]))
index_file.writelines(
(
"scoreboard players add @a[scores={"
+ scoreboard_name
+ "=1..}] "
+ scoreboard_name
+ " 1\n",
(
"scoreboard players reset @a[scores={"
+ scoreboard_name
+ "="
+ str(maxscore + 20)
+ "..}]"
+ f" {scoreboard_name}\n"
)
if auto_reset
else "",
f"function mscplay/progressShow\n" if data_cfg.progressbar_style else "",
)
)
if data_cfg.progressbar_style:
with open(
f"{data_cfg.dist_path}/temp/functions/mscplay/progressShow.mcfunction",
"w",
encoding="utf-8",
) as f:
f.writelines(
"\n".join(
[
single_cmd.cmd
for single_cmd in midi_cvt.form_progress_bar(
maxscore, scoreboard_name, data_cfg.progressbar_style
)
]
)
)
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")
compress_zipfile(
f"{data_cfg.dist_path}/temp/",
f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack",
)
shutil.rmtree(f"{data_cfg.dist_path}/temp/")
return maxlen, maxscore
def to_addon_pack_in_delay(
midi_cvt: MidiConvert, midi_cvt: MidiConvert,
data_cfg: ConvertConfig, data_cfg: ConvertConfig,
player: str = "@a", player: str = "@a",
max_height: int = 64, max_height: int = 64,
): ) -> Tuple[int, int]:
""" """
将midi以延迟播放器形式转换为mcstructure结构文件后打包成附加包并在附加包中生成相应地导入函数 将midi以延迟播放器形式转换为mcstructure结构文件后打包成附加包并在附加包中生成相应地导入函数
@ -88,6 +204,14 @@ def to_mcstructure_addon_in_delay(
indent=4, indent=4,
) )
# 写入stop.mcfunction
with open(
f"{data_cfg.dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
) as f:
f.write(
"gamerule commandblocksenabled false\ngamerule commandblocksenabled true"
)
# 将命令列表写入文件 # 将命令列表写入文件
index_file = open( index_file = open(
f"{data_cfg.dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8" f"{data_cfg.dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
@ -219,16 +343,14 @@ def to_mcstructure_addon_in_delay(
return len(command_list), max_delay return len(command_list), max_delay
def to_addon_pack_in_repeater(
def to_mcstructure_addon_in_redstone_cd(
midi_cvt: MidiConvert, midi_cvt: MidiConvert,
data_cfg: ConvertConfig, data_cfg: ConvertConfig,
player: str = "@a", player: str = "@a",
max_height: int = 65, max_height: int = 65,
): ) -> Tuple[int, int]:
""" """
将midi以延迟播放器形式转换为mcstructure结构文件后打包成附加包并在附加包中生成相应地导入函数 将midi以中继器播放器形式转换为mcstructure结构文件后打包成附加包并在附加包中生成相应地导入函数
Parameters Parameters
---------- ----------
@ -252,7 +374,7 @@ def to_mcstructure_addon_in_redstone_cd(
else COMPABILITY_VERSION_119 else COMPABILITY_VERSION_119
) )
command_list, max_delay,max_together = midi_cvt.to_command_list_in_delay( command_list, max_delay, max_together = midi_cvt.to_command_list_in_delay(
data_cfg.volume_ratio, data_cfg.volume_ratio,
data_cfg.speed_multiplier, data_cfg.speed_multiplier,
player, player,
@ -279,6 +401,14 @@ def to_mcstructure_addon_in_redstone_cd(
indent=4, indent=4,
) )
# 写入stop.mcfunction
with open(
f"{data_cfg.dist_path}/temp/functions/stop.mcfunction", "w", encoding="utf-8"
) as f:
f.write(
"gamerule commandblocksenabled false\ngamerule commandblocksenabled true"
)
# 将命令列表写入文件 # 将命令列表写入文件
index_file = open( index_file = open(
f"{data_cfg.dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8" f"{data_cfg.dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"

View File

@ -20,5 +20,5 @@ __all__ = [
] ]
__author__ = (("金羿", "Eilles Wan"),) __author__ = (("金羿", "Eilles Wan"),)
from .main import * from .main import to_BDX_file_in_delay,to_BDX_file_in_score

View File

@ -18,8 +18,14 @@ import brotli
from ...main import MidiConvert from ...main import MidiConvert
from ...subclass import SingleCommand from ...subclass import SingleCommand
from ..bdx import (bdx_move, commands_to_BDX_bytes, from ..bdx import (
form_command_block_in_BDX_bytes, x, y, z) bdx_move,
commands_to_BDX_bytes,
form_command_block_in_BDX_bytes,
x,
y,
z,
)
from ..main import ConvertConfig from ..main import ConvertConfig

View File

@ -25,5 +25,3 @@ def bottem_side_length_of_smallest_square_bottom_box(total: int, maxHeight: int)
:param maxHeight: 最大高度 :param maxHeight: 最大高度
:return: 外切正方形的边长 int""" :return: 外切正方形的边长 int"""
return math.ceil(math.sqrt(math.ceil(total / maxHeight))) return math.ceil(math.sqrt(math.ceil(total / maxHeight)))

View File

@ -1,132 +0,0 @@
# -*- coding: utf-8 -*-
"""
版权所有 © 2023 · 开发者
Copyright © 2023 all the developers of Musicreater
开源相关声明请见 仓库根目录下的 License.md
Terms & Conditions: License.md in the root directory
"""
# 睿穆组织 开发交流群 861684859
# Email TriM-Organization@hotmail.com
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
import json
import os
import shutil
from typing import Tuple
from ...main import MidiConvert
from ..archive import behavior_mcpack_manifest, compress_zipfile
from ..main import ConvertConfig
def to_function_addon_in_score(
midi_cvt: MidiConvert,
data_cfg: ConvertConfig,
scoreboard_name: str = "mscplay",
auto_reset: bool = False,
) -> Tuple[int, int]:
"""
将midi以计分播放器形式转换为我的世界函数附加包
Parameters
----------
midi_cvt: MidiConvert 对象
用于转换的MidiConvert对象
data_cfg: ConvertConfig 对象
部分转换通用参数
scoreboard_name: str
我的世界的计分板名称
auto_reset: bool
是否自动重置计分板
Returns
-------
tuple[int指令数量, int音乐总延迟]
"""
cmdlist, maxlen, maxscore = midi_cvt.to_command_list_in_score(
scoreboard_name, data_cfg.volume_ratio, data_cfg.speed_multiplier
)
# 当文件f夹{self.outputPath}/temp/functions存在时清空其下所有项目然后创建
if os.path.exists(f"{data_cfg.dist_path}/temp/functions/"):
shutil.rmtree(f"{data_cfg.dist_path}/temp/functions/")
os.makedirs(f"{data_cfg.dist_path}/temp/functions/mscplay")
# 写入manifest.json
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 + "播放",
modules_description=f"无 - 由 音·创 生成",
),
fp=f,
indent=4,
)
# 将命令列表写入文件
index_file = open(
f"{data_cfg.dist_path}/temp/functions/index.mcfunction", "w", encoding="utf-8"
)
for i in range(len(cmdlist)):
index_file.write(f"function mscplay/track{i + 1}\n")
with open(
f"{data_cfg.dist_path}/temp/functions/mscplay/track{i + 1}.mcfunction",
"w",
encoding="utf-8",
) as f:
f.write("\n".join([single_cmd.cmd for single_cmd in cmdlist[i]]))
index_file.writelines(
(
"scoreboard players add @a[scores={"
+ scoreboard_name
+ "=1..}] "
+ scoreboard_name
+ " 1\n",
(
"scoreboard players reset @a[scores={"
+ scoreboard_name
+ "="
+ str(maxscore + 20)
+ "..}]"
+ f" {scoreboard_name}\n"
)
if auto_reset
else "",
f"function mscplay/progressShow\n" if data_cfg.progressbar_style else "",
)
)
if data_cfg.progressbar_style:
with open(
f"{data_cfg.dist_path}/temp/functions/mscplay/progressShow.mcfunction",
"w",
encoding="utf-8",
) as f:
f.writelines(
"\n".join(
[
single_cmd.cmd
for single_cmd in midi_cvt.form_progress_bar(
maxscore, scoreboard_name, data_cfg.progressbar_style
)
]
)
)
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")
compress_zipfile(
f"{data_cfg.dist_path}/temp/",
f"{data_cfg.dist_path}/{midi_cvt.midi_music_name}.mcpack",
)
shutil.rmtree(f"{data_cfg.dist_path}/temp/")
return maxlen, maxscore

View File

@ -16,9 +16,9 @@ Terms & Conditions: License.md in the root directory
__all__ = [ __all__ = [
"to_mcstructure_file_in_delay", "to_mcstructure_file_in_delay",
"to_mcstructure_file_in_redstone_CD", "to_mcstructure_file_in_repeater",
] ]
__author__ = (("金羿", "Eilles Wan"),) __author__ = (("金羿", "Eilles Wan"),)
from .main import * from .main import to_mcstructure_file_in_delay,to_mcstructure_file_in_repeater

View File

@ -81,7 +81,7 @@ def to_mcstructure_file_in_delay(
return size, max_delay return size, max_delay
def to_mcstructure_file_in_redstone_CD( def to_mcstructure_file_in_repeater(
midi_cvt: MidiConvert, midi_cvt: MidiConvert,
data_cfg: ConvertConfig, data_cfg: ConvertConfig,
player: str = "@a", player: str = "@a",

View File

@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
"""
用以生成结构附加包的附加功能
版权所有 © 2023 · 开发者
Copyright © 2023 all the developers of Musicreater
开源相关声明请见 仓库根目录下的 License.md
Terms & Conditions: License.md in the root directory
"""
# 睿穆组织 开发交流群 861684859
# Email TriM-Organization@hotmail.com
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
__all__ = [
"to_mcstructure_addon_in_delay"
]
__author__ = (("金羿", "Eilles Wan"),)
from .main import *

View File

@ -349,7 +349,7 @@ def commands_to_redstone_delay_structure(
goahead = forward_IER(forward) goahead = forward_IER(forward)
command_actually_length = sum([int(bool(cmd.delay))for cmd in commands]) command_actually_length = sum([int(bool(cmd.delay)) for cmd in commands])
a = 1 a = 1
for cmd in commands: for cmd in commands:
@ -359,7 +359,6 @@ def commands_to_redstone_delay_structure(
else: else:
a += 1 a += 1
struct = Structure( struct = Structure(
size=( size=(
round(delay_length / 2 + command_actually_length) round(delay_length / 2 + command_actually_length)
@ -370,7 +369,7 @@ def commands_to_redstone_delay_structure(
if extensioon_direction == z if extensioon_direction == z
else a, else a,
), ),
fill=Block('minecraft','air',compability_version=compability_version_), fill=Block("minecraft", "air", compability_version=compability_version_),
compability_version=compability_version_, compability_version=compability_version_,
) )
@ -391,7 +390,7 @@ def commands_to_redstone_delay_structure(
additional_repeater = int(cmd.delay / 2 // 4) additional_repeater = int(cmd.delay / 2 // 4)
for i in range(additional_repeater): for i in range(additional_repeater):
struct.set_block( struct.set_block(
tuple(pos_now.values()),# type: ignore tuple(pos_now.values()), # type: ignore
Block( Block(
"minecraft", "minecraft",
base_block, base_block,
@ -409,7 +408,7 @@ def commands_to_redstone_delay_structure(
pos_now[extensioon_direction] += goahead pos_now[extensioon_direction] += goahead
if single_repeater_value >= 0: if single_repeater_value >= 0:
struct.set_block( struct.set_block(
tuple(pos_now.values()),# type: ignore tuple(pos_now.values()), # type: ignore
Block( Block(
"minecraft", "minecraft",
base_block, base_block,
@ -482,4 +481,4 @@ def commands_to_redstone_delay_structure(
) )
chain_list += 1 chain_list += 1
return struct, struct.size, tuple(pos_now.values())# type: ignore return struct, struct.size, tuple(pos_now.values()) # type: ignore

View File

@ -16,4 +16,3 @@ Terms & Conditions: License.md in the root directory
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
import nbtschematic import nbtschematic

View File

@ -16,26 +16,25 @@ Terms & Conditions: License.md in the root directory
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
import fcwslib import fcwslib
# 这个库有问题,正在检修 # 这个库有问题,正在检修
class Plugin(fcwslib.Plugin): class Plugin(fcwslib.Plugin):
async def on_connect(self) -> None: async def on_connect(self) -> None:
print('对象已被连接') print("对象已被连接")
await self.send_command('list', callback=self.list) await self.send_command("list", callback=self.list)
await self.subscribe('PlayerMessage', callback=self.player_message) await self.subscribe("PlayerMessage", callback=self.player_message)
async def on_disconnect(self) -> None: async def on_disconnect(self) -> None:
print('对象停止连接') print("对象停止连接")
async def on_receive(self, response) -> None: async def on_receive(self, response) -> None:
print('已接收非常规回复 {}'.format(response)) print("已接收非常规回复 {}".format(response))
async def list(self, response) -> None: async def list(self, response) -> None:
print('已收取指令执行回复 {}'.format(response)) print("已收取指令执行回复 {}".format(response))
async def player_message(self, response) -> None: async def player_message(self, response) -> None:
print('已收取玩家事件回复 {}'.format(response)) print("已收取玩家事件回复 {}".format(response))

View File

@ -15,8 +15,6 @@ Terms & Conditions: License.md in the root directory
# Email TriM-Organization@hotmail.com # Email TriM-Organization@hotmail.com
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
from typing import Dict, List, Tuple, Union
from .exceptions import * from .exceptions import *
from .main import MidiConvert, mido from .main import MidiConvert, mido
from .subclass import * from .subclass import *
@ -99,10 +97,8 @@ class ObsoleteMidiConvert(MidiConvert):
return [tracks, commands, maxscore] return [tracks, commands, maxscore]
def _toCmdList_m1( def _toCmdList_m1(
self, self, scoreboardname: str = "mscplay", volume: float = 1.0, speed: float = 1.0
scoreboardname: str = "mscplay", ) -> list:
volume: float = 1.0,
speed: float = 1.0) -> list:
""" """
使用Dislink Sforza的转换思路将midi转换为我的世界命令列表 使用Dislink Sforza的转换思路将midi转换为我的世界命令列表
:param scoreboardname: 我的世界的计分板名称 :param scoreboardname: 我的世界的计分板名称
@ -119,8 +115,7 @@ class ObsoleteMidiConvert(MidiConvert):
commands = 0 commands = 0
maxscore = 0 maxscore = 0
for i, track in enumerate(self.midi.tracks): for i, track in enumerate(self.midi.tracks): # type:ignore
ticks = 0 ticks = 0
instrumentID = 0 instrumentID = 0
singleTrack = [] singleTrack = []
@ -137,18 +132,18 @@ class ObsoleteMidiConvert(MidiConvert):
instrumentID = msg.program instrumentID = msg.program
if msg.type == "note_on" and msg.velocity != 0: if msg.type == "note_on" and msg.velocity != 0:
nowscore = round( nowscore = round(
(ticks * tempo) (ticks * tempo) / ((self.midi.ticks_per_beat * float(speed)) * 50000) # type: ignore
/ ((self.midi.ticks_per_beat * float(speed)) * 50000)
) )
maxscore = max(maxscore, nowscore) maxscore = max(maxscore, nowscore)
soundID, _X = self.__Inst2soundID_withX(instrumentID) soundID, _X = self.inst_to_souldID_withX(instrumentID)
singleTrack.append( singleTrack.append(
"execute @a[scores={" + "execute @a[scores={"
str(scoreboardname) + + str(scoreboardname)
"=" + + "="
str(nowscore) + + str(nowscore)
"}" + + "}"
f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}") + f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}"
)
commands += 1 commands += 1
if len(singleTrack) != 0: if len(singleTrack) != 0:
tracks.append(singleTrack) tracks.append(singleTrack)

View File

@ -10,7 +10,7 @@
<h3 align="center">一款免费开源的我的世界数字音频转换库</h3> <h3 align="center">一款免费开源的我的世界数字音频转换库</h3>
<p align="center"> <p align="center">
<img src="https://forthebadge.com/images/badges/built-with-love.svg"> <img src="https://img.shields.io/badge/BUILD%20WITH%20LOVE-FF3432?style=for-the-badge">
<a href='https://gitee.com/TriM-Organization/Musicreater'> <a href='https://gitee.com/TriM-Organization/Musicreater'>
<img align="right" src='https://gitee.com/TriM-Organization/Musicreater/widgets/widget_1.svg' alt='Fork me on Gitee'> <img align="right" src='https://gitee.com/TriM-Organization/Musicreater/widgets/widget_1.svg' alt='Fork me on Gitee'>
</img> </img>
@ -42,21 +42,15 @@
- 使用 pypi - 使用 pypi
```bash ```bash
pip install Musicreater pip install --upgrade Musicreater
``` ```
- 如果出现错误可以尝试 - 如果无法更新最新可以尝试
```bash ```bash
pip install -i https://pypi.python.org/simple Musicreater pip install --upgrade -i https://pypi.python.org/simple Musicreater
``` ```
- 升级 - 克隆仓库并安装**不推荐**
```bash
pip install -i https://pypi.python.org/simple Musicreater --upgrade
```
- 克隆仓库并安装
```bash ```bash
git clone https://gitee.com/TriM-Organization/Musicreater.git git clone https://gitee.com/TriM-Organization/Musicreater.git
cd Musicreater cd Musicreater
@ -92,11 +86,12 @@
- 感谢 **[神羽](https://gitee.com/snowykami) [SnowyKami](https://github.com/snowyfirefly)** 对我们项目的支持与宣传非常感谢他为我们提供的服务器 - 感谢 **[神羽](https://gitee.com/snowykami) [SnowyKami](https://github.com/snowyfirefly)** 对我们项目的支持与宣传非常感谢他为我们提供的服务器
- 感谢 **指令师\_苦力怕 playjuice123**\<QQ240667197\> 为我们的程序找出错误并提醒我们修复一个一直存在的大 bug - 感谢 **指令师\_苦力怕 playjuice123**\<QQ240667197\> 为我们的程序找出错误并提醒我们修复一个一直存在的大 bug
- 感谢 **雷霆**\<QQ3555268519\> 用他那令所有开发者都大为光火的操作方法为我们的程序找出错误并提醒修复 bug - 感谢 **雷霆**\<QQ3555268519\> 用他那令所有开发者都大为光火的操作方法为我们的程序找出错误并提醒修复 bug
- 感谢 **小埋**\<2039310975\> 反馈附加包生成时缺少描述和标题的问题 - 感谢 **小埋**\<QQ2039310975\> 反馈附加包生成时缺少描述和标题的问题
- <table><tr><td>感谢 **油炸**\<QQ2836146704\> 激励我们不断开发新的内容</td><td><img height="50" src="https://foruda.gitee.com/images/1695478907647543027/08ea9909_9911226.jpeg"></td></tr></table>
> 感谢广大群友为此程序提供的测试等支持 > 感谢广大群友为此库提供的测试和建议等
> >
> 若您对我们有所贡献但您的名字没有显示在此列表中请联系我们 > 若您对我们有所贡献但您的名字没有出现在此列表中请联系我们
## 联系 📞 ## 联系 📞

View File

@ -10,7 +10,7 @@
<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 converting digital music files into <i>Minecraft</i> formats.</h3>
<p align="center"> <p align="center">
<img src="https://forthebadge.com/images/badges/built-with-love.svg"> <img src="https://img.shields.io/badge/BUILD%20WITH%20LOVE-FF3432?style=for-the-badge">
</img> </img>
<p> <p>
@ -28,7 +28,7 @@
[简体中文 🇨🇳](README.md) | English🇬🇧 [简体中文 🇨🇳](README.md) | English🇬🇧
**Notice that the language translation of _Musicreater_ may be a little SLOW.** **Notice that the localizations of documents may NOT be up-to-date.**
## Introduction🚀 ## Introduction🚀
@ -41,21 +41,15 @@ Welcome to join our QQ group: [861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr
- Via pypi - Via pypi
```bash ```bash
pip install Musicreater pip install Musicreater --upgrade
``` ```
- If not work, also try: - If above command cannot fetch latest version, try:
```bash
pip install -i https://pypi.python.org/simple Musicreater
```
- Update:
```bash ```bash
pip install -i https://pypi.python.org/simple Musicreater --upgrade pip install -i https://pypi.python.org/simple Musicreater --upgrade
``` ```
- Clone repo and Install: - Clone repo and Install (**NOT RECOMMANDED**):
```bash ```bash
git clone https://github.com/TriM-Organization/Musicreater.git git clone https://github.com/TriM-Organization/Musicreater.git
cd Musicreater cd Musicreater
@ -94,10 +88,12 @@ This list is not in any order.
- Thank _[神羽](https://gitee.com/snowykami) [SnowyKami](https://github.com/snowyfirefly)_ for supporting and promoting our project, and also thanks him for his server which given us to use for free. - Thank _[神羽](https://gitee.com/snowykami) [SnowyKami](https://github.com/snowyfirefly)_ for supporting and promoting our project, and also thanks him for his server which given us to use for free.
- Thank **指令师\_苦力怕 playjuice123**\<QQ240667197\> for finding bugs within our code, and noticed us to repair a big problem. - Thank **指令师\_苦力怕 playjuice123**\<QQ240667197\> for finding bugs within our code, and noticed us to repair a big problem.
- Thank **雷霆**\<QQ3555268519\> for his annoying and provoking operations which may awake some problems within the program by chance and reminding us to repair. - Thank **雷霆**\<QQ3555268519\> for his annoying and provoking operations which may awake some problems within the program by chance and reminding us to repair.
- Thank **小埋**\<QQ2039310975\> for reporting the empty add-on packs title and description problem.
- <table><tr><td>Thank **油炸**\<QQ2836146704\> for inspiring us to constantly develop something new.</td><td><img width="260" src="https://foruda.gitee.com/images/1695478907647543027/08ea9909_9911226.jpeg" alt="The groupmate on the picture was saying that our convert-QQ-bot had once brought him great convinience but now it closed down by some reason so he was feeling regretful." title="&quot;It was once, a convert-QQ-bot is just in front my eyes&quot;&#10;&quot;Until lose, I finally know cannot chase back what I needs&quot;"></td><td><small>&quot;It was once, a convert-QQ-bot is just in front my eyes&quot;<br>&quot;Until lose, I finally know cannot chase back what I needs&quot;</small></td></tr></table>
> Thanks for a lot of groupmates' support and help > Thanks for the support and help of a lot of groupmates
> >
> If you have given contribution but haven't been in the list, please contact us! > If you have given contributions but have not been in the list, please contact us!
## Contact Us 📞 ## Contact Us 📞
@ -105,6 +101,8 @@ Meet problems? Welcome to give out your issue [here](https://github.com/EillesWa
Want to get in contact of developers? Welcome to join our [Chat QQ group](https://jq.qq.com/?_wv=1027&k=hpeRxrYr). Want to get in contact of developers? Welcome to join our [Chat QQ group](https://jq.qq.com/?_wv=1027&k=hpeRxrYr).
Or contact us via [TriM-Org Official Email](mailto:TriM-Organization@hotmail.com)!
--- ---
NOT AN OFFICIAL MINECRAFT PRODUCT. NOT AN OFFICIAL MINECRAFT PRODUCT.

View File

@ -1,12 +1,10 @@
<h1 align="center">· Musicreater</h1> <h1 align="center">· Musicreater</h1>
<h2 align="center">库版 Package Version</h2>
<p align="center"> <p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" > <img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p> </p>
**此为开发相关文档内容包括所生成文件结构的详细说明特殊参数的详细解释** **此为开发相关文档内容包括库的调用所生成文件结构的详细说明特殊参数的详细解释**
# 库的简单调用 # 库的简单调用
@ -101,13 +99,15 @@
在上面的代码中进度条样式是可以自定义的详见[下方说明](%E5%BA%93%E7%9A%84%E7%94%9F%E6%88%90%E4%B8%8E%E5%8A%9F%E8%83%BD%E6%96%87%E6%A1%A3.md#进度条自定义)。 在上面的代码中进度条样式是可以自定义的详见[下方说明](%E5%BA%93%E7%9A%84%E7%94%9F%E6%88%90%E4%B8%8E%E5%8A%9F%E8%83%BD%E6%96%87%E6%A1%A3.md#进度条自定义)。
- 转换成指令是一个方面接下来是再转换为可以导入MC的格式我们提供了 · 内置的附加组件可以借助 `MidiConvert` 对象转换为相应格式 - 转换成指令是一个方面接下来是再转换为可以导入MC的格式我们提供了 **·** 内置的附加组件可以借助 `MidiConvert` 对象转换为相应格式
```python ```python
# 导入 Musicreater # 导入 Musicreater
import Musicreater import Musicreater
# 导入附加组件功能 # 导入附加组件功能
import Musicreater.plugin import Musicreater.plugin
# 导入相应的文件格式转换功能 # 导入相应的文件格式转换功能
# 转换为函数附加包 # 转换为函数附加包
@ -122,7 +122,6 @@
import Musicreater.plugin.websocket import Musicreater.plugin.websocket
# 定义转换参数 # 定义转换参数
cvt_cfg = Musicreater.plugin.ConvertConfig( cvt_cfg = Musicreater.plugin.ConvertConfig(
output_path, output_path,
@ -131,9 +130,17 @@
progressbar, # 进度条样式组(详见下方) progressbar, # 进度条样式组(详见下方)
) )
# 使用附加组件转换,其调用的函数应为:
# 懒得写了,等哪天有空写吧,后面的没用,是老的。 # Musicreater.plugin.输出格式.播放器格式
# 值得注意的是,并非所有输出格式都支持所有播放器格式
# 调用的时候还请注意甄别
# 例如,以下函数是将 MidiConvert 对象 cvt_mid
# 以 cvt_cfg 指定的参数
# 以延迟播放器转换为 mcstructure 文件
Musicreater.plugin.mcstructfile.to_mcstructure_file_in_delay(
cvt_mid,
cvt_cfg,
)
``` ```
@ -147,49 +154,29 @@
|指令链|与链式指令方块不同一个指令链通常指代的是一串由某种非链式指令方块作为开头后面连着一串链式指令方块的结构|通常的链都应用于需要单次激活而多指令的简单功能| |指令链|与链式指令方块不同一个指令链通常指代的是一串由某种非链式指令方块作为开头后面连着一串链式指令方块的结构|通常的链都应用于需要单次激活而多指令的简单功能|
|起始块|链最初的那个非链式指令方块|此方块为脉冲方块或重复方块皆可| |起始块|链最初的那个非链式指令方块|此方块为脉冲方块或重复方块皆可|
|指令系统系统|指令系统通常指的是由一个或多个指令链以及相关红石机构相互配合一同组成的为达到某种特定的功能而构建的整体结构|通常的系统都应用于需要综合调配指令的复杂功能可由多个实现不同功能的模块构成不同系统之间可以相互调用各自的模块| |指令系统系统|指令系统通常指的是由一个或多个指令链以及相关红石机构相互配合一同组成的为达到某种特定的功能而构建的整体结构|通常的系统都应用于需要综合调配指令的复杂功能可由多个实现不同功能的模块构成不同系统之间可以相互调用各自的模块|
|游戏刻|游戏的一刻是指我的世界的游戏循环运行一次所占用的时间[详见我的世界中文维基](https://minecraft.fandom.com/zh/wiki/%E5%88%BB#%E6%B8%B8%E6%88%8F%E5%88%BB))。指令方块的延迟功能(即指令方块的“延迟刻数”设置项,此项的名称被误译为“已选中项的延迟”)的单位即为`1`游戏刻。|正常情况下游戏固定以每秒钟20刻的速率运行。但是由于游戏内的绝大多数操作都是基于刻数而非现实中的时间来计时并进行的一次游戏循环内也许会发生大量的操作很多情况下一秒对应的游戏刻会更少。 | |游戏刻|游戏的一刻是指我的世界的游戏进程循环运行一次所占用的时间[详见我的世界中文维基](https://minecraft.fandom.com/zh/wiki/%E5%88%BB#%E6%B8%B8%E6%88%8F%E5%88%BB))。指令方块的延迟功能(即指令方块的“延迟刻数”设置项,此项的名称被误译为“已选中项的延迟”)的单位即为`1`游戏刻。|正常情况下,游戏固定以每秒钟 $20$ 刻的速率运行。但是,由于游戏内的绝大多数操作都是基于游戏进程循环而非现实中的时间来计时并进行的,一次游戏循环内也许会发生大量的操作,更多情况下,一秒对应的游戏刻会更少。|
|红石刻|一个红石刻代表了两个游戏刻[详见我的世界中文维基](https://minecraft.fandom.com/zh/wiki/%E5%88%BB#%E7%BA%A2%E7%9F%B3%E5%88%BB))。红石中继器会带来 $1$~$4$ 个红石刻的延迟,其默认的延迟时间为 $1$ 红石刻。|正常情况下,红石信号在一个红石电路中传输回存在 $\frac{1}{10}$ 秒左右的延迟。但是,同理于游戏刻,一秒对应的红石刻是不定的。|
## 文件格式
1. 附加包格式`.mcpack`
使用附加包格式导出音乐则音乐会以指令函数文件`.mcfunction`存储于附加包内在附加包中函数文件的存储结构应为
- `functions\`
- `index.mcfunction`
- `mscply\`
- `progressShow.mcfunction`
- `track1.mcfunction`
- `track2.mcfunction`
- ...
- `trackN.mcfunction`
如图其中`index.mcfunction`文件和`mscply`文件夹存在于函数目录的根下`mscply`目录中包含音乐导出的众多音轨播放文件`trackX.mcfunction`同时若生成此包时选择了带有进度条的选项则会包含`progressShow.mcfunction`文件
`index.mcfunction`用于开始播放其中包含打开各个音轨对应函数的指令以及加分指令这里的加分是将**播放计分板的值大于等于`1`**的所有**玩家**的播放计分板分数增加`1`同时若生成此包时选择了自动重置计分板的选项则会包含一条重置计分板的指令
> 你知道吗·创的最早期版本我的世界函数音乐生成器正是用函数来播放不过这个版本采取的读入数据的形式大有不同
2. 结构格式
无论是音·创生成的是何种结构`MCSTRUCTURE`还是`BDX`都会依照此处的格式来生成此处我们想说明的结构的格式不是结构文件存储的格式而是结构导出之后方块将如何摆放的问题结构文件存储的格式这一点在各个我的世界开发的相关网站上都可能会有说明
考虑到进行我的世界游戏开发时为了节约常加载区域很多游戏会将指令区设立为一种层叠式的结构这种结构会限制每一层的指令系统的高度但是虽然长宽也是有限的却仍然比其纵轴延伸得更加自由
所以结构的生成形状依照给定的高度和内含指令的数量决定 $Z$ 轴延伸长度为指令方块数量对于给定高度之商的向下取整结果的平方根的向下取整用数学公式的方式表达则是
$$ MaxZ = \left\lfloor\sqrt{\left\lfloor{\frac{NoC}{MaxH}}\right\rfloor}\right\rfloor $$
其中$MaxZ$ 即生成结构的$Z$轴最大延伸长度$NoC$ 表示链结构中所含指令方块的个数$MaxH$ 表示给定的生成结构的最大高度
我们的结构生成器在生成指令链时将首先以相对坐标系 $(0, 0, 0)$ 即相对原点开始自下向上堆叠高度轴 $Y$ 的长当高度轴达到了限制的高度时便将 $Z$ 轴向正方向堆叠`1`个方块并开始自上向下重新堆叠直至高度轴坐标达到相对为 `0`若当所生成结构的 $Z$ 轴长达到了其最大延伸长度则此结构生成器将反转 $Z$ 轴的堆叠方向直至 $Z$ 轴坐标相对为 `0`如此往复直至指令链堆叠完成
## 播放器 ## 播放器
以结构生成的文件可以采用多种方式播放一类播放方式我们称其为**播放器**例如**延迟播放器****计分板播放器**等等以后推出的新的播放器届时也会在此处更新 **·**生成的文件可以采用多种方式播放一类播放方式我们称其为**播放器**例如**延迟播放器****计分板播放器**等等以后推出的新的播放器届时也会在此处更新
为什么要设计这么多播放器是为了适应不同的播放环境需要通常情况下一个音乐中含有多个音符音符与音符之间存在间隔这里就产生了不一样的实现音符间时间间隔的方式而不同的应用环境下又会产生不一样的要求接下来将对不同的播放器进行详细介绍 为什么要设计这么多播放器是为了适应不同的播放环境需要通常情况下一个音乐中含有多个音符音符与音符之间存在间隔这里就产生了不一样的实现音符间时间间隔的方式而不同的应用环境下又会产生不一样的要求接下来将对不同的播放器进行详细介绍
### 参数释义
|参数|说明|备注|
|--------|-----------|----------|
|`ScBd`|指定的计分板名称||
|`Tg`|播放对象|选择器或玩家名|
|`x`|音发出时对应的分数值||
|`InstID`|声音效果ID|不同的声音ID可以对应不同的乐器详见转换[乐器对照表](./%E8%BD%AC%E6%8D%A2%E4%B9%90%E5%99%A8%E5%AF%B9%E7%85%A7%E8%A1%A8.md)|
|`Ht`|播放点对玩家的距离|通过距离来表达声音的响度 $S$ 表示此参数`Ht`以Vol表示音量百分比则计算公式为 $S = \frac{1}{Vol}-1$ |
|`Vlct`|原生我的世界中规定的播放力度|这个参数是一个谜一样的存在似乎它的值毫不重要因为无论这个值是多少我们听起来都差不多当此音符所在MIDI通道为第一通道则这个值为 $0.7$ 倍MIDI指定力度其他则为 $0.9$ |
|`Ptc`|音符的音高|这是决定音调的参数 $P$ 表示此参数 $n$ 表示其在MIDI中的编号 $x$ 表示一定的音调偏移则计算公式为 $P = 2^\frac{n-60-x}{12}$之所以存在音调偏移是因为在我的世界不同的[乐器存在不同的音域](https://minecraft.fandom.com/zh/wiki/%E9%9F%B3%E7%AC%A6%E7%9B%92#%E4%B9%90%E5%99%A8),我们通过音调偏移来进行调整。|
### 播放器内容
1. 计分板播放器 1. 计分板播放器
计分板播放器是一种传统的我的世界音乐播放方式通过对于计分板加分来实现播放不同的音符一个很简单的原理就是**用不同的计分板分值对应不同的音符**再通过加分来达到那个分值即播放出来 计分板播放器是一种传统的我的世界音乐播放方式通过对于计分板加分来实现播放不同的音符一个很简单的原理就是**用不同的计分板分值对应不同的音符**再通过加分来达到那个分值即播放出来
@ -200,14 +187,7 @@
execute @a[scores={ScBd=x}] ~ ~ ~ playsound InstID @s ^ ^ ^Ht Vlct Ptc execute @a[scores={ScBd=x}] ~ ~ ~ playsound InstID @s ^ ^ ^Ht Vlct Ptc
``` ```
|参数|说明|备注|
|--------|-----------|----------|
|`ScBd`|指定的计分板名称||
|`x`|音发出时对应的分数值||
|`InstID`|声音效果ID|不同的声音ID可以对应不同的乐器详见转换[乐器对照表](./%E8%BD%AC%E6%8D%A2%E4%B9%90%E5%99%A8%E5%AF%B9%E7%85%A7%E8%A1%A8.md)|
|`Ht`|播放点对玩家的距离|通过距离来表达声音的响度 $S$ 表示此参数`Ht`以Vol表示音量百分比则计算公式为 $S = \frac{1}{Vol}-1$ |
|`Vlct`|原生我的世界中规定的播放力度|这个参数是一个谜一样的存在似乎它的值毫不重要因为无论这个值是多少我们听起来都差不多当此音符所在MIDI通道为第一通道则这个值为0.7倍MIDI指定力度其他则为0.9|
|`Ptc`|音符的音高|这是决定音调的参数 $P$ 表示此参数 $n$ 表示其在MIDI中的编号 $x$ 表示一定的音域偏移则计算公式为 $P = 2^\frac{n-60-x}{12}$ |
后四个参数决定了这个音的性质而前两个参数仅仅是为了决定音播放的时间 后四个参数决定了这个音的性质而前两个参数仅仅是为了决定音播放的时间
@ -215,32 +195,78 @@
延迟播放器是通过我的世界游戏中指令方块的设置项延迟刻数来达到定位音符的效果**将所有的音符依照其播放时距离乐曲开始时的时间毫秒放在一个序列内再计算音符两两之间对应的时间差值转换为我的世界内对应的游戏刻数之后填入指令方块的设置中** 延迟播放器是通过我的世界游戏中指令方块的设置项延迟刻数来达到定位音符的效果**将所有的音符依照其播放时距离乐曲开始时的时间毫秒放在一个序列内再计算音符两两之间对应的时间差值转换为我的世界内对应的游戏刻数之后填入指令方块的设置中**
·由于此方式播放的音乐不需要用计分板所以播放指令是这样的 **·**由于此方式播放的音乐不需要用计分板所以播放指令是这样的
```mcfunction ```mcfunction
execute Tg ~ ~ ~ playsound InstID @s ^ ^ ^Ht Vlct Ptc execute Tg ~ ~ ~ playsound InstID @s ^ ^ ^Ht Vlct Ptc
``` ```
|参数|说明|备注|
|--------|-----------|----------|
|`Tg`|播放对象|选择器或玩家名|
|`InstID`|声音效果ID|不同的声音ID可以对应不同的乐器详见转换[乐器对照表](./%E8%BD%AC%E6%8D%A2%E4%B9%90%E5%99%A8%E5%AF%B9%E7%85%A7%E8%A1%A8.md)|
|`Ht`|播放点对玩家的距离|通过距离来表达声音的响度 $S$ 表示此参数`Ht`以Vol表示音量百分比则计算公式为 $S = \frac{1}{Vol}-1$ |
|`Vlct`|原生我的世界中规定的播放力度|这个参数是一个谜一样的存在似乎它的值毫不重要因为无论这个值是多少我们听起来都差不多当此音符所在MIDI通道为第一通道则这个值为0.7倍MIDI指定力度其他则为0.9|
|`Ptc`|音符的音高|这是决定音调的参数 $P$ 表示此参数 $n$ 表示其在MIDI中的编号$x$表示一定的音域偏移则计算公式为 $P = 2^\frac{n-60-x}{12}$ |
其中后四个参数决定了这个音的性质 其中后四个参数决定了这个音的性质
由于这样的延迟数据是依赖于指令方块的设置项所以使用这种播放器所转换出的结果仅可以存储在包含方块NBT信息及方块实体NBT信息的结构文件中或者直接输出至世界 由于这样的延迟数据是依赖于指令方块的设置项所以使用这种播放器所转换出的结果仅可以存储在包含方块NBT信息及方块实体NBT信息的结构文件中或者直接输出至世界
3. 中继器播放器
中继器播放器是一种传统的我的世界红石音乐播放方式利用游戏内红石组件红石中继器以达到定位音符之用**但是中继器的延迟为1红石刻**
## 文件格式
1. 附加包格式`.mcpack`
使用附加包格式导出音乐若采用计分板 播放器则音乐会以指令函数文件`.mcfunction`存储于附加包内而若为延迟或中继器播放器则音乐回以结构文件`.mcstructure`存储在所生成的附加包中函数文件的存储结构应为
- `functions\`
- `index.mcfunction`
- `stop.mcfunction`
- `mscply\`
- `progressShow.mcfunction`
- `track1.mcfunction`
- `track2.mcfunction`
- ...
- `trackN.mcfunction`
- `structures\`
- `XXX_main.mcstructure`
- `XXX_start.mcstructure`
- `XXX_reset.mcstructure`
- `XXX_pgb.mcstructure`
如图其中`index.mcfunction`文件`stop.mcfunction`文件和`mscply`文件夹存在于函数目录的根下`mscply`目录中包含音乐导出的众多音轨播放文件`trackX.mcfunction`同时若使用计分板播放器生成此包时启用生成进度条则会包含`progressShow.mcfunction`文件若选择延迟或中继器播放器则会生成`structures`目录以及相关`.mcstructure`文件其中`mian`表示音乐播放用的主要结构`start`是用于初始化播放的部分仅包含一个指令方块即起始块`reset``pgb`仅在启用生成进度条时出现前者用于重置临时计分板后者用于显示进度条
`index.mcfunction`用于开始播放
1. 若为计分板播放器则其中包含打开各个音轨对应函数的指令以及加分指令这里的加分是将**播放计分板的值大于等于 $1$ 的所有玩家**的播放计分板分数增加 $1$同时若生成此包时选择了自动重置计分板的选项则会包含一条重置计分板的指令
2. 若为延迟或中继器播放器则其中的指令仅包含用以正确加载结构的`structure`指令
`stop.mcfunction`用于终止播放
1. 若为计分板播放器则其中包含将**全体玩家的播放计分板**重置的指令
2. 若为延迟或中继器播放器则其中包含**停用命令方块****启用命令方块**的指令~~然鹅实际上对于播放而言是一点用也没有~~
> 你知道吗·创的最早期版本我的世界函数音乐生成器正是用函数来播放不过这个版本采取的读入数据的形式大有不同
2. 生成结构的方式
无论是音·创生成的是何种结构`MCSTRUCTURE`还是`BDX`都会依照此处的格式来生成此处我们想说明的结构的格式不是结构文件存储的格式而是结构导出之后方块摆放的方式结构文件存储的格式这一点在各个我的世界开发的相关网站上都可能会有说明
考虑到进行我的世界游戏开发时为了节约常加载区域很多游戏会将指令区设立为一种层叠式的结构这种结构会限制每一层的指令系统的高度但是虽然长宽也是有限的却仍然比其纵轴延伸得更加自由
所以结构的生成形状依照给定的高度和内含指令的数量决定 $Z$ 轴延伸长度为指令方块数量对于给定高度之商的向下取整结果的平方根的向下取整用数学公式的方式表达则是
$$ MaxZ = \left\lfloor\sqrt{\left\lfloor{\frac{NoC}{MaxH}}\right\rfloor}\right\rfloor $$
其中$MaxZ$ 即生成结构的$Z$轴最大延伸长度$NoC$ 表示链结构中所含指令方块的个数$MaxH$ 表示给定的生成结构的最大高度
我们的结构生成器在生成指令链时将首先以相对坐标系 $(0, 0, 0)$ 即相对原点开始自下向上堆叠高度轴 $Y$ 的长当高度轴达到了限制的高度时便将 $Z$ 轴向正方向堆叠 $1$ 个方块并开始自上向下重新堆叠直至高度轴坐标达到相对为 $0$若当所生成结构的 $Z$ 轴长达到了其最大延伸长度则此结构生成器将反转 $Z$ 轴的堆叠方向直至 $Z$ 轴坐标相对为 $0$如此往复直至指令链堆叠完成
# 进度条自定义 # 进度条自定义
因为我们提供了可以自动转换进度条的功能因此在这里给出进度条自定义参数的详细解释 因为我们提供了可以自动转换进度条的功能因此在这里给出进度条自定义参数的详细解释
请注意并非所有的演示样例程序都支持自定义进度条
一个进度条明显地**固定部分****可变部分**来构成而可变部分又包括了文字和图形两种当然我的世界里头的进度条可变的图形也就是那个这一点你需要了解因为后文中包含了很多这方面的概念需要你了解 一个进度条明显地**固定部分****可变部分**来构成而可变部分又包括了文字和图形两种当然我的世界里头的进度条可变的图形也就是那个这一点你需要了解因为后文中包含了很多这方面的概念需要你了解
进度条的自定义功能使用一个字符串来定义自己的样式其中包含众多**标识符**来表示可变部分 进度条的自定义功能使用一个字符串来定义自己的样式其中包含众多**标识符**来表示可变部分

View File

@ -1,16 +1,12 @@
<h1 align="center">· Musicreater</h1> <h1 align="center">· Musicreater</h1>
<h2 align="center">库版 Package Version</h2>
<p align="center"> <p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" > <img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p> </p>
# 生成文件的使用 # 生成文件的使用
*由于先前的 **读我文件**(README.md) 过于冗杂现另辟蹊径来给大家全方位的教程* *这是本库所生成文件的使用声明不是使用本库的教程若要查看**本库的文档**可点击[此处](./%E5%BA%93%E7%9A%84%E7%94%9F%E6%88%90%E4%B8%8E%E5%8A%9F%E8%83%BD%E6%96%87%E6%A1%A3.md)若要查看有关文件结构的内容可以点击[此处](./%E7%94%9F%E6%88%90%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E8%AF%B4%E6%98%8E.md)*
*这是本库所生成文件的使用声明不是使用本库的教程若要查看**本库的大致文档**可点击[此处](./%E5%BA%93%E7%9A%84%E7%94%9F%E6%88%90%E4%B8%8E%E5%8A%9F%E8%83%BD%E6%96%87%E6%A1%A3.md)若要查看有关文件结构的内容可以点击[此处](./%E7%94%9F%E6%88%90%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E8%AF%B4%E6%98%8E.md)*
## 附加包格式 ## 附加包格式
@ -24,6 +20,7 @@
4. 激活循环方块 4. 激活循环方块
5. 若想要暂停播放可以停止循环指令方块的激活状态 5. 若想要暂停播放可以停止循环指令方块的激活状态
6. 若想要重置某实体的播放可以将其播放用的计分板重置 6. 若想要重置某实体的播放可以将其播放用的计分板重置
7. 若要终止全部玩家的播放在聊天框输入指令 `function stop`
> 其中 步骤三 步骤四 的顺序可以调换 > 其中 步骤三 步骤四 的顺序可以调换
@ -32,6 +29,7 @@
1. 导入附加包 1. 导入附加包
2. 在聊天框输入指令 `function index` 2. 在聊天框输入指令 `function index`
3. 同时激活所生成的循环和脉冲指令方块 3. 同时激活所生成的循环和脉冲指令方块
4. 若要终止播放在聊天框输入指令 `function stop` 试试看不确保有用
> 需要注意的是循环指令方块需要一直激活直到音乐结束 > 需要注意的是循环指令方块需要一直激活直到音乐结束

View File

@ -1,6 +1,14 @@
<h1 align="center">· Musicreater</h1>
<p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p>
# 转换乐器对照表
**_注意本文档中的对照表版权归属于音·创作者并按照本仓库根目录下 LICENSE.md 中规定开源_** **_注意本文档中的对照表版权归属于音·创作者并按照本仓库根目录下 LICENSE.md 中规定开源_**
**_使用时请遵循规定_** **_使用时请遵循协议规定_**
- 版权所有 © 2023 · 开发者 - 版权所有 © 2023 · 开发者
- Copyright © 2023 all the developers of Musicreater - Copyright © 2023 all the developers of Musicreater
@ -12,187 +20,196 @@
Email TriM-Organization@hotmail.com\ Email TriM-Organization@hotmail.com\
若需转载或借鉴 许可声明请查看仓库根目录下的 License.md 若需转载或借鉴 许可声明请查看仓库根目录下的 License.md
### 名词解释
| 名词 | 说明 |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| 音符名称 | 我的世界游戏内用于播放音乐的 `playsound` 指令所规定的 `Sound ID` |
| 音调偏移参数 | 我的世界不同乐器的音域不同对应的 `pitch` 值也不尽相同该参数的解释请参考[文档说明](库的生成与功能文档.md#参数释义) |
# 乐音乐器 # 乐音乐器
| Midi 乐器值 | 我的世界音符名称 | 我的世界音调偏移参数 | 对照表版本2023 0527
| ----------- | ------------------- | -------------------- |
| 0 | note.harp | 6 | | Midi 乐器值 | 音符名称 | 音调偏移参数 |
| 1 | note.harp | 6 | | ----------- | ------------------- | ------------ |
| 2 | note.pling | 6 | | 0 | note.harp | 6 |
| 3 | note.harp | 6 | | 1 | note.harp | 6 |
| 4 | note.pling | 6 | | 2 | note.pling | 6 |
| 5 | note.pling | 6 | | 3 | note.harp | 6 |
| 6 | note.harp | 6 | | 4 | note.pling | 6 |
| 7 | note.harp | 6 | | 5 | note.pling | 6 |
| 8 | note.share | 7 | | 6 | note.harp | 6 |
| 9 | note.harp | 6 | | 7 | note.harp | 6 |
| 10 | note.didgeridoo | 8 | | 8 | note.share | 7 |
| 11 | note.harp | 6 | | 9 | note.harp | 6 |
| 12 | note.xylophone | 4 | | 10 | note.didgeridoo | 8 |
| 13 | note.chime | 4 | | 11 | note.harp | 6 |
| 14 | note.harp | 6 | | 12 | note.xylophone | 4 |
| 15 | note.harp | 6 | | 13 | note.chime | 4 |
| 16 | note.bass | 8 | | 14 | note.harp | 6 |
| 17 | note.harp | 6 | | 15 | note.harp | 6 |
| 18 | note.harp | 6 | | 16 | note.bass | 8 |
| 19 | note.harp | 6 | | 17 | note.harp | 6 |
| 20 | note.harp | 6 | | 18 | note.harp | 6 |
| 21 | note.harp | 6 | | 19 | note.harp | 6 |
| 22 | note.harp | 6 | | 20 | note.harp | 6 |
| 23 | note.guitar | 7 | | 21 | note.harp | 6 |
| 24 | note.guitar | 7 | | 22 | note.harp | 6 |
| 25 | note.guitar | 7 | | 23 | note.guitar | 7 |
| 26 | note.guitar | 7 | | 24 | note.guitar | 7 |
| 27 | note.guitar | 7 | | 25 | note.guitar | 7 |
| 28 | note.guitar | 7 | | 26 | note.guitar | 7 |
| 29 | note.guitar | 7 | | 27 | note.guitar | 7 |
| 30 | note.guitar | 7 | | 28 | note.guitar | 7 |
| 31 | note.bass | 8 | | 29 | note.guitar | 7 |
| 32 | note.bass | 8 | | 30 | note.guitar | 7 |
| 33 | note.bass | 8 | | 31 | note.bass | 8 |
| 34 | note.bass | 8 | | 32 | note.bass | 8 |
| 35 | note.bass | 8 | | 33 | note.bass | 8 |
| 36 | note.bass | 8 | | 34 | note.bass | 8 |
| 37 | note.bass | 8 | | 35 | note.bass | 8 |
| 38 | note.bass | 8 | | 36 | note.bass | 8 |
| 39 | note.bass | 8 | | 37 | note.bass | 8 |
| 40 | note.harp | 6 | | 38 | note.bass | 8 |
| 41 | note.harp | 6 | | 39 | note.bass | 8 |
| 42 | note.harp | 6 | | 40 | note.harp | 6 |
| 43 | note.harp | 6 | | 41 | note.harp | 6 |
| 44 | note.iron_xylophone | 6 | | 42 | note.harp | 6 |
| 45 | note.guitar | 7 | | 43 | note.harp | 6 |
| 46 | note.harp | 6 | | 44 | note.iron_xylophone | 6 |
| 47 | note.harp | 6 | | 45 | note.guitar | 7 |
| 48 | note.guitar | 7 | | 46 | note.harp | 6 |
| 49 | note.guitar | 7 | | 47 | note.harp | 6 |
| 50 | note.bit | 6 | | 48 | note.guitar | 7 |
| 51 | note.bit | 6 | | 49 | note.guitar | 7 |
| 52 | note.harp | 6 | | 50 | note.bit | 6 |
| 53 | note.harp | 6 | | 51 | note.bit | 6 |
| 54 | note.bit | 6 | | 52 | note.harp | 6 |
| 55 | note.flute | 5 | | 53 | note.harp | 6 |
| 56 | note.flute | 5 | | 54 | note.bit | 6 |
| 57 | note.flute | 5 | | 55 | note.flute | 5 |
| 58 | note.flute | 5 | | 56 | note.flute | 5 |
| 59 | note.flute | 5 | | 57 | note.flute | 5 |
| 60 | note.flute | 5 | | 58 | note.flute | 5 |
| 61 | note.flute | 5 | | 59 | note.flute | 5 |
| 62 | note.flute | 5 | | 60 | note.flute | 5 |
| 63 | note.flute | 5 | | 61 | note.flute | 5 |
| 64 | note.bit | 6 | | 62 | note.flute | 5 |
| 65 | note.bit | 6 | | 63 | note.flute | 5 |
| 66 | note.bit | 6 | | 64 | note.bit | 6 |
| 67 | note.bit | 6 | | 65 | note.bit | 6 |
| 68 | note.flute | 5 | | 66 | note.bit | 6 |
| 69 | note.harp | 6 | | 67 | note.bit | 6 |
| 70 | note.harp | 6 | | 68 | note.flute | 5 |
| 71 | note.flute | 5 | | 69 | note.harp | 6 |
| 72 | note.flute | 5 | | 70 | note.harp | 6 |
| 73 | note.flute | 5 | | 71 | note.flute | 5 |
| 74 | note.harp | 6 | | 72 | note.flute | 5 |
| 75 | note.flute | 5 | | 73 | note.flute | 5 |
| 76 | note.harp | 6 | | 74 | note.harp | 6 |
| 77 | note.harp | 6 | | 75 | note.flute | 5 |
| 78 | note.harp | 6 | | 76 | note.harp | 6 |
| 79 | note.harp | 6 | | 77 | note.harp | 6 |
| 80 | note.bit | 6 | | 78 | note.harp | 6 |
| 81 | note.bit | 6 | | 79 | note.harp | 6 |
| 82 | note.bit | 6 | | 80 | note.bit | 6 |
| 83 | note.bit | 6 | | 81 | note.bit | 6 |
| 84 | note.bit | 6 | | 82 | note.bit | 6 |
| 85 | note.bit | 6 | | 83 | note.bit | 6 |
| 86 | note.bit | 6 | | 84 | note.bit | 6 |
| 87 | note.bit | 6 | | 85 | note.bit | 6 |
| 88 | note.bit | 6 | | 86 | note.bit | 6 |
| 89 | note.bit | 6 | | 87 | note.bit | 6 |
| 90 | note.bit | 6 | | 88 | note.bit | 6 |
| 91 | note.bit | 6 | | 89 | note.bit | 6 |
| 92 | note.bit | 6 | | 90 | note.bit | 6 |
| 93 | note.bit | 6 | | 91 | note.bit | 6 |
| 94 | note.bit | 6 | | 92 | note.bit | 6 |
| 95 | note.bit | 6 | | 93 | note.bit | 6 |
| 96 | note.bit | 6 | | 94 | note.bit | 6 |
| 97 | note.bit | 6 | | 95 | note.bit | 6 |
| 98 | note.bit | 6 | | 96 | note.bit | 6 |
| 99 | note.bit | 6 | | 97 | note.bit | 6 |
| 100 | note.bit | 6 | | 98 | note.bit | 6 |
| 101 | note.bit | 6 | | 99 | note.bit | 6 |
| 102 | note.bit | 6 | | 100 | note.bit | 6 |
| 103 | note.bit | 6 | | 101 | note.bit | 6 |
| 104 | note.harp | 6 | | 102 | note.bit | 6 |
| 105 | note.banjo | 6 | | 103 | note.bit | 6 |
| 106 | note.harp | 6 | | 104 | note.harp | 6 |
| 107 | note.harp | 6 | | 105 | note.banjo | 6 |
| 108 | note.harp | 6 | | 106 | note.harp | 6 |
| 109 | note.harp | 6 | | 107 | note.harp | 6 |
| 110 | note.harp | 6 | | 108 | note.harp | 6 |
| 111 | note.guitar | 7 | | 109 | note.harp | 6 |
| 112 | note.harp | 6 | | 110 | note.harp | 6 |
| 113 | note.bell | 4 | | 111 | note.guitar | 7 |
| 114 | note.harp | 6 | | 112 | note.harp | 6 |
| 115 | note.cow_bell | 5 | | 113 | note.bell | 4 |
| 116 | note.bd | 7 | | 114 | note.harp | 6 |
| 117 | note.bass | 8 | | 115 | note.cow_bell | 5 |
| 118 | note.bit | 6 | | 116 | note.bd | 7 |
| 119 | note.bd | 7 | | 117 | note.bass | 8 |
| 120 | note.guitar | 7 | | 118 | note.bit | 6 |
| 121 | note.harp | 6 | | 119 | note.bd | 7 |
| 122 | note.harp | 6 | | 120 | note.guitar | 7 |
| 123 | note.harp | 6 | | 121 | note.harp | 6 |
| 124 | note.harp | 6 | | 122 | note.harp | 6 |
| 125 | note.hat | 7 | | 123 | note.harp | 6 |
| 126 | note.bd | 7 | | 124 | note.harp | 6 |
| 127 | note.snare | 7 | | 125 | note.hat | 7 |
| 126 | note.bd | 7 |
| 127 | note.snare | 7 |
# 打击乐器 # 打击乐器
| Midi 打击乐器值 | 我的世界音符名称 | 我的世界音调偏移参数 | | Midi 打击乐器值 | 音符名称 | 音调偏移参数 |
| --------------- | ------------------- | -------------------- | | --------------- | ------------------- | ------------ |
| 34 | note.bd | 7 | | 34 | note.bd | 7 |
| 35 | note.bd | 7 | | 35 | note.bd | 7 |
| 36 | note.hat | 7 | | 36 | note.hat | 7 |
| 37 | note.snare | 7 | | 37 | note.snare | 7 |
| 38 | note.snare | 7 | | 38 | note.snare | 7 |
| 39 | note.snare | 7 | | 39 | note.snare | 7 |
| 40 | note.hat | 7 | | 40 | note.hat | 7 |
| 41 | note.snare | 7 | | 41 | note.snare | 7 |
| 42 | note.hat | 7 | | 42 | note.hat | 7 |
| 43 | note.snare | 7 | | 43 | note.snare | 7 |
| 44 | note.snare | 7 | | 44 | note.snare | 7 |
| 45 | note.bell | 4 | | 45 | note.bell | 4 |
| 46 | note.snare | 7 | | 46 | note.snare | 7 |
| 47 | note.snare | 7 | | 47 | note.snare | 7 |
| 48 | note.bell | 4 | | 48 | note.bell | 4 |
| 49 | note.hat | 7 | | 49 | note.hat | 7 |
| 50 | note.bell | 4 | | 50 | note.bell | 4 |
| 51 | note.bell | 4 | | 51 | note.bell | 4 |
| 52 | note.bell | 4 | | 52 | note.bell | 4 |
| 53 | note.bell | 4 | | 53 | note.bell | 4 |
| 54 | note.bell | 4 | | 54 | note.bell | 4 |
| 55 | note.bell | 4 | | 55 | note.bell | 4 |
| 56 | note.snare | 7 | | 56 | note.snare | 7 |
| 57 | note.hat | 7 | | 57 | note.hat | 7 |
| 58 | note.chime | 4 | | 58 | note.chime | 4 |
| 59 | note.iron_xylophone | 6 | | 59 | note.iron_xylophone | 6 |
| 60 | note.bd | 7 | | 60 | note.bd | 7 |
| 61 | note.bd | 7 | | 61 | note.bd | 7 |
| 62 | note.xylophone | 4 | | 62 | note.xylophone | 4 |
| 63 | note.xylophone | 4 | | 63 | note.xylophone | 4 |
| 64 | note.xylophone | 4 | | 64 | note.xylophone | 4 |
| 65 | note.hat | 7 | | 65 | note.hat | 7 |
| 66 | note.bell | 4 | | 66 | note.bell | 4 |
| 67 | note.bell | 4 | | 67 | note.bell | 4 |
| 68 | note.hat | 7 | | 68 | note.hat | 7 |
| 69 | note.hat | 7 | | 69 | note.hat | 7 |
| 70 | note.flute | 5 | | 70 | note.flute | 5 |
| 71 | note.flute | 5 | | 71 | note.flute | 5 |
| 72 | note.hat | 7 | | 72 | note.hat | 7 |
| 73 | note.hat | 7 | | 73 | note.hat | 7 |
| 74 | note.xylophone | 4 | | 74 | note.xylophone | 4 |
| 75 | note.hat | 7 | | 75 | note.hat | 7 |
| 76 | note.hat | 7 | | 76 | note.hat | 7 |
| 77 | note.xylophone | 4 | | 77 | note.xylophone | 4 |
| 78 | note.xylophone | 4 | | 78 | note.xylophone | 4 |
| 79 | note.bell | 4 | | 79 | note.bell | 4 |
| 80 | note.bell | 4 | | 80 | note.bell | 4 |

View File

@ -21,8 +21,11 @@ import os
import Musicreater import Musicreater
from Musicreater.plugin import ConvertConfig from Musicreater.plugin import ConvertConfig
from Musicreater.plugin.bdxfile import to_BDX_file_in_delay, to_BDX_file_in_score from Musicreater.plugin.bdxfile import to_BDX_file_in_delay, to_BDX_file_in_score
from Musicreater.plugin.funcpack import to_function_addon_in_score from Musicreater.plugin.addonpack import (
from Musicreater.plugin.mcstructpack import to_mcstructure_addon_in_delay, to_mcstructure_addon_in_redstone_cd to_addon_pack_in_delay,
to_addon_pack_in_repeater,
to_addon_pack_in_score,
)
# 获取midi列表 # 获取midi列表
midi_path = input(f"请输入MIDI路径") midi_path = input(f"请输入MIDI路径")
@ -107,18 +110,16 @@ cvt_mid = Musicreater.MidiConvert.from_midi_file(midi_path, old_exe_format=True)
cvt_cfg = ConvertConfig(out_path, *prompts[:3]) cvt_cfg = ConvertConfig(out_path, *prompts[:3])
if playerFormat == 1: if playerFormat == 1:
cvt_method = to_function_addon_in_score cvt_method = to_addon_pack_in_score
elif playerFormat == 0: elif playerFormat == 0:
cvt_method = to_mcstructure_addon_in_delay cvt_method = to_addon_pack_in_delay
elif playerFormat == 2: elif playerFormat == 2:
cvt_method = to_mcstructure_addon_in_redstone_cd cvt_method = to_addon_pack_in_repeater
print( print(
" 指令总长:{},最高延迟:{}".format( " 指令总长:{},最高延迟:{}".format(
*( *(cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore
cvt_method(cvt_mid, cvt_cfg, *prompts[3:]) # type: ignore
)
) )
if fileFormat == 0 if fileFormat == 0
else " 指令总长:{},最高延迟:{},结构大小{},终点坐标{}".format( else " 指令总长:{},最高延迟:{},结构大小{},终点坐标{}".format(

View File

@ -1,9 +1,9 @@
import Musicreater.experiment import Musicreater.experiment
import Musicreater.plugin import Musicreater.plugin
import Musicreater.plugin.mcstructpack import Musicreater.plugin.addonpack
print( print(
Musicreater.plugin.mcstructpack.to_mcstructure_addon_in_delay( Musicreater.plugin.addonpack.to_addon_pack_in_delay(
Musicreater.experiment.FutureMidiConvertM4.from_midi_file(input("midi路径:"), old_exe_format=False), Musicreater.experiment.FutureMidiConvertM4.from_midi_file(input("midi路径:"), old_exe_format=False),
Musicreater.plugin.ConvertConfig( Musicreater.plugin.ConvertConfig(
input("输出路径:"), input("输出路径:"),

View File

@ -5,9 +5,6 @@ import Musicreater.plugin.mcstructfile
print( print(
Musicreater.plugin.mcstructfile.to_mcstructure_file_in_delay( Musicreater.plugin.mcstructfile.to_mcstructure_file_in_delay(
Musicreater.MidiConvert.from_midi_file(input("midi路径:"), old_exe_format=False), Musicreater.MidiConvert.from_midi_file(input("midi路径:"), old_exe_format=False),
Musicreater.plugin.ConvertConfig( Musicreater.plugin.ConvertConfig(input("输出路径:"), volume=1),
input("输出路径:"),
volume=1
),
) )
) )

View File

@ -3,11 +3,8 @@ import Musicreater.plugin
import Musicreater.plugin.mcstructfile import Musicreater.plugin.mcstructfile
print( print(
Musicreater.plugin.mcstructfile.to_mcstructure_file_in_redstone_CD( Musicreater.plugin.mcstructfile.to_mcstructure_file_in_repeater(
Musicreater.MidiConvert.from_midi_file(input("midi路径:"), old_exe_format=False), Musicreater.MidiConvert.from_midi_file(input("midi路径:"), old_exe_format=False),
Musicreater.plugin.ConvertConfig( Musicreater.plugin.ConvertConfig(input("输出路径:"), volume=1),
input("输出路径:"),
volume=1
),
) )
) )

View File

@ -3,11 +3,10 @@ import Musicreater.plugin
import Musicreater.plugin.mcstructfile import Musicreater.plugin.mcstructfile
print( print(
Musicreater.plugin.mcstructfile.to_mcstructure_file_in_redstone_CD( Musicreater.plugin.mcstructfile.to_mcstructure_file_in_repeater(
Musicreater.experiment.FutureMidiConvertM4.from_midi_file(input("midi路径:"), old_exe_format=False), Musicreater.experiment.FutureMidiConvertM4.from_midi_file(
Musicreater.plugin.ConvertConfig( input("midi路径:"), old_exe_format=False
input("输出路径:"),
volume=1
), ),
Musicreater.plugin.ConvertConfig(input("输出路径:"), volume=1),
) )
) )