- Fretboard.chord(), .tab(), .chart() convenience methods
- Fingering.tab() for rendering ASCII tablature
- Fingering algorithm now considers muting, fret span, root-in-bass,
and contiguous bass-side muting for idiomatic voicings
- All docs converted from code-block:: python to pycon with >>> prompts
- All doc outputs verified against actual library output
- Tests for new methods; version test no longer checks exact string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New `fb.chord("G")` API lets you look up fingerings by chord name
instead of knowing fret positions upfront. Updates all docs to use
REPL-style examples with verified output.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show Key class, chord progressions, chord identification, interval
naming, and labeled fingerings in the hero code block. Add pip install
line, CLI examples, and a Highlights section summarizing all features.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gamelan uses its own tone names (nem, pi, barang, etc.), not Western
note names. Fixed tonic from C4 to nem4 and added pelog nem/barang
modes. Replaced miyako-bushi with iwato and kumoi (actual scale names
in the system). Added ValueError to exception handling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Version is now pulled from pytheory.__version__ instead of hardcoded.
GitHub button changed from watch to star with count.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both were using incorrect frequency scaling (magic numbers instead of
deriving cycle length from sample rate / hz). Now they match the sine
wave approach: compute one cycle at the correct frequency, then resize.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>