From 2c6e83153313916e80a30e1240f98c87013b64cd Mon Sep 17 00:00:00 2001 From: Eilles Date: Wed, 8 Jul 2026 06:22:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9F=B3=E8=BD=A8=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E4=B8=8D=E5=BD=BB=E5=BA=95=E3=80=81=E9=A2=84=E8=A7=88?= =?UTF-8?q?=E9=9F=B3=E9=87=8F=E6=9C=AA=E8=83=BD=E8=B0=83=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=81=E5=AE=8C=E6=95=B4=E6=94=AF=E6=8C=81=E5=B0=8F?= =?UTF-8?q?=E5=8F=B7=E9=9F=B3=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builtin_plugins/midi_read/__init__.py | 8 ++-- .../builtin_plugins/midi_read/constants.py | 36 +++++++++++++++++- Musicreater/builtin_plugins/midi_read/main.py | 8 ++-- .../builtin_plugins/music_preview/__init__.py | 2 +- .../builtin_plugins/music_preview/main.py | 25 ++++++++++-- Musicreater/constants.py | 38 ++++++++++++++++--- Musicreater/data.py | 26 +++++++++++-- old-things/Musicreater/experiment.py | 8 ++-- old-things/Musicreater/old_init.py | 8 ++-- old-things/Musicreater/old_main.py | 20 +++++----- 10 files changed, 140 insertions(+), 39 deletions(-) diff --git a/Musicreater/builtin_plugins/midi_read/__init__.py b/Musicreater/builtin_plugins/midi_read/__init__.py index 557cc2f..847ad50 100644 --- a/Musicreater/builtin_plugins/midi_read/__init__.py +++ b/Musicreater/builtin_plugins/midi_read/__init__.py @@ -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", diff --git a/Musicreater/builtin_plugins/midi_read/constants.py b/Musicreater/builtin_plugins/midi_read/constants.py index e633003..900e9d3 100644 --- a/Musicreater/builtin_plugins/midi_read/constants.py +++ b/Musicreater/builtin_plugins/midi_read/constants.py @@ -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 +"""默认的打击乐器音色对照表""" diff --git a/Musicreater/builtin_plugins/midi_read/main.py b/Musicreater/builtin_plugins/midi_read/main.py index 505744b..3f9e3a9 100644 --- a/Musicreater/builtin_plugins/midi_read/main.py +++ b/Musicreater/builtin_plugins/midi_read/main.py @@ -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 {} diff --git a/Musicreater/builtin_plugins/music_preview/__init__.py b/Musicreater/builtin_plugins/music_preview/__init__.py index dc64b8c..f2787b2 100644 --- a/Musicreater/builtin_plugins/music_preview/__init__.py +++ b/Musicreater/builtin_plugins/music_preview/__init__.py @@ -68,7 +68,7 @@ class PcmConversionConfig(PluginConfig): - 1 拉伸至 mc 播放器定义(我的世界效果) - 2 根据 midi 音符长度裁剪 - 3 混音预留 - - 4 匹配 midi 音符长度(最佳效果) + - 4 匹配 midi 音符长度 """ overlay_mode: Literal[1, 2] = 1 """ diff --git a/Musicreater/builtin_plugins/music_preview/main.py b/Musicreater/builtin_plugins/music_preview/main.py index ac14b1c..54e6a0a 100644 --- a/Musicreater/builtin_plugins/music_preview/main.py +++ b/Musicreater/builtin_plugins/music_preview/main.py @@ -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, ) diff --git a/Musicreater/constants.py b/Musicreater/constants.py index 3e1b98a..e83fb08 100644 --- a/Musicreater/constants.py +++ b/Musicreater/constants.py @@ -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, } """ 不同乐器的音调偏离对照表 diff --git a/Musicreater/data.py b/Musicreater/data.py index 3da853f..da967b1 100644 --- a/Musicreater/data.py +++ b/Musicreater/data.py @@ -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]: """通过确切的开始时间来获取音符""" diff --git a/old-things/Musicreater/experiment.py b/old-things/Musicreater/experiment.py index 8e4ca7d..d23f8b8 100644 --- a/old-things/Musicreater/experiment.py +++ b/old-things/Musicreater/experiment.py @@ -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] = {}, diff --git a/old-things/Musicreater/old_init.py b/old-things/Musicreater/old_init.py index 3412671..e414b9c 100644 --- a/old-things/Musicreater/old_init.py +++ b/old-things/Musicreater/old_init.py @@ -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, diff --git a/old-things/Musicreater/old_main.py b/old-things/Musicreater/old_main.py index 2f6d6de..3738981 100644 --- a/old-things/Musicreater/old_main.py +++ b/old-things/Musicreater/old_main.py @@ -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,