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>
94 lines
3.2 KiB
Python
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}")
|