Skip to main content

Melody-Features

Open in GitHub Codespaces

DOI

Tests

Coverage

Overview

This is a Python package designed to facilitate the use of many different melody analysis tools.

The main goal of this package is to consolidate a wide range of features from the computational melody analysis literature into a single place, in a single language.

This package is strictly for monophonic melodies - it will not compute any features for polyphonic music!

Included Contributions

Included in the package are contributions from:

  • FANTASTIC (Müllensiefen, 2009)
  • SIMILE (Müllensiefen & Frieler, 2006)
  • melsim (Silas & Frieler, n.d.)
  • jSymbolic2 (McKay & Fujinaga, 2006)
  • IDyOM (Pearce, 2005)
  • MIDI Toolbox (Eerola & Toiviainen, 2004)
  • MUST (Clemente et al., 2020)
  • Partitura (Cancino-Chacón, 2022)

Melody Features Summary

This package provides over 200 features from various computational melody analysis frameworks. For a comprehensive, interactive table with search and sorting capabilities, refer to:

Interactive Features Table

The interactive table allows you to:

  • Search features by name, implementation, or description
  • Sort by any column (Name, Implementation, Type, etc.)
  • Browse all features with detailed descriptions and references

Installation

# using pip
pip install melody-features

# or clone the repository
git clone https://github.com/dmwhyatt/melody-features.git
cd melody-features

# Install in development mode
pip install -e .

Quick Start

The feature set can be easily accessed using the top-level function get_all_features. Here's a basic example:

from melody_features import get_all_features

# Extract features from a directory of MIDI files, a single MIDI file
# or a list of paths to MIDI files
results = get_all_features(input="path/to/your/midi/files")

# Print the result of all feature calculations
print(results.iloc[:1,].to_json(indent=4, orient="records"))

By default, this function will produce a Pandas DataFrame containing the tabulated features, using the a collection of 903 Western traditional music melodies as the reference corpus, from Pearce (2006).

This function can be customised in a number of ways, please see notebooks/example.ipynb for a detailed breakdown.

Long format

By default get_all_features returns one row per melody, with one column per feature ({family}.{feature_name}, e.g. absolute_pitch.pitch_range). Pass long_format=True to instead get a tidy long-format DataFrame with one row per melody/feature combination.

from melody_features import get_all_features, get_feature_metadata, to_long_format

long_results = get_all_features(input="path/to/your/midi/files", long_format=True)
# columns: melody_num, melody_id, feature_name, family, source, domain, type, value, description, notes, references

# e.g. keep only descriptor-type features from jSymbolic
descriptors = long_results[
    (long_results["type"] == "Descriptor") & (long_results["source"].str.contains("jSymbolic"))
]

# group by source or family, e.g. to see which sources contribute most features
long_results.groupby("family")["feature_name"].nunique()

By default, feature metadata (source, family, domain, type, description) is joined onto the long DataFrame automatically. Pass join_metadata=False to skip this and get a minimal melody_num, melody_id, feature_name, value table instead.

You can also reshape an existing wide-format DataFrame (for example one you've already saved to CSV) with to_long_format, and fetch the metadata table on its own with get_feature_metadata():

wide_results = get_all_features(input="path/to/your/midi/files")
long_results = to_long_format(wide_results)

metadata = get_feature_metadata()  # feature_name, family, source, domain, type, description, notes, references

Loading melodies and computing individual features

Besides the batch pipeline, you can load a Melody and call feature functions from the package root. Use list_available_features() to browse the full catalogue.

from melody_features import pitch_range
from melody_features.corpus import get_corpus_files
from melody_features.io.midi import load_midi

midi_path = get_corpus_files("essen", max_files=1)[0]
melody = load_midi(str(midi_path))
print(pitch_range(melody.pitches))

Some features (FANTASTIC corpus statistics, IDyOM) need extra configuration or reference corpora; it is easiest to use get_all_features with Config when you need those.

Melsim

Melsim is an R package for computing the similarity between two or more melodies. It is currently under development by Seb Silas and Klaus Frieler (https://github.com/sebsilas/melsim)

It is included with this feature set through a wrapper approach - take a look at example.py and the supplied MIDI files.

Since calculating similarities is highly modular in Melsim, we leave the user to decide how they wish to construct comparisons. Melsim is not run as part of the get_all_features function.

Available Corpora

The package comes with two example corpora: a MIDI conversion of the well-known Essen Folksong Collection (Eck, 2024; Schaffrath, 1995), and 903 Western musical tradition melodies, used by Pearce for IDyOM pretraining (Pearce, 2006). By default, the 903-melody corpus is invoked by get_all_features.

Development

Running Tests

# Simply run pytest
pytest

# or with Python, run all tests
python tests/run_tests.py

# Run specific test suites
python -m pytest tests/test_module_setup.py -v
python -m pytest tests/test_corpus_import.py -v
python -m pytest tests/test_idyom_setup.py -v

Contributing

If you spot something you think ought to be included here, feel free to contribute it! Simply fork the repo, implement your feature, and submit a Pull Request that explains the proposed addition(s). If you seek to contribute features that relate to one another, you may propose them in a single PR, otherwise, please submit separate PRs for each feature, as this makes it simpler to review the code.

Presently, we don't use a formalised style guide. However, we expect that your code will adhere to the following principles:

  • Each module should always include a docstring that succintly explains the purpose of the module
  • Each function within a module should have its own docstring and type hints. The docstring should include a citation to the relevant literature resource
  • Each top-level feature should return using a native Python type
  • New features should be accompanied by tests. Where it is possible, implemented features should be validated against their source implementation: see tests/test_jsymbolic_validation.py for an example.

License

This project is licensed under the MIT License - see the LICENSE-MIT file for details.

Open-source code adapted from the Partitura Python package is licensed under the Apache-2.0 license, which can be found in the LICENSE-APACHE file. More details can be found in NOTICE.

Metadata

Release files for melody-features 1.3.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for melody-features 1.3.3
File Size Uploaded
melody_features-1.3.3.tar.gz 1.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for melody-features 1.3.3
File Interpreter ABI Platform
melody_features-1.3.3-py3-none-any.whl Python 3 none any Details

Total release size: 5.5 MB

Release files / melody_features-1.3.3.tar.gz

Download URL melody_features-1.3.3.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
45675e6e43a7f9383e1e13e14fc3f6a871c3261996f91787145b6438f1fee68e
BLAKE2b-256 checksum
How to use checksums
a36cc1b51be6c9c1894dbc86d2ac2f407b18ad147c9d2c1d72e4104a586015cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.2

Release files / melody_features-1.3.3-py3-none-any.whl

Download URL melody_features-1.3.3-py3-none-any.whl
Size 4.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
4491dd64ece8b0e17b3a629ecc1820c5b7694c1c9df9b280e276de542c80aae1
BLAKE2b-256 checksum
How to use checksums
bdb772549d8c19b845d7f088b0a80dfdce10e8e8b4fb39c7628cce2709ef6048
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.2

Release history Release notifications | RSS feed

This release

1.3.3 This release

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.8

2 release files

1.1.7

2 release files

1.1.6

2 release files

1.1.5

2 release files

1.1.4

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.10

2 release files

1.0.9

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release 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