refactor(bridge): split fx bridge, stabilize VST3 host chain, drop old install engines

- remove diagnostic canaries from audio hot path (crackle fix) and
  stuck C5 note raw-MIDI test (Vst2Instrument::init noteOff)
- split native bridge into daw_vst_bridge (VSTi) + fx_vst_bridge (VST FX)
- VST3: processData prepare before setActive, zero input buses, accept
  both .vstpreset and bridge-state blob in RenderJob presets
- native_render/vst_engine: bridge-exe discovery + render_fx_chain + /fx-gui
- delete old install/ engine binaries (install via sidecar+resources now)
- add BUILD_LAYOUT.md, build_selfcheck, tools/ diagnostics
This commit is contained in:
2026-08-20 09:42:42 +07:00
parent 5df96aef1e
commit 7c22ae1f02
42 changed files with 2363 additions and 210 deletions
+69
View File
@@ -0,0 +1,69 @@
import struct
path = r"C:/Users/locpham/AppData/Local/Temp/sf_dumps/bridge_crash_1696.dmp"
data = open(path, "rb").read()
sig, ver, numstreams, sdir = struct.unpack_from("<IIIIIIQ", data, 0)[:4]
streams = {}
for i in range(numstreams):
stype, datasize, rva = struct.unpack_from("<III", data, sdir + i * 12)
streams[stype] = (rva, datasize)
mods = []
rva, sz = streams[4]
n = struct.unpack_from("<I", data, rva)[0]
pos = rva + 4
for i in range(n):
base, imgsz, cksum, ts, name_rva = struct.unpack_from("<QIIII", data, pos)
nlen = struct.unpack_from("<I", data, name_rva)[0]
name = data[name_rva + 4:name_rva + 4 + nlen].decode("utf-16-le", "replace").rstrip("\x00")
mods.append((base, imgsz, name))
pos += 108
def mod_for(addr):
for base, szz, name in mods:
if base <= addr < base + szz:
return base, name.split("\\")[-1]
return None, None
# crash thread context
rva, sz = streams[6]
ex_tid = struct.unpack_from("<I", data, rva)[0]
rva, sz = streams[3]
n = struct.unpack_from("<I", data, rva)[0]
pos = rva + 4
ctx_rva = None
for i in range(n):
tid2, susp, pric, pri, teb, st_start, st_sz, st_rva, ctx_sz2, ctx_rva2 = struct.unpack_from("<IIIIQQIIII", data, pos)
if tid2 == ex_tid:
ctx_rva = ctx_rva2
st_rva_used = st_rva
st_start_used = st_start
pos += 48
rip = struct.unpack_from("<Q", data, ctx_rva + 0xF8)[0]
rsp = struct.unpack_from("<Q", data, ctx_rva + 0x98)[0]
print("crash tid", ex_tid, "RIP", hex(rip), "RSP", hex(rsp))
# find memory region covering RSP
rva, sz = streams[5]
n = struct.unpack_from("<I", data, rva)[0]
pos = rva + 4
region = None
for i in range(n):
start, msz, mrva = struct.unpack_from("<QII", data, pos)
if start <= rsp < start + msz:
region = (start, msz, mrva)
pos += 16
print("stack region", region and (hex(region[0]), hex(region[1])))
# walk stack: assume return addresses are qwords that fall into executable modules
start, msz, mrva = region
base_rsp = rsp
print("\nstack walk from RSP:")
prev = None
for j in range(0, 16384 - 8, 8):
addr = base_rsp + j
if addr >= start + msz: break
val = struct.unpack_from("<Q", data, mrva + (addr - start))[0]
b, nm = mod_for(val)
if nm and (val - b) > 0x1000: # code pointer heuristic (offset beyond header)
print(" %016x [%04x] %016x -> %s+%x" % (addr, j, val, nm, val - b))