Files
pytheory/examples/interval_trainer.py
T
kennethreitz 9da3ac8b28 Add 12 example scripts showcasing pytheory features
- 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>
2026-03-22 20:27:18 -04:00

94 lines
3.2 KiB
Python

"""Learn intervals — names, sounds, and relationships."""
from pytheory import Tone, Chord, Interval
c4 = Tone.from_string("C4", system="western")
# ── Interval Reference ──────────────────────────────────────────────────
print("Interval Reference (from C4)")
print("=" * 70)
print()
print(f"{'Semitones':>10s} {'Note':>5s} {'Interval Name':>18s} {'Sound / Song'}")
print(f"{'' * 10} {'' * 5} {'' * 18} {'' * 30}")
songs = {
0: "Same note",
1: "Jaws",
2: "Happy Birthday",
3: "Greensleeves",
4: "Here Comes the Sun",
5: "Here Comes the Bride",
6: "The Simpsons",
7: "Star Wars (main theme)",
8: "Love Story",
9: "My Bonnie Lies Over the Ocean",
10: "Somewhere (West Side Story)",
11: "Take On Me (chorus)",
12: "Somewhere Over the Rainbow",
}
for semitones in range(13):
tone = c4 + semitones
name = c4.interval_to(tone)
song = songs.get(semitones, "")
print(f"{semitones:>10d} {tone.name:>5s} {name:>18s} {song}")
# ── Interval Constants ──────────────────────────────────────────────────
print()
print("Interval Constants (pytheory.Interval)")
print("=" * 40)
constants = [
("UNISON", Interval.UNISON),
("MINOR_SECOND", Interval.MINOR_SECOND),
("MAJOR_SECOND", Interval.MAJOR_SECOND),
("MINOR_THIRD", Interval.MINOR_THIRD),
("MAJOR_THIRD", Interval.MAJOR_THIRD),
("PERFECT_FOURTH", Interval.PERFECT_FOURTH),
("TRITONE", Interval.TRITONE),
("PERFECT_FIFTH", Interval.PERFECT_FIFTH),
("MINOR_SIXTH", Interval.MINOR_SIXTH),
("MAJOR_SIXTH", Interval.MAJOR_SIXTH),
("MINOR_SEVENTH", Interval.MINOR_SEVENTH),
("MAJOR_SEVENTH", Interval.MAJOR_SEVENTH),
("OCTAVE", Interval.OCTAVE),
]
for name, value in constants:
print(f" Interval.{name:16s} = {value}")
# ── Compound Intervals ─────────────────────────────────────────────────
print()
print("Compound Intervals (beyond one octave)")
print("=" * 50)
for semitones in [13, 14, 15, 16, 19, 24]:
tone = c4 + semitones
name = c4.interval_to(tone)
print(f" {semitones:2d} semitones {tone.full_name:5s} {name}")
# ── Consonance Ranking ──────────────────────────────────────────────────
print()
print("Intervals Ranked by Consonance")
print("=" * 50)
intervals = []
for semitones in range(1, 13):
tone = c4 + semitones
dyad = Chord.from_tones("C", tone.name)
name = c4.interval_to(tone)
intervals.append((dyad.harmony, dyad.dissonance, semitones, name))
# Sort by harmony score (descending)
intervals.sort(key=lambda x: x[0], reverse=True)
print(f"{'Rank':>5s} {'Interval':>18s} {'Harmony':>8s} {'Dissonance':>11s}")
print(f"{'' * 5} {'' * 18} {'' * 8} {'' * 11}")
for rank, (harmony, dissonance, _, name) in enumerate(intervals, 1):
print(f"{rank:>5d} {name:>18s} {harmony:>8.4f} {dissonance:>11.4f}")