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
90 lines
3.2 KiB
Python
90 lines
3.2 KiB
Python
import os
|
|
import json
|
|
import pytest
|
|
from app.core.render_engine import PythonRenderEngine
|
|
|
|
def test_render_engine_init():
|
|
engine = PythonRenderEngine()
|
|
assert engine.sample_rate == 44100
|
|
|
|
def test_bars_to_samples():
|
|
engine = PythonRenderEngine()
|
|
samples = engine.bars_to_samples(4.0, 120.0, 4)
|
|
assert samples == 352800
|
|
|
|
def test_render_session_container_empty():
|
|
engine = PythonRenderEngine()
|
|
session = {"tracks": []}
|
|
buf = engine.render_session_container(session, {}, 120.0, 4, 1000)
|
|
assert buf.shape == (2, 1000)
|
|
assert (buf == 0.0).all()
|
|
|
|
def _midi_track(instrument_id, fx_type=None):
|
|
return {
|
|
"id": "t1",
|
|
"type": "MIDI",
|
|
"instrument_id": instrument_id,
|
|
"instrument_source": "vsti",
|
|
"fx_type": fx_type,
|
|
"volume_db": 0.0,
|
|
"pan": 0.0,
|
|
"mute": False,
|
|
"items": [{
|
|
"type": "MIDI_ITEM",
|
|
"start_bar": 0.0,
|
|
"duration_bars": 1.0,
|
|
"clip_start_offset_bars": 0.0,
|
|
"source_data": {
|
|
"notes": [
|
|
{"pitch": 60, "velocity": 0.8, "start_beat": 0.0, "duration_beats": 1.0}
|
|
]
|
|
},
|
|
}],
|
|
}
|
|
|
|
|
|
def test_render_session_vsti_bridge_unknown_instrument_falls_back(monkeypatch):
|
|
"""SF_RENDER_ENGINE=bridge: track VSTi đi vào native_render; instrument lạ
|
|
(404) → fallback oscillator, không crash, không cần pedalboard."""
|
|
from app.api.v1 import plugins as pl
|
|
monkeypatch.setattr(pl.settings, "RENDER_ENGINE", "bridge")
|
|
engine = PythonRenderEngine()
|
|
session = {"tracks": [_midi_track("__no_such_plugin__")]}
|
|
buf = engine.render_session_container(session, {}, 120.0, 4, 44100)
|
|
assert buf.shape == (2, 44100)
|
|
# oscillator sinh âm thật (non-silent)
|
|
assert (buf != 0.0).any()
|
|
|
|
|
|
def test_render_session_vsti_non_bridge_engine_falls_back(monkeypatch):
|
|
"""Engine không phải bridge (vd 'pedalboard' cũ): VSTi → fallback oscillator (không crash)."""
|
|
from app.api.v1 import plugins as pl
|
|
monkeypatch.setattr(pl.settings, "RENDER_ENGINE", "pedalboard")
|
|
engine = PythonRenderEngine()
|
|
session = {"tracks": [_midi_track("__no_such_plugin__")]}
|
|
buf = engine.render_session_container(session, {}, 120.0, 4, 44100)
|
|
assert buf.shape == (2, 44100)
|
|
|
|
|
|
def test_render_session_fx_chorus_scipy_fallback():
|
|
"""FX chorus: fallback scipy (không pedalboard) không crash, thay đổi âm."""
|
|
from app.api.v1 import plugins as pl
|
|
pl.settings.RENDER_ENGINE = "bridge"
|
|
engine = PythonRenderEngine()
|
|
session = {"tracks": [_midi_track("__no_such_plugin__", fx_type="chorus")]}
|
|
buf = engine.render_session_container(session, {}, 120.0, 4, 44100)
|
|
assert buf.shape == (2, 44100)
|
|
assert (buf != 0.0).any()
|
|
|
|
|
|
def test_render_session_fx_reverb_scipy_fallback():
|
|
"""FX reverb: fallback scipy (không pedalboard) không crash, thay đổi âm."""
|
|
from app.api.v1 import plugins as pl
|
|
pl.settings.RENDER_ENGINE = "bridge"
|
|
engine = PythonRenderEngine()
|
|
session = {"tracks": [_midi_track("__no_such_plugin__", fx_type="reverb")]}
|
|
buf = engine.render_session_container(session, {}, 120.0, 4, 44100)
|
|
assert buf.shape == (2, 44100)
|
|
assert (buf != 0.0).any()
|
|
|