Files
SonicForgeStudio/md/37_FIXVST3_SUGGEST.md
T

4.3 KiB

Nguyên nhân xuất hiện thông báo lỗi từ SpessaSynth Core: basic_synthesizer_core.ts:169 No preset found for 0:0:0! Did you forget to add a sound bank?

Thông số 0:0:0 trong thông báo đại diện cho Bank MSB : Bank LSB : Program Number (cấu hình mặc định ban đầu của kênh MIDI). Lỗi này xảy ra do 3 nguyên nhân chính sau:


1. Phân tích nguyên nhân kỹ thuật

  1. Chưa gửi lệnh programChange & controllerChange sang SpessaSynth khi chọn "Pipa":
  • Khi chọn nhạc cụ "Pipa" trên UI, ứng dụng mới chỉ cập nhật giao diện mà chưa kích hoạt lệnh đổi tiếng (synthInstance.programChange(channel, program)) sang kênh MIDI tương ứng của SpessaSynth.
  • Khi gõ phím trên SE49 (nhận dữ liệu Raw MIDI [144, 65, 78]), SpessaSynth vẫn truy xuất bộ tiếng ở vị trí mặc định là Bank 0 : Program 0 (thường là Grand Piano theo chuẩn General MIDI).
  • Trong SoundFont DSK_Asian_DreamZ, vị trí 0:0:0 không tồn tại hoặc không chứa thông tin nốt, khiến SpessaSynth thông báo không tìm thấy preset.
  1. Sai chỉ số Bank / Program của nhạc cụ "Pipa":
  • Tệp SoundFont DSK_Asian_DreamZ là bộ tiếng tùy chỉnh (Non-General MIDI). 8 nhạc cụ bên trong (Pipa, Pipa Tremolo, Luan, Guzhen, Erhu, Koto, Ban Di, Percussion) được đánh số Program riêng biệt.
  • Nếu UI gửi program = 0 nhưng thực tế trong file SoundFont, tiếng Pipa nằm ở program = 1 hoặc bank = 1, SpessaSynth sẽ không tìm thấy preset tương ứng.
  1. **Lỗi Header/Mapping khi convert từ .sf2 sang .sf3**:
  • Một số công cụ nén (như mscore CLI) khi convert các SoundFont tùy chỉnh có cấu trúc phi chuẩn có thể làm mất hoặc biến đổi bảng thông tin Preset Header.

2. Các bước khắc phục

Bước 1: Gọi programChange & controllerChange ngay khi chọn nhạc cụ trên UI

Đảm bảo khi người dùng chọn nhạc cụ trên giao diện, hàm chọn Bank/Program được kích hoạt trên kênh MIDI phát tiếng:

// Khi người dùng chọn "Pipa" trên Dropdown Synth UI
async function onSelectTrackInstrument(trackChannel, sfId, bank, program) {
    // 1. Nạp file .sf3 vào SpessaSynth (nếu chưa nạp)
    await soundFontPlayerInstance.loadSoundFont(sfId);

    // 2. BẮT BUỘC: Gửi lệnh đổi Bank (CC 0) và Program Change sang SpessaSynth
    if (soundFontPlayerInstance.synthInstance) {
        soundFontPlayerInstance.synthInstance.controllerChange(trackChannel, 0, bank);
        soundFontPlayerInstance.synthInstance.programChange(trackChannel, program);
        console.log(`[SonicSF] Switched Channel ${trackChannel} -> Bank: ${bank}, Program: ${program}`);
    }
}

Bước 2: Kiểm tra chính xác chỉ số Bank & Program của Pipa từ Catalog API

Sử dụng API GET /api/v1/plugins/soundfonts/catalog (từ mô-đun SoundFontInspector đã xây dựng) để tra cứu vị trí chính xác của "Pipa":

"dsk_asian_dreamz": {
  "soundfont_id": "dsk_asian_dreamz",
  "instruments": [
    { "bank": 0, "program": 0, "name": "Pipa" },
    { "bank": 0, "program": 1, "name": "Pipa Tremolo" },
    { "bank": 0, "program": 6, "name": "Ban Di" }
  ]
}

Lưu ý: Nếu kết quả trả về tiếng Pipa nằm ở program: 1 hoặc bank: 1, hãy truyền đúng thông số này vào hàm programChange.

**Bước 3: Kiểm tra danh sách Presets mà SpessaSynth đọc được từ file .sf3**

Để đảm bảo quá trình convert .sf3 không làm hỏng dữ liệu Preset Header, bạn hãy log danh sách preset sau khi nạp tệp:

// Thêm log kiểm tra sau khi addSoundFont vào SpessaSynth
try {
    await this.synthInstance.soundFontManager.addSoundFont(buffer);
    
    // In danh sách các preset đọc được ra console để kiểm tra
    const loadedSF = this.synthInstance.soundFontManager.soundFonts[0];
    console.log("[SonicSF] Loaded Presets in SF3:", loadedSF.presets);
} catch (e) {
    console.error("[SonicSF] Error parsing SF3:", e);
}

  • Nếu loadedSF.presets rỗng ([]), file .sf3 đã bị hỏng khi nén. Bạn hãy thử nạp lại file .sf2 gốc chưa nén để đối chiếu.