subsequence.harmony =================== .. py:module:: subsequence.harmony .. autoapi-nested-parse:: Harmony helpers — diatonic chords without the chord-graph engine. Standalone convenience functions (``diatonic_chords``, ``diatonic_chord``, ``diatonic_chord_sequence``) for building chords from a key and mode, plus the ``ChordPattern`` view. For generative progressions use ``progressions``. Module Contents --------------- .. py:class:: ChordPattern(harmonic_state: subsequence.harmonic_state.HarmonicState, length: int = 4, root_midi: int = 52, velocity: int = subsequence.constants.velocity.DEFAULT_CHORD_VELOCITY, reschedule_lookahead: int = 1, channel: Optional[int] = None, voice_leading: bool = False) Bases: :py:obj:`subsequence.pattern.Pattern` A repeating chord pattern that follows the shared harmonic state. Initialize a chord pattern driven by composition-level harmony. :param harmonic_state: Shared harmonic state that provides chord changes :param length: Pattern length in beats (default 4) :param root_midi: Base MIDI note number for the chord root (default 52) :param velocity: MIDI velocity 0-127 (default 90) :param reschedule_lookahead: Reschedule lookahead in beats (default 1) :param channel: MIDI channel (0-15, required) :param voice_leading: When True, each chord automatically picks the inversion closest to the previous chord for smooth movement .. py:method:: on_reschedule() -> None Rebuild the chord pattern from the shared harmonic state. .. py:function:: diatonic_chord(key: str, mode: str = 'ionian', degree: int = 0) -> subsequence.chords.Chord Return a single diatonic chord by scale degree. Convenience wrapper around :func:`diatonic_chords` for the common case where only one chord is needed. :param key: Root note name (e.g. ``"E"``, ``"Bb"``). :param mode: Scale mode (default ``"ionian"``). :param degree: Zero-indexed scale degree (0 = I/tonic, 4 = V/dominant, etc.). :raises ValueError: If *degree* is out of range for the mode. .. rubric:: Example .. code-block:: python tonic = diatonic_chord("E", "phrygian") # I dominant = diatonic_chord("E", "phrygian", degree=4) # V .. py:function:: diatonic_chord_sequence(key: str, root_midi: int, count: int, mode: str = 'ionian') -> List[Tuple[subsequence.chords.Chord, int]] Return a list of ``(Chord, midi_root)`` tuples stepping diatonically upward. Useful for mapping a continuous value (like altitude or brightness) to a chord, or for building explicit rising/falling progressions without using the chord graph engine. The returned list has ``count`` entries. Each entry contains the ``Chord`` object (quality and pitch class) and the exact MIDI note number to use as that chord's root. Pass both directly to ``p.chord(chord, root=midi_root)``. Counts larger than the number of scale degrees wrap into higher octaves automatically. The sequence always steps upward — reverse the list for a falling sequence. :param key: Note name for the key (e.g., ``"D"``, ``"Eb"``, ``"F#"``). :param root_midi: MIDI note number for the first chord's root. Must fall on a scale degree of the chosen key and mode. :param count: Number of ``(Chord, midi_root)`` pairs to generate. :param mode: One of ``"ionian"`` (or ``"major"``), ``"dorian"``, ``"phrygian"``, ``"lydian"``, ``"mixolydian"``, ``"aeolian"`` (or ``"minor"``), ``"locrian"``, ``"harmonic_minor"``, ``"melodic_minor"``. :returns: List of ``(Chord, int)`` tuples, one per step. :raises ValueError: If ``key`` or ``mode`` is not recognised, or if ``root_midi`` does not fall on a scale degree of the key. .. rubric:: Example .. code-block:: python from subsequence.harmony import diatonic_chord_sequence # 7-step D Major ladder starting at D3 (MIDI 50) sequence = diatonic_chord_sequence("D", root_midi=50, count=7) # Map a 0-1 value to a chord (e.g. from ISS altitude) chord, root = sequence[int(ratio * (len(sequence) - 1))] p.chord(chord, root=root, sustain=True) # Falling sequence for chord, root in reversed(diatonic_chord_sequence("A", 57, 7, "minor")): ... .. py:function:: diatonic_chords(key: str, mode: str = 'ionian') -> List[subsequence.chords.Chord] Return the diatonic triads for a key and mode. This is a convenience function for generating chord sequences without using the chord graph engine. The returned ``Chord`` objects can be passed directly to ``p.chord()`` or ``chord.tones()`` inside a pattern. :param key: Note name for the key (e.g., ``"C"``, ``"Eb"``, ``"F#"``). :param mode: A mode with chord qualities defined (e.g. ``"ionian"``, ``"dorian"``, ``"minor"``). Scales without chord qualities (e.g. ``"hirajoshi"``) will raise ``ValueError`` — use ``p.snap_to_scale()`` for pitch snapping instead. :returns: List of ``Chord`` objects, one per scale degree. .. rubric:: Example .. code-block:: python from subsequence.harmony import diatonic_chords # All 7 chords in Eb Major chords = diatonic_chords("Eb") # Natural minor chords in A chords = diatonic_chords("A", mode="minor") # Dorian chords in D chords = diatonic_chords("D", mode="dorian")