Python implementation of the solderless.engineering stem loader for the Teenage Engineering x Kanye West SP-1 Stem Player. The serial protocol, WAV encoding, and album metadata format were re-implemented from the original JavaScript source.
pip install pyserial
# Enter transfer mode (first time only — auto-detects boot mode)
python3 sp1-loader.py /dev/cu.usbmodem* --list
# Load a song
python3 sp1-loader.py /dev/cu.usbmodem* song.wav --album-title "My Album" --artist "Artist Name"python3 sp1-gui.pyA cross-platform Tkinter GUI with:
- Auto-detect serial ports and connect to the SP-1
- File picker for choosing one or more WAV files
- Album title, artist, and BPM fields
- Preserve Jesus Is King and metadata-only checkboxes
- Device Info window with live fader positions, buttons, temperature, battery, and charging status
- Log pane showing transfer progress
No dependencies beyond pyserial and Python's built-in tkinter.
# Single track
python3 sp1-loader.py /dev/cu.usbmodem* song.wav --album-title "My Album"
# Multiple tracks (order matters — first WAV is track 1, etc.)
python3 sp1-loader.py /dev/cu.usbmodem* drums.wav bass.wav vox.wav --album-title "Demo"
# With per-track BPM (extracted from filename if it contains "NN bpm")
python3 sp1-loader.py /dev/cu.usbmodem* song.wav --bpm 120
# Set artist for all tracks
python3 sp1-loader.py /dev/cu.usbmodem* song.wav --artist "Artist Name"
# Print low-level transfer diagnostics
python3 sp1-loader.py /dev/cu.usbmodem* song.wav --debug-transferTransfers only the metadata sector (instant, no audio re-transfer). Use this to add, remove, or reorder songs without re-transferring audio data.
# Remove a song: pass all WAVs except the one to delete
python3 sp1-loader.py /dev/cu.usbmodem* keep1.wav keep2.wav --metadata-only --album-title "My Album"
# Remove all user songs, keep only Jesus Is King (default)
python3 sp1-loader.py /dev/cu.usbmodem* --metadata-only --album-title "JIK Only"
# Remove everything including JIK
python3 sp1-loader.py /dev/cu.usbmodem* --metadata-only --album-title "Empty" --no-preserve-jik
# Reorder songs
python3 sp1-loader.py /dev/cu.usbmodem* track3.wav track1.wav track2.wav --metadata-only --album-title "My Album"Note:
--metadata-onlydoes not re-transfer audio. Removed tracks become unreachable but their audio data remains on the device (there is no delete command in the SP-1 protocol).
python3 sp1-loader.py /dev/cu.usbmodem* --listShows device state, album title, device ID, and the track listing from the local metadata file (sp1-album.json) if available. The SP-1 protocol does not support reading the full metadata back from the device, so --list relies on the metadata saved locally during uploads.
# One-shot snapshot
python3 sp1-loader.py /dev/cu.usbmodem* --device-info
# Real-time dashboard (faders, buttons, temperature, etc.)
python3 sp1-loader.py /dev/cu.usbmodem* --device-info --watch--device-info displays: device ID, mode, album title, album data integrity, temperature, charging status, power state, fader positions, button states, and ladder values.
--watch continuously refreshes the display for real-time monitoring. Press Ctrl+C to exit.
The 11-track Jesus Is King album is preserved by default. When you upload songs, JIK tracks are kept in the track list before your songs.
# Remove JIK (use with caution)
python3 sp1-loader.py /dev/cu.usbmodem* song.wav --no-preserve-jik# Export full album binary (no device needed)
python3 sp1-loader.py /dev/null song.wav --export album.sp1
# Export metadata only
python3 sp1-loader.py /dev/null song.wav --metadata-only --export album.sp1If the SP-1 is in bootloader mode (state 00100), the tool auto-detects it, switches to transfer mode, waits for the reboot, and then continues.
On macOS use /dev/cu.usbmodem*. On Linux it's /dev/ttyACM0. On Windows it's COM3 or similar. The tool auto-detects available ports if you use the glob pattern.
The SP-1 requires 24-bit, 48 kHz, 8-channel PCM WAV files (4 stereo stems). Use sp1-merge to create compatible files from individual stem files.
Use sp1-debug.py for raw serial protocol inspection:
For upload performance diagnostics, use --debug-transfer with sp1-loader.py. It prints packet counters, host-side transfer rate, max serial write time, and per-sector GET_WRITE_COUNTER response time:
python3 sp1-loader.py /dev/cu.usbmodem* song.wav --debug-transfer# Send a command and see raw bytes
python3 sp1-debug.py /dev/cu.usbmodem*
# Interactive mode
python3 sp1-debug.py /dev/cu.usbmodem* -i
# Listen for incoming data
python3 sp1-debug.py /dev/cu.usbmodem* --listen
# Scan all ports
python3 sp1-debug.py --scan 3