= Chord(["C", "E", "G"])
c_major assert c_major.name == "C major triad"
assert c_major.oct_s_notes == ["C4", "E4", "G4"]
c_major
Chord: '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_major
Chord: '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_eb
Chord: '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_flat13
Chord: '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.