Guess Scale or Chord from Notes
The music theory encoded in OMusic allows for some interesting applications. For example, omusic.guesser.guess takes a set of notes, then guesses which scale of chords the notes may be from.
[11]:
import random
random.seed(44313)
from omusic.guesser import guess, tabulate_guess
from omusic.guesser import TEST_SCALES, TEST_SCALES_STANDARD
Note that guess takes two arguments: (a) a set of note names and (b) scales and chords to test against.
The module comes with several options for the latter:
Option |
Included |
|---|---|
|
Major and minor |
|
Natural, harmonic, and melodic minors |
|
Augmented, diminished, pentatonic, and blues |
|
Augmented, diminished, pentatonic, and blues |
|
From Ionian to Locrian |
|
The (1, 3, 5) triad and sevenths |
|
Every scale. Probably has perfect matches for everything. |
Try not to use scales and TEST_CHORDS together: because scales are larger, the default sorting criteria will prioritise them. Consider using sort_key=matched_percent instead.
Suppose we are transcribe a song with “G”, “E”, and “C#”. Call guess, then tabulate the result:
[12]:
tabulate_guess(guess({"G", "E", "C#"},
TEST_SCALES)[:10],
tablefmt="html")
[12]:
| Base | Mode | Matched | Unused | Unmatched |
|---|---|---|---|---|
| C | diminished, half whole | {'C#', 'G', 'E'} | {'A#', 'D#', 'F#', 'C', 'A'} | set() |
| C# | diminished, whole half | {'C#', 'G', 'E'} | {'A#', 'D#', 'F#', 'C', 'A'} | set() |
| C# | diminished, half whole | {'C#', 'G', 'E'} | {'A#', 'B', 'D', 'F', 'G#'} | set() |
| C# | blues minor | {'C#', 'G', 'E'} | {'G#', 'B', 'F#'} | set() |
| C# | locrian | {'C#', 'G', 'E'} | {'D', 'A', 'B', 'F#'} | set() |
| D | major | {'C#', 'G', 'E'} | {'D', 'A', 'B', 'F#'} | set() |
| D | harmonic minor | {'C#', 'G', 'E'} | {'D', 'A', 'F', 'A#'} | set() |
| D | melodic minor | {'C#', 'G', 'E'} | {'D', 'A', 'F', 'B'} | set() |
| D | diminished, whole half | {'C#', 'G', 'E'} | {'A#', 'B', 'D', 'F', 'G#'} | set() |
| D | ionian | {'C#', 'G', 'E'} | {'D', 'A', 'B', 'F#'} | set() |
There are several good matches; half whole diminished C is unlikely to be the answer. Time to use your discretion: if the song sounds like a major, try to match for major and minor scales only:
[13]:
tabulate_guess(guess({"G", "E", "C#"},
TEST_SCALES_STANDARD)[:10],
tablefmt="html")
[13]:
| Base | Mode | Matched | Unused | Unmatched |
|---|---|---|---|---|
| D | major | {'C#', 'G', 'E'} | {'D', 'A', 'B', 'F#'} | set() |
| B | minor | {'C#', 'G', 'E'} | {'D', 'A', 'B', 'F#'} | set() |
| C | major | {'G', 'E'} | {'B', 'D', 'F', 'C', 'A'} | {'C#'} |
| C# | minor | {'C#', 'E'} | {'D#', 'B', 'F#', 'G#', 'A'} | {'G'} |
| D | minor | {'G', 'E'} | {'A#', 'D', 'F', 'C', 'A'} | {'C#'} |
| E | major | {'C#', 'E'} | {'D#', 'B', 'F#', 'G#', 'A'} | {'G'} |
| E | minor | {'G', 'E'} | {'B', 'F#', 'D', 'C', 'A'} | {'C#'} |
| F | major | {'G', 'E'} | {'A#', 'D', 'F', 'C', 'A'} | {'C#'} |
| F | minor | {'C#', 'G'} | {'A#', 'D#', 'F', 'C', 'G#'} | {'E'} |
| F# | minor | {'C#', 'E'} | {'B', 'F#', 'D', 'G#', 'A'} | {'G'} |
Looks like D is the answer!