Skip to main content

MuseCPEval

Measures music context preservation between an original audio file and an edited version of it: how much of the original's harmony, rhythm, structure, melody, and timbre survives the edit.

Give it a reference/estimate pair and it returns a JSON object of scores. Give it a manifest or a pair of directories and it scores thousands of pairs in parallel.

Metrics

CLI name Output key Returns
harmony harmony_tonality key_relatedness (distance_steps, distance_norm_0to1), chroma_similarity (chroma_dtw_cosine, mean_chroma_cosine)
rhythm rhythm_meter delta_bpm_folded, beat_mir_eval (F-measure, Information gain)
structure structural_form pairwise_f, ari
melody melodic_content contour_dtw_similarity, motif_3gram_recall
timbre timbre_texture mfcc_skl_similarity, mean_mfcc_cosine

All five run by default. Scoring an identical pair (same file as reference and estimate) returns 1.0 on the similarity metrics and 0.0 on the distance metrics — mean_chroma_cosine lands a few float ulps short of 1.0 rather than exactly on it. That is a quick way to confirm an install is sane.

Data

The audio used for the objective evaluation is available on Google Drive.

Install

The metric code needs numpy ≤ 2.2 — librosa depends on numba, and numba refuses newer numpy — so a dedicated environment is the least painful route:

conda create -y -n musecpeval python=3.10
conda activate musecpeval

pip install musecpeval==0.3.0

Pinning the version is the recommended form — the metric numbers are what you cite, so you want them reproducible. pip install musecpeval takes the newest release instead. Published at pypi.org/project/musecpeval.

Installing from GitHub instead

For an unreleased change, or to work on the metrics:

pip install "git+https://github.com/Yashvishe13/MuseCPEval.git"   # straight from main
pip install "git+https://github.com/Yashvishe13/MuseCPEval.git@v0.1.0"  # at a tag

git clone https://github.com/Yashvishe13/MuseCPEval.git && cd MuseCPEval
pip install .                   # from a clone
pip install -e .                # editable, so edits to the metrics take effect

Either way you get the musecpeval command and the importable package:

from musecpeval import (
    harmony_score, melody_score, rhythm_score, structural_score, timbre_score,
)

harmony_score("original.wav", "edited.wav")

--metrics structure additionally needs msaf, which is not pulled in by default: its PyPI release is old and pins numpy/scipy versions that fight the rest of the stack, so install it yourself and expect to referee the pins.

pip install msaf                # or: pip install "musecpeval[structure]"

Verify:

musecpeval --ref path/to/file.wav --est path/to/file.wav

python -m musecpeval is equivalent, and python runner.py still works from a clone without installing anything.

Run

Single pair

# JSON to stdout
musecpeval --ref original.wav --est edited.wav

# JSON to a file
musecpeval --ref original.wav --est edited.wav --out-json result.json

# a subset of metrics
musecpeval --ref original.wav --est edited.wav --metrics harmony rhythm

Batch

Exactly one input source is required.

# JSON manifest
musecpeval --batch-json pairs.json --output-dir results/

# CSV manifest
musecpeval --batch-csv pairs.csv --output-dir results/

# two flat directories, paired by filename
musecpeval --ref-dir originals/ --est-dir edited/ --output-dir results/

# nested edits (edited/<section>/<slug>/001.wav) against flat originals
musecpeval --ref-dir originals/ --est-dir edited/ --recursive --output-dir results/
[
  {"ref": "originals/001.wav", "est": "edited/harmony/-3semitone/001.wav",
   "id": "harmony/-3semitone/001", "section": "harmony", "n_steps": -3}
]

Output

--output-dir receives three files:

File Contents
results.jsonl one record per pair, appended and flushed as each finishes
results.json the same records as a single array, written at the end
summary.csv one row per pair, nested scores flattened to dotted columns

results.jsonl is what makes a run resumable, so it is written incrementally; results.json and summary.csv only appear once the run finishes.

Resuming

Rerunning the same command skips pairs already present in results.jsonl, so an interrupted job continues instead of restarting. Ctrl-C exits 130 with partial results intact. Pass --no-resume to discard prior results and start clean.

Pairs are identified by id when present, otherwise by the absolute ref and est paths.

There is no lock file: two runs against the same --output-dir can process the same pairs. Use separate output directories for concurrent jobs.

Options

Flag Meaning
--ref FILE, --est FILE single-pair input
--out-json FILE single mode: write here instead of stdout
--batch-json FILE batch from a JSON manifest
--batch-csv FILE batch from a CSV manifest
--ref-dir DIR, --est-dir DIR batch by pairing two directories
--recursive walk --est-dir subdirectories
--ext EXT extension for directory pairing (default .wav)
--output-dir DIR batch output directory (default ./results)
--metrics ... any of harmony rhythm structure melody timbre (default: all)
--n-workers N worker processes (default min(8, cpus - 1))
--max-cpu use every CPU as a worker
--no-parallel run serially in one process
--no-resume ignore and overwrite prior results
--limit N only the first N pairs, for smoke tests

Worker count is capped at the number of pairs.

Exit codes

Code Meaning
0 everything scored cleanly
1 a pair failed, a metric family failed, or a score was degraded — or bad arguments
130 interrupted; partial results kept and resumable

Repository layout

musecpeval/
  __init__.py          lazily re-exports the five scoring functions
  __main__.py          `python -m musecpeval`
  runner.py            CLI: single-pair and batch evaluation
  metrics/             the five metric families
    harmony_tonality.py  key relatedness, chroma similarity
    rhythm_meter.py      tempo delta, beat F-measure
    structural_form.py   segmentation agreement (needs msaf)
    melody_motif.py      contour DTW, motif n-gram recall
    timbre.py            MFCC symmetric-KL similarity, mean-MFCC cosine
    utils.py             shared helpers
pyproject.toml         deps, the [structure] extra, the `musecpeval` entry point
requirements.txt       mirror of the dependency list, for `pip install -r`
runner.py              shim, so `python runner.py` keeps working from a clone

Each metric module also has its own __main__ block that scores a directory of pairs for that family alone — python -m musecpeval.metrics.rhythm_meter --orig-dir a/ --edit-dir b/. The flag spelling is not consistent between them: rhythm_meter.py and timbre.py take --orig-dir / --edit-dir, the other three take --orig_dir / --edit_dir.

Download files

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

Source Distribution

musecpeval-0.3.0.tar.gz (32.8 kB view details)

Uploaded Source

Built Distribution

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

musecpeval-0.3.0-py3-none-any.whl (35.6 kB view details)

Uploaded Python 3

File details

Details for the file musecpeval-0.3.0.tar.gz.

File metadata

  • Download URL: musecpeval-0.3.0.tar.gz
  • Upload date:
  • Size: 32.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.2

File hashes

Hashes for musecpeval-0.3.0.tar.gz
Algorithm Hash digest
SHA256 51b8efd2597a2538c53e27dd55df9af0efac719560f385cb65145691a2db3bbe
MD5 6c6ea0421e3367ab1059a3c92f00e789
BLAKE2b-256 0bff65b5c164afe4fb60d964b1bc7240d3f1c70f047c14e44028a8a212c25905

See more details on using hashes here.

File details

Details for the file musecpeval-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: musecpeval-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 35.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.2

File hashes

Hashes for musecpeval-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1e2c0a671fdcb486dd2c2a1a7351c2f8cf098cfb1173b6e35ed6c02eb977ce34
MD5 d911d61adafd7715190ed1d1bf042a5b
BLAKE2b-256 94bdead7ee25ee10221048dc6f776b8fc617302ed6c09185d301aebd74a1f3aa

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page