Core

The Melody type used throughout the package.

class Melody(midi_data, tempo=None)[source]

Bases: object

Melody representation backed by parallel note lists.

Construct directly with from_notes(), or pass a midi_data dict with pitches, starts, and ends (as produced by melody_features.io.midi.import_midi()). Legacy dicts that only provide MIDI Sequence are still supported via string parsing.

Parameters:
classmethod from_notes(pitches, starts, ends, *, tempo=100.0, melody_id='', time_signature='4/4', tempo_changes=None)[source]

Construct a melody from parallel note lists without reading MIDI.

Parameters:
Return type:

Melody

__init__(midi_data, tempo=None)[source]

Initialize a Melody object from MIDI sequence data.

Args:

midi_data (dict): Dictionary containing MIDI sequence data tempo (float, optional): Tempo in BPM. If None, uses tempo from midi_data if available.

Parameters:
property midi_data: dict

Raw import dictionary backing this melody (e.g. from import_midi()).

property id: str

Get the ID (file path) of the MIDI file.

Returns:

str: File path or ID of the MIDI file

property pitches: list[int]

List of MIDI note pitches in order of appearance.

property starts: list[float]

List of MIDI note start times in order of appearance.

property ends: list[float]

List of MIDI note end times in order of appearance.

property channels: list[int]

MIDI channel numbers (MIDI Toolbox uses channels 1-16).

property tempo: float

Extract tempo from Class input.

Returns:

float: Tempo of the melody in beats per minute

property tempo_changes: list[tuple[float, float]]

Get tempo changes from the melody.

Returns:

list[tuple[float, float]]: List of (time_in_seconds, tempo_in_bpm) tuples

property meter: tuple[int, int]

Extract the first time signature from the melody.

Returns:
tuple[int, int]: First time signature as (numerator, denominator)

Defaults to (4, 4) if no time signature information available

property time_signatures: list[tuple[float, int, int]]

Get all time signatures present in the melody.

Returns:
list[tuple[float, int, int]]: List of tuples (time_in_seconds, numerator, denominator).

If none are available, falls back to a single entry using the first meter at time 0.0.

property proportion_of_time_in_first_meter: float

Calculate the proportion of time spent in the first time signature.

Returns:
float: Proportion (0.0 to 1.0) that the first time signature comprises

of the total melody duration. 1.0 means the melody uses only one time signature throughout.

property total_duration: float

Get the total duration of the MIDI sequence in seconds.

Returns:
float: Total duration of the MIDI sequence in seconds, including any

leading or trailing silence. This matches jSymbolic’s DurationInSecondsFeature implementation.

property key_signature: tuple

Get the first key signature in the melody.

Returns:
tuple or None: (key_name, mode) where key_name is a string like ‘C’, ‘Am’, ‘F#’

and mode is either ‘major’ or ‘minor’. Returns None if no key signature found.

property key_signatures: list

Get all key signatures present in the melody.

Returns:
list[tuple]: List of tuples (key_name, mode) for all key signatures.

Empty list if no key signatures are found.

property has_key_signature: bool

Check if the MIDI file contains any key signature information.

Returns:

bool: True if at least one key signature was found, False otherwise.

property key_fifths: int

Get the circle of fifths position of the first key signature.

Returns:
int or None: Position on circle of fifths (-7 to 7) where:

0 = C major / A minor Positive = sharps (G=1, D=2, A=3, E=4, B=5, F#=6, C#=7) Negative = flats (F=-1, Bb=-2, Eb=-3, Ab=-4, Db=-5, Gb=-6, Cb=-7) Returns None if no key signature found.

property key_mode: int

Get the mode of the first key signature as an integer.

Returns:

int or None: 1 for major, -1 for minor. Returns None if no key signature found.

Helpers

build_midi_data(pitches, starts, ends, *, melody_id='', tempo=100.0, time_signature='4/4', tempo_changes=None)[source]

Build a midi_data dict from parallel note lists.

This is the structured input expected by Melody and matches the shape returned by melody_features.io.midi.import_midi().

Parameters:
Return type:

dict

build_midi_sequence_string(pitches, starts, ends)[source]

Build the legacy MIDI Sequence string from parallel note lists.

Parameters:
Return type:

str

read_midijson(file_path)[source]
Parameters:

file_path (str)

Return type:

dict