Files
SonicForgeStudio/DESIGN_VST2_BACKWARD_COMPAT.md

5.4 KiB

Thiết kế: tương thích ngược VSTi cũ (VST2, 32-bit) — bridge âm thanh

Ngày: 2026-08-15 Trạng thái: THIẾT KẾ (chưa sửa code sản phẩm). Linux làm thiết kế + spike khả thi; code theo thoả thuận triển khai (Windows).

1. Mục tiêu

Standalone bridge (standalone-shm-bridge) hiện chỉ host VST3. Nhiều VSTi cũ (vintage, freeware, 32-bit) chỉ có bản VST2. Mục tiêu: VST2 64-bit phát được qua bridge chính (headless, realtime), không phá luồng VST3 hiện tại.

2. Hiện trạng (đã xác minh trên code)

VST2 không được implement trong bridge

  • native_bridge/src/NativeInstrumentEngine.cpp:166-180 — create_instrument(): case VST2: return nullptr + comment "ponytail: VST2 host (VST2.4 SDK, Steinberg discontinued) not implemented".
  • Enum đã có sẵn: native_bridge/src/INativeInstrument.h:8-12 (VST3=0, VST2=1, SF2/SF3=2, SFZ=3).
  • StateStore.h:14 — type 1 = VST2.

Backend đã nhận diện VST2 (scan + UI)

  • app/api/v1/plugins.py:117-130,224-247 — file .dll (không phải folder .vst3) → "type":"VST2".
  • app/vst_engine.py:282-300 — scan .vst3/.so/.dll.
  • JS mapping: nativeBridgeService.js:7 INSTRUMENT_TYPE={VST3:0,VST2:1,SF2:2,SF3:2,SFZ:3}.

→ Hệ quả: UI liệt kê plugin VST2 là loại hợp lệ, user assign → bridge create_instrument trả nullptr → assign false → fail im lặng, không có lỗi nào hiển thị. Đây là bug UX chính cần sửa kèm.

Đường khác không thay thế

  • Carla (Windows) hỗ trợ VST2 nhưng là đường GUI/preset riêng (plugins.py:530-630 carla-midi/carla-play-notes/open-in-carla), KHÔNG phải đường audio bridge chính.
  • Preset .fxp/.fxb nằm trong PRESET_EXTENSIONS (vst_engine.py:592) nhưng apply_preset_to_plugin gọi load_preset của VST3Plugin — không chạy VST2.

Hạ tầng tái dùng được

  • SandboxVst3Host + SandboxHostIPC double-buffer (SharedMemoryIPC.h:33-39), plugin_host_main.cpp, env SF_SANDBOX_VST3 — pattern sẵn cho helper process 32-bit.
  • Build: native_bridge/vcpkg.json chỉ fluidsynth+pkgconf; VST3 SDK là git submodule vst3sdk (không có vestige — cần thêm header nếu làm VST2 host); CMake -EHa.

3. Thiết kế đề xuất

3.1. VST2 64-bit — host Vst2Instrument dùng vestige (làm trước)

  • vestige (vestige/aeffect.h, mã nguồn mở, từ dự án LMMS): header-only, tự định nghĩa lại interface + ABI VST2.4 (vtable layout, dispatcher opcode). Không cần Steinberg VST2 SDK (đã discontinued, license không cấp mới) → sạch pháp lý, zero dependency build, không submodule mới.
  • Vst2Instrument implement cùng interface INativeInstrument: assign / SHM double-buffer / renderAll tái dùng nguyên trạng.
  • Phạm vi audio headless: processReplacing, setSampleRate, setBlockSize, resume/suspend, getParameter/setParameter, effGetChunk/effSetChunk (preset .fxp/.fxb), effGetParamLabel (tên tham số cho UI).
  • GUI editor: defer (không window, không thread GUI). Nhiều VSTi cổ vẫn phát headless; plugin nào đòi GUI mới ra tiếng thì ghi rõ giới hạn ở UI.
  • Sửa kèm bug im lặng: khi create_instrument trả nullptr → trả lỗi rõ ràng lên UI thay vì fail câm.

3.2. VST2 32-bit — helper process (defer, effort cao)

  • Helper plugin_host.exe 32-bit, tái dùng pattern SandboxVst3Host + SandboxHostIPC double-buffer + env SF_SANDBOX_VST3.
  • Lý do defer: cần bản build 32-bit riêng, xử lý wow64 + marshalling (MIDI/sample rate/block size qua IPC), khó debug. Làm sau khi 64-bit ổn định.

3.3. Quirk plugin cũ (khi test thực tế)

  • Block size: thử 256 / 512 / 1024 (nhiều plugin cũ chỉ nhận bội số cố định).
  • Sample rate: 44.1 kHz là mặc định an toàn nhất.
  • Thread affinity: open + process cùng 1 thread; tránh đổi thread giữa resume và vòng render.
  • Plugin 32-bit đòi GUI: một số chỉ phát sau khi editor từng mở — ghi rõ giới hạn, không cố host GUI trong bridge.

3.4. Giới hạn docker/server

  • pedalboard không hỗ trợ VST2 → pipeline VSTi→SF2 (DESIGN_DOCKER_VSTI_PLAY.md) chỉ nhận VST3. VST2 không render được asset SF2 trên server. Ghi rõ ở UI.

4. Kiến trúc thêm mới (tối thiểu)

native_bridge/
  vestige/aeffect.h                 # header mã nguồn mở (thêm file)
  src/Vst2Instrument.h/.cpp         # host VST2, implement INativeInstrument
  src/NativeInstrumentEngine.cpp    # case VST2 -> new Vst2Instrument

Không đổi ABI, không đổi SharedMemoryIPC, không đổi JS service layer.

5. Rủi ro / giới hạn

  • Vài plugin rất cổ đòi host callback lạ (effGetPlugCategory, vendor opcode) → patch nhỏ riêng từng plugin.
  • Vestige không cung cấp editor GUI → plugin phụ thuộc GUI sẽ câm.
  • ABI VST2 ổn định từ 1999 → 64-bit .dll hiện đại + cổ đều theo, rủi ro thấp.

6. Thứ tự triển khai

  1. Vst2Instrument + vestige: load, assign, render thử 1 plugin VST2 64-bit.
  2. Sửa bug fail im lặng khi không host được.
  3. Preset .fxp/.fxb qua effSetChunk/param.
  4. Test block size / sample rate / thread affinity với plugin cổ.
  5. (Defer) 32-bit helper process.