c_major = Chord(["C", "E", "G"])
assert c_major.name == "C major triad"
assert c_major.oct_s_notes == ["C4", "E4", "G4"]
c_majorChord: 'C major triad'. Notes: ['C4', 'E4', 'G4']
The Chord class is a collection of notes played together. The name of the chord is automatically inferred from the notes.
Chord (notes:List[musy.note.Note])
Base class for objects needing a basic __repr__
c_major = Chord(["C", "E", "G"])
assert c_major.name == "C major triad"
assert c_major.oct_s_notes == ["C4", "E4", "G4"]
c_majorChord: 'C major triad'. Notes: ['C4', 'E4', 'G4']
Chord objects can be created from a string.
Chord: 'C major seventh'. Notes: ['C4', 'E4', 'G4', 'B4']
Chord objects can also be created from MIDI.
cmaj9_midi = [60, 64, 67, 71, 74]
cmaj9 = Chord.from_midi(cmaj9_midi)
assert cmaj9.midi == cmaj9_midi
assert cmaj9.s_notes == ["C", "E", "G", "B", "D"]
assert cmaj9.oct_s_notes == ["C5", "E5", "G5", "B5", "D6"]
assert cmaj9.name == "C major ninth"
assert cmaj9.root == Note("C", oct=5)
assert cmaj9.s_root == "C"
assert cmaj9.oct_s_root == "C5"We can get the MIDI numbers for each note in a chord.
There is also the option to get a unique binary representation of a chord.
We will treat the lowest note of a Chord as the root.
Chord objects can be compared to each other using familiar Python operators. The length of the chords and the underlying notes are compared. For example, A C major chord is technically lower than a C major 7th chord. The 1st 3 notes are the same, but Cmaj7 has an additional 4th note.
Length is only a tie breaker in this example. For example, an E major chord is higher than a D major 7 chord, because its root note is higher.
Chord objects can be transposed in the same way as Note objects.
Chord: 'D major seventh'. Notes: ['D4', 'F#4', 'A4', 'C#5']
As with Note objects, there are shortcuts for transposing whole notes up and down by using the % and // operators, respectively.
Chord: 'D major seventh'. Notes: ['D4', 'F#4', 'A4', 'C#5']
Note objects can be multiplied with other Note objects to form a Chord. Multiplying Chord objects with Note objects will add the note to the chord.
Chord.__mul__ (other)
Add a note to a chord.
Note.__mul__ (other:musy.note.Note)
Form a chord from two notes.
# C/Eb slash chord
c_over_eb = Note("Eb", oct=3) * Note("C", oct=4) * Note("E", oct=4) * Note("G", oct=4)
c_over_ebChord: 'No chord found.'. Notes: ['Eb3', 'C4', 'E4', 'G4']
Using the syntax above, we can for example define the “mu chord” (major with add2) made famous by Steely Dan with concise code.
def mu(root: Note): return root * (root % 1) * (root % 2) * (root + 7)
c_mu = mu(Note("C"))
c_mu.notes[C4, D4, E4, G4]
Alternatively, we can use Note shortcuts to define the same Chord.
Chord objects can be inverted with invert.
Chord.invert (n:int=1)
Interval objects can be obtained for a Chord.
Relative intervals means we start from the root note and calculate all the intervals from it.
Absolute intervals means we calculate the intervals between the notes.
Chord.abs_intervals ()
Chord.rel_intervals ()
We create a single .dominant method to get the dominant chord that resolves to a given Chord. This is handy for analyzing secondary dominants and ii-V-I progressions.
By default, the dominant 7th chord (V7) is returned. If dim=True, the diminished 7th chord (vii°7) is returned.
We assume that the 1st note of the chord is the root.
Chord.dominant (dim=False)
The dominant of a D major chord is A7.
d = Chord.from_short("D")
assert d.dominant() == Chord([Note("A", oct=4), Note("C#", oct=5), Note("E", oct=5), Note("G", oct=5)])
d.dominant()Chord: 'A dominant seventh'. Notes: ['A4', 'C#5', 'E5', 'G5']
The diminished dominant (vii°7) of D major is C#°7.
assert d.dominant(dim=True) == Chord([Note("C#", oct=4), Note("E", oct=4), Note("G", oct=4), Note("A#", oct=4)])
assert d.dominant(dim=True).root == Note("C#", oct=4)
d.dominant(dim=True)Chord: 'A# diminished seventh, first inversion'. Notes: ['C#4', 'E4', 'G4', 'A#4']
The dominant of Cmaj7 is G7.
Added-note chords are generally triads on which a 2nd (add2), 4th (add4) or 6th (add6) is added. We have method add2, add4 and add6 that adds an interval to a Chord if it doesn’t exist yet.
We also add support for upper extensions with add_ext and for removing notes with remove_ext.
Chord.remove_ext (name:str)
Chord.add_ext (name:str)
Chord.add6 ()
Chord.add4 ()
Chord.add2 ()
Chord.add_interval (semitones:int)
Add note to existing chord.
An added 6th yields a 6th chord.
Chord: 'D major sixth'. Notes: ['D4', 'F#4', 'A4', 'B4']
A major triad with an added 2 creates a Mu Chord, made popular by Steely Dan.
Chord: 'No chord found.'. Notes: ['D4', 'E4', 'F#4', 'A4']
You can also get upper extensions with a more general method add_ext. These methods can be chained.
For example, this line of code yields a Dadd#9addb13 chord.
d_sharp9_flat13 = d.add_ext("#9").add_ext("b13")
assert d_sharp9_flat13.root == Note("D", oct=4)
assert d_sharp9_flat13.notes == [Note("D", oct=4), Note("F#", oct=4), Note("A", oct=4), Note("F", oct=5), Note("A#", oct=5)]
d_sharp9_flat13Chord: 'No chord found.'. Notes: ['D4', 'F#4', 'A4', 'F5', 'A#5']
Extensions can be removed with remove_ext.
Here we remove the upper extensions as well as the third to get a D power chord (D5).
Chord objects can be played, just like Note objects.
Chord.play (length=1)
Chord.get_audio_array (length=1)
We can display all the relevant information about a chord in a Pandas DataFrame table.
Chord.to_frame ()
| Notes | Relative Degree | Relative Interval | Absolute Interval | Absolute Degree | |
|---|---|---|---|---|---|
| 0 | C | 1 | unison | unison | 1 |
| 1 | E | 3 | major third | major third | 3 |
| 2 | G | 5 | perfect fifth | minor third | b3 |
| 3 | B | 7 | major seventh | major third | 3 |
Visualizing the chord as a table gives us a nice overview for analysis.
For example, in the table for the Cdim6maj7 chord below we can readily see that it constitutes of: - A diminished triad (minor third (b3), and tritone (b5)), - a major sixth (6) and - a major seventh (maj7).
| Notes | Relative Degree | Relative Interval | Absolute Interval | Absolute Degree | |
|---|---|---|---|---|---|
| 0 | C | 1 | unison | unison | 1 |
| 1 | D# | b3 | minor third | minor third | b3 |
| 2 | F# | b5 | tritone | minor third | b3 |
| 3 | A | 6 | major sixth | minor third | b3 |
| 4 | B | 7 | major seventh | major second | 2 |
A PolyChord is a combination of notes. Much of the functionality is inherited from the Chord object.
PolyChord (chords:list[__main__.Chord])
Base class for objects needing a basic __repr__
Like Chord objects, PolyChord objects can be inverted.
PolyChord.invert (n:int=1)
PolyChord: 'C major seventh, first inversion|D suspended second triad'. Notes: ['E4', 'G4', 'B4', 'C5', 'D5', 'E5', 'A6']
[major third (3),
perfect fifth (5),
major seventh (7),
minor thirteenth (b13),
major ninth (9),
major tenth (10)]
For the table display of a PolyChord we analyze the underlying chords separately.
PolyChord.to_frame ()
| Notes | Relative Degree | Relative Interval | Absolute Interval | Absolute Degree | |
|---|---|---|---|---|---|
| 0 | C | 1 | unison | unison | 1 |
| 1 | E | 3 | major third | major third | 3 |
| 2 | G | 5 | perfect fifth | minor third | b3 |
| 3 | B | 7 | major seventh | major third | 3 |
| Notes | Relative Degree | Relative Interval | Absolute Interval | Absolute Degree | |
|---|---|---|---|---|---|
| 0 | A | 1 | unison | unison | 1 |
| 1 | D | 5 | perfect fifth | perfect fifth | 5 |
| 2 | E | 4 | perfect fourth | major second | 2 |
TODO: Check which scales/modes the chord belongs to.
FIX: Identify all diatonic chords in a scale.
TODO: Check if chord is diatonic within a scale.