This commit is contained in:
EillesWan 2023-09-29 17:20:03 +08:00
parent 732dd0453d
commit cd3dc6fcaa
4 changed files with 346 additions and 95 deletions

View File

@ -116,7 +116,7 @@ def format_ipt(
# 获取midi列表
while True:
midi_path = ipt(f"请键入MIDI地址或所在目录地址")
midi_path = ipt(f"MIDI地址或所在目录地址")
try:
if os.path.exists(midi_path):
if os.path.isfile(midi_path):
@ -140,7 +140,7 @@ while True:
# 获取输出地址
while True:
out_path = ipt(f"请键入文件生成输出地址:")
out_path = ipt(f"文件生成输出地址:")
try:
if not os.path.exists(out_path):
prt("该地址不存在,或无法访问该地址,请重新输入。")
@ -170,26 +170,26 @@ def is_in_player(sth: str):
output_file_format = format_ipt(
"请键入输出文件类型 (mcpack/0|bdx/1)",
"输出文件类型 (mcpack/0|bdx/1)",
is_in_bdx_mcpack,
"输入内容有误,请重新输入。",
)[1]
if output_file_format == 0:
player_format = format_ipt(
"请选择播放器类型 (延迟/0|计分板/1|中继器/2)",
"播放器类型 (延迟/0|计分板/1|中继器/2)",
is_in_player,
"输入内容有误,请重新输入。",
)[1]
else:
player_format = format_ipt(
"请选择播放器类型 (延迟/0|计分板/1)",
"播放器类型 (延迟/0|计分板/1)",
is_in_player,
"输入内容有误,请重新输入。",
)[1]
old_exe_enabled = format_ipt(
"启用1.19以前的旧版execute指令格式 (否/0|是/1)", bool_str, "输入内容格式错误,应为 是/1/真/t/y 或 否/0/假/f/n"
old_exe_enabled = not format_ipt(
"启用新版代执行指令 (否/0|是/1)", bool_str, "输入内容格式错误,应为 是/1/真/t/y 或 否/0/假/f/n"
)[1]

227
llc_spec_Creeper.py Normal file
View File

@ -0,0 +1,227 @@
# -*- coding: utf-8 -*-
# 伶伦 开发交流群 861684859
"""
伶伦转换器暨模组特用奇巧
Linglun Converter for Special Use with addons
版权所有 © 2023 金羿 & 睿穆开发组
Copyright © 2023 EillesWan & TriM Org.
开源相关声明请见 ./License.md
Terms & Conditions: ./Lisense.md
"""
__version__ = "0.0.1"
import json
import os
import sys
from rich.table import Table
import Musicreater
from Musicreater.constants import MIDI_PITCH_NAME_TABLE, PERCUSSION_INSTRUMENT_LIST
from utils.io import *
osc.project_name = "伶伦暨模组特用奇巧"
osc.version = __version__
if len(sys.argv) > 0:
def go_for_args(debugMode: str = "False", logfile: str = "True"):
global logger
osc.isRelease = False if debugMode.lower() in ("true", "1") else True
logger.printing = not osc.isRelease
logger.writing = True if logfile.lower() in ("true", "1") else False
go_for_args(*sys.argv)
# 显示大标题
MainConsole.print(
"[#121110 on #F0F2F4] ",
style="#121110 on #F0F2F4",
justify="center",
)
MainConsole.rule(
title="[bold #AB70FF]欢迎使用{}".format(osc.project_name),
characters="=",
style="#26E2FF",
)
# MainConsole.rule(title="[bold #AB70FF]Welcome to Linglun Converter", characters="-")
MainConsole.rule(
title="[#AB70FF]版本{} | 音·创内核版本{}".format(__version__, Musicreater.__version__),
characters="-",
style="#26E2FF",
)
MainConsole.print(
"[#121110 on #F0F2F4] ",
style="#121110 on #F0F2F4",
justify="center",
)
# 获取midi列表
while True:
midi_path = ipt(f"MIDI地址或所在目录地址")
try:
if os.path.exists(midi_path):
if os.path.isfile(midi_path):
midis = (midi_path,)
elif os.path.isdir(midi_path):
midis = (
os.path.join(midi_path, i)
for i in os.listdir(midi_path)
if i.lower().endswith(".mid") or i.lower().endswith(".midi")
)
else:
prt("输入内容有误,请重新输入。")
continue
else:
prt("该地址不存在,或无法访问该地址,请重新输入。")
continue
except PermissionError:
prt("无法访问该地址,请检查是否给予程序相关文件的访问权限。")
continue
break
# percussion_only = format_ipt(
# "仅处理打击乐器 (否/0|是/1)", bool_str, "输入内容格式错误,应为 是/1/真/t/y 或 否/0/假/f/n"
# )[1]
speed: float = format_ipt("播放速度", float_str, "错误,需要浮点型数据;请重新输入。")[1]
final_result: Dict[str, Dict[int, List[Tuple[str, int, str]]]] = {}
for single_midi in midis:
fn = os.path.splitext(os.path.split(single_midi)[-1])[0]
midi_cvt = Musicreater.MidiConvert.from_midi_file(
single_midi,
)
midi_cvt.to_music_channels()
max_delay = 0
instrument_ID = -1
total_track = {}
instriments = {}
# 此处 我们把通道视为音轨
for i in midi_cvt.channels.keys():
# 如果当前通道为空 则跳过
if not midi_cvt.channels[i]:
continue
# 第十通道是打击乐通道
SpecialBits = True if i == 9 else False
for track_no, track in midi_cvt.channels[i].items():
for msg in track:
if msg[0] == "PgmC":
instrument_ID = msg[1]
if msg[0] == "NoteS":
soundID, _X = (
midi_cvt.perc_inst_to_soundID_withX(msg[1])
if SpecialBits
else midi_cvt.inst_to_souldID_withX(instrument_ID)
)
score_now = round(msg[-1] / float(speed) / 50)
max_delay = max(max_delay, score_now)
mc_pitch = "" if SpecialBits else 2 ** ((msg[1] - 60 - _X) / 12)
try:
total_track[score_now].append(
(MIDI_PITCH_NAME_TABLE[msg[1]], mc_pitch, soundID),
)
except (IndexError, KeyError):
total_track[score_now] = [
(MIDI_PITCH_NAME_TABLE[msg[1]], mc_pitch, soundID),
]
try:
instriments[soundID] += 1
except (IndexError, KeyError):
instriments[soundID] = 1
del midi_cvt
table = Table(
*instriments.keys(),
title="[bold #AB70FF on #121110]{} 乐器统计".format(fn),
title_style="#26E2FF on #121110",
)
table.add_row(*[str(i) for i in instriments.values()])
MainConsole.print(
"[bold #8B50DF on #F0F2F4]-={}=-".format(fn),
style="#AB70FF on #F0F2F4",
justify="center",
)
prt(table)
inst_selected: Set[str] = format_ipt(
"""请选择需要保留的乐器;以空格作分割;以 percussion 表示全部打击乐器|以 pitched 表示全部乐音乐器|以 all 表示所有乐器\n""",
lambda x: set(
[
i.lower()
for i in x.split(" ")
if isin(
i,
{
True: (
list(instriments.keys()) + ["all", "pitched", "percussion"]
)
},
)
]
),
"输入错误,需要在已有的乐器范围之内。",
strict_mode=True,
)[1]
if "all" in inst_selected:
inst_selected.remove("all")
for i in instriments.keys():
inst_selected.add(i)
if "percussion" in inst_selected:
inst_selected.remove("percussion")
for i in instriments.keys():
if i in PERCUSSION_INSTRUMENT_LIST:
inst_selected.add(i)
if "pitched" in inst_selected:
inst_selected.remove("pitched")
for i in instriments.keys():
if i not in PERCUSSION_INSTRUMENT_LIST:
inst_selected.add(i)
result_piece = []
for i, ele in total_track.items():
this_ele = [k for k in ele if k[-1] in inst_selected]
if this_ele:
result_piece.append((i, this_ele))
result_piece.sort(key=lambda x: x[0])
final_result[fn] = {}
for ind, ele in result_piece:
final_result[fn][ind - result_piece[0][0]] = ele
with open("result.json", "w", encoding="utf-8") as f:
json.dump(
final_result,
f,
ensure_ascii=False,
indent=3,
sort_keys=True,
)

View File

@ -21,50 +21,41 @@ import os
import random
import sys
print("小贴不妨试试Mid-BDX转换网页在线的多功能Midi转换器")
print("https://dislink.github.io/midi2bdx/")
import Musicreater
from Musicreater.plugin import ConvertConfig
from Musicreater.plugin.bdxfile import to_BDX_file_in_delay, to_BDX_file_in_score
from Musicreater.plugin.addonpack import (
to_addon_pack_in_delay,
to_addon_pack_in_repeater,
to_addon_pack_in_score,
)
from Musicreater.constants import DEFAULT_PROGRESSBAR_STYLE
from utils.io import *
from languages.lang import languages
osc.project_name = "伶伦转换器"
osc.version = __version__
def __main__():
MainConsole.print(
"[#121110 on #F0F2F4] ",
style="#121110 on #F0F2F4",
justify="center",
)
osc.project_name = "伶伦转换器"
osc.version = __version__
if len(sys.argv) > 0:
def go_for_args(
languageChange: str = "ZH-CN", debugMode: str = "False", logfile: str = "True"
):
global currentLang
def go_for_args(debugMode: str = "False", logfile: str = "True"):
global logger
currentLang = (
languageChange.upper()
if languageChange.upper() in languages.keys()
else "ZH-CN"
)
osc.isRelease = False if debugMode.lower() in ("true", "1") else True
logger.printing = not osc.isRelease
logger.writing = True if logfile.lower() in ("true", "1") else False
if len(sys.argv) > 0:
go_for_args(*sys.argv)
def _(__):
"""
`languages`
"""
return languages[currentLang][__]
# 显示大标题
MainConsole.rule(title="[bold #AB70FF]欢迎使用伶伦独立转换器", characters="=", style="#26E2FF")
MainConsole.rule(title="[bold #AB70FF]Welcome to Linglun Converter", characters="-")
@ -74,7 +65,9 @@ nowYang = datetime.datetime.now()
if nowYang.month == 8 and nowYang.day == 6:
# 诸葛八卦生日
MainConsole.print(
"[#7DB5F0 on #121110]今天可不是催更的日子!\n诸葛亮与八卦阵{}岁生日快乐!".format(nowYang.year - 2008),
"[#7DB5F0 on #121110]今天可不是催更的日子!\n诸葛亮与八卦阵{}岁生日快乐!".format(
nowYang.year - 2008
),
style="#7DB5F0 on #121110",
justify="center",
)
@ -93,27 +86,25 @@ else:
justify="center",
)
prt(f"{_('LangChd')}{_(':')}{_(currentLang)}")
prt("伶伦转换器简易版 正在启动……")
def __main__():
print('伶伦转换器简易版 正在启动……')
print('更新执行位置...')
if sys.platform == 'win32':
prt("更新执行位置...")
if sys.platform == "win32":
try:
os.chdir(__file__[:len(__file__) - __file__[len(__file__)::-1].index('\\')])
logger.info('更新执行位置,当前文件位置 {}'.format(__file__))
except FileNotFoundError: # 程序规范修改根据新的语法标准except后面不能没有错误类型所以既然是pass就随便填一个错误
os.chdir(
__file__[: len(__file__) - __file__[len(__file__) :: -1].index("\\")]
)
logger.info("Win32 更新执行位置,当前文件位置 {}".format(__file__))
except FileNotFoundError:
pass
else:
try:
os.chdir(__file__[:len(__file__) - __file__[len(__file__)::-1].index('/')])
except Exception:
os.chdir(
__file__[: len(__file__) - __file__[len(__file__) :: -1].index("/")]
)
except FileNotFoundError:
pass
log('其他平台:{} 更新执行位置,当前文件位置 {}'.format(sys.platform, __file__))
print('完成!')
log("其他平台:{} 更新执行位置,当前文件位置 {}".format(sys.platform, __file__))
prt("完成!")
prt("载入功能……")

View File

@ -1,7 +1,7 @@
from typing import Any, Literal, Optional, TextIO
import urllib.request
import urllib.error
import urllib.request
from typing import Any, Callable, Literal, Optional, Set, TextIO, Tuple, Dict, List
import TrimLog
from TrimLog import Console, object_constants
@ -19,10 +19,10 @@ logger = TrimLog.Logger(
try:
myWords = (
urllib.request.urlopen(
'https://gitee.com/TriM-Organization/LinglunStudio/raw/master/resources/myWords.txt'
"https://gitee.com/TriM-Organization/LinglunStudio/raw/master/resources/myWords.txt"
)
.read()
.decode('utf-8')
.decode("utf-8")
.strip("\n")
.split("\n")
)
@ -158,27 +158,32 @@ def ipt(
def format_ipt(
notice: str,
fun,
err_note: str = "",
fun: Callable,
err_note: str = "{}",
strict_mode: bool = False,
*extraArg,
):
) -> Tuple[str, Any]:
"""循环输入,以某种格式
notice: 输入时的提示
fun: 格式函数
err_note: 输入不符格式时的提示
strict_mode: 是否将函数值作为结束循环的判断依据之一
*extraArg: 对于函数的其他参数"""
while True:
result = ipt(notice)
# noinspection PyBroadException
try:
if strict_mode:
if fun_result := fun(result, *extraArg):
break
else:
fun_result = fun(result, *extraArg)
break
# noinspection PyBroadException
except BaseException:
prt(err_note)
except ValueError as E:
prt(err_note.format(E))
continue
return result, fun_result
def isin(sth: str, range_list: dict):
sth = sth.lower()
for bool_value, res_list in range_list.items():
@ -192,9 +197,9 @@ def bool_str(sth: str):
try:
return bool(float(sth))
except:
if str(sth).lower() in ("true", "", "", 'y', 't'):
if str(sth).lower() in ("true", "", "", "y", "t"):
return True
elif str(sth).lower() in ("false", "", "", 'f', 'n'):
elif str(sth).lower() in ("false", "", "", "f", "n"):
return False
else:
raise ValueError
@ -205,10 +210,38 @@ def float_str(sth: str):
return float(sth)
except ValueError:
try:
return float(sth.replace("", "1").replace("", "2").replace("", "3").replace("", "4").replace("", "5").replace("", "6").replace("", "7").replace("", "8").replace("", "9").replace("", "0").replace("", "1").replace("",'2').replace("", "3").replace("", "4").replace("", "5").replace("", "6").replace("", "7").replace("", "8").replace("", "9").replace("", "0").replace("", "0").replace("", "1").replace("", "2").replace("", "2").replace("","7").replace("",'.'))
return float(
sth.replace("", "1")
.replace("", "2")
.replace("", "3")
.replace("", "4")
.replace("", "5")
.replace("", "6")
.replace("", "7")
.replace("", "8")
.replace("", "9")
.replace("", "0")
.replace("", "1")
.replace("", "2")
.replace("", "3")
.replace("", "4")
.replace("", "5")
.replace("", "6")
.replace("", "7")
.replace("", "8")
.replace("", "9")
.replace("", "0")
.replace("", "0")
.replace("", "1")
.replace("", "2")
.replace("", "2")
.replace("", "7")
.replace("", ".")
)
except:
raise ValueError
def int_str(sth: str):
try:
return int(float_str(sth))