subsequence.chords¶
Chord definitions and pitch class utilities.
This module provides chord quality definitions, pitch class mappings, and the Chord class
for representing and manipulating chords.
Module-level constants:
NOTE_NAME_TO_PC: Maps note names (e.g.,"C","F#","Bb") to pitch classes (0-11)PC_TO_NOTE_NAME: Maps pitch classes to note namesCHORD_INTERVALS: Maps chord quality names to interval lists (semitones from root)CHORD_SUFFIX: Maps chord quality names to human-readable suffixes (e.g.,"m","7")
Module-level helpers:
key_name_to_pc(key_name): Validate a key name and return its pitch class (0–11). RaisesValueErrorfor unknown names. This is the canonical key validation function used byharmony.py,pattern_builder.snap_to_scale(), andchord_graphs.validate_key_name().
Chord qualities: "major", "minor", "diminished", "augmented", "dominant_7th",
"major_7th", "minor_7th", "half_diminished_7th", "sus2", "sus4"
Module Contents¶
- class subsequence.chords.Chord[source]¶
Represents a chord as a root pitch class and quality.
- bass_note(root_midi: int, octave_offset: int = -1) int[source]¶
Return the chord root shifted by a number of octaves.
Commonly used to produce a bass register note one or two octaves below the chord voicing.
- Parameters:
root_midi – Reference MIDI note number (passed to
root_note()).octave_offset – Octaves to shift; negative moves down (default
-1).
- Returns:
MIDI note number of the chord root in the target register.
Example
chord = Chord(root_pc=4, quality="major") # E major chord.bass_note(64) # → 52 (E3, one octave down from E4) chord.bass_note(64, -2) # → 40 (E2, two octaves down)
- name() str[source]¶
Return a human-friendly chord name.
A registered quality without a suffix prints as
root(quality)(e.g."C(quartal)") rather than masquerading as a plain major.
- root_note(root_midi: int) int[source]¶
Return the MIDI note number for the chord root nearest to root_midi.
This is equivalent to
self.tones(root_midi)[0]but makes intent explicit when you only need the single root pitch.- Parameters:
root_midi – Reference MIDI note number used to find the closest octave of this chord’s root pitch class.
- Returns:
MIDI note number of the chord root.
Example
chord = Chord(root_pc=4, quality="major") # E major chord.root_note(60) # → 64 (E4, nearest to C4) chord.root_note(69) # → 64 (E4, nearest to A4)
- tones(root: int, inversion: int = 0, count: int | None = None) List[int][source]¶
Return MIDI note numbers for chord tones starting from a root.
Finds the MIDI note corresponding to the chord’s root pitch class that is closest to the provided
rootargument.- Parameters:
root – MIDI note number (e.g., 60 = middle C) to center the chord around.
inversion – Chord inversion (0 = root position, 1 = first, 2 = second, …). Wraps around for values >= number of notes.
count – Number of notes to return. When set, the chord intervals cycle into higher octaves until
countnotes are produced. WhenNone(default), returns the natural chord tones.
- Returns:
List of MIDI note numbers for chord tones
Example
chord = Chord(root_pc=0, quality="major") # C major chord.tones(root=60) # [60, 64, 67] - root position around C4 chord.tones(root=62) # [60, 64, 67] - still finds C4 as closest root chord.tones(root=70) # [72, 76, 79] - finds C5 as closest root
- subsequence.chords.key_name_to_pc(key_name: str) int[source]¶
Validate a key name and return its pitch class (0–11).
- Parameters:
key_name – Note name (e.g.
"C","F#","Bb").- Returns:
Pitch class integer (0–11).
- Raises:
ValueError – If the key name is not recognised.
Example
key_name_to_pc("C") # → 0 key_name_to_pc("F#") # → 6 key_name_to_pc("Bb") # → 10
- subsequence.chords.parse_chord(name: str) Chord[source]¶
Parse a chord name like
"Cm7"or"Dbmaj7"into aChord.The name is a root note (
A–Gwith an optional#orb) followed by a quality suffix:""major,mminor,dimdiminished,+/augaugmented,7dominant 7th,maj7major 7th,m7minor 7th,m7b5/øhalf-diminished 7th,sus2,sus4. A few common alternates (min,-,M7, …) are accepted too.Raises
ValueErrorfor anything it can’t read, so a typo surfaces at the call site rather than as a silently wrong chord.Example
parse_chord("Cm7") # → Chord(root_pc=0, quality="minor_7th") parse_chord("Dbmaj7") # → Chord(root_pc=1, quality="major_7th") parse_chord("F#") # → Chord(root_pc=6, quality="major")
- subsequence.chords.register_chord_quality(name: str, intervals: List[int], suffix: str | None = None) None[source]¶
Register a custom chord quality for use everywhere chords are used.
The counterpart to
subsequence.intervals.register_scale()— it opens the quality table so quartal stacks, clusters, and extended chords become first-class symbolic chords: they work in progressions, graphs, voice leading, anddescribe()output.Built-in qualities (e.g.
"minor") cannot be overwritten. Custom names may be re-registered freely — live reload re-runs registration on every save, so this must not raise.- Parameters:
name – Quality name (used as
Chord(root_pc, quality=name)).intervals – Semitone offsets from the root (e.g.
[0, 5, 10]for a quartal stack,[0, 3, 7, 10, 14]for a minor 9th). Must start with 0, ascend strictly, and stay within 0–24 (extensions reach past the octave).suffix – Optional chord-name suffix. When given,
parse_chord()accepts"A" + suffixandChord.name()prints it — soregister_chord_quality("minor_9th", [0, 3, 7, 10, 14], suffix="m9")makes"Am9"parse from then on. Must not collide with a built-in suffix.
Example
import subsequence subsequence.register_chord_quality("quartal", [0, 5, 10], suffix="q4") subsequence.parse_chord("Dq4") # → Chord(root_pc=2, quality="quartal")