songleaf.harmony¶
What a chord does in its song’s key, so that sheets can shade chords by function.
The key is estimated from the chords alone (a key given in a chart often names
the sounding key while the chords are written for a capo), and each chord is
then the "tonic", "diatonic" (another chord of the key), or "outside"
the key (borrowed, secondary dominant, chromatic).
>>> key = estimate_key(["G", "D", "Em", "C", "G", "D", "G"])
>>> key
Key(tonic=7, minor=False)
>>> [chord_function(symbol, key) for symbol in ["G", "Em", "C", "Bb", "N.C."]]
['tonic', 'diatonic', 'diatonic', 'outside', None]
>>> estimate_key(["Am", "Dm", "E7", "Am"])
Key(tonic=9, minor=True)
Functions
|
|
|
The key that best explains a song's chords, in order; None if there are no chords. |
|
|
|
|
|
A copy of |
|
|
|
The chords of a song moved by |
|
Whether chords in |
Classes
|
A key: its tonic as a pitch class (C = 0, C# = 1, . |
- class songleaf.harmony.Key(tonic, minor=False)[source]¶
Bases:
objectA key: its tonic as a pitch class (C = 0, C# = 1, … B = 11), major or minor.
- songleaf.harmony.chord_function(symbol, key)[source]¶
"tonic","diatonic"or"outside"inkey; None ifsymbolis not a chord.
- songleaf.harmony.estimate_key(symbols)[source]¶
The key that best explains a song’s chords, in order; None if there are no chords.
Each chord scores for a key when it belongs to it, and more when it is its tonic; a song that starts or ends on a key’s tonic chord scores extra for that key. Ties go to the major key, and to the lower tonic.
- songleaf.harmony.key_name(key, *, flats=None)[source]¶
"G","Bb","F#m": the key spelled as its tonic chord.>>> key_name(Key(10)), key_name(Key(6, minor=True)), key_name(Key(6, minor=True), flats=True) ('Bb', 'F#m', 'Gbm')
- Return type:
- songleaf.harmony.parse_chord(symbol)[source]¶
(root pitch class, quality), or None for what is not a chord.The quality is
"major","minor","diminished", or"open"(a suspended or power chord, which has no third). A bass note is ignored. What the chart parser would not read as a chord (is_chord_token) is not one.>>> parse_chord("F#m7"), parse_chord("Bbmaj7/D"), parse_chord("A7sus4"), parse_chord("Bm7b5") ((6, 'minor'), (10, 'major'), (9, 'open'), (11, 'diminished')) >>> parse_chord("C-7"), parse_chord("Bridge") ((0, 'minor'), None)
- songleaf.harmony.transpose(song, semitones)[source]¶
A copy of
songwith every chord moved bysemitones, spelled for the new key.
- songleaf.harmony.transpose_chord(symbol, semitones, *, flats=False)[source]¶
symbolmoved bysemitones: root and bass move, the rest is kept as written.flatsspells moved notes with flats (choose it from the target key withuses_flats()). What is not a chord comes back unchanged.>>> transpose_chord("G", 2), transpose_chord("F#m7", 1), transpose_chord("C/E", 3, flats=True) ('A', 'Gm7', 'Eb/G') >>> transpose_chord("Bbmaj7", -1, flats=True), transpose_chord("N.C.", 4), transpose_chord("Am", 0) ('Amaj7', 'N.C.', 'Am') >>> [transpose_chord(c, 2) for c in ("D7/9", "Bm5-/7", "C6/9", "C(4/9)", "(Em7)", "Am7/G)")] ['E7/9', 'C#m5-/7', 'D6/9', 'D(4/9)', '(F#m7)', 'Bm7/A)']
- Return type:
- songleaf.harmony.transposition_table(symbols, semitones, *, key=None)[source]¶
The chords of a song moved by
semitones, spelled for the new key.symbolsare the song’s chords in order (they give the key whenkeyis not given). Returns{"semitones", "key", "chords"}: the new key’s name (""when there are no chords) and{original: transposed}over the distinct chords, in order of first appearance.>>> transposition_table(["G", "D", "Em", "C", "G"], 3) {'semitones': 3, 'key': 'Bb', 'chords': {'G': 'Bb', 'D': 'F', 'Em': 'Gm', 'C': 'Eb'}}
- Return type: