fix(export): carry bridge-captured VSTi preset into offline render
Offline render tao bridge moi khong co preset -> plugin load init patch -> am khac realtime (user tuong fallback). Gio doc presetBase64 tu bridge_state.json (channel == track.id, plugin_path khop basename) va truyen vao render_offline khi track khong nhung preset_data.
This commit is contained in:
@@ -137,6 +137,43 @@ def _preset_b64(preset_id, preset_path, preset_data_b64) -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def bridge_state_preset_b64(channel=None, plugin_path=None) -> str:
|
||||
"""presetBase64 từ bridge_state.json — bridge C++ đang giữ preset user
|
||||
chỉnh realtime (capture mỗi ~2s). Export tạo bridge mới không có preset →
|
||||
plugin load init patch → âm khác realtime (user tưởng "fallback"). Fallback
|
||||
này nối: dùng preset mà bridge đã capture cho channel đó.
|
||||
|
||||
Match: channel == int(track.id) (scheduleMidiNoteDispatch pushEvent
|
||||
channel: trkId) + path khớp plugin (basename, case-insensitive). Không tìm
|
||||
thấy → "" (giữ hành vi cũ — không đoán bừa preset channel khác)."""
|
||||
try:
|
||||
st_path = os.path.join(os.environ.get("APPDATA", ""), "SonicForgeDAW",
|
||||
"state", "bridge_state.json")
|
||||
if not os.path.isfile(st_path):
|
||||
return ""
|
||||
with open(st_path, encoding="utf-8", errors="replace") as fh:
|
||||
st = json.load(fh)
|
||||
try:
|
||||
ch = int(channel) if channel is not None else None
|
||||
except Exception:
|
||||
ch = None
|
||||
want = None
|
||||
if plugin_path:
|
||||
want = os.path.basename(os.fspath(plugin_path)).lower()
|
||||
for ins in st.get("instruments") or []:
|
||||
if ch is not None and ins.get("channel") != ch:
|
||||
continue
|
||||
ip = ins.get("path") or ""
|
||||
if want and os.path.basename(ip).lower() != want:
|
||||
continue
|
||||
pb = ins.get("presetBase64") or ""
|
||||
if pb:
|
||||
return pb
|
||||
except Exception:
|
||||
pass
|
||||
return ""
|
||||
|
||||
|
||||
def _run_notes_job(job: dict, label: str) -> tuple:
|
||||
"""Chạy job MIDI render qua native_bridge --render → (out_path, duration_sec).
|
||||
|
||||
|
||||
@@ -709,6 +709,18 @@ class PythonRenderEngine:
|
||||
"start_beat": ev["start_beat"],
|
||||
"duration_beats": ev["duration_beats"],
|
||||
} for ev in midi_events]
|
||||
# preset_data rỗng → fallback preset
|
||||
# bridge đang giữ (bridge_state.json) —
|
||||
# export tạo bridge mới init patch ≠ âm
|
||||
# realtime user đang nghe.
|
||||
preset_b64 = (se2.get("preset_data")
|
||||
or track.get("preset_data"))
|
||||
if not preset_b64:
|
||||
preset_b64 = native_render.bridge_state_preset_b64(
|
||||
channel=track.get("id"),
|
||||
plugin_path=(se2.get("plugin_path")
|
||||
or track.get("plugin_path")),
|
||||
)
|
||||
out_path, _dur = native_render.render_offline(
|
||||
instrument_id=instrument_id,
|
||||
notes=bridge_notes,
|
||||
@@ -716,7 +728,7 @@ class PythonRenderEngine:
|
||||
sample_rate=self.sample_rate,
|
||||
preset_id=se2.get("preset_id") or track.get("preset_id"),
|
||||
preset_path=se2.get("preset_path") or track.get("preset_path"),
|
||||
preset_data_b64=se2.get("preset_data") or track.get("preset_data"),
|
||||
preset_data_b64=preset_b64,
|
||||
soundfont_bank=soundfont_bank,
|
||||
soundfont_program=soundfont_program,
|
||||
plugin_path=se2.get("plugin_path") or track.get("plugin_path"),
|
||||
|
||||
Reference in New Issue
Block a user