Melody Engine API¶
Package Overview¶
The melody_engine package re-exports the main public classes and functions from the engine
submodules. The detailed API reference below documents those submodules directly so the type
index stays unambiguous.
Structure Module¶
- class melody_engine.structure.TimeSignature(beats_per_bar: 'int', beat_unit: 'int')[source]¶
Bases:
object- beats_per_bar: int¶
- beat_unit: int¶
- classmethod from_string(value: str) TimeSignature[source]¶
- property bar_length: float¶
- class melody_engine.structure.NoteEvent(scale_step: 'int', duration: 'float', chromatic_adjustment: 'int' = 0, is_rest: 'bool' = False)[source]¶
Bases:
object- scale_step: int¶
- duration: float¶
- chromatic_adjustment: int = 0¶
- is_rest: bool = False¶
- class melody_engine.structure.NoteCandidate(scale_step: 'int', chromatic_adjustment: 'int' = 0, is_rest: 'bool' = False)[source]¶
Bases:
object- scale_step: int¶
- chromatic_adjustment: int = 0¶
- is_rest: bool = False¶
- class melody_engine.structure.VoiceProfile(name: 'str', range_min: 'int', range_max: 'int', tessitura_min: 'int', tessitura_max: 'int', clef_hint: 'str | None' = None)[source]¶
Bases:
object- name: str¶
- range_min: int¶
- range_max: int¶
- tessitura_min: int¶
- tessitura_max: int¶
- clef_hint: str | None = None¶
- property melodic_span: int¶
- class melody_engine.structure.FormSection(label: 'str', start_bar: 'int', end_bar: 'int', role: 'str', source_bar: 'int | None' = None, transform: 'str' = 'free')[source]¶
Bases:
object- label: str¶
- start_bar: int¶
- end_bar: int¶
- role: str¶
- source_bar: int | None = None¶
- transform: str = 'free'¶
- class melody_engine.structure.FormPlan(kind: 'str', sections: 'tuple[FormSection, ...]' = ())[source]¶
Bases:
object- kind: str¶
- sections: tuple[FormSection, ...] = ()¶
- section_for_bar(bar_number: int) FormSection | None[source]¶
- class melody_engine.structure.ChoralePlan(voice_profiles: 'tuple[VoiceProfile, ...]' = ())[source]¶
Bases:
object- voice_profiles: tuple[VoiceProfile, ...] = ()¶
- class melody_engine.structure.Motif(events: 'tuple[NoteEvent, ...]', name: 'str' = 'motif')[source]¶
Bases:
object- name: str = 'motif'¶
- classmethod from_steps(scale_steps: list[int], durations: list[float], name: str = 'motif') Motif[source]¶
- property length: float¶
- class melody_engine.structure.HarmonySpan(start_bar: 'int', end_bar: 'int', roman_symbol: 'str', weight: 'float' = 1.0, start_beat: 'float' = 0.0, end_beat: 'float | None' = None)[source]¶
Bases:
object- start_bar: int¶
- end_bar: int¶
- roman_symbol: str¶
- weight: float = 1.0¶
- start_beat: float = 0.0¶
- end_beat: float | None = None¶
- class melody_engine.structure.HarmonyPlan(spans: 'tuple[HarmonySpan, ...]' = ())[source]¶
Bases:
object- spans: tuple[HarmonySpan, ...] = ()¶
- chord_for_bar(bar_number: int) HarmonySpan | None[source]¶
- chord_for_position(bar_number: int, beat_in_bar: float, bar_length: float) HarmonySpan | None[source]¶
- class melody_engine.structure.Melody(key: 'Key', time_signature: 'TimeSignature', events: 'tuple[NoteEvent, ...]', harmony_plan: 'HarmonyPlan' = HarmonyPlan(spans=()), clef: 'str | None' = None, voice_profile: 'VoiceProfile' = VoiceProfile(name='melody', range_min=0, range_max=9, tessitura_min=1, tessitura_max=8, clef_hint=None), metadata: 'dict[str, object]' = <factory>)[source]¶
Bases:
object- time_signature: TimeSignature¶
- harmony_plan: HarmonyPlan = HarmonyPlan(spans=())¶
- clef: str | None = None¶
- voice_profile: VoiceProfile = VoiceProfile(name='melody', range_min=0, range_max=9, tessitura_min=1, tessitura_max=8, clef_hint=None)¶
- metadata: dict[str, object]¶
- class melody_engine.structure.ChoraleScore(key: 'Key', time_signature: 'TimeSignature', soprano: 'Melody', alto: 'Melody', tenor: 'Melody', bass: 'Melody', harmony_plan: 'HarmonyPlan' = <factory>, metadata: 'dict[str, object]' = <factory>)[source]¶
Bases:
object- time_signature: TimeSignature¶
- harmony_plan: HarmonyPlan¶
- metadata: dict[str, object]¶
- class melody_engine.structure.GenerationSettings(key: 'Key', time_signature: 'TimeSignature', bars: 'int', allowed_durations: 'tuple[float, ...]' = (0.5, 1.0, 2.0), range_min: 'int' = 0, range_max: 'int' = 9, motif: 'Motif | None' = None, motif_repetition_bar: 'int | None' = None, motif_repetition_shift: 'int' = 1, harmonic_plan: 'HarmonyPlan' = HarmonyPlan(spans=()), phrase_length_bars: 'int' = 4, cadence_duration: 'float' = 2.0, attempts: 'int' = 48, random_seed: 'int' = 7, form_plan: 'FormPlan' = FormPlan(kind='free', sections=()), clef: 'str | None' = None, texture: 'str' = 'melody', voice_profile: 'VoiceProfile' = VoiceProfile(name='melody', range_min=0, range_max=9, tessitura_min=1, tessitura_max=8, clef_hint=None), chorale_plan: 'ChoralePlan' = ChoralePlan(voice_profiles=()))[source]¶
Bases:
object- time_signature: TimeSignature¶
- bars: int¶
- allowed_durations: tuple[float, ...] = (0.5, 1.0, 2.0)¶
- range_min: int = 0¶
- range_max: int = 9¶
- motif_repetition_bar: int | None = None¶
- motif_repetition_shift: int = 1¶
- harmonic_plan: HarmonyPlan = HarmonyPlan(spans=())¶
- phrase_length_bars: int = 4¶
- cadence_duration: float = 2.0¶
- attempts: int = 48¶
- random_seed: int = 7¶
- clef: str | None = None¶
- texture: str = 'melody'¶
- voice_profile: VoiceProfile = VoiceProfile(name='melody', range_min=0, range_max=9, tessitura_min=1, tessitura_max=8, clef_hint=None)¶
- chorale_plan: ChoralePlan = ChoralePlan(voice_profiles=())¶
Theory Module¶
Constraints Module¶
- class melody_engine.constraints.CandidateContext(key: 'Key', events: 'tuple[NoteEvent, ...]', index: 'int', bar_number: 'int', beat_in_bar: 'float', total_events: 'int', climax_index: 'int', climax_step: 'int', phrase_end_bars: 'frozenset[int]', current_duration: 'float', harmony_span: 'HarmonySpan | None' = None, motif_target_step: 'int | None' = None, section_role: 'str' = 'free', section_transform: 'str' = 'free')[source]¶
Bases:
object- index: int¶
- bar_number: int¶
- beat_in_bar: float¶
- total_events: int¶
- climax_index: int¶
- climax_step: int¶
- phrase_end_bars: frozenset[int]¶
- current_duration: float¶
- harmony_span: HarmonySpan | None = None¶
- motif_target_step: int | None = None¶
- section_role: str = 'free'¶
- section_transform: str = 'free'¶
- property previous_interval: int | None¶
- property previous_pitched_interval: int | None¶
- property notes_since_last_rest: int¶
- property candidate_is_final: bool¶
- property on_strong_beat: bool¶
- class melody_engine.constraints.SoftConstraint(*args, **kwargs)[source]¶
Bases:
Protocol- name: str¶
- weight: float¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.StepwiseMotionConstraint(weight: 'float' = 1.0, name: 'str' = 'stepwise_motion')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'stepwise_motion'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.LeapRecoveryConstraint(weight: 'float' = 1.0, name: 'str' = 'leap_recovery')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'leap_recovery'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.LeadingToneResolutionConstraint(weight: 'float' = 1.0, name: 'str' = 'leading_tone_resolution')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'leading_tone_resolution'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.ChordTonePreferenceConstraint(weight: 'float' = 1.0, non_chord_tone_penalty: 'float' = -0.35, name: 'str' = 'chord_tone_preference')[source]¶
Bases:
object- weight: float = 1.0¶
- non_chord_tone_penalty: float = -0.35¶
- name: str = 'chord_tone_preference'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.StrongBeatStabilityConstraint(weight: 'float' = 1.0, name: 'str' = 'strong_beat_stability')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'strong_beat_stability'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.PhraseCadenceConstraint(weight: 'float' = 1.0, name: 'str' = 'phrase_cadence')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'phrase_cadence'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.SingleClimaxConstraint(weight: 'float' = 1.0, name: 'str' = 'single_climax')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'single_climax'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.MotifPreferenceConstraint(weight: 'float' = 1.0, name: 'str' = 'motif_preference')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'motif_preference'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.RepeatedPitchConstraint(weight: 'float' = 1.0, name: 'str' = 'repeated_pitch_control')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'repeated_pitch_control'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.DirectionChangeConstraint(weight: 'float' = 1.0, name: 'str' = 'direction_change')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'direction_change'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.LargeLeapConstraint(weight: 'float' = 1.0, name: 'str' = 'large_leap')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'large_leap'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.RestConstraint(weight: 'float' = 1.0, name: 'str' = 'rest_usage')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'rest_usage'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
- class melody_engine.constraints.FormSectionConstraint(weight: 'float' = 1.0, name: 'str' = 'form_section')[source]¶
Bases:
object- weight: float = 1.0¶
- name: str = 'form_section'¶
- evaluate(candidate: NoteCandidate, context: CandidateContext) float[source]¶
Generator Module¶
- class melody_engine.generator.GenerationAttempt(events: 'tuple[NoteEvent, ...]', score: 'float')[source]¶
Bases:
object- score: float¶
- class melody_engine.generator.MelodyGenerator(settings: GenerationSettings, constraints: list[SoftConstraint])[source]¶
Bases:
object
LilyPond Module¶
- melody_engine.lilypond.chorale_to_lilypond_source(score: ChoraleScore) str[source]¶
- melody_engine.lilypond.export_chorale(score: ChoraleScore, output_path: str | Path) Path[source]¶
- melody_engine.lilypond.render_lilypond_file(source_path: str | Path, output_dir: str | Path | None = None, *, cropped: bool = False, lilypond_bin: str = 'lilypond') list[Path][source]¶