JammLab is a native macOS practice app for importing local audio or video, building a timeline, marking song sections, looping difficult parts, and separating stems locally.
The app is local-first: playback, waveform rendering, project files, stem
separation jobs, and video-audio extraction run on the user's Mac. JammLab does
not require a server, paid API, cloud upload, or user-installed
audio-separator runtime.
- Import local MP3/WAV audio and MP4/MOV/M4V video, with audio-first video extraction and an optional muted sidecar Video Window.
- Practice on a DAW-style timeline with waveform rendering, beat grid, notes, markers, colored regions, loop editing, click, snap, speed, and pitch controls.
- Edit lead-sheet harmony in the synced Notation track or full Notation Window, measure selection, copy/paste, and playback-marker jumps.
- Export notation as MusicXML with harmony, tempo marking, Region labels, and note/rest duration data.
- Separate stems locally through bundled helper processes, with no user-installed
Python,
audio-separator, Demucs, FFmpeg, ONNX Runtime, Torch, or NumPy. - Save portable
.jammlabprojects with project-localstems/,peaks/, andmedia/artifacts next to the project file. - Use lightweight local BPM/key analysis, a live tuner, editable theme colors, click sound settings, and audio input/output device preferences.
- Rely on undo/redo, modified-project save prompts, and local-only processing without server, cloud upload, or paid API dependencies.
JammLab is a native macOS SwiftUI application. See CONTRIBUTING.md for local setup, verification commands, and bundled separator helper build instructions.
Before a normal app build, create the bundled separator artifact with
scripts/build_separator_helper.sh. The JammLab target copies it from
build/JammLabSeparatorHelper/dist/JammLabSeparatorHelper into
JammLab.app/Contents/Resources/JammLabSeparatorHelper. Test workflows that do
not need the packaged helper may set SKIP_BUNDLED_SEPARATOR_HELPER=1.
GitHub CI uses these modes:
- feature branches and pull requests to
main: Python helper tests and Swift tests; mainpushes: tests plus unsigned Debug/Release build smoke;- stable release tags
vMAJOR.MINOR.PATCH: tests, bundled separator build, unsigned Release app build, DMG packaging, source archive upload, and a published latest GitHub Release with downloadable assets; - beta release tags
vMAJOR.MINOR.PATCH-beta: the same artifact build, published as a GitHub prerelease and not marked latest; - development tags
vMAJOR.MINOR.PATCH-dev.N: the same artifact build, uploaded only as workflow artifacts. Dev tags do not create GitHub Releases.
Release versions are derived from Git tags. Tags such as v1.0.0,
v1.0.0-beta, and v1.0.0-dev.1 all build the app with
MARKETING_VERSION=1.0.0; the standard macOS About panel reads that base app
version from the generated app Info.plist. The tag suffix is used only for the
release channel and artifact names. GitHub release notes are generated
automatically for stable and beta releases. Re-running a tag workflow replaces
release assets with the same names, while workflow artifacts remain available
for build debugging.
Stem separation runs through two bundled helpers:
JammLabStemHelper: a Swift job watcher that owns heartbeat, cancellation, cache, and job status protocol.JammLabSeparatorHelper: a PyInstaller-packaged Python runtime that wrapsaudio-separator.
No user-installed pipx, Python, audio-separator, Demucs, ffmpeg,
onnxruntime, torch, or numpy runtime is required. The packaged separator
includes its Python runtime, FFmpeg provider, and a prefilled model cache for
the configured separator models. At runtime JammLab seeds
Application Support/JammLab/StemModels from the bundled cache before
separation.
Stem separation is an offline background job and can take a while on longer tracks.
Unsaved projects use app cache as temporary staging storage. After a project is saved, project-specific artifacts move next to the project file:
Song/
Song.jammlab
stems/
peaks/
media/
stems/stores separated stem WAV files and metadata.peaks/stores main and stem peakform cache files.media/stores extracted video audio such asaudio.m4a.
The shared separator model cache remains under Application Support because it is a backend dependency, not a project artifact.
JammLab favors a compact, audio-first workflow over a large editing surface. The main audio engine owns transport time, playback state, loop execution, and click timing. UI views display the audio clock and send explicit editing commands; they do not drive playback timing themselves.
The interface follows a DAW-inspired style: dense controls, minimal chrome, drag-adjustable numeric fields, compact value sliders, and editable theme colors. Project state is portable when saved as a project folder, while global preferences such as app colors, audio devices, and click sound settings stay in application settings.
JammLab/
Models/
Services/
ViewModels/
Views/
DesignSystem/
Utilities/
JammLabStemHelper/
JammLabSeparatorHelper/
Configurations/
scripts/
docs/
The app uses SwiftUI + MVVM with a service layer and focused pure logic models.
AudioPlayerViewModel coordinates import/open/save, playback state, project
edits, stems, video follower state, and undo/dirty tracking. Timeline rendering
uses TimelineViewport as the shared time-to-pixel model so waveform, beat
grid, regions, markers, loop handles, and playhead stay synchronized.
Notation rendering uses the same playback clock and harmony editing state in
the timeline track and the standalone Notation Window.
- BPM is estimated from a short-time RMS energy envelope and autocorrelation.
- Key is estimated from a Goertzel-based pitch-class chroma and Krumhansl-style major/minor profile matching.
- Waveform rendering uses cached multi-resolution min/max/rms peakform data.
The analysis is intentionally lightweight and local. It is useful for practice workflow hints, not as a replacement for a full music-information-retrieval pipeline.
JammLab is released under the MIT License. See LICENSE.
Third-party runtime and build dependency notices are listed in THIRD_PARTY_NOTICES.md.
