fix(render): offline SF fallback tìm font GM có sẵn trong plugin_dirs user (Windows)

This commit is contained in:
2026-08-25 09:45:08 +07:00
parent 51d948fdc9
commit ebf0828c55
+36
View File
@@ -21,6 +21,13 @@ SYS_SOUNDFONTS = [
("SGM-V2.01.sf2", "SGM v2.01"),
]
# GM font dự phòng khi track dùng sf_generaluser_gs nhưng máy không có font đó
# (Windows không ship SF2; SYSTEM_SF_DIR là path Linux). Mirror policy frontend
# realtime (app.jsx pickFallbackSoundfont: sgm → generaluser → tgsf21x → timgm
# → font đầu tiên) — offline render phải ra tiếng GM gần đúng, không rơi xuống
# oscillator synth.
GM_SF_FALLBACK_STEMS = ["sgm", "generaluser", "tgsf21x", "timgm", "fluid", "chorium", "musescore"]
def _find_sf2_path(sf_id: str) -> str:
clean_id = sf_id.replace("sf_", "") if sf_id.startswith("sf_") else sf_id
clean_lower = clean_id.lower()
@@ -61,6 +68,35 @@ def _find_default_sf2() -> str:
p = os.path.join(base_dir, sf_name)
if os.path.exists(p):
return p
# Windows: scan plugin dirs user — ưu tiên font GM quen thuộc (sgm/
# generaluser/tgsf21x...), bất kỳ SF2 khác làm fallback cuối (vẫn hơn
# oscillator). Walk sâu: soundfont có thể nằm trong subdir (vd
# Downloads\Collections soundfont\<subdir>\foo.sf2).
try:
from app.core.vst_engine import _load_user_plugin_dirs
found = []
for base_dir in _load_user_plugin_dirs():
if not os.path.isdir(base_dir):
continue
for root, dirs, files in os.walk(base_dir):
for fname in files:
_fb, fext = os.path.splitext(fname)
if fext.lower() not in (".sf2", ".sf3"):
continue
fname_l = fname.lower()
score = 0
for i, stem in enumerate(GM_SF_FALLBACK_STEMS):
if stem in fname_l:
score = 100 - i
break
if score == 0 and ("gm" in fname_l or "general" in fname_l):
score = 50
found.append((score, os.path.join(root, fname)))
if found:
found.sort(key=lambda x: -x[0])
return found[0][1]
except Exception:
pass
return ""
def _apply_master_volume_automation(buf, sr, nodes):