madmom.evaluation.chords

This module contains chord evaluation functionality.

It provides the evaluation measures used for the MIREX ACE task, and tries to follow [Raff97c8dd6dc-1] and [Raff97c8dd6dc-2] as closely as possible.

Notes

This implementation tries to follow the references and their implementation (e.g., https://github.com/jpauwels/MusOOEvaluator for [Raff97c8dd6dc-2]). However, there are some known (and possibly some unknown) differences. If you find one not listed in the following, please file an issue:

  • Detected chord segments are adjusted to fit the length of the annotations. In particular, this means that, if necessary, filler segments of ‘no chord’ are added at beginnings and ends. This can result in different segmentation scores compared to the original implementation.

References

[Raff97c8dd6dc-1]Christopher Harte, “Towards Automatic Extraction of Harmony Information from Music Signals.” Dissertation, Department for Electronic Engineering, Queen Mary University of London, 2010.
[Raff97c8dd6dc-2](1, 2) Johan Pauwels and Geoffroy Peeters. “Evaluating Automatically Estimated Chord Sequences.” In Proceedings of ICASSP 2013, Vancouver, Canada, 2013.
madmom.evaluation.chords.encode(chord_labels)[source]

Encodes chord labels to numeric interval representations.

Parameters:
chord_labels : numpy structured array

Chord segments in madmom.io.SEGMENT_DTYPE format

Returns:
encoded_chords : numpy structured array

Chords in CHORD_ANN_DTYPE format

madmom.evaluation.chords.chords(labels)[source]

Transform a list of chord labels into an array of internal numeric representations.

Parameters:
labels : list

List of chord labels (str).

Returns:
chords : numpy.array

Structured array with columns ‘root’, ‘bass’, and ‘intervals’, containing a numeric representation of chords (CHORD_DTYPE).

madmom.evaluation.chords.chord(label)[source]

Transform a chord label into the internal numeric represenation of (root, bass, intervals array) as defined by CHORD_DTYPE.

Parameters:
label : str

Chord label.

Returns:
chord : tuple

Numeric representation of the chord: (root, bass, intervals array).

madmom.evaluation.chords.modify(base_pitch, modifier)[source]

Modify a pitch class in integer representation by a given modifier string.

A modifier string can be any sequence of ‘b’ (one semitone down) and ‘#’ (one semitone up).

Parameters:
base_pitch : int

Pitch class as integer.

modifier : str

String of modifiers (‘b’ or ‘#’).

Returns:
modified_pitch : int

Modified root note.

madmom.evaluation.chords.pitch(pitch_str)[source]

Convert a string representation of a pitch class (consisting of root note and modifiers) to an integer representation.

Parameters:
pitch_str : str

String representation of a pitch class.

Returns:
pitch : int

Integer representation of a pitch class.

madmom.evaluation.chords.interval(interval_str)[source]

Convert a string representation of a musical interval into a pitch class (e.g. a minor seventh ‘b7’ into 10, because it is 10 semitones above its base note).

Parameters:
interval_str : str

Musical interval.

Returns:
pitch_class : int

Number of semitones to base note of interval.

madmom.evaluation.chords.interval_list(intervals_str, given_pitch_classes=None)[source]

Convert a list of intervals given as string to a binary pitch class representation. For example, ‘b3, 5’ would become [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0].

Parameters:
intervals_str : str

List of intervals as comma-separated string (e.g. ‘b3, 5’).

given_pitch_classes : None or numpy array

If None, start with empty pitch class array, if numpy array of length 12, this array will be modified.

Returns:
pitch_classes : numpy array

Binary pitch class representation of intervals.

madmom.evaluation.chords.chord_intervals(quality_str)[source]

Convert a chord quality string to a pitch class representation. For example, ‘maj’ becomes [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0].

Parameters:
quality_str : str

String defining the chord quality.

Returns:
pitch_classes : numpy array

Binary pitch class representation of chord quality.

madmom.evaluation.chords.merge_chords(chords)[source]

Merge consecutive chord annotations if they represent the same chord.

Parameters:
chords : numpy structured arrray

Chord annotations to be merged, in CHORD_ANN_DTYPE format.

Returns:
merged_chords : numpy structured array

Merged chord annotations, in CHORD_ANN_DTYPE format.

madmom.evaluation.chords.evaluation_pairs(det_chords, ann_chords)[source]

Match detected with annotated chords and create paired label segments for evaluation.

Parameters:
det_chords : numpy structured array

Chord detections with ‘start’ and ‘end’ fields.

ann_chords : numpy structured array

Chord annotations with ‘start’ and ‘end’ fields.

Returns:
annotations : numpy structured array

Annotated chords of evaluation segments.

detections : numpy structured array

Detected chords of evaluation segments.

durations : numpy array

Durations of evaluation segments.

madmom.evaluation.chords.score_root(det_chords, ann_chords)[source]

Score similarity of chords based on only the root, i.e. returns a score of 1 if roots match, 0 otherwise.

Parameters:
det_chords : numpy structured array

Detected chords.

ann_chords : numpy structured array

Annotated chords.

Returns:
scores : numpy array

Similarity score for each chord.

madmom.evaluation.chords.score_exact(det_chords, ann_chords)[source]

Score similarity of chords. Returns 1 if all chord information (root, bass, and intervals) match exactly.

Parameters:
det_chords : numpy structured array

Detected chords.

ann_chords : numpy structured array

Annotated chords.

Returns:
scores : numpy array

Similarity score for each chord.

madmom.evaluation.chords.reduce_to_triads(chords, keep_bass=False)[source]

Reduce chords to triads.

The function follows the reduction rules implemented in [1]. If a chord chord does not contain a third, major second or fourth, it is reduced to a power chord. If it does not contain neither a third nor a fifth, it is reduced to a single note “chord”.

Parameters:
chords : numpy structured array

Chords to be reduced.

keep_bass : bool

Indicates whether to keep the bass note or set it to 0.

Returns:
reduced_chords : numpy structured array

Chords reduced to triads.

References

[1](1, 2) Johan Pauwels and Geoffroy Peeters. “Evaluating Automatically Estimated Chord Sequences.” In Proceedings of ICASSP 2013, Vancouver, Canada, 2013.
madmom.evaluation.chords.reduce_to_tetrads(chords, keep_bass=False)[source]

Reduce chords to tetrads.

The function follows the reduction rules implemented in [1]. If a chord does not contain a third, major second or fourth, it is reduced to a power chord. If it does not contain neither a third nor a fifth, it is reduced to a single note “chord”.

Parameters:
chords : numpy structured array

Chords to be reduced.

keep_bass : bool

Indicates whether to keep the bass note or set it to 0.

Returns:
reduced_chords : numpy structured array

Chords reduced to tetrads.

References

[1](1, 2) Johan Pauwels and Geoffroy Peeters. “Evaluating Automatically Estimated Chord Sequences.” In Proceedings of ICASSP 2013, Vancouver, Canada, 2013.
madmom.evaluation.chords.select_majmin(chords)[source]

Compute a mask that selects all major, minor, and “no chords” with a 1, and all other chords with a 0.

Parameters:
chords : numpy structured array

Chords to compute the mask for.

Returns:
mask : numpy array (boolean)

Selection mask for major, minor, and “no chords”.

madmom.evaluation.chords.select_sevenths(chords)[source]

Compute a mask that selects all major, minor, seventh, and “no chords” with a 1, and all other chords with a 0.

Parameters:
chords : numpy structured array

Chords to compute the mask for.

Returns:
mask : numpy array (boolean)

Selection mask for major, minor, seventh, and “no chords”.

madmom.evaluation.chords.adjust(det_chords, ann_chords)[source]

Adjust the length of detected chord segments to the annotation length.

Discard detected chords that start after the annotation ended, and shorten the last detection to fit the last annotation; discared detected chords that end before the annotation begins, and shorten the first detection to match the first annotation.

Parameters:
det_chords : numpy structured array

Detected chord segments.

ann_chords : numpy structured array

Annotated chord segments.

Returns:
det_chords : numpy structured array

Adjusted detected chord segments.

madmom.evaluation.chords.segmentation(ann_starts, ann_ends, det_starts, det_ends)[source]

Compute the normalized Hamming divergence between chord segmentations as defined in [1] (Eqs. 8.37 and 8.38).

Parameters:
ann_starts : list or numpy array

Start times of annotated chord segments.

ann_ends : list or numpy array

End times of annotated chord segments.

det_starts : list or numpy array

Start times of detected chord segments.

det_ends : list or numpy array

End times of detected chord segments.

Returns:
distance : float

Normalised Hamming divergence between annotated and detected chord segments.

References

[1](1, 2) Christopher Harte, “Towards Automatic Extraction of Harmony Information from Music Signals.” Dissertation, Department for Electronic Engineering, Queen Mary University of London, 2010.
class madmom.evaluation.chords.ChordEvaluation(detections, annotations, name=None, **kwargs)[source]

Provide various chord evaluation scores.

Parameters:
detections : str

File containing chords detections.

annotations : str

File containing chord annotations.

name : str, optional

Name of the evaluation object (e.g., the name of the song).

length

Length of annotations.

root

Fraction of correctly detected chord roots.

majmin

Fraction of correctly detected chords that can be reduced to major or minor triads (plus no-chord). Ignores the bass pitch class.

majminbass

Fraction of correctly detected chords that can be reduced to major or minor triads (plus no-chord). Considers the bass pitch class.

sevenths

Fraction of correctly detected chords that can be reduced to a seventh tetrad (plus no-chord). Ignores the bass pitch class.

seventhsbass

Fraction of correctly detected chords that can be reduced to a seventh tetrad (plus no-chord). Considers the bass pitch class.

undersegmentation

Normalized Hamming divergence (directional) between annotations and detections. Captures missed chord segments.

oversegmentation

Normalized Hamming divergence (directional) between detections and annotations. Captures how fragmented the detected chord segments are.

segmentation

Minimum of oversegmentation and undersegmentation.

tostring(**kwargs)[source]

Format the evaluation metrics as a human readable string.

Returns:
eval_string : str

Evaluation metrics formatted as a human readable string.

class madmom.evaluation.chords.ChordSumEvaluation(eval_objects, name=None)[source]

Class for averaging Chord evaluation scores, considering the lengths of the pieces. For a detailed description of the available metrics, refer to ChordEvaluation.

Parameters:
eval_objects : list

Evaluation objects.

name : str, optional

Name to be displayed.

length()[source]

Length of all evaluation objects.

class madmom.evaluation.chords.ChordMeanEvaluation(eval_objects, name=None)[source]

Class for averaging chord evaluation scores, averaging piecewise (i.e. ignoring the lengths of the pieces). For a detailed description of the available metrics, refer to ChordEvaluation.

Parameters:
eval_objects : list

Evaluation objects.

name : str, optional

Name to be displayed.

length()[source]

Number of evaluation objects.

madmom.evaluation.chords.add_parser(parser)[source]

Add a chord evaluation sub-parser to an existing parser.

Parameters:
parser : argparse parser instance

Existing argparse parser object.

Returns:
sub_parser : argparse sub-parser instance

Chord evaluation sub-parser.