A lightweight C++ program that bridges MIDI clock signals to JACK transport, allowing hardware sequencers, drum machines and other MIDI-clock-capable devices to control tempo in JACK/PipeWire-based audio environments.
This program listens to incoming MIDI clock messages (via ALSA) and translates them into JACK transport tempo and BBT (Bar/Beat/Tick) information. It acts as a JACK timebase master, providing stable tempo synchronization for JACK-aware applications. The tool was specifically created to work seamlessly with Carla as a primary use case, ensuring tight synchronization when using external MIDI-clock hardware with Carla-hosted instruments and plugins.
┌─────────────────────────────────────────────────────────────────┐
│ 🎹 EXTERNAL CLOCK SOURCE │
│ MIDI Clock Source (HW/DAW) │
│ • Sends F8 (clock ticks at 24 PPQN) │
│ • Optional: FA/FB/FC transport messages │
└────────────────────────────┬────────────────────────────────────┘
│ MIDI Protocol (ALSA)
▼
┌─────────────────────────────────────────────────────────────────┐
│ 🔄 MIDI CLOCK SYNC PROGRAM │
│ ** BPM TRANSLATOR ** │
├─────────────────────────────────────────────────────────────────┤
│ ✓ Opens ALSA MIDI input port │
│ ✓ Listens to MIDI Clock ticks (F8) │
│ ✓ Measures time between ticks │
│ ✓ Calculates current BPM from tick intervals │
│ ✓ Continuously updates JACK transport BPM │
│ ✓ Provides BBT position as JACK timebase master │
└────────────────────────────┬────────────────────────────────────┘
│ Writes BPM to JACK Transport
▼
┌─────────────────────────────────────────────────────────────────┐
│ 🎚️ JACK / PIPEWIRE ENGINE │
│ • Current BPM ← continuously updated │
│ • BBT time information │
│ • Transport state (rolling/stopped) │
└────────────────────────────┬────────────────────────────────────┘
│ All clients read shared BPM
▼
┌─────────────────────────────────────────────────────────────────┐
│ 🎛️ CARLA / ARDOUR │
│ • Registers as JACK client │
│ • Reads current BPM from JACK transport │
│ • Plugins stay in sync with external MIDI clock │
└─────────────────────────────────────────────────────────────────┘
- MIDI Clock Detection: Listens for 24 PPQN MIDI clock
- Adaptive BPM Smoothing: Intelligent smoothing & stability detection
- JACK Timebase Master: Provides tempo, time signature (4/4), BBT
- Transport Control: Responds to Start/Stop/Continue messages
- Auto-start: Begins JACK transport on first received MIDI clock
- Realtime Status Reports: View status using
SIGUSR1 - PipeWire Compatible: Works via
pw-jack
- ALSA
- JACK or PipeWire (with JACK compatibility)
- MIDI clock source (hardware or software)
sudo apt-get install \
build-essential \
libasound2-dev \
libjack-jackd2-dev \
pipewire-jackgit clone https://github.com/ariel10aguero/midi-clock-jack-bridge
cd midi-clock-jack-bridgechmod +x build.sh
./build.shBuild settings:
- C++17
-O3optimization- Links ALSA, JACK, pthread, atomic
aconnect -lExample:
client 24: 'Scarlett 2i4 USB'
0 'Scarlett 2i4 USB MIDI 1'
pw-jack ./midi_clock_sync 24:0Replace 24:0 with your MIDI source port.
For stable tempo sync, use Multiple Clients mode:
- Open Carla
- Configure Carla → Engine
- Set Process Mode: Multiple Clients
- Enable Use JACK Transport
- Restart engine
- Then run:
pw-jack ./midi_clock_sync <client>:<port>- PipeWire running
- Run
midi_clock_sync - Launch Carla
Send a SIGUSR1:
kill -USR1 $(pidof midi_clock_sync)Example:
╔════════════════════════════════════════╗
║ MIDI CLOCK SYNC STATUS ║
╠════════════════════════════════════════╣
║ Transport State: ▶ PLAYING ║
║ JACK BPM: 86.00 ║
║ Position: Bar 4, Beat 1 ║
║ Frame: 416768 ║
║ Time Signature: 4.00/4.00 ║
║ Detected BPM: 86.00 ║
║ Measurements: 16 ║
║ Current Pos: 4:1:854 ║
╚════════════════════════════════════════╝
Carla Configuration Note
For proper JACK transport syncing, ensure Carla’s config file contains:
nano ~/.config/falkTX/Carla2.conf
Set:
TransportMode=2
Press “R” in the terminal → Resets the bar counter to 1