Workbench

Harmonize Scales with the Python Musthe library

I'm pleased to say that a new feature I wrote for the Python musthe music theory library has accepted and merged into the code base.

If you're not familiar with Musthe, it's a general-purpose library for exploring scales and chords; the project README gives a good overview of the kinds of things you can do with it.

I added two new methods to the Scale class: harmonize() and harmonize_dict(). Given any scale, these methods will return all of the diatonic chords (That is, chords containing notes from that scale,) plus dominant 7th chords.

Installation

As of July 2024, you'll need to install musthe directly from the git repository to use the latest features, as there has not been a new PyPi release since 2018:

pip install musthe@git+https://github.com/gciruelos/musthe

Usage

For example, to get a dictionary of chords for the E Dorian scale:

from musthe import Note, Scale
from pprint import pprint

scale = Scale(Note('E'), 'dorian')
pprint(scale.harmonize(), indent=2, compact=True)

This will give you:

[ [ Chord(Note('E4'), 'min'), Chord(Note('E4'), 'min7'),
    Chord(Note('E4'), 'sus2'), Chord(Note('E4'), 'sus4'),
    Chord(Note('E4'), 'open5'), Chord(Note('E4'), 'min9')],
  [ Chord(Note('F#4'), 'min'), Chord(Note('F#4'), 'min7'),
    Chord(Note('F#4'), 'sus4'), Chord(Note('F#4'), 'open5')],
  [ Chord(Note('G4'), 'maj'), Chord(Note('G4'), 'dom7'),
    Chord(Note('G4'), 'maj7'), Chord(Note('G4'), 'sus2'),
    Chord(Note('G4'), 'open5'), Chord(Note('G4'), 'dom9'),
    Chord(Note('G4'), 'maj9')],
  [ Chord(Note('A4'), 'maj'), Chord(Note('A4'), 'dom7'),
    Chord(Note('A4'), 'sus2'), Chord(Note('A4'), 'sus4'),
    Chord(Note('A4'), 'open5'), Chord(Note('A4'), 'dom9')],
  [ Chord(Note('B4'), 'min'), Chord(Note('B4'), 'min7'),
    Chord(Note('B4'), 'sus2'), Chord(Note('B4'), 'sus4'),
    Chord(Note('B4'), 'open5'), Chord(Note('B4'), 'min9')],
  [Chord(Note('C#4'), 'dim'), Chord(Note('C#4'), 'm7dim5')],
  [ Chord(Note('D4'), 'maj'), Chord(Note('D4'), 'dom7'),
    Chord(Note('D4'), 'maj7'), Chord(Note('D4'), 'sus2'),
    Chord(Note('D4'), 'sus4'), Chord(Note('D4'), 'open5'),
    Chord(Note('D4'), 'dom9'), Chord(Note('D4'), 'maj9')]]

Or, for a human-friendlier output you can use harmonize_dict() and format the chords as strings:

for note, chords in scale.harmonize_dict().items():
  print(note)
  for c in chords:
    print(f"\t{c}")

Which gives you:

E
        Emin
        Emin7
        Esus2
        Esus4
        Eopen5
        Emin9
F#
        F#min
        F#min7
        F#sus4
        F#open5
G
        Gmaj
        Gdom7
        Gmaj7
        Gsus2
        Gopen5
        Gdom9
        Gmaj9
A
        Amaj
        Adom7
        Asus2
        Asus4
        Aopen5
        Adom9
B
        Bmin
        Bmin7
        Bsus2
        Bsus4
        Bopen5
        Bmin9
C#
        C#dim
        C#m7dim5
D
        Dmaj
        Ddom7
        Dmaj7
        Dsus2
        Dsus4
        Dopen5
        Ddom9
        Dmaj9

If you prefer to omit dominant 7th chords, you can use harmonize(include_dom7=False) and harmonize_dict(include_dom7=False).


Mon Jul 29 2024 20:00:00 GMT-0400 (Eastern Daylight Time)