mirror of
https://github.com/kennethreitz/pytheory.git
synced 2026-06-05 14:50:18 +00:00
9da3ac8b28
- circle_of_fifths.py — visualize keys around the circle - chord_identifier.py — identify chords from notes and fingerings - key_explorer.py — explore keys, signatures, progressions, borrowed chords - temperament_comparison.py — compare equal, Pythagorean, and meantone - chord_tension.py — analyze tension, consonance, and voice leading - world_scales.py — scales from 6 musical traditions - fretboard_explorer.py — instruments, tunings, capo transposition - midi_converter.py — MIDI ↔ note ↔ frequency reference - progression_writer.py — famous progressions, Nashville numbers, random generation - interval_trainer.py — interval names, songs, and consonance ranking - overtone_series.py — harmonics and why chords sound good - key_detection.py — detect keys from melodies and chord progressions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
53 lines
1.5 KiB
Python
53 lines
1.5 KiB
Python
"""Analyze harmonic tension and resolution across chords."""
|
|
|
|
from pytheory import Chord
|
|
|
|
print("Chord Tension Analysis")
|
|
print("=" * 70)
|
|
print()
|
|
print(f"{'Chord':>20s} {'Tension':>8s} {'Harmony':>8s} {'Dissonance':>11s} {'Notes'}")
|
|
print(f"{'─' * 20} {'─' * 8} {'─' * 8} {'─' * 11} {'─' * 15}")
|
|
|
|
chords = [
|
|
# Stable chords
|
|
"C", "Am",
|
|
# Moderate tension
|
|
"Dm7", "Cmaj7",
|
|
# High tension
|
|
"G7", "Bdim",
|
|
# Extended
|
|
"Am7", "Cmaj9",
|
|
]
|
|
|
|
for name in chords:
|
|
chord = Chord.from_name(name)
|
|
t = chord.tension
|
|
tones = " ".join(tone.name for tone in chord.tones)
|
|
print(
|
|
f"{name:>20s} {t['score']:>8.2f} {chord.harmony:>8.4f}"
|
|
f" {chord.dissonance:>11.4f} {tones}"
|
|
)
|
|
|
|
# Show the V7 → I resolution
|
|
print()
|
|
print("─" * 70)
|
|
print()
|
|
print("The V7 → I resolution (the strongest pull in tonal music):")
|
|
print()
|
|
|
|
g7 = Chord.from_name("G7")
|
|
c = Chord.from_name("C")
|
|
|
|
print(f" G7 (dominant): tension={g7.tension['score']:.2f} "
|
|
f"tritones={g7.tension['tritones']} "
|
|
f"dominant_function={g7.tension['has_dominant_function']}")
|
|
print(f" C (tonic): tension={c.tension['score']:.2f} "
|
|
f"tritones={c.tension['tritones']} "
|
|
f"dominant_function={c.tension['has_dominant_function']}")
|
|
|
|
print()
|
|
print("Voice leading (G7 → C):")
|
|
for src, dst, motion in g7.voice_leading(c):
|
|
direction = "↑" if motion > 0 else "↓" if motion < 0 else "="
|
|
print(f" {src.name:3s} → {dst.name:3s} ({direction} {abs(motion)} semitones)")
|