Jam-PT is a macOS practice plugin built with JUCE and CMake. It uses the external demucs CLI to separate a song offline, then mixes the generated drums, bass, other, and vocals stems in real time inside the plugin.
Jam-PT lets you:
- load a local audio file into the plugin
- cache the file in an app-managed library
- run Demucs offline in the background
- reuse cached stems instead of separating the same file again
- control stem levels with four dedicated knobs
- use per-stem
SoloandMute - scrub the waveform and play the cached source
- place persistent markers and jump between them
- expose transport, marker, and stem toggle controls to AU hosts such as MainStage
The plugin does not embed Demucs, PyTorch, CoreML, or any model runtime internally. All separation is delegated to the external demucs executable already installed on the machine.
- macOS
- Audio Unit generator (
AU,augn) - VST3
- Standalone app
- universal build support for both Apple silicon (
arm64) and Intel (x86_64) Macs - intended host compatibility with MainStage 3.6.4, including Intel-based Macs, when the AU is built with an
x86_64slice
src/PluginProcessor.*: plugin lifecycle, state restore, host parameters, transport routingsrc/PluginEditor.*: plugin UI, waveform, transport, markers, stem controlssrc/AudioFilePlayer.*: source-file playbacksrc/DemucsProcessor.*: Demucs CLI orchestration, cache management, stem loading, markers, stem mixing
- macOS
- Xcode with Command Line Tools
- CMake 3.22+
- a working JUCE toolchain
- a working external
demucsCLI installation visible to the host process
JUCE can be fetched automatically at configure time, so a global JUCE install is not required unless you want to build against a local checkout.
Jam-PT stores its working cache under:
~/Library/Application Support/Jam-PT/DemucsCache/
Each source file gets its own folder named after the original file. If a folder with that name already exists for a different source, Jam-PT creates a suffixed variant such as My Song.wav (2).
Inside each source folder, Jam-PT keeps:
DemucsCache/
My Song.wav/
cache-info.xml
source.wav
spectrogram.thumb
htdemucs/
drums.flac
bass.flac
other.flac
vocals.flac
source.<ext>: the cached copy of the selected source file, preserving the original extensionspectrogram.thumb: cached waveform/spectrogram thumbnail used by the UI<model>/: one folder per Demucs model containing lossless cached stems inFLACcache-info.xml: relative metadata for the cached source and its markers
Demucs itself still renders temporary WAV files, but Jam-PT converts them to FLAC internally and removes the temporary WAV output when the import finishes.
If an older cache already contains legacy stem files as WAV, Jam-PT migrates them to FLAC automatically and deletes the old WAV copies.
cache-info.xml stores portable metadata only:
- original file name
- original file size
- original modification timestamp
- cached source file name
- spectrogram cache file name
- marker positions
Absolute source paths are intentionally not stored in cache metadata, so the cache remains portable and self-contained.
The editor layout is:
- Cached-file selector
+button to import a new source fileShow Folderbutton to open the selected cache folder in Finder- waveform / spectrogram area
- position and duration labels under the waveform
- four stem sections in this order:
Drums,Bass,Other,Vocals - bottom transport / marker row:
Prev,Play/Pause,+,Stop,Next - model selector footer
- the waveform is read from
spectrogram.thumbwhen available - if no cached thumbnail exists, it is regenerated from
source.<ext>and then saved - a playhead is shown during playback
- marker positions are drawn as thin yellow vertical lines
- during stem generation, the waveform shows a loading spinner overlay
Each stem has:
- a gain knob
- a
Sbutton forSolo - a
Mbutton forMute
Behavior is standard:
- if no stem is soloed, every non-muted stem plays
- if one or more stems are soloed, only soloed and non-muted stems play
- mute still wins if a stem is both soloed and muted
Jam-PT supports persistent markers stored in cache-info.xml.
+adds a marker at the current position- if the playhead is already on a marker,
+becomes-and removes it Prevjumps to the previous marker when markers exist, otherwise it seeks backward by10sNextjumps to the next marker when markers exist, otherwise it seeks forward by10s
Marker actions are available only when the plugin is in a ready state and do not force a transport state change by themselves.
To keep marker navigation useful during playback, Prev and Next use a tolerance window so repeated presses can continue moving across markers even while the playhead is advancing.
For AU hosts, Jam-PT exposes these controls as automatable parameters:
Play/PauseStopPrevious MarkerAdd MarkerRemove MarkerNext MarkerVocals Solo,Vocals MuteDrums Solo,Drums MuteBass Solo,Bass MuteOther Solo,Other Mute
Stop, Previous Marker, Add Marker, Remove Marker, and Next Marker are exposed as impulse-style actions for host mapping. When no markers exist, Previous Marker and Next Marker fall back to -10s and +10s seeks. Hosts may still render them as generic boolean controls rather than the exact JUCE button styling used in the plugin editor.
Jam-PT depends on an external Demucs runtime. If demucs fails in Terminal, it will fail inside the plugin too.
- Install Python and FFmpeg:
brew install python@3.12 ffmpegpython@3.11 is also a good option. Avoid building your Demucs runtime around Python 3.14 unless you already know your local torch, torchaudio, and torchcodec versions are compatible.
On Apple silicon, Homebrew typically lives under /opt/homebrew.
On Intel Macs, Homebrew typically lives under /usr/local.
- Install
pipxif needed:
brew install pipx
pipx ensurepathRestart Terminal after pipx ensurepath so ~/.local/bin is visible in PATH.
- Remove any older broken Demucs environment:
pipx uninstall demucs- Install Demucs with an explicit Python interpreter:
pipx install --python /opt/homebrew/bin/python3.12 demucsIf you use Python 3.11 instead:
pipx install --python /opt/homebrew/bin/python3.11 demucsIntel Homebrew examples:
pipx install --python /usr/local/bin/python3.12 demucsor:
pipx install --python /usr/local/bin/python3.11 demucs- Inject
torchcodec:
pipx inject demucs torchcodecConfirm that the executable is visible:
which demucs
demucs --helpThen run a real separation test manually:
demucs -n htdemucs "/absolute/path/to/test-file.mp3"If you need to set an output folder and the path contains spaces, quote every path argument:
demucs -n htdemucs -o "/Users/your-user/Library/Application Support/Jam-PT/DemucsCache" "/absolute/path/to/test-file.mp3"-
FFmpeg is not installedInstall FFmpeg withbrew install ffmpeg. -
No module named 'torchcodec'orTorchCodec is requiredRunpipx inject demucs torchcodec. -
Could not load libtorchcodecwith missinglibavutil.*.dylibYour Demucs environment is mismatched or FFmpeg is missing. Reinstall Demucs after installing FFmpeg, preferably with Python 3.11 or 3.12. -
No executable for the provided Python version 'python3.12' found in PATHInstallpython@3.12with Homebrew and use the full interpreter path, for example/opt/homebrew/bin/python3.12.
Jam-PT looks for demucs in common macOS locations first, including:
~/.local/bin/demucs/opt/homebrew/bin/demucs/usr/local/bin/demucs
If it is not found there, the plugin falls back to the process PATH.
cmake -S . -B build -G Xcode -DJAMPT_FETCH_JUCE=ON
cmake --build build --config Releasecmake -S . -B build -G Xcode -DJAMPT_FETCH_JUCE=OFF -DJUCE_SOURCE_DIR=/path/to/JUCE
cmake --build build --config ReleaseFor local development:
cmake -S . -B build-xcode -G Xcode -DJAMPT_FETCH_JUCE=ON
cmake --build build-xcode --config Debug --target Jam-PTThe root CMakeLists.txt is set up to build a universal macOS binary by default:
-DJAMPT_MACOS_ARCHITECTURES="arm64;x86_64"and to use a lower deployment target suitable for older Intel host setups:
-DJAMPT_MACOS_DEPLOYMENT_TARGET=11.0If you want to build only the Intel slice for MainStage 3.6.4 on an Intel Mac, configure explicitly with:
cmake -S . -B build-intel -G Xcode \
-DJAMPT_FETCH_JUCE=ON \
-DJAMPT_MACOS_ARCHITECTURES=x86_64 \
-DJAMPT_MACOS_DEPLOYMENT_TARGET=11.0
cmake --build build-intel --config Release --target Jam-PTIf you want to keep a universal build but configure it explicitly:
cmake -S . -B build-universal -G Xcode \
-DJAMPT_FETCH_JUCE=ON \
-DJAMPT_MACOS_ARCHITECTURES="arm64;x86_64" \
-DJAMPT_MACOS_DEPLOYMENT_TARGET=11.0
cmake --build build-universal --config Release --target Jam-PTTo build the VST3 target explicitly:
cmake --build build-xcode --config Debug --target Jam-PT_VST3After configure, you can also open the generated Xcode project and build the Standalone, AU, or VST3 targets from Xcode.
The project enables COPY_PLUGIN_AFTER_BUILD, so the plugin formats are normally copied automatically after a successful build.
If you need to install AU manually, copy the generated component bundle to:
~/Library/Audio/Plug-Ins/Components/
If you need to install VST3 manually, copy the generated .vst3 bundle to:
~/Library/Audio/Plug-Ins/VST3/
Then rescan plugins in Logic Pro, MainStage, or your preferred host if needed.
If the AU still does not appear in MainStage after a rebuild, validate the component directly:
auval -v augn JmPt MtBsIf validation fails or the plugin is not listed, rebuild the AU target in Release, clear the Audio Unit cache if needed, and rescan the host.
AUis exposed as a generator (augn) for host useVST3is available for compatible hosts, but it is not tagged with an AU-stylegeneratortypeStandaloneexists mainly for development and debugging- MainStage should see the AU as a generator, not as an insert FX
- in the current transport mapping,
Play/Pauseis a toggle, whileRewind,Previous Marker, andNext Markerare exposed as temporary trigger-style controls - the
generatorclassification is specific to theAUbuild viaAU_MAIN_TYPE; it does not carry over toVST3 - the plugin falls back to playing the cached source file until separated stems are ready
- once stems exist in cache for the selected source and model, Jam-PT reuses them automatically
- cached stems are stored as lossless
FLAC, and legacy cachedWAVstems are migrated automatically - temporary
WAVfiles produced during Demucs runs are cleaned up after conversion
- separation is offline per loaded file, so long files can still take noticeable time and disk space
- the plugin depends on an external Demucs runtime with compatible Python, FFmpeg, and TorchCodec
- only the stems produced by the selected Demucs model are reused
- stem cache migration happens on demand when an older
WAV-based cache is encountered - Intel compatibility still depends on having an
x86_64-compatible external Demucs runtime on the target Mac - no automated test suite is included yet
Released under the MIT License. See LICENSE.
