更丰富的音符附加信息支持

This commit is contained in:
2025-08-20 18:57:21 +08:00
parent 774f78359c
commit b796a363d8
6 changed files with 102 additions and 42 deletions

View File

@ -22,8 +22,8 @@ The Licensor of Musicreater("this project") is Eilles, bgArray.
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
__version__ = "2.4.1"
__vername__ = "Midi 歌词支持,文档格式更新"
__version__ = "2.4.2"
__vername__ = "音符附加信息升级"
__author__ = (
("金羿", "Eilles"),
("诸葛亮与八卦阵", "bgArray"),

View File

@ -79,7 +79,7 @@ class FutureMidiConvertLyricSupport(MidiConvert):
relative_coordinates,
volume_percentage,
mc_pitch,
) = minenote_to_command_paramaters(
) = minenote_to_command_parameters(
note,
pitch_deviation=self.music_deviation,
)
@ -367,7 +367,7 @@ class FutureMidiConvertKamiRES(MidiConvert):
relative_coordinates,
volume_percentage,
mc_pitch,
) = minenote_to_command_paramaters(
) = minenote_to_command_parameters(
note,
pitch_deviation=self.music_deviation,
)
@ -446,7 +446,7 @@ class FutureMidiConvertKamiRES(MidiConvert):
relative_coordinates,
volume_percentage,
mc_pitch,
) = minenote_to_command_paramaters(
) = minenote_to_command_parameters(
note,
pitch_deviation=self.music_deviation,
)
@ -783,7 +783,7 @@ class FutureMidiConvertJavaE(MidiConvert):
relative_coordinates,
volume_percentage,
mc_pitch,
) = minenote_to_command_paramaters(
) = minenote_to_command_parameters(
note,
pitch_deviation=self.music_deviation,
)
@ -874,8 +874,14 @@ class FutureMidiConvertM4(MidiConvert):
totalCount = int(_note.duration / _apply_time_division)
if totalCount == 0:
print(_note.extra_info)
if (
totalCount == 0
or (_note.get_info("PITCH") > 2 and _note.sound_name != "note.bass")
):
from rich import print as prt
prt("[INFO] 音符太短或音调太高,无法生成插值")
prt(_note)
return [
_note,
]
@ -883,18 +889,24 @@ class FutureMidiConvertM4(MidiConvert):
result: List[MineNote] = []
_slide = _note.duration / totalCount
_distance_slide = 20 / totalCount
for _i in range(totalCount):
result.append(
MineNote(
mc_sound_name=_note.sound_name,
midi_pitch=_note.note_pitch,
midi_velocity=_note.velocity,
start_time=int(
_note.start_tick + _i * (_note.duration / totalCount)
),
last_time=int(_note.duration / totalCount),
start_time=int(_note.start_tick + _i * _slide),
last_time=int(_slide),
# track_number=_note.track_no,
is_percussion=_note.percussive,
distance=_note.sound_distance + _i * _distance_slide,
azimuth=(
_note.sound_azimuth[0],
_note.sound_azimuth[1] + 5 * random.random(),
),
extra_information=_note.extra_info,
)
# (
@ -931,14 +943,17 @@ class FutureMidiConvertM4(MidiConvert):
for channel in self.channels.values():
for note in channel:
note.set_info(
minenote_to_command_paramaters(
["NOTE_ID", "COODINATES", "VOLUME", "PITCH"],
minenote_to_command_parameters(
note,
pitch_deviation=self.music_deviation,
)
),
)
if not note.percussive:
notes_list.extend(self._linear_note(note, 1 * note.extra_info[3]))
notes_list.extend(
self._linear_note(note, 2 * note.get_info("PITCH"))
)
else:
notes_list.append(note)
@ -954,12 +969,17 @@ class FutureMidiConvertM4(MidiConvert):
else:
max_multi = max(max_multi, multi)
multi = 0
(
mc_sound_ID,
relative_coordinates,
volume_percentage,
mc_pitch,
) = note.extra_info
) = minenote_to_command_parameters(
note,
pitch_deviation=self.music_deviation,
)
self.music_command_list.append(
MineCommand(
command=(

View File

@ -112,7 +112,7 @@ class MusicSequence:
"""
音符序列类
Paramaters
Parameters
==========
name_of_music: str
乐曲名称
@ -175,7 +175,7 @@ class MusicSequence:
"""
自mido对象导入一个音符序列类
Paramaters
Parameters
==========
mido_file: mido.MidiFile
需要处理的midi对象
@ -247,7 +247,7 @@ class MusicSequence:
"""
从字节码导入音乐序列,目前支持 MSQ 第二、三、四版和 FSQ 第一、二版。
Paramaters
Parameters
==========
bytes_buffer_in: bytes
字节码
@ -1588,7 +1588,7 @@ class MidiConvert(MusicSequence):
relative_coordinates,
volume_percentage,
mc_pitch,
) = minenote_to_command_paramaters(
) = minenote_to_command_parameters(
note,
pitch_deviation=self.music_deviation,
)
@ -1672,7 +1672,7 @@ class MidiConvert(MusicSequence):
relative_coordinates,
volume_percentage,
mc_pitch,
) = minenote_to_command_paramaters(
) = minenote_to_command_parameters(
note,
pitch_deviation=self.music_deviation,
)
@ -1758,7 +1758,7 @@ class MidiConvert(MusicSequence):
relative_coordinates,
volume_percentage,
mc_pitch,
) = minenote_to_command_paramaters(
) = minenote_to_command_parameters(
note,
pitch_deviation=self.music_deviation,
)

View File

@ -18,7 +18,7 @@ Terms & Conditions: License.md in the root directory
from math import sin, cos, asin, radians, degrees, sqrt, atan
from dataclasses import dataclass
from typing import Optional, Any, List, Tuple, Union, Dict
from typing import Optional, Any, List, Tuple, Union, Dict, Sequence
from .constants import MC_PITCHED_INSTRUMENT_LIST
@ -54,7 +54,7 @@ class MineNote:
sound_azimuth: Tuple[float, float]
"""声源方位 角度"""
extra_info: Any
extra_info: Dict[str, Any]
"""你觉得放什么好?"""
def __init__(
@ -68,7 +68,7 @@ class MineNote:
is_percussion: Optional[bool] = None,
distance: Optional[float] = None,
azimuth: Optional[Tuple[float, float]] = None,
extra_information: Optional[Dict[str, Any]] = None,
extra_information: Dict[str, Any] = {},
):
"""
用于存储单个音符的类
@ -98,7 +98,7 @@ class MineNote:
此参数为tuple包含两个元素分别表示
`rV` 发声源在竖直(上下)轴上,从玩家视角正前方开始,向顺时针旋转的角度
`rH` 发声源在水平(左右)轴上,从玩家视角正前方开始,向上(到达玩家正上方顶点后变为向下,以此类推的旋转)旋转的角度
extra_information: Any
extra_information: Dict[str, Any]
附加信息,尽量存储为字典
Returns
@ -136,7 +136,7 @@ class MineNote:
)
"""声源距离"""
self.extra_info = extra_information
self.extra_info = extra_information if extra_information else {}
@classmethod
def from_traditional(
@ -210,7 +210,15 @@ class MineNote:
is_percussion=is_percussion,
distance=r,
azimuth=(alpha_v, beta_h),
extra_information=extra_information,
extra_information=(
(
extra_information
if isinstance(extra_information, dict)
else {"EXTRA_INFO": extra_information}
)
if extra_information
else {}
),
)
@property
@ -225,7 +233,7 @@ class MineNote:
@classmethod
def decode(cls, code_buffer: bytes, is_high_time_precision: bool = True):
"""自字节码析出MineNote类"""
"""自字节码析出 MineNote """
group_1 = int.from_bytes(code_buffer[:6], "big")
percussive_ = bool(group_1 & 0b1)
duration_ = (group_1 := group_1 >> 1) & 0b11111111111111111
@ -375,9 +383,34 @@ class MineNote:
)
)
def set_info(self, sth: Any):
def set_info(self, key: Union[str, Sequence[str]], value: Any):
"""设置附加信息"""
self.extra_info = sth
if isinstance(key, str):
self.extra_info[key] = value
elif (
isinstance(key, Sequence)
and isinstance(value, Sequence)
and (k := len(key)) == len(value)
):
for i in range(k):
self.extra_info[key[i]] = value[i]
else:
raise TypeError("参数类型错误")
def get_info(self, key: str) -> Any:
"""获取附加信息"""
if key in self.extra_info:
return self.extra_info[key]
elif "EXTRA_INFO" in self.extra_info:
if (
isinstance(self.extra_info["EXTRA_INFO"], dict)
and key in self.extra_info["EXTRA_INFO"]
):
return self.extra_info["EXTRA_INFO"].get(key)
else:
return self.extra_info["EXTRA_INFO"]
else:
return None
def stringize(
self, include_displacement: bool = False, include_extra_data: bool = False

View File

@ -49,7 +49,7 @@ ChannelType = Dict[
],
]
"""
以字典所标记的道信息类型(已弃用)
以字典所标记的道信息类型(已弃用)
Dict[int,Dict[int,List[Union[Tuple[Literal["PgmC"], int, int],Tuple[Literal["NoteS"], int, int, int],Tuple[Literal["NoteE"], int, int],]],],]
"""
@ -60,7 +60,14 @@ MineNoteChannelType = Mapping[
List[MineNote,],
]
"""
我的世界道信息类型
我的世界道信息类型
Dict[int,Dict[int,List[MineNote,],],]
"""
MineNoteTrackType = Mapping[
int,
List[MineNote,],
]

View File

@ -212,8 +212,8 @@ def panning_2_rotation_trigonometric(pan_: float) -> float:
return math.degrees(math.acos((64 - pan_) / 63)) - 90
def minenote_to_command_paramaters(
note_: MineNote,
def minenote_to_command_parameters(
mine_note: MineNote,
pitch_deviation: float = 0,
) -> Tuple[
str,
@ -226,7 +226,7 @@ def minenote_to_command_paramaters(
Parameters
------------
note_: MineNote
mine_note: MineNote
音符对象
deviation: float
音调偏移量
@ -238,19 +238,19 @@ def minenote_to_command_paramaters(
"""
return (
note_.sound_name,
note_.position_displacement,
note_.velocity / 127,
mine_note.sound_name,
mine_note.position_displacement,
mine_note.velocity / 127,
(
None
if note_.percussive
if mine_note.percussive
else (
2
** (
(
note_.note_pitch
mine_note.note_pitch
- 60
- MM_INSTRUMENT_DEVIATION_TABLE.get(note_.sound_name, 6)
- MM_INSTRUMENT_DEVIATION_TABLE.get(mine_note.sound_name, 6)
+ pitch_deviation
)
/ 12