MAJEPPA

MAJEPPA is a unified self-supervised model for piano performance that both generates and understands solo-piano MIDI in a single framework. Built on a pre-trained MIDI autoregressive backbone, it combines score-conditioned next-token prediction with a Joint-Embedding Predictive Architecture (JEPA) objective β€” learning to produce expressive continuations while also yielding transferable embeddings for downstream analysis.

Applications include score-conditioned generation across expertise levels, performance quality assessment, competition ranking, technique classification, mistake detection, and expressive-style analysis.

πŸ“– Paper: MAJEPPA: Morphing and Assessing in a Unified Piano Performance Space (ISMIR 2026)
πŸ’» Code (loading, inference, generation): github.com/anusfoil/majeppa
πŸ“Š Benchmark: github.com/anusfoil/evpmr

Model Details

  • Base model: loubb/aria-medium β€” 660M-parameter LLaMA-style autoregressive MIDI transformer.
  • Adaptation: Low-Rank Adaptation (LoRA, rank 512) on attention projections; a linear projection head 1536 β†’ 512 for global embedding output; and additional learned tokens for conditioning ([COND_perf], [COND_rec]) and prediction ([PRED]).
  • Context length: 4096 tokens (linear RoPE scaling).

model.safetensors contains the full set of weights (base model, LoRA adapters, projection head, and added token embeddings), ready to be loaded together.

Quickstart

pip install torch safetensors transformers
pip install git+https://github.com/EleutherAI/aria-utils.git

Load via the reference implementation in the MAJEPPA repository:

Understanding β€” global embedding

from majeppa import load_model, load_tokenizer

model = load_model("anusfoil/majeppa", device="cuda")
tokenizer = load_tokenizer()

tokens = tokenizer.encode_from_file("performance.mid", return_tensors="pt")
embedding = model.encode(tokens.to("cuda"))       # (1, 1536)
token_emb, ts = model.encode_tokens(tokens.to("cuda"))  # (T, 1536), (T,)

Generation β€” score-conditioned performance

score_tokens = tokenizer.encode_from_file("score.mid", return_tensors="pt")

# Condition on performer type and recording context
performance = model.generate(
    score_tokens.to("cuda"),
    cond_performer="virtuoso",      # or "child_beginner", "adult_intermediate", ...
    cond_recording="concert",       # or "practice", "sight_reading", "demo", ...
    max_new_tokens=2048,
    temperature=0.8,
    top_k=50,
)
tokenizer.decode_to_file(performance, "generated.mid")

See the repository for the full list of condition tags and advanced usage.

Intended Use

For non-commercial research on symbolic piano performance modelling. Refer to the paper for evaluation protocols and limitations.

Citation

@inproceedings{zhou2026majeppa,
  title  = {MAJEPPA: Morphing and Assessing in a Unified Piano Performance Space},
  author = {Zhou, Jinwen and Zhang, Huan and Zhai, Weixi and Liang, Jinhua and Hogg, Aidan O. T. and Dixon, Simon},
  booktitle = {Proc. International Society for Music Information Retrieval Conference (ISMIR)},
  year   = {2026}
}
Downloads last month
2
Safetensors
Model size
0.7B params
Tensor type
F32
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for anusfoil/majeppa

Finetuned
(1)
this model