mirror of
https://github.com/TriM-Organization/Musicreater.git
synced 2025-01-31 07:23:17 +08:00
修复重大问题:延迟播放器中音符的延迟过长,感谢Mono
This commit is contained in:
parent
6fe8e41dfa
commit
cb95c51a47
5
.gitignore
vendored
5
.gitignore
vendored
@ -11,6 +11,11 @@
|
|||||||
*.bdx
|
*.bdx
|
||||||
*.json
|
*.json
|
||||||
*.mcstructure
|
*.mcstructure
|
||||||
|
/logs
|
||||||
|
/languages
|
||||||
|
/llc_cli.py
|
||||||
|
/utils
|
||||||
|
test.py
|
||||||
|
|
||||||
# Byte-compiled / optimized
|
# Byte-compiled / optimized
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
@ -19,6 +19,6 @@ Terms & Conditions: ../License.md
|
|||||||
|
|
||||||
from .main import *
|
from .main import *
|
||||||
|
|
||||||
__version__ = "0.5.0.2"
|
__version__ = "0.5.1"
|
||||||
__all__ = []
|
__all__ = []
|
||||||
__author__ = (("金羿", "Eilles Wan"), ("诸葛亮与八卦阵", "bgArray"), ("鸣凤鸽子", "MingFengPigeon"))
|
__author__ = (("金羿", "Eilles Wan"), ("诸葛亮与八卦阵", "bgArray"), ("鸣凤鸽子", "MingFengPigeon"))
|
||||||
|
@ -43,7 +43,7 @@ DEFAULT_PROGRESSBAR_STYLE = (
|
|||||||
|
|
||||||
class SingleNote:
|
class SingleNote:
|
||||||
def __init__(
|
def __init__(
|
||||||
self, instrument: int, pitch: int, velocity: int, startTime: int, lastTime: int
|
self, instrument: int, pitch: int, velocity: int, startTime: int, lastTime: int
|
||||||
):
|
):
|
||||||
"""用于存储单个音符的类
|
"""用于存储单个音符的类
|
||||||
:param instrument 乐器编号
|
:param instrument 乐器编号
|
||||||
@ -216,7 +216,7 @@ class midiConvert:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __Inst2soundID_withX(
|
def __Inst2soundID_withX(
|
||||||
instrumentID: int,
|
instrumentID: int,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
返回midi的乐器ID对应的我的世界乐器名,对于音域转换算法,如下:
|
返回midi的乐器ID对应的我的世界乐器名,对于音域转换算法,如下:
|
||||||
@ -260,7 +260,7 @@ class midiConvert:
|
|||||||
try:
|
try:
|
||||||
return percussion_instrument_list[instrumentID]
|
return percussion_instrument_list[instrumentID]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print("WARN", "无法使用打击乐器列表库,或者使用了不存在的乐器,打击乐器使用Dislink算法代替。{instrumentID}")
|
print("WARN", f"无法使用打击乐器列表库,或者使用了不存在的乐器,打击乐器使用Dislink算法代替。{instrumentID}")
|
||||||
if instrumentID == 55:
|
if instrumentID == 55:
|
||||||
return "note.cow_bell", 5
|
return "note.cow_bell", 5
|
||||||
elif instrumentID in [41, 43, 45]:
|
elif instrumentID in [41, 43, 45]:
|
||||||
@ -278,10 +278,10 @@ class midiConvert:
|
|||||||
return str(int(int(score / 20) / 60)) + ":" + str(int(int(score / 20) % 60))
|
return str(int(int(score / 20) / 60)) + ":" + str(int(int(score / 20) % 60))
|
||||||
|
|
||||||
def __form_progress_bar(
|
def __form_progress_bar(
|
||||||
self,
|
self,
|
||||||
max_score: int,
|
max_score: int,
|
||||||
scoreboard_name: str,
|
scoreboard_name: str,
|
||||||
progressbar_style: tuple = DEFAULT_PROGRESSBAR_STYLE,
|
progressbar_style: tuple = DEFAULT_PROGRESSBAR_STYLE,
|
||||||
) -> list:
|
) -> list:
|
||||||
"""
|
"""
|
||||||
生成进度条
|
生成进度条
|
||||||
@ -466,10 +466,10 @@ class midiConvert:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def _toCmdList_m1(
|
def _toCmdList_m1(
|
||||||
self,
|
self,
|
||||||
scoreboard_name: str = "mscplay",
|
scoreboard_name: str = "mscplay",
|
||||||
MaxVolume: float = 1.0,
|
MaxVolume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
) -> list:
|
) -> list:
|
||||||
"""
|
"""
|
||||||
使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表
|
使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表
|
||||||
@ -525,7 +525,7 @@ class midiConvert:
|
|||||||
+ str(nowscore)
|
+ str(nowscore)
|
||||||
+ "}"
|
+ "}"
|
||||||
+ f"] ~ ~ ~ playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} "
|
+ f"] ~ ~ ~ playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} "
|
||||||
f"{2 ** ((msg.note - 60 - _X) / 12)}"
|
f"{2 ** ((msg.note - 60 - _X) / 12)}"
|
||||||
)
|
)
|
||||||
commands += 1
|
commands += 1
|
||||||
if len(singleTrack) != 0:
|
if len(singleTrack) != 0:
|
||||||
@ -535,10 +535,10 @@ class midiConvert:
|
|||||||
|
|
||||||
# 原本这个算法的转换效果应该和上面的算法相似的
|
# 原本这个算法的转换效果应该和上面的算法相似的
|
||||||
def _toCmdList_m2(
|
def _toCmdList_m2(
|
||||||
self,
|
self,
|
||||||
scoreboard_name: str = "mscplay",
|
scoreboard_name: str = "mscplay",
|
||||||
MaxVolume: float = 1.0,
|
MaxVolume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
) -> list:
|
) -> list:
|
||||||
"""
|
"""
|
||||||
使用神羽和金羿的转换思路,将midi转换为我的世界命令列表
|
使用神羽和金羿的转换思路,将midi转换为我的世界命令列表
|
||||||
@ -597,7 +597,7 @@ class midiConvert:
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
||||||
msg.type == "note_off"
|
msg.type == "note_off"
|
||||||
):
|
):
|
||||||
channels[msg.channel].append(("NoteE", msg.note, microseconds))
|
channels[msg.channel].append(("NoteE", msg.note, microseconds))
|
||||||
|
|
||||||
@ -660,7 +660,7 @@ class midiConvert:
|
|||||||
.replace(")", r"}")
|
.replace(")", r"}")
|
||||||
)
|
)
|
||||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
||||||
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
cmdAmount += 1
|
cmdAmount += 1
|
||||||
@ -671,10 +671,10 @@ class midiConvert:
|
|||||||
return [tracks, cmdAmount, maxScore]
|
return [tracks, cmdAmount, maxScore]
|
||||||
|
|
||||||
def _toCmdList_m3(
|
def _toCmdList_m3(
|
||||||
self,
|
self,
|
||||||
scoreboard_name: str = "mscplay",
|
scoreboard_name: str = "mscplay",
|
||||||
MaxVolume: float = 1.0,
|
MaxVolume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
) -> list:
|
) -> list:
|
||||||
"""
|
"""
|
||||||
使用金羿的转换思路,将midi转换为我的世界命令列表
|
使用金羿的转换思路,将midi转换为我的世界命令列表
|
||||||
@ -720,7 +720,7 @@ class midiConvert:
|
|||||||
if msg.time != 0:
|
if msg.time != 0:
|
||||||
try:
|
try:
|
||||||
microseconds += (
|
microseconds += (
|
||||||
msg.time * tempo / self.midi.ticks_per_beat / 1000
|
msg.time * tempo / self.midi.ticks_per_beat / 1000
|
||||||
)
|
)
|
||||||
# print(microseconds)
|
# print(microseconds)
|
||||||
except NameError:
|
except NameError:
|
||||||
@ -728,10 +728,10 @@ class midiConvert:
|
|||||||
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
|
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
|
||||||
else:
|
else:
|
||||||
microseconds += (
|
microseconds += (
|
||||||
msg.time
|
msg.time
|
||||||
* mido.midifiles.midifiles.DEFAULT_TEMPO
|
* mido.midifiles.midifiles.DEFAULT_TEMPO
|
||||||
/ self.midi.ticks_per_beat
|
/ self.midi.ticks_per_beat
|
||||||
) / 1000
|
) / 1000
|
||||||
|
|
||||||
if msg.is_meta:
|
if msg.is_meta:
|
||||||
if msg.type == "set_tempo":
|
if msg.type == "set_tempo":
|
||||||
@ -759,7 +759,7 @@ class midiConvert:
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
||||||
msg.type == "note_off"
|
msg.type == "note_off"
|
||||||
):
|
):
|
||||||
channels[msg.channel][track_no].append(
|
channels[msg.channel][track_no].append(
|
||||||
("NoteE", msg.note, microseconds)
|
("NoteE", msg.note, microseconds)
|
||||||
@ -825,7 +825,7 @@ class midiConvert:
|
|||||||
.replace(")", r"}")
|
.replace(")", r"}")
|
||||||
)
|
)
|
||||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
||||||
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
cmdAmount += 1
|
cmdAmount += 1
|
||||||
@ -837,10 +837,10 @@ class midiConvert:
|
|||||||
|
|
||||||
# 简单的单音填充
|
# 简单的单音填充
|
||||||
def _toCmdList_m4(
|
def _toCmdList_m4(
|
||||||
self,
|
self,
|
||||||
scoreboard_name: str = "mscplay",
|
scoreboard_name: str = "mscplay",
|
||||||
MaxVolume: float = 1.0,
|
MaxVolume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
) -> list:
|
) -> list:
|
||||||
"""
|
"""
|
||||||
使用金羿的转换思路,将midi转换为我的世界命令列表,并使用完全填充算法优化音感
|
使用金羿的转换思路,将midi转换为我的世界命令列表,并使用完全填充算法优化音感
|
||||||
@ -893,7 +893,7 @@ class midiConvert:
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
||||||
msg.type == "note_off"
|
msg.type == "note_off"
|
||||||
):
|
):
|
||||||
channels[msg.channel].append(("NoteE", msg.note, microseconds))
|
channels[msg.channel].append(("NoteE", msg.note, microseconds))
|
||||||
|
|
||||||
@ -1009,7 +1009,7 @@ class midiConvert:
|
|||||||
+ str(score_now)
|
+ str(score_now)
|
||||||
+ "}"
|
+ "}"
|
||||||
+ f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / every_note[4] - 1} ~ "
|
+ f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / every_note[4] - 1} ~ "
|
||||||
f"{note.velocity * (0.7 if CheckFirstChannel else 0.9)} {2 ** ((note.pitch - 60 - _X) / 12)}"
|
f"{note.velocity * (0.7 if CheckFirstChannel else 0.9)} {2 ** ((note.pitch - 60 - _X) / 12)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
cmdAmount += 1
|
cmdAmount += 1
|
||||||
@ -1018,10 +1018,10 @@ class midiConvert:
|
|||||||
return [tracks, cmdAmount, maxScore]
|
return [tracks, cmdAmount, maxScore]
|
||||||
|
|
||||||
def _toCmdList_withDelay_m1(
|
def _toCmdList_withDelay_m1(
|
||||||
self,
|
self,
|
||||||
MaxVolume: float = 1.0,
|
MaxVolume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
player: str = "@a",
|
player: str = "@a",
|
||||||
) -> list:
|
) -> list:
|
||||||
"""
|
"""
|
||||||
使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表,并输出每个音符之后的延迟
|
使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表,并输出每个音符之后的延迟
|
||||||
@ -1061,18 +1061,19 @@ class midiConvert:
|
|||||||
tracks[now_tick].append(
|
tracks[now_tick].append(
|
||||||
self.execute_cmd_head.format(player)
|
self.execute_cmd_head.format(player)
|
||||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} "
|
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} "
|
||||||
f"{2 ** ((msg.note - 60 - _X) / 12)}"
|
f"{2 ** ((msg.note - 60 - _X) / 12)}"
|
||||||
)
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
tracks[now_tick] = [
|
tracks[now_tick] = [
|
||||||
self.execute_cmd_head.format(player)
|
self.execute_cmd_head.format(player)
|
||||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} "
|
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg.velocity / 128} "
|
||||||
f"{2 ** ((msg.note - 60 - _X) / 12)}"
|
f"{2 ** ((msg.note - 60 - _X) / 12)}"
|
||||||
]
|
]
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
all_ticks = list(tracks.keys())
|
all_ticks = list(tracks.keys())
|
||||||
|
all_ticks.sort()
|
||||||
|
|
||||||
for i in range(len(all_ticks)):
|
for i in range(len(all_ticks)):
|
||||||
if i != 0:
|
if i != 0:
|
||||||
@ -1090,10 +1091,10 @@ class midiConvert:
|
|||||||
return [results, max(all_ticks)]
|
return [results, max(all_ticks)]
|
||||||
|
|
||||||
def _toCmdList_withDelay_m2(
|
def _toCmdList_withDelay_m2(
|
||||||
self,
|
self,
|
||||||
MaxVolume: float = 1.0,
|
MaxVolume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
player: str = "@a",
|
player: str = "@a",
|
||||||
) -> list:
|
) -> list:
|
||||||
"""
|
"""
|
||||||
使用神羽和金羿的转换思路,将midi转换为我的世界命令列表,并输出每个音符之后的延迟
|
使用神羽和金羿的转换思路,将midi转换为我的世界命令列表,并输出每个音符之后的延迟
|
||||||
@ -1137,7 +1138,7 @@ class midiConvert:
|
|||||||
for msg in self.midi:
|
for msg in self.midi:
|
||||||
try:
|
try:
|
||||||
microseconds += (
|
microseconds += (
|
||||||
msg.time * 1000
|
msg.time * 1000
|
||||||
) # 任何人都tm不要动这里,这里循环方式不是track,所以,这里的计时方式不一样
|
) # 任何人都tm不要动这里,这里循环方式不是track,所以,这里的计时方式不一样
|
||||||
|
|
||||||
# print(microseconds)
|
# print(microseconds)
|
||||||
@ -1146,7 +1147,7 @@ class midiConvert:
|
|||||||
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
|
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
|
||||||
else:
|
else:
|
||||||
microseconds += (
|
microseconds += (
|
||||||
msg.time * 1000
|
msg.time * 1000
|
||||||
) # 任何人都tm不要动这里,这里循环方式不是track,所以,这里的计时方式不一样
|
) # 任何人都tm不要动这里,这里循环方式不是track,所以,这里的计时方式不一样
|
||||||
|
|
||||||
if msg.is_meta:
|
if msg.is_meta:
|
||||||
@ -1169,7 +1170,7 @@ class midiConvert:
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
||||||
msg.type == "note_off"
|
msg.type == "note_off"
|
||||||
):
|
):
|
||||||
channels[msg.channel].append(("NoteE", msg.note, microseconds))
|
channels[msg.channel].append(("NoteE", msg.note, microseconds))
|
||||||
|
|
||||||
@ -1223,16 +1224,17 @@ class midiConvert:
|
|||||||
tracks[score_now].append(
|
tracks[score_now].append(
|
||||||
self.execute_cmd_head.format(player)
|
self.execute_cmd_head.format(player)
|
||||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
||||||
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
||||||
)
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
tracks[score_now] = [
|
tracks[score_now] = [
|
||||||
self.execute_cmd_head.format(player)
|
self.execute_cmd_head.format(player)
|
||||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
||||||
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
||||||
]
|
]
|
||||||
|
|
||||||
all_ticks = list(tracks.keys())
|
all_ticks = list(tracks.keys())
|
||||||
|
all_ticks.sort()
|
||||||
|
|
||||||
for i in range(len(all_ticks)):
|
for i in range(len(all_ticks)):
|
||||||
for j in range(len(tracks[all_ticks[i]])):
|
for j in range(len(tracks[all_ticks[i]])):
|
||||||
@ -1254,10 +1256,10 @@ class midiConvert:
|
|||||||
return [results, max(all_ticks)]
|
return [results, max(all_ticks)]
|
||||||
|
|
||||||
def _toCmdList_withDelay_m3(
|
def _toCmdList_withDelay_m3(
|
||||||
self,
|
self,
|
||||||
MaxVolume: float = 1.0,
|
MaxVolume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
player: str = "@a",
|
player: str = "@a",
|
||||||
) -> list:
|
) -> list:
|
||||||
"""
|
"""
|
||||||
使用金羿的转换思路,将midi转换为我的世界命令列表,并输出每个音符之后的延迟
|
使用金羿的转换思路,将midi转换为我的世界命令列表,并输出每个音符之后的延迟
|
||||||
@ -1303,7 +1305,7 @@ class midiConvert:
|
|||||||
if msg.time != 0:
|
if msg.time != 0:
|
||||||
try:
|
try:
|
||||||
microseconds += (
|
microseconds += (
|
||||||
msg.time * tempo / self.midi.ticks_per_beat / 1000
|
msg.time * tempo / self.midi.ticks_per_beat / 1000
|
||||||
)
|
)
|
||||||
# print(microseconds)
|
# print(microseconds)
|
||||||
except NameError:
|
except NameError:
|
||||||
@ -1311,10 +1313,10 @@ class midiConvert:
|
|||||||
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
|
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
|
||||||
else:
|
else:
|
||||||
microseconds += (
|
microseconds += (
|
||||||
msg.time
|
msg.time
|
||||||
* mido.midifiles.midifiles.DEFAULT_TEMPO
|
* mido.midifiles.midifiles.DEFAULT_TEMPO
|
||||||
/ self.midi.ticks_per_beat
|
/ self.midi.ticks_per_beat
|
||||||
) / 1000
|
) / 1000
|
||||||
|
|
||||||
if msg.is_meta:
|
if msg.is_meta:
|
||||||
if msg.type == "set_tempo":
|
if msg.type == "set_tempo":
|
||||||
@ -1322,15 +1324,14 @@ class midiConvert:
|
|||||||
if self.debug_mode:
|
if self.debug_mode:
|
||||||
self.prt(f"TEMPO更改:{tempo}(毫秒每拍)")
|
self.prt(f"TEMPO更改:{tempo}(毫秒每拍)")
|
||||||
else:
|
else:
|
||||||
if self.debug_mode:
|
try:
|
||||||
try:
|
if msg.channel > 15 and self.debug_mode:
|
||||||
if msg.channel > 15:
|
raise ChannelOverFlowError(f"当前消息 {msg} 的通道超限(≤15)")
|
||||||
raise ChannelOverFlowError(f"当前消息 {msg} 的通道超限(≤15)")
|
if not track_no in channels[msg.channel].keys():
|
||||||
except AttributeError:
|
channels[msg.channel][track_no] = []
|
||||||
pass
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
if not track_no in channels[msg.channel].keys():
|
|
||||||
channels[msg.channel][track_no] = []
|
|
||||||
if msg.type == "program_change":
|
if msg.type == "program_change":
|
||||||
channels[msg.channel][track_no].append(
|
channels[msg.channel][track_no].append(
|
||||||
("PgmC", msg.program, microseconds)
|
("PgmC", msg.program, microseconds)
|
||||||
@ -1342,7 +1343,7 @@ class midiConvert:
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
||||||
msg.type == "note_off"
|
msg.type == "note_off"
|
||||||
):
|
):
|
||||||
channels[msg.channel][track_no].append(
|
channels[msg.channel][track_no].append(
|
||||||
("NoteE", msg.note, microseconds)
|
("NoteE", msg.note, microseconds)
|
||||||
@ -1395,21 +1396,23 @@ class midiConvert:
|
|||||||
else self.__Inst2soundID_withX(-1)
|
else self.__Inst2soundID_withX(-1)
|
||||||
)
|
)
|
||||||
score_now = round(msg[-1] / float(speed) / 50)
|
score_now = round(msg[-1] / float(speed) / 50)
|
||||||
|
# print(score_now)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tracks[score_now].append(
|
tracks[score_now].append(
|
||||||
self.execute_cmd_head.format(player)
|
self.execute_cmd_head.format(player)
|
||||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
||||||
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
||||||
)
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
tracks[score_now] = [
|
tracks[score_now] = [
|
||||||
self.execute_cmd_head.format(player)
|
self.execute_cmd_head.format(player)
|
||||||
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
+ f"playsound {soundID} @s ^ ^ ^{1 / MaxVolume - 1} {msg[2] / 128} "
|
||||||
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
f"{2 ** ((msg[1] - 60 - _X) / 12)}"
|
||||||
]
|
]
|
||||||
|
|
||||||
all_ticks = list(tracks.keys())
|
all_ticks = list(tracks.keys())
|
||||||
|
all_ticks.sort()
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
for i in range(len(all_ticks)):
|
for i in range(len(all_ticks)):
|
||||||
@ -1432,13 +1435,13 @@ class midiConvert:
|
|||||||
return [results, max(all_ticks)]
|
return [results, max(all_ticks)]
|
||||||
|
|
||||||
def to_mcpack(
|
def to_mcpack(
|
||||||
self,
|
self,
|
||||||
method: int = 1,
|
method: int = 1,
|
||||||
volume: float = 1.0,
|
volume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
progressbar: Union[bool, tuple] = None,
|
progressbar: Union[bool, tuple] = None,
|
||||||
scoreboard_name: str = "mscplay",
|
scoreboard_name: str = "mscplay",
|
||||||
isAutoReset: bool = False,
|
isAutoReset: bool = False,
|
||||||
) -> tuple:
|
) -> tuple:
|
||||||
"""
|
"""
|
||||||
使用method指定的转换算法,将midi转换为我的世界mcpack格式的包
|
使用method指定的转换算法,将midi转换为我的世界mcpack格式的包
|
||||||
@ -1466,7 +1469,7 @@ class midiConvert:
|
|||||||
# 写入manifest.json
|
# 写入manifest.json
|
||||||
if not os.path.exists(f"{self.output_path}/temp/manifest.json"):
|
if not os.path.exists(f"{self.output_path}/temp/manifest.json"):
|
||||||
with open(
|
with open(
|
||||||
f"{self.output_path}/temp/manifest.json", "w", encoding="utf-8"
|
f"{self.output_path}/temp/manifest.json", "w", encoding="utf-8"
|
||||||
) as f:
|
) as f:
|
||||||
f.write(
|
f.write(
|
||||||
'{\n "format_version": 1,\n "header": {\n "description": "'
|
'{\n "format_version": 1,\n "header": {\n "description": "'
|
||||||
@ -1483,7 +1486,7 @@ class midiConvert:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
with open(
|
with open(
|
||||||
f"{self.output_path}/temp/manifest.json", "r", encoding="utf-8"
|
f"{self.output_path}/temp/manifest.json", "r", encoding="utf-8"
|
||||||
) as manifest:
|
) as manifest:
|
||||||
data = json.loads(manifest.read())
|
data = json.loads(manifest.read())
|
||||||
data["header"][
|
data["header"][
|
||||||
@ -1507,9 +1510,9 @@ class midiConvert:
|
|||||||
"function mscplay/track" + str(cmdlist.index(track) + 1) + "\n"
|
"function mscplay/track" + str(cmdlist.index(track) + 1) + "\n"
|
||||||
)
|
)
|
||||||
with open(
|
with open(
|
||||||
f"{self.output_path}/temp/functions/mscplay/track{cmdlist.index(track) + 1}.mcfunction",
|
f"{self.output_path}/temp/functions/mscplay/track{cmdlist.index(track) + 1}.mcfunction",
|
||||||
"w",
|
"w",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
) as f:
|
) as f:
|
||||||
f.write("\n".join(track))
|
f.write("\n".join(track))
|
||||||
index_file.writelines(
|
index_file.writelines(
|
||||||
@ -1520,12 +1523,12 @@ class midiConvert:
|
|||||||
+ scoreboard_name
|
+ scoreboard_name
|
||||||
+ " 1\n",
|
+ " 1\n",
|
||||||
(
|
(
|
||||||
"scoreboard players reset @a[scores={"
|
"scoreboard players reset @a[scores={"
|
||||||
+ scoreboard_name
|
+ scoreboard_name
|
||||||
+ "="
|
+ "="
|
||||||
+ str(maxscore + 20)
|
+ str(maxscore + 20)
|
||||||
+ "..}]"
|
+ "..}]"
|
||||||
+ f" {scoreboard_name}\n"
|
+ f" {scoreboard_name}\n"
|
||||||
)
|
)
|
||||||
if isAutoReset
|
if isAutoReset
|
||||||
else "",
|
else "",
|
||||||
@ -1538,18 +1541,18 @@ class midiConvert:
|
|||||||
# 改这一行没🐎
|
# 改这一行没🐎
|
||||||
if progressbar is True:
|
if progressbar is True:
|
||||||
with open(
|
with open(
|
||||||
f"{self.output_path}/temp/functions/mscplay/progressShow.mcfunction",
|
f"{self.output_path}/temp/functions/mscplay/progressShow.mcfunction",
|
||||||
"w",
|
"w",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
) as f:
|
) as f:
|
||||||
f.writelines(
|
f.writelines(
|
||||||
"\n".join(self.__form_progress_bar(maxscore, scoreboard_name))
|
"\n".join(self.__form_progress_bar(maxscore, scoreboard_name))
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
with open(
|
with open(
|
||||||
f"{self.output_path}/temp/functions/mscplay/progressShow.mcfunction",
|
f"{self.output_path}/temp/functions/mscplay/progressShow.mcfunction",
|
||||||
"w",
|
"w",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
) as f:
|
) as f:
|
||||||
f.writelines(
|
f.writelines(
|
||||||
"\n".join(
|
"\n".join(
|
||||||
@ -1573,13 +1576,13 @@ class midiConvert:
|
|||||||
return True, maxlen, maxscore
|
return True, maxlen, maxscore
|
||||||
|
|
||||||
def to_mcpack_with_delay(
|
def to_mcpack_with_delay(
|
||||||
self,
|
self,
|
||||||
method: int = 1,
|
method: int = 1,
|
||||||
volume: float = 1.0,
|
volume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
progressbar: Union[bool, tuple] = False,
|
progressbar: Union[bool, tuple] = False,
|
||||||
player: str = "@a",
|
player: str = "@a",
|
||||||
max_height: int = 64,
|
max_height: int = 64,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
使用method指定的转换算法,将midi转换为mcstructure结构文件后打包成mcpack文件
|
使用method指定的转换算法,将midi转换为mcstructure结构文件后打包成mcpack文件
|
||||||
@ -1592,7 +1595,7 @@ class midiConvert:
|
|||||||
:param player: 玩家选择器,默认为`@a`
|
:param player: 玩家选择器,默认为`@a`
|
||||||
:return 成功与否,成功返回(True,未经过压缩的源,结构占用大小),失败返回(False,str失败原因)
|
:return 成功与否,成功返回(True,未经过压缩的源,结构占用大小),失败返回(False,str失败原因)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from TrimMCStruct import Structure
|
from TrimMCStruct import Structure
|
||||||
|
|
||||||
if self.enable_old_exe_format:
|
if self.enable_old_exe_format:
|
||||||
@ -1648,14 +1651,14 @@ class midiConvert:
|
|||||||
|
|
||||||
struct, size, end_pos = commands_to_structure(command_list, max_height - 1)
|
struct, size, end_pos = commands_to_structure(command_list, max_height - 1)
|
||||||
with open(
|
with open(
|
||||||
os.path.abspath(
|
os.path.abspath(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
self.output_path,
|
self.output_path,
|
||||||
"temp/structures/",
|
"temp/structures/",
|
||||||
f"{self.mid_file_name}_main.mcstructure",
|
f"{self.mid_file_name}_main.mcstructure",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
"wb+",
|
"wb+",
|
||||||
) as f:
|
) as f:
|
||||||
struct.dump(f)
|
struct.dump(f)
|
||||||
|
|
||||||
@ -1677,19 +1680,20 @@ class midiConvert:
|
|||||||
(0, 0, 0),
|
(0, 0, 0),
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
|
alwaysRun=False,
|
||||||
customName="显示进度条并加分",
|
customName="显示进度条并加分",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.abspath(
|
os.path.abspath(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
self.output_path,
|
self.output_path,
|
||||||
"temp/structures/",
|
"temp/structures/",
|
||||||
f"{self.mid_file_name}_start.mcstructure",
|
f"{self.mid_file_name}_start.mcstructure",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
"wb+",
|
"wb+",
|
||||||
) as f:
|
) as f:
|
||||||
struct_a.dump(f)
|
struct_a.dump(f)
|
||||||
|
|
||||||
@ -1704,14 +1708,14 @@ class midiConvert:
|
|||||||
)
|
)
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.abspath(
|
os.path.abspath(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
self.output_path,
|
self.output_path,
|
||||||
"temp/structures/",
|
"temp/structures/",
|
||||||
f"{self.mid_file_name}_pgb.mcstructure",
|
f"{self.mid_file_name}_pgb.mcstructure",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
"wb+",
|
"wb+",
|
||||||
) as f:
|
) as f:
|
||||||
pgb_struct.dump(f)
|
pgb_struct.dump(f)
|
||||||
|
|
||||||
@ -1726,20 +1730,21 @@ class midiConvert:
|
|||||||
r"scoreboard players reset {} {}".format(player, scb_name),
|
r"scoreboard players reset {} {}".format(player, scb_name),
|
||||||
(0, 0, 0),
|
(0, 0, 0),
|
||||||
1,
|
1,
|
||||||
1,
|
0,
|
||||||
|
alwaysRun=False,
|
||||||
customName="重置进度条计分板",
|
customName="重置进度条计分板",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.abspath(
|
os.path.abspath(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
self.output_path,
|
self.output_path,
|
||||||
"temp/structures/",
|
"temp/structures/",
|
||||||
f"{self.mid_file_name}_reset.mcstructure",
|
f"{self.mid_file_name}_reset.mcstructure",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
"wb+",
|
"wb+",
|
||||||
) as f:
|
) as f:
|
||||||
struct_a.dump(f)
|
struct_a.dump(f)
|
||||||
|
|
||||||
@ -1770,12 +1775,12 @@ class midiConvert:
|
|||||||
return True, len(command_list), max_delay
|
return True, len(command_list), max_delay
|
||||||
|
|
||||||
def to_mcstructure_file_with_delay(
|
def to_mcstructure_file_with_delay(
|
||||||
self,
|
self,
|
||||||
method: int = 1,
|
method: int = 1,
|
||||||
volume: float = 1.0,
|
volume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
player: str = "@a",
|
player: str = "@a",
|
||||||
max_height: int = 64,
|
max_height: int = 64,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
使用method指定的转换算法,将midi转换为mcstructure结构文件
|
使用method指定的转换算法,将midi转换为mcstructure结构文件
|
||||||
@ -1804,25 +1809,25 @@ class midiConvert:
|
|||||||
struct, size, end_pos = commands_to_structure(cmd_list, max_height - 1)
|
struct, size, end_pos = commands_to_structure(cmd_list, max_height - 1)
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.abspath(
|
os.path.abspath(
|
||||||
os.path.join(self.output_path, f"{self.mid_file_name}.mcstructure")
|
os.path.join(self.output_path, f"{self.mid_file_name}.mcstructure")
|
||||||
),
|
),
|
||||||
"wb+",
|
"wb+",
|
||||||
) as f:
|
) as f:
|
||||||
struct.dump(f)
|
struct.dump(f)
|
||||||
|
|
||||||
return True, size, max_delay
|
return True, size, max_delay
|
||||||
|
|
||||||
def to_BDX_file(
|
def to_BDX_file(
|
||||||
self,
|
self,
|
||||||
method: int = 1,
|
method: int = 1,
|
||||||
volume: float = 1.0,
|
volume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
progressbar: Union[bool, tuple] = False,
|
progressbar: Union[bool, tuple] = False,
|
||||||
scoreboard_name: str = "mscplay",
|
scoreboard_name: str = "mscplay",
|
||||||
isAutoReset: bool = False,
|
isAutoReset: bool = False,
|
||||||
author: str = "Eilles",
|
author: str = "Eilles",
|
||||||
max_height: int = 64,
|
max_height: int = 64,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
使用method指定的转换算法,将midi转换为BDX结构文件
|
使用method指定的转换算法,将midi转换为BDX结构文件
|
||||||
@ -1847,17 +1852,17 @@ class midiConvert:
|
|||||||
os.makedirs(self.output_path)
|
os.makedirs(self.output_path)
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.abspath(
|
os.path.abspath(
|
||||||
os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
|
os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
|
||||||
),
|
),
|
||||||
"w+",
|
"w+",
|
||||||
) as f:
|
) as f:
|
||||||
f.write("BD@")
|
f.write("BD@")
|
||||||
|
|
||||||
_bytes = (
|
_bytes = (
|
||||||
b"BDX\x00"
|
b"BDX\x00"
|
||||||
+ author.encode("utf-8")
|
+ author.encode("utf-8")
|
||||||
+ b" & Musicreater\x00\x01command_block\x00"
|
+ b" & Musicreater\x00\x01command_block\x00"
|
||||||
)
|
)
|
||||||
|
|
||||||
commands = []
|
commands = []
|
||||||
@ -1884,14 +1889,14 @@ class midiConvert:
|
|||||||
[
|
[
|
||||||
(i, 0)
|
(i, 0)
|
||||||
for i in (
|
for i in (
|
||||||
self.__form_progress_bar(maxScore, scoreboard_name)
|
self.__form_progress_bar(maxScore, scoreboard_name)
|
||||||
# 此处是对于仅有 True 的参数和自定义参数的判断
|
# 此处是对于仅有 True 的参数和自定义参数的判断
|
||||||
# 改这一行没🐎
|
# 改这一行没🐎
|
||||||
if progressbar is True
|
if progressbar is True
|
||||||
else self.__form_progress_bar(
|
else self.__form_progress_bar(
|
||||||
maxScore, scoreboard_name, progressbar
|
maxScore, scoreboard_name, progressbar
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
],
|
],
|
||||||
max_height - 1,
|
max_height - 1,
|
||||||
)
|
)
|
||||||
@ -1907,24 +1912,24 @@ class midiConvert:
|
|||||||
_bytes += cmdBytes
|
_bytes += cmdBytes
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.abspath(
|
os.path.abspath(
|
||||||
os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
|
os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
|
||||||
),
|
),
|
||||||
"ab+",
|
"ab+",
|
||||||
) as f:
|
) as f:
|
||||||
f.write(brotli.compress(_bytes + b"XE"))
|
f.write(brotli.compress(_bytes + b"XE"))
|
||||||
|
|
||||||
return True, total_count, maxScore, size, finalPos
|
return True, total_count, maxScore, size, finalPos
|
||||||
|
|
||||||
def to_BDX_file_with_delay(
|
def to_BDX_file_with_delay(
|
||||||
self,
|
self,
|
||||||
method: int = 1,
|
method: int = 1,
|
||||||
volume: float = 1.0,
|
volume: float = 1.0,
|
||||||
speed: float = 1.0,
|
speed: float = 1.0,
|
||||||
progressbar: Union[bool, tuple] = False,
|
progressbar: Union[bool, tuple] = False,
|
||||||
player: str = "@a",
|
player: str = "@a",
|
||||||
author: str = "Eilles",
|
author: str = "Eilles",
|
||||||
max_height: int = 64,
|
max_height: int = 64,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
使用method指定的转换算法,将midi转换为BDX结构文件
|
使用method指定的转换算法,将midi转换为BDX结构文件
|
||||||
@ -1951,17 +1956,17 @@ class midiConvert:
|
|||||||
os.makedirs(self.output_path)
|
os.makedirs(self.output_path)
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.abspath(
|
os.path.abspath(
|
||||||
os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
|
os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
|
||||||
),
|
),
|
||||||
"w+",
|
"w+",
|
||||||
) as f:
|
) as f:
|
||||||
f.write("BD@")
|
f.write("BD@")
|
||||||
|
|
||||||
_bytes = (
|
_bytes = (
|
||||||
b"BDX\x00"
|
b"BDX\x00"
|
||||||
+ author.encode("utf-8")
|
+ author.encode("utf-8")
|
||||||
+ b" & Musicreater\x00\x01command_block\x00"
|
+ b" & Musicreater\x00\x01command_block\x00"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 此处是对于仅有 True 的参数和自定义参数的判断
|
# 此处是对于仅有 True 的参数和自定义参数的判断
|
||||||
@ -2011,17 +2016,17 @@ class midiConvert:
|
|||||||
_bytes += cmdBytes
|
_bytes += cmdBytes
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.abspath(
|
os.path.abspath(
|
||||||
os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
|
os.path.join(self.output_path, f"{self.mid_file_name}.bdx")
|
||||||
),
|
),
|
||||||
"ab+",
|
"ab+",
|
||||||
) as f:
|
) as f:
|
||||||
f.write(brotli.compress(_bytes + b"XE"))
|
f.write(brotli.compress(_bytes + b"XE"))
|
||||||
|
|
||||||
return True, len(cmdlist), max_delay, size, finalPos
|
return True, len(cmdlist), max_delay, size, finalPos
|
||||||
|
|
||||||
def toDICT(
|
def toDICT(
|
||||||
self,
|
self,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""
|
"""
|
||||||
使用金羿的转换思路,将midi转换为字典
|
使用金羿的转换思路,将midi转换为字典
|
||||||
@ -2064,9 +2069,9 @@ class midiConvert:
|
|||||||
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
|
raise NotDefineTempoError("计算当前分数时出错 未定义参量 Tempo")
|
||||||
else:
|
else:
|
||||||
microseconds += (
|
microseconds += (
|
||||||
msg.time
|
msg.time
|
||||||
* mido.midifiles.midifiles.DEFAULT_TEMPO
|
* mido.midifiles.midifiles.DEFAULT_TEMPO
|
||||||
/ self.midi.ticks_per_beat
|
/ self.midi.ticks_per_beat
|
||||||
)
|
)
|
||||||
|
|
||||||
if msg.is_meta:
|
if msg.is_meta:
|
||||||
@ -2095,7 +2100,7 @@ class midiConvert:
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
elif (msg.type == "note_on" and msg.velocity == 0) or (
|
||||||
msg.type == "note_off"
|
msg.type == "note_off"
|
||||||
):
|
):
|
||||||
channels[msg.channel][track_no].append(
|
channels[msg.channel][track_no].append(
|
||||||
("NoteE", msg.note, microseconds)
|
("NoteE", msg.note, microseconds)
|
||||||
|
@ -89,7 +89,7 @@
|
|||||||
- 感谢由 **[CMA_2401PT](https://github.com/CMA2401PT)** 为我们的软件开发的一些方面进行指导,同时我们参考了他的BDXworkshop作为BDX结构编辑的参考
|
- 感谢由 **[CMA_2401PT](https://github.com/CMA2401PT)** 为我们的软件开发的一些方面进行指导,同时我们参考了他的BDXworkshop作为BDX结构编辑的参考
|
||||||
- 感谢由 **[Dislink Sforza](https://github.com/Dislink) “断联·斯福尔扎”**\<QQ1600515314\> 带来的midi音色解析以及转换指令的算法,我们将其改编并应用;同时,感谢他的[网页版转换器](https://dislink.github.io/midi2bdx/)给我们的开发与更新带来巨大的压力和动力,让我们在原本一骑绝尘的摸鱼道路上转向开发,希望他能考上一个理想的大学!
|
- 感谢由 **[Dislink Sforza](https://github.com/Dislink) “断联·斯福尔扎”**\<QQ1600515314\> 带来的midi音色解析以及转换指令的算法,我们将其改编并应用;同时,感谢他的[网页版转换器](https://dislink.github.io/midi2bdx/)给我们的开发与更新带来巨大的压力和动力,让我们在原本一骑绝尘的摸鱼道路上转向开发,希望他能考上一个理想的大学!
|
||||||
- 感谢 **Touch “偷吃”**\<QQ1793537164\> 提供的BDX导入测试支持,并对程序的改进提供了丰富的意见;同时也感谢他的不断尝试新的内容,使我们的排错更进一步
|
- 感谢 **Touch “偷吃”**\<QQ1793537164\> 提供的BDX导入测试支持,并对程序的改进提供了丰富的意见;同时也感谢他的不断尝试新的内容,使我们的排错更进一步
|
||||||
- 感谢 **Mono**\<QQ738893087\> 反馈安装时的问题,辅助我们找到了视窗操作系统下的兼容性问题
|
- 感谢 **Mono**\<QQ738893087\> 反馈安装时的问题,辅助我们找到了视窗操作系统下的兼容性问题;感谢其反馈延迟播放器出现的重大问题,让我们得以修改全部延迟播放错误
|
||||||
- 感谢 **Ammelia “艾米利亚”**\<QQ2838334637\> 敦促我们进行新的功能开发,并为新功能提出了非常优秀的大量建议,以及提供的BDX导入测试支持,为我们的新结构生成算法提供了大量的实际理论支持
|
- 感谢 **Ammelia “艾米利亚”**\<QQ2838334637\> 敦促我们进行新的功能开发,并为新功能提出了非常优秀的大量建议,以及提供的BDX导入测试支持,为我们的新结构生成算法提供了大量的实际理论支持
|
||||||
- 感谢 **[神羽](https://gitee.com/snowykami) “[SnowyKami](https://github.com/snowyfirefly)”** 对我们项目的支持与宣传,希望他能考的一所优秀的大学!
|
- 感谢 **[神羽](https://gitee.com/snowykami) “[SnowyKami](https://github.com/snowyfirefly)”** 对我们项目的支持与宣传,希望他能考的一所优秀的大学!
|
||||||
- 感谢 **指令师_苦力怕 playjuice123**\<QQ240667197\>为我们的程序找出错误,并提醒我们修复一个一直存在的大bug。
|
- 感谢 **指令师_苦力怕 playjuice123**\<QQ240667197\>为我们的程序找出错误,并提醒我们修复一个一直存在的大bug。
|
||||||
|
Loading…
x
Reference in New Issue
Block a user