SkillAgentSearch skills...

Pyharmonytooling

python code to manage music harmony

Install / Use

/learn @Moustov/Pyharmonytooling

README

PyHarmonyTooling

<div align="center"> <img src="circle_of_5th.png" width="300" alt="Circle of 5th"> </div>

OVERVIEW

Series of tools to handle harmony in music

Install

pip install pyHarmonyTooling 

Features

Usages of this library:

  • https://github.com/Moustov/pyHarmonyUI

Warning

All possible chord names are defined by the PyChord library See here

Features on Harmony

Find substitutes from a chord

It is possible to find a chord other names

from pyharmonytools.harmony.cof_chord import CofChord

chord = "G6"
substitutes = CofChord.find_substitutes(Chord(chord))
print("substitutes from :", chord, substitutes)

ouput (detailed log skipped):

substitutes from : G6 [<Chord: Em7>, <Chord: Em7/9>, <Chord: Em7/11>, <Chord: Em7/13>, <Chord: Em/D>, <Chord: Em7/B>, <Chord: Em7/D>, <Chord: Em7/G>, <Chord: Em7/9/B>, <Chord: Em7/9/D>, <Chord: Em7/9/G>, <Chord: Em7/11/B>, <Chord: Em7/11/D>, <Chord: Em7/11/G>, <Chord: Em7/13/B>, <Chord: Em7/13/D>, <Chord: Em7/13/G>, <Chord: G6>, <Chord: G6/9>, <Chord: G/E>, <Chord: G6/B>, <Chord: G6/D>, <Chord: G6/E>, <Chord: G6/9/B>, <Chord: G6/9/D>, <Chord: G6/9/E>]

See related unit tests

Guess chord from notes

To guess a chord from notes, there is a feature that enables:

  • to have a list of possible chords that include all the provided notes
  • to limit this list to chord with exactly the same notes (is_strictly_compliant=True)
  • to provide the simplest possible chord (simplest_chord_only=True)

Code sample:

from pychord import Chord
from pyharmonytools.harmony.cof_chord import CofChord
from pyharmonytools.harmony.note import Note

expected = [Chord("Cmaj7")]
notes = [Note("C"), Note("E"), Note("G"), Note("B")]
res = CofChord.guess_chord_name(notes, is_strictly_compliant=True, simplest_chord_only=True)
print(res == expected)

output:

True

See related unit tests

Guitar tools

Find chord fingering on a guitar

from pyharmonytools.guitar_neck.fingering import Fingering

fng = Fingering()
f = fng.get_fingering_from_chord(Chord("C"))
print(f)

output:

[[0, 3, 2, 0, 1, 0], [0, 3, 2, 0, 1, 3], [3, 3, 2, 0, 1, 0], ... ]

Find chords from tabs

This tool is done to guess involved chords from a guitar tab. It is supposed to handle tab guitar techniques such as

  • h: Hammer-on
  • p: Pull-off
  • ^: Bend
  • /: Slide up
  • \: Slide down
  • ~: Vibrato

The involved method is based on building chords as long as the fret range is acceptable (Fingering.FINGERING_WIDTH) and you have enough fingers or a tab therefore, sometimes the chord guessing is not accurate since musical phrases are not taken into account.

This wizard is then merely a guide you should check with both hears and fingers! :wink:

from pyharmonytools.displays.console_for_guitar_tab import ConsoleForGuitarTab
from pyharmonytools.guitar_tab.guitar_tab import GuitarTab

tab = """
      e|--11-----11-----10-----11---|
      B|--11-----12-----11-----11---|
      G|--11-----13-----10-----11---|
      D|----------------------------|
      A|----------------------------|
      E|----------------------------|
"""
gt = GuitarTab(tab_full)
ConsoleForGuitarTab.display(gt)

Output

----------------
Bar #0:
    D#m    G#m    A#     D#m    
e|--11-----11-----10-----11----|
B|--11-----12-----11-----11----|
G|--11-----13-----10-----11----|
D|-----------------------------|
A|-----------------------------|
E|-----------------------------|

If the tab if well formatted (only tabbed strings with names and | as bars separators), a whole song can be processes. Among the unit tests, a chord guessing of Johann Sebastian Bach's Prelude for Cello, Suite No. 1 (BWV1007) can be found.

See related unit tests

Song Processing

Song processing tools on simple text song

It is possible to extracts chords from a song

    from pychord import Chord 
    from pyharmonytools.song.text_song import TextSongWithLineForChords

    song = """
                        A           E
                Happy Birthday to you
                      E           A
                Happy Birthday to you
                      A7            D
                Happy Birthday dear (name)
                      A        E    A
                Happy Birthday to you
            """
    the_song = TextSongWithLineForChords()
    the_song.digest(song)
    print(the_song.chords_sequence)

output:

[<Chord: A>, <Chord: E>, <Chord: E>, <Chord: A>, <Chord: A7>, <Chord: D>, <Chord: A>, <Chord: E>, <Chord: A>]

See related unit tests

Guess the tonality & mode of a song"

It is possible to guess a song tonality and the mode that goes along

from pyharmonytools.displays.console import _HarmonyLogger
from pyharmonytools.harmony.circle_of_5th import CircleOf5th

_HarmonyLogger.outcome_level_of_detail = _HarmonyLogger.LOD_NONE

ouput:

[1.0, 'A', 'Natural Major', ['A', 'B', 'Db', 'D', 'E', 'Gb', 'Ab', 'Ab']]

Guess borrowed chords in a song

It is possible to guess borrowed chords from a song from a tonality point of view

song = """
      C Dm Em F G Am Bdim Cm
      """
cof = CircleOf5thNaturalMajor()
cp = cof.digest_song(song)
tone = cof.generate_circle_of_fifths()["C"]
borrowed_chords = cof.get_borrowed_chords(tone, cp)
print("   Borrowed chords:", borrowed_chords.keys())

ouput:

Borrowed chords: dict_keys(['Cm'])

See related unit tests

Get degrees on a song from a guessed tonality

It is possible to guess a chord song from a degree point of view

    from pychord import Chord
    from pyharmonytools.displays.unit_test_report import UnitTestReport
    from pyharmonytools.song.text_song import TextSongWithLineForChords

    song = """
                        A           E
                Happy Birthday to you
                      E           A
                Happy Birthday to you
                      A7            D
                Happy Birthday dear (name)
                      A        E    A
                Happy Birthday to you
            """
    the_song = TextSongWithLineForChords()
    the_song.digest(song)
    the_song.generate_degrees_from_chord_progression()
    assert (the_song.degrees == ['I', 'V', 'V', 'I', 'I7', 'IV', 'I', 'V', 'I'])

Guess chord progressions ("cadences" in a song)

It is possible to guess remarkable cadences in a song

    from deepdiff import DeepDiff
    from pyharmonytools.displays.unit_test_report import UnitTestReport
    from pyharmonytools.song.text_song import TextSongWithLineForChords
    
    song = """
                        A           E
                Happy Birthday to you
                      E           A
                Happy Birthday to you
                      A7            D
                Happy Birthday dear (name)
                      A        E    A
                Happy Birthday to you
            """
    the_song = TextSongWithLineForChords()
    the_song.digest(song)
    the_song.generate_degrees_from_chord_progression()
    res = the_song.get_remarquable_cadences()
    expected = {'REMARQUABLE_CADENCES_NATURAL_MAJOR:AUTHENTIC CADENCE': [4]}
    diff = DeepDiff(res, expected, ignore_order=True)
    self.ut_report.assertTrue(diff == {})

The returned dictionary provides for each cadence the chord position the progression starts

Transpose song chords

It is possible to transpose a song with a number_half_tone:

    from pychord import Chord
    from pyharmonytools.displays.unit_test_report import UnitTestReport
    from pyharmonytools.song.text_song import TextSongWithLineForChords

    song_happy_birthday = """
                        A           E
                Happy Birthday to you
                      E           A
                Happy Birthday to you
                      A7            D
                Happy Birthday dear (name)
                      A        E    A
                Happy Birthday to you
            """
    the_song = TextSongWithLineForChords()
    the_song.digest(song_happy_birthday)
    the_song.generate_degrees_from_chord_progression()
    res = the_song.transpose(number_half_tone=-5)
    expected = ['E', 'B', 'B', 'E', 'E7', 'A', 'E', 'B', 'E']
    self.ut_report.assertTrue(res == expected)

Song Querying

Song search & processing tools on Ultimate Guitar through Google.com

You may search and handle song lyrics & tabs

from pyharmonytools.song.song import UltimateGuitarSong
from pyharmonytools.song.ultimate_guitar_search import UltimateGuitarSearch

ug_engine = UltimateGuitarSearch()
query = "D Dm A"
urls = ug_engine.search(query, 20)
song = UltimateGuitarSong()
for link in urls:
    print("===================================")
    song.extract_song_from_url(link)
    print(song.get_string())

This piece of code will display 20 songs matching the query (songs holding the "D/Dm/A" cadence)

Output:

===================================
Title: AUTREFOIS
Artist: Pink Martini
[tab][ch]A[/ch]                                     [ch]D[/ch]\r\nJ'ai ecris des mots doux а toutes les filles de France[/tab]\r\n
[tab][ch]Dm[/ch]                

Related Skills

View on GitHub
GitHub Stars7
CategoryDevelopment
Updated1y ago
Forks1

Languages

HTML

Security Score

60/100

Audited on Jan 20, 2025

No findings