API
- loeric.__main__.check_midi_control(groover: Groover, control2contour: dict[int, str]) Callable[[], None]
Returns a function that associates a contour name (values) for every MIDI control number in the dictionary (keys) and updates the groover accordingly. The value of the contour will be the control value mapped in the interval [0, 1].
- Parameters:
groover – the groover object.
control2contour – a dictionary of control numbers associated to contour names.
- Returns:
a callback function that will check for the given values.
- loeric.__main__.play(groover, tune, out, args) None
Play the given tune with the given groover.
- Parameters:
groover – the groover object
tune – the tune object
out – the output midi port
args – the performance arguments
- loeric.loeric_utils.get_ports(input_number: int = None, output_number: int = None, list_ports: bool = False)
Return the port names associated to the given indexes. If listing ports, only input and output port names will be printed.
- Parameters:
input_number – the input port index.
output_number – the output port index.
list_ports – whether or not to list port names and return.
- Returns:
a tuple (input, output) containing the input and output port names.
- loeric.loeric_utils.is_note(msg: Message) bool
Check if a midi event is a note event (either note-on or note-off).
- Parameters:
msg – the message to check.
- Returns:
True if the message is a note event.
- loeric.loeric_utils.is_note_off(msg: Message) bool
Check if a midi event is to be considered a note-off event, that is:
its type is “note-off” or
its type is “note-on” and it has 0 velocity.
- Parameters:
msg – the message to check.
- Returns:
True if the message is a note on event.
- loeric.loeric_utils.is_note_on(msg: Message) bool
Check if a midi event is to be considered a note-on event, that is:
its type is “note-on”;
it has non-zero velocity.
- Parameters:
msg – the message to check.
- Returns:
True if the message is a note on event.
- class loeric.groover.Groover(tune: Tune, bpm: int = None, midi_channel: int = 0, transpose: int = 0, diatonic_errors: bool = True, random_weight: float = 0, human_impact: float = 0, seed: int = 42, apply_savgol: bool = True, config_file: str = None)
The class responsible for playback, ornamentation and human interaction.
- __init__(tune: Tune, bpm: int = None, midi_channel: int = 0, transpose: int = 0, diatonic_errors: bool = True, random_weight: float = 0, human_impact: float = 0, seed: int = 42, apply_savgol: bool = True, config_file: str = None)
Initialize the groover class by setting user-defined parameters and creating the contours. Any parameters set on class instatiation that are also present in the configuration file will be overwritten. To preserve command line arguments, omit the corresponding fields from the configuration file.
- Parameters:
tune – the tune that will be performed.
bpm – the user-defined tempo in bpm for the tune.
midi_channel – the midi output channel for all messages.
transpose – the number of semitones by which to transpose the tune.
diatonic_errors – whether or not error generation should be quantized to the tune’s mode.
random_weight – the weight of the random component in contour generation.
human_impact – the weight of the external control signal.
seed – the random seed of the performance.
apply_savgol – whether or not to apply savgol filtering in contour generation. True by default (recommended).
config_file – the path to the configuration file (must be a JSON file).
- __weakref__
list of weak references to the object (if defined)
- property _current_tempo: int
- Returns:
the current tempo given the value of the tempo contour. If the option use_old_tempo_warp is set to True the contour affects tempo in terms of percentage of the original one (e.g. 20% faster); otherwise in terms of a fixed amount of bpms (e.g. 10 bpms faster).
- property _current_velocity: int
- Returns:
the current velocity given the value of the velocity contour.
- property _cut_duration
- Returns:
the duration of a cut note.
- _duration_of(time: float) float
Calculate the duration in seconds in the current tempo of the input duration, given in tune tempo.
- Parameters:
time – the input time value in seconds, given the original tempo.
- Returns:
the new duration of the input time value in seconds.
- property _eight_duration
- Returns:
the duration of a eight note in seconds at current tempo.
- _instantiate()
Generate all parameter settings following the current configuration.
- property _roll_duration
- Returns:
the duration of a single note in a roll.
- property _slide_duration
- Returns:
the duration of a slide.
- approach_from_above(note_number: int, tune: Tune) int
Return the midi note number to approach the given note from above. If no special approach rule is specified in the configuration file, it will return the next note in the scale of the tune’s key from the given note.
- Parameters:
note_number – the note to approach.
tune – the reference tune.
- Returns:
the note used the approach the given note from above.
- approach_from_below(note_number: int, tune: Tune) int
Return the midi note number to approach the given note from below. If no special approach rule is specified in the configuration file, it will return the previous note in the scale of the tune’s key from the given note.
- Parameters:
note_number – the note to approach.
tune – the reference tune.
- Returns:
the note used the approach the given note from below.
- can_generate_ornament() bool
- Returns:
whether or not to generate an ornament given the current ornament contour.
- choose_ornament(message: Message) str
Evaluate the ornament specific rules and chooose how the note will be ornamented.
- Parameters:
message – the midi message to ornament.
- Returns:
the chosen ornament type.
- generate_ornament(message: Message, ornament_type: str) list[Message]
Generate the sequence of notes corresponding to the chosen ornament.
- Parameters:
message – the midi message to ornament.
ornament_type – the type of ornament to generate.
- Returns:
the list of midi events corresponding to the chosen ornament.
- perform(message: Message) list[Message]
‘Perform’ a single note event by affecting its timing, pitch, velocity and adding ornaments.
- Parameters:
message – the midi message to perform.
- Returns:
the list of midi messages corresponding to the input message’s performance.
- reset() None
Reset all contours so that the next call to next() will yield the first value of each contour.
- set_contour_value(contour_name: str, value: float) None
Set the value of a given contour to a given value until the update.
- Parameters:
contour_name – the name of the contour.
value – the value to set the contour to.
- Raises:
groover.UnknownContourError – if the contour name does not correspond to any of the Groover’s contours.
- property tempo
- Returns:
the user-set tempo.
- exception loeric.groover.UnknownContourError
Raised if trying to set a contour whose name does not correspond to any of the Groover’s contours.
- __weakref__
list of weak references to the object (if defined)
- class loeric.contour.Contour
A class representing a note-wise intensity conotour.
- __init__()
Initialize the class.
- __weakref__
list of weak references to the object (if defined)
- calculate(midi: Tune) None
Calculate the intensity contour for the given tune.
- Parameters:
midi – the input tune.
- next() float
Return the next element (i.e. intensity value) of the intensity contour.
- Raises:
contour.UncomputedContourError – if the contour has not been computed yet.
contour.InvalidIndexError – if the index of the current value is below 0 or exceeds the length of the contour.
- Returns:
the next intensity value.
- ocanainn_scores(midi: Tune) tuple[array, array, array, array, array]
Computes the individual components for the ocanainn score:
frequency score;
beat score;
ambitus score;
leap score;
length score.
- Parameters:
midi – the input tune used to compute the individual scores.
- Returns:
the frequency score, the beat score, the ambitus score, the leap score and the length score.
- reset() None
Resets the contour iteration. The next call to next() will return the first element of the contour.
- scale_and_savgol(array: ndarray, shift: bool = False) ndarray
Scale the contour, then apply a Savitzky-Golay filter with a window of 15 and order 3. Optionally, shift the array to bring its mean closer to 0.5.
- Parameters:
array – the input contour.
shift – whether or not to shift the filtered array so that its mean is close to 0.5.
- Returns:
the filtered array.
- class loeric.contour.IntensityContour
A contour given by the weighted sum of O’Canainn components.
- __init__()
Initialize the class.
- calculate(midi: Tune, weights: array = None, random_weight: float = 0, savgol: bool = True, shift: bool = False) None
Compute the contour as the weighted sum of O’Canainn component. An optional random component can be added.
- Parameters:
midi – the input tune.
weights – the weights for the components, respectively frequency score, beat score, ambitus score, leap score and length score.
random_weight – the weight of the random component over the sum of the weighted O’Canainn scores. If None, the components will be averaged together.
savgol – whether or not to apply a final savgol filtering step (recommended).
shift – whether or not to apply a final shifting step to bring the mean of the array close to 0.5.
- exception loeric.contour.InvalidIndexError
Raised if the index of the current value is below 0 or exceeds the length of the contour.
- __weakref__
list of weak references to the object (if defined)
- class loeric.contour.MessageLengthContour
A contour holding the length of each note in the tune.
- __init__()
Initialize the class.
- class loeric.contour.PitchDifferenceContour
A contour holding the pitch difference between notes in the tune.
- __init__()
Initialize the class.
- class loeric.contour.RandomContour
A randomly initialized contour.
- __init__()
Initialize the class.
- calculate(midi: Tune, extremes: tuple[float, float] = None) None
Compute a random contour following a uniform distribution in the specified range, by default between 0 and 1.
- Parameters:
midi – the input tune.
extremes – the upper and lower bound for the random contour. If None, the range will be (0, 1).
- exception loeric.contour.UncomputedContourError
Raised if the contour has not been computed yet.
- __weakref__
list of weak references to the object (if defined)
- class loeric.tune.Tune(filename: str)
A wrapper for a midi file.
- __getitem__(idx: int) Message
Return the item in the midi event list corresponding to the given index.
- Parameters:
idx – the element index.
- Returns:
the midi message corresponding to that index.
- __init__(filename: str)
Initialize the class. A number of properties is computed:
the duration of the pickup bar, if there is any;
the key signature (only the first encountered is considered, key signature changes are not supported);
the time signature (only the first encountered is considered, time signature changes are not supported);
- Parameters:
filename – the path to the midi file.
- __len__() int
Return the length of the list of midi messages.
- Returns:
the number of midi messages in this tune.
- __weakref__
list of weak references to the object (if defined)
- _get_key_signature() str
Retrieve the key signature of the tune, if there is any. Only the first key signature will be retrieved.
- Returns:
the first key signature if there is any, else None.
- _get_original_tempo() int
Retrieve the tempo of the tune, if there is any. Only the first tempo change will be retrieved.
- Returns:
the first tempo change if there is any, else None.
- _get_performance_offset() float
Return the length of the pickup bar, if there is any.
- Returns:
the length of the pickup bar in seconds.
- _get_time_signature() TimeSignature
Retrieve the time signature of the tune, if there is any. Only the first time signature will be retrieved.
- Returns:
the first time signature if there is any, else None.
- property _quarter_duration: float
Return the duration of a quarter note in seconds given the current tempo.
- Returns:
the amount of seconds corresponding to a quarter note given the current tempo.
- events() Generator[Message, None, None]
A generator returning each midi event in the tune. Each time an event is retrieved, the performance time is updated.
- Returns:
the sequence of midi events one by one
- filter(filtering_function: Callable[[Message], bool]) list[Message]
Retrieve the midi events that fullfill the given filtering function.
- Parameters:
filtering_function – the function filtering the midi events.
- Returns:
a list of midi events fullfilling the filtering function.
- is_on_a_beat() bool
Decide if we are on a beat or not, given the current cumulative performance time.
- Returns:
True if we are on a beat.
- property offset: float
- Returns:
the tune’s performance offset (i.e. the length of the pickup bar) in seconds.
- semitones_from_tonic(midi_note: int) int
Compute the distance between the given note and the tonic of the tune in semitones.
- Parameters:
midi_note – the input note.
- Returns:
the distance between note and the tonic in semitones.
- property time_signature: TimeSignature
- Returns:
the tune’s time signature.
- class loeric.player.Player(tempo: int, key_signature: str, time_signature: TimeSignature, save: bool, midi_out)
The class responsible for performance playback and saving.
- __init__(tempo: int, key_signature: str, time_signature: TimeSignature, save: bool, midi_out)
Initialize the class.
- Parameters:
tempo – the performance’s tempo in microseconds per quarter note.
key_signature – the performance’s key signature.
time_signature – the performance’s time signature.
save – whether or not to save the performance to a midi file
midi_out – the output midi port.
- __weakref__
list of weak references to the object (if defined)