dc331f39d8
- config.py: SF_RENDER_ENGINE default 'bridge' (pedalboard GPL-3.0 đã gỡ)
- requirements.txt: bỏ pedalboard==0.9.19
- vst_engine.py: bỏ HAS_PEDALBOARD/check_pedalboard_safe/load_vst/import pedalboard;
midi_events_to_messages giữ làm utility thuần (không gate pedalboard)
- render_engine.py: bỏ nhánh elif vst and HAS_PEDALBOARD + import thừa
- plugins.py: preview/midi-render chỉ qua native_bridge; guard SF_RENDER_ENGINE=bridge
- runtime.py: _vst_render_available() check bridge exe (SF_BRIDGE_PATH/install/) thay find_spec('pedalboard')
- LICENSE.md/THIRD_PARTY_LICENSES.md: bỏ cảnh báo GPL-3.0 pedalboard, đánh số lại
- tests: bỏ test golden so pedalboard + test requires_pedalboard; 114 passed 0 skip
69 lines
2.8 KiB
Python
69 lines
2.8 KiB
Python
"""Phase 2: native_render client (thay pedalboard bằng native_bridge --render).
|
|
|
|
Unit: phân loại plugin, tìm bridge, instrument lạ → 404. E2E nhỏ: bridge render
|
|
SF2 thật ra WAV đúng duration (giống native_bridge/tests/test_offline_render.py).
|
|
Skip nếu máy thiếu bridge exe hoặc file SF2 fixture."""
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
|
|
import pytest
|
|
import soundfile as sf
|
|
from fastapi import HTTPException
|
|
|
|
from app.core import native_render
|
|
|
|
|
|
def test_classify_instrument():
|
|
assert native_render.classify_instrument(r"C:\VST\Vital.vst3") == 0
|
|
assert native_render.classify_instrument(r"C:\VST\foo.dll") == 1
|
|
assert native_render.classify_instrument(r"C:\SF\a.sf2") == 2
|
|
assert native_render.classify_instrument(r"C:\SF\a.sf3") == 2
|
|
assert native_render.classify_instrument(r"C:\SF\a.sfz") == 3
|
|
|
|
|
|
def test_find_bridge_exe_dev():
|
|
exe = native_render.find_bridge_exe()
|
|
assert exe, "không tìm thấy bridge exe (install/ hoặc SF_BRIDGE_PATH)"
|
|
assert os.path.isfile(exe)
|
|
|
|
|
|
def test_render_offline_unknown_instrument_404():
|
|
with pytest.raises(HTTPException) as ei:
|
|
native_render.render_offline("__no_such_plugin__", [], bpm=120.0, sample_rate=44100)
|
|
assert ei.value.status_code == 404
|
|
|
|
|
|
def test_bridge_render_sf2_e2e():
|
|
exe = native_render.find_bridge_exe()
|
|
if not exe:
|
|
pytest.skip("bridge exe missing")
|
|
sf2 = r"C:\Users\locpham\SonicForgeStudio\app\storage\soundfonts\518e850f-a5d3-4790-b1f9-0c90c203c524.sf2"
|
|
if not os.path.isfile(sf2):
|
|
pytest.skip("SF2 fixture missing")
|
|
with tempfile.TemporaryDirectory() as td:
|
|
job = {"instrument_type": 2, "plugin_path": sf2, "sample_rate": 44100, "bpm": 120.0,
|
|
"notes": [{"pitch": 60, "velocity": 0.8, "start_beat": 0.0, "duration_beats": 1.0}]}
|
|
jp = os.path.join(td, "job.json")
|
|
out = os.path.join(td, "out.wav")
|
|
with open(jp, "w", encoding="utf-8") as fh:
|
|
json.dump(job, fh)
|
|
r = subprocess.run([exe, "--render", jp, "--out", out],
|
|
capture_output=True, text=True, timeout=120)
|
|
assert r.returncode == 0, ((r.stdout or "") + (r.stderr or ""))[-500:]
|
|
assert os.path.isfile(out)
|
|
info = sf.info(out)
|
|
assert info.samplerate == 44100
|
|
assert info.frames == 22050
|
|
|
|
|
|
def test_plugins_bridge_branch_dispatch(monkeypatch):
|
|
"""SF_RENDER_ENGINE=bridge: _render_midi_notes_pedalboard phải đi
|
|
vào native_render (instrument lạ -> 404), không cần pedalboard."""
|
|
from app.api.v1 import plugins as pl
|
|
monkeypatch.setattr(pl.settings, "RENDER_ENGINE", "bridge")
|
|
with pytest.raises(HTTPException) as ei:
|
|
pl._render_midi_notes_pedalboard("__no_such__", [], bpm=120.0, sample_rate=44100)
|
|
assert ei.value.status_code == 404
|