Melodies: Twinkle Twinkle, Ode to Joy, Happy Birthday, Fur Elise
Progressions: Pop I-V-vi-IV, 12-bar blues in A, Jazz ii-V-I turnaround
Interactive menu for picking songs. Clean helper functions for
melody and chord progression playback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
14 tests covering: flat tone creation, frequency matching with sharp
equivalents, all enharmonic pairs, arithmetic, intervals, exists
property, index resolution, chords built from flats, and
System.resolve_name().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Flat names are now resolved to their canonical sharp equivalents when
looking up tones in a system. This means Tone.from_string("Db4") now
works for frequency, arithmetic, intervals, and chord building —
previously it raised a ValueError.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace plain tuples from fingering() methods with a Fingering object
that labels each fret position with its string name, supporting both
named (f['A']) and index (f[1]) access while remaining backward
compatible with tuple equality.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Chord names like Cmaj7 and G7 were incorrectly treated as tone names
because they contain digits. Now tries chord name lookup first. v0.5.1.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Supports single tones and chords, with --synth (sine/saw/triangle),
--duration, and --temperament flags. Bumps version to v0.5.0.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dedicated section explaining symbolic=True with examples across
all three temperaments, showing exact SymPy expressions, arbitrary
precision evaluation, and why the math reveals temperament differences.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pytheory tone C5 -t pythagorean
pytheory tone A4 -t meantone
Shows frequency in chosen temperament and difference in cents
from equal temperament. Supports equal, pythagorean, meantone.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CLI (pytheory command):
pytheory tone C4 — frequency, MIDI, overtones
pytheory scale C major — notes and intervals
pytheory chord C E G — identify, harmony, tension
pytheory key C major — full key analysis with diatonic chords
pytheory fingering Am — ASCII guitar tab
pytheory progression C major I V vi IV — build from Roman numerals
pytheory detect C D E G — detect the key
Jupyter notebook (examples/tutorial.ipynb):
46-cell interactive tutorial covering tones, scales, modes, keys,
chord analysis, progressions, world music systems, guitar fingerings,
and building a song from scratch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Type hints: all methods and properties across Tone, Scale, TonedScale,
Key, Chord, and Fretboard now have full type annotations using
from __future__ import annotations.
Docstrings: added to all methods that were missing them —
constructors, dunder methods, properties, classmethods.
Property caching:
- TonedScale._scales: computed once and cached (immutable after init)
- Chord.identify(): cached result, cleared on transpose/inversion
- Tone.frequency: cached after first computation
428 tests passing, no behavior changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fretboard:
- Fretboard.guitar(capo=2) — capo as constructor parameter
- fretboard.capo(fret) — apply capo to any instrument
Chord:
- chord1 + chord2 — merge/layer two chords
- chord.tritone_sub() — jazz tritone substitution (transpose by 6)
Key:
- key.secondary_dominant(5) → V/V (e.g. D7 in C major)
- Key.all_keys() → all 24 major and minor keys
Progressions (14 total, up from 8):
- Pachelbel (Canon in D)
- Andalusian cadence (flamenco)
- Rhythm changes A section
- Jazz turnaround (iii-vi-ii-V)
- Dorian vamp, Mixolydian vamp
Also: py.typed marker for type checkers. 428 tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- full_name used 'if self.octave' which is falsy for octave 0,
so A0 displayed as "A" instead of "A0"
- pitch() used 'self.octave or 4' which defaulted octave 0 to 4,
so A0 returned 440 Hz instead of 27.5 Hz
Both now use 'is not None' checks. 404 tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dependencies were at the root level instead of under [project] — uv
ignored them entirely. This caused uv.lock to omit pytuning, scipy,
numpy, and sounddevice. API reference pages were blank because
autodoc couldn't import the modules.
Also adds [build-system] so uv treats the project as editable
instead of virtual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
uv sync --group docs only installs sphinx, not pytheory's deps
(pytuning, scipy, etc). Autodoc needs to import the package to
generate API reference pages. Now runs uv sync first.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TonedScale(tonic="Sa4", system="indian") now works — no need to
import SYSTEMS. Same for Key("C", "major", system="blues").
Updated README and all docs to use the cleaner string syntax,
removing 'from pytheory.systems import SYSTEMS' boilerplate.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Key.detect("C", "E", "G") → <Key C major>
Tries all major/minor keys, returns best match.
Prefers major when tied with relative minor.
Tone properties:
tone.is_natural → True for C, D, E, F, G, A, B
tone.is_sharp → True for C#, F#, etc.
tone.is_flat → True for Bb, Eb, etc.
Fretboard.INSTRUMENTS — list of all 25 preset names.
402 tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Key class — the friendliest entry point for music theory:
Key("C", "major").chords → all diatonic triads
Key("C", "major").seventh_chords → all diatonic 7th chords
Key("C", "major").progression("I", "V", "vi", "IV")
Key("C", "major").relative → Key("A", "minor")
Key("C", "major").parallel → Key("C", "minor")
Note = Tone alias for discoverability.
README rewritten to showcase the full API:
tones, scales, diatonic harmony, chord analysis,
6 systems, 25 instruments, audio playback,
comprehensive feature list.
381 tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New features:
- Tone.interval_to(other): "perfect 5th", "major 3rd", "octave"
- Tone.midi: MIDI note number (C4=60, A4=69)
- Tone.transpose(n): alias for tone arithmetic
- Chord.transpose(n): shift all tones, preserving quality
- Chord.root: identify the root tone
- Chord.quality: identify the chord quality ("major", "minor 7th")
- Scale.transpose(n): shift to a new key
Cleanup:
- __version__ = "0.3.0"
- __all__ defined — no more ceil/floor leaking
- pyproject.toml: author, license, classifiers, project URLs
319 tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
RST cannot nest inline markup — **`link <url>`_** renders the raw
markup instead of a clickable link. Removed all 37 instances across
5 guide pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Link key music theory terms to Wikipedia across all guide pages
- Physics of Consonance section now demos .harmony, .dissonance,
.tension, and .beat_frequencies with code examples
- Copyright updated to 2026
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New features:
- Chord.identify(): name any chord (17 patterns — triads, 7ths, 9ths, sus, power)
- Chord.voice_leading(other): find smoothest voice motion between chords
- Chord.analyze(key): Roman numeral analysis (I, ii, V7, etc.)
- Chord.tension: score with tritone count, dominant function detection
- Tone.overtones(n): harmonic series frequencies
Also:
- Rewrite README with all current features and docs link
- Add all new features to chords guide with music theory context
- Remove logo from docs sidebar
- 296 tests passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Every guide page rewritten with deep music theory content:
- Tones: scientific pitch notation, frequency/pitch relationship,
temperament history (equal/Pythagorean/meantone), interval table
with song examples, circle of fifths
- Scales: interval pattern construction, major/minor/harmonic minor
theory, all 7 modes with character descriptions and song references,
scale degree names and functions, diatonic harmony and common
chord progressions (I-IV-V, I-V-vi-IV, ii-V-I)
- Chords: triad and seventh chord construction tables, all 12 chord
qualities with interval formulas, consonance/dissonance theory
(Pythagoras to Plomp-Levelt), beat frequency perceptual ranges
- Fretboard: how frets work, string interval explanation, reading
fingering notation, 8 alternate tunings with musical context,
custom instrument examples (banjo, mandolin)
- Playback: waveform physics (harmonics, Fourier), temperament
listening guide
- Quickstart: updated feature list (6 systems, 40+ scales, 144 chords)
- Fix duplicate logo/title in sidebar
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Blues: major/minor pentatonic, blues scale, major blues, dominant,
minor (Dorian). The foundational scales of blues, rock, and jazz.
Gamelan: slendro (5-tone equidistant), pelog (7-tone with 3 pathet
subsets: nem, barang, lima). 12-TET approximations of Javanese
gamelan tuning with traditional tone names (ji, ro, lu, pat, mo,
nem, pi/barang).
Total systems: 6 (western, indian, arabic, japanese, blues, gamelan)
277 tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
intervals: now returns semitone counts (integers) instead of Hz
differences — octave-invariant and musically meaningful
harmony: frequency ratio simplicity model — reduces each pairwise
frequency ratio to simplest form and scores by 1/(num+denom).
Simple ratios (octave 2:1, fifth 3:2) score highest.
dissonance: Plomp-Levelt roughness with Bark-scale critical bandwidth
(Zwicker & Terhardt 1980). Models sensory roughness from interfering
fundamentals — peaks when freq difference ≈ critical bandwidth.
beat_frequencies: new property returning all pairwise beat frequencies
as sorted (tone, tone, hz) tuples
beat_pulse: returns smallest non-zero beat frequency (most perceptible)
All properties have detailed docstrings with psychoacoustic references,
perceptual ranges, and usage examples.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>