diff --git a/DESIGN_VST2_BACKWARD_COMPAT.md b/DESIGN_VST2_BACKWARD_COMPAT.md new file mode 100644 index 0000000..7ddff42 --- /dev/null +++ b/DESIGN_VST2_BACKWARD_COMPAT.md @@ -0,0 +1,102 @@ +# 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.