Cookbook ======= Real-world recipes for common musical tasks. Each recipe is self-contained and ready to paste into a Python session. Analyze a Song -------------- Take the chord progression from "Let It Be" (C G Am F) and analyze it in the key of C major: .. code-block:: pycon >>> from pytheory import Chord, Key >>> C = Chord.from_name("C") >>> G = Chord.from_name("G") >>> Am = Chord.from_name("Am") >>> F = Chord.from_name("F") >>> [c.identify() for c in [C, G, Am, F]] ['C major', 'G major', 'A minor', 'F major'] >>> [c.analyze("C") for c in [C, G, Am, F]] ['I', 'V', 'vi', 'IV'] >>> key = Key("C", "major") >>> [c.identify() for c in key.progression("I", "V", "vi", "IV")] ['C major', 'G major', 'A minor', 'F major'] Write a 12-Bar Blues -------------------- The `12-bar blues `_ is built from the I, IV, and V chords. Here it is in the key of A: .. code-block:: pycon >>> from pytheory import Key, Chord >>> key = Key("A", "major") >>> [c.identify() for c in key.progression("I", "IV", "V")] ['A major', 'D major', 'E major'] >>> bars = ["I","I","I","I", "IV","IV","I","I", "V","IV","I","V"] >>> [c.identify() for c in key.progression(*bars)] ['A major', 'A major', 'A major', 'A major', 'D major', 'D major', 'A major', 'A major', 'E major', 'D major', 'A major', 'E major'] >>> Chord.from_name("A7").identify() 'A dominant 7th' >>> Chord.from_name("D7").identify() 'D dominant 7th' >>> Chord.from_name("E7").identify() 'E dominant 7th' Find Chords in a Key -------------------- The :class:`~pytheory.scales.Key` class builds diatonic chords for any key and lets you pull progressions by Roman numeral or Nashville number: .. code-block:: pycon >>> from pytheory import Key >>> key = Key("G", "major") >>> key.chords ['G major', 'A minor', 'B minor', 'C major', 'D major', 'E minor', 'F# diminished'] >>> [c.identify() for c in key.progression("I", "V", "vi", "IV")] ['G major', 'D major', 'E minor', 'C major'] >>> [c.identify() for c in key.nashville(1, 5, 6, 4)] ['G major', 'D major', 'E minor', 'C major'] Compare Scales -------------- Play the same tonic through different scales to hear how each mode reshapes the palette. The western modes share the same notes but start on different degrees; the blues scale adds the "blue note" (flat 5th): .. code-block:: pycon >>> from pytheory import TonedScale >>> c = TonedScale(tonic="C4") >>> c["major"].note_names ['C', 'D', 'E', 'F', 'G', 'A', 'B', 'C'] >>> c["minor"].note_names ['C', 'D', 'Eb', 'F', 'G', 'Ab', 'Bb', 'C'] >>> c["dorian"].note_names ['C', 'D', 'Eb', 'F', 'G', 'A', 'Bb', 'C'] >>> c["mixolydian"].note_names ['C', 'D', 'E', 'F', 'G', 'A', 'Bb', 'C'] >>> c_blues = TonedScale(tonic="C4", system="blues") >>> c_blues["blues"].note_names ['C', 'Eb', 'F', 'Gb', 'G', 'Bb', 'C'] Guitar Chord Chart ------------------ Generate fingerings for guitar and ukulele with :class:`~pytheory.tones.Fretboard`: .. code-block:: pycon >>> from pytheory import Fretboard >>> fb = Fretboard.guitar() >>> fb.chord("C") Fingering(e=0, B=1, G=0, D=2, A=3, E=x) >>> fb.chord("G") Fingering(e=3, B=0, G=0, D=0, A=2, E=3) >>> fb.chord("Am") Fingering(e=0, B=1, G=2, D=2, A=0, E=x) >>> fb.chord("D") Fingering(e=2, B=3, G=2, D=0, A=x, E=x) >>> uke = Fretboard.ukulele() >>> uke.chord("C") Fingering(A=3, E=0, C=0, G=0) >>> uke.chord("G") Fingering(A=2, E=3, C=2, G=0) Explore an Interval ------------------- Start from A4 (440 Hz) and walk through intervals, checking names and frequency ratios: .. code-block:: pycon >>> from pytheory import Tone >>> a4 = Tone.from_string("A4", system="western") >>> a4.frequency 440.0 >>> minor_3rd = a4 + 3 >>> a4.interval_to(minor_3rd) 'minor 3rd' >>> p5 = a4 + 7 >>> a4.interval_to(p5) 'perfect 5th' >>> round(p5.frequency / a4.frequency, 4) 1.4983 >>> octave = a4 + 12 >>> a4.interval_to(octave) 'octave' >>> round(octave.frequency / a4.frequency, 4) 2.0 Walk the Circle of Fifths ------------------------- The `circle of fifths `_ is the backbone of Western harmony — each step adds one sharp or flat: .. code-block:: pycon >>> from pytheory import Tone >>> c = Tone.from_string("C4", system="western") >>> [t.name for t in c.circle_of_fifths()] ['C', 'G', 'D', 'A', 'E', 'B', 'F#', 'C#', 'G#', 'D#', 'A#', 'F'] >>> g = Tone.from_string("G4", system="western") >>> [t.name for t in g.circle_of_fifths()] ['G', 'D', 'A', 'E', 'B', 'F#', 'C#', 'G#', 'D#', 'A#', 'F', 'C'] Voice Leading Between Chords ----------------------------- Find the smoothest path from one chord to the next — each voice moves the minimum distance: .. code-block:: pycon >>> from pytheory import Chord >>> c_maj = Chord.from_tones("C", "E", "G") >>> f_maj = Chord.from_tones("F", "A", "C") >>> for src, dst, motion in c_maj.voice_leading(f_maj): ... print(f"{src} -> {dst} ({motion:+d} semitones)") G4 -> A4 (+2 semitones) E4 -> F4 (+1 semitones) C4 -> C4 (+0 semitones) Measure Harmonic Tension ------------------------ Quantify how much a chord "wants to resolve." Dominant 7ths have the most tension — the tritone between the 3rd and 7th pulls toward resolution: .. code-block:: pycon >>> from pytheory import Chord >>> for name in ["C", "Am", "G7", "Cmaj7"]: ... ch = Chord.from_name(name) ... t = ch.tension ... print(f"{name:6s} tension={t['score']:.2f} tritones={t['tritones']} dominant={t['has_dominant_function']}") C tension=0.00 tritones=0 dominant=False Am tension=0.00 tritones=0 dominant=False G7 tension=0.60 tritones=1 dominant=True Cmaj7 tension=0.15 tritones=0 dominant=False Tritone Substitution (Jazz) --------------------------- Replace any dominant chord with the one a `tritone `_ away — they share the same tritone interval: .. code-block:: pycon >>> from pytheory import Chord >>> g7 = Chord.from_name("G7") >>> g7.tritone_sub().identify() 'C# dominant 7th' >>> # ii-V-I with tritone sub: >>> # Dm7 -> G7 -> Cmaj7 (standard) >>> # Dm7 -> Db7 -> Cmaj7 (chromatic bass line!) Key Signatures and Detection ----------------------------- View the accidentals in any key, or detect the key from a set of notes: .. code-block:: pycon >>> from pytheory import Key >>> Key("C", "major").signature {'sharps': 0, 'flats': 0, 'accidentals': []} >>> Key("G", "major").signature {'sharps': 1, 'flats': 0, 'accidentals': ['F#']} >>> Key("D", "major").signature {'sharps': 2, 'flats': 0, 'accidentals': ['F#', 'C#']} >>> Key.detect("C", "E", "G", "A", "D") Relative and Parallel Keys -------------------------- Every major key has a **relative minor** (same notes, different root) and a **parallel minor** (same root, different notes): .. code-block:: pycon >>> from pytheory import Key >>> c = Key("C", "major") >>> c.relative 'A minor' >>> c.parallel 'C minor' Borrowed Chords and Secondary Dominants --------------------------------------- Add color by borrowing from the parallel key or building secondary dominants that approach other scale degrees: .. code-block:: pycon >>> from pytheory import Key >>> c = Key("C", "major") >>> c.borrowed_chords[:4] ['C minor', 'D diminished', 'Eb major', 'F minor'] >>> c.secondary_dominant(5).identify() 'D dominant 7th' >>> c.secondary_dominant(2).identify() 'A dominant 7th' >>> c.secondary_dominant(6).identify() 'E dominant 7th' The Overtone Series ------------------- Every musical tone contains a stack of harmonics — the physics behind why intervals sound consonant: .. code-block:: pycon >>> from pytheory import Tone >>> a4 = Tone.from_string("A4", system="western") >>> [round(f, 1) for f in a4.overtones(6)] [440.0, 880.0, 1320.0, 1760.0, 2200.0, 2640.0] >>> # Harmonic 2 = octave (2:1) >>> # Harmonic 3 = perfect 5th + octave (3:1) >>> # Harmonic 5 = major 3rd + two octaves (5:1) Enharmonic Spellings -------------------- Find the alternate name for any sharp or flat: .. code-block:: pycon >>> from pytheory import Tone >>> for name in ["C#4", "D#4", "F#4", "G#4"]: ... t = Tone.from_string(name, system="western") ... print(f"{t.name} = {t.enharmonic}") C# = Db D# = Eb F# = Gb G# = Ab World Scales ------------ Explore scales from Indian, Arabic, and Japanese traditions: .. code-block:: pycon >>> from pytheory import TonedScale >>> indian = TonedScale(tonic="Sa", system="indian") >>> indian["bhairav"].note_names ['Sa', 'komal Re', 'Ga', 'Ma', 'Pa', 'komal Dha', 'Ni', 'Sa'] >>> arabic = TonedScale(tonic="Do", system="arabic") >>> arabic["hijaz"].note_names ['Do', 'Reb', 'Mi', 'Fa', 'Sol', 'Solb', 'Sib', 'Do'] >>> japanese = TonedScale(tonic="C4", system="japanese") >>> japanese["hirajoshi"].note_names ['C', 'D', 'Eb', 'G', 'Ab', 'C'] Visualize a Scale on Guitar ---------------------------- See where the notes fall across the fretboard — E minor pentatonic, the most-played scale in rock: .. code-block:: pycon >>> from pytheory import Fretboard, Scale >>> fb = Fretboard.guitar() >>> pent = Scale(tonic="E4", system="blues")["minor pentatonic"] >>> print(fb.scale_diagram(pent, frets=12)) 0 1 2 3 4 5 6 7 8 9 10 11 12 E| E | - | - | G | - | A | - | B | - | - | D | - | E | B| B | - | - | D | - | E | - | - | G | - | A | - | B | G| G | - | A | - | B | - | - | D | - | E | - | - | G | D| D | - | E | - | - | G | - | A | - | B | - | - | D | A| A | - | B | - | - | D | - | E | - | - | G | - | A | E| E | - | - | G | - | A | - | B | - | - | D | - | E |