修复音轨删除不彻底、预览音量未能调的问题、完整支持小号音色

This commit is contained in:
Eilles
2026-07-08 06:22:22 +08:00
parent 026c529182
commit 2c6e831533
10 changed files with 140 additions and 39 deletions
@@ -25,8 +25,8 @@ from .constants import (
MIDI_DEFAULT_VOLUME_VALUE,
MM_CLASSIC_PITCHED_INSTRUMENT_TABLE,
MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE,
MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
MM_DISLINK_PITCHED_INSTRUMENT_TABLE,
MM_DISLINK_PERCUSSION_INSTRUMENT_TABLE,
MM_NBS_PITCHED_INSTRUMENT_TABLE,
@@ -55,8 +55,8 @@ __all__ = [
# Midi 与 游戏内容 的对照表
"MM_CLASSIC_PITCHED_INSTRUMENT_TABLE",
"MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE",
"MM_TOUCH_PITCHED_INSTRUMENT_TABLE",
"MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE",
"MM_DEFAULT_PITCHED_INSTRUMENT_TABLE",
"MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE",
"MM_DISLINK_PITCHED_INSTRUMENT_TABLE",
"MM_DISLINK_PERCUSSION_INSTRUMENT_TABLE",
"MM_NBS_PITCHED_INSTRUMENT_TABLE",
@@ -19,7 +19,6 @@ Terms & Conditions: License.md in the root directory
from typing import Dict, List, Tuple
# Midi用对照表
MIDI_DEFAULT_VOLUME_VALUE: int = (
@@ -403,6 +402,34 @@ MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE: Dict[int, str] = {
}
"""“偷吃”打击乐器对照表"""
# 金羿音色对照表,在偷吃的表的基础上修改而来
MM_EILLES_PITCHED_INSTRUMENT_TABLE: Dict[int, str] = (
MM_TOUCH_PITCHED_INSTRUMENT_TABLE
| {
57: "note.trumpet",
58: "note.trumpet_exposed",
59: "note.trumpet_weathered",
61: "note.trumpet",
62: "note.trumpet_oxidized",
63: "note.trumpet_weathered",
64: "note.trumpet_oxidized",
65: "note.trumpet",
66: "note.trumpet_exposed",
67: "note.trumpet_weathered",
68: "note.trumpet_oxidized",
69: "note.trumpet",
70: "note.trumpet",
71: "note.trumpet_exposed",
72: "note.banjo",
}
)
"""“金羿”乐音乐器对照表"""
MM_EILLES_PERCUSSION_INSTRUMENT_TABLE: Dict[int, str] = {}
"""“金羿”打击乐器对照表"""
# Dislink “断联” 音色对照表
# https://github.com/Dislink/midi2bdx/blob/main/index.html
@@ -795,3 +822,10 @@ MM_NBS_PERCUSSION_INSTRUMENT_TABLE: Dict[int, str] = {
87: "note.basedrum",
}
"""“NBS”打击乐器对照表"""
# 默认音色对照表
MM_DEFAULT_PITCHED_INSTRUMENT_TABLE = MM_EILLES_PITCHED_INSTRUMENT_TABLE
"""默认的乐音乐器音色对照表"""
MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE
"""默认的打击乐器音色对照表"""
@@ -37,8 +37,8 @@ from Musicreater._utils import enumerated_stuffcopy_dictionary
from .constants import (
MIDI_DEFAULT_PROGRAM_VALUE,
MIDI_DEFAULT_VOLUME_VALUE,
MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
)
from .exceptions import (
NoteOnOffMismatchError,
@@ -89,12 +89,12 @@ class MidiImportConfig(PluginConfig):
self.pitched_note_reference_table = (
self.pitched_note_reference_table
if self.pitched_note_reference_table
else MM_TOUCH_PITCHED_INSTRUMENT_TABLE
else MM_DEFAULT_PITCHED_INSTRUMENT_TABLE
)
self.percussion_note_reference_table = (
self.percussion_note_reference_table
if self.percussion_note_reference_table
else MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE
else MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE
)
self.note_replacement_table = (
self.note_replacement_table if self.note_replacement_table else {}
@@ -68,7 +68,7 @@ class PcmConversionConfig(PluginConfig):
- 1 拉伸至 mc 播放器定义(我的世界效果)
- 2 根据 midi 音符长度裁剪
- 3 混音预留
- 4 匹配 midi 音符长度(最佳效果)
- 4 匹配 midi 音符长度
"""
overlay_mode: Literal[1, 2] = 1
"""
@@ -48,6 +48,12 @@ from Musicreater.constants import MM_INSTRUMENT_DEVIATION_TABLE
class MusicPreview:
# 当前的资源存储方法过于鸡肋
# 应当依托于 SingleMusic 和 SingleTrack 提供的 extra_info 参数,得到更优的解法
# 或者更理想的情况是把当前插件作为一个 Service 插件,然后通过 serve API 进行调用
# 但是还没设计好,等未来看看
"""
原始资源存储规范:
Dict[str"ID1": Dict[str"SoundID": ndarray[]]]
@@ -96,7 +102,11 @@ class MusicPreview:
self.output_sample_rate = sample_rate
self.get_value_method = value_get_method
self.resources_path = resource_folder
self.pitch_precision_decimals = pitch_accuracy_decimals
# 在当前算法下,小数点精度必须为 0
# 此处 TODO,需待旧梦来完善
self.pitch_precision_decimals = 0
self.pitch_deviation = music_deviation
@@ -343,12 +353,21 @@ class MusicPreview:
)
if not note.percussive:
overlay(
self.res_data[note.instrument][accurate_pitch] * note.volume / 127,
self.res_data[note.instrument][accurate_pitch]
* note.volume
/ (note.position.sound_distance + 0.5)
/ 127,
note.start_tick,
)
# 上述参数的原顺序应为
# x * (音量 / 127) * (1 / (距离 + 0.5))
# 乘法优先是为了提高计算精度,小的数的除法优先同理
else:
overlay(
self.res_data[note.instrument][accurate_pitch] * note.volume / 127,
self.res_data[note.instrument][accurate_pitch]
* note.volume
/ (note.position.sound_distance + 0.5)
/ 127,
note.start_tick,
)
+33 -5
View File
@@ -254,10 +254,10 @@ MIDI_PITCHED_NOTE_NAME_TABLE: Dict[int, Tuple[str, str]] = {
62: ("铜管乐组", "Brass Section"),
63: ("合成铜管 1", "Synth Brass 1"),
64: ("合成铜管 2", "Synth Brass 2"),
65: ("高音萨克斯", "Soprano Sax"),
66: ("中音萨克斯", "Alto Sax"),
67: ("次中音萨克斯", "Tenor Sax"),
68: ("上低音萨克斯", "Baritone Sax"),
65: ("高音萨克斯", "Soprano Sax"),
66: ("中音萨克斯", "Alto Sax"),
67: ("次中音萨克斯", "Tenor Sax"),
68: ("上低音萨克斯", "Baritone Sax"),
69: ("双簧管", "Oboe"),
70: ("英国管", "English Horn"),
71: ("大管(巴松管)", "Bassoon"),
@@ -400,6 +400,10 @@ MC_PITCHED_INSTRUMENT_LIST: List[str] = [
"note.didgeridoo",
"note.bit",
"note.cow_bell",
"note.trumpet",
"note.trumpet_exposed",
"note.trumpet_weathered",
"note.trumpet_oxidized",
]
"""乐音乐器列表"""
@@ -422,6 +426,10 @@ MC_INSTRUMENT_BLOCKS_TABLE: Dict[str, Tuple[str, ...]] = {
"note.pling": ("glowstone",),
"note.bassattack": ("stone",), # 无法找到此音效
"note.harp": ("dirt",),
"note.trumpet": ("waxed_copper",),
"note.trumpet_exposed": ("waxed_exposed_copper",),
"note.trumpet_weathered": ("waxed_weathered_copper",),
"note.trumpet_oxidized": ("waxed_oxidized_copper",),
# 呃……
"firework.blast": ("sandstone",),
"firework.twinkle": ("red_sandstone",),
@@ -430,6 +438,14 @@ MC_INSTRUMENT_BLOCKS_TABLE: Dict[str, Tuple[str, ...]] = {
}
"""MC乐器对音符盒下垫方块对照表"""
MC_EILLES_RT261_INSTRUMENT_REPLACE_TABLE: Dict[str, str] = {
"note.trumpet": "note.flute",
"note.trumpet_exposed": "note.flute",
"note.trumpet_weathered": "note.banjo",
"note.trumpet_oxidized": "note.banjo",
}
MC_EILLES_RTJE12_INSTRUMENT_REPLACE_TABLE: Dict[str, str] = {
"note.iron_xylophone": "note.xylophone",
"note.cow_bell": "note.xylophone",
@@ -457,6 +473,7 @@ MC_EILLES_RTBETA_INSTRUMENT_REPLACE_TABLE: Dict[str, str] = {
}
"""在 Minecraft JE Beta1.2 / BE 0.13.0 ~ JE 1.12 / BE 1.13.0 的版本中,部分乐器是没有的,这是金羿的乐器替换表"""
# Midi对MC通用对照表
MM_INSTRUMENT_RANGE_TABLE: Dict[str, Tuple[Tuple[int, int], int]] = {
@@ -481,8 +498,15 @@ MM_INSTRUMENT_RANGE_TABLE: Dict[str, Tuple[Tuple[int, int], int]] = {
"firework.twinkle": ((-1, 128), 0),
"fire.ignite": ((-1, 128), 0),
"note.cow_bell": ((54, 78), 66),
"note.trumpet": ((42, 66), 54),
"note.trumpet_exposed": ((42, 66), 54),
"note.trumpet_weathered": ((30, 54), 42),
"note.trumpet_oxidized": ((30, 54), 42),
}
"""不同乐器的音域偏离对照表"""
"""
不同乐器的音域偏离对照表
元组里的是范围,后面的整数是中央 C 所在
"""
MM_INSTRUMENT_DEVIATION_TABLE: Dict[str, int] = {
"note.harp": 6,
@@ -505,6 +529,10 @@ MM_INSTRUMENT_DEVIATION_TABLE: Dict[str, int] = {
"firework.twinkle": 0,
"fire.ignite": 0,
"note.cow_bell": 6,
"note.trumpet": 6,
"note.trumpet_exposed": 6,
"note.trumpet_weathered": -6,
"note.trumpet_oxidized": -6,
}
"""
不同乐器的音调偏离对照表
+23 -3
View File
@@ -93,6 +93,20 @@ class SoundAtmos:
)
"""声源距离"""
def set_azimuth(self, azimuth: Tuple[float, float]) -> None:
"""设置声源方位"""
self.sound_azimuth = (azimuth[0] % 360, azimuth[1] % 360)
def set_distance(self, distance: float) -> None:
"""设置声源距离"""
self.sound_distance = (
(16 if distance > 16 else (distance if distance >= 0 else 0.01))
if distance is not None
else 0.01
)
@classmethod
def from_displacement(
cls,
@@ -609,9 +623,15 @@ class SingleTrack(List[SingleNote]):
for curve in self.argument_curves.values():
if curve is not None:
curve.delete(start_time, end_time)
for i, note in enumerate(self):
if start_time <= note.precise_start_time <= end_time:
del self[i]
for i, j in enumerate(
[
i
for i, x in enumerate(self)
if start_time <= x.precise_start_time <= end_time
]
):
del self[j - i]
def get(self, time: int) -> Generator[SingleNote, None, None]:
"""通过确切的开始时间来获取音符"""
+4 -4
View File
@@ -22,8 +22,8 @@ from .old_exceptions import *
from .old_main import (
MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE,
MM_CLASSIC_PITCHED_INSTRUMENT_TABLE,
MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
MidiConvert,
mido,
)
@@ -140,8 +140,8 @@ class FutureMidiConvertKamiRES(MidiConvert):
default_program_value: int = -1,
default_volume_value: int = 64,
default_tempo_value: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
pitched_note_rtable: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_rtable: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
pitched_note_rtable: MidiInstrumentTableType = MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
percussion_note_rtable: MidiInstrumentTableType = MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
vol_processing_function: FittingFunctionType = velocity_2_distance_natural,
pan_processing_function: FittingFunctionType = panning_2_rotation_trigonometric,
note_rtable_replacement: Dict[str, str] = {},
+4 -4
View File
@@ -65,8 +65,8 @@ __all__ = [
"MM_INSTRUMENT_DEVIATION_TABLE",
"MM_CLASSIC_PITCHED_INSTRUMENT_TABLE",
"MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE",
"MM_TOUCH_PITCHED_INSTRUMENT_TABLE",
"MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE",
"MM_DEFAULT_PITCHED_INSTRUMENT_TABLE",
"MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE",
"MM_DISLINK_PITCHED_INSTRUMENT_TABLE",
"MM_DISLINK_PERCUSSION_INSTRUMENT_TABLE",
"MM_NBS_PITCHED_INSTRUMENT_TABLE",
@@ -122,8 +122,8 @@ from Musicreater.builtin_plugins.midi_read import (
panning_2_rotation_trigonometric,
MM_CLASSIC_PITCHED_INSTRUMENT_TABLE,
MM_CLASSIC_PERCUSSION_INSTRUMENT_TABLE,
MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
MM_DISLINK_PITCHED_INSTRUMENT_TABLE,
MM_DISLINK_PERCUSSION_INSTRUMENT_TABLE,
MM_NBS_PITCHED_INSTRUMENT_TABLE,
+10 -10
View File
@@ -48,8 +48,8 @@ from Musicreater.exceptions import (
from Musicreater.builtin_plugins.midi_read.constants import (
MIDI_DEFAULT_PROGRAM_VALUE,
MIDI_DEFAULT_VOLUME_VALUE,
MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
)
from Musicreater.builtin_plugins.midi_read.exceptions import (
NoteOnOffMismatchError,
@@ -198,8 +198,8 @@ class MusicSequence:
default_midi_program: int = MIDI_DEFAULT_PROGRAM_VALUE,
default_midi_volume: int = MIDI_DEFAULT_VOLUME_VALUE,
default_tempo: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
pitched_note_referance_table: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_referance_table: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
pitched_note_referance_table: MidiInstrumentTableType = MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
percussion_note_referance_table: MidiInstrumentTableType = MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
minimum_vol: float = 0.1,
volume_processing_function: FittingFunctionType = volume_2_distance_natural,
panning_processing_function: FittingFunctionType = panning_2_rotation_linear,
@@ -869,8 +869,8 @@ class MusicSequence:
default_program_value: int = MIDI_DEFAULT_PROGRAM_VALUE,
default_volume_value: int = MIDI_DEFAULT_VOLUME_VALUE,
default_tempo_value: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
pitched_note_rtable: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_rtable: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
pitched_note_rtable: MidiInstrumentTableType = MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
percussion_note_rtable: MidiInstrumentTableType = MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
vol_processing_function: FittingFunctionType = volume_2_distance_natural,
pan_processing_function: FittingFunctionType = panning_2_rotation_trigonometric,
note_rtable_replacement: Dict[str, str] = {},
@@ -1146,8 +1146,8 @@ class MidiConvert(MusicSequence):
default_midi_program_value: int = MIDI_DEFAULT_PROGRAM_VALUE,
default_midi_volume_value: int = MIDI_DEFAULT_VOLUME_VALUE,
default_tempo_value: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
pitched_note_rtable: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_rtable: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
pitched_note_rtable: MidiInstrumentTableType = MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
percussion_note_rtable: MidiInstrumentTableType = MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
enable_old_exe_format: bool = False,
minimum_volume: float = 0.1,
vol_processing_function: FittingFunctionType = volume_2_distance_natural,
@@ -1229,8 +1229,8 @@ class MidiConvert(MusicSequence):
default_midi_program: int = MIDI_DEFAULT_PROGRAM_VALUE,
default_midi_volume: int = MIDI_DEFAULT_VOLUME_VALUE,
default_tempo: int = mido.midifiles.midifiles.DEFAULT_TEMPO,
pitched_note_table: MidiInstrumentTableType = MM_TOUCH_PITCHED_INSTRUMENT_TABLE,
percussion_note_table: MidiInstrumentTableType = MM_TOUCH_PERCUSSION_INSTRUMENT_TABLE,
pitched_note_table: MidiInstrumentTableType = MM_DEFAULT_PITCHED_INSTRUMENT_TABLE,
percussion_note_table: MidiInstrumentTableType = MM_DEFAULT_PERCUSSION_INSTRUMENT_TABLE,
old_exe_format: bool = False,
min_volume: float = 0.1,
vol_processing_func: FittingFunctionType = volume_2_distance_natural,