C.W.K.
Stream
Lesson 03 of 04 · published

MIR as a Parts Library (Demucs)

~13 min · mir, demucs, stem-separation, parts-library

Level 0Cold Ash
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"librosa, madmom, Demucs — these are parts in a drawer, not a frame you live inside."

Parts, Not a Framework

Tier A is powered by mature open-source music-information-retrieval: librosa and madmom for tempo/beat/chord/key, essentia for assorted features, Demucs for stem separation, basic-pitch for pitch. The discipline that matters is how Bonfire uses them: as a parts library, wrapped behind Bonfire's own interface — never as a framework the engine is built inside of. The engine depends on Bonfire's StemSeparator, not on Demucs directly. Swap Demucs for something better next year and the engine never notices. This is exactly the discipline Ember holds toward diffusers: own the interface, borrow the implementation.

Demucs in the Spotlight: Stem Separation

Demucs takes a finished mix and splits it into stems — drums, bass, vocals, and 'other' (where guitars and keys usually land). For a learning tool, that one capability is worth a surprising amount:

  • Isolate what you're studying. Learning the bass line? Solo the bass stem and the rest drops away.
  • Mute the part you're replacing and play over the rest. This is the backing-track move — kill the original lead, keep drums + bass + chords, and play your simplified version on top. (That's exactly what the v1 mixer's original / solo / chord channels are for.)
  • Cleaner analysis per stem. Chord and pitch detection on an isolated instrument is far more accurate than on a dense full mix — so stems feed better Tier-A results back into the model.

Heavy, So It Lives in the Backend

Stem separation is GPU-hungry. Demucs runs in the Python backend on office/server hardware (Apple Silicon, MPS, an M3 Ultra with 512 GB), never in the browser. That's a deliberate placement: the client stays light and the heavy lifting happens where the silicon is. (The MIR layer is Stage 2 work — the engine skeleton and UI shipped first; this is the design the analysis layer is being built into, not a claim that every library is wired up today.)

Code

Demucs as a wrapped part, not a dependency that owns you·python
class StemSeparator:
    """Wraps Demucs. The engine depends on THIS interface, not on Demucs.
    Swap the implementation later and nothing upstream changes."""

    def separate(self, audio: AudioBuffer) -> dict[str, AudioBuffer]:
        # Heavy: runs in the backend on MPS (M3 Ultra), never the browser.
        return demucs_apply(audio)   # -> {drums, bass, vocals, other}

# What stems buy easy-mode:
#   isolate("bass")                 -> study one instrument alone
#   mute("vocals"); keep(rest)      -> backing track to play over
#   analyze(stems["other"])         -> cleaner chord/pitch detection
#
# The engine knows StemSeparator. It does NOT know Demucs.

External links

Exercise

Pick a library you depend on heavily. Write the thin interface YOUR code would call if you wanted to swap that library out next year without touching anything upstream. If you can't write that interface in a few lines, you're probably built inside the library as a framework — not using it as a part.
Hint
The test: could you replace the library with a totally different one behind the same interface, and have zero callers change? If yes, it's a part. If callers reach into the library's own types and idioms everywhere, it's a framework you live inside.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue
💛 by Pippawarm

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.