Separate stems in a module

Split a mix into vocals, drums, bass and other with the host separation task, then play the aligned stems through your Processor.

Stem separation turns one recording into aligned parts you can mute, solo, remix or resample. It is part of AI tasks in your module. For what to expect from separated stems, read Split a song into stems in the Help Center.

1. Declare the task and the stem buffer

The host separates and prepares the stems; your Processor plays them. Declare the capability and one in-place data resource sized for the longest clip:

ts
implementation: {
  kind: "processor",
  source: "src/dsp/processor.ts",
  resources: [
    {
      id: "stems",
      kind: "data",
      elementType: "f32",
      maxElements: 2 + 8 * SEPARATION_MAX_FRAMES,
      loading: "preload",
      storage: "in-place",
    },
  ],
},
ui: {
  entry: "./ui/index.tsx",
  hostCapabilities: { optional: ["audio.separation/v1"] },
},

SEPARATION_MAX_FRAMES comes from @maruaudio/audio-contracts (180 seconds at 44.1 kHz). The buffer layout is [sourceRate, frames, vocalsL, vocalsR, drumsL, drumsR, …]: four stereo stems, aligned sample for sample.

The shared @maruaudio/dsp/processors/stem-player leaf plays that buffer on the sample clock with per-stem gain, mute, solo and pan. StemSep's Processor delegates to it entirely.

2. Drive it from the face

tsx
const separation = face.separation
if (!separation) return <p>Stem separation is not available here.</p>

const { phase, source, results, progress } = separation.state

<Button onClick={separation.chooseSource}>Choose a song</Button>
<Button disabled={!source || phase === "separating"} onClick={separation.separate}>
  Separate
</Button>
MemberPurpose
methods, setMethod(id)The separation methods the host offers, each with execution (local, server or commercial), size, availability and a reason when unavailable
chooseSource(), chooseExample(id)Pick a file or a host-supplied example
separate(), cancel()Run or stop separation
state.results, selectResult(id)Each run's stems with peaks and timing; selecting one loads it into the Processor
exportStem(id), exportAll()Host-encoded WAV exports
configureKey?(), forgetKey?()A person's own key for a commercial provider
trackRhythm?(source), state.rhythmBeats and downbeats of the mix or the drum stem (see Beats and tempo)
clearModelCache()Remove downloaded model files

Always show the chosen method's execution. A local method keeps the audio on the person's device; server and commercial methods upload it.

Current implementations

MethodExecutionModel
On this devicelocalSpleeter 4-stem
Maru serverserverSCNet (evaluation)
Commercial providercommercialThe provider's service, with the person's own key

Show method labels and descriptions from methods rather than naming models in your face.

From an app or server

Apps submit separate_audio_stems with a prepared source and the stems they want. See Add generative audio to your app.

Limits and availability

  • Up to 180 seconds and 128 MiB per source; long clips are processed in 30-second windows.
  • Separation runs on website module pages. Studio and native plug-ins do not offer it yet; a module there can still play stems it already has.

Ask your agent

text
Read the Maru docs page "Separate stems in a module", then read StemSep's
source with `maru module files stemsep` and `maru module read stemsep
src/index.ts`. Build a module that separates a song and lets me loop and
pitch-shift only the vocal stem.