Skip to main content

Objective evaluation metrics for Symbolic Music Generation

Project description

smg-metrics

Symbolic Music Generation Metrics — 51 objective evaluation metrics, zero config.

Python 3.10+ License: MIT PyPI version

8 categories, 51 metrics, 20 papers/projects (1990–2026), fully typed & tested.

Category Count Latest source Year
A. Single-file Quality 13 MusPy / XMusic 2025
B. Note-level Pairwise 5 Ou et al. 2025
C. Bar-level Pairwise 2 MuseMorphose 2023
D. Chord-level Pairwise 1 FGG / music-x-lab 2025
E. Distribution-level 5 SongMASS 2020
F. Advanced 14 Text2midi 2025
G. Structural 4 MuseTok 2026
H. Rhythmic/Temporal 7 D3PIA 2026

Quick Start

pip install smg-metrics
from smg_metrics import single_file, single_file_rhythmic, pair_eval

# Single-file quality (13 MusPy metrics)
quality = single_file("generated.mid")
print(quality.pce, quality.ebr, quality.gs)

# Rhythmic metrics (4 D3PIA-style)
rhythm = single_file_rhythmic("generated.mid")
print(rhythm.mean_ioi, rhythm.rhythmic_density)

# Pairwise comparison (10 metrics)
pair = pair_eval("generated.mid", "reference.mid")
print(pair.note_f1, pair.sim_chr, pair.ca)
# CLI
smg-eval -m generated.mid
smg-eval -p gen.mid -r ref.mid
smg-eval -m gen.mid -p gen.mid -r ref.mid -d -a -S -R
smg-eval -m gen.mid --only pce ebr gs --json

Installation

pip install smg-metrics

# Or install from source:
git clone https://github.com/OlyMarco/smg_metric.git
cd smg_metric && pip install -e .
Package Version Purpose
muspy >= 0.5.0 13 single-file quality metrics
miditoolkit >= 1.0 MIDI parsing
pretty-midi >= 0.2.10 Beat tracking & bar-level parsing
mir-eval >= 0.7 Note-overlap metric
numpy >= 1.24 Numerical computation
scipy >= 1.10 Scientific computing

Python API

from smg_metrics import (
    single_file,                # 13 MusPy quality metrics
    single_file_structural,     # 2 structural single-file metrics
    single_file_rhythmic,       # 4 D3PIA-style rhythmic metrics
    pair_eval,                  # 10 core pairwise metrics
    pair_eval_structural,       # 2 structural pairwise metrics
    distribution_eval,          # 5 distribution-level metrics
    advanced_eval,              # 14 advanced metrics
)
Container Fields Count
SingleFileResult pce, ebr, gs, sc, pisr, polyphony, polyphony_rate, pitch_range, n_pitches_used, n_pitch_classes_used, emr, pe, dpc 13
StructuralSingleResult che, ngram_div 2
RhythmicResult mean_ioi, rhythmic_intensity, rhythmic_density, voice_number 4
PairResult note_f1, notei_f1, mel_f1, i_iou, ver, sim_chr, sim_grv, ca, onset_xor, note_overlap 10
StructuralPairResult melody_match, tonal_dist 2
DistributionResult pd, dd, sc_sim, pce_sim, gs_sim 5
AdvancedResult kl_duration, kl_ioi, kl_pitch, oa_duration, oa_ioi, oa_pitch_range, oa_density, ci_precision, ci_recall, ci_f1, cts, cr_pred, cr_ref, recon_acc 14

Every result container is a frozen dataclass with .to_dict().

Chord Recognition

from smg_metrics import recognize_chords, compute_ca

# Beat-level DP chord recognition (music-x-lab algorithm)
chords = recognize_chords("song.mid")
for iv in chords:
    print(f"{iv.start:.2f}-{iv.end:.2f}: {iv.label}")

# Chord Accuracy with DP method (default)
ca = compute_ca("pred.mid", "ref.mid", method="dp")

# Or use Viterbi method (GETMusic)
ca = compute_ca("pred.mid", "ref.mid", method="viterbi")

Individual metrics

from smg_metrics import (
    chord_histogram_entropy, ngram_diversity,
    melody_matchness, tonal_distance,
    compute_ca, midi_to_chords, midi_to_chords_dp,
    mean_ioi, rhythmic_intensity, rhythmic_density,
    voice_number, onset_xor_distance, note_overlap,
    grooving_pattern_similarity,
)

che = chord_histogram_entropy("file.mid")
ca = compute_ca("pred.mid", "ref.mid")
gs = grooving_pattern_similarity("pred.mid", "ref.mid")

CLI Usage

# Single-file quality (13 metrics)
smg-eval -m generated.mid

# Single-file + structural + rhythmic (19 metrics)
smg-eval -m generated.mid -S -R

# Pairwise core (10 metrics)
smg-eval -p gen.mid -r ref.mid

# Full 51-metric run
smg-eval -m gen.mid -p gen.mid -r ref.mid -d -a -S -R

# Select specific metrics
smg-eval -m gen.mid --only pce ebr gs
smg-eval -p gen.mid -r ref.mid --only ca note_f1 grooving_pattern_similarity

# List all available metrics
smg-eval --list-metrics

# JSON output
smg-eval -m gen.mid --json

# Batch directory
smg-eval --pred_dir ./pred/ --ref_dir ./ref/

# Timing
smg-eval -m gen.mid --time
Flag Description Default
-m, --music PATH Single-file mode --
-p, --pred PATH Predicted MIDI for pair mode --
-r, --ref PATH Reference MIDI for pair mode --
--pred_dir DIR Batch predicted directory --
--ref_dir DIR Batch reference directory --
--root INT Root pitch for PISR 0
--mode {major,minor} Scale mode for PISR major
-d, --dist Distribution-level metrics false
-a, --advanced Advanced metrics false
-S, --structural Structural metrics false
-R, --rhythmic Rhythmic metrics false
--only METRIC ... Select specific metrics --
--list-metrics List all metric names --
--json JSON output false
--time Print elapsed time false

Metrics Reference

A. Single-file Quality (13)

Sources: MusPy / ISMIR 2020, XMusic / IEEE 2025.

Metric Symbol Range Reference
Pitch Class Entropy PCE [0, log₂12] Wu & Yang, ISMIR 2020; XMusic 2025
Empty Beat Rate EBR [0, 1] Dong et al., ISMIR 2018; XMusic 2025
Groove Consistency GS [0, 1] Wu & Yang, ISMIR 2020; XMusic 2025
Scale Consistency SC [0, 1] Mogren, NeurIPS-W 2016
Pitch-in-Scale Rate PISR [0, 1] Dong et al., AAAI 2018
Polyphony Poly [1, ∞) Dong et al., AAAI 2018
Polyphony Rate PR [0, 1] Dong et al., AAAI 2018
Pitch Range Range [0, 127] MusPy 2020
Unique Pitches N_p [0, 128] MusPy 2020
Unique Pitch Classes N_pc [0, 12] MusPy 2020
Empty Measure Rate EMR [0, 1] Dong et al., AAAI 2018
Pitch Entropy PE [0, 7] MusPy 2020
Drum Pattern Consistency DPC [0, 1] Dong et al., AAAI 2018

B. Note-level Pairwise (5)

Source: Ou et al., NeurIPS 2025.

Metric Symbol Range
Note F1 F1 [0, 1]
Notei F1 F1i [0, 1]
Melody F1 F1mel [0, 1]
Instrument IoU I-IoU [0, 1]
Voice Error Rate VER [0, ∞)

B2. Pairwise Rhythmic (3)

Sources: D3PIA ICASSP 2026, mir_eval ISMIR 2014, Wu & Yang ISMIR 2020.

Metric Symbol Range
Onset XOR Distance XOR [0, 1]
Note Overlap NOvlp [0, 1]
Grooving Pattern Similarity GS_d3pia [0, ∞)

C. Bar-level Pairwise (2)

Source: MuseMorphose, IEEE/ACM TASLP 2023.

Metric Symbol Range
Chroma Similarity simChr [0, 1]
Groove Similarity simGrv [0, 1]

D. Chord-level Pairwise (1)

Source: FGG ICML 2025, music-x-lab/midi-chord-recognition.

Metric Symbol Range Description
Chord Accuracy CA [0, 1] Beat-level DP chord recognition + exact match

Chord Recognition Pipeline (adapted from music-x-lab):

  1. Extract beat/downbeat positions from MIDI tempo map
  2. Quantise notes to beat grid → per-beat 12-dim treble chroma + bass chroma
  3. Channel-weighted aggregation (thickness + bass reweighting)
  4. Score each chord template per beat (with bass bonus)
  5. Dynamic-programming decode with span-length reward and transition penalty
  6. Output interval-level chord labels

Two methods available: 'dp' (default, beat-level) and 'viterbi' (bar-level HMM).

E. Distribution-level (5)

Sources: SongMASS ACM-MM 2020, MusPy ISMIR 2020.

Metric Symbol Range
Pitch Distribution PD [0, 1]
Duration Distribution DD [0, 1]
Scale Consistency Sim SC_sim [0, 1]
Pitch Class Entropy Sim PCE_sim [0, 1]
Groove Consistency Sim GS_sim [0, 1]

F. Advanced (14)

Sources: GETMusic IJCAI 2025, Rule Guided ICML 2024, Text2midi AAAI 2025, MuseTok ICASSP 2026.

Metric Symbol Range
KL Divergence (Duration) KL_dur [0, ∞)
KL Divergence (IOI) KL_ioi [0, ∞)
KL Divergence (Pitch) KL_pitch [0, ∞)
Overlapping Area ×4 OA [0, 1]
Instrument Coverage ×3 CI [0, 1]
Correct Time Signature CTS {0, 1}
Compression Ratio ×2 CR [0, ∞)
Reconstruction Accuracy ReconAcc [0, 1]

G. Structural (4)

Sources: Papadopoulos & Peeters ISMIR 2012, Yang & Lerch NCA 2018, Mongeau & Sankoff CH 1990, Harte et al. ACM MM 2006.

Metric Symbol Type Range
Chord Histogram Entropy CHE single [0, log₂C]
N-gram Diversity Ngram single [0, 1]
Melody Matchness MM pair [0, 1]
Tonal Distance TD pair [0, ∞)

H. Rhythmic/Temporal Single-file (4)

Source: D3PIA ICASSP 2026, MIDISym feature extraction.

Metric Symbol Range
Mean IOI IOI [0, ∞)
Rhythmic Intensity RI [0, ∞)
Rhythmic Density RD [0, 1]
Voice Number VN [0, ∞)

v5.0 Changelog

New features

  • Beat-level DP chord recognition (music-x-lab algorithm): replaces bar-level Viterbi as default CA method
  • D3PIA Grooving Pattern Similarity: pairwise within-file XOR similarity metric
  • --only flag: select specific metrics for faster evaluation
  • --list-metrics: display all available metric names
  • Short flags: -m, -p, -r, -d, -a, -S, -R for faster CLI usage
  • Lazy imports: faster CLI startup time

Removed

  • OOK (Out-of-Key Rate): requires external key annotations, limited standalone utility
  • Chord Similarity (CS): requires pretrained chord encoder model

Changed

  • CA default method: 'dp' (beat-level) instead of 'viterbi' (bar-level)
  • Distribution metrics: removed OOK (PD, DD, SC_sim, PCE_sim, GS_sim remain)
  • Numpy: removed <2.0 upper bound
  • Version: 0.4.0 → 5.0.0

License

MIT — see LICENCE.

Citation

If you use smg-metrics in your research, please cite:

@software{smg_metrics,
  title  = {smg-metrics: Objective Evaluation Metrics for Symbolic Music Generation},
  author = {Temmie Pratt},
  year   = {2026},
  url    = {https://github.com/OlyMarco/smg_metric},
}

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

smg_metrics-5.0.0.tar.gz (44.1 kB view details)

Uploaded Source

Built Distribution

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

smg_metrics-5.0.0-py3-none-any.whl (49.9 kB view details)

Uploaded Python 3

File details

Details for the file smg_metrics-5.0.0.tar.gz.

File metadata

  • Download URL: smg_metrics-5.0.0.tar.gz
  • Upload date:
  • Size: 44.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for smg_metrics-5.0.0.tar.gz
Algorithm Hash digest
SHA256 2965d36ee6833fc071098c43f94d6d7834000c49ec06812ffbcff58fba857fbe
MD5 b4dcade9b1445294d693f4cc2d88765a
BLAKE2b-256 bb2d590b2732cd04a9abba6d1fe91de729e9694cdbc002a0122086c51f1f009d

See more details on using hashes here.

File details

Details for the file smg_metrics-5.0.0-py3-none-any.whl.

File metadata

  • Download URL: smg_metrics-5.0.0-py3-none-any.whl
  • Upload date:
  • Size: 49.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for smg_metrics-5.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 844aa219145e4264ca97c73d35f82f2cbaa0eb2a3560cd9c73202656118585d1
MD5 dca70948b7b4236d1be13dcff36232ac
BLAKE2b-256 7de1333fa37247db7f6c208b4d9babe57385b7587aea9cb97830ca1d0ad57661

See more details on using hashes here.

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