MIDImod is a Python tool that lets you intercept, transform, and reroute MIDI messages between your hardware and software instruments in real time. Define your MIDI processing rules using simple JSON files - no coding required.
Basic MIDI Routing
- Connect any MIDI device to any other device
- Change MIDI channels on the fly
- Split and layer sounds across multiple instruments
Creative Transformations
- Transpose notes and create harmonies
- Keep melodies in key with scale quantization
- Transform knob movements into different CC parameters
- Scale and remap value ranges (e.g., limit knob to 50-100 instead of 0-127)
- Convert notes to program changes or other MIDI events
- Store values in user variables for complex interactions
Performance Tools
- Built-in sequencer with swing, probability, and micro-timing
- Flexible arpeggiator with multiple modes and octave control
- Live reloading of configurations during performance
- Multiple "versions" - switch entire setups with one button
Advanced Features
- Smart encoder handling (relative, accelerated, catch-up modes)
- OSC integration - receive OSC messages, send OSC, transform MIDI to/from OSC
- Virtual MIDI ports for DAW integration
- Real-time monitor with customizable CC displays
pip install mido python-rtmidi prompt-toolkit json5 python-osc watchdog
- Create a
rules/
folder next tomidimod.py
- Add your rule files (
.json
format) - Run:
python midimod.py
Connect keyboard to synth:
{
"device_alias": {
"MyKeyboard": "KeyboardPortName",
"MySynth": "SynthPortName"
},
"midi_filter": [{
"device_in": "MyKeyboard",
"device_out": "MySynth"
}]
}
Transpose everything up one octave:
{
"midi_filter": [{
"device_in": "MyKeyboard",
"event_in": "note",
"device_out": "MySynth",
"value_1_out": "value_1_in + 12"
}]
}
Remap a knob to control filter cutoff:
{
"midi_filter": [{
"device_in": "MyController",
"event_in": "cc",
"value_1_in": 20,
"device_out": "MySynth",
"value_1_out": 74
}]
}
Create a simple 4-step sequence:
{
"sequencer": [{
"seq_id": "bass_line",
"device_in": "MyClock",
"device_out": "MySynth",
"step_total": 4,
"seq_note": [36, 43, 36, 41],
"seq_gate": [1, 1, 1, 1]
}]
}
Perfect for performance - automatically reloads rules when you save changes:
python midimod.py --live
Switch between different MIDI setups instantly using number keys or MIDI triggers.
- Absolute: Standard knob behavior
- Relative: Endless encoders
- abs_relative: Accelerated control for smooth parameter changes
- abs_catchup: Prevents parameter jumps
- Sequencer: Pattern-based with swing, probability, micro-timing
- Arpeggiator: Real-time note generation with multiple modes
python midimod.py [rule_files...] [options]
Options:
--live Live mode with auto-reload
--list-ports Show available MIDI ports
--log Start with log monitor instead of TUI
--log-out Save all console output to 'midimod.log' with timestamps
--verbose Show detailed debug information
--help Show detailed help
While running:
- Tab: Toggle between TUI and log monitor
- Space: Cycle through versions
- 0-9: Jump to specific version
- Enter: Send transport start/stop
- Ctrl+C: Exit
your_project/
├── midimod.py
├── midimod.conf.json # Global configuration (optional)
├── rules/
│ ├── basic_setup.json
│ ├── performance.json
│ └── effects.json
└── live/ # For --live mode
└── current.json
Create midimod.conf.json
in the main directory for settings that apply to all rule files:
{
"device_alias": {
"MyKeyboard": "KeyboardPortName",
"MySynth": "SynthPortName"
},
"user_variables": {
"global_transpose": 0,
"master_volume": 100
}
}
- See REFERENCE.md for complete technical documentation
- Check EXAMPLES.md for practical use cases
- Use
--list-ports
to identify your MIDI devices - Start with simple routing, then explore transformations
- Python 3.7+
- Works on Windows, macOS, Linux
- Supports all standard MIDI interfaces
- Compatible with any DAW via virtual ports
For detailed configuration options, advanced features, and complete API reference, see REFERENCE.md