Skip to main content

Human-readable MIDI markup language compiler and tools

Project description

MIDI Markdown

Human-readable MIDI markup language for creating and automating MIDI sequences

Python 3.12+ License: MIT Tests: 1090+ Coverage: 72.53% Code Style: Ruff Type Checking: mypy CI: Passing PyPI Published

✅ Production-Ready — 1090+ tests, 72.53% coverage | Real-time MIDI playback | 6 device libraries (300+ aliases)

🎹 Real-Time MIDI Playback (NEW)

TUI Demo

Interactive Terminal UI with real-time MIDI playback, sub-5ms timing precision, and keyboard controls (Space/Q/R)

Table of Contents

What is MIDI Markdown?

The Problem: Musicians struggle with MIDI automation for live performances. A single preset change requires manually programming 3+ MIDI commands (Bank MSB, Bank LSB, Program Change). Traditional solutions—DAWs, raw MIDI files—are either not portable or completely unreadable.

The Solution: MIDI Markdown (MMD) provides human-readable, text-based MIDI automation designed specifically for live performance. Instead of cryptic hex values and binary files, you write semantic commands like cortex_load 1.2.0.5 that compile to precise MIDI sequences.

Why Choose MMD?

  • Device aliases: Write cortex_load 1.2.0.5 instead of 3 cryptic MIDI commands (Bank MSB, LSB, PC)
  • Version control: Commit your automation to Git alongside your setlists—see exactly what changed between gigs
  • Real-time playback: Interactive TUI with sub-5ms timing precision, keyboard controls (Space/Q/R), no DAW overhead
  • 300+ pre-built aliases: 6 supported devices (Neural DSP Quad Cortex, Eventide H90, Line 6 Helix, HX Stomp, HX Effects, HX Stomp XL)
  • Flexible timing: Absolute timecode [mm:ss.ms], musical time [bars.beats.ticks], relative [+500ms], simultaneous [@]
  • Production-tested: 1090+ tests, 72.53% code coverage—built for reliability

Example: From Chaos to Clarity

# Without MMD: cryptic raw MIDI
- cc 1.32.2    # Bank MSB (what does this do?)
- cc 1.0.0     # Bank LSB (no idea!)
- pc 1.5       # Program Change (which preset?)

# With MMD: semantic, obvious
- cortex_load 1.2.0.5  # Load Setlist 2, Group A, Preset 5

Why MMD?

If you're currently managing MIDI automation for live performance, you might be wondering why MMD is better than other approaches. Here's how it compares:

Aspect Manual MIDI Programming DAW Session Files Raw MIDI Files MIDI Markdown
Readability Hex values, hard to scan GUI-based, not portable Binary, unreadable Human-readable text ✓
Version Control Difficult to diff/merge Large binary files Binary diffs Text-based, Git-friendly ✓
Device Portability Device-specific Locked to DAW Needs mapping tables Device-agnostic core ✓
Performance Tweaking Manual editing tedious Requires DAW open Binary hex editing Simple text editing ✓
Reusability Copy-paste error-prone Project-locked No structure Aliases & imports ✓
Real-time Editing ❌ Not possible Requires DAW running ❌ Not possible Interactive TUI ✓

Why musicians choose MMD:

  • Version control: Commit your automation to Git alongside your setlists. See exactly what changed between gigs.
  • Portable: Same automation works across any MIDI device. Use Quad Cortex one night, Helix the next—no rewiring needed.
  • Device libraries: Pre-built aliases for 6+ devices (Quad Cortex, H90, Helix, HX effects). Create your own in minutes.
  • Live-friendly: Edit and test automations on the fly with interactive playback. No DAW startup overhead.
  • Human-readable: Comments, clear syntax, and intuitive timing make automation easy to understand and maintain.

Example: Switching from Neural DSP Quad Cortex to Eventide H90? Change one line (@import "devices/h90.mmd") and your automation adapts automatically.

Key Features

🎹 Real-Time MIDI Playback — Interactive TUI with play/pause/stop, sub-5ms timing precision, keyboard controls (Space/Q/R)

🎛️ Device-Specific Aliases — 300+ aliases for 6 devices (Quad Cortex, H90, Helix, HX Stomp, HX Effects, HX Stomp XL) — replace raw MIDI with semantic commands

📝 Human-Readable Syntax — Markdown-inspired format, version control friendly, designed for musicians not programmers

Multiple Timing Systems — Absolute [00:16.250], musical [8.2.240], relative [+500ms], simultaneous [@]

🔄 Advanced Automation — Variables, loops, conditionals, sweeps, generative patterns with random(), Bezier curves, LFO modulation, envelopes

📊 Comprehensive Output — MIDI files (formats 0/1/2), JSON export, CSV export (midicsv-compatible), Rich table display for debugging

Quick Example

Imagine you're setting up a live performance with your Neural DSP Quad Cortex and need to automate preset changes throughout your set. With traditional MIDI, you'd have to manually configure bank selects and program changes. With MML, you write human-readable code and let the compiler handle the complexity:

---
title: "Live Performance - Quad Cortex Automation"
tempo: 120
ppq: 480
---

# Import device-specific aliases for Quad Cortex
@import "devices/quad_cortex.mmd"

# Define reusable scene transitions with timing
@alias switch_scene {ch} {scene} {name}
  - marker "{name}"
  - cc {ch}.34.{scene}    # CC#34 = scene select
  - [+100ms]              # Account for device latency
@end

# ============= INTRO (Clean Tones) =============
[00:00.000]
- tempo 120
- qc_load_preset 1 0 0 5  # Load preset 5 from Setlist 1

# Build tone with gain automation
[00:04.000]
- switch_scene 1 0 "Intro - Scene A (Clean)"

# ============= VERSE (Rhythm Tone) =============
[00:16.000]
- switch_scene 1 1 "Verse - Scene B (Light OD)"

# Boost volume for section
[00:20.000]
- cc 1.7.100  # Master volume to 100

# ============= CHORUS (Heavy Tone) =============
[00:32.000]
- switch_scene 1 2 "Chorus - Scene C (Heavy Distortion)"

# ============= SOLO (Lead Tone) =============
[00:48.000]
- qc_load_preset 1 0 0 12  # Switch to lead preset
- [+150ms]
- switch_scene 1 3 "Solo - Scene D (High Gain Lead)"

# ============= OUTRO =============
[01:04.000]
- switch_scene 1 0 "Outro - Back to Clean"

Compile it:

mmdc compile performance.mmd -o performance.mid

Play it live:

mmdc play performance.mmd --port "Quad Cortex MIDI"

What just happened:

  • You imported Neural DSP's device library with 86+ pre-built aliases
  • You wrote readable, structured code using switch_scene and qc_load_preset instead of cryptic CC/PC numbers
  • Automatic delays are built in so your device has time to process messages
  • The compiler generated precise MIDI timing (down to milliseconds)
  • You can now sync your entire performance to your DAW or play it standalone in real-time

This is what makes MMD special: device automation becomes readable, reusable, and reliable.

Getting Started

New to MMD? Check out the Getting Started Guide for a 5-minute tutorial.

Installation

Recommended (pipx):

pipx install midi-markdown
mmdc --version

Alternative (pip):

pip install midi-markdown

Development (from source):

git clone https://github.com/cjgdev/midi-markdown.git
cd midi-markdown
uv sync  # or: pip install -e ".[dev]"

Standalone executables (no Python required): Download from GitHub Releases for Linux, macOS, and Windows.

See Installation Guide for detailed platform-specific instructions.

Usage

CLI Commands

# Compile MMD to MIDI
mmdc compile song.mmd -o song.mid

# Real-time playback (NEW - Phase 3)
mmdc play song.mmd --port "IAC Driver Bus 1"
mmdc play song.mmd --port 0 --no-ui
mmdc play --list-ports

# Validate MMD syntax
mmdc validate song.mmd

# Quick syntax check
mmdc check song.mmd

# Show version
mmdc version

# Device library management
mmdc library list
mmdc library info quad_cortex

Python API

# TODO: API usage examples once implementation is complete
from midi_markdown import compile_mml

compile_mml("song.mmd", "output.mid", ppq=480)

Claude Code Skills

For Claude Code users: MIDI Markdown provides official Claude Code skills to enhance your development experience:

  • mmd-writing - Help writing MMD files with correct syntax, timing, and commands
  • mmdc-cli-usage - Help using the mmdc CLI effectively

Installation: Download the skills package from the latest release and run the included installation script. See the Claude Skills documentation for detailed instructions.

Benefits:

  • ✅ Automatic syntax help when editing .mmd files
  • ✅ CLI command suggestions and best practices
  • ✅ Error troubleshooting and debugging assistance
  • ✅ Example code and common patterns

Device Libraries

Device libraries enable semantic commands that replace raw MIDI sequences. Instead of manual CC/PC sequences, write cortex_load 1.2.0.5 for "Load Setlist 2, Group A, Preset 5"—much clearer and easier to maintain. MIDI Markdown includes 300+ pre-built aliases across 6 device libraries:

Device Aliases Key Features
Neural DSP Quad Cortex 86 Preset loading, scene switching, I/O routing
Eventide H90 61 Preset management, parameter control, MIDI mapping
Line 6 Helix Floor/LT/Rack 49 Snapshots, command center, routing
Line 6 HX Effects 40+ Preset switching, bypass, parameters
Line 6 HX Stomp 39 Compact control, scene switching
Line 6 HX Stomp XL 40+ Extended control, preset management

Use device libraries to replace low-level MIDI with expressive, semantic commands:

# Instead of cryptic raw MIDI
- cc 1.32.2               # Bank MSB (unclear!)
- cc 1.0.0                # Bank LSB
- pc 1.5                  # Program Change

# Write clear, semantic commands
- cortex_load 1.2.0.5     # Load Setlist 2, Group A, Preset 5 (obvious!)

# Import device libraries (Stage 8 coming soon)
# @import "devices/quad_cortex.mmd"

Examples

See the examples/README.md for a complete guide with learning path and feature matrix.

Quick Links:

Documentation

Comprehensive documentation is available in the docs/ directory:

Contributing

Contributions are welcome! Whether you're a developer, musician, or device enthusiast, there are many ways to help improve MIDI Markdown.

Quick Start for Contributors

# Clone and setup
git clone https://github.com/cjgdev/midi-markdown.git
cd midi-markdown

# Install dependencies (UV is fast!)
uv sync

# Run tests
just test  # or: pytest

Ways to Contribute

🎛️ Device Libraries (Great First Contribution!)

Creating device libraries is the easiest way to contribute—no complex coding required! If you have a MIDI device with documented CC/PC mappings:

  1. Create a new file in devices/ directory (e.g., devices/axe_fx.mmd)
  2. Add YAML frontmatter with device metadata
  3. Define aliases using the simple alias syntax (just MIDI CC/PC basics needed)
  4. Submit a PR—we'll help with any questions!

See Device Library Creation Guide for step-by-step instructions.

🐛 Bug Reports & Feature Requests

💻 Code Contributions

Focus areas for development:

  • Parser improvements (better error messages, recovery)
  • New MIDI features (MPE, MIDI 2.0 support)
  • CLI enhancements (interactive mode, better diagnostics)
  • Documentation (tutorials, examples, guides)

Code Quality Tools

We use modern Python tooling for code quality:

# Run all quality checks
just check  # or: ruff check . && mypy src

# Auto-fix issues
just fix    # or: ruff format . && ruff check --fix .

# Run tests with coverage
just test-cov  # or: pytest --cov

Development Workflow

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests and quality checks (just check && just test)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

See CONTRIBUTING.md for detailed guidelines (coming soon).

Roadmap

Recently Completed

Real-time MIDI playback with interactive TUI (Phase 3, Nov 2025)

  • Sub-5ms event scheduler, tempo tracking, keyboard controls (Space/Q/R)

Generative & modulation features (Phase 6)

  • Random pattern generation, Bezier curves, LFO, envelope modulation

Diagnostic output formats (Phase 1)

  • JSON, CSV, Rich table display for analysis and debugging

Core compilation pipeline (MVP Complete)

  • Lark parser, alias resolution, variables, loops, sweeps, validation
  • 1090+ tests, 72.53% code coverage

Planned Features

  • REPL mode for interactive editing (Phase 2)
  • MIDI Learn and device interrogation
  • MIDI 2.0 support
  • OSC integration
  • Python/Lua scripting for advanced automation

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspired by Markdown's human-readable syntax
  • Built for musicians and live performers
  • Powered by modern Python tooling: UV, Ruff, Typer, pytest

Links


Built with ❤️ for musicians by musicians — If MMD helps your workflow, give us a ⭐ on GitHub!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

midi_markdown-0.1.0.tar.gz (956.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

midi_markdown-0.1.0-py3-none-any.whl (193.6 kB view details)

Uploaded Python 3

File details

Details for the file midi_markdown-0.1.0.tar.gz.

File metadata

  • Download URL: midi_markdown-0.1.0.tar.gz
  • Upload date:
  • Size: 956.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for midi_markdown-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5aafdc824a38f852a1a99beec66fb55b7b098b668162672c1b303d4900237a87
MD5 d27d7a1861655218f3e9f64f41ea15a7
BLAKE2b-256 463c025099f797c41b1704554b6abaac479a72c7d99212615b736db883d2e4d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for midi_markdown-0.1.0.tar.gz:

Publisher: release.yml on cjgdev/midi-markdown

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file midi_markdown-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: midi_markdown-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 193.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for midi_markdown-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 02e524d4e44927b5969510b9ce7029210f0e861bb7422712f79a183f4e1f554e
MD5 f89a523e3f2a0a98794af7c584cb3f5d
BLAKE2b-256 b242dcacd8f670f8a7b9ce6668adf6e02b5c4c212355e6843ee05aa792dc7272

See more details on using hashes here.

Provenance

The following attestation bundles were made for midi_markdown-0.1.0-py3-none-any.whl:

Publisher: release.yml on cjgdev/midi-markdown

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page