Created
September 17, 2015 14:48
-
-
Save adamchalmers/8d7e5e19c9fbfb034d8d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """Lists ways to play a certain chord on mandolin. | |
| Example invocation: | |
| $ python mandolin_chords.py Abm | |
| Example output: | |
| The chord Abm has notes Ab, B, Eb | |
| (4, 6, 6, 4) plays B, Ab, Eb, Ab | |
| (8, 6, 6, 7) plays Eb, Ab, Eb, B | |
| (1, 1, 2, 4) plays Ab, Eb, B, Ab | |
| (4, 1, 2, 4) plays B, Eb, B, Ab | |
| (4, 6, 6, 7) plays B, Ab, Eb, B | |
| """ | |
| import itertools | |
| import sys | |
| NOTES = ["A", "Bb", "B", "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab"] | |
| def note_up(note, dist): | |
| """Returns the note $dist semitones above base note $note.""" | |
| return NOTES[(NOTES.index(note) + dist) % len(NOTES)] | |
| def notes_in_chord(chord): | |
| """Returns the three notes that make $chord. $chord examples: 'A', 'Cbm'.""" | |
| targets = [] | |
| if chord[-1] == "m": | |
| assert chord[:-1] in NOTES, "%s isn't a valid note." % chord[:-1] | |
| targets.append(chord[:-1]) | |
| targets.append(note_up(targets[0], 3)) | |
| else: | |
| assert chord in NOTES, "%s isn't a valid note." % chord | |
| targets.append(chord) | |
| targets.append(note_up(targets[0], 4)) | |
| targets.append(note_up(targets[0], 7)) | |
| return targets | |
| def fingers_for_chord(chord): | |
| targets = set(notes_in_chord(chord)) | |
| options = [] # List of 4 ints, representing which fret to play on each string. | |
| print "The chord %s has notes %s" % (chord, ", ".join(notes_in_chord(chord))) | |
| # Loop over every possible combination of frets on each of the four strings | |
| for g, d, a, e in itertools.product(range(16), range(16), range(16), range(16)): | |
| positions = {"G": g, "D": d, "A": a, "E": e} | |
| notes = [note_up(note, i) for note, i in positions.items()] | |
| # If this combination of frets plays the chord, add it to the options list. | |
| if targets == set(notes): | |
| options.append((g, d, a, e)) | |
| # Sort the list by the amount your fingers have to stretch. | |
| options.sort(key=lambda option: max(option) - min(option)) | |
| for option in options[:5]: | |
| ma, mi = max(option), min(option) | |
| print option, "plays", ", ".join([note_up(n,i) for n,i in zip(["G", "D", "A", "E"], option)]) | |
| if __name__ == "__main__": | |
| fingers_for_chord(sys.argv[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment