feat(foundry): merge-of-stems multimodel — Roformer vocals + demucs rest (#9)
PLN's "merge of stems": the best vocal isolation cascaded into the best 4-way split. There is no 4-stem Roformer, so MultiModelBackend orchestrates a cascade — 1. Roformer (audio-separator, py3.12 venv) isolates vocals + instrumental; 2. demucs runs on the INSTRUMENTAL (vocals already gone → cleaner) for drums/bass/other; 3. merge = Roformer vocals ⊕ demucs drums/bass/other in the standard 4-stem contract. Refactored separate.py for composite backends: a backend declares what it `produces` and (for composites) a `run_composite` hook; the subprocess runner is factored into _run_cmd so the cascade can drive several sub-separations. RoformerBackend is now wired (was a stub): audio-separator CLI, 2-stem (vocals/instrumental), normalize() globs the "(Vocals)"/"(Instrumental)" output names. The default normalizer maps by produces[]. Verified end to end on the Loituma source: merge → vocals (Roformer) + drums/bass/other (demucs-on-instrumental), 4 clean PCM_16/44.1k stems. All three backends report available on this box. GUI renders whatever stems a backend emits (demucs/merge 4, roformer 2 incl. instrumental), canonical roles first. 53 tests (added: registry has the three engines, roformer produces 2 + builds its cmd, merge is composite/4-stem). Keeps the 2-stem Roformer door open as its own backend (vocal isolation), and the merge as the flagship. Foundry's engine registry now showcases the pluggable design PLN wants to grow into a product/API/service.
Showing
This diff is collapsed.
Click to expand it.
Please
register
or
sign in
to comment