An open API service indexing awesome lists of open source software.

https://github.com/Daninet/mtxt

A human-writable text format for musical notes, timing, and expression.
https://github.com/Daninet/mtxt

format midi music notation sheet-music text

Last synced: 3 days ago
JSON representation

A human-writable text format for musical notes, timing, and expression.

Awesome Lists containing this project

README

          

# MTXT - Music Text Format

MTXT is a human-editable, text-based format for representing musical performance data. It stores events with precise timing, pitch, and expression values in a simple line-based structure that's easy to edit without requiring specialized tools.

The format is designed for cases where exact performance details matter - arbitrary timings, micro-tuning, dynamic changes, and other expressive parameters. MTXT avoids binary encoding, making it suitable for manual and AI-assisted editing.

## Features
- **Beat-based**: Events are placed on fractional beats using simple decimal notation (e.g., in a 4/4 time signature, 1 beat = 1 quarter note, so 3.25 represents 3 quarter notes plus 1 sixteenth note).
- **One event per line**: Easy to search and modify with any text editor.
- **Human-friendly**: Use of musical note names (C4, D#3, etc.) and custom note aliases (e.g. `kick` or `Cmaj7`). Hand-crafted files are practical and expressive.
- **Transitions**: Built-in support for gliding continuous parameters (CC, tempo) with customizable curves and timing.
- **Real-time ready**: Supports streaming musical events and real-time data transfer with transitions and flexible timing.
- **Microtonal support**: Built-in cents notation for notes (e.g. `C4+50`, `D4-25`) and global tuning commands for alternate tuning systems and just intonation.
- **Flexible organization**: Events can be written in any order in the file, with the parser handling chronological sorting.
- **MIDI compatible**: Reference implementation includes MIDI to MTXT and MTXT to MIDI conversion.
- **LLM compatible**: Can be easily generated and manipulated by language models.
- **Future-proof**: Supports up to 65535 channels, arbitrary CC parameters with custom string keys and custom metadata.

## Quick Example
```
mtxt 1.0
meta global title Sunrise Melody
meta global author Jane Composer

// Define aliases for drums and chords
alias kick C1
alias Cmaj7 C4,E4,G4,B4

// Global tempo and time signature
0.0 tempo 100
0.0 timesig 4/4

// Set defaults for channel, duration, and velocity
ch=0
dur=1.0
vel=0.8

// Set voice. "John's bright grand" has precedence, but it falls back to a more generic "piano" if not found.
0.0 voice piano, John's bright grand

// Start silently
0.0 cc volume 0.0

// Fade in volume over 3.0 beats, ending at beat 4.0
4.0 cc volume 1.0 transition_time=3.0 transition_curve=0.5

// Play melody (uses default duration and velocity from above, unless overridden)
0.0 note C4
2.0 note G4 vel=0.5
// Notes can be put in arbitrary order, the parser will sort them
1.0 note E4
2.0 note G4 vel=0.5

// Chords can also be played (defined above as an alias for C4,E4,G4,B4 notes)
1.0 note Cmaj7 dur=2.0 vel=0.2

// Tempo ramp
8.0 tempo 120 transition_time=4.0

// Microtonal note (12TET equal temperament C4 + 50 cents)
3.0 note C4+50
```

## Rust Library and CLI Tool

This repository includes a reference implementation in Rust that provides:

- **Library (`mtxt`)**: Rust crate for parsing and writing MTXT files, with MIDI conversion features.
- **CLI tool**: Command-line utility for converting between MIDI and MTXT formats with built-in transforms. Builds can be downloaded from [releases](https://github.com/Daninet/mtxt/releases).

### Basic Usage

```bash
mtxt input.mid output.mtxt # MIDI to MTXT
mtxt input.mtxt output.mid # MTXT to MIDI
mtxt input.mtxt output.mtxt --sort # transform MTXT file and sort events by time
```

### Transform Options

The CLI supports various transforms that can be applied during conversion:

**Musical Transforms:**
- `--transpose ` - Transpose all notes by semitones (e.g., `--transpose +2` or `--transpose -12`)
- `-q, --quantize ` - Quantize timing to a grid (e.g., `4` for quarter notes, `16` for 16th notes)
- `--offset ` - Offset all events by beats (e.g., `--offset 1.5`, `--offset -0.5`). Events shifted to negative times are removed.
- `--swing ` - Apply swing feel (0.0 to 1.0)
- `--humanize ` - Add timing randomization for humanization (0.0 to 1.0)

**Channel Filtering:**
- `--include-channels ` - Include only specific channels (comma-separated, e.g., `1,2,10`)
- `--exclude-channels ` - Exclude specific channels (comma-separated, e.g., `1,2,10`)

**File Organization:**
- `--apply-directives` - Apply global directives to events (inline parameters)
- `--extract-directives` - Extract common inline parameters into global directives
- `--merge-notes` - Merge note on / off pairs into note shorthand events with durations
- `--group-channels` - Group events by channel
- `--sort` - Sort events by time
- `--indent` - Enable timestamp padding

---

## MTXT Specification

## Versioning

- First line must declare version:
```
mtxt 1.0
```

## Structure

- A file consists of:
1. Version line
2. Global metadata (optional)
3. Events (can be in any timestamp order)

## Timing

- All times are in beats specified as fractional numbers. e.g. in a 4/4 time signature, 1 beat = 1 quarter note, so 3.25 represents 3 quarter notes plus 1 sixteenth note.
- This allows changing the tempo and time signature without affecting the timing of events.
- Events may appear in any order in the file; the parser will sort them before playback
- Precision is limited to 5 decimal places (5 microseconds at 120 BPM).

## Commands

### version (mtxt)
```
mtxt
```
- Declares the file format version in the major.minor format (e.g., `mtxt 1.0`).
- Must be the first non-comment line.

### meta
```
// global meta (applies to the entire file and all channels)
meta global
// channel meta (applies to a single channel), starting from the specified time
[

#### Standard Meta Types

| Type | Description | Example |
| -------------- | ---------------- | ----------------------------------------- |
| `title` | Song title | `meta global title My Song` |
| `author` | Composer/author | `meta global author John Doe` |
| `copyright` | Copyright notice | `meta global copyright © 2024 Music Corp` |
| `composer` | Composer name | `meta global composer John Doe` |
| `name` | Channel name | `meta ch=1 name Lead Guitar` |
| `instrument` | Instrument name | `meta ch=2 instrument Steinway Grand` |
| `smpte` | SMPTE offset | `meta global smpte 00:00:00:00` |
| `keysignature` | Key signature | `4.0 meta ch=3 keysignature C major` |
| `text` | General text | `meta text Verse 1` |
| `lyric` | Lyrics | `5.0 meta lyric Hello world` |
| `marker` | Marker/cue point | `6.0 meta marker Chorus` |
| `cue` | Cue point | `7.0 meta cue Solo begins` |
| `program` | Program name | `meta global program Piano Ballad` |
| `device` | Device name | `meta global device OpenPiano 1000` |
| `key` | Key signature | `meta global key C major` |
| `date` | Creation date | `meta global date 2024-01-01` |
| `genre` | Musical genre | `meta global genre Rock` |
| `album` | Album name | `meta global album Greatest Hits` |
| `url` | Related URL | `meta global url https://example.com` |
| `artist` | Performer name | `meta global artist The Band` |
| `license` | Usage license | `meta global license CC-BY-4.0` |
| `generator` | Software tool | `meta global generator MySequencer v1.0` |

### ch (channel directive)
```
ch=<0..65535>
```
- Sets the default MIDI channel for subsequent events.
- Inline `ch=` on events overrides the default for that event only.
- Required before channel-dependent events that omit inline `ch`.

### alias (note naming)
```
alias
```
- Defines a named alias for a note pitch or a chord.
- ``: Alphanumeric identifier (e.g., `snare`, `Cmaj7`).
- ``: Target note(s), comma-separated if multiple.
- No timestamp. Applies to all subsequent events in the file until overridden.
- Name is case-insensitive.
- Example:
```
alias snare C2
alias Cmaj7 C4,E4,G4,B4 // chord alias
0.0 note snare
1.0 note Cmaj7 // plays all 4 notes
```

### vel (default note-on velocity)
```
vel=<0.0..1.0>
```
- Sets the default note-on velocity.
- Inline `vel=` on `note`/`on` overrides for that event.

### offvel (default note-off velocity)
```
offvel=<0.0..1.0>
```
- Sets the default note-off velocity.
- Inline `offvel=` on `note`/`off` overrides for that event.
- Defaults to `1.0` if not set.

### dur (default note duration)
```
dur=
```
- Sets the default note duration in beats.
- Inline `dur=` on `note` overrides for that event.
- Defaults to `1.0` if not set.

### transition settings
```
transition_curve=
transition_interval=
```
- Sets default transition parameters for `cc` and `tempo`.
- `transition_time` must be specified per event (default `0.0`).
- See **Transitions** section for details.
- Defaults: `curve=0.0`, `interval=1.0`.

### note (shorthand)
```

### on (note-on)
```

### off (note-off)
```

### cc (control change)
```

#### Standard CC Names

| Name | Range | Description |
| ------------------- | ------------- | ------------------------------------------------------------------------------- |
| `pitch` | `-12.0..12.0` | Pitch bend in semitones. 0=none, 1 = one semitone up, `-0.005` = half cent down |
| `aftertouch` | `0.0..1.0` | Channel or Polyphonic Aftertouch |
| `vibrato` | `0.0..1.0` | Vibrato depth (Modulation Wheel) |
| `vibrato_rate` | `0.0..1024.0` | Vibrato rate in Hz |
| `breath` | `0.0..1.0` | Breath controller pressure |
| `foot` | `0.0..1.0` | Foot controller pedal position |
| `portamento` | `0.0..1.0` | Portamento glide time |
| `volume` | `0.0..1.0` | Channel volume level |
| `balance` | `-1.0..1.0` | Stereo balance (left < 0, right > 0) |
| `pan` | `-1.0..1.0` | Stereo panning position (left < 0, right > 0) |
| `expression` | `0.0..1.0` | Expression (secondary volume, relative to main) |
| `sustain` | `0.0..1.0` | Sustain pedal (damper) on/off (> 0.5 is on) |
| `portamento_switch` | `0.0..1.0` | Portamento on/off switch (> 0.5 is on) |
| `sostenuto` | `0.0..1.0` | Sostenuto pedal on/off (> 0.5 is on) |
| `soft` | `0.0..1.0` | Soft pedal (una corda) on/off (> 0.5 is on) |
| `legato` | `0.0..1.0` | Legato footswitch on/off (> 0.5 is on) |
| `sound_variation` | `0.0..1.0` | Sound variation |
| `timbre` | `0.0..1.0` | Timbre/harmonic intensity |
| `resonance` | `0.0..1.0` | Resonance/Harmonic Content |
| `attack` | `0.0..1.0` | Attack time |
| `decay` | `0.0..1.0` | Decay time |
| `hold` | `0.0..1.0` | Hold time |
| `sustain_level` | `0.0..1.0` | Sustain level (envelope) |
| `release` | `0.0..1.0` | Release time |
| `cutoff` | `0.0..1.0` | Filter cutoff frequency (Brightness) |
| `reverb` | `0.0..1.0` | Reverb send level |
| `tremolo` | `0.0..1.0` | Tremolo depth |
| `tremolo_rate` | `0.0..1024.0` | Tremolo rate in Hz |
| `chorus` | `0.0..1.0` | Chorus send level |
| `detune` | `0.0..1.0` | Detune depth |
| `phaser` | `0.0..1.0` | Phaser depth |
| `distortion` | `0.0..1.0` | Distortion/Drive amount |
| `compression` | `0.0..1.0` | Compression amount |
| `local_control` | `0.0..1.0` | Local control on/off (> 0.5 is on) |
| `polyphony` | `1.0..1024.0` | Polyphony count (rounded to int). 1=mono |

### voice (instrument selection)
```

### tempo
```

### timesig
```

### tuning
```

### reset
```

### sysex
```

### Comments
```
// full-line comment
// inline comment
```
- Everything after `//` is ignored by the parser (except for `://` in URLs).

## Transitions

Use transitions to glide a continuous parameter to a target value by a specific beat, with a chosen feel.

- Supported on: `cc`, `tempo`.
- Fields:
- `transition_curve=` controls the feel of the glide:
- `0.0` (linear): steady change from start to finish (default)
- `> 0` (gentle start → speeds up): musical "ease-in", swells late.
- `< 0` (fast start → settles): musical "ease-out", arrives smoothly.
- `transition_time=` (`τ`) is the glide length in beats. Defaults to `0.0` (instant jump). The change begins at `T − τ` and reaches the target at command time `T`.
- `transition_interval=` is the minimum time between each value update in milliseconds. Defaults to `1.0` (as fast as possible).

Examples:
- `0.0 cc pitch 0.0` — pitch is `0.0` at `0.0`.
- `1.0 cc pitch 0.5 transition_time=0.2` — pitch glides to `0.5` value between beats `0.8` and `1.0`.
- `5.0 cc pitch 0.95 transition_curve=0.5 transition_time=1.5` — starts at `3.5`, accelerates toward `0.95` near `5.0`.
- `7.0 cc volume 0.2 transition_curve=-0.4 transition_time=2.0` — begins at `5.0`, moves quickly then coasts into `0.2` at `7.0`.

Curve definition:
- `value(t) = V0 + (V1 − V0) * ( s + max(α,0) * (s^4 − s) − max(−α,0) * ((1 − (1 − s)^4) − s) )`
- `s = (t − (T − τ)) / τ`; if `τ = 0`, the change is instant at `T`.

Notes:
- Each transition needs a defined value before its end time `T` to establish the start (`V0` at `T − τ`). If no prior value exists, this is an error.
- Overlapping transitions on the same parameter/channel: the new transition immediately aborts the previous at the current value and takes over. When segments conflict, the one with the later end beat (`T`) has precedence.

## Common note lengths

| | Fraction | Expanded | Beats |
|-----------------------|----------|-------------------|-----------|
| Whole | `4/1` | | 4.0 |
| Half | `2/1` | | 2.0 |
| Quarter | `1/1` | | 1.0 |
| Eighth | `1/2` | | 0.5 |
| Sixteenth | `1/4` | | 0.25 |
| Thirty-second | `1/8` | | 0.125 |
| Dotted half | `3/1` | `2 + 1` | 3.0 |
| Dotted quarter | `3/2` | `1 + 1/2` | 1.5 |
| Dotted eighth | `3/4` | `1/2 + 1/4` | 0.75 |
| Dotted sixteenth | `3/8` | `1/4 + 1/8` | 0.375 |
| Double-dotted quarter | `7/4` | `1 + 1/2 + 1/4` | 1.75 |
| Double-dotted eighth | `7/8` | `1/2 + 1/4 + 1/8` | 0.875 |
| Quarter triplet | `2/3` | `1 * 2/3` | 0.666667 |
| Eighth triplet | `1/3` | `1/2 * 2/3` | 0.333333 |
| Sixteenth triplet | `1/6` | `1/4 * 2/3` | 0.166667 |
| Quarter quintuplet | `4/5` | `1 * 4/5` | 0.8 |
| Eighth quintuplet | `2/5` | `1/2 * 4/5` | 0.4 |
| Sixteenth quintuplet | `1/5` | `1/4 * 4/5` | 0.2 |
| Quarter septuplet | `4/7` | `1 * 4/7` | 0.571429 |
| Eighth septuplet | `2/7` | `1/2 * 4/7` | 0.285714 |
| Sixteenth septuplet | `1/7` | `1/4 * 4/7` | 0.142857 |

## License

Copyright © 2025 Dani Biró

MTXT specification and reference implementation are dual-licensed under the Apache-2.0 license or the MIT license, at your option.