Files
kennethreitz 7153dc908f Add Chord.from_name, Interval constants, PROGRESSIONS, enharmonic, fix API docs
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>
2026-03-22 07:09:16 -04:00

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}")