subsequence.voicings¶
Chord inversions and voice leading.
Provides functions for rotating chord intervals into different inversions and choosing the smoothest voicing between consecutive chords. Voice leading minimises the total semitone movement so that chord pads sound connected rather than jumping around the keyboard.
Example
# Manual inversion
from subsequence.voicings import invert_chord
first_inv = invert_chord([0, 4, 7], inversion=1) # [4, 7, 12]
# Automatic voice leading across a pattern
@composition.pattern(channel=0, length=4, voice_leading=True)
def chords (p, chord):
p.chord(chord, root=52, velocity=90, sustain=True)
Module Contents¶
- class subsequence.voicings.VoiceLeadingState[source]¶
Track the previous voicing across chord changes.
Each pattern that uses voice leading gets its own instance so that a bass line and a pad can voice-lead independently.
Example
state = VoiceLeadingState() voicing1 = state.next([0, 4, 7], 60) # root position (no previous) voicing2 = state.next([0, 3, 7], 60) # picks closest inversion to voicing1
Start with no previous voicing.
- subsequence.voicings.invert_chord(intervals: List[int], inversion: int) List[int][source]¶
Rotate chord intervals to produce an inversion.
Inversion 0 is root position. Inversion 1 raises the bottom note by an octave (first inversion). Wraps around for inversions >= the number of notes.
- Parameters:
intervals – Chord intervals in semitones from root (e.g.,
[0, 4, 7])inversion – Which inversion to produce (0 = root position)
- Returns:
Rotated interval list, still measured from the original chord root, so adding any root yields the same chord with a different bass note.
Example
invert_chord([0, 4, 7], 0) # [0, 4, 7] - root position invert_chord([0, 4, 7], 1) # [4, 7, 12] - first inversion (E-G-C) invert_chord([0, 4, 7], 2) # [7, 12, 16] - second inversion (G-C-E)
- subsequence.voicings.voice_lead(intervals: List[int], root_midi: int, previous_voicing: List[int] | None) List[int][source]¶
Find the inversion closest to a previous voicing.
Tries every inversion, in the nearest octaves, and picks the candidate with the smallest total semitone movement from
previous_voicing. Voices are compared positionally (voiceito voicei), so this picks the best inversion rather than the globally optimal voice reassignment. Ifprevious_voicingisNoneor the chord sizes differ, returns root position.- Parameters:
intervals – Chord intervals in semitones from root (e.g.,
[0, 4, 7])root_midi – MIDI note number for the chord root
previous_voicing – MIDI note numbers of the previous chord, or
None
- Returns:
MIDI note numbers for the best voicing