修复了打击乐器转换时,注释部分format代码报错的问题

This commit is contained in:
EillesWan 2024-02-02 18:12:29 +08:00
parent dbb3f4c83f
commit 99a7564648
14 changed files with 297 additions and 139 deletions

View File

@ -17,8 +17,8 @@ Terms & Conditions: License.md in the root directory
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
__version__ = "1.7.1"
__vername__ = "更高的自定义化程度—修复类型定义的重复问题"
__version__ = "1.7.2"
__vername__ = "修复部分情况下的崩溃问题"
__author__ = (
("金羿", "Eilles Wan"),
("诸葛亮与八卦阵", "bgArray"),
@ -33,7 +33,6 @@ __all__ = [
"SingleCommand",
"SingleNoteBox",
# "TimeStamp", 未来功能
# 默认值
"DEFAULT_PROGRESSBAR_STYLE",
"MM_INSTRUMENT_DEVIATION_TABLE",

View File

@ -20,7 +20,11 @@ Terms & Conditions: License.md in the root directory
from .exceptions import *
from .subclass import *
from .utils import *
from .main import MidiConvert, MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE
from .main import (
MidiConvert,
MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE,
MM_CLASSIC_PITCHED_INSTRUMENT_TABLE,
)
from .types import Tuple, List, Dict, ChannelType
@ -75,7 +79,7 @@ class FutureMidiConvertM4(MidiConvert):
lastime=int(_note.duration / totalCount),
track_number=_note.track_no,
is_percussion=_note.percussive,
extra_information=_note.extra_info
extra_information=_note.extra_info,
)
# (
# _note.start_time + _i * _apply_time_division,
@ -120,8 +124,18 @@ class FutureMidiConvertM4(MidiConvert):
# 此处 我们把通道视为音轨
for channel in self.to_music_note_channels().values():
for note in channel:
note.set_info(note_to_command_parameters(note,self.percussion_note_referrence_table if note.percussive else self.pitched_note_reference_table, (max_volume) if note.track_no == 0 else (max_volume * 0.9),self.volume_processing_function,))
note.set_info(
note_to_command_parameters(
note,
(
self.percussion_note_referrence_table
if note.percussive
else self.pitched_note_reference_table
),
(max_volume) if note.track_no == 0 else (max_volume * 0.9),
self.volume_processing_function,
)
)
if not note.percussive:
notes_list.extend(self._linear_note(note, note.extra_info[3] * 500))
@ -291,9 +305,13 @@ class FutureMidiConvertM5(MidiConvert):
elif msg[0] == "NoteS":
soundID, _X = (
inst_to_sould_with_deviation(msg[1],MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE)
inst_to_sould_with_deviation(
msg[1], MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE
)
if SpecialBits
else inst_to_sould_with_deviation(InstID,MM_CLASSIC_PITCHED_INSTRUMENT_TABLE)
else inst_to_sould_with_deviation(
InstID, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE
)
)
score_now = round(msg[-1] / float(speed) / 50)

View File

@ -30,16 +30,16 @@ Terms & Conditions: ../License.md
"""
# ============================
import mido
class NoteMessage:
def __init__(self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None):
def __init__(
self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None
):
self.channel = channel
self.note = pitch
self.velocity = velocity
@ -49,19 +49,39 @@ class NoteMessage:
def mt2gt(mt, tpb_a, bpm_a):
return mt / tpb_a / bpm_a * 60
self.startTrueTime = mt2gt(self.startTime, midi.ticks_per_beat, self.tempo) # / 20
self.startTrueTime = mt2gt(
self.startTime, midi.ticks_per_beat, self.tempo
) # / 20
# delete_extra_zero(round_up())
if change_bpm is not None:
self.lastTrueTime = mt2gt(self.lastTime, midi.ticks_per_beat, change_bpm) # / 20
self.lastTrueTime = mt2gt(
self.lastTime, midi.ticks_per_beat, change_bpm
) # / 20
else:
self.lastTrueTime = mt2gt(self.lastTime, midi.ticks_per_beat, self.tempo) # / 20
self.lastTrueTime = mt2gt(
self.lastTime, midi.ticks_per_beat, self.tempo
) # / 20
# delete_extra_zero(round_up())
print((self.startTime * self.tempo) / (midi.ticks_per_beat * 50000))
def __str__(self):
return "noteMessage channel=" + str(self.channel) + " note=" + str(self.note) + " velocity=" + \
str(self.velocity) + " startTime=" + str(self.startTime) + " lastTime=" + str(self.lastTime) + \
" startTrueTime=" + str(self.startTrueTime) + " lastTrueTime=" + str(self.lastTrueTime)
return (
"noteMessage channel="
+ str(self.channel)
+ " note="
+ str(self.note)
+ " velocity="
+ str(self.velocity)
+ " startTime="
+ str(self.startTime)
+ " lastTime="
+ str(self.lastTime)
+ " startTrueTime="
+ str(self.startTrueTime)
+ " lastTrueTime="
+ str(self.lastTrueTime)
)
def load(mid: mido.MidiFile):
@ -75,7 +95,7 @@ def load(mid: mido.MidiFile):
for msg in track:
# print(msg)
if msg.is_meta is not True:
if msg.type == 'note_on' and msg.velocity == 0:
if msg.type == "note_on" and msg.velocity == 0:
type_[1] = True
elif msg.type == "note_off":
type_[0] = True
@ -108,10 +128,10 @@ def load(mid: mido.MidiFile):
bpm = 60000000 / msg.tempo
is_change_bpm = True
if msg.type == 'note_on' and msg.velocity != 0:
if msg.type == "note_on" and msg.velocity != 0:
noteOn.append([msg, msg.note, ticks])
if type_[1] is True:
if msg.type == 'note_on' and msg.velocity == 0:
if msg.type == "note_on" and msg.velocity == 0:
for u in noteOn:
index = 0
if u[1] == msg.note:
@ -121,13 +141,31 @@ def load(mid: mido.MidiFile):
index += 1
print(lastTick)
if is_change_bpm and recent_change_bpm != 0:
trackS.append(NoteMessage(msg.channel, msg.note, lastMessage.velocity, lastTick, ticks - lastTick,
mid, recent_change_bpm, bpm))
trackS.append(
NoteMessage(
msg.channel,
msg.note,
lastMessage.velocity,
lastTick,
ticks - lastTick,
mid,
recent_change_bpm,
bpm,
)
)
is_change_bpm = False
else:
trackS.append(
NoteMessage(msg.channel, msg.note, lastMessage.velocity, lastTick, ticks - lastTick,
mid, bpm))
NoteMessage(
msg.channel,
msg.note,
lastMessage.velocity,
lastTick,
ticks - lastTick,
mid,
bpm,
)
)
# print(noteOn)
# print(index)
try:
@ -139,20 +177,19 @@ def load(mid: mido.MidiFile):
print(j)
if __name__ == '__main__':
if __name__ == "__main__":
load(mido.MidiFile("test.mid"))
# ============================
from typing import Literal
from ..constants import x,y,z
from ..constants import x, y, z
# 不要用 没写完
def delay_to_note_blocks(
baseblock: str = "stone",
position_forward: Literal['x','y','z'] = z,
position_forward: Literal["x", "y", "z"] = z,
):
"""传入音符,生成以音符盒存储的红石音乐
:param:
@ -169,8 +206,7 @@ def delay_to_note_blocks(
log = print
startpos = [0,0,0]
startpos = [0, 0, 0]
# 1拍 x 2.5 rt
for i in notes:
@ -180,7 +216,10 @@ def delay_to_note_blocks(
[startpos[0], startpos[1] + 1, startpos[2]],
form_note_block_in_NBT_struct(height2note[i[0]], instrument),
)
struct.set_block(startpos, Block("universal_minecraft", instuments[i[0]][1]),)
struct.set_block(
startpos,
Block("universal_minecraft", instuments[i[0]][1]),
)
error = False
except ValueError:
log("无法放置音符:" + str(i) + "" + str(startpos))

View File

@ -260,7 +260,9 @@ class MidiConvert:
if r"%%%" in pgs_style:
result.append(
SingleCommand(
'scoreboard objectives add {}PercT dummy "百分比计算"'.format(sbn_pc),
'scoreboard objectives add {}PercT dummy "百分比计算"'.format(
sbn_pc
),
annotation="新增临时百分比变量",
)
)
@ -325,13 +327,17 @@ class MidiConvert:
if r"%%t" in pgs_style:
result.append(
SingleCommand(
'scoreboard objectives add {}TMinT dummy "时间计算:分"'.format(sbn_pc),
'scoreboard objectives add {}TMinT dummy "时间计算:分"'.format(
sbn_pc
),
annotation="新增临时分变量",
)
)
result.append(
SingleCommand(
'scoreboard objectives add {}TSecT dummy "时间计算:秒"'.format(sbn_pc),
'scoreboard objectives add {}TSecT dummy "时间计算:秒"'.format(
sbn_pc
),
annotation="新增临时秒变量",
)
)
@ -589,7 +595,9 @@ class MidiConvert:
)
else:
raise NoteOnOffMismatchError(
"当前的MIDI很可能有损坏之嫌……", msg, "无法在上文中找到与之匹配的音符开音消息。"
"当前的MIDI很可能有损坏之嫌……",
msg,
"无法在上文中找到与之匹配的音符开音消息。",
)
"""整合后的音乐通道格式
@ -663,27 +671,46 @@ class MidiConvert:
mc_pitch,
) = note_to_command_parameters(
note,
(
self.percussion_note_referrence_table
if note.percussive
else self.pitched_note_reference_table,
else self.pitched_note_reference_table
),
(max_volume) if note.track_no == 0 else (max_volume * 0.9),
self.volume_processing_function,
)
this_channel.append(
SingleCommand(
(
self.execute_cmd_head.format(
"@a[scores=({}={})]".format(scoreboard_name, score_now)
.replace("(", r"{")
.replace(")", r"}")
)
+ r"playsound {} @s ^ ^ ^{} {} {}".format(
mc_sound_ID, mc_distance_volume, volume_percentage, mc_pitch
+ r"playsound {} @s ^ ^ ^{} {}".format(
mc_sound_ID, mc_distance_volume, volume_percentage
)
if note.percussive
else r"playsound {} @s ^ ^ ^{} {} {}".format(
mc_sound_ID,
mc_distance_volume,
volume_percentage,
mc_pitch,
)
),
annotation="{}播放{}%{}".format(
annotation=(
"{}播放{}%{}噪音".format(
mctick2timestr(score_now),
max_volume * 100,
mc_sound_ID,
)
if note.percussive
else "{}播放{}%{}乐音".format(
mctick2timestr(score_now),
max_volume * 100,
"{}:{:.2f}".format(mc_sound_ID, mc_pitch),
)
),
),
)
@ -751,29 +778,45 @@ class MidiConvert:
mc_pitch,
) = note_to_command_parameters(
note,
(
self.percussion_note_referrence_table
if note.percussive
else self.pitched_note_reference_table,
else self.pitched_note_reference_table
),
(max_volume) if note.track_no == 0 else (max_volume * 0.9),
self.volume_processing_function,
)
self.music_command_list.append(
SingleCommand(
command=(
self.execute_cmd_head.format(player_selector)
+ r"playsound {} @s ^ ^ ^{} {} {}".format(
+ r"playsound {} @s ^ ^ ^{} {}".format(
mc_sound_ID, mc_distance_volume, volume_percentage
)
if note.percussive
else r"playsound {} @s ^ ^ ^{} {} {}".format(
mc_sound_ID,
mc_distance_volume,
volume_percentage,
mc_pitch,
)
),
tick_delay=tickdelay,
annotation="{}播放{}%{}".format(
annotation=(
"{}播放{}%{}噪音".format(
mctick2timestr(delaytime_now),
max_volume * 100,
mc_sound_ID,
)
if note.percussive
else "{}播放{}%{}乐音".format(
mctick2timestr(delaytime_now),
max_volume * 100,
"{}:{:.2f}".format(mc_sound_ID, mc_pitch),
),
)
),
tick_delay=tickdelay,
),
)
delaytime_previous = delaytime_now

View File

@ -101,6 +101,7 @@ def to_addon_pack_in_score(
+ "=1..}] "
+ scoreboard_name
+ " 1\n",
(
(
"scoreboard players reset @a[scores={"
+ scoreboard_name
@ -110,7 +111,8 @@ def to_addon_pack_in_score(
+ f" {scoreboard_name}\n"
)
if auto_reset
else "",
else ""
),
f"function mscplay/progressShow\n" if data_cfg.progressbar_style else "",
)
)

View File

@ -150,6 +150,7 @@ def commands_to_BDX_bytes(
for command in commands_list:
_bytes += form_command_block_in_BDX_bytes(
command.command_text,
(
(1 if y_forward else 0)
if (
((now_y != 0) and (not y_forward))
@ -162,6 +163,7 @@ def commands_to_BDX_bytes(
or (z_forward and (now_z != _sideLength - 1))
)
else 5
)
),
impluse=2,
condition=command.conditional,

View File

@ -85,13 +85,22 @@ class ConvertConfig:
"""进度条样式"""
return
elif isinstance(progressbar, tuple):
if isinstance(progressbar[0],str) and isinstance(progressbar[1], tuple):
if isinstance(progressbar[1][0], str) and isinstance(progressbar[1][1], str):
self.progressbar_style = ProgressBarStyle(progressbar[0],progressbar[1][0],progressbar[1][1])
if isinstance(progressbar[0], str) and isinstance(
progressbar[1], tuple
):
if isinstance(progressbar[1][0], str) and isinstance(
progressbar[1][1], str
):
self.progressbar_style = ProgressBarStyle(
progressbar[0], progressbar[1][0], progressbar[1][1]
)
return
if not ignore_progressbar_param_error:
raise TypeError("参数 {} 的类型 {} 与所需类型 Union[bool, Tuple[str, Tuple[str, str]], ProgressBarStyle] 不符。".format(progressbar,type(progressbar)))
raise TypeError(
"参数 {} 的类型 {} 与所需类型 Union[bool, Tuple[str, Tuple[str, str]], ProgressBarStyle] 不符。".format(
progressbar, type(progressbar)
)
)
self.progressbar_style = None
"""进度条样式组"""

View File

@ -189,9 +189,11 @@ def form_command_block_in_NBT_struct(
return Block(
"minecraft",
(
"command_block"
if impluse == 0
else ("repeating_command_block" if impluse == 1 else "chain_command_block"),
else ("repeating_command_block" if impluse == 1 else "chain_command_block")
),
states={"conditional_bit": condition, "facing_direction": particularValue},
extra_data={
"block_entity_data": {
@ -257,7 +259,8 @@ def commands_to_structure(
form_command_block_in_NBT_struct(
command=command.command_text,
coordinate=coordinate,
particularValue=(1 if y_forward else 0)
particularValue=(
(1 if y_forward else 0)
if (
((now_y != 0) and (not y_forward))
or (y_forward and (now_y != (max_height - 1)))
@ -269,6 +272,7 @@ def commands_to_structure(
or (z_forward and (now_z != _sideLength - 1))
)
else 5
)
),
impluse=2,
condition=False,
@ -357,20 +361,16 @@ def commands_to_redstone_delay_structure(
for cmd in commands:
# print("\r 正在进行处理:",end="")
if cmd.delay > 2:
a_max = max(a,a_max)
a_max = max(a, a_max)
total_cmd += (a := 1)
else:
a += 1
struct = Structure(
size=(
round(delay_length / 2 + total_cmd)
if extensioon_direction == x
else a_max,
round(delay_length / 2 + total_cmd) if extensioon_direction == x else a_max,
3,
round(delay_length / 2 + total_cmd)
if extensioon_direction == z
else a_max,
round(delay_length / 2 + total_cmd) if extensioon_direction == z else a_max,
),
fill=Block("minecraft", "air", compability_version=compability_version_),
compability_version=compability_version_,

View File

@ -154,9 +154,13 @@ class ObsoleteMidiConvert(MidiConvert):
)
maxscore = max(maxscore, nowscore)
if msg.channel == 9:
soundID, _X = inst_to_sould_with_deviation(instrumentID,MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE)
soundID, _X = inst_to_sould_with_deviation(
instrumentID, MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE
)
else:
soundID, _X = inst_to_sould_with_deviation(instrumentID,MM_CLASSIC_PITCHED_INSTRUMENT_TABLE)
soundID, _X = inst_to_sould_with_deviation(
instrumentID, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE
)
singleTrack.append(
"execute @a[scores={"
@ -214,9 +218,13 @@ class ObsoleteMidiConvert(MidiConvert):
)
maxscore = max(maxscore, nowscore)
if msg.channel == 9:
soundID, _X = inst_to_sould_with_deviation(instrumentID,MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE)
soundID, _X = inst_to_sould_with_deviation(
instrumentID, MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE
)
else:
soundID, _X = inst_to_sould_with_deviation(instrumentID,MM_CLASSIC_PITCHED_INSTRUMENT_TABLE)
soundID, _X = inst_to_sould_with_deviation(
instrumentID, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE
)
singleTrack.append(
"execute @a[scores={"
+ str(scoreboardname)
@ -277,9 +285,13 @@ class ObsoleteMidiConvert(MidiConvert):
elif msg[0] == "NoteS":
soundID, _X = (
inst_to_sould_with_deviation(msg[1],MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE)
inst_to_sould_with_deviation(
msg[1], MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE
)
if SpecialBits
else inst_to_sould_with_deviation(InstID,MM_CLASSIC_PITCHED_INSTRUMENT_TABLE)
else inst_to_sould_with_deviation(
InstID, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE
)
)
score_now = round(msg[-1] / float(speed) / 50)
maxScore = max(maxScore, score_now)
@ -345,9 +357,13 @@ class ObsoleteMidiConvert(MidiConvert):
)
if msg.channel == 9:
soundID, _X = inst_to_sould_with_deviation(instrumentID,MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE)
soundID, _X = inst_to_sould_with_deviation(
instrumentID, MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE
)
else:
soundID, _X = inst_to_sould_with_deviation(instrumentID,MM_CLASSIC_PITCHED_INSTRUMENT_TABLE)
soundID, _X = inst_to_sould_with_deviation(
instrumentID, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE
)
try:
tracks[now_tick].append(
self.execute_cmd_head.format(player)
@ -421,9 +437,13 @@ class ObsoleteMidiConvert(MidiConvert):
elif msg[0] == "NoteS":
soundID, _X = (
inst_to_sould_with_deviation(msg[1],MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE)
inst_to_sould_with_deviation(
msg[1], MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE
)
if SpecialBits
else inst_to_sould_with_deviation(InstID,MM_CLASSIC_PITCHED_INSTRUMENT_TABLE)
else inst_to_sould_with_deviation(
InstID, MM_CLASSIC_PITCHED_INSTRUMENT_TABLE
)
)
score_now = round(msg[-1] / float(speed) / 50)

View File

@ -377,7 +377,7 @@ class ProgressBarStyle:
self.played_style = value
def copy(self):
dst = ProgressBarStyle(self.base_style,self.to_play_style,self.played_style)
dst = ProgressBarStyle(self.base_style, self.to_play_style, self.played_style)
return dst

View File

@ -16,7 +16,19 @@ Terms & Conditions: License.md in the root directory
# Email TriM-Organization@hotmail.com
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
from typing import Any, Dict, List, Literal, Optional, Tuple, Union, Iterable, Sequence, Mapping, Callable
from typing import (
Any,
Dict,
List,
Literal,
Optional,
Tuple,
Union,
Iterable,
Sequence,
Mapping,
Callable,
)
MidiNoteNameTableType = Mapping[int, Tuple[str, ...]]
@ -32,8 +44,6 @@ Midi乐器对照表类型
FittingFunctionType = Callable[[float], float]
ChannelType = Dict[
int,
Dict[

View File

@ -21,7 +21,16 @@ import random
from .constants import MM_INSTRUMENT_DEVIATION_TABLE, MC_INSTRUMENT_BLOCKS_TABLE
from .subclass import SingleNote
from .types import Any, Dict, Tuple, Optional, Callable, Literal, Union, MidiInstrumentTableType
from .types import (
Any,
Dict,
Tuple,
Optional,
Callable,
Literal,
Union,
MidiInstrumentTableType,
)
def mctick2timestr(mc_tick: int) -> str:
@ -77,9 +86,11 @@ def inst_to_sould_with_deviation(
instrumentID,
(
default_instrument,
(
default_deviation
if default_deviation
else MM_INSTRUMENT_DEVIATION_TABLE.get(default_instrument, -1),
else MM_INSTRUMENT_DEVIATION_TABLE.get(default_instrument, -1)
),
),
)
@ -136,7 +147,12 @@ def note_to_command_parameters(
reference_table: MidiInstrumentTableType,
volume_percentage: float = 1,
volume_processing_method: Callable[[float], float] = natural_curve,
) -> Tuple[str, float, float, Union[float, Literal[None]],]:
) -> Tuple[
str,
float,
float,
Union[float, Literal[None]],
]:
"""
将音符转为播放的指令
:param note_:int 音符对象

View File

@ -50,7 +50,7 @@
pip install --upgrade -i https://pypi.python.org/simple Musicreater
```
- 克隆仓库并安装**不推荐**
- 克隆仓库并安装最新版本但**不推荐**
```bash
git clone https://gitee.com/TriM-Organization/Musicreater.git
cd Musicreater

View File

@ -49,7 +49,7 @@ Welcome to join our QQ group: [861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr
pip install -i https://pypi.python.org/simple Musicreater --upgrade
```
- Clone repo and Install (**NOT RECOMMANDED**):
- Clone repo and Install (Latest but **NOT RECOMMANDED**):
```bash
git clone https://github.com/TriM-Organization/Musicreater.git
cd Musicreater
@ -75,7 +75,7 @@ Commands such as `python`、`pip` could be changed to some like `python3` or `pi
**Touch (偷吃不是Touch)**: A man who is used to use command(s) in _Minecraft: Bedrock Edition_, who supported us of debugging and testing program and algorithm
## Thanks 🙏
## Acknowledgements 🙏
This list is not in any order.