Skip to main content

An interval-analysis based music similarity engine

Find the project on Github and PyPI

Current Version: 0.3.3

Project Capabilities

  • Find exact and close melodic matches given an mei file
  • Find occurences of matching soggetto given a "vectorized" pattern
  • Output a 0-1 similarity score between two musical works
  • Classify melodic matches into periodic entries, imitative duos, fuga
  • Output match data in a variety of ways: command line output, csv, pandas, python data types

Getting Started

To download the project via the Python Packagae Index, use pip install crim-intervals and in a python shell enter from crim_intervals import * To use the project via github, clone the repository and in a python shell in the directory of the repository enter from main import *

Method, Class help

The project is now documented with docstrings, for help using/understanding methods or classes use help(method_or_class_name)

Assisted Usage

For a guided way to get results for the basic intended usages of the project, simply enter:

from crim_intervals import *
assisted_interface()

wherever you are writing your code. The assisted interface will return an array of matches.

User-inputted parameters

Each parameter listed has its own section below detailing configuration.

  • Whether to input one score at a time, or a entire corpus at once with more limited selection ability, as well as what notes are to be analyzed, and the variety of ways in which they can be grouped (Detailed under "Note List Selection- Corpus" and "Note List Selection- Single Score")
  • Whether to create generic or semitone intervals (Detailed under "Creating vectorized representations and selecting their types")
  • The size of pattern to be analyzed (Detailed under "Grouping the vectors into patterns")
  • The minimum number of matches needed to be displayed, and optionally, the cumulative difference threshold for a two patterns to be considered closely matched (Detailed under "Finding close and exact matches")

Note List Selection- Corpus

This section covers the capabilities falling under the CorpusBase object, which has the capability to import multiple pieces at once. To begin, import your scores using either as a list of urls and/or file paths. File paths must begin with a '/', otherwise they will be processed as urls.

corpus = CorpusBase(['url_to_mei_file1.mei', 'url_to_mei_file2.mei', 'path/to/mei/file1.mei', 'path/to/mei/file2.mei'])

After, the first decision to be made is how you want to analyze the imported pieces:

  • Get the whole piece corpus.note_list_whole_piece()
  • Get the whole piece combining unisons into one note corpus.note_list_no_unisons()
  • Get the whole piece only at selected offset within a measure corpus.note_list_selected_offset([offset1, offset2, offset3, etc.])
  • Get the note sounding at every regular offset corpus.note_list_incremental_offset(offset_increment) For more information on each method, use help(method name), for example: help(note_list_incremental_offset)

Note List Selection- Single Score

This section covers the capabilities falling under the ScoreBase object, which can give more precise note lists, but only for a single piece at a time. To begin, import your score using either score1 = ScoreBase('https://url_to_mei_file.mei') for a file url or score2 = ScoreBase('/path/to/file.mei') for a file path (this path MUST start with a '/', otherwise it will be read as a url After, decide on how you want to analyze or deconstruct your imported piece:

  • Get the whole piece score1.note_list_whole_piece()
  • Get a note list from a selected measure range within a single voice score1.note_list_single_part(part_number, measure_start, measures_until_end)
  • Get a note list from a selected measure range over all voices score1.note_list_all_parts(measure_start, measures_until_end)
  • Get the whole piece combining unisons into one note score1.note_list_no_unisons()
  • Get the whole piece only at selected offset within a measure score1.note_list_selected_offset([offset1, offset2, offset3, etc.])
  • Get the note sounding at every regular offset score1.note_list_incremental_offset(offset_increment)
  • Get a note list from the whole piece, going by provided beats score1.note_list_selected_beat([beat1, beat2, etc.]) *For more information on each method, use help(method name), for example: help(note_list_incremental_offset)

Creating vectorized representations and selecting their types

At this point you should have constructed a note list from the methods of a CorpusBase or ScoreBase object. The next step is to group those notes into intervals using the IntervalBase object, which accepts note lists as a list, in case you want to analyze multiple ScoreBase note lists.

  • Multiple note lists: vectors = IntervalBase([score1.note_list_whole_piece(), score2.note_list_incremental_offset(2), corpus.note_list_whole_piece()]
  • Just one: vectors = IntervalBase([corpus.note_list_whole_piece()] The IntervalBase object's methods turn the note list given into the vectors with which we do pattern comparisons. To get those vectors, we must decide whether to use generic or semitone intervals:
  • Semitone intervals: vectors.semitone_intervals()
  • Generic intervals: vectors.generic_intervals()

Grouping the vectors into patterns

Now that we have a list of vectors (or intervals between notes), we can begin to place them into patterns to be analyzed for similarity. To do so we must select the size of pattern to be used for our analysis: patterns = into_patterns(vectors.generic_intervals, pattern_size) As always, for information on methods and their parameters, use the help() function- help(into_patterns)

Finding close and exact matches

Now that we have patterns, it is time to analyze them for similarity, which can be either in the form of exact matches, or "close" matches- which gauge similarity based on a cumulative difference threshold (for more on that, see this example notebook). To find only exact matches- or those that follow the same melodic pattern (with potential for transposition across pitches), we bring in the patterns variable from the previous section: exact_matches = find_exact_matches(patterns, min_matches) where the parameter min_matches determines the minimum number of matches a pattern needs to be considered relevant and displayed. To print information about all matches found, use a simple for loop and another method:

for item in exact_matches:
    item.print_exact_matches()

Alternatively, if we want to look for "close" matches, we follow a similar stucture, but must provide the threshold detailed above and print slightly differently:

close_matches = find_close_matches(patterns, min_matches, threshold)
for item in close_matches:
    item.print_close_matches()

Accessing information about matches

There are a few ways information about matches can be accessed.

  • To get information on the command line, use the for loop specified above, using the print_exact_matches or print_close_matches methods
  • To export the matches information to a csv file use: export_to_csv(exact_matches) or export_to_csv(close_matches) where the parameter for the method is the return value from the match finding functions detailed above.
  • To export the matches information to a pandas dataframe use: export_pandas(exact_matches) or export_pandas(close_matches) where the parameter for the method is the return value from the match finding functions detailed above.
  • For more programming-oriented users: The methods find_exact_matches and find_close_matches return an array of PatternMatches objects, each of which contain a list of Match object under the parameter pattern_match_obj.matches. Each match object has information about its pattern and the notes which make it up, which can be useful for data analysis. Using the help function is always recommended if parameters/attributes are unclear.

Additional Features

  • Get a similarity "score" between 0 to 1, comparing the motifs shared between two pieces: similarity_score(first piece note list, second piece note list). The note lists are gathered from the methods of either a ScoreBase or CorpusBase object.
  • Find a desired motif/soggetto within a corpus. Your soggetto must be specified as a list of intervals between notes. For example, the soggetto C-D-E-D-C would be vectorized in generic intervals as [2,2,-2,-2].find_motif(corpus, soggetto_vector_list). If instead you wish to search in terms of semitone intervals, you have to specify an additional parameter as False: find_motif(corpus, soggetto_vector_list, False)
  • Classify Matches into periodic entries, imitative duos, and fuga. Using the return value from find_exact_matches or find_close_matches, you can classify matches using classify_matches(exact_matches) or classify_matches(exact_matches, 2) where the second parameter is an optional cumulative duration difference threshold. The return value of this function is a list of ClassifiedMatch objects, with Match object data inside the parameter matches. Use help(ClassifiedMatch) for more information.
    • Additionally, in addition to the printed terminal output, this information can be exported to a csv file using the return value of the function:
    classified_matches = classify_matches(exact_matches)
    export_to_csv(classified_matches)
    

Download files

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

Source Distribution

crim_intervals-0.3.7.tar.gz (21.7 kB view details)

Uploaded Source

Built Distribution

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

crim_intervals-0.3.7-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file crim_intervals-0.3.7.tar.gz.

File metadata

  • Download URL: crim_intervals-0.3.7.tar.gz
  • Upload date:
  • Size: 21.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.0.9 CPython/3.7.3 Darwin/17.6.0

File hashes

Hashes for crim_intervals-0.3.7.tar.gz
Algorithm Hash digest
SHA256 296e729b61a473f33f3837a39788bcaf79d5299442ae9574a73b6bf26332e786
MD5 15fc5a9ea8f4577fd9ee05e4d5d5a89f
BLAKE2b-256 4279fe586cb6b3a768c5956dd0ecc399cecde122248f4ecd7a442bfd79dff894

See more details on using hashes here.

File details

Details for the file crim_intervals-0.3.7-py3-none-any.whl.

File metadata

  • Download URL: crim_intervals-0.3.7-py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.0.9 CPython/3.7.3 Darwin/17.6.0

File hashes

Hashes for crim_intervals-0.3.7-py3-none-any.whl
Algorithm Hash digest
SHA256 6793d33d9013807487d7747dc93bcae0585f417ec541ebdbbb3b94b81f0d569c
MD5 311b942e575e537cc227688e9a0b791e
BLAKE2b-256 4f26c38d77b47d8905d4bcd495ce84151b86d6b9b7fc7dc58ff708d0b4487d96

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.7

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page