V45: D17 seamless loop wrap + D18 stop solo note-off (Qin) + D18b/c guard + engine VST load fixes

- D17: wrap_info/wrap-skip, fx wrap xfade, playhead-derived scheduling
- D18: solo stop -> NOTE_OFF all sounding timeline pitches + CC123/CC120
- D18b: track audible gain guard, tracksRef fallback
- D18c: timelinePitchesRef per-track Set, kill at applyAllTrackMuteSolo
- bridge ring _MAX 16, index v=202608290928
- plugins.py/vst_engine.py/fx_realtime.py/JuceFxEngine.cpp: VSTi load + Qin fixes (uncommitted 12:18)
This commit is contained in:
2026-08-29 16:39:02 +07:00
parent 2afa828c8f
commit c084ac8ba7
9 changed files with 434 additions and 104 deletions
+3 -1
View File
@@ -1,9 +1,9 @@
# SonicForge Studio VST / VSTi Engine Service
from __future__ import annotations
import os
import json
import re
import time as _time
import numpy as np
import functools
import threading
from ctypes import c_char_p
@@ -52,6 +52,7 @@ def render_soundfont_midi_to_audio(midi_events: list, sf_path: str, bank: int =
Xử lí đúng note CHỒNG nhau + đuôi release (event-stream noteon/noteoff).
Trả stereo float32 (2, N). Raise RuntimeError nếu pyfluidsynth thiếu / SF
không load được."""
import numpy as np
import fluidsynth as _fs
settings = _fs.new_fluid_settings()
_fs.fluid_settings_setnum(settings, b'synth.sample-rate', float(sr))
@@ -112,6 +113,7 @@ def render_soundfont_midi_to_audio(midi_events: list, sf_path: str, bank: int =
@_render_locked
def render_midi_events_to_audio(midi_events: list, sr: int = 44100, bpm: float = 120.0, instrument: str = 'synth') -> np.ndarray:
import numpy as np
beat_duration_sec = 60.0 / max(30.0, bpm)
max_duration_sec = 2.0
for event in midi_events: