Spaces:
Sleeping
MusES
MusES is a Python library for representing and transforming musical objects: notes, temporal collections, multi-track pieces, realized chords, scales, chord names, and small generation-oriented workflows.
It is deliberately more oriented toward creating, editing, and generating music than toward large-scale symbolic analysis. MusES keeps common construction, pitch/key handling, and MIDI-editing operations lightweight.
The project continues a line of MusES implementations in Smalltalk, Java, and Python. It is still evolving, so the current priority is to make the core object model reliable, documented, and pleasant to use from other projects.
What It Provides
TemporalNote: a MIDI pitch with start beat, duration, velocity, and channel.TemporalCollection: an ordered stream of temporal objects, useful for melodies, bass lines, chord tracks, or generated material.Piece: a multi-track musical object with MIDI load/save support.RealizedChord: a temporal sonority with one shared span and several pitches.- MusicXML export for simple notatable
Pieceobjects. ChordNamer: jazz/pop chord naming from MIDI pitch sets.- Lightweight pitch helpers for pitch names, pitch classes, MIDI conversion, and simple intervals.
Scale,MajorScale,HarmonicMinorScale,MelodicMinorScale: scale objects for pitch generation and compatibility checks.- Transformations such as transposition, stretching, reversing, concatenation, soprano extraction, negative harmony, and chordification.
Installation
From the repository root:
python3 -m venv venv
source venv/bin/activate
python3 -m pip install -e .
If you use uv:
uv sync
uv run pytest -q
Quick Examples
Create a melody and write it to MIDI:
from muses.base.temporals import Piece, TemporalCollection
melody = TemporalCollection(name="phrase", instrument="piano")
melody.insert_note(60, start=0.0, dur=1.0)
melody.insert_note(64, start=1.0, dur=1.0)
melody.insert_note(67, start=2.0, dur=1.0)
piece = Piece(name="demo", melodies=[melody], key_signature="C")
piece.save_midi("demo.mid")
Export the same material as MusicXML for notation tools:
from muses.base.temporals import Piece, TemporalCollection
from muses.io import write_musicxml
melody = TemporalCollection(name="phrase", instrument="piano")
melody.insert_note(60, start=0.0, dur=1.0)
melody.insert_note(64, start=1.0, dur=0.5)
melody.insert_note(67, start=1.5, dur=0.5)
piece = Piece(title="Demo", composer="MusES", melodies=[melody], key_signature="C")
write_musicxml(piece, "demo.musicxml")
MusicXML exports are written as self-contained score excerpts: the final measure is padded with rests when needed and ends with a final barline.
Load a MIDI file and create its negative harmony:
from muses.base.temporals import Piece
piece = Piece.load_midi("data/prelude_c.mid")
negative = piece.negative_harmony(tonic=60, adjust_octaves=True)
negative.save_midi("data/prelude_c_negative.mid")
Name scale-tone chords:
from muses.base.chord_names import ChordNamer
from muses.base.scales import MajorScale
namer = ChordNamer("data/all_chords_C.txt", max_polyphony=5)
for chord in MajorScale("D").get_scale_tone_chords(4):
print(chord, namer.name_for(chord))
Chordify a multi-track piece into temporal sonorities:
from muses.base.temporals import Piece
piece = Piece.load_midi("data/nice_chords.mid")
chords = piece.chordify_collection(min_notes=2)
for chord in chords.temporals:
print(chord.start_beat, chord.duration(), chord.get_pitches())
chords.save_midi("data/chordified.mid")
Examples
The examples/ directory contains small runnable scripts:
examples/harmony/analyze_progression.py: name chords in a progression.examples/harmony/compare_tonality_methods.py: compare the former transition-only DP analysis with tonal-parsimony analysis on the corpus.examples/harmony/tonality_path_analysis.py: assign a parsimonious tonality path to a progression or a slice ofdata/chord_sequences.txt.examples/harmony/generate_tonal_parsimony_sequences.py: use the siblingvo_regular_bpproject to generate endpoint-constrained chord sequences and cluster them by post-analysis tonal-parsimony K.examples/harmony/name_midi_chords.py: split and name chords from MIDI.examples/harmony/negative_harmony.py: mirror a phrase through negative harmony and optionally save it as MIDI.examples/harmony/scale_detection.py: find candidate scales for a melody.examples/harmony/soprano_extraction.py: extract a top voice from MIDI.examples/harmony/pitch_profile_weights.py: inspect pitch-profile weights.examples/generation/scale_phrase.py: generate a phrase from a scale.examples/generation/polya_melody.py: generate a phrase with the experimental Polya urn.examples/midi/transform_midi.py: load, transform, and optionally save MIDI.examples/quickstart.py: small end-to-end workflow.examples/interaction/harmonizer_setup.py: inspect MIDI ports and bootstrap an interactive harmonizer session.
Run them with:
uv run python examples/harmony/negative_harmony.py
Tonality Analysis Layers
The harmonic-analysis code is intentionally split into layers. The detailed
guide is in src/muses/analysis/README.md.
The current full-corpus comparison report is in
docs/tonality_analysis_comparison.md.
algos.dynaprog.VariableDomainSequenceOptimizer: generic variable-domain sequence DP. It knows nothing about chords, scales, or tonalities.muses.base.tonality_path_analyzer.best_tonality_path: the core tonal-parsimony solver, minimizing modulations and then distinct tonalities.muses.base.chord_sequence_analyzer.ChordSequenceAnalyzer: the backward-compatible simple facade for one-off chord sequence analysis.muses.analysis.tonality_methods: named analysis methods that can be compared side by side, currently transition-only DP, pure NValue hitting set, and tonal parsimony.muses.analysis.tonality_corpus: corpus parsing, chord-name-to-domain construction, and reusable multi-method comparison utilities.muses.analysis.expert_jazz_bench: curated mDecks expert-jazz cases with both functional-root and chord-scale agreement scores.muses.analysis.mdecks_pdf_extractor: local extraction pipeline for user-owned mDecks PDFs, producing reusable chord sequences plus chord-scale and beat-position metadata.examples/harmony/*.py: command-line entry points that demonstrate or report on the analysis methods without defining the core algorithms.
For adding another method, start with muses.analysis.tonality_methods; the
corpus comparison script is method-list driven, so it can grow without changing
the corpus parsing or reporting utilities.
Design Direction
MusES aims to be a compact musical object library for generative systems:
- Keep the core temporal model simple and explicit.
- Prefer transformations that return new musical objects instead of mutating inputs unexpectedly.
- Preserve enough MIDI metadata to make load/transform/save workflows reliable.
- Keep chord objects temporal without duplicating onset/duration on every pitch.
- Keep experimental generation algorithms available, but separate from the stable object model.
- Provide examples that can be copied into creative coding projects.
Compared with music21, MusES is not trying to cover all musicological analysis.
It is meant to make musical material easy to construct, transform, generate, and
send back to MIDI.
Experimental madrigal-to-string-quartet reduction code now lives in a separate
gesualdo project next to this repository, so it can evolve as research code
without adding heavy notation dependencies to the core package.
Development
Run the tests:
uv run pytest -q
The current tests focus on temporal collection behavior, MIDI metadata handling, MusicXML export, chord naming, pitch helpers, chordification, and negative harmony.
Background
MusES is inspired by earlier work including:
- Pachet, F., Ramalho, G., and Carrive, J. "Representing Temporal Musical Objects and Reasoning in the MusES System." Journal of New Music Research, 25(3):252-275, 1996.
- Pachet, F., Ramalho, G., Carrive, J., and Cornic, G. "Representing temporal objects and reasoning in the MusES system." International Congress on Music and Artificial Intelligence, Edinburgh, 1995.
- Pachet, F. "The MusES system: an environment for experimenting with knowledge representation techniques in tonal harmony." First Brazilian Symposium on Computer Music, 1994.
- Pachet, F. "An Object-Oriented Representation of Pitch-Classes, Intervals, Scales and Chords." Journees d'Informatique Musicale, Bordeaux, 1994.
Author
License
MIT. See LICENSE for details.