Files
SonicForgeStudio/md/53_VSTI_AUTOSAMPLE_RENDER.md
T

5.3 KiB

TASK 53: ALTERNATIVE SOLUTIONS FOR DIRECT VSTi USAGE IN STANDALONE DAW APPLICATIONS

Spec: "ALTERNATIVE SOLUTIONS FOR DIRECT VSTi USAGE IN STANDALONE DAW APPLICATIONS" Thực hiện trên C:/Users/locpham/SonicForgeStudio (branch standalone). Tài liệu đi kèm: md/53_VSTI_AUTOSAMPLE_RENDER_WALKTHROUGH.md.


1. Mục tiêu (từ spec)

Option Yêu cầu spec Hiện thực
Option 1 Client-side WASM live preview với 0% IPC — cần "a custom Python script" tự động sample các preset VSTi thành .sf3 (~3-8MB) tools/autosample_vsti.py — render từng nốt qua pedalboard → SF2 (16-bit mono), tùy chọn convert sang SF3
Option 2 Offline render/export qua Python backend (pedalboard VST3 + FluidSynth) — WAV chất lượng 24-bit / 32-bit Thêm bit_depth (16/24/32) vào toàn bộ đường render/export backend + frontend

2. Thay đổi

2.1 Auto-sampling tool (mới)

File: tools/autosample_vsti.py (mới, untracked)

  • CLI: --instrument <plugin_id> --out out.sf2 [--preset] [--low --high --step] [--sf3] [--duration --release --velocity --sample-rate]
  • Reuse PluginManager().load_vst, apply_preset_to_plugin, HAS_PEDALBOARD từ app/core/vst_engine.py
  • Render từng nốt bằng pedalboard, MIDI dạng raw tuple (bytes([0x90,note,vel]), 0.0) / (bytes([0x80,note,0]), dur) — pedalboard 0.9.19 build này không có NoteOn classes; khớp PluginManager.midi_events_to_messages (trả (bytes, seconds) tuples)
  • Trim leading silence + normalize peak 0.9 trước khi cast int16
  • write_sf2(): SF2 tối giản hợp lệ — 16-bit mono PCM, 1 zone/nốt (keyRange lo=hi), sampleID, overridingRootKey, end=exclusive; preset 0/bank 0
  • --sf3: convert qua SoundFontConverter (app/core/soundfont_converter.py); fallback giữ SF2 nếu thiếu ffmpeg libvorbis
  • Toàn bộ text ASCII-only (an toàn cp1252 console Windows)

SF2 writer — chi tiết đúng chuẩn (đã verify bằng sf2utils):

  • INFO text chunk (INAM) phải chẵn — pad \x00 bên trong data (strict parsers không skip RIFF pad byte của odd chunk)
  • Records: phdr 38B (name20 + <HHHIII), inst 22B, pmod/imod 10B, pgen/igen 4B (<HH), ibag/pbag 4B, shdr 46B; bắt buộc terminator records cho từng bảng

Kết quả verify: Nexus.vst3 → 3 nốt (60/62/64) → SF2 207KB, sf2utils parse sạch, audio peak 29490. Kontakt load được nhưng silent (không có .nki — đúng dự kiến).

2.2 bit_depth 16/24/32 WAV export (Option 2)

File Thay đổi
app/core/render_engine.py render_project(self, project_json, output_filepath, bit_depth=16) (L453); subtype_map={16:"PCM_16",24:"PCM_24",32:"PCM_32"}sf.write (L479-481)
app/api/v1/plugins.py bit_depth: int = 16 thêm vào RenderRequest (L493), MidiRenderRequest (L937), SoundfontRenderRequest (L1063); truyền xuống engine.render_project(..., bit_depth=req.bit_depth) (L1200), _render_midi_notes_pedalboard(..., bit_depth=16) (signature L1001, sf.write L1048), soundfont_render sf.write L1100
app/core/audio_editor.py Cả 2 subtype map {8:"PCM_S8",16:"PCM_16",24:"PCM_24",32:"PCM_32"} (L196, L257) — mix multitrack + export
app/static/js/app.jsx Option 32 thêm vào cả 2 dropdown export (L11355 JSX + compiled); encoder 32-bit (view.setInt32(... s*0x80000000 ...)) thêm vào cả 2 client WAV encoder — realtime bounce (L25044-25045) và offline-session (L25363-25368). Đồng thời sửa bug có sẵn: trước đây chọn 24-bit rơi vào nhánh fallback 8-bit

2.3 Tests

  • tests/test_autosampler.py (mới): test_write_sf2_valid_structure (RIFF/sfbk, 3 samples, preset 0/bank 0, 8820 frames), test_write_sf2_rejects_empty, test_write_sf2_odd_name_no_corruption (regression: tên lẻ "Nexus" không làm sf2utils báo corrupted)
  • tests/test_render_engine.py: thêm test_render_project_bit_depth (16/24/32 → PCM_16/24/32)

3. Kết quả test

python -m pytest tests/ -q
→ 108 passed, 1 skipped, 1 failed

1 fail: tests/test_vst_engine.py::TestPluginManager::test_initlỗi môi trường có sẵn (machine VST3 override C:\Program Files\Common Files\VST3 vs expected /opt/daw_engine/vst3; đã xác nhận fail cả trên code sạch bằng git stash). Không thuộc task này.

Lưu ý: không chạy pytest bare từ root repo (collect torch resources dưới src-tauri/target/release/resources/ → 52 collection errors). Luôn nhắm tests/.


4. Cách dùng

# Option 1 — auto-sample VSTi preset sang SF2 (client WASM preview, 0% IPC)
python tools/autosample_vsti.py --instrument Nexus.vst3 --out app/storage/soundfonts/nexus.sf2 --preset <path.vstpreset> --low 36 --high 96 --step 2

# ... hoặc sang SF3 (cần ffmpeg + libvorbis)
python tools/autosample_vsti.py --instrument Nexus.vst3 --out app/storage/soundfonts/nexus.sf3 --sf3

# Option 2 — render/export 24-bit/32-bit (API)
POST /api/v1/plugins/render  { "project_json": {...}, "bit_depth": 24 }
POST /api/v1/plugins/midi-render  { ..., "bit_depth": 32 }
POST /api/v1/plugins/soundfont-render  { ..., "bit_depth": 24 }

SF2/SF3 đặt vào app/storage/soundfonts/ để client tải qua /soundfonts/download.