mirror of
https://github.com/kennethreitz/pytheory.git
synced 2026-06-05 06:46:14 +00:00
7153dc908f
New features:
- Chord.from_name("Am7") — build chords from chart names
- Chord.__str__() — prints "C major" instead of raw tones
- Interval constants: Interval.PERFECT_FIFTH, MAJOR_THIRD, OCTAVE, etc.
- PROGRESSIONS dict: 8 common progressions as Roman numeral tuples
("I-V-vi-IV", "ii-V-I", "12-bar blues", etc.)
- Tone.enharmonic: C# → "Db", natural notes → None
- Key.__str__(): "C major"
Fix: docs CI now installs all dependencies (uv sync --group docs)
so autodoc can import pytheory modules. API reference pages were
blank on GitHub Pages because pytuning/scipy weren't installed.
New example: examples/explore.py — comprehensive demo of the full API.
393 tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
75 lines
3.1 KiB
Python
75 lines
3.1 KiB
Python
"""Explore music theory with PyTheory."""
|
|
|
|
from pytheory import Key, Chord, Tone, Interval, PROGRESSIONS, Fretboard
|
|
|
|
# ── Keys and Scales ──────────────────────────────────────────────────────
|
|
|
|
key = Key("C", "major")
|
|
print(f"Key: {key}")
|
|
print(f"Notes: {key.note_names}")
|
|
print()
|
|
|
|
# ── Diatonic Harmony ─────────────────────────────────────────────────────
|
|
|
|
print("Diatonic triads:")
|
|
for i, chord in enumerate(key.scale.harmonize()):
|
|
analysis = chord.analyze("C")
|
|
print(f" {analysis:4s} {chord}")
|
|
|
|
print()
|
|
print("Diatonic seventh chords:")
|
|
for name in key.seventh_chords:
|
|
print(f" {name}")
|
|
|
|
# ── Progressions ─────────────────────────────────────────────────────────
|
|
|
|
print()
|
|
print("Common progressions in C major:")
|
|
for name, numerals in PROGRESSIONS.items():
|
|
chords = key.progression(*numerals)
|
|
chord_names = [str(c) for c in chords]
|
|
print(f" {name:20s} {' → '.join(chord_names)}")
|
|
|
|
# ── Intervals ────────────────────────────────────────────────────────────
|
|
|
|
print()
|
|
c4 = Tone.from_string("C4", system="western")
|
|
print("Intervals from C4:")
|
|
for semitones in range(13):
|
|
tone = c4 + semitones
|
|
name = c4.interval_to(tone)
|
|
print(f" {semitones:2d} semitones = {tone.name:3s} ({name})")
|
|
|
|
# ── Circle of Fifths ─────────────────────────────────────────────────────
|
|
|
|
print()
|
|
print("Circle of fifths:", " → ".join(t.name for t in c4.circle_of_fifths()))
|
|
|
|
# ── Chord Analysis ───────────────────────────────────────────────────────
|
|
|
|
print()
|
|
g7 = Chord.from_name("G7")
|
|
print(f"Chord: {g7}")
|
|
print(f" Intervals: {g7.intervals}")
|
|
print(f" Tension: {g7.tension}")
|
|
print(f" Analysis in C: {g7.analyze('C')}")
|
|
|
|
# ── Guitar Fingerings ────────────────────────────────────────────────────
|
|
|
|
print()
|
|
fb = Fretboard.guitar()
|
|
print("Guitar fingerings:")
|
|
for name in ["C", "G", "Am", "F", "Dm", "E7"]:
|
|
from pytheory import CHARTS
|
|
fingering = CHARTS["western"][name].fingering(fretboard=fb)
|
|
print(f" {name:4s} {fingering}")
|
|
|
|
# ── Overtone Series ──────────────────────────────────────────────────────
|
|
|
|
print()
|
|
a4 = Tone.from_string("A4", system="western")
|
|
print(f"Overtone series of {a4}:")
|
|
for i, hz in enumerate(a4.overtones(8), 1):
|
|
nearest = Tone.from_frequency(hz)
|
|
print(f" Harmonic {i}: {hz:8.1f} Hz ≈ {nearest.full_name}")
|