mirror of
https://github.com/TriM-Organization/Musicreater.git
synced 2026-07-24 01:02:32 +00:00
新增新文件路径小参数,新增音乐预览插件测试样例。修复小问题
This commit is contained in:
@@ -17,10 +17,12 @@ Terms & Conditions: License.md in the root directory
|
||||
|
||||
|
||||
from copy import deepcopy, copy
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Generator, List, Optional, Tuple, Union, TypeVar
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def enumerated_stuffcopy_dictionary(
|
||||
enumeration_times: int = 17, staff: T = {}
|
||||
) -> Dict[int, T]:
|
||||
@@ -30,3 +32,16 @@ def enumerated_stuffcopy_dictionary(
|
||||
# 这告诉我们,你不能忽略任何一个复制的序列,因为它真的,我哭死,折磨我一整天,全在这个bug上了
|
||||
# 上面的这指的是 copy.deepcopy —— 金羿 来自 20260210
|
||||
return {i: deepcopy(staff) for i in range(enumeration_times)}
|
||||
|
||||
|
||||
def incremental_save_path(
|
||||
file_name: str, suffix: str = ".file", appendix_connector: str = "-"
|
||||
) -> Path:
|
||||
ss_path = Path(file_name).with_suffix(suffix)
|
||||
if ss_path.exists():
|
||||
now_appendix = 2
|
||||
while (
|
||||
ss_path := Path(file_name + appendix_connector + str(now_appendix) + suffix)
|
||||
).exists():
|
||||
now_appendix += 1
|
||||
return ss_path
|
||||
|
||||
@@ -107,6 +107,9 @@ class NoteDataConvert2PcmPlugin(MusicOutputPluginBase):
|
||||
license="Apache 2.0",
|
||||
)
|
||||
|
||||
|
||||
supported_formats = ("WAV", "WAVE", "PCM")
|
||||
|
||||
def dump(self, data: SingleMusic, file_path: Path, config: PcmConversionConfig):
|
||||
|
||||
pr = perf_counter_ns()
|
||||
|
||||
@@ -48,7 +48,7 @@ from Musicreater.constants import MM_INSTRUMENT_DEVIATION_TABLE
|
||||
|
||||
|
||||
class MusicPreview:
|
||||
|
||||
|
||||
# 当前的资源存储方法过于鸡肋
|
||||
# 应当依托于 SingleMusic 和 SingleTrack 提供的 extra_info 参数,得到更优的解法
|
||||
# 或者更理想的情况是把当前插件作为一个 Service 插件,然后通过 serve API 进行调用
|
||||
@@ -102,12 +102,11 @@ class MusicPreview:
|
||||
self.output_sample_rate = sample_rate
|
||||
self.get_value_method = value_get_method
|
||||
self.resources_path = resource_folder
|
||||
|
||||
|
||||
# 在当前算法下,小数点精度必须为 0
|
||||
# 此处 TODO,需待旧梦来完善
|
||||
self.pitch_precision_decimals = 0
|
||||
|
||||
|
||||
self.pitch_deviation = music_deviation
|
||||
|
||||
for file in self.resources_path.iterdir():
|
||||
@@ -189,13 +188,13 @@ class MusicPreview:
|
||||
else:
|
||||
# if self.mode == 1:
|
||||
# 重采样, 不变调
|
||||
print(">>", sound_name, pitch)
|
||||
# print(">>", sound_name, pitch)
|
||||
self.res_data[sound_name][pitch] = librosa.resample(
|
||||
y_orig,
|
||||
orig_sr=sr_orig,
|
||||
target_sr=self.output_sample_rate,
|
||||
fix=False, # 尽管这样不变调,但是也不应将 pitch 与打击乐器联系在一起
|
||||
)
|
||||
) # 已经在下面重新用 0 取代了打击乐器的 pitch
|
||||
"""elif self.mode == 0:
|
||||
# 重采样, 不变调, 衰弱
|
||||
self.cache_dict[raw_name] = librosa_resample(
|
||||
@@ -221,14 +220,15 @@ class MusicPreview:
|
||||
duration: int,
|
||||
):
|
||||
|
||||
print(
|
||||
sound_name,
|
||||
pitch,
|
||||
">>",
|
||||
(pitch := self.make_pitch_accurate(pitch)),
|
||||
percussive,
|
||||
duration,
|
||||
)
|
||||
# print(
|
||||
# sound_name,
|
||||
# pitch,
|
||||
# ">>",
|
||||
# (pitch := self.make_pitch_accurate(pitch)),
|
||||
# percussive,
|
||||
# duration,
|
||||
# )
|
||||
pitch = 0 if percussive else self.make_pitch_accurate(pitch)
|
||||
|
||||
if sound_name in self.res_data:
|
||||
if pitch in self.res_data[sound_name]:
|
||||
@@ -333,24 +333,24 @@ class MusicPreview:
|
||||
out_sr = self.output_sample_rate
|
||||
|
||||
for note in music.get_minenotes(start_time=start_tick, end_time=end_tick):
|
||||
accurate_pitch = self.make_pitch_accurate(
|
||||
note.pitch
|
||||
- 60
|
||||
- (
|
||||
0
|
||||
if note.percussive
|
||||
else MM_INSTRUMENT_DEVIATION_TABLE.get(note.instrument, 6)
|
||||
accurate_pitch = (
|
||||
0
|
||||
if note.percussive
|
||||
else self.make_pitch_accurate(
|
||||
note.pitch
|
||||
- 60
|
||||
- MM_INSTRUMENT_DEVIATION_TABLE.get(note.instrument, 6)
|
||||
)
|
||||
)
|
||||
print(
|
||||
":",
|
||||
note.instrument,
|
||||
note.pitch,
|
||||
">>",
|
||||
accurate_pitch,
|
||||
note.percussive,
|
||||
note.duration_tick,
|
||||
)
|
||||
# print(
|
||||
# ":",
|
||||
# note.instrument,
|
||||
# note.pitch,
|
||||
# ">>",
|
||||
# accurate_pitch,
|
||||
# note.percussive,
|
||||
# note.duration_tick,
|
||||
# )
|
||||
if not note.percussive:
|
||||
overlay(
|
||||
self.res_data[note.instrument][accurate_pitch]
|
||||
|
||||
+1
-1
@@ -509,7 +509,7 @@ class SingleTrack(List[SingleNote]):
|
||||
|
||||
self.argument_curves = {item: None for item in CurvableParam}
|
||||
|
||||
super().__init__(*args)
|
||||
super().__init__(args)
|
||||
super().sort()
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# 一个简单的项目实践测试
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from rich import print
|
||||
|
||||
from Musicreater import load_plugin_from_module, MusiCreater
|
||||
from Musicreater.plugins import _global_plugin_registry
|
||||
from Musicreater._utils import incremental_save_path
|
||||
|
||||
load_plugin_from_module("Musicreater.builtin_plugins.midi_read")
|
||||
load_plugin_from_module("Musicreater.builtin_plugins.music_preview")
|
||||
|
||||
from Musicreater.builtin_plugins.midi_read import MidiImportConfig
|
||||
from Musicreater.builtin_plugins.music_preview import PcmConversionConfig
|
||||
|
||||
print("当前支持的导入格式:", _global_plugin_registry.supported_input_formats())
|
||||
print("当前支持的导出格式:", _global_plugin_registry.supported_output_formats())
|
||||
|
||||
msct = MusiCreater.import_music(
|
||||
Path(input("文件路径:")).resolve(),
|
||||
plugin_config=MidiImportConfig(),
|
||||
)
|
||||
|
||||
print("全局插件注册表:", _global_plugin_registry)
|
||||
print("插件缓存字典:", msct._plugin_cache)
|
||||
|
||||
print(
|
||||
msct.export_music(
|
||||
(fn := incremental_save_path("output", suffix=".wav")),
|
||||
plugin_id="music_to_pcm_plugin",
|
||||
plugin_config=PcmConversionConfig(
|
||||
assets_path=Path("./vanilla_assets/wav/").resolve(),
|
||||
synthesis_mode=2,
|
||||
pitch_accuracy_decimals=0,
|
||||
),
|
||||
),
|
||||
"\n文件路径:",
|
||||
fn,
|
||||
)
|
||||
Reference in New Issue
Block a user