Skip to content

feat(stems): DiCoSe stem splitter — engine + music-page split (by Hamza Qayyum) - #59

Merged
Alex-Wengg merged 5 commits into
mainfrom
feat/dicose-stems
Aug 24, 2026
Merged

feat(stems): DiCoSe stem splitter — engine + music-page split (by Hamza Qayyum)#59
Alex-Wengg merged 5 commits into
mainfrom
feat/dicose-stems

Conversation

@Alex-Wengg

Copy link
Copy Markdown
Member

Integrates Hamza Qayyum's DiCoSe.wgsl stem splitter: a raw WebGPU WGSL port of DiCoSe (BS-RoFormer + one-step consistency-distilled refinement, arXiv 2412.06965, karchkha/DiCoSe checkpoints) — vendored as a workspace package and wired up as a new engine kind plus a Suno-style Split stems feature on the music page.

What's here

  • packages/dicose — vendored DiCoSe.wgsl runtime (same pattern as packages/acestep): npm-workspace-ified, vite build converted to library mode (dist/index.js + dist/worker.js + d.ts; vite dev still serves the upstream demo so its browser harnesses are untouched), vitest suite runnable (dicose:test, 34 passed / 1 artifact-dependent skip). Two minimal source patches: checkSupport() exported from the package index, and a DiCoSeClientOptions.createWorker seam so the host bundles the dedicated worker (which also carries the no-referrer fetch patch, like the acestep worker). Weights are never committed (public/model/ gitignored).
  • stem-dicose engine (src/engines/stem-dicose/) — new engine kind, audio → multi-audio: core/types.ts grows a minimal SeparationEngine contract (decodeFile() + separate() over full-band, stereo-capable PCM — explicitly not the 16 kHz mono ASR decode). Registered under Other Audio Models (category: "analysis", heavy) with an HF availability probe and models-local local-weights-first. Fast deterministic mode by default; { outputMode: "refined" } reaches the full CD path (constructor opt, unused by the UI for now).
  • Playground multi-output run path — separation engines render one player + stereo WAV download per stem (drums / bass / other / vocals + derived instrumental); pcmToWav gains an optional right channel.
  • Music page: Split stems — after a generation, a Split stems button in the result panel lazy-loads the engine, runs fast-mode separation on the generated WAV, streams weight-download + chunk progress through the existing progress panel, and renders the five stems as players + downloads. The separator holds a ~625 MB GPU weight buffer, so it is disposed whenever the result panel resets and on pagehide.
  • Docs + CI — README engines-table row & music-page section, THIRD-PARTY-LICENSES.md entry, dicose CI job mirroring the acestep one.

Weights

623 MB f16 package + 1.25 MB manifest hosted at FluidInference/fluidaudio-web/dicose; verified byte-identical to the local converter output (manifest byte-compare + full-bin length + prefix compare; the loader additionally validates streamed length against the manifest). Requires shader-f16 + subgroups + fixed 32-wide subgroups + a 1 GiB storage binding — checkSupport() gates all of it with a readable error.

Verified (headless Chrome 151, M5 Pro, localhost)

  • Other Audio Models page: 30 s / 48 kHz song → 5 stereo stems in 11.2 s wall (RTFx 2.7×, includes decode + WAV encode + render); stems all 30.00 s stereo; drums/bass/other/instrumental non-silent, vocals silent as expected for an instrumental input. Local-weights load path 1.0 s.
  • Music page: warm-OPFS profile → generate 30 s seed 12345 (20.1 s wall, 15.2 s generation) → Split stems → 5 stereo players + downloads in 11.0 s wall (9.3 s separation + local model load/decode); vocals near-silent on the instrumental output as expected, instrumental stem intact. Engine disposed on panel reset/pagehide.
  • Gates: root tsc, production npm run build, prettier, interface conformance, dicose:check/dicose:test all green.

Licensing

DiCoSe.wgsl is MIT per its package.json; the upstream repo does not yet ship the LICENSE text — Hamza will supply it, and it will land at packages/dicose/LICENSE (noted in THIRD-PARTY-LICENSES.md). Authorship is credited in packages/dicose/package.json and the README, like packages/acestep. Model weights retain the karchkha/DiCoSe MIT license.

🤖 Generated with Claude Code

…za Qayyum)

Vendors Hamza Qayyum's DiCoSe.wgsl stem-separation runtime (BS-RoFormer +
one-step consistency-distilled refinement, raw WebGPU WGSL, MIT) at
packages/dicose, following the packages/acestep pattern:

- npm-workspace-ified package.json (pnpm pin dropped, scripts npm-compatible,
  author credit retained); vitest suite stays runnable (34 passed, 1
  artifact-dependent skip).
- vite build converted to library mode emitting dist/index.js +
  dist/worker.js + d.ts; vite dev still serves the upstream demo, so the
  browser harnesses under scripts/ are unchanged.
- Two minimal source patches: checkSupport() exported from the package index
  (capability gating for hosts), and a DiCoSeClientOptions.createWorker seam
  so a consumer bundling the prebuilt dist can supply the dedicated worker
  (the internal new URL("./worker.ts", import.meta.url) default remains).
- Weights are never committed: public/model/ gitignored (623 MB f16 package
  is hosted; production origin wired in a follow-up commit). Converter venv,
  model cache, and generated wav artifacts excluded from vendoring.
- public/Mixture_audio_1.wav symlink replaced with the real file (CI rejects
  tracked symlinks).

Upstream repo currently ships no LICENSE text (package.json declares MIT);
Hamza will supply it — noted in THIRD-PARTY-LICENSES.md in a follow-up.
New engine kind — audio in, multiple audios out:

- core/types.ts grows a minimal source-separation contract: StemAudio /
  SeparationInput (full-band, stereo-capable — explicitly NOT the 16 kHz mono
  ASR decode) and SeparationEngine with decodeFile() + separate().
- src/engines/stem-dicose/: page-side wrapper over the vendored
  DiCoSeWorkerClient. checkSupport() gating (shader-f16 + subgroups + fixed
  32-wide subgroups + 1 GiB storage binding), site-owned worker entry via the
  package's createWorker seam (carries the same no-referrer fetch patch as
  the acestep worker), weight/chunk progress mapped onto the shared
  LoadProgress/TranscribeProgress shapes. Fast deterministic output mode by
  default; { outputMode: "refined" } reaches the full CD path.
- Registry entry (category "analysis", heavy): HF availability probe +
  models-local/dicose local-weights-first via localWeightDir; production
  weights default to the FluidInference HF mirror.
- Playground run path: separation engines decode the picked file at native
  rate/stereo through the engine and render one player + WAV download per
  stem (drums/bass/other/vocals + derived instrumental); pcmToWav gains an
  optional right channel for stereo downloads.

Root typecheck, production build, prettier, and interface conformance green.
Suno-style follow-up on the /music result panel: a Split stems action next
to Download WAV lazy-loads the stem-dicose engine, runs fast-mode DiCoSe on
the generated WAV (decoded through the vendored full-band decoder), and
renders the five stems — drums / bass / other / vocals / derived
instrumental — as players with per-stem stereo WAV downloads.

- Progress reuses the generation progress panel: byte-accurate weight
  download (623 MB, first use only), then chunk-level separation progress
  from the worker client.
- Resource discipline: the separator holds a ~625 MB GPU weight buffer, so
  the engine is disposed whenever the result panel resets (new generation)
  and on pagehide; stem object URLs are revoked with it. Generate and Split
  are mutually exclusive while either runs.
- Styling matches the page's design language (result-actions/stems-panel
  additions live in the existing fluidaudio-web block of the acestep demo
  stylesheet).
…t, CI job

- README: stem-dicose row (verified fast-mode ~3x RT on a 30 s / 48 kHz
  song), Split stems paragraph in the music section, dicose gate commands,
  packages/dicose in the layout map, and Hamza Qayyum credited for the
  DiCoSe.wgsl port alongside ace-step-1.5.wgsl.
- THIRD-PARTY-LICENSES.md: DiCoSe.wgsl entry (MIT per package.json; upstream
  LICENSE text pending from the author) with karchkha/DiCoSe checkpoint
  provenance.
- ci.yml: dicose job mirroring the acestep one (dicose:check + dicose:test;
  contract tests self-exclude without the gitignored weight package).
- Other Audio Models page copy now mentions stem separation.
The Split stems path now probes the vite models-local middleware
(models-local/dicose) before falling back to the HF default, matching the
registry entry's behavior — localhost iteration shouldn't re-download the
623 MB package that is already on disk. localWeightDir is exported from the
engine registry for that.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
fluidaudio-web e534ec8 Aug 24 2026, 04:47 PM

@Alex-Wengg
Alex-Wengg merged commit a09da61 into main Aug 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant